.. py:module:: tbot.machine.linux ``tbot.machine.linux`` ====================== This module contains utilities for interacting with linux hosts. This includes: - :ref:`linux-shells` - tbot's own path type: :py:class:`tbot.machine.linux.Path` .. _linux-shells: Linux Shells ------------ The base-class :py:class:`tbot.machine.linux.LinuxShell` defines the common interface all linux-shells should provide. This interface consists of the following methods: - :py:meth:`lnx.escape() ` - Escape args for the underlying shell. - :py:meth:`lnx.exec0() ` - Run command and ensure it succeeded. - :py:meth:`lnx.exec() ` - Run command and return output and return code. - :py:meth:`lnx.run() ` - Start a command and allow a testcase to interact with its stdio. - :py:meth:`lnx.test() ` - Run command and return boolean whether it succeeded. - :py:meth:`lnx.env() ` - Get/Set environment variables. - :py:meth:`lnx.subshell() ` - Start a subshell environment. - :py:meth:`lnx.interactive() ` - Start an interactive session for this machine. And the following properties: - :py:attr:`lnx.username ` - Current user. - :py:attr:`lnx.fsroot ` - Path to the file-system root (just for convenience). - :py:attr:`lnx.workdir ` - Path to a directory which testcases can store files in. tbot contains implementations of this interface for the following shells: .. autoclass:: tbot.machine.linux.Bash .. autoclass:: tbot.machine.linux.LinuxShell :members: .. _linux-argtypes: Argument Types ~~~~~~~~~~~~~~ For a lot of methods defined in :py:class:`~tbot.machine.linux.LinuxShell`, a special set of types can be given as arguments. This protects against a lot of common errors. The allowed types are: - :py:class:`str` - Every string argument will be properly quoted so the shell picks it up as only one parameter. Example: .. code-block:: python lnx.exec0("echo", "Hello World!", "Is this tbot?") # Will run: # echo "Hello World!" "Is this tbot?" - :py:class:`tbot.machine.linux.Path` - tbot's path class keeps track of the machine the path is associated with. This prevents you from accidentally using a path from one host on another. The path class behaves like :py:mod:`pathlib` paths, so you can do things like: .. code-block:: python tftpdir = lnx.fsroot / "var" / "lib" / "tftpboot" lnx.exec0("ls", "-1", tftpdir) if (tftpdir / "u-boot.bin").is_file(): tbot.log.message("Binary exists!") - **"Specials"** - Sometimes you will need special shell-syntax for certain operations, for example to redirect output of a command. For these things, tbot provides special "tokens". The full list can be found in :ref:`linux-specials`. As an example, redirecting to a file works like this: .. code-block:: python lnx.exec0("dmesg", linux.RedirStdout(lnx.workdir / "kernel.log")) # Will run: # dmesg >/tmp/tbot-wd/kernel.log .. _linux-specials: Specials ~~~~~~~~ Specials can be used as part of commands to use certain shell-syntaxes. This can be used to chain multiple commands or to redirect output. .. py:data:: AndThen Chain commands using ``&&``. **Example**: .. code-block:: python lnx.exec0("sleep", str(10), linux.AndThen, "echo", "Hello!") .. py:data:: OrElse Chain commands using ``||``. .. py:data:: Then Chain commands using ``;``. .. py:data:: Pipe Pipe the output of one command into another: .. code-block:: python lnx.exec0("dmesg", linux.Pipe, "grep", "usb") .. py:class:: RedirStdout(file) Redirect ``stdout`` (``>...``) to a file. .. py:class:: RedirStderr(file) Redirect ``stderr`` (``2>...``) to a file. .. py:class:: RedirBoth(file) Redirect both ``stdout`` and ``stderr`` (``>... 2>&1``) to a file. .. py:class:: RedirStdin(file) Redirect to ``stdin`` (``<...``) from a file. .. py:class:: AppendStdout(file) Redirect ``stdout`` (``>>...``) to a file, appending to the file rather than overwriting its contents. .. versionadded:: 0.9.1 .. py:class:: AppendStderr(file) Redirect ``stderr`` (``2>>...``) to a file, appending to the file rather than overwriting its contents. .. versionadded:: 0.9.1 .. py:class:: AppendBoth(file) Redirect both ``stdout`` and ``stderr`` (``>>... 2>&1``) to a file, appending to the file rather than overwriting its contents. .. versionadded:: 0.9.1 .. py:data:: Background Tells the shell to run this command in the background (``&``). By default all output from the command is suppressed (by redirection to ``/dev/null``). If you do want to save command output, use the alternate form of :py:data:`Background`: .. code-block:: python f1 = lh.workdir / "stdout.txt" f2 = lh.workdir / "stderr.txt" # Just redirect stdout to a file, discard stderr linux.Background(stdout=f1) # Just redirect stderr to a file, discard stdout linux.Background(stderr=f2) # Redirect both to files linux.Background(stdout=f1, stderr=f2) .. warning:: Beware of the side-effects of running commands in the background! **Never ever add** ``linux.Background`` **after a command that you expect will terminate at some point on its own!** This will potentially clobber an unrelated command's output which can have unexpected effects. Only use this special token with commands that will run forever until terminated manually. A good pattern to follow is this: .. code-block:: python lh.exec0("some", "cmd", "that", "won't", "terminate", linux.Background) pid = lh.env("!") ... lh.exec0("kill", pid, linux.Then, "wait", pid) .. versionchanged:: 0.9.1 ``Background`` now always properly redirects stderr as well. .. py:class:: Raw(str) Emits a raw string, bypassing shell quoting/escaping. .. warning:: Only use this if nothing else works! :py:class:`linux.Raw ` can quickly lead to hard-to-find bugs. RunCommandProxy --------------- .. autoclass:: tbot.machine.linux.RunCommandProxy :members: .. autoclass:: tbot.machine.linux.CommandEndedException Paths ----- .. autoclass:: tbot.machine.linux.Path :members: Workdir ~~~~~~~ .. py:class:: Workdir .. automethod:: tbot.machine.linux.Workdir.static .. automethod:: tbot.machine.linux.Workdir.athome .. automethod:: tbot.machine.linux.Workdir.xdg_data .. automethod:: tbot.machine.linux.Workdir.xdg_runtime ``copy()`` ~~~~~~~~~~ .. autofunction:: tbot.machine.linux.copy Lab-Host -------- .. autoclass:: tbot.machine.linux.Lab :members: Builder ------- The :py:class:`~tbot.machine.linux.Builder` mixin allows marking a machine as a build-host. This means generic testcases like ``uboot.build`` can use it to automatically build projects. For this to work, a build-host needs to specify which toolchains it has installed and where tbot can find them. .. autoclass:: tbot.machine.linux.Builder :members: .. py:module:: tbot.machine.linux.build Toolchains ~~~~~~~~~~ .. autoclass:: tbot.machine.linux.build.Toolchain :members: .. autoclass:: tbot.machine.linux.build.DistroToolchain .. autoclass:: tbot.machine.linux.build.EnvScriptToolchain .. py:module:: tbot.machine.linux.auth Authenticators -------------- For logging in via SSH using :class:`~tbot.machine.connector.ParamikoConnector` or :class:`~tbot.machine.connector.SSHConnector`, tbot provides the following 'authenticators': .. autoclass:: tbot.machine.linux.auth.NoneAuthenticator :members: .. autoclass:: tbot.machine.linux.auth.PrivateKeyAuthenticator :members: .. autoclass:: tbot.machine.linux.auth.PasswordAuthenticator :members: