diff --git a/nixos/doc/manual/development/writing-nixos-tests.section.md b/nixos/doc/manual/development/writing-nixos-tests.section.md index a9ffffe2277c..e5ee1cb01ff1 100644 --- a/nixos/doc/manual/development/writing-nixos-tests.section.md +++ b/nixos/doc/manual/development/writing-nixos-tests.section.md @@ -159,34 +159,42 @@ The following methods are available on machine objects: `execute` : Execute a shell command, returning a list `(status, stdout)`. + + Commands are run with `set -euo pipefail` set: + + - If several commands are separated by `;` and one fails, the + command as a whole will fail. + + - For pipelines, the last non-zero exit status will be returned + (if there is one; otherwise zero will be returned). + + - Dereferencing unset variables fails the command. + + - It will wait for stdout to be closed. + If the command detaches, it must close stdout, as `execute` will wait for this to consume all output reliably. This can be achieved by redirecting stdout to stderr `>&2`, to `/dev/console`, `/dev/null` or a file. Examples of detaching commands are `sleep 365d &`, where the shell forks a new process that can write to stdout and `xclip -i`, where the `xclip` command itself forks without closing stdout. + Takes an optional parameter `check_return` that defaults to `True`. Setting this parameter to `False` will not check for the return code and return -1 instead. This can be used for commands that shut down the VM and would therefore break the pipe that would be used for retrieving the return code. + A timeout for the command can be specified (in seconds) using the optional + `timeout` parameter, e.g., `execute(cmd, timeout=10)` or + `execute(cmd, timeout=None)`. The default is 900 seconds. + `succeed` : Execute a shell command, raising an exception if the exit status is - not zero, otherwise returning the standard output. Commands are run - with `set -euo pipefail` set: - - - If several commands are separated by `;` and one fails, the - command as a whole will fail. - - - For pipelines, the last non-zero exit status will be returned - (if there is one, zero will be returned otherwise). - - - Dereferencing unset variables fail the command. - - - It will wait for stdout to be closed. See `execute` for the - implications. + not zero, otherwise returning the standard output. Similar to `execute`, + except that the timeout is `None` by default. See `execute` for details on + command execution. `fail` @@ -196,10 +204,13 @@ The following methods are available on machine objects: `wait_until_succeeds` : Repeat a shell command with 1-second intervals until it succeeds. + Has a default timeout of 900 seconds which can be modified, e.g. + `wait_until_succeeds(cmd, timeout=10)`. See `execute` for details on + command execution. `wait_until_fails` -: Repeat a shell command with 1-second intervals until it fails. +: Like `wait_until_succeeds`, but repeating the command until it fails. `wait_for_unit` diff --git a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml index b194d58e5beb..7ce3e4cb2906 100644 --- a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml +++ b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml @@ -274,35 +274,9 @@ start_all() Execute a shell command, returning a list - (status, stdout). If the command - detaches, it must close stdout, as - execute will wait for this to consume all - output reliably. This can be achieved by redirecting stdout - to stderr >&2, to - /dev/console, - /dev/null or a file. Examples of - detaching commands are sleep 365d &, - where the shell forks a new process that can write to stdout - and xclip -i, where the - xclip command itself forks without - closing stdout. Takes an optional parameter - check_return that defaults to - True. Setting this parameter to - False will not check for the return code - and return -1 instead. This can be used for commands that - shut down the VM and would therefore break the pipe that - would be used for retrieving the return code. + (status, stdout). - - - - - succeed - - - Execute a shell command, raising an exception if the exit - status is not zero, otherwise returning the standard output. Commands are run with set -euo pipefail set: @@ -317,22 +291,63 @@ start_all() For pipelines, the last non-zero exit status will be - returned (if there is one, zero will be returned - otherwise). + returned (if there is one; otherwise zero will be + returned). - Dereferencing unset variables fail the command. + Dereferencing unset variables fails the command. - It will wait for stdout to be closed. See - execute for the implications. + It will wait for stdout to be closed. + + If the command detaches, it must close stdout, as + execute will wait for this to consume all + output reliably. This can be achieved by redirecting stdout + to stderr >&2, to + /dev/console, + /dev/null or a file. Examples of + detaching commands are sleep 365d &, + where the shell forks a new process that can write to stdout + and xclip -i, where the + xclip command itself forks without + closing stdout. + + + Takes an optional parameter check_return + that defaults to True. Setting this + parameter to False will not check for the + return code and return -1 instead. This can be used for + commands that shut down the VM and would therefore break the + pipe that would be used for retrieving the return code. + + + A timeout for the command can be specified (in seconds) + using the optional timeout parameter, + e.g., execute(cmd, timeout=10) or + execute(cmd, timeout=None). The default + is 900 seconds. + + + + + + succeed + + + + Execute a shell command, raising an exception if the exit + status is not zero, otherwise returning the standard output. + Similar to execute, except that the + timeout is None by default. See + execute for details on command execution. + @@ -353,7 +368,10 @@ start_all() Repeat a shell command with 1-second intervals until it - succeeds. + succeeds. Has a default timeout of 900 seconds which can be + modified, e.g. + wait_until_succeeds(cmd, timeout=10). See + execute for details on command execution. @@ -363,8 +381,8 @@ start_all() - Repeat a shell command with 1-second intervals until it - fails. + Like wait_until_succeeds, but repeating + the command until it fails. diff --git a/nixos/lib/test-driver/test_driver/machine.py b/nixos/lib/test-driver/test_driver/machine.py index f3e615fe5bf9..035e3ffe8973 100644 --- a/nixos/lib/test-driver/test_driver/machine.py +++ b/nixos/lib/test-driver/test_driver/machine.py @@ -526,10 +526,17 @@ class Machine: self.run_callbacks() self.connect() - if timeout is not None: - command = "timeout {} sh -c {}".format(timeout, shlex.quote(command)) + # Always run command with shell opts + command = f"set -euo pipefail; {command}" + + timeout_str = "" + if timeout is not None: + timeout_str = f"timeout {timeout}" + + out_command = ( + f"{timeout_str} sh -c {shlex.quote(command)} | (base64 --wrap 0; echo)\n" + ) - out_command = f"( set -euo pipefail; {command} ) | (base64 --wrap 0; echo)\n" assert self.shell self.shell.send(out_command.encode())