Teaching with screen(1)
Using a standard Unix tool for remote interaction
(originally published on Linux.com)
Recently I needed to do some distance education: one of my coworkers wanted me to show him how to do some software builds on Linux. The only problem was that I'm on the east coast and he is on the west coast. How could I show him the build and install process? I could just do the work and use the standard Unix utility
script(1) to save a log of my typing. This has several problems, not the least of which is the horrible resulting output (
script saves everything, including carriage returns and corrections). In addition, this would be completely non-interactive. If my coworker had a question or needed a clarification we would have to correspond via email afterward. That would be a frustrating experience for both of us.
One solution to this problem would be to use VNC. My coworker could connect to my display and we could alternate control of the mouse and keyboard. That approach seemed like overkill since what I wanted to demonstrate was purely command-line work. It would also be difficult to generate a log of a VNC session. Finally, technical limitations dictated that the only way he could connect to my machine for the demonstration was over a simple ssh connection so this dictated a purely command-line solution.
With this in mind I narrowed my search to command line tools only. I have recently become a great fan of GNU Screen. and I knew you could use some sort of multiuser mode in screen. That seemed like a promising solution.
Screen is one of those tools that is hard to explain but pure genius once you see it in operation. The description from the official website doesn't help too much:
Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells.
For an introduction to screen, check out this Linux.com article from last year. Basically screen allows you to create virtual terminals which are not connected to your actual xterms or console screens. You can then disconnect from a screen session and reconnect from somewhere else while preserving your shell or other running processes.
This is just the beginning of screen's power and flexibility. You can connect to a session more than once using the
-x argument to screen. That means you can for example leave your mail program running in a terminal (under screen) at work and then connect from home to read your mail in the same process. No need to disconnect at work and when you come back in the next morning your mailer will be exactly as you left it will all your state perfectly preserved.
Screen takes this feature (called multi-display mode) to the next level with multi-user mode. In multi-user mode more than one user can access and control a screen session. The problem with this mode is that it's not very obvious how to set it up. Here's what I ultimately figured out with the help of some google searching. Note that the two users are
- Set the screen binary (
/usr/bin/screen) setuid root. By default screen is installed with the setuid bit turned off as this is a potential security hole.
- The teacher starts screen in a local xterm, for example via
screen -S SessionName. The
-Sswitch gives the session a name which makes multiple screen sessions easier to manage.
- The student uses ssh to connect to the teacher's computer.
- The teacher then has to allow multiuser access in the screen session via the command
ctrl-a :multiuser on(all screen commands start with the screen escape sequence,
- Next the teacher grants permission to the student user to access the screen session with
ctrl-a :acladd studentwhere
studentis the student login id.
- The student can now connect to the teacher's screen session. The syntax to connect to another user's screen session is
screen -x username/session.
At this point the teacher and student both have control of the session. Note that there are certainly security implications to this - the student is operating the session as the teacher and could potentially do something to damage the system. If you don't trust your students then you should probably use a special teacher account and not your normal login account. The teacher can also make the student's session read-only as desired. To do this, use the
aclchg screen command to remove write access for the student:
ctrl-a :aclchg student -w "#". The student can then only observe the teacher's actions. Otherwise, the teacher will have to work on the honor system.
While my example centers on one teacher and one student, many more users could attach to the session. There could even be multiple 'teachers' and 'students' if desired.
What about communication between teacher and student? In my example, this was accomplished with a telephone. Alternately you could use some sort of instant messaging or IRC connection for asking questions. There is also an message feature in multiuser screen:
ctrl-a :wall message will write a message to all users connected to a screen session. One problem with this is it uses the terminal status line. In an xterm this is the window titlebar area, which depending on your window manager may not be very obvious.
The final ingredient for using screen as a teaching tool is logging. With a log of all the terminal output my coworker and I would have an exact transcript of what we did in case there were any questions later. As I mentioned earlier the standard Unix tool
script(1) is the obvious answer but it is a very limited tool and does not produce very readable output. You also can't turn it on and off inside a session if for example you want to run a full-screen tool like a text editor.
Fortunately screen comes with a comprehensive logging facility which is much more sophisticated than what
script(1) can do. screen logging can be turned on or off at any time with
ctrl-a H, or you can use the
-L switch when starting screen to enable it by default. The log file will be written to the current directory under the name
n is incremented by one for each new log.
The logfile will contain the 'cooked' output of your session, i.e. what with corrections and cursor movements already evaluated and applied. One caveat is that programs that send control sequences to the screen will still confuse the output. One example of this is GNU ls, which by default colorizes output. Turn this off in your session by using something like the following bash alias:
alias ls='ls --color=none'
With that all the pieces are in place: multiple users can share a screen session for any sort of command line-based instruction. The teacher can at any time take control of the session by switching all other users to read-only access. Finally you can turn on the logging facilities in screen to get an accurate and usable log of the entire session (or just portions of the session if you desire).
I found this use of screen to work extremely well and my coworker was also pleased with the results. Some of the options and controls in screen can be a bit hard to figure out but much of that is because screen is so powerful and flexible. I plan on using this tool in the future and I encourage anyone in a similar situation to give it a try as well.
After this article was originally published, Samuel Skånberg asked the question of how in a script you would open one screen session with multiple windows, instead of separate screen sessions for each process. Originally he was trying to do this:
#!/bin/bash for i in [email protected] do screen -d -m btdownloadcurses $i done
which of course opens separate screen sessions for each invocation of
btdowloadcurses file. The solution he shared with me was to generate your
.screenrc programatically before invoking screen with something like this:
#!/bin/sh conf=/tmp/screen-$PPID.rc touch $conf echo source /.screenrc >> $conf n=0 for i in *.torrent; do echo screen $n btdownloadcurses $i >> $conf let n++ done screen -c $conf rm $conf
which seems like a workable solution to me. Thanks to Samuel and the screen-users mailing list for the tip.