Why does `cd` command not work via SSH?

52,584

Solution 1

İt's a quoting issue. Ssh already runs the command you pass it in a shell. When you pass multiple parameters, they are concatenated with a space in between to build a string. So the remote command that you are running remotely is /bin/sh -c cd /boot && ls -l (no quotes, because the quotes in your command were interpreted by the local shell).

/bin/sh -c cd /boot runs /bin/sh and tells it to run the command cd and also to set $0 to /boot. Once this is done, the parent shell (the one launched by sshd) runs ls -l.

In your case, just remove the sh -c which is completely useless unless your remote shell (as indicated in /etc/passwd or other password database) does not understand this command.

ssh root@server "cd /boot && ls -l"

If you need to invoke a different shell, you must quote the remote command to protect it from expansion by the remote shell invoked by sshd. For example, if your login shell is dash and you want to run a bash command:

ssh root@server 'bash -c "cd ~bob && ls -l"'

Solution 2

I think it has more to do with how the options are getting parsed by the shell. For example, this works:

$ ssh root@server /bin/sh -c '"cd /boot && ls -l"'

This has the same issue as your command:

$ ssh root@server /bin/sh -c 'cd /boot && ls -l'

If you enable the -v switch to ssh you can see what's going on:

1st command:

debug1: Sending command: /bin/sh -c "cd /boot && ls -l"

2nd command:

debug1: Sending command: /bin/sh -c cd /boot && ls -l

Typically when sending commands through ssh you have to pay special attention to the quoting and wrap quotes within quotes as the various layers strip them away. Also don't bother sending /bin/sh.

You can do very useful thing once you understand the quoting of ssh such as the following. This will run the command on the remote server but collect the results in a file locally on the system where you ran the ssh command:

$ ssh root@server 'free -m' > /tmp/memory.status

or this, where you tar a directory on a remote server and create it on the local system:

$ ssh remotehost 'tar zcvf - SOURCEDIR' | cat > DESTFILE.tar.gz

References

Solution 3

Typically you don't have to specify what shell to use. This works:

ssh user@host "cd /boot && pwd"

But if your default shell is problematic, then just make sure you quote the entire command, including the shell invocation. Either of the following works

ssh user@host '/bin/sh -c "cd /boot && pwd"'
ssh user@host "/bin/sh -c \"cd /boot && pwd\""
Share:
52,584

Related videos on Youtube

Ambroz Bizjak
Author by

Ambroz Bizjak

Updated on September 18, 2022

Comments

  • Ambroz Bizjak
    Ambroz Bizjak over 1 year

    I was trying to backup some files via SSH but instead of tar'ing the ones I wanted I got my home folder. I did some further testing and it boils down to this:

    ssh root@server /bin/sh -c "cd /boot && ls -l"
    

    Which to my surprise lists files in /root not /boot. But if I run the entire /bin/sh command from a terminal it properly cds and prints the /boot files.

    What's happening here?

  • Stéphane Chazelas
    Stéphane Chazelas almost 11 years
    Note that while cd /boot && pwd works in all shells of the major families (Bourne, csh, rc), /bin/sh -c "cd /boot && pwd" would not work if the remote shell is of the rc family where " is not special.