45

Whenever I login to my Linux server I'd like to have several commands run automatically (set some variables, change location, etc.)

This needs to be done on user login, not on system start.

How can I set it to do this?

1
  • You need to read the section INVOCATION in bash(1) (man bash). Nov 8, 2011 at 9:39

7 Answers 7

48

Put the commands in ~/.bashrc. Anything in there is executed each time you log in.

If you need commands to only run when logging in via ssh (but not when logging in physically), you could probably test for the presence of the SSH_CONNECTION environment variable, and only run the commands if you find it exists.

11
  • I'm not logging in as root, it's an AWS server so I have to login as "ec2-user" then change to root using "sudo su -". So should I put the commands in "/home/ec2-user/.bashrc"?
    – Alasdair
    Nov 8, 2011 at 6:45
  • 5
    This assumes ~/.bashrc is sourced from your ~/.bash_profile. ~/.bash_profile will be the script that is invoked for a login shell like ssh. I believe ~/.bashrc will get called if you open up a Gnome Terminal, for example, AFTER having already logged in.
    – dgrant
    Nov 8, 2011 at 6:46
  • You've confused me, let me explain more: This is an Amazon Web Services instance, which is a virtually server, so no one will ever physically log in (I'm not even sure if it physically exists as one machine). I login using PUTTY with the username ec2-user. This drops me in /home/ec2-user directory. I then change to root user by typing "sudo su -", which then drops me into "/root", then I have to type a series of commands, including changing me back to "/home/ec2-user" and setting some variables, aliases, etc. So... how would I get it to do this?
    – Alasdair
    Nov 8, 2011 at 6:52
  • Also, since I am changing user, I expect that in the ec2-user bash profile I should put only "sudo su -", and then the rest of the commands in the root bash file?
    – Alasdair
    Nov 8, 2011 at 6:52
  • NOTE: actually, it's .profile that gets called if it exists, unless .bash_profile, exists, then it is called instead.
    – dgrant
    Nov 8, 2011 at 6:52
29

Just put this in ~/.bashrc or /etc/bash.bashrc if you want this for all users:

if [[ -n $SSH_CONNECTION ]] ; then
    echo "I am logged in remotely"
fi
6
  • and how do I lose the session after closing execution?
    – e-info128
    Oct 27, 2014 at 18:47
  • 1
    @WHK What do you mean by losing the session? Oct 28, 2014 at 16:16
  • @Llamageddon: I think he's wondering the same thing I am. If I wanted to put my entire SSH session into screen, I might use your answer and put screen there instead of the echo. The problem with that is that finishing the screen session will return to the SSH prompt instead of logging out. Just writing out this comment gave me the answer, though: add the logout command after the screen command.
    – zondo
    Jan 4, 2017 at 13:53
  • This however does not work for ssh session which do not use bash, e.g. when I open an sftp session.
    – Fabio
    Jan 28, 2017 at 10:49
  • @zondo @e-info128 exec command will replace the current shell with whatever you run. Jan 29, 2017 at 12:37
20

Alternatively, you can specify a command to be run during the invocation of ssh:

$ ssh -t server 'cmd; exec bash -l'

The last command in the list should start an interactive session in your preferred shell. If you have a lot of commands to run, consider creating a script file on your SSH server.

1
  • 2
    THIS is very useful. Not sure if it's exactly the answer the questioner asked, but people should know about it, since it may not be obvious. For example "ssh user@host "export x=5; bash" Then in terminal that pops up echo $x displays 5.
    – clearlight
    Jul 26, 2019 at 12:00
17

Actually ~/.ssh/rc is a right place for you to add command to run when you log in, rather than any user of the system.

 ~/.ssh/rc
         Commands in this file are executed by ssh when the user logs in,
         just before the user's shell (or command) is started.  See the
         sshd(8) manual page for more information.
3
  • Not necessarily. It is a location where commands can be placed.
    – Daniel B
    Nov 9, 2018 at 6:44
  • 1
    That could REALLY get someone into trouble if they didn't know what they are doing. It's potentially useful in corner cases, but that could REALLY mess someone up if they forgot they put commands there or the name and the path of that file. Gennerally it would be highly preferred to put the startup login commands in the expected place, .bashrc on the remote side and test for $SSH_CONNECTION, as other answers here have suggested.
    – clearlight
    Jul 26, 2019 at 12:29
6

If you use a SSH config file to connect, you can embed a startup command that will only execute when you connect the host.

For this insert / edit the following into your ~/.ssh/config on your client machine:

Host myhost
  HostName *.*.*.*
  User root
  RequestTTY force
  RemoteCommand cd / && bash -i

Put the appropriate hostname and append a new line Port XX if the port differs from 22. The sample will cd in the root of the server. && bash -i and RequestTTY force are essential to continue usage of the remote terminal.

To connect to your host you have to install your public key on the target machine that you can retrieve like so:

cat ~/.ssh/id_rsa.pub

And install on the remote like so:

mkdir -p ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys && chmod 644 ~/.ssh/authorized_keys && echo "YOUR_PUBLIC_KEY" >> ~/.ssh/authorized_keys

Then you can simply connect the machine like so:

ssh myhost

And it will connect and execute the RemoteCommand.

1
  • 2
    To copy keys to the remote server, it's much easier to use ssh-copy-id -i <path_to_your_keyfile>. It will handle all the directory creation and access controls for you. However, the ssh-copy-id command is not available on all systems.
    – JS.
    Aug 4, 2022 at 20:27
1

If you want to run a script after any user logs into your server, you can achieve this by using the ForceCommand directive in the sshd_config file. The ForceCommand will run before any user-supplied commands and before they are given access to a shell.

Follow these steps to set it up:

  1. Edit the /etc/ssh/sshd_config file using your preferred text editor. You may need superuser privileges to do this:

    $ sudo nano /etc/ssh/sshd_config
    
  2. Add the following lines to the sshd_config file:

    Match User *
        ForceCommand /bin/bash -c "/path/to/script"
    

    Some important notes:

    • This will override the process of ssh running the user their shell, so that will have to be added to the script as done below.
    • You can make this user specific by putting the username in place of the star.

Here's an example of what your script could look like:

#!/bin/bash

# Create a welcome file for the user
touch ~$USER/welcome

# Check if the user is sending a specific command via SSH
if [[ $SSH_ORIGINAL_COMMAND ]]; then
    eval "$SSH_ORIGINAL_COMMAND"
else
    # !!NB!!
    # if the user has not specified a ssh command run their shell
    exec $SHELL
fi

The script first creates a welcome file in the user's home directory. Then, it checks if the user is sending a specific command via SSH and, if so, executes that command after the script has completed.

Don't forget to restart your sshd service with either $ sudo systemctl restart sshd.service or $ sudo service ssh restart depending on your system.

0

To have a script that will execute for any user on login you can add an additional script in:

/etc/profile.d/

For example:

/etc/profile.d/Hello.sh
Hello `whoami`

On login would produce:

$ ssh MyTestUser@localhost
Hello MyTestUser

The profile script is executed as the user that is logging in. This may or may not be a problem depending on what you want the script to do.

You must log in to answer this question.

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