OpenSSH has a nice feature that makes it possible to open one “master connection”, which can be shared by multiple subsequent ssh/scp/sftp “slave connections”. The advantage is that you need to supply password only when opening the master connection and thus you can easily perform a sequence of remote commands without constant re-authentication. Let’s see how to do it in such a way that it can be used in a script.
1. Open the master connection
We will open an SSH connection that sets up the shared channel and puts itself into the background when authenticated and does nothing else:
SSHSOCKET=~/.ssh/myUsername@targetServerName ssh -M -f -N -o ControlPath=$SSHSOCKET myUsername@targetServerName
The options have the following meaning:
- -M instructs SSH to become the master, i.e. to create a master socket that will be used by the slave connections
- -f makes SSH to go into the background after the authentication
- -N tells SSH not to execute any command or to expect an input from the user; that’s good because we want it only to manage and keep open the master connection and nothing else
- -o ControlPath=$SSHSOCKET – this defines the name to be used for the socket that represents the master connection; the slaves will use the same value to connect via it
Thanks to -N and -f the SSH master connection will get out of the way but will stay open and such usable by subsequent ssh/scp invocations. This is exactly what we need in a shell script. If you just do something manually than you can leave out -N and -f and use directly this connection for whatever you need while you can also open a slave connection in another terminal window. Just don’t forget that once the master connection exits slaves won’t work.
2. Open and close other connections without re-authenticating as you like
Now you can do as many ssh/scp operations as you like and you won’t be prompted for a password. You only always have to provide the command with the same ControlPath, which we ensure by having stored it into the variable SSHSOCKET:
ssh -o ControlPath=$SSHSOCKET myUsername@targetServerName "echo 'Hello from the remote server!'; ls" ... scp -o ControlPath=$SSHSOCKET myUsername@targetServerName:remoteFile.txt ./
3. Close the master connection
You likely don’t want to keep the master connection open forever. And it’s better to close it properly beause otherwise the socket file would not be deleted and would prevent the master connection from opening in the future.
You close the connection by sending the control command exit to the socket:
ssh -S $SSHSOCKET -O exit myUsername@targetServerName
- This time time we use -S instead of “-o ControlPath=” because we intend to use the socket for controlling the master SSH instance
- -O <command name> is used to send a command to the master SSH instance; the commands allowed are “exit” and “check”
This is a neat way how to execute multiple ssh/scp/… commands while only supplying a password once. There are also other ways how to do it, such as putting you key into the ~/.ssh/authorized_keys at the host or using the ssh-agent and ssh-add.
It should be noted that at least some older versions of OpenSSH have the limitation that slave connections cannot set up port forwarding.