Force SSH to use a specific shell

107,925

Solution 1

I don't believe this is possible, at least with openssh-based systems. If you have the ability, a better solution might be to sftp up a shell-script file, and then execute it with the method you posted. It would have the advantage of minimizing the amount of escaping needed, but would leave a file behind that would have to be removed (perhaps as the last step of the script).

Solution 2

You can use the -t option to force allocation of a pseudo-tty for the program you want to start, as if you were executing the standard shell. Then pass the shell you want as a plain old argument.

With this technique you're able to not only use any shell that's installed but you can also open vim and other programs which require a TTY, from a single command. Which is cool if you're writing a shell script that logs you in somewhere and opens a file on vim, or htop or something.

Here's bash

me@my-machine $ ssh root@myhost -t bash
root@myhost:~# 

sh works too. As does anything else really.

me@my-machine $ ssh root@myhost -t sh
# 

Not sure whether this is a login shell but there's options to make bash act like a login shell, so your shell might have that too.

Solution 3

Use a heredoc:

ssh host.domain.com /bin/bash << EOF
big ugly commands
lots of them
EOF

Solution 4

Use key-based logins, not password-based. Then you can add a (list of) "forced command(s)" to your public ssh key (in the "options" field in case of SSH1) which is installed on the server (in ~/.ssh/authorized_keys file for SSH1, ~/.ssh2/authorization for SSH2).

Make your forced command so that your desired shell is called...

More: You can associate at most one forced command to a given key. If you require multiple forced commands for different purposes, you have to setup different keys. (Of course you can put multiple things into one script, which you call via forced command. But be aware that forced commands are always run for a given account/key if the user logs in, regardless if he asked for something different to run. If you want to still honor the original command asked for, have a look into how to exploit the $SSH_ORIGINAL_COMMAND variable...)

Read up about "forced commands" via Google.

Solution 5

Surprisingly I see different results with the following:

run in dash:

ssh [email protected] /bin/bash -c "echo <(cat)"                                              
sh: 1: Syntax error: "(" unexpected

vs bash:

ssh [email protected] '/bin/bash -c "echo <(cat)"'                                            
/dev/fd/63

Showing the fully quoted command is working as expected.

Share:
107,925

Related videos on Youtube

plinehan
Author by

plinehan

Updated on September 17, 2022

Comments

  • plinehan
    plinehan almost 2 years

    Is there any way to force SSH to use a particular shell on the remote end, regardless of what the user's default shell is?

    I've tried solutions akin to:

    ssh host.domain.com /bin/bash -c 'complicated, multi-line command'
    

    but unfortunately the default shell on the remote end is responsible for parsing the "complicated, multi-line command" part, and I'm having difficulty escaping it sufficiently to work both for Bash and C shell users.

  • Weboide
    Weboide almost 14 years
    shouldn't you use "-s" for bash to read commands from stdin?
  • Ignacio Vazquez-Abrams
    Ignacio Vazquez-Abrams almost 14 years
    It isn't always required.
  • plinehan
    plinehan almost 14 years
    This is what I eventually did, but using scp. A great idea.
  • plinehan
    plinehan almost 14 years
    Good stuff. That graphic on the O'Reilly page is very nice. In my particular case, however, I want to be able to force this for any users, not just users who have set up their keys correctly. I also don't have root on the server machines, so I can't edit files like /etc/sshrc.
  • Kurt Pfeifle
    Kurt Pfeifle almost 14 years
    Well, it is always the server (or better: the one who exerts control over the server) who calls the shots when you connect to its service.... The 'owner' of the server decides what can be done with it. -- You cannot force anything 'for any user(s)' if you don't have higher privileges than them.
  • Eric Woodruff
    Eric Woodruff almost 10 years
    If the client can run arbitrary commands then the client can run an arbitrary shell as a command too.
  • Eric Woodruff
    Eric Woodruff almost 10 years
    I would vote this down if I could because it prevents the commands from having access to stdin and the question was about invoking a particular shell.
  • Brian Vandenberg
    Brian Vandenberg over 9 years
    @KurtPfeifle that link to O'Reilly is broken
  • Kurt Pfeifle
    Kurt Pfeifle over 9 years
    @BrianVandenberg: Thx for the hint. I removed that link now.
  • Charles Duffy
    Charles Duffy about 7 years
    @EricWoodruff, ...invoking a particular shell (in this case bash) is exactly what this shows how to do.
  • Charles Duffy
    Charles Duffy about 7 years
    Not surprising at all. The remote ssh daemon effectively runs sh -c "$*". Thus, you're running sh -c "/bin/bash -c echo <(cat)"; the echo command itself is the only argument passed to -c, and the <(cat) is a separate argument altogether.
  • Trevor Boyd Smith
    Trevor Boyd Smith about 6 years
    FYI you can also do cat /tmp/tempfile_containing_your_script ssh ${hostname} /bin/bash. So instead of one step you have two steps: step 1 copy your script to a file, step 2 cat the script to ssh.
  • belvederef
    belvederef over 4 years
    I do not get why this does not appear higher in the search results. Worked perfectly!
  • Hi-Angel
    Hi-Angel about 4 years
    Thanks, I confirm it works for me for automatically logging into zsh instead of bash (users of the remote instance vary, so I can't force zsh on everyone with chsh). That said, I think it would help if usage example was in the answer instead of being a link to google. I'd sure give it my upvote.
  • Hi-Angel
    Hi-Angel about 4 years
    Okay, my rejoice was prematurely. What now happens is that sshfs hangs. In fact, anything you could try to execute as ssh … mycommand hangs, with sshfs just being a particular case I'm interested in. So I guess no automatic login to zsh for me :c