6

I want to take screenshots simultaneously from multiple X servers on one desktop PC.

I have multiple users logged in different terminals (tty1, tty2, tty3, tty4) who start multiple Xservers with startx /usr/bin/openbox-session -- :1 (and :2, :3, :4 respectively). So I can access each one of them with Ctrl+Alt+F8, +F9, +F10, +F11.

There is only one monitor on that desktop.

I want to take screenshots for each of these X servers, preferably with scrot, but I currently get a black/blank image whenever I try it. Only when I am active on that X server I get a proper screenshot.

For example, if I am on Ctrl+Alt+F8 and run scrot test.png I get a proper screenshot; if I understand correctly I do not have to set the $DISPLAY, since being on Ctrl+Alt+F8 I get echo $DISPLAY > :1. But if I run sleep 10; scrot test.png and go to Ctrl+Alt+F7, then I get a black image.

How can I get multiple screenshots from each one of those terminals simultaneously?

What worked for me was Xephyr. The only problem with this solution seems to be that when I run extremely fast xdotool commands it is not as responsive as X.

For future reference, what I did for every of the four users and terminals was:

In ~/.profile, I set each user to auto-login after my system boot, like:

if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then
     sleep 30 # for some reason it crashes if I do not let 
              # it sleep for a while, not necessarily so long. 
              # I guess it has to do with my "normal" X at DISPLAY=:0 . 
              # Thus for tty2 I let it sleep 40 seconds, 
              # for tty3 50 seconds and so on.
     startx
fi

In ~/.Xsession, I start an Xserver/client (with blackbox) and Xephyr (with openbox) in it like:

Xephyr -fullscreen -screen 1920x1200 :11 &
exec blackbox & 
sleep 3 # Perhaps sleeping is redundant.
DISPLAY=:11 /usr/bin/openbox-session

I want the "final" window manager do be openbox-session. I would like to use openbox for both the Xserver and Xephyr, but exec openbox & DISPLAY=:11 /usr/bin/openbox-session crashes, while exec openbox & DISPLAY=:11 /usr/bin/openbox does not.

This way, the user in :11 can take screenshot, while the monitor shows :0. (or :13, :14, etc.).

I did not try XVnc, but I have the feeling that it might be slower than Xephyr; please correct me if I am wrong.

Konstantinos
  • 1,075
  • 8
  • 13
  • The `$DISPLAY` variable needs to change for `scrot`. This will not happen if it remains in the subshell launched from the Xserver you just switched from. – mikeserv Aug 21 '14 at 01:36
  • each one of those VTs is a separate `X` server. If you are on one of them and switch to another you're looking at a different `X` server - a different `$DISPLAY`. So when you run a delayed `scrot` with one `$DISPLAY` and switch to a different one before it executes its `$DISPLAY` goes dark. It would have worked without `Xephyr` at all - and, in truth, layering the servers that way only complicates the issue further, though it can be made to work. – mikeserv Aug 22 '14 at 00:01
  • @mikeserv I appreciate very much your support and it seems I misunderstand something very basic. How could it work without `Xephyr`? When on the VT of `Ctrl+Alt+F8` I run `sleep 3; DISPLAY=$(echo $DISPLAY) scrot test.png` (which is the same as `sleep 3; DISPLAY=:1 scrot test.png` and within 3 seconds I switch to `Ctrl+Alt+F7` (where `$DISPLAY` is `:0`) I get a blank `test.png`. – Konstantinos Aug 22 '14 at 07:38
  • This is the reason: the `scrot` process is a child of VT8 - its `$DISPLAY` is always `:1` - even after you switch. That is the value `export`ed into its environment by its parent shell - which you *leave behind* when you switch to VT7. Think about it this way - if there were no Xservers running at all and only the console - at boot you'd get a login prompt then a shell. If you switch to another you'll get *another* login prompt and *another* shell. Different VTs, different shells. Different VTs, different `$DISPLAY`s `scrot` gets *left behind*. Do `DISPLAY=:0 scrot test.png`. – mikeserv Aug 22 '14 at 07:47
  • When I am at VT8 and run `sleep 3; DISPLAY=:0 scrot test.png` and switch within 3 seconds to VT7, I get the screenshot of VT7. Is this what you mean? I want to work on VT7, and get the screenshot of VT8. Is this possible without `Xephyr`? – Konstantinos Aug 22 '14 at 07:51
  • Yeah. So if there is *someone* currently looking at an `X` display that is viewable by you just by switching to it - say on VT1 as `$DISPLAY = :1` - and you are on VT8 and your `$DISPLAY = :8` then doing `DISPLAY=:1 scrot screen.shot` should grab an image of whatever that *someone* is doing on VT1. See? – mikeserv Aug 22 '14 at 08:17

2 Answers2

6

Method #1 - Using xwd

You could just use the command line tool xwd to grab the X displays like so:

$ xwd -display :1 -root -out 1.xwd

You could loop through 1 to 4 like so:

$ for i in {1..4};do xwd -display :$i -root $i.xwd; done

NOTE: The resulting .xwd files are a special type of X Windows dump file.

$ file 1.xwd 
1.xwd: XWD X Window Dump image data, "xwdump", 4160x1440x24

You can use xwud to display them like so:

$ xwud -in 1.xwd

Or you can use ImageMagick's display command to view them:

$ display 1.xwd

Method #2 - Using import

You can also use ImagMagick's import command to do something similar:

$ import -window root -display :0.0 -screen /tmp/0.png

Method #3 - using scrot

Or as was suggested by @mikeserv in the comments, try setting the $DISPLAY so that scrot can find the active X display correctly:

$ DISPLAY=:1 scrot 1.png

This could be looped like so:

$ for i in {1..4};do DISPLAY=:$i scrot $i.png; done

References

slm
  • 363,520
  • 117
  • 767
  • 871
  • 1
    @mikeserv - I was able to view the resulting xwd dump file using `display` out of ImageMagick. I don't even have access to that tool, `xwud` on F20. Querying the YUM repos to see if it's buried somewhere else 8-) – slm Aug 21 '14 at 14:59
  • @mikeserv - found it, it's buried in this pkg: xorg-x11-apps-0:7.7-7.fc20.x86_64. – slm Aug 21 '14 at 15:02
  • @mikeserv - yeah they do, my mistake. I ran that on F19 last night, and now I'm on F20 and didn't have that pkg installed...yet 8-). Updated the A with your info as well, thanks! – slm Aug 21 '14 at 15:07
  • I may be missing something, but I understood the question as that the OP did try a solution like these, and got a black screen only - so I would expect that these methods do not work too? It the OP just did not set DISPLAY, he would get an error, not a black image, I think. – Volker Siegel Aug 21 '14 at 15:25
  • @VolkerSiegel - he didn't explicitly say that he did set `$DISPLAY`, also with these methods he does not need to set `$DISPLAY` since these commands take the display arg. directly. Also I 1/2 suspect that he might need to `export $DISPLAY`, so that `scrot` can pick it up. These will just sit here until he confirms all this for us. – slm Aug 21 '14 at 15:29
  • But if the display is not set, he would get an error - I just tried: `$ DISPLAY= scrot out.png` gives me `giblib error: Can't open X display. It *is* running, yeah?`. And he is aware of multiple displays, the point question makes not much sense it he would not try to address multiple displays for screenshots. – Volker Siegel Aug 21 '14 at 15:35
  • It's not that `$DISPLAY=` it's that it's likely set to `$DISPLAY=:1` in one scenario and something else entirely in the other. Without his info we're just conjecturing, just be patient and wait until he comes back to expand his Q. – slm Aug 21 '14 at 15:38
  • @VolkerSiegel - no the asker provides the command : `sleep 10; scrot test.png`. That is run from a shell opened on /dev/tty7. There is no error because `$DISPLAY` *is* set - to `:7` - or whatever that `X` server is. In the ten seconds between calling `sleep` and switching to VT8, that X server went inactive - black screen. That is why I downvoted your answer - for which I'm sorry - but it further complicated the issue without correctly answering the question. This answer, however, was correct and had one fewer votes than yours. I wanted the correct info at top, so I voted on both. – mikeserv Aug 21 '14 at 19:37
  • Guys you are magnificent. I do not believe setting `$DISPLAY` works, but on the other hand I might be missing something. Perhaps the problem is indeed that "X server is not painting the image into some image buffer". My perception is that setting `$DISPLAY` helps in taking the screenshot when X is active on the same `$DISPLAY`, but I want to take a screenshot when it is not. The `solution` I was seeking was "like" having "virtual machines/desktops", but running on the same system, of course. – Konstantinos Aug 21 '14 at 20:52
3

I understand the problem in the question as follows:

  • You are on a text console tty,
    so there is no X running on the tty where you are running the screenshot command.

  • You can run command line screenshot commands for the X displays.

  • You have specified the X displays for the screenshot commands, like in
    DISPLAY=:2 scrot out.png.

  • The screen shot command does not give you an error


But you get a black image as output.


The problem could be that the X server is not painting the image into some image buffer, and the screenshot is taken from that empty buffer. But it could also be that it's a compositing window manager, like compiz, that is not painting. At least if you capture single windows, that could be the problem. I think it's worth trying to use a not compositing window manager, like metacity.

If that does not solve it, there is a completely different approach:

Run all your X servers as nested X servers on one display. Each nested X server is showing it's screen output in a window. You can then either make full screen screenshots of the nested display, or window screenshots on the main display.

As implementation of a nested X server, Xephyr seems to be the most current. There are also the older Xnest and Xvfb:

From man Xephyr:

 NAME
        Xephyr - X server outputting to a window on a pre-existing X display

 DESCRIPTION
        Xephyr  is a kdrive server that outputs to a window on a pre-existing "host" X dis‐
        play.  Think Xnest but with support for modern extensions  like  composite,  damage
        and randr.

        Unlike  Xnest  which is an X proxy, i.e.  limited to the capabilities of the host X
        server, Xephyr is a real X server which uses the host X server  window  as  "frame‐
        buffer" via fast SHM XImages.

In a similar way, Xvnc (from package vnc4server) could be used, providing access by VNC protocol additionally:

From Xvnc4:

 NAME
        Xvnc - the X VNC server

 DESCRIPTION
        Xvnc  is the X VNC (Virtual Network Computing) server.  It is based on a standard X
        server, but it has a "virtual" screen rather than a physical one.   X  applications
        display  themselves  on  it  as if it were a normal X display, but they can only be
        accessed via a VNC viewer - see vncviewer(1).

        So Xvnc is really two servers in one. To the applications it is an X server, and to
        the  remote  VNC  users it is a VNC server. By convention we have arranged that the
        VNC server display number will be the same as the X server  display  number,  which
        means  you  can  use eg. snoopy:2 to refer to display 2 on machine "snoopy" in both
        the X world and the VNC world.

(Xvnc is available as package vnc4server in Ubuntu)

Volker Siegel
  • 16,983
  • 5
  • 52
  • 79
  • the asker has specifically *not* set the `$DISPLAY` variable to other than the current VT. - see? *if I understand correctly I do not have to set the $DISPLAY, since being on Ctrl+Alt+F8 I get echo $DISPLAY > :1. But if I run sleep 10; scrot test.png and go to Ctrl+Alt+F7, then I get a black image.* – mikeserv Aug 21 '14 at 23:57