Memra

Quoting decides which machine does the work

◈ 11 cards

Run a command on another machine with ssh, and predict for any command line which machine performs each redirection and each pipe.

What actually happens when you run a remote command

ssh host command does not teleport a command. It opens an encrypted connection to the SSH daemon on host, and that daemon starts your remote login shell to run the command you sent. Four consequences follow, and every question in this lesson is one of them:

  1. The command starts in your home directory on the remote machine, not in the directory you were standing in locally.
  2. The remote shell runs its rc file.bashrc, or .cshrc — and not its login file, .profile or .login. So your remote PATH may be missing what your interactive logins normally add to it, and a command that works when you log in and type it can fail when ssh runs it.
  3. The remote command's three standard descriptors are connected back to your local terminal, which is why its output appears in front of you.
  4. Your local shell parsed the command line before ssh ever ran. Anything the local shell recognised — a redirection, a pipe, a glob, a variable — it acted on locally. Anything hidden inside quotes it passed through untouched, and the remote shell dealt with it instead.

Point 4 is the whole lesson. Unquoted redirection is performed by the local shell; quoted redirection is performed by the remote shell. The quote is the boundary between the machines.

Worked example: four variants, one remote host

Assume a file students in your local directory, and another file also called students in your remote home directory.

ssh h sort students > sorted — the local shell sees > sorted outside any quotes, so it creates sorted locally and points ssh stdout at it. What crosses the network is the command sort students, which the remote shell runs in your remote home, sorting the remote file. Remote input, local output.

ssh h sort < students > sorted — now both operators are local. The local shell opens the local students on descriptor 0 and the local sorted on descriptor 1, and ssh inherits both. The remote sort is given no filename at all, so it reads stdin, which arrives over the connection from your machine. Local input, local output, and the remote machine never touches a file.

cat students | ssh h 'sort > sorted' — the local cat reads the local file and pipes it into ssh, which carries it to the remote sort as stdin. But > sorted is inside single quotes, so the local shell passed it through as text and the remote shell performed it. The result is written on the remote machine, in your remote home directory, and nothing comes back. Local input, remote output.

ssh h 'ps -e | grep d$' | grep sshd — two pipes, one on each machine. The quoted pipeline runs entirely on h: the remote ps lists remote processes and the remote grep filters them. Its output travels back and is fed to the local grep, which filters again here. A single command line, two machines, and the quote marks the seam.

The sharpest pair

The difference between these two is one character of position:

cat f | ssh h 'sort | grep D'
cat f | ssh h 'sort' | grep D

Both send the local f across. In the first, the closing quote comes after grep D, so both stages run remotely and only the finished matches travel back. In the second, the quote closes after sort, so the whole sorted stream comes back over the network and the filtering happens here. Same output, different work and different bandwidth — and if grep existed only on the remote machine, only the first would run at all.

The old names, and why they are gone

Before SSH there was a family of commands with the same jobs: rsh to run a remote command, rlogin and telnet to log in, rcp to copy, ftp to transfer. Each of them sends everything in cleartext — including your password — and the r* commands authenticate by host name, through /etc/hosts.equiv on the machine and ~/.rhosts in the account. If a machine's name appears in one of those files, being that machine is enough. Anyone able to spoof the name is you.

SSH replaces the lot with encryption on the wire and cryptographic keys instead of a list of trusted names. The migration is clean enough to be worth memorising as a substitution: rsh and rlogin and telnet become ssh, rcp becomes scp, ftp becomes sftp — and every example in this lesson reads identically with the old names substituted, which is exactly why the exam can still ask about them.

Command lineInput fromOutput tossh h sort students >sortedremote filelocal filessh h sort < students >sortedlocal filelocal filecat students | ssh h 'sort> sorted'local fileremote filessh h 'ps -e | grep d' |grep sshdremote processeslocal screenRow 1 has no quotes, so the redirection is local and the filename is remote.
Read each row by asking one question: was the operator inside the quotes? Everything else follows from the answer.
InsecureSecureWhat was wrongrshsshcleartext; trusts a hostnamerlogin, telnetssh (slogin)password sent in the clearrcpscpfile contents in the clearftpsftpcredentials and data in theclearThe daemon on the far end of all three secure forms is sshd.
Learn the left column for the exam and the right column for your machines. The substitution is one for one — the examples in this lesson read the same either way.

source OpenSSH ssh-keygen(1), ssh-copy-id(1), sshd(8) AUTHORIZED_KEYS FILE FORMAT

NORMAL ~/memra/learn/comp-325/ssh-and-who-performs-the-redirection utf-8 LF