Often, restarting Secure Shell (SSH) sessions is a daily occurrence. Because of this, it’s usually optimal to have repeating commands automated on entry.
In this tutorial, we explore ways to automate command execution during SSH session establishment. Our main example is a simple directory change. First, we briefly discuss remote administration and the repetitive tasks it may introduce. Next, we look at system solutions for an automatic directory change. After that, we turn to SSH for ways to automate command execution. Finally, an SSH configuration option takes the spotlight as the potential best solution.
For brevity and security reasons, we only consider the newest iteration of SSH version 2 (SSHv2) as implemented by OpenSSH.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4 and OpenSSH 8.4p1. It should work in most POSIX-compliant environments.
2. Remote Administration
Indeed, there are many different reasons for establishing an SSH session:
- tunneling and proxying
- forwarding X Server
- firewall setup
- network troubleshooting
- server configuration
- server troubleshooting
During network troubleshooting, there are sets of commands most administrators would run directly. However, if we automate repetitive actions for each SSH session, we can minimize our time when performing the task.
For the last two points from the list, administrators usually start by changing to a specific directory. For example, we might switch to a log (/var/logs), web server content (/var/www), or other common location.
Let’s take /var/log as an example. Switching to that path is easy with a simple command:
$ cd /var/logs
However, repeating an action on each connection can become an unnecessary delay and burden. Indeed, we have several options to avoid this.
3. System Solutions
Naturally, one of the simplest ways to run a command automatically comes from the system itself without relating to the access protocol.
3.1. Shell Configuration
As usual, we can employ the configuration of our shell to automate command execution in interactive and non-interactive sessions.
Actually, including any command in either Bash session setup file should suffice as both source .bashrc:
$ echo 'cd /var/log' >> $HOME/.bashrc $ echo 'cd /var/log' >> $HOME/.bash_profile
In the case of the latter command, we would only have the directory change in interactive sessions. Further, as one alternative to .bash_profile, the .profile file is more versatile in terms of shell compatibility.
3.2. Environment Variables
By default, OpenSSH uses AcceptEnv to pass through locale and language data:
AcceptEnv LANG LC_*
Building on top of the shell configuration changes from earlier, we can pass information with our client connection via an LC_* variable and the SendEnv option:
$ LC_CDPATH=/var/www ssh -o SendEnv=LC_CDPATH [email protected]
Here, we use the ssh client with its -o switch to introduce more options. Also, the command is prepended with a local environment variable assignment.
In practice, we can include the SendEnv option in our ssh_config file and then use $LC_CDPATH as our path in .bashrc or .bash_profile.
3.3. User Home Directory
When a directory switch is our only aim, depending on the circumstances, changing a given user’s home directory can be a viable option.
If our website administrator is webadmin, we can change the home directory of that user per our needs:
$ usermod --home '/var/www' webadmin
Here, we use the –home (-d) flag with the new path to change the supplied user’s home.
4. Authorized SSH Key Commands
On the SSH side, we can employ a lesser-known feature of the authorized_keys file to execute commands on all connections with a given public key.
By prepending command= to a line in authorized_keys, we can include a directory switch:
command="cd /var/www; /bin/bash -i" ssh-rsa AAAAB3NzaC1yc2EAAAAD[...]J9w7W0eJ/Yqr1hc6QjU= [email protected]
Note that the contents of command must be surrounded by double quotes. In fact, there are many other options and rules in authorized_keys.
Here, we use a script with two statements, as it needs to execute our desired action but also provide a shell afterward. In this case, it’s an interactive (-i) Bash session, but we can change that accordingly.
Critically, there are several potentially fatal flaws with this method:
- can override the default shell
- must specify session type on our own
- the prepended command affects other tools like scp and rsync, as well as all non-interactive sessions
- any error in the command or authorized_keys file syntax can prevent login, locking us out of our remote system
Still, the same user can create two keys and have only one change the current path. Further, we can configure this behavior in ssh_config on the client side and base it on the hostname:
Host xost HostName 192.168.6.66 User webadmin IdentityFile ~/.ssh/key Host webxost HostName 192.168.6.66 User webadmin IdentityFile ~/.ssh/commandkey
Now, connecting to webxost employs the key, which invokes a command, while using xost connects as usual.
5. SSH RemoteCommand
Finally, perhaps the most standard way for executing any command when establishing a remote SSH session is the aptly-named RemoteCommand statement, part of the ssh_config client configuration since OpenSSH version 7.6.
By using this statement, the setup becomes simple:
Host webxost HostName 192.168.6.66 User webadmin IdentityFile ~/.ssh/key RequestTTY force RemoteCommand 'cd /var/www; /bin/bash -i'
At this point, when connecting to 192.168.6.66 via the hostname webxost, we should end up in /var/www and an interactive Bash session. Because of the RemoteCommand statement, we need to explicitly force a TTY with RequestTTY.
This way, we have a properly set up shell session already in the correct directory.
In this article, we looked at ways to execute remote commands when establishing an SSH session with the example of a simple directory change.
In conclusion, while there are many ways to approach the problem and example, one stands out as the standard.