122

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.

2

12 Answers 12

57

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
8
  • 4
    Yep, just wanted to mention to same. You can put the cd command in ~/.bashrc at the remote server instead.
    – vdboor
    Aug 5, 2010 at 16:00
  • That's annoying. As I mentioned in another comment, the server has a number of hostnames and I wanted to have different behaviour based on which was used. I guess it's not possible to determine which was used from .bashrc?
    – Gareth
    Aug 5, 2010 at 16:15
  • It's possible, just probably not advisable. Something like replacing ssh with a small shell script or alias that passes the host name as a variable to be exported (a la "ssh -t user@host 'export connhostname=host; bash --login'"). But you're starting to get into very strange territory, indeed. Perhaps a better question is, WHY do you want this behavior?
    – BMDan
    Aug 5, 2010 at 17:50
  • It's not really that big a deal to be honest. I'm just in the situation where the vast majority of the time I log into this server I head straight to one of two directories (depending on which host I'm using)
    – Gareth
    Aug 6, 2010 at 7:32
  • 2
    What is RequestTTY yes for? Sep 8, 2021 at 18:22
93

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.

4
  • 1
    This ends me up at the correct location, with a bash prompt. perfect! Jul 13, 2012 at 21:06
  • This works for me too but if I try to use it with ssh jump-host it doesn't work. I get a connection closed message.
    – Riccardo
    Nov 4, 2015 at 10:29
  • This works perfectly for me. Aug 10, 2021 at 17:18
  • You can also specify another shell if you want. For example, you can replace bash with zsh
    – ma3oun
    Jan 24, 2023 at 17:29
69
  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.

5
  • 6
    On some machines you may need need to append cd /path/to/your/destination to ~/.bashrc instead of to ~/.bash_profile. The result should be the same.
    – Matthias
    Feb 2, 2016 at 11:11
  • This works perfectly thanks - is it only restricted to my user id or will it affect others user logins as well?
    – Ulysses
    Apr 26, 2017 at 3:53
  • @BabyGroot if you modify ~/.bash_profile or ~/.bashrc it will only affect the current user. Mar 15, 2018 at 13:27
  • I noticed I had to use .bashrc, but apart from that it works great! Jul 8, 2020 at 8:25
  • perfecto gracias Apr 28, 2022 at 14:29
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?

2
  • That directive is set, yes (and I assume I wouldn't see the error message shown if it wasn't). The problem with using .bashrc is that the server has different host names, and I'd like different host names to translate to different starting directories
    – Gareth
    Aug 5, 2010 at 14:57
  • Unless each host name has a different IP address, there would be no way for the server to know which host name you requested. While HTTP requests provide a friendly Host: header to identify the requested host name, SSH connections do not.
    – Fosco
    Aug 5, 2010 at 19:42
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
1
  • Creative... as long as you have write perms to /tmp
    – smci
    Nov 2, 2017 at 21:24
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

2
  • I prefer this to the previous suggestion because '$SHELL' is always valid, while 'bash' may not be. Also the use of 'exec' is a nice touch.
    – Dave
    Aug 16, 2017 at 2:24
  • A further refinement would to be ensure 'cd' is successful - "cd ~/$1 && exec ...'
    – Dave
    Aug 16, 2017 at 2:27
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.

1
  • Ok, removing quotes seem to help but I still have errors (see edited post)
    – Gareth
    Aug 5, 2010 at 15:15
2

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

ssh server -t "cd /my/remote/directory; bash"
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)

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.

0

I use the following in .ssh/config:

  RemoteCommand cd ~/mydir;bash
  RequestTTY force

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .