248 lines
8.5 KiB
HTML
248 lines
8.5 KiB
HTML
|
<!--startcut ==========================================================-->
|
||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||
|
<HTML>
|
||
|
<HEAD>
|
||
|
<title>Remote Compilation Using SSH and Make Issue 21</title>
|
||
|
</HEAD>
|
||
|
<BODY BGCOLOR="#fff0e8" TEXT="#301400" LINK="#0000FF" VLINK="#0020F0"
|
||
|
ALINK="#FF0000">
|
||
|
<!--endcut ============================================================-->
|
||
|
|
||
|
<H4>
|
||
|
"Linux Gazette...<I>making Linux just a little more fun!</I>"
|
||
|
</H4>
|
||
|
|
||
|
<P> <HR> <P>
|
||
|
<!--===================================================================-->
|
||
|
|
||
|
<center>
|
||
|
<H2>Remote Compilation Using SSH and Make</H2>
|
||
|
<H4>By John R. Daily,
|
||
|
<a href="mailto:jdaily@bbn.com">jdaily@bbn.com</a></H4>
|
||
|
</center>
|
||
|
<P><HR><P>
|
||
|
|
||
|
<H3>
|
||
|
Problem
|
||
|
</H3>
|
||
|
|
||
|
<P>
|
||
|
Occasionally I use my Linux machine at home to write code that I
|
||
|
intend to compile on a remote machine.
|
||
|
<P>
|
||
|
While maintaining open <TT>ftp</TT> and <TT>telnet</TT> connections to
|
||
|
the remote machine to handle the transfer and compilation steps is a
|
||
|
manageable solution, I decided to explore <TT><A
|
||
|
HREF="#ssh">ssh</A></TT> and <TT><A HREF="#make">make</A></TT> to
|
||
|
develop a more automated method.
|
||
|
<P>
|
||
|
The benefits of my solution:
|
||
|
<UL>
|
||
|
<LI> No need to remember which files have been modified.
|
||
|
<LI> Ability to use Emacs' compilation capabilities to move to errors in
|
||
|
the source. <LI> As mentioned above, no need to use <TT>ftp</TT>
|
||
|
and <TT>telnet</TT>, and hence no
|
||
|
benefit to keep an open dialup connection when not compiling.
|
||
|
<LI> Automate, automate, automate. Laziness is a virtue.
|
||
|
</UL>
|
||
|
|
||
|
<H3>
|
||
|
Overview of Solution
|
||
|
</H3>
|
||
|
<P>
|
||
|
My first step was to set up <TT>ssh</TT> and related tools in order to
|
||
|
allow
|
||
|
secure copying of files to my remote system. While setting up a
|
||
|
<TT>.rhosts</TT>
|
||
|
file is a (barely) acceptable solution, my IP address and name is
|
||
|
different each time I dial in, and it would be rather awkward to
|
||
|
change the remote system's <TT>.rhosts</TT> file each time I dialed
|
||
|
in.
|
||
|
<P>
|
||
|
<TT>ssh</TT> allows me to use a much more secure form of
|
||
|
authentication to copy
|
||
|
files and execute remote commands.
|
||
|
<P>
|
||
|
Once I had <TT>ssh</TT> behaving properly, I used Emacs' <TT>info</TT> facility to
|
||
|
explore implicit rules in makefiles, and wrote a simple makefile to
|
||
|
handle the file transfers and remote compilation.
|
||
|
<P>
|
||
|
As an example of the intended effect, assume my remote machine is
|
||
|
called "remote" (and my local machine "local"), and I've just modified
|
||
|
a source file called <TT>daemon.c</TT>. I would like to execute the
|
||
|
following commands in an automated fashion (note that <TT>scp</TT> is
|
||
|
a secure copy command packaged with <TT>ssh</TT>, and that the
|
||
|
<TT>-C</TT> option specifies compression, useful for dialup connections):
|
||
|
<PRE>
|
||
|
scp -C daemon.c jdaily@remote:~/source-directory
|
||
|
ssh -C remote "cd source-directory && make"
|
||
|
</PRE>
|
||
|
|
||
|
<H3>
|
||
|
Implementation
|
||
|
</H3>
|
||
|
<P>
|
||
|
First, I needed <TT>sshd</TT> running on the remote system to handle my secure
|
||
|
connections. Fortunately, <TT>sshd</TT> was already running on the remote
|
||
|
system in question, but according to the man pages, it can be run as
|
||
|
any user, and is restricted to handling connections for that user
|
||
|
(which should be quite sufficient for our needs).
|
||
|
<P>
|
||
|
Then, I needed to install the <TT>ssh</TT> toolset on my local machine. Again,
|
||
|
ideally these would be installed in a public binary directory such as
|
||
|
<TT>/usr/local/bin</TT>, but any user can install them in his/her
|
||
|
home directory.
|
||
|
|
||
|
<P>
|
||
|
I also wanted a key which would allow me to authenticate myself
|
||
|
between systems, and which would eliminate the need to type my
|
||
|
password each time I tried to run one of the <TT>ssh</TT> commands. For this, I
|
||
|
just ran <TT>ssh-keygen</TT>, and made sure to not give a pass
|
||
|
phrase, so that
|
||
|
none would be needed to use my private key to establish the
|
||
|
connection.
|
||
|
|
||
|
<PRE>
|
||
|
[jdaily@local ~]$ ssh-keygen
|
||
|
Initializing random number generator...
|
||
|
Generating p: ............++ (distance 186)
|
||
|
Generating q: ......................................++ (distance 498)
|
||
|
Computing the keys...
|
||
|
Testing the keys...
|
||
|
Key generation complete.
|
||
|
Enter file in which to save the key (/home/jdaily/.ssh/identity): <CR>
|
||
|
Enter passphrase: <CR>
|
||
|
Enter the same passphrase again: <CR>
|
||
|
Your identification has been saved in /home/jdaily/.ssh/identity.
|
||
|
Your public key is:
|
||
|
1024 35 718535638573954[...] jdaily@local
|
||
|
Your public key has been saved in /home/jdaily/.ssh/identity.pub
|
||
|
</PRE>
|
||
|
|
||
|
<P>
|
||
|
Once I had a public key, I used <TT>scp</TT> to copy it to the remote machine.
|
||
|
|
||
|
<PRE>
|
||
|
[jdaily@local ~]$ scp -C ~/.ssh/identity.pub jdaily@remote:~/.ssh/key
|
||
|
jdaily's password: <entered my remote password>
|
||
|
</PRE>
|
||
|
<P>
|
||
|
Then I logged into the remote host and copied the key file into
|
||
|
<TT>~/.ssh/authorized_hosts</TT>. If that file already existed, I
|
||
|
would have
|
||
|
appended the key file.
|
||
|
<P>
|
||
|
Following all this, I could run <TT>ssh</TT> and <TT>scp</TT> without needing either a
|
||
|
password or a pass phrase to connect to <TT>remote</TT>.
|
||
|
<P>
|
||
|
Now I needed a makefile to automate my system. Ideally, the files on
|
||
|
the remote machine would be checked to see if they were older than the
|
||
|
files on my local machine, and if so, they would be copied over. To
|
||
|
simplify matters, I decided to keep a record of the "last transferred
|
||
|
date" for each file by touching a corresponding file each time I
|
||
|
copied a source file over.
|
||
|
<P>
|
||
|
As an example, when I transferred a newer copy of <TT>daemon.c</TT>
|
||
|
over, I touched <TT>daemon.ct</TT> in the same directory. Any
|
||
|
transfer of a <TT>.h</TT> file would be marked by the creation of a
|
||
|
file with a <TT>.ht</TT> suffix.
|
||
|
<P>
|
||
|
After poking around the <TT>info</TT> file for <TT>make</TT>, I came
|
||
|
up with the following makefile.
|
||
|
<PRE>
|
||
|
TRANSFER=scp
|
||
|
REXEC=ssh
|
||
|
SSHFLAGS=-C # Compress data
|
||
|
REMOTE=jdaily@remote:~/source-directory
|
||
|
FILES=debug.ht messages.ht client.ct daemon.ct queue.ct queue.ht
|
||
|
|
||
|
%.ht : %.h
|
||
|
$(TRANSFER) $(SSHFLAGS) $< $(REMOTE)
|
||
|
touch $@
|
||
|
|
||
|
%.ct : %.c
|
||
|
$(TRANSFER) $(SSHFLAGS) $< $(REMOTE)
|
||
|
touch $@
|
||
|
|
||
|
all-done: $(FILES)
|
||
|
$(REXEC) $(SSHFLAGS) remote "cd source-directory && make"
|
||
|
touch all-done
|
||
|
</PRE>
|
||
|
<P>
|
||
|
This had one limitation in particular; I was unable to specify
|
||
|
command-line arguments for <TT>make</TT> on the remote machine without writing
|
||
|
them directly into the makefile on my local system. While this was
|
||
|
fine for the current application, I decided to generalize it by
|
||
|
creating a <TT>run-make</TT> shell script, which would handle the remote
|
||
|
execution of make after calling make on the local system.
|
||
|
<P>
|
||
|
Here is my <TT>run-make</TT> shell script:
|
||
|
<PRE>
|
||
|
#!/bin/sh
|
||
|
|
||
|
make
|
||
|
echo ssh -C remote \"cd source-directory \&\& make $*\"
|
||
|
ssh -C remote "cd source-directory && make $*"
|
||
|
</PRE>
|
||
|
<P>
|
||
|
I then removed the line from my makefile which remotely ran <TT>make</TT>.
|
||
|
<P>
|
||
|
Here's the output from a successful compilation sequence.
|
||
|
|
||
|
<PRE>
|
||
|
cd ~/source-directory/
|
||
|
./run-make
|
||
|
scp -C debug.h jdaily@remote:~/source-directory
|
||
|
touch debug.ht
|
||
|
scp -C messages.h jdaily@remote:~/source-directory
|
||
|
touch messages.ht
|
||
|
scp -C client.c jdaily@remote:~/source-directory
|
||
|
touch client.ct
|
||
|
scp -C daemon.c jdaily@remote:~/source-directory
|
||
|
touch daemon.ct
|
||
|
scp -C queue.c jdaily@remote:~/source-directory
|
||
|
touch queue.ct
|
||
|
scp -C queue.h jdaily@remote:~/source-directory
|
||
|
touch queue.ht
|
||
|
touch all-done
|
||
|
ssh -C remote "cd source-directory && make "
|
||
|
gcc -Wall -Wstrict-prototypes -Wmissing-prototypes -g -c queue.c
|
||
|
gcc -Wall -Wstrict-prototypes -Wmissing-prototypes -g -DPORT=3000 -o daemon daemon.c queue.o -lsocket -lthread
|
||
|
gcc -Wall -Wstrict-prototypes -Wmissing-prototypes -g -DPORT=3000 -o client client.c -lsocket
|
||
|
|
||
|
Compilation finished at Sat Aug 9 01:22:19
|
||
|
</PRE>
|
||
|
|
||
|
<H3>
|
||
|
Tools
|
||
|
</H3>
|
||
|
<A NAME="ssh">
|
||
|
<TT>ssh</TT> is a secure replacement for such tools as <TT>rsh</TT>,
|
||
|
<TT>rlogin</TT>, and <TT>rcp</TT>. It can be found at
|
||
|
<A HREF="http://www.cs.hut.fi/ssh">http://www.cs.hut.fi/ssh</A>.
|
||
|
<P>
|
||
|
<A NAME="make">
|
||
|
<TT>make</TT> is a standard Unix utility. GNU's <TT>make</TT> comes with most, if not
|
||
|
all, Linux distributions.
|
||
|
|
||
|
<!--===================================================================-->
|
||
|
<P> <hr> <P>
|
||
|
<center><H5>Copyright © 1997, John R. Daily<BR>
|
||
|
Published in Issue 21 of the Linux Gazette, September 1997</H5></center>
|
||
|
|
||
|
<!--===================================================================-->
|
||
|
<P> <hr> <P>
|
||
|
<A HREF="./index.html"><IMG ALIGN=BOTTOM SRC="../gx/indexnew.gif"
|
||
|
ALT="[ TABLE OF CONTENTS ]"></A>
|
||
|
<A HREF="../index.html"><IMG ALIGN=BOTTOM SRC="../gx/homenew.gif"
|
||
|
ALT="[ FRONT PAGE ]"></A>
|
||
|
<A HREF="./icewm.html"><IMG SRC="../gx/back2.gif"
|
||
|
ALT=" Back "></A>
|
||
|
<A HREF="./spare.html"><IMG SRC="../gx/fwd.gif" ALT=" Next "></A>
|
||
|
<P> <hr> <P>
|
||
|
<!--startcut ==========================================================-->
|
||
|
</BODY>
|
||
|
</HTML>
|
||
|
<!--endcut ============================================================-->
|
||
|
|