Taking screenshots of QEMU guests

In order to take a screenshot from QEMU (which they call a screendump), you can:

  1. Use qm monitor 121:

      $ sudo qm monitor 121
      Entering Qemu Monitor for VM 121 - type 'help' for help
      qm> screendump /tmp/screendump.ppm
      qm> quit
    
    
      $ ls -lsh /tmp/screendump.ppm 
      2.3M -rw-r----- 1 blog_jay_sh blog_jay_sh 2.3M Mar  6 21:26 /tmp/screendump.ppm
    

    This works perfectly if you only want to do it once. However, scripting this is not easy simply because it refuses to read from standard input like other sane utilities. Instead, we can try the second option.

  2. Use QMP and socat:

    You will find many resources that tell you that you should be able to execute a screendump command (as JSON) and write that to the QMP socket via socat. However, this won't work unless you specifically execute qmp_capabilities first (in the same session), which is easily overlooked when these parts of the documentation are disjoined. (and the error message you would get does not give any indication that you must do this first). This works perfectly:

    $ (
        echo '
            {
                "execute": "qmp_capabilities"
            }
        ';
        echo '
            {
                "execute": "screendump",
                "arguments": {
                    "filename": "/tmp/screendump.ppm"
                }
            }
        '
    ) | sudo socat - /var/run/qemu-server/121.qmp
    

    Which should return something like:

    {"QMP": {"version": {"qemu": {"micro": 2, "minor": 1, "major": 2}, "package": ""}, "capabilities": []}}
    {"return": {}}
    {"return": {}}
    

    The two {"return": {}}s indicate that the screenshots were taken successfully (i.e. both commands executed without error). If, for example, you were to omit the qmp_capabilities command, this is what you would get:

    {"QMP": {"version": {"qemu": {"micro": 2, "minor": 1, "major": 2}, "package": ""}, "capabilities": []}}
    {"error": {"class": "CommandNotFound", "desc": "The command screendump has not been found"}}
    

    Which is not at all helpful for figuring out what the underlying problem is.