Usage Guide¶
PySnap exposes a single command line entry point named pysnap.
Help¶
Running the command without arguments, or with --help, lists the commands
in groups with a one-line summary each. Every command has its own help with a
description, its arguments and options, and examples:
pysnap --help
pysnap clone --help
pysnap report --help
pysnap report check --help
Open Bundled Documentation¶
The docs command opens the compiled HTML documentation that is bundled
inside the installed PySnap package.
By default, PySnap tries to launch firefox. When it is not available, pass
an explicit browser executable through --browser.
pysnap docs
pysnap docs --browser /usr/bin/chromium
List Virtual Machines¶
The list command prints all detected VirtualBox groups and the names of the
virtual machines inside each group.
When the VirtualBox data directories are missing or the VBoxManage service
does not respond, for example right after pysnap full-clean, the list
command prints No virtual machines found. and exits cleanly. PySnap runs
the underlying VBoxManage list calls with a bounded timeout, so a stale
VBoxSVC process cannot block the listing forever.
pysnap list
Run an Integration Test¶
PySnap can run a real end-to-end VirtualBox integration scenario directly from the command line:
pysnap --integration-test image.ova
The integration scenario:
imports the appliance as a temporary base VM
creates three linked clones
connects clone A and B with
intnetconnects clone B and C with
deepnetconnects clone C and A with
virtnetattaches a serial terminal probe to clone A
starts clone B in headless mode without attaching to it
captures
monitoroutput and verifies that clone A isWorkingwhile clone B isActiveprints details for the base VM and all three clones
removes the four VMs one by one
Register Proto Settings for a Base VM¶
The protosettings command registers one base VM in the persistent
proto-settings list stored at Path.home() / ".ptotosettings". The file
contains one VM name per line and is used as a set without duplicates.
This option exists for the image conventions used in the educational program of CMC MSU. When a base VM is present in the proto-settings list, every linked clone created from it receives additional DMI values:
DmiSystemVendor = <CloneVM>DmiSystemSKU = port<Port>[.<net1-name>[.<net2-name>[.<net3-name>]]]
This behavior is relevant for the following CMC MSU courses:
pysnap protosettings BaseVM
Registered base VMs and their clones are also known to have their console on
COM1, so PySnap reaches them through the serial console; every other VM is
reached through ssh (see Access to the Guest).
Access to the Guest¶
PySnap reaches the guest of a VM in one of two ways:
COM1 serial console for base VMs registered with
pysnap protosettingsand their clones:UART1is a TCP server on the hostssh for every other VM: a rule named
pysnap-sshon the NAT adapter forwards a host port on127.0.0.1to port 22 of the guest
The choice can be overridden per VM with pysnap set VM access=com|ssh and
returned to the automatic choice with access=auto. Clones inherit an
explicit choice of their base VM. ssh connections use the guest user root
unless pysnap set VM ssh-user=NAME names another one; clones inherit it.
pysnap show prints the access of a VM and pysnap monitor shows
ssh:PORT instead of the serial port for ssh VMs.
pysnap show first
...
Access: ssh root@127.0.0.1:2400 (default)
pysnap set first access=com
pysnap set first access=auto ssh-user=student
Install the ssh Key¶
ssh connections of PySnap use only key login. PySnap keeps its own key pair in
~/.pysnap/ssh (pysnap_vm_access_ed25519, created once without a
passphrase) and one known_hosts file per VM in
~/.pysnap/ssh/known_hosts.d/<VM UUID>: the first host key of a VM is
accepted, a different key later is refused. ~/.ssh is never read or
changed, and existing files are never overwritten. PySnap runs the system
OpenSSH client ssh, which is part of Linux distributions, macOS and
Windows 10 and newer.
pysnap ssh-key installs the key in a running guest:
pysnap ssh-key first --user student
student@127.0.0.1's password:
PySnap: the key is installed for student.
PySnap: enter the root password to install the key for root too (press Enter to skip).
Password:
PySnap: the key is installed for root.
PySnap key works for: student, root
ssh logs in with the password of the given user (by default the ssh user of the VM) in the current terminal and adds the key for that user
then the guest asks for the root password through
su; with it the key is added for root as well, an empty or wrong password skips rootmany systems refuse a root password over ssh, so the login usually uses an ordinary user with
--userwhen the ssh user of the VM cannot use the key afterwards but the login user can, the ssh user of the VM is switched to the login user
with
--consolethe command that adds the key is typed on the VM screen through VirtualBox keyboard input instead, for a shell that is already logged in there; the guest needs a Latin keyboard layout
Import an Appliance¶
Import either an .ova or .ovf appliance.
If the appliance already defines a group, PySnap keeps it. Otherwise, the
virtual machine is placed into the /Others group.
When the appliance contains exactly one VM, an optional VMName argument can
override the imported VM name.
Before running VBoxManage import, PySnap checks the final VM name. If the
name already exists, the import is aborted before creating anything. For the
default one-VM case, PySnap recommends using the optional VMName argument
to choose a different target name.
During the import, PySnap renders a live progress bar based on the percentage
output reported by VBoxManage import.
pysnap import image.ova
pysnap import image.ovf
pysnap import image.ova RenamedVM
Show Virtual Machine Details¶
The show command prints the VM name, the assigned group, and the serial TCP
port configured through UART1.
pysnap show MyVM
Plug a Virtual Machine for PySnap Connections¶
The plug command prepares an existing VM for pysnap connect. For a VM
reached through ssh it adds the pysnap-ssh forwarding rule on the first NAT
adapter with a free host port; this works on stopped, running and paused VMs,
and a VM without a NAT adapter is refused with a hint to run
pysnap set VM nic1=nat. For a VM reached through the COM1 console it
configures UART1 as a tcpserver endpoint when this can be done safely.
For the COM1 console PySnap checks these conditions:
the VM exists
if
UART1is already configured astcpserver,<port>, the VM is left unchangedif
UART1is already bound to another backend, PySnap refuses to overwrite itif a reconfiguration is needed, the VM must be in a stopped state
the selected TCP port must be free in both VirtualBox and the host OS
When all checks pass, PySnap assigns the same kind of serial TCP port used by
the imported protocols-* images, so the VM becomes connectable through the
built-in terminal interface.
pysnap plug MyVM
pysnap connect MyVM
Graphviz example diagrams are rendered automatically when the dot
executable is available on the documentation build host.
Set Serial Ports and Network Adapters¶
The set command shows or changes the serial (COM) ports and the network
adapters of a VM. Each option is KEY=VALUE; N is any number the VM
offers: VirtualBox has COM1-COM4 and, depending on the chipset of the
VM, NIC1-NIC8 (PIIX3) or NIC1-NIC36 (ICH9). The output lists
NIC1-NIC4 and further adapters up to the last one in use.
comN=auto: a TCP server on a free port (an existing TCP server keeps its port);comN=PORTuses the given portcomN=server:NAMEandcomN=client:NAME: a host pipe between two VMs, created by the VM withserverand joined by the VM withclientcomN=off: no serial portnicN=NETWORK: the internal networkNETWORKnicN=nat: NAT;nicN=off: no network adapteraccess=com|ssh|autoandssh-user=NAME: how PySnap reaches the guest (see Access to the Guest); these two work on a VM in any state
pysnap set first nic2=left nic3=right com2=server:link
pysnap set second nic2=left com2=client:link
pysnap set first
first (poweroff)
COM1 TCP server, port 2326
COM2 pipe server, creates "link" (/tmp/pysnap-link)
COM3 off
COM4 off
NIC1 NAT
NIC2 internal network "left"
NIC3 internal network "right"
NIC4 off
Without options the current settings are printed. Changes require a stopped
VM; all options are checked first and then applied together, so an invalid
option changes nothing. PySnap checks that a TCP port is not used by another
VM, by another COM port of the same VM or on the host. Removing a TCP server
prints a warning; pysnap connect uses COM1 and cannot reach a VM
without it.
A pipe name is short; PySnap turns it into the path format of the host
(\\.\pipe\pysnap-NAME on Windows, a pysnap-NAME socket in the
temporary directory elsewhere), so the same name connects two VMs on any
platform.
For clones of proto-settings base VMs, the DMI system SKU is rebuilt from the
new COM1 port and the internal networks of NIC2-NIC4, for example
port2326.left.right. An adapter without an internal network leaves an
empty place (port2326..right). When COM1 is no TCP server, the
highest TCP port of the other COM ports is used; without any TCP port the
port part of the previous SKU is kept.
Connect to a Headless Virtual Machine¶
The connect command ensures that the selected VM is running in headless
mode and then attaches a built-in PySnap terminal interface to the guest: to
its UART1 TCP console, or to an ssh login shell for VMs reached through
ssh (see Access to the Guest).
For VMs that do not already expose a suitable UART1 tcpserver endpoint or
a forwarded ssh port, run pysnap plug <VM> first.
Over ssh, connect logs in with the PySnap key as the ssh user of the VM:
while the guest is still booting and no ssh server answers yet, PySnap waits up to three minutes and says so once;
Ctrl-Cstops waitingwhen the guest refuses the key, PySnap installs it right away in the same way as
pysnap ssh-key(password of the user, then optionally of root) and then logs in with the keythe status line shows
ssh:PORTinstead ofUART1:PORT, no waking newline is sent because the login shell prints its own prompt, and the session ends when the login shell exits (exitorCtrl-D)a paused VM is refused with a hint to run
pysnap resume, because a paused guest cannot answer the loginone
connectsession per VM is allowed, as on the serial console
All keys go to the guest, so editors and shells get Esc, Ctrl-L,
Ctrl-Q, Alt combinations and function keys as in a regular terminal.
PySnap commands start with Ctrl-], which guest programs hardly use, as in
telnet; the status line then lists the command keys:
qdetaches the session; detaching does not stop the virtual machineUpandDownscroll the local scrollback buffer by one line,PgUpandPgDnby one screen,Homejumps to the oldest retained output andEndback to the live output; the command keys stay active for further scrollingvpastes the text of the host clipboard (see below)Ctrl-]sendsCtrl-]itself to the guestEscor any other key leaves the command keys without sending anythingon Linux, the mouse wheel or touchpad scroll gesture moves the local scrollback buffer by three lines while the command keys are active
Outside the command keys the mouse belongs to your terminal: select, copy
and paste text the way your terminal does it for every program, for example
by dragging and Ctrl-Shift-C/Ctrl-Shift-V or the middle button on
Linux, Ctrl-C/Ctrl-V or the right button in Windows Terminal, the
right button in the Windows console and Cmd-C/Cmd-V on macOS. Text
in the local scrollback can be selected after scrolling to it with the
command keys. Ctrl-C always goes to the guest as an interrupt.
A pasted text reaches the guest the way a terminal sends it: line breaks of
any system become the Enter key (CR), so a text copied on Windows gives no
empty lines, and when the guest asked for bracketed paste, as bash and vim
do, the text is marked as a paste; bash then waits for Enter instead of
running each pasted line, and vim does not indent it again. Ctrl-] v
pastes the host clipboard in the same way for terminals without a paste key,
for example the Windows console without its Ctrl key shortcuts, where
Ctrl-V reaches the guest as ^V. The clipboard is read only then: on
Windows through the system API, on macOS with pbpaste, elsewhere with
wl-paste (Wayland), xclip or xsel; the status line tells when none
is installed. Over the serial console a long paste can lose characters, because
the console has no flow control.
Full-screen programs such as vim, nano and less use the alternate screen: while they run, the local scrollback is off, and they scroll with their own keys; when they exit, the shell screen comes back as it was, and their screens never enter the scrollback.
While the session is attached, PySnap continuously tracks the outer terminal size and resizes the visible guest text area to match it. This also works after reconnecting to an already running VM.
For xterm-compatible guest-side tools, PySnap replies to standard size queries
such as CSI 18 t and cursor-position reports such as CSI 6 n. On Linux
guests this makes terminal-size refresh workflows such as resize much more
practical over the raw serial console.
On macOS, PySnap also checks the standard VirtualBox application-bundle path
for VBoxManage when the command is not exported in PATH.
pysnap connect MyVM
A paused VM can be attached through UART1 too: the status line shows
Paused, keys are held back and nothing is sent to the guest until
pysnap resume; the Ctrl-] commands keep working. Then the keys work
again, and when the guest has not printed anything yet PySnap sends the usual
waking newline. When a VM is paused during a session, the session stays open
in the same way, so Ctrl-] q on a paused VM and a new
connect lead to the same state. If the paused VM does not accept the
serial connection within three seconds, connect fails with a hint to run
pysnap resume.
Monitor Active Virtual Machines¶
The monitor command prints compact runtime records in the form
<VM> (state: <State> ; <serial port> ; <group>).
PySnap currently uses these runtime labels:
Workingwhen the VM is running and PySnap has an active attached sessionActivewhen the VM is running in headless mode without an attached sessionStoppingwhen the VM is shutting down gracefullyChangingwhen the VM is starting or otherwise transitioningPausedwhen VirtualBox reports a paused machineErrorwhen VirtualBox reports an error-like runtime state
pysnap monitor
srv (state: Working ; 2345 ; /Lab)
db (state: Active ; 2346 ; /Lab)
router (state: Stopping ; 2347 ; /Net)
Stop Running Virtual Machines¶
PySnap stops headless virtual machines through VBoxManage controlvm
<VM> acpipowerbutton only. No automatic fallback to savestate or other
shutdown modes is used.
When a VM stops, any active pysnap connect session attached to it finishes
automatically because the VM state changes and the serial connection is closed.
A paused guest cannot handle the ACPI power button, so stop resumes a
paused VM first; stop --all also stops paused VMs.
pysnap stop MyVM
pysnap stop --all
Pause and Resume Virtual Machines¶
pause freezes a running VM through VBoxManage controlvm <VM> pause; it
stays in memory and shows up as Paused in pysnap monitor. resume
continues it. With --all the commands act on every running or every paused
VM. This is not savestate: nothing is written to disk and the VM does not
stop.
pysnap pause MyVM
pysnap resume MyVM
pysnap pause --all
pysnap resume --all
Create a Linked Clone¶
The clone command creates a linked clone from a base VM. The clone inherits
the base VM group.
When -p is provided, its value is used as the host TCP port for
modifyvm <VM> --uart1 0x3F8 4 --uartmode1 tcpserver <port>.
When -p is omitted, PySnap scans existing VMs, finds the maximum already
used serial TCP port, and assigns the next value. If no serial TCP ports are
configured yet, the automatic sequence starts at 1024.
Up to three extra positional arguments configure internal networks:
nic1stays innatmode, the requested networks are mapped ontonic2throughnic4, and omitted adapters are left enabled. This layout is used for clones of proto-settings base VMs and for every clone reached through ssh, whose ssh port is forwarded onnic1only a clone of a base VM set to
access=comwithout protosettings keeps the legacy layout: networks are mapped sequentially ontonic1throughnic3, and omitted adapters are set tonone
A clone copies the settings of its base VM, including its pysnap-ssh rule;
PySnap removes that copy, because its host port belongs to the base VM, and a
clone reached through ssh gets its own free port.
If the base VM was previously registered through pysnap protosettings,
PySnap also applies educational DMI settings to the clone.
pysnap clone BaseVM CloneVM -p 2345 intnet1 intnet2 intnet3
pysnap clone BaseVM CloneVM intnet1
Erase Virtual Machines¶
PySnap supports three erase modes:
pysnap erase VMremoves a single VM when no dependent linked clones exist.pysnap erase --group GROUPremoves all VMs inside one group.pysnap erase --allremoves all registered VirtualBox VMs.
The single-VM erase mode refuses deletion when dependent clones still exist. The group erase mode refuses deletion when descendants outside the target group still depend on the selected VMs.
Every erase mode accepts the --clones-only flag, which restricts the
operation to VMs created as PySnap linked clones:
pysnap erase --all --clones-onlyremoves every linked clone and keeps the imported base VMs registered.pysnap erase --group GROUP --clones-onlyremoves only the linked clones inside one group. The operation is refused when clones outside the group still depend on the selected clones.pysnap erase VM --clones-onlybehaves like the normal single-VM erase for a clone. For a base VM, PySnap prints a warning and refuses the deletion, so the flag stays safe in scripted cleanups.
PySnap recognizes clones through the pysnap/kind and pysnap/parent
metadata written into VirtualBox extra data during cloning, so the clone list
stays correct without a separate registry file.
When a VM is removed successfully, PySnap also removes its name from the proto-settings file if it was registered there.
pysnap erase BaseVM
pysnap erase --group /Lab
pysnap erase --all
pysnap erase --all --clones-only
pysnap erase --group /Lab --clones-only
pysnap erase CloneVM --clones-only
Remove All VirtualBox Data¶
The full-clean command permanently deletes the VirtualBox machine folder
and the VirtualBox configuration directory from the host file system. Stop
VirtualBox and all virtual machines before running it.
Without --path, PySnap removes ~/VirtualBox VMs together with the
OS-specific configuration directory:
~/.config/VirtualBoxon Linux and other Unix systems~/Library/VirtualBoxon macOS~/.VirtualBoxon Windowsthe directory from
VBOX_USER_HOMEwhen the variable is set
The repeated --path option replaces the default selection with explicit
directories. This covers custom machine-folder locations configured through
VBoxManage setproperty machinefolder.
The command prints the target directories, marks missing ones, and asks for two
different explicit confirmations: yes on the first prompt and delete on
the second one. Any other answer cancels the cleanup without touching the file
system. Directories are removed recursively through shutil.rmtree, so the
same behavior applies on every supported operating system.
pysnap full-clean
pysnap full-clean --path /data/vms --path /data/vbox-config
Read Session Reports¶
Students record their work inside the educational VMs with the report
utility, which produces a report.<NN>.<host> archive. The
pysnap report command reads such archives safely: nothing is extracted to
disk and nothing from the report is sent to the terminal as a raw control
sequence.
The text subcommand prints the text of the session without timing, as the
student saw it. The prompt installed by report is highlighted and the
entered commands are shown in bold; colors produced inside the VM are kept.
Colors are used only when the output is a terminal; --color always or
--color never overrides the detection, and the NO_COLOR environment
variable disables colors.
The --commands option prints only the numbered list of entered commands
with the time since the start of the recording. Commands typed at the prompt
of another program, for example inside vtysh, are marked with that
prompt. Line editing, history recall and interrupted commands are resolved,
so the list shows what was actually executed.
Problems found in the report, such as a truncated recording, are printed as warnings to the error stream; the available text is still shown.
When the output is a terminal and the text is longer than the screen, text
opens a pager. Like less -S, the pager keeps the recorded line layout:
lines longer than the window are cut at its edge, and > or < in the
edge column marks text hidden to the right or left.
Up/Downork/jscroll by a linePageUp/PageDown,bandSpacescroll by a pageg/HomeandG/Endjump to the start or endLeft/Rightshift the view by half the window widththe mouse wheel scrolls on Linux
qorCtrl-Qquits
--no-pager prints the text directly.
pysnap report text report.01.first
pysnap report text report.01.first --commands
1 00:17.05 ip a show eth1
2 00:29.86 ping -c5 10.9.0.2
pysnap report text report.01.first --color never > report.01.first.txt
pysnap report text report.01.first --no-pager
The show subcommand replays the session with its timing in a safe
terminal view of the recorded size. Pauses longer than --max-delay
seconds (1 by default, 0 keeps the real pauses) are shortened, like
scriptreplay -m, and --speed selects the initial speed. When the
window is smaller than the recorded screen, the view is clipped around the
cursor and the status line reports the recorded size.
Spacepauses and resumes playback; resuming at the end starts over+and-change the speed between x0.25 and x16nandpjump to the start of the next or previous commandHomeandEndjump to the start or the end of the recordingwhile paused,
Alt-Up/Alt-Downand the mouse wheel on Linux scroll the screen historyqorCtrl-Qquits
Characters that would be invisible, such as zero-width spaces or
bidirectional overrides, are shown as ? in text and show.
pysnap report show report.01.first
pysnap report show report.01.first --speed 4 --max-delay 0.5
The check subcommand prints a report information block. Without a check
file it shows only this block:
Identity: task and host from the
report.<NN>.<host>file name and from the prompts recorded byreport; a warning is printed when they differ or when the prompts show several hostsTiming: start, end, duration and the exit code of the recorded shell
Environment: terminal device, type and size, CPU model and hypervisor from
CPU.txtCommands: the number of commands and unique commands, commands interrupted with
Ctrl-C, recalled from history (Up,Down,Ctrl-R) or typed at the prompt of another program, and the pause before each command, measured from the last output to the first keyTyping: keys per second from the first key of a command to
Enter, the share ofBackspacekeys and input chunks that look pasted (five or more printable characters at once, or a bracketed-paste marker)Addresses in output: IPv4 and MAC addresses shown by the commands, without the broadcast and all-zero MAC addresses
Integrity: problems found while reading the report and a comparison of the archive member times with the recording start (
CPU.txt) and end (the other members) within two seconds
pysnap report check report.01.first
pysnap report check report.01.first lab02-first.check.toml
Check Files¶
With a check file, check also checks the expected commands and output
blocks and grades the report. A check file is written in TOML, usually with
the .check.toml extension, one file per host of a lab:
[report] # optional expectations, reported as warnings
task = 1
host = "first"
[[command]]
id = "addr" # optional name used by "of" and "after"
cmd = "ip a show <ETH-A>"
[[command]]
id = "ping"
cmd = "ping -c5 <IP-B>"
[[output]]
of = "addr" # search only in the output of that command
text = '''
<*>: <ETH-A>: <*>UP<*>
...
inet <IP-A>/<MASK> scope global <ETH-A>
'''
[[output]]
of = "ping"
min_count = 5 # the block must occur at least five times
text = "64 bytes from <IP-B>: icmp_seq=<*> ttl=64 time=<*>"
[grading]
total = 10
scale = [[90, "5"], [75, "4"], [50, "3"], [0, "2"]]
[[command]] items are compared with the entered commands as a whole.
Keys:
cmd(required): the command patternid: a name forofandafterreferencesafter: the id of an earlier command; the item passes only when its command was entered after that command. If that command did not pass, this item fails too.points: the weight of the item, 1 by default
[[output]] items are blocks of output lines. Keys:
text(required): the block; a line holding only...matches any number of lines, otherwise the lines must follow each otherof: the id of a command; the block is searched only in the output of the runs of that command, otherwise in the whole reportorder = "any": the lines may appear in any order, which suits tables such asip route;...is not allowed thenmin_count: how many times the block must occur, 1 by default, for example for ping repliespoints: the weight of the item, 1 by default
Patterns may contain placeholders:
<IP>,<ETH>and<MASK>match any IPv4 address,ethNinterface or prefix length from 0 to 32a label such as
<IP-A>,<ETH-A>or<MASK-A>remembers the first matched value; every later use of the same label, in commands and in output blocks, must show the same valueany other name, such as
<X>, matches one word and also remembers it<*>matches any text inside a line and remembers nothing; use it for values that change, such as ping times or sequence numbers\<writes a literal<; text like< /dev/ttyS1needs no escaping
Spaces never matter: both the report lines and the patterns are trimmed and every run of spaces or tabs counts as one space, so aligned table columns match patterns written with single spaces.
Commands are checked in file order, then output blocks. PySnap chooses among
several possible matches, for example several ping runs, so that as many
items as possible pass; with equal results it prefers the earliest match. An
item that fails does not make later items fail through wrong label values.
[grading] is required. Every item contributes its weight; the percentage
of the passed weight is scaled to total points, and the mark is the first
scale step whose threshold in percent is reached. Thresholds are listed
from the highest to the lowest.
The output lists every item as PASS or FAIL. A passed command shows
the entered command it matched; a passed block shows where it was found; a
failed item shows the reason and, for commands, the closest entered command.
The values of all labels, the number of passed items, the points, the
percentage and the mark follow. When the [report] task or host differs
from the report file name or prompts, a warning is printed and the grade is
not changed.
Extract a Report from a Running VM¶
The extract subcommand copies a report from a running VM to the host.
A VM reached through ssh (see Access to the Guest) is read through a
separate ssh session; every other VM through the same UART1 serial
console that pysnap connect uses, so no second COM port and no VM restart
are needed.
pysnap report extract first report.01.first
Extracted "$HOME"/report.01.first from first to /home/user/report.01.first (2621 bytes, sha256 ...).
pysnap report extract first /tmp/report.03.pc1 --output reports/pc1 --force
Over ssh:
the VM is running, has a forwarded ssh port (see
pysnap plug) and the PySnap key is installed for its ssh user (seepysnap ssh-key); unlikeconnect,extractnever asks for a passwordone command prints the
sha256sumof the file and the file itself; PySnap verifies the checksum and writes the file as described belowthe student’s terminal is not touched: nothing is typed into it, so the command works the same with or without an attached
pysnap connectand needs no shell prompt there. A report that is still being recorded is copied as it is at that momenta name without
/becomes"$HOME"/NAMEand the guest shell of the ssh user expands$HOME: the name is looked up in the home directory of the ssh user of the VM (pysnap set VM ssh-user=NAME,rootby default) and nowhere else. A path with/is used as given; a relative path starts in that home directory too. With the default user,report.01.firstmeans/root/report.01.first; withssh-user=studentit means/home/student/report.01.first. A report recorded by another user needs its full path, for examplepysnap report extract first /home/student/report.01.first, and the ssh user must be allowed to read itthe transfer fails when it takes more than two minutes
On the serial console:
the VM is running and has a
UART1TCP port (seepysnap plug)the command also works while
pysnap connectis attached to the VM: VirtualBox serves one client, soextractasks the attached session to run the transfer on its connection. The terminal shows a message in the status line, keys are paused until the transfer ends, and afterwards the screen is cleared and a fresh prompt appears. Sessions started by an older PySnap cannot do this; detach them withCtrl-]qfirstthe console is logged in and at a shell prompt; PySnap checks this with
echo PYSNAP_$((20+22))and stops when the answer does not arriveno
reportrecording is running: PySnap pressesCtrl-Uand Enter once, and when the recording prompt appears it stops before sending any command, so nothing else ends up in the student’s reporta name without
/is looked up in the home directory ($HOME) of the shell running on the console, that is of the user logged in there; a path with/is used as given, and a relative one starts in the current directory of that shellthe file is sent as
base64together with itssha256sum; PySnap verifies the checksum, writes the file under the same name into the current directory or to--output, and never replaces an existing file without--forcethe service commands start with a space, so shells with
HISTCONTROLset toignorespacekeep them out of the history, and the guest screen is cleared afterwardsafter the copy PySnap reads the file as a report and warns when it is not one
A serial console typically runs at 115200 baud, about 11 KB/s: a report of a few kilobytes takes well under a second. The transfer fails only when no data arrives for ten seconds.
Compare Reports¶
The compare subcommand compares every pair of the given reports and lists
signs that two reports share their origin. Paths may be report files or
directories; directories are searched recursively for files named
report.NN.HOST, and a file reached twice is compared once. PySnap does not
know which reports belong to the same student: reports of one student
legitimately share values such as the MAC address of the same VM, so the
teacher decides which pairs matter.
pysnap report compare reports/
SIGNALS reports/ivanov/report.01.first <-> reports/petrov/report.01.first
strong S3 same MAC address: 08:00:27:a9:84:3a
medium M3 identical CPU.txt
OK reports/ivanov/report.01.first <-> reports/sidorov/report.01.first
OK reports/petrov/report.01.first <-> reports/sidorov/report.01.first
Compared 3 reports, 3 pairs: 1 with signals (strongest: 1 strong, 0 medium, 0 weak), 2 OK.
Pairs with signals come first, strongest first, and show only the signals
found; other pairs take one OK line.
Code |
Level |
Signal |
|---|---|---|
|
strong |
identical report files; the other signals are then not listed |
|
strong |
identical recorded output |
|
strong |
the same MAC address in both outputs (all-zero, broadcast and multicast addresses are ignored) |
|
strong |
the same |
|
medium |
at least 20 identical consecutive keyboard delays, to the microsecond, which points at a copied timing log |
|
medium |
at least three consecutive |
|
medium |
byte-identical |
|
medium |
at least two shared commands whose output says |
|
weak |
the same CPU model (not shown when |
Unreadable paths are reported as warnings and skipped. The exit code is
0 when at least one report was read and 1 otherwise.