231

I'm trying to find UNIX or bash command to run a command after connecting to an ssh server. For example:

ssh name@ip "tmux list-sessions"

The above code works, it lists the sessions, but it then immediately disconnects. Putting it in the sshrc on the server side works, but I need to be able to type it in client side. I want to be able to run a command, it logs in, opens up the window, then runs the command I've set. Ive tried

[command] | ssh name@ip

ssh name@ip [command]

ssh name@ip "[command]"

ssh -t name@ip [command]
cadlac
  • 2,802
  • 3
  • 18
  • 34
  • 11
    You want to run a command, and then be left in an interactive shell on the remote server? – Barmar Aug 29 '13 at 23:54
  • @tripleee according to dates not this but another question is duplicate. – zviad Apr 27 '18 at 08:50
  • @zviad The age of a question is a secondary or tertiary concern when marking something as a duplicate. I don't have a strong opinion either way in this particular case, though I feel that perhaps the other question is more likely to be recognized as asking about this particular problem by new users who are looking for a solution to this. Ideally, a site moderator could merge the two questions if they both have valuable answers, though I have never seen that in practice. – tripleee Apr 30 '18 at 07:25
  • 3
    `ssh name@server "command; bash -i"` if you would like to send command to a remote server and stay connected – JP Zhang Nov 01 '19 at 17:13

3 Answers3

358
ssh -t 'command; bash -l'

will execute the command and then start up a login shell when it completes. For example:

ssh -t user@domain.example 'cd /some/path; bash -l'
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 3
    Forgot my own syntax, almost gave up on this! For anyone else, just suffix any command with "; bash -l". Perhaps you could change it to '[command]; bash -l' or something for clarities sake? I'll change my question. Thanks! – cadlac Sep 01 '13 at 08:38
  • 10
    I think it's even better to `exec bash -l`. – Jo So Sep 01 '13 at 09:08
  • That's great, but what if you want the command to show up in the bash history? – bsmoo Jan 30 '15 at 23:33
  • Don't know a good way to push a command into the history. – Barmar Jan 30 '15 at 23:37
  • 4
    Works well but this hides the command prompt for me. Is there are way to make it display in the usual way? – pythonjsgeo Feb 18 '15 at 02:18
  • I get the command prompt when I try it. Check your shell startup scripts to see what they test when setting the prompt, and figure out why it's not being set in this case. – Barmar Feb 18 '15 at 19:48
  • 4
    But what if the script you are attempting to run requires bash environment variables? – NobleUplift Oct 20 '15 at 14:23
  • 4
    @NobleUplift You could put an explicit `source .bash_profile` before the command – Barmar Oct 20 '15 at 15:23
  • 1
    ssh -i "key.pem" ec2-user@ec2-XX-XX-XX-XX.us-west-2.compute.amazonaws.com -t 'sudo su' but it does not switch to the superuser – Nusrat Nuriyev Sep 17 '17 at 19:49
  • @CEOatApartico Not sure what that has to do with this question, which is about going into a shell after executing some other command. – Barmar Sep 18 '17 at 18:41
  • For people using Homestead, this worked for me: `homestead.bat ssh -- -t 'cd /home/vagrant/Code/mysite/; ./vendor/bin/phpunit; /bin/bash'` (https://stackoverflow.com/a/22529114/470749) – Ryan Oct 05 '17 at 14:39
  • I normally change the shell to `bash` after loging in. Trying to automate this via above is not working. Any help if it this is achievable? I am trying `ssh $host -t "bash; cd workspace;" – mtk Oct 13 '17 at 11:46
  • @mtk https://serverfault.com/questions/368054/run-an-interactive-bash-subshell-with-initial-commands-without-returning-to-the – Barmar Oct 13 '17 at 15:47
  • Works great. After getting into the login shell I want to kick up a Rails console, something like this: `ssh 123.123.123.123 -t 'cd myapp; bash -l; rails console'`. Any ideas? Thanks. – Joshua Pinter Oct 30 '17 at 16:40
  • @JoshuaPinter Why do you need `bash`? Just `ssh -123.123.123.123 -t 'cd myapp; rails console'`. – Barmar Oct 30 '17 at 17:25
  • 1
    @Barmar I get a Rails error that only shows up when I don't use `bash -l`. The error is `database configuration does not specify adapter`. Maybe it's a bash environment thing. I tried `source .bashrc` but that didn't help. Not sure how to find out what's going on with `bash -l` that makes it work fine. – Joshua Pinter Oct 31 '17 at 03:10
  • Try sourcing your `.profile` or `.bash_profile`. – Barmar Oct 31 '17 at 03:20
  • Jo so's answer is correct. On macOS, the only way I can being an ssh session and then automatically open say, Gnome disks is: `ssh -Y root@cheese exec gnome-disks` – Tomachi Mar 26 '19 at 15:40
7

This isn't quite what you're looking for, but I've found it useful in similar circumstances.

I recently added the following to my $HOME/.bashrc (something similar should be possible with shells other than bash):

if [ -f $HOME/.add-screen-to-history ] ; then
    history -s 'screen -dr'
fi

I keep a screen session running on one particular machine, and I've had problems with ssh connections to that machine being dropped, requiring me to re-run screen -dr every time I reconnect.

With that addition, and after creating that (empty) file in my home directory, I automatically have the screen -dr command in my history when my shell starts. After reconnecting, I can just type Control-P Enter and I'm back in my screen session -- or I can ignore it. It's flexible, but not quite automatic, and in your case it's easier than typing tmux list-sessions.

You might want to make the history -s command unconditional.

This does require updating your $HOME/.bashrc on each of the target systems, which might or might not make it unsuitable for your purposes.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • This is quite useful, but what I've noticed is that the history will be cleared, except for the new command on a fresh login. Do you know why that happens and how you can prevent that? I just noticed that after I commented out the line in .bashrc the full history is now available. – Andy Jul 22 '16 at 06:19
4

You can use the LocalCommand command-line option if the PermitLocalCommand option is enabled:

ssh username@hostname -o LocalCommand="tmux list-sessions"

For more details about the available options, see the ssh_config man page.

Darryl Hein
  • 142,451
  • 95
  • 218
  • 261
gypaetus
  • 6,873
  • 3
  • 35
  • 45
  • 1
    For me, (OS X) this had to be `ssh -o "LocalCommand tmux list-sessions" user@hostname`. – Erik Nomitch Sep 16 '15 at 11:24
  • 52
    This answer is based on misunderstanding the question. The question is about running a command on the remote server immediately after connecting. LocalCommand (as the name implies) runs a command on the local machine. – robo Feb 15 '16 at 19:46
  • 7
    RemoteCommand is the option you are looking for here. `ssh name@ip -t -o RemoteCommand="tmux ls; bash"` See: https://man.openbsd.org/ssh_config#RemoteCommand – Hockey Jun 23 '21 at 08:16