Scripting screen for fun and profit... :)
This article is written in english and rather long. First of all to improve my written english. But more importantly to get a bigger audience for this article. :-) I hope my english is not that bad.
People reading my blog know that I am a console-cowboy, meaning I mainly use console tools to do my work. As every cool console-cowboy naturally I use screen to manage my applications and displays.
I assume people reading this article already know about screen and its benefits and just want to learn how to get more out of it. But for all those people who don’t know about screen or why to use it, here are some random benefits:
screen detaching (safenet if you have a flaky network connection)
saving screen real estate
no need to use the mouse (everything can be done with the keyboard)
using the scrollback buffer you can view and search in the output of commands
using detached screens you can put interactive console tools into the background, like a daemon
many others I can’t remember just now
Gnu screen is a very powerful tool and has a lot of features which are sometimes not that easy to grasp. But investing some time into learning it can speed up your workflow a lot!
An introduction to screen can be found here:
Basics of screen scripting
OK. Enough chit chat. Lets get down to business. Most of the time you will use screen interactively. You want another screen windows, you press the buttons. But maybe unknown to some, screen is in some sort scriptable. It unfortunately is not straightforward and the very good manual gives only hidden hints. But if you know the edges it’s quite helpful.
The first and basic parameter you need to know is -X. With this parameter you can send screen commands to any screen session (for a list of screen commands take a look at the very fine man page for screen). By default it uses the screen session you are currently attached to. So just to test this, start screen, create a second window pressing C-a c. Now enter the following line at the shell prompt:
$ screen -X next
Wow. You just left the current window and went to the next window. This is the same as pressing C-a n or C-a :next<CR>. Impressive, isn’t it? :)
Where could this be used. Consider a program which needs a very long time to complete. You could start it inside a screen in the following way:
$ longrunningapp.sh; screen -X select <thiswindownumber>
You can get the windownumber by pressing C-a w. It’s the number right in front of the name of the screen which is marked by the star. If your windows have distinct names you can also use the name as parameter for the select command!
This line starts the application. After the application finishes the screen session focuses on the applications window, which means you will be automatically brought to that window. You don’t lose time looking and looking whether the application already finished. In the meantime you can continue work in another window.
screen -X -p
We just talked about different windows and their names/numbers. Consider the screen command stuff. It is used to send keystrokes to a window. By default the current window is used as the target. But this command is not very helpful if used interactively like
$ screen -X stuff hello
This way you can write notes to yourself. But if you add the parameter -p to this line you can send those commands to another window in the same screen session. Now this is helpful. You can remote control applications in windows this way. Consider the following example:
Create a screen-window and start e.g. w3m in it to show a webpage which changes over time (w3m is a console web browser like lynx or links). This could be a webpage showing usage statistics or stock information on the net or whatever. For this example we will use a page which shows the current weather for munich:
$ w3m http://www.meteo24.de/wetter/49X7464.html
This will output the current temperature etc. for munich. Unfortunately this display is not updated automatically. You manually have to reload the page. Let’s see how screen can help us.
Give the window a distinct name or just use the number of the screen window. To rename the current window to another name press C-a :title watchit. The current screen window now has the name "watchit". Enter C-a w to check this.
Now comes the interesting part. Go to another window in your screen session. To reload the website in w3m you have to enter R (Shift-r). So using the following line we periodically send R to the w3m-window which then reloads the website and updates the display.
$ while true; do screen -p watchit -X stuff R; sleep 5m; done
The sleep-command is used to reload the webpage only once every 5 minutes. You can enter nearly any value here. See man sleep for more information about sleep.
As you can see we now can remote control w3m. This might be a very simple example for remote controlling. With some experimentation you will certainly find more uses for this technique. Remember that w3m was just an example. We really only sent keystrokes to the other window. So any console tool can in principle be remote controlled using screen.
screen -X -p -S
Now lets take another step and remote control windows in other screen sessions. Remember that screen can be started on several terminals which creates several screen instances on your computer. You can see those screen-instances using screen -ls
$ screen -ls There is a screen on: 1840.pts-0.work (Attached) 6027.pts-5.work (Attached) 2 Sockets in /var/run/screen/S-gerhard.
As with windows in screen sessions, several screen instances (called sessions) can be identified by their number and their name. You can give a new screen session another name than the default one (which is the name of the tty it is started in) by adding the parameter -S at the command line (you have to be outside screen to start a new session!).
$ screen -S mysession
If you now run screen -ls you will see something like this:
$ screen -ls There are screens on: 1840.pts-0.work (Attached) 6027.pts-5.work (Attached) 6203.mysession (Attached) 3 Sockets in /var/run/screen/S-gerhard.
Other information in this output is whether the session is currently attached (meaning if it is currently shown on any terminal) or detached. Detached screen sessions are still running like attached screen sessions, but are not displayed anywhere.
Now to send a screen command to a certain screen session you can use:
$ screen -S mysession -X stuff hello
Try it and you will find the word hello in the currently open window in the other screen session.
Together with the -p parameter we now are able to send any screen command to any screen session (which is owned by yourself. screen does have some multiuser capabilities. But to describe them I will have to do another tutorial someday). The screen sessions have to run on the same computer though!
To get the current identifier of the screen you are currently in, you can read the environment-variable $STY. This way you have an identifier from inside scripts.
$ echo $STY 1840.pts-0.work
This environment-variable can also be used to check if your scripts is currently running inside an screen session. Be aware that if you change the name of the screen session via C-a :sessionname myname only screen -ls will show the correct name. $STY still will show the name the session had on starting it.
A thing to look out for
On thing to keep in mind while scripting screen is to be aware, that commands send to screen via the screen-command might not be finished when the commands returns. They might not even have worked correctly. The commands are put into a queue where they are execute when possible. So you don’t know wether a command was received, when it will be executed and if the execution was successful. The screen -X command works asynchronous. Take a look at the window-content-example below which demonstrates this point.
Examples for simple screen scripting
The following are simple examples on how to use screen scripting to do some things. I am expecting you to use bash as your shell. You might have to convert the examples to other shell environments if you are not using bash.
Checking if you are inside a screen session
$ if [ -n "$STY" ]; then echo 'We are inside screen'; fi
Getting the contents of a window
Using the hardcopy-command you can send the content of a screen window to a file for further observation. This way you e.g. could check in what state a remotely controlled application currently is. Be aware, that on exiting the screen-command doesn’t mean, the file is created! Unfortunately you have to wait for it to be created. Normally if you just sleep for some time after issuing the command should be enough. But you could also check for the file in a tight loop.
$ screen -S screenname -p windowname -X hardcopy /tmp/filename; sleep 1s; cat /tmp/filename
You can also get the whole content of the scrollback buffer if you add -h to the hardcopy-command.
The output in the filename also contains the screen status bar, if turned on. This can be used to check which window the screen session was in when the command hit it. Naturally you have to output the window name in the status bar to do this. :)
Running a screen window dia-show
Suppose you have several running console applications which output different changing data. As a screen lover you put them in several windows. If you want to see the output every now and then, you manually have to switch to all the windows and take a look (obviously you also could split the screen, but thats not always possible).
With the following line you can create a simple dia show effect, where every windows is shown for a small amount of time. You only need to now the sessionname of the screen session where the applications are running in. This way your precious data is constantly presented to you.
$ while true; do screen -S sessionname -X next; sleep 10s; done
A real script using screen is my screengraph-utility. It is available from this very website with full source code. Effectively it just uses hardcopy to gather the data from the designated screen window and then outputs the found data using gnuplot.
You now know how to send noninteractively commands to any screen windows running on your computer. With this knowledge you are able to automate your console tools, even if they are fully interactive. If you create interesting scripts using this technique please tell me. If there are enough ideas I might post another blog entry with those ideas. Just send them to firstname.lastname@example.org
I hope this article was of some help to anyone. Please post comments if you have annotations or if you find something that is wrong.
Example with long running example was wrong (2012-08-22).