69

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?

7 Answers 7

57

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

chsh -s /bin/ksh foo
chsh -s /bin/bash username
6
  • 7
    Please note that the path to the binary has to be in /etc/shells for the shell to be selectable.
    – Kimvais
    Commented Jan 27, 2010 at 6:40
  • Ubuntu 16.04 doesn't have this command. Commented Nov 29, 2017 at 8:59
  • @david.perez Yes it does, in the passwd package.
    – dessert
    Commented May 10, 2018 at 8:15
  • This doesn't work when authentication is handled via LDAP Commented Jul 18, 2018 at 21:16
  • 3
    How is this SSH-specific??
    – user541686
    Commented May 21, 2020 at 2:45
29

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.

2
  • 2
    For accessing a windows machine, you can use: ssh -t <user@hostname> "powershell", or pwsh.)
    – not2qubit
    Commented Apr 29, 2020 at 22:33
  • 1
    If you'd like to automatically append that command via ~/.ssh/config so you don't have to type it each time, check this answer Commented Dec 15, 2023 at 18:46
14

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"

3
  • Why the -1 (15 chars...)? Commented Jan 27, 2010 at 7:31
  • that is a lower case L
    – floer32
    Commented Jan 6, 2015 at 21:40
  • 3
    ssh -t is required to get a TTY for last options. By default if a command (like zsh -l) is provided, OpenSSH would do a non-login shell, which would not allocate TTY for you, and -l won't change that (because that is executed after log in). Commented Oct 25, 2017 at 19:24
14

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

5
  • For some reason the users I recently created had no default shell. This worked for me. Thanks.
    – mimoralea
    Commented Jul 17, 2014 at 20:04
  • 2
    Thanks this answer is great. I didn't have a shell here either. I found the line myusername:x:1000:1000::/home/myusername: and added /bin/bash to the end. Log out and in and my ssh session is using bash :) Commented Dec 11, 2016 at 23:57
  • Can you explain how to edit this file?--meaning what changes to make to change the default shell? Commented Nov 9, 2021 at 1:09
  • I think the answer in serverfault.com/a/106723/3835 is much better to avoid messing directly with the file Commented Mar 15, 2022 at 9:54
  • 1
    It's far safer and easier to use proper tools for this purpose, e.g. usermod --shell /bin/zsh someuser
    – Walf
    Commented Sep 12, 2023 at 1:49
10

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"
1
  • this was already been told in the comments
    – djdomi
    Commented Nov 4, 2021 at 19:32
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).

You must log in to answer this question.

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