user118464 user118464 - 1 year ago 81
Bash Question

How to check progress of a screen session without reattaching into the session?

I'm running screen sessions on Unix. After opening and running a few screen sessions, I'd like to check progress of each screen session to see if any session completes running.

In command line, if I type:

$screen -ls

I could see a list of detached screen sessions, e.g.

There are screens on:
4683.pts-0.xxxx (Detached)
4869.pts-0.xxxx (Detached)
4848.pts-0.xxxx (Detached)
4890.pts-0.xxxx (Detached)
4 Sockets in /var/run/screen/S-xyzxyz.

If I want to check if any of the 4 sessions finishes running, I could reattach one session to check progress:

$screen -r 4683.pts-0.xxxx

Then I could see if this session finishes running.

However, is there any way that I could check the progress of all the screen sessions without reattaching to each session?

Thanks a lot!

Answer Source

(Since you've tagged the question with "tmux", I'm going to assume that you're okay with an answer that uses Tmux instead of Screen.)

Tmux has a concept of activity monitoring: if a change happens in a window, user will be notified. "Activity" is any visual change to the window, be it something printed out or just program finishing (and returning to shell, who in turn will print out its prompt and thus trigger activity monitor.) If your processes already behave like that, you can skip step 2 in the list below, and also simplify step 4.

If you have processes that output a lot of stuff and you don't want to redirect that output into a file, you'll have to resort to silence monitoring. In that mode, Tmux will watch for windows where no output happened within last N seconds. I advise against this approach as it requires more work than activity monitoring.

So here's what you can do:

  1. Enable activity monitoring for all windows by putting the following into .tmux.conf:

    set-window-option -g monitor-activity on

    That should cover most of usecases.

  2. If you want to monitor for inactivity, you'll have to set monitor-silence for each window. You can set it globally, but I don't think you'll be lucky enough to have one timeout that will fit everything; thus, here I present a command that should be run in each window separately (by pressing prefix, which is Ctrl-a by default, and then typing it):

    set-window-option monitor-silence N

    N here is number of seconds after which Tmux should consider the window silent.

  3. Now you can start all your processes and detach from sessions.

    Note: activity and silence monitoring only notifies you of windows you don't look at; so you should detach from all sessions if you want the report we'll generate in the next step to be complete.

  4. Finally, you can run the following to find out which sessions have activity or silence notifications:

    tmux list-windows -a \
        -F "#{window_activity_flag}#{window_silence_flag} #S:#W" \
    | egrep '^(10|01)'

    What's going on here?

    1. tmux list-windows lists windows, obviously;
    2. -a means "list all windows of all sessions";
    3. -F specifies the output format. Here we're outputting two flags (which can be either 0 or 1) followed by a space and then session and window names delimited by colon;
    4. finally, we grep for lines where either window_activity_flag or window_silence_flag is 1, i.e. for windows for which Tmux generated activity or silence reports. (You can also set up both activity and silence monitors and then grep for 11 combination, but that makes the setup even more fragile, so I'm leaving that as an excercise for the reader :)
    5. The backslashes are just for formatting—they're escaping the newlines. You can omit them and use all that code as oneliner.

    The output looks like this:

    10 project:vim
    10 project:zsh
    10 rfcs:WebDAV
    10 rfcs:WebDAV requirements
    10 rfcs:Versioning WebDAV
    01 test:zsh

    The first five windows have activity notification, the last one has silence notification.