When starting ssh session with ssh command I seem to have two options - default interactive session with default env and starting from home directory - or to execute arbitrary command but non-interactively (even tricks like ssh "command; command; bash -i -l" don't seem to do much good). Quite often I want interactive session, but with something happening before that - normally a directory change, or sometimes system environment adjustment. These things would vary from session to session, so I cannot just stick them into .bashrc or so.

Is there any way to make that happen?


I'm self-answering, as I've finally discovered the secret. Neither -t option for ssh, nor -l option for bash will lead to login shell on their own - but in combination they work.

ssh user@host.com -t 'cd /some/where; FOO=BAR NUMBER=42 bash -l' changes directory, sets environment variables, and then starts proper login shell (the only difference I've found so far is that /etc/motd isn't displayed this way - it's normally ssh's or login's responsibility, not bash's - other than that everything seems to work perfectly, and all environmental variables are identical).

These environment / directory changes happen after ssh, so they're not restricted by PermitUserEnvironment and related settings (exactly as planned), but before .bashrc/.profile get executed. This has upsides and downsides - it is harder to just override something that gets set from bash init scripts like PS1, but easier to pack exactly the right values into ssh command lines, and have .profile do all the heavy lifting.

And if really necessary, it's actually pretty easy to get bash to execute something after .profile with command line like ssh user@foo.com -t 'cd /mnt; echo ". ~/.bash_profile; PS1=\"\\h-\w \"" >~/xxx; bash --init-file ~/xxx' - very ugly when put that way, but these alternative .profile files can be prepared before. (as far as I can tell bash has a few candidate locations for .profile script and will execute the first one found - . file doesn't have such automatic fallbacks, so you'll need to check where's your normal profile if you want to do that)

  • Awesome, thanks for this! I was looking to find a way to su into a user's account right after ssh'ing in, and the "-t" option made it work. Without that option, your shell doesn't have a prompt, doesn't have command history, dies from a SIGINT, etc. – Ashoat May 18 '12 at 1:22
  • This answer is really helpful but you're missing a few ;s from the first ssh login string. It won't let me edit your answer because I'm not changing enough. I got this to work ssh user@host.com -t 'cd /some/where; FOO=BAR; NUMBER=42; bash -l'. I think that's what you intended. – Rob Kwasowski Apr 5 '19 at 4:02
  • @RobKwasowski No @taw's version is correct: Without the semicolons the variables are passed as environment variables to bash -l and thus set in the ensuing login shell, while in your version $FOO and $NUMBER are set locally in the "intermediate session" but lost once the login shell starts. Yours should work if you exported the variables (e.g., export FOO=BAR;), though you would gain nothing but verbosity over the other approach. – flotzilla Apr 13 '20 at 11:00

Edit .bashrc and enclose your SSH-specific environment settings in:

if [ $SSH_TTY ]; then

This would allow you to add settings specifically for SSH sessions. 'Course, if all you want is to set arbitrary environment variables right at the outset that vary by session, I don't know how you can make the machine guess them for you apart from typing them... no matter what, you'll need some testable condition to base the choice of settings on.


From the ssh man page:

Additionally, ssh reads ~/.ssh/environment, and adds lines of the format “VARNAME=value” to the environment if the file exists and users are allowed to change their environment. For more information, see the PermitUserEnvironment option in sshd_config(5).

which says:

Specifies whether ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd(8). The default is “no”. Enabling environment processing may enable users to bypass access restrictions in some configurations using mechanisms such as LD_PRELOAD.

This facility could be used to conditionally execute statements in your remote ~/.bashrc using the if structure that Mickey suggested.


Simply run in this way : ssh -t yourdomain 'cd /yourpath; bash'

  • -t : so that prompt sh'd appear
  • ; bash : so that it sh'd return back the control despite of executing command (here cd) and exiting from ssh session
  • Welcome to ServerFault! Please provide and explaination and/or documentation for commands or scripts to explain what they are for. – Cory Knutson Oct 8 '18 at 18:00
  • 1
    Thanks @CoryKnutson, I have made the changes as you requested – Sumit Ramteke Oct 8 '18 at 19:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.