127

I'm trying to get ssh to automatically change to a particular directory when I log in. I tried to get that behaviour working using the following directives in ~/.ssh/config:

Host example.net
LocalCommand "cd web"

but whenever I log in, I see the following:

/bin/bash: cd web: No such file or directory

although though there is definitely a web folder in my home directory. Even using an absolute path gives the same message. To be clear, if I type cd web after logging in I get to the right folder.

What am I missing here?

EDIT:

Different combinations of quotes/absolute paths give different error messages:

LocalCommand "cd web"
/bin/bash: cd web: No such file or directory

LocalCommand cd web
/bin/bash: line 0: cd: web: No such file or directory

LocalCommand cd /home/gareth/web
/bin/bash: line 0: cd: /home/gareth/web: Input/output error

This makes me think that the quotes shouldn't be there, and that there's another error happening.

sobi3ch
  • 943
Gareth
  • 1,496
  • 3
  • 11
  • 12

12 Answers12

94

This works:

ssh server -t "cd /my/remote/directory; bash --login"

To create a directory if it doesn't exist:

ssh server -t "mkdir -p newfolder; cd ~/newfolder; pwd; bash --login"

If you don't add bash to the end of path then you exit after the cd comand runs. And If you don't add --login then your ~/.profile isn't sourced.

rcoup
  • 167
71
  1. Login to your box
  2. Edit ~/.bash_profile
  3. On the end of the file add cd /path/to/your/destination
  4. Save it & exit
  5. Logout from the box
  6. Login again and then you should land on /path/to/your/destination

Note (Dec 2021): As @Matthias points out on some machines you may need need to append your command to ~/.bashrc instead of to ~/.bash_profile.

sobi3ch
  • 943
61

cd is a shell builtin. LocalCommand is executed as:

/bin/sh -c <localcommand>

What you're looking to do can't really be accomplished via SSH; you need to modify the shell in some way, e.g. via bashrc/bash_profile.

<Editing almost a decade later...>

LocalCommand isn't what you want, anyway. That's run on your machine.

You want RemoteCommand. Something like this worked for me:

Host example.net
  RemoteCommand cd / && exec bash --login
  RequestTTY yes
BMDan
  • 7,379
5

Have you enabled this directive in your ssh config?

PermitLocalCommand yes

The default for that is no, in which case your LocalCommand directive would be ignored.

Alternatively, have you tried adding the command to your .bashrc file?

EEAA
  • 110,608
4

More robust solution for the case when you need to ssh and override default .bashrc file. This is useful in cases when remote server environment has multiple docroots and used by multiple users.

alias ssh_myserver='ssh server_name -t "echo cd /path/to/desired/dir>/tmp/.bashrc_tmp; bash --rcfile /tmp/.bashrc_tmp"'

More detailed:

  1. First command creates .bashrc_tmp file in /tmp directory on the remote server with a content cd /path/to/dir
  2. Next command executes bash with config file specified in step 1. This allows to switch to desired dir and suppress default .bashrc.
  3. This whole command is wrapped as an alias, so on ssh client command prompt it can be called as ssh_myserver
slm
  • 8,010
4

So I have searched a lot of websites (stackoverflow, this one) but did not find what I wanted. I ended up creating my own shell script. I am pasting it here. Also you can copy it a directory in the $PATH.

#!/bin/bash
ssh -t <username@hostname> "cd ~/$1; exec \$SHELL --login"

So after this. I do:

connect <foldername>

Note: You may need to log out and log in again after changing the path variable

kasperd
  • 31,086
Aryan
  • 49
3

In your ~/.ssh/config:

LocalCommand echo '/home/%r/some/subdir' > /home/%r/.ssh/ssh_cd

At the end of your ~/.bashrc:

if [[ -f $HOME/.ssh/ssh_cd ]]
then
    cd $(<$HOME/.ssh/ssh_cd)
    # uncomment the line below and the file will be removed so the cd won't work
    # unless the file is regenerated since you may not want this to operate for
    # non-ssh logins or for ssh logins that you want to function differently
    # rm $HOME/.ssh/ssh_cd
fi

I tried doing this using variable passing, including with an exported variable, but these commands get run in different shells.

When testing what you were trying to do I didn't get an error when I used the unquoted absolute path, by the way. I added ; pwd at the end of the command and the correct directory is displayed, however the directory I end up in is ~. There are no cd commands in my shell startup files. I tried putting a different cd somedir; pwd in ~/.ssh/rc (with the other still in place). The config command is executed before the motd is issued and the rc command is issued afterwards, but before the shell startup files are sourced. So again, it's happening in a different shell.

Try the passing-by-file technique and let me know if it works for you.

2

Have you tried it without the quotes around it? The only examples I've seen don't have them so with them it could be trying to execute cd\ web as a command.

James L
  • 6,205
  • 1
  • 25
  • 26
2

You could also try this, with the option -t:

ssh server -t "cd /my/remote/directory; bash"
kenorb
  • 7,125
1

I use the following in .ssh/config:

  RemoteCommand cd ~/mydir;bash
  RequestTTY force
sluge
  • 129
1

Try using RemoteCommand instead, e.g.

Host myhost
  HostName IP
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  RemoteCommand cd web; $SHELL -il

RemoteCommand: Specifies a command to execute on the remote machine after successfully connecting to the server. (man ssh_config)

kenorb
  • 7,125
0

Maybe you need to create ~/.bash_profile although you already have a ~/.bashrc.

On my debian system the ~/.bashrc was not executed upon login with sshpass.

Since I added cd directory to the newly created ~/.bash_profile it worked fine.

bomben
  • 115