使用 ssh 和 make 进行远程编译

作者:John R. Daily

我偶尔会在家里的 Linux 机器上编写代码,然后在远程机器上编译。

虽然保持与远程机器的开放 FTP 和 TELNET 连接来处理传输和编译步骤是一个可行的解决方案,但我决定探索 sshmake,以开发一种更自动化的方法。

我的解决方案的优点

  • 无需记住哪些文件已被修改。

  • 能够使用 Emacs 的编译功能来跳转到源代码中的错误。

  • 如上所述,无需使用 FTP 或 TELNET,因此在不编译时无需保持拨号连接。

  • 自动化,自动化,自动化——懒惰是一种美德。

解决方案概述

我的第一步是设置 ssh 和相关工具,以便安全地将文件复制到我的远程系统。虽然设置 .rhosts 文件是一个(勉强)可以接受的解决方案,但我的 IP 地址和名称每次拨入时都会不同,并且每次拨入时都更改远程系统的 .rhosts 文件会相当麻烦。

ssh 为我提供了更安全的身份验证形式,用于复制文件和执行远程命令。

一旦 ssh 运行正常,我就使用 Emacs 的 info 工具来探索 Makefile 中的隐式规则,并编写了一个简单的 Makefile 来处理文件传输和远程编译。

作为预期效果的示例,假设我的远程机器名为“remote”(我的本地机器名为“local”),并且我刚刚修改了一个名为 daemon.c 的源文件。我希望以自动方式执行以下命令(请注意,scp 是 ssh 打包的安全复制命令,-C 选项指定压缩,对于拨号连接非常有用)

scp -C daemon.c jdaily@remote:~/source-directory
ssh -C remote "cd source-directory && make"
实施

首先,我需要在远程系统上运行 sshd 以处理我的安全连接。幸运的是,sshd 已经在有问题的远程系统上运行。根据手册页,它可以由任何用户运行(即,用户不必是 root),并且仅限于处理该用户的连接(这应该为我们的需求提供足够的安全性)。

然后,我需要在我的本地机器上安装 ssh 工具集。同样,理想情况下,这些工具应该安装在公共二进制目录中,例如 /usr/local/bin,但任何用户都可以将它们安装在其主目录中。

我还想要一个密钥,它允许我在系统之间验证身份,并消除每次尝试运行 ssh 命令时都输入密码的需求。为此,我运行了 ssh-keygen 并确保不提供密码短语,这样在使用我的私钥建立连接时就不需要密码短语。列表 1 显示了一个 ssh-keygen 会话示例。

获得公钥后,我使用 scp 将其复制到远程机器。

$ scp -C ~/.ssh/identity.pub \jdaily@remote:~/.ssh/keyjdaily 的密码:<输入了我的远程密码>

然后我登录到远程主机,并将密钥文件复制到 ~/.ssh/authorized_keys。如果该文件已经存在,我将追加密钥文件。

完成所有这些操作后,我可以运行 ssh 和 scp,而无需密码或密码短语即可连接到远程主机。

现在我需要一个 makefile 来自动化我的系统。理想情况下,应该检查远程机器上的文件是否比本地机器上的文件旧,如果是,则应替换它们。为了简化问题,我决定通过在每次复制源文件时触摸相应的文件来记录每个文件的“上次传输日期”。

例如,当我传输 daemon.c 的较新副本时,我在同一目录中触摸了 daemon.ct。任何 .h 文件的传输都将通过创建带有 .ht 后缀的文件来标记。

在浏览了 make 的 info 文件后,我想出了列表 2中显示的 Makefile。这个 Makefile 有一个特别的限制;我无法为远程机器上的 make 指定命令行参数,除非将它们直接写入本地系统上的 makefile 中。虽然这对于当前应用程序来说很好,但我决定通过创建一个 run-make shell 脚本来概括它,该脚本将在本地系统上调用 make 后处理 make 的远程执行。列表 3 是我的 run-make shell 脚本。然后我从我的 Makefile 中删除了远程运行 make 的行。列表 4 是成功编译序列的输出。

资源

John Daily 在 BBN(或者是 GTE?)担任系统管理员/软件工程师。他花费了太多的时间在电脑前。只要有可能,他更喜欢骑着他的新自行车在户外探索新英格兰。可以通过电子邮件 jdaily@bbn.com 与他联系。

加载 Disqus 评论