a1134c12a5bf238ccdd4148942095e1942961225
[rsync-web.git] / faqbody.html
1 <table><tr><td><ul>
2 <li><a href="#1">Read-only file system</a><br>
3 <li><a href="#2">copies every file</a><br>
4 <li><a href="#3">is your shell clean</a><br>
5 <li><a href="#4">memory usage</a><br>
6 <li><a href="#5">out of memory</a><br>
7 </ul></td><td>&nbsp;&nbsp;&nbsp;&nbsp;</td><td><ul>
8 <li><a href="#6">rsync through a firewall</a><br>
9 <li><a href="#7">rsync and cron</a><br>
10 <li><a href="#8">rsync: Command not found</a><br>
11 <li><a href="#9">spaces in filenames</a><br>
12 <li><a href="#10">ignore "vanished files" warning</a><br>
13 </ul></td></tr></table>
14
15 <h3><a name=1>Read-only file system</a></h3>
16
17 <p>If you get "Read-only file system" as an error when sending to a rsync
18 daemon then you probably forgot to set "read only = no" for that module.
19
20 <hr>
21 <h3><a name=2>copies every file</a></h3>
22
23 <p>Some people occasionally report that rsync copies every file when they
24 expect it to copy only a small subset. In most cases the explanation is
25 that you forgot to include the --times (-t) option in the original copy,
26 so rsync is forced to check every file to see if it has changed (because
27 the modified time and size do not match).
28
29 <p>If you think that rsync is erroneously copying every file then look at
30 the stats produced with -v and see if rsync is really sending all the data. 
31
32 <hr>
33 <h3><a name=3>is your shell clean</a></h3>
34
35 <p>The "is your shell clean" message and the "protocol mismatch" message
36 are usually caused by having some sort of program in your .cshrc, .profile,
37 .bashrc or equivalent file that writes a message every time you connect
38 using a remote-shell program (such as ssh or rsh).  Data written in this
39 way corrupts the rsync data stream. rsync detects this at startup and
40 produces those error messages.  However, if you are using rsync-daemon
41 syntax (host::path or rsync://) without using a remote-shell program (no
42 --rsh or -e option), there is not remote-shell program involved, and the
43 problem is probably caused by an error on the daemon side (so check the
44 daemon logs).
45
46 <p>A good way to test if your remote-shell connection is clean is to try
47 something like this (use ssh or rsh, as appropriate):
48
49 <blockquote><pre>ssh remotesystem /bin/true &gt; test.dat</pre></blockquote>
50
51 <p>That should create a file called test.dat with nothing in it. If
52 test.dat is not of zero length then your shell is not clean.  Look at the
53 contents of test.dat to see what was sent. Look at all the startup files on
54 remotesystem to try and find the problem.
55
56 <hr>
57 <h3><a name=4>memory usage</a></h3>
58
59 <p>Yes, rsync uses a lot of memory. The majority of the memory is used to
60 hold the list of files being transferred. This takes about 100 bytes per
61 file, so if you are transferring 800,000 files then rsync will consume
62 about 80M of memory. It will be higher if you use -H or --delete.
63
64 <p>To fix this requires a major rewrite of rsync, which my or may not
65 happen.
66
67 <hr>
68 <h3><a name=5>out of memory</a></h3>
69
70 <p>The usual reason for "out of memory" when running rsync is that you are
71 transferring a _very_ large number of files.  The size of the files doesn't
72 matter, only the total number of files.
73
74 <p>As a rule of thumb you should expect rsync to consume about 100 bytes
75 per file in the file list. This happens because rsync builds a internal
76 file list structure containing all the vital details of each file.  rsync
77 needs to hold structure in memory because it is being constantly traversed.
78
79 <p>A future version of rsync could be built with an improved protocol that
80 transfers files in a more incremental fashion, which would require a lot
81 less memory.  Unfortunately, such an rsync does not yet exist.
82
83 <hr>
84 <h3><a name=6>rsync through a firewall</a></h3>
85
86 <p>If you have a setup where there is no way to directly connect two
87 systems for an rsync transfer, there are several ways to use the firewall
88 system to act as an intermediary in the transfer.
89
90 <h4>Method 1</h4>
91
92 <p>Use your remote shell (e.g. ssh) to access the middle system and have it
93 use a remote shell to hop over to the actual target system.
94
95 <p>To effect this extra hop, you'll need to make sure that the remote-shell
96 connection from the middle system to the target system does not involve any
97 tty-based user interaction (such as prompting for a password) because there
98 is no way for the middle system to access the local user's tty.
99
100 <p>One way that works for both rsh and ssh is to enable host-based
101 authentication, which would allow all connections from the middle system to
102 the target system to succeed (when the username remains the same).
103 However, this may not be a desirable setup.
104
105 <p>Another method that works with ssh (and is also very safe) is to setup
106 an ssh key (see the ssh-key manpage) and ensure that ssh-agent forwarding
107 is turned on (e.g. "ForwardAgent&nbsp;yes").  You would put the public
108 version of your key onto the middle and target systems, and the private key
109 on your local system (which I recommend you encrypt).  With this setup, a
110 series of ssh connections that starts from the system where your private
111 key is available will auto-authorize (after the pass-phrase prompt on the
112 first system).
113
114 <p>You should then test that a series of ssh connections works without
115 multiple prompts by running a command like this (put in the real "middle"
116 and "target" hostnames, of course):
117
118 <blockquote><pre>ssh middle ssh target uptime</pre></blockquote>
119
120 <p>If you get a password/passphrase prompt to get into the middle system
121 that's fine, but the extra hop needs to occur without any extra user
122 interaction.
123
124 <p>Once that's done, you can do an rsync copy like this:
125
126 <blockquote><pre>rsync -av -e "ssh middle ssh" target:/source/ /dest/</pre></blockquote>
127
128 <h4>Method 2</h4>
129
130 <p>Assuming you're using ssh as your remote shell, you can configure ssh to
131 use a proxy command to get to the remote host you're interested in reaching.
132 Doing this will allow the multi-hop connection to work with rsync, even if
133 both hosts prompt for a password -- this is because both ssh connections
134 originate from the localhost, and thus both instances of ssh have access to
135 the local console to use for an out-of-band password prompt.
136
137 <p>Here is an example config for your ~/.ssh/config file (substitute "target",
138 "target_user", and "middle" as appropriate):
139
140 <blockquote><pre>Host target
141   ProxyCommand nohup ssh middle nc -w1 %h %p
142   User target_user
143 </pre></blockquote>
144
145 <p>This proxy setup uses ssh to login to the firewall system ("middle") and
146 uses nc (netcat) to connect to the target host (%h) using the target port
147 number (%p).  The use of "nohup" silences a warning at the end of the run,
148 and the "-w1" option tells nc to shut down when the connection closes.
149
150 <p>With this done, you could run a normal-looking rsync command to "target"
151 that would run the proxy command to get through the firewall system:
152
153 <blockquote><pre>rsync -av /src/ target:/dest/</pre></blockquote>
154
155 <h4>Method 3</h4>
156
157 <p>Assuming you're using ssh as your remote shell, you can configure ssh to
158 forward a local port through your middle system to the ssh port (22) on the
159 target system.  This method does not require the use of "nc" (it uses only
160 ssh to effect the extra hop), but otherwise it is similar to, but slightly
161 less convenient than, method 2.
162
163 <p>The first thing we need is an ssh configuration that will allow us to
164 connect to the forwarded port as if we were connecting to the target
165 system, and we need ssh to know what we're doing so that it doesn't
166 complain about the host keys being wrong.  We can do this by adding this
167 section to your ~/.ssh/config file (substitute "target" and "target_user"
168 as appropriate):
169
170 <blockquote><pre>Host target
171   HostName localhost
172   Port 2222
173   HostKeyAlias target
174   User target_user
175 </pre></blockquote>
176
177 <p>Next, we need to enable the port forwarding:
178
179 <blockquote><pre>ssh -fN -l middle_user -L 2222:target:22 middle</pre></blockquote>
180
181 <p>What this does is cause a connection to port 2222 on the local system to
182 get tunneled to the middle system and then turn into a connection to the
183 target system's port 22.  The -N option tells ssh not to start a shell on
184 the remote system, which works with modern ssh versions (you can run a
185 sleep command if -N doesn't work).  The -f option tells ssh to put the
186 command in the background after any password/passphrase prompts.
187
188 <p>With this done, you could run a normal-looking rsync command to "target"
189 that would use a connection to port 2222 on localhost automatically:
190
191 <blockquote><pre>rsync -av target:/src/ /dest/</pre></blockquote>
192
193 <p><b>Note:</b> starting an ssh tunnel allows anyone on the source system
194 to connect to the localhost port 2222, not just you, but they'd still need
195 to be able to login to the target system using their own credentials.
196
197 <h4>Method 4</h4>
198
199 <p>Install and configure an rsync daemon on the target and use an ssh
200 tunnel to reach the rsync sever.  This is similar to method 3, but it
201 tunnels the daemon port for those that prefer to use an rsync daemon.
202
203 <p>Installing the rsync daemon is beyond the scope of this document, but
204 see the rsyncd.conf manpage for more information.  Keep in mind that you
205 don't need to be root to run an rsync daemon as long as you don't use a
206 protected port.
207
208 <p>Once your rsync daemon is up and running, you build an ssh tunnel
209 through your middle system like this:
210
211 <blockquote><pre>ssh -fN -l middle_user -L 8873:target:873 middle</pre></blockquote>
212
213 <p>What this does is cause a connection to port 8873 on the local system to
214 turn into a connection from the middle system to the target system on port
215 873.  (Port 873 is the normal port for an rsync daemon.) The -N option
216 tells ssh not to start a shell on the remote system, which works with
217 modern ssh versions (you can run a sleep command if -N doesn't work).  The
218 -f option tells ssh to put the command in the background after any
219 password/passphrase prompts.
220
221 <p>Now when an rsync command is executed with a daemon-mode command-line
222 syntax to the local system, the conversation is directed to the target
223 system.  For example:
224
225 <blockquote><pre>rsync -av --port 8873 localhost::module/source dest/
226 rsync -av rsync://localhost:8873/module/source dest/</pre></blockquote>
227
228 <p><b>Note:</b> starting an ssh tunnel allows anyone on the source system
229 to connect to the localhost port 8873, not just you, so you may want to
230 enable username/password restrictions on your rsync daemon.
231
232 <hr>
233 <h3><a name=7>rsync and cron</a></h3>
234
235 <p>On some systems (notably SunOS4) cron supplies what looks like a socket
236 to rsync, so rsync thinks that stdin is a socket. This means that if you
237 start rsync with the --daemon switch from a cron job you end up rsync
238 thinking it has been started from inetd. The fix is simple&mdash;just
239 redirect stdin from /dev/null in your cron job.
240
241 <hr>
242 <h3><a name=8>rsync: Command not found</a></h3>
243
244 <p>This error is produced when the remote shell is unable to locate the rsync
245 binary in your path. There are 3 possible solutions:
246
247 <ol>
248
249 <li>install rsync in a "standard" location that is in your remote path. 
250
251 <li>modify your .cshrc, .bashrc etc on the remote system to include the path
252 that rsync is in
253
254 <li>use the --rsync-path option to explicitly specify the path on the
255 remote system where rsync is installed
256
257 </ol>
258
259 <p>You may echo find the command:
260
261 <blockquote><pre>ssh host 'echo $PATH'</pre></blockquote>
262
263 <p>for determining what your remote path is.
264
265 <hr>
266 <h3><a name=9>spaces in filenames</a></h3>
267
268 <p>Can rsync copy files with spaces in them?
269
270 <p>Short answer: Yes, rsync can handle filenames with spaces.
271
272 <p>Long answer: 
273
274 <p>Rsync handles spaces just like any other unix command line application.
275 Within the code spaces are treated just like any other character so a
276 filename with a space is no different from a filename with any other
277 character in it.
278
279 <p>The problem of spaces is in the argv processing done to interpret the
280 command line.  As with any other unix application you have to escape spaces
281 in some way on the command line or they will be used to separate arguments. 
282
283 <p>It is slightly trickier in rsync (and other remote-copy programs like
284 scp) because rsync sends a command line to the remote system to launch the
285 peer copy of rsync (this assumes that we're not talking about daemon mode,
286 which is not affected by this problem because no remote shell is involved
287 in the reception of the filenames).  The command line is interpreted by the
288 remote shell and thus the spaces need to arrive on the remote system
289 escaped so that the shell doesn't split such filenames into multiple
290 arguments.
291
292 <p>For example:
293
294 <blockquote><pre>rsync -av host:'a long filename' /tmp/</pre></blockquote>
295
296 <p>This is usually a request for rsync to copy 3 files from the remote
297 system, "a", "long", and "filename" (the only exception to this is for a
298 system running a shell that does not word-split arguments in its commands,
299 and that is exceedingly rare).  If you wanted to request a single file with
300 spaces, you need to get some kind of space-quoting characters to the remote
301 shell that is running the remote rsync command.  The following commands
302 should all work:
303
304 <blockquote><pre>rsync -av host:'"a long filename"' /tmp/
305 rsync -av host:'a\ long\ filename' /tmp/
306 rsync -av host:a\\\ long\\\ filename /tmp/</pre></blockquote>
307
308 <p>You might also like to use a '?' in place of a space as long as there
309 are no other matching filenames than the one with spaces (since '?' matches
310 any character):
311
312 <blockquote><pre>rsync -av host:a?long?filename /tmp/</pre></blockquote>
313
314 <p>As long as you know that the remote filenames on the command line
315 are interpreted by the remote shell then it all works fine. 
316
317 <hr>
318 <h3><a name=10>ignore "vanished files" warning</a></h3>
319
320 <p>Some folks would like to ignore the "vanished files" warning, which
321 manifests as an exit-code 24.  The easiest way to do this is to create
322 a shell script wrapper.  For instance, name this something like
323 "rsync-no24":
324
325 <blockquote><pre>#!/bin/sh
326 rsync "$@"
327 e=$?
328 if test $e = 24; then
329     exit 0
330 fi
331 exit $e</pre></blockquote>
332
333 <hr>
334