Running programs on a remote machine in an ssh session is convenient, but has a few downsides. First, if the connection drops (Internet outage at either end, firewall reconfiguration, or other network problem), the running program is frequently killed. Second, you no longer have the freedom to shut down or move the ssh client laptop; if it moves to a new address, we lose the program on the server as well.
We can fix both of these by running apps on the server(s) inside screen, a utility included in Linux, Mac OS, and other unixes (and available on Windows with the Cygwin add-on). The screen program grabs the program output and remembers it even when the ssh connection has gone away for either of these reasons, showing it to us again when we reconnect. This allows the user to start a program, run it for a while, disconnect entirely from the server, shut down her laptop, and reconnect when she gets home. The program on the server doesn't even notice that the user temporarily disappeared.
You'll need to have the screen program installed on each server. To see if it's already on the server, run this from your client:
ssh myserver 'which screen'
If this returns a path to the screen program you're all set; otherwise run:
ssh -t myserver 'sudo apt-get install screen || sudo yum -y install screen'
While you certainly can have screen on your client system and it can be quite useful on the client end too, it's not required for this.
This script sets up the connection and sets a title for your local window when possible. Pick a directory in your path and save the following lines to the file to in that directory:
#!/bin/bash echo -ne "\033]0;${1}: ${2}\007" ssh -t "$1" screen -S "${2:-DefaultScreen}" -d -R
Now make the script executable with:
chmod 755 /script/directory/to
Instead of running ssh myserver, run:
to myserver
If you've set up ssh keys already, this will put you in a shell just like ssh did. (Note: if you're still using a password for ssh, you'll be prompted for it. This would be a great time to switch over to ssh keys for the convenience and security.)
Here you can start up anything you could have with ssh. To test it, run this command:
while sleep 5 ; do date ; done
Let this output a few lines, then let's disconnect with Ctrl-a, then d. This tells the screen program on the server that you're exiting, and the ssh connection that got you there will close down too. The screen program will continue to run on the server, running the date program every 5 seconds. Wait for 15 seconds or so, then reconnect with the same to myserver command you used above. When you're back, notice that there are more date output lines than when you started; the screen program caught them and remembered them while you were disconnected. You can disconnect with Ctrl-a, d and reconnect with to myserver as often as you'd like and the program will keep running. You can even disconnect, shut down your laptop, move to a totally different network, start back up again with a new IP address, and reconnect - screen and the programs you run in it won't notice.
Disconnect with Ctrl-a, d when you're done.
You can even have multiple screens running on a single server. Pick a name for a new session, one that describes what you intend to run in it. In this example I want to run top and be able to disconnect and reconnect. I'll call the session monitoring and start it up with:
to myserver monitoring
Instead of connecting to your old session that was running date every 5 seconds, you get a fresh command prompt. Run top in it and test that you can disconnect like above. Once you're back to your laptop, connect to the original session with:
to myserver
You should be looking at the date output again. This lets you switch back and forth between as many sessions as you'd like by giving them different names. For reference, our first screen session actually does have a name: "DefaultScreen", since we didn't include one following to myserver.
Let's say you want the output from a single command to show up in multiple terminal windows; perhaps you're doing a demo of a tool and want to see it on multiple (non-mirrored) monitors.
First, create the screen session on the server that will host it with:
screen -S screen_name -R
(don't use the "to" script with any of these sharing approaches; "to" kicks off anyone that has that screen session open, which is not what we want.)
Start a program to watch there, say, "top".
Now ssh to the server if you're not already on it and connect with the "-x" parameter:
ssh server_name screen -x screen_name
You should instantly see the "top" program you started. Any keystrokes you type in either window are fed to the program immediately. If you type "M" in one window top will sort by memory usage; if you then type "P" in the other window it will sort by processor usage.
Lets say two different users - lisa and bart - want to see the same output. The steps are similar, but the user that starts the screen window needs to give permission to the second user before they can connect. One bit of housekeeping; as root or under sudo, run this once (and after the screen package is updated in the future):
sudo chmod u+s $(which screen)
Now, create the screen session as lisa:
screen -S screen_name -R
In that window, you'll need to type the following:
ctrl-a:multiuser onEnter ctrl-a:acladd bartEnter
At this point bart can connect with:
screen -x lisa/screen_name
Keep in mind that bart now has access to a terminal that's logged in as lisa, and can type any commands that lisa has rights for. Good thing bart never misbehaves.
To let other users see what you're doing but not give them access to type anything, we have to do two things. First, we have to block bart from writing to this specific terminal:
ctrl-a:aclchg bart -w "#"Enter
Now, we have to block bart from most of the features of screen, or else he could simply create a new window, in which he regains write privileges. The first command below strips bart of all access, then the second command gives him back minimal abilities:
ctrl-a:aclchg bart -x "?"Enter ctrl-a:aclchg bart +x "colon,wall,detach"Enter
If lisa is hosting multiple users and wants to make them all read-only:
ctrl-a:aclchg * -w "#"Enter ctrl-a:aclchg * -x "?"Enter ctrl-a:aclchg * +x "colon,wall,detach"Enter
All of the above restrictions and sharing commands should be run before you give bart or other users access to this machine.
sudo adduser shareduser sudo passwd shareduserGive everyone involved access to this account with password or ssh keys. Log in as shareduser and create the screen session with:
ssh shareduser@server_name screen -S screen_name -REveryone else logs in as shareduser and connects with the "-x" parameter:
ssh shareduser@server_name screen -x screen_nameWhen done, delete the account with:
userdel -r shareduserDepending on your operating system, you may need to use "deluser" instead - check the man pages for details.
When you're connected using any of the above approaches, you're interacting with the screen program, so you can do things like running multiple programs in a single screen session (create a new window with ctrl-a, c, switch to the next window with ctrl-a, n, switch to the previous window with ctrl-a, p, and close a shell with exit). See man screen or the User's manual for more details.
This is perfect for both services for which you want to see the output, perhaps for debugging, and other long-running processing jobs. If your server sends a lot of output to the screen and/or you have a slow connection between the client and the server, this approach may actually let the program run faster than over straight ssh. Simply start the program up, disconnect for a while, and reconnect from time to time to see how it's doing. While you're connected, the program will likely have to wait for the output to arrive at the client. While disconnected, screen on the server accepts that output essentially as fast as the program can create it, letting it run more quickly.
If you need to forward ports, the agent service, and/or X-windows over ssh, you'll want to do all of those with a standard ssh session instead of this screen approach. It's fine to have one or more screen-over-ssh windows as well as standard ssh connections to the same server at the same time.
If you forgot what you named a screen, you can get a list of running sessions with:
ssh myserver 'screen -list'
If you're inside X-windows or a smart terminal program on the client end, the title bar will likely change to show you to which server and screen session you're connected.
You're not limited to a single client machine with this. As an example, you could connect to a screen session from your home Linux PC first thing in the morning, and then connect to that same session from your work Mac before lunch. The script even handles the case where you forgot to disconnect before you drove to work; to will kick off any old connections to a screen automatically.
When you're done with a screen session, simply type exit in the screen session, just like you would have done in ssh.