62

How do I set the shell that is used when a user SSHs to a server. For example I can't stand BASH and need to use ZSH, how do I make it so ZSH is loaded along with my profile (.zsh_profile) when I ssh to the machine.

I dont want to have to pass a bunch of parameters with ssh either, can't I set the default shell?

JP Silvashy
  • 1,447
  • 6
  • 24
  • 30

7 Answers7

54

Assuming you're running on Linux, you can use the chsh command.

chsh -s /bin/ksh foo
chsh -s /bin/bash username
Dominic Barnes
  • 641
  • 1
  • 7
  • 4
23

If you can't change your default shell, ssh -t user@host 'zsh -l' works.

The -t flag forces a pseudo-tty allocation, and the -l flag spawns a login shell.

Mark
  • 366
  • 2
  • 3
15

man chsh changes shell, does not always work

Alternatively, you can stick exec /bin/zsh in your bash login script.this will replace bash instance with your shell.

Or you can do ssh host "zsh -l"

13

Edit /etc/passwd (if you have the rights, or ask your system admin) to change your default shell.

Valentin Rocher
  • 231
  • 1
  • 4
8

I'm not sure how you can put your local .zshrc to remote server, (that's without permanently storing it there), this works for me to change my login shell on remote server.

Since it's a shared account, I can use zsh only for myself with this method.

Add this to your ~/.ssh/config file in your local machine.

Host yourServer
    HostName <IP, FQDN or DNS resolvable name>
    IdentityFile ~/.ssh/<your keyfile>
    RemoteCommand zsh -l
    RequestTTY force
    User <yourUsername>

There could be hackish way to accomplish what you are looking for, like below.

WARNING This comes with no guarantees and doesn't look 'wise', however I did managed to put my local file to server and source it in login shell using this.

Host someHost
    HostName someIP
    IdentityFile ~/.ssh/somekey.pem
    RemoteCommand zsh -l -c 'sleep 1; source /tmp/somefile; zsh'
    PermitLocalCommand yes
    LocalCommand bash -c 'sftp %r@%h <<< "put /tmp/somefile /tmp/somefile"'
    RequestTTY force
    User someUser

How it works?

  • RemoteCommand defines what needs to be run on remote side.
  • LocalCommand defines what needs to be run on local, which is used to copy your local file to remote server for sourcing it. Here is the catch, it happens only after 'successful' connection to remote host.

Meaning:

  1. Your connection to remote should be open and alive
  2. Your remote shell doesn't have the file yet, so it has to wait till file is there, ergo sleep
  3. Your local uses sftp to put your file to remote server, remote server wakes up from sleep and sources your scripts.

It's super hackish, I'd like to know if there is a better way, too.

Update: This can be used instead of 'long' sleep time:
RemoteCommand zsh -l -c 'while [[ ! -f /tmp/somefile ]]; do sleep 0.05; done; source /tmp/somefile; zsh'

3

If you are using Windows:

  • to use PowerShell 5, use ssh -t <username@servername> "powershell"
  • to use PowerShell Core, use ssh -t <username@servername> "pwsh"
  • to use bash (Git Bash or WSL), use ssh -t <username@servername> "bash"
Ayka
  • 31
  • 1
1

About the original question: change the shell opened by a SSH session, I don't think that it is configurable. You can change the shell used by the user on the system (chsh, or edit /etc/passwd), or even change the default shell of the machine, but not the SSH shell (I think SSH just opens a regular session with the user's parameters, including shell configuration).

Regis
  • 11
  • 1