You all know scp as part of the OpenSSH suite, which copies files from and/or to a remote host. But when it comes to reading and/or writing to non-regular files/objects, scp stops working. Here is a short introduction how you can get around this unimplemented feature.

Back in the past, scp was just a wrapper script for ssh but later became its own application. Still, ssh itself has not lost the features it possessed those days. ssh is not only an interactive program that gives you a shell on a remote host, but also a non-interactive mode (which is e.g. very useful in cronjobs). Most of you probably do not know what's happening when you type

$ ssh user@host ls -l

but exactly that is a non-interactive session. In both modes, interactive and non-ia, the local STDIN/STDOUT is blindly connected to the remote STDIN/STDOUT -- otherwise you would not get any output from ls -l of course. Some might also have discovered by now that this works:

$ ssh user@host "ls -l" >lsoutput.txt

I.e. a redirection of ssh's output. SSH continues to be flexible -- you could use a filter program that resides on the remote host:

$ ssh -C user@host "tr A-Z a-z" <input.txt >output.txt

This will give input.txt. (-C will request compression.) The technicians might now wonder how this reliably works, because the remote side usually allocates a pty (pseudo terminal). Adding the -t option makes the trick visible: Pseudo-terminal will not be allocated because stdin is not a terminal. (This is very important because a text file just is not a terminal.) I still suggest using the -T option to explicitly deactivate allocating a pty.

As with text files, you can transfer anything else, even block devices. Before I will hand out the final command, there is one thing to pay attention. Try this: ssh user@localhost and then hit the tilde, then the period key. Now think of what happened if that sequence "~." was in your input file. (Luckily, this escape sequence, as documented in ssh(1) is disabled when no pty is allocated.) Still, it's best to supply -e none. The full command to do a network backup thus is:

# tar -cvj / | ssh -T -e none "cat >/backup.tar.bz2"

Or with a little shell squash and different encryption:

# tar -cvj / | ssh -Tcblowfish -enone "cat >/backup.tar.bz2"

Details to this command: tar packs all directories and files of the local host (starting at the root directory /) into an archive using bzip2 compression (-j) and writes this archive to STDOUT. (Typically for tar (with or without compression): the archive is output on-the-fly, so the RAM usage is very low.) ssh reads that from STDIN and passes the data to the remote host. cat's STDIN is the network socket, i.e. cat gets the archive on STDIN, and displays it to its STDOUT. (The nature of cat.) The invisble shell (!) then redirects it to the file backup.tbz2.

Additional keywords: on the fly pipe transmission