### Process Launch Steps (Python) Source: https://sh.readthedocs.io/en/latest/sections/architecture Details the sequence of operations for launching a child process, including pipe setup, forking, and synchronization between parent and child processes. ```python 1. Open pipes and/or TTYs STDIN/OUT/ERR. 2. Open a pipe for communicating pre-exec exceptions from the child to the parent. 3. Open a pipe for child/parent launch synchronization. 4. os.fork() a child process. ``` -------------------------------- ### Install sh Library (Shell) Source: https://sh.readthedocs.io/en/latest/index Provides the command to install the sh library using pip, the Python package installer. This command should be run in a terminal or command prompt. ```shell pip install sh ``` -------------------------------- ### Patch sh Commands in Unit Tests Source: https://sh.readthedocs.io/en/latest/sections/faq Provides examples of how to use `unittest.mock.patch` to mock sh commands during testing. It shows how to patch individual commands like `sh.pwd` and the `sh.Command` class itself, explaining the necessity of `create=True` in certain scenarios. ```python from unittest.mock import patch import sh def get_something(): return sh.pwd() @patch("sh.pwd", create=True) def test_something(pwd): pwd.return_value = "/" assert get_something() == "/" ``` ```python from unittest.mock import patch import sh def get_something(): pwd = sh.Command("pwd") return pwd() @patch("sh.Command") def test_something(Command): Command().return_value = "/" assert get_something() == "/" ``` -------------------------------- ### Log sh Command Execution Source: https://sh.readthedocs.io/en/latest/sections/faq Shows how to enable logging in the sh module to view the commands being executed, their start times, and completion status. This is useful for debugging and understanding the module's behavior. ```python import logging import sh logging.basicConfig(level=logging.INFO) sh.ls() ``` -------------------------------- ### Pass Arguments to Command (Python) Source: https://sh.readthedocs.io/en/latest/index Shows how to pass arguments to a system command executed via sh. Arguments are passed as strings to the function call, similar to how they would be provided on the command line. 'color="never"' is an example of an optional argument. ```python sh.ls("-l", "/tmp", color="never") ``` -------------------------------- ### Python: Process GCC warnings with sh and git Source: https://sh.readthedocs.io/en/latest/tutorials/real_time_output This example shows how to capture and process output from the 'gcc' command using 'sh'. It iterates over the compiler output, and if a 'warning' is found, it parses the line, uses 'git blame' to find the commit associated with the file and line number, and then sends an email with the warning message. ```python from sh import gcc, git for line in gcc("-o", "awesome_binary", "awesome_source.c", _iter=True): if "warning" in line: # parse out the relevant info filename, line, char, message = line.split(":", 3) # find the commit using git commit = git("blame", "-e", filename, L="%d,%d" % (line,line)) # send them an email email_address = parse_email_from_commit_line(commit) send_email(email_address, message) ``` -------------------------------- ### Handling TimeoutException in Python using sh Source: https://sh.readthedocs.io/en/latest/sections/command_class Demonstrates how to catch and handle the TimeoutException, which is raised when a command exceeds its specified timeout. This includes examples for both direct command execution with a timeout and waiting for a background process with a timeout. ```python import sh try: sh.sleep(10, _timeout=1) except sh.TimeoutException: print("we timed out, as expected") ``` ```python import sh p = sh.sleep(10, _bg=True) try: p.wait(timeout=1) except sh.TimeoutException: print("we timed out waiting") p.kill() ``` -------------------------------- ### Execute Remote Command with sh Source: https://sh.readthedocs.io/en/latest/tutorials/interacting_with_processes This snippet demonstrates the basic usage of the 'sh' library to execute a command ('ifconfig') on a remote server via SSH. It requires the 'sh' library to be installed and a pre-configured SSH connection (e.g., using ssh-copy-id). The output of the remote command is printed to the console. ```python import sh print(sh.ssh("amoffat@10.10.10.100", "ifconfig")) ``` -------------------------------- ### Bake SSH Command with sh Source: https://sh.readthedocs.io/en/latest/tutorials/interacting_with_processes This example shows how to use 'sh.ssh.bake()' to create a reusable command object for a specific SSH server. This simplifies subsequent calls, as the server address is pre-configured. It demonstrates calling 'ifconfig' and 'whoami' on the remote server using the baked command object. ```python import sh my_server = sh.ssh.bake("amoffat@10.10.10.100") print(my_server("ifconfig")) print(my_server("whoami")) ``` -------------------------------- ### Bake Arguments into ls Command (Python) Source: https://sh.readthedocs.io/en/latest/sections/baking Demonstrates how to use the 'bake' method to pre-set arguments for the 'ls' command. This creates a new callable where the baked arguments are automatically included in subsequent calls. It requires the 'sh' library to be installed. ```python from sh import ls ls = ls.bake("-la") print(ls) # "/usr/bin/ls -la" # resolves to "ls -la /" print(ls("/")) ``` -------------------------------- ### Run command with sudo using 'with' context Source: https://sh.readthedocs.io/en/latest/sections/with Executes a command within a Python 'with' context using sh.contrib.sudo. This is useful for running commands that require elevated privileges. The example shows printing the contents of '/root'. ```python with sh.contrib.sudo: print(ls("/root")) ``` -------------------------------- ### Handle Glob Expansion with sh and Python's glob Source: https://sh.readthedocs.io/en/latest/sections/faq Illustrates how to perform shell-style glob expansion when executing commands with the sh library. Since sh itself doesn't perform glob expansion, Python's `glob.glob()` should be used first to get a list of matching files, which is then passed as arguments to the command. Requires `sh` and `glob` libraries. ```python import sh import glob sh.ls(glob.glob("*.py")) ``` -------------------------------- ### Handle Process Termination by Signal - Python Source: https://sh.readthedocs.io/en/latest/sections/exit_codes Demonstrates how to handle exceptions raised when a process terminates due to a signal using the 'sh' library. It shows the use of 'SignalException' and its subclasses, like 'SignalException_SIGKILL', which inherit from 'ErrorReturnCode'. The example catches a 'SIGKILL' signal after terminating a background process. ```python try: p = sh.sleep(3, _bg=True) p.kill() except sh.SignalException_SIGKILL: print("killed") ``` -------------------------------- ### Customize OK Exit Codes for Commands - Python Source: https://sh.readthedocs.io/en/latest/sections/exit_codes Explains how to define a set of acceptable exit codes for a command using the '_ok_code' argument in the 'sh' library. This is useful for commands where certain non-zero exit codes are not considered errors, such as 'grep' not finding a match. The example shows how to treat exit codes 0 and 1 as success. ```python for i in range(10): sh.grep("string to check", f"file_{i}.txt", _ok_code=(0, 1)) ``` -------------------------------- ### Instantiate and Use sh.Command Source: https://sh.readthedocs.io/en/latest/sections/command_class Demonstrates how to create and use `Command` objects, representing system programs. It shows both direct instantiation by name and dynamic lookup via attributes. The assertion confirms that both methods yield equivalent `Command` objects. ```python import sh ls1 = sh.Command("ls") ls2 = sh.ls assert ls1 == ls2 ``` -------------------------------- ### Command Instantiation with Paths Source: https://sh.readthedocs.io/en/latest/sections/command_class Shows how to instantiate a `Command` object. The constructor accepts the program name, which will be searched for in the system's PATH. Alternatively, a full path to the executable can be provided directly. ```python from sh import Command ifconfig = Command("ifconfig") ifconfig = Command("/sbin/ifconfig") ``` -------------------------------- ### Correct Command Instantiation with Full Paths and Arguments Source: https://sh.readthedocs.io/en/latest/sections/command_class Highlights the correct way to instantiate `Command` objects when using full paths and intending to pass arguments. It emphasizes that the `Command` constructor should only receive the binary path, and arguments should be passed during invocation to avoid `CommandNotFound` exceptions. ```python lscmd = sh.Command("/bin/ls") lscmd("-l") tarcmd = sh.Command("/bin/tar") tarcmd("cvf", "/tmp/test.tar", "/my/home/directory/") ``` -------------------------------- ### RunningCommand Class Source: https://sh.readthedocs.io/en/latest/reference Documentation for the `RunningCommand` class and its various methods and attributes. ```APIDOC ## RunningCommand Class ### Description Represents a command that is currently running or has finished running. ### Methods and Attributes #### `RunningCommand.wait()` ##### Description Waits for the command to complete execution. ##### Method `wait()` ##### Endpoint N/A (Instance Method) ##### Parameters None ##### Request Example None ##### Response N/A ##### Response Example None #### `RunningCommand.process` ##### Description Provides access to the underlying process object. ##### Attribute `process` ##### Type Process object #### `RunningCommand.stdout` ##### Description Captures the standard output of the command. ##### Attribute `stdout` ##### Type String or bytes #### `RunningCommand.stderr` ##### Description Captures the standard error of the command. ##### Attribute `stderr` ##### Type String or bytes #### `RunningCommand.exit_code` ##### Description Returns the exit code of the command. ##### Attribute `exit_code` ##### Type Integer #### `RunningCommand.pid` ##### Description Returns the process ID (PID) of the command. ##### Attribute `pid` ##### Type Integer #### `RunningCommand.sid` ##### Description Returns the session ID (SID) of the command. ##### Attribute `sid` ##### Type Integer #### `RunningCommand.pgid` ##### Description Returns the process group ID (PGID) of the command. ##### Attribute `pgid` ##### Type Integer #### `RunningCommand.ctty` ##### Description Returns the controlling terminal (ctty) of the command. ##### Attribute `ctty` ##### Type String #### `RunningCommand.signal()` ##### Description Sends a signal to the command. ##### Method `signal(signal_number)` ##### Parameters * **signal_number** (int) - The signal number to send. ##### Request Example None ##### Response N/A ##### Response Example None #### `RunningCommand.signal_group()` ##### Description Sends a signal to the process group of the command. ##### Method `signal_group(signal_number)` ##### Parameters * **signal_number** (int) - The signal number to send. ##### Request Example None ##### Response N/A ##### Response Example None #### `RunningCommand.terminate()` ##### Description Sends a termination signal (SIGTERM) to the command. ##### Method `terminate()` ##### Endpoint N/A (Instance Method) ##### Parameters None ##### Request Example None ##### Response N/A ##### Response Example None #### `RunningCommand.kill()` ##### Description Sends a kill signal (SIGKILL) to the command. ##### Method `kill()` ##### Endpoint N/A (Instance Method) ##### Parameters None ##### Request Example None ##### Response N/A ##### Response Example None #### `RunningCommand.kill_group()` ##### Description Sends a kill signal (SIGKILL) to the process group of the command. ##### Method `kill_group()` ##### Endpoint N/A (Instance Method) ##### Parameters None ##### Request Example None ##### Response N/A ##### Response Example None #### `RunningCommand.is_alive()` ##### Description Checks if the command is currently running. ##### Method `is_alive()` ##### Endpoint N/A (Instance Method) ##### Parameters None ##### Request Example None ##### Response N/A ##### Response Example None ``` -------------------------------- ### Command Class Source: https://sh.readthedocs.io/en/latest/reference Documentation for the `Command` class and its `bake()` method. ```APIDOC ## Command Class ### Description Provides a class to represent and manage commands. ### Methods #### `Command.bake()` ##### Description Bakes the command, preparing it for execution. ##### Method `bake()` ##### Endpoint N/A (Class Method) ##### Parameters None ##### Request Example None ##### Response N/A ##### Response Example N/A ``` -------------------------------- ### Get Exit Code of a Command - Python Source: https://sh.readthedocs.io/en/latest/sections/exit_codes Demonstrates how to retrieve the exit code of a command using the 'sh' library in Python. It shows how to execute a command and access its 'exit_code' attribute when the command is set to return the command object using '_return_cmd=True'. ```python output = ls("/", _return_cmd=True) print(output.exit_code) # should be 0 ``` -------------------------------- ### Parent Process Execution Logic (Python) Source: https://sh.readthedocs.io/en/latest/sections/architecture Outlines the steps taken by the parent process after forking, focusing on exception handling, child synchronization, and TTY configuration. ```python 1. Check for any exceptions via the exception pipe connected to the child. 2. Block and read our child’s session id from a pipe connected to the child. 3. If we’re using a TTY for STDIN, via _tty_in=True, disable echoing on the TTY. ``` -------------------------------- ### Execute System Command (Python) Source: https://sh.readthedocs.io/en/latest/index Demonstrates how to execute a system command like 'ifconfig' using the sh library in Python. It takes the command name and its arguments as function calls. The output is the standard output of the executed command. ```python from sh import ifconfig print(ifconfig("wlan0")) ``` -------------------------------- ### Use Subcommands (Python) Source: https://sh.readthedocs.io/en/latest/index Demonstrates how to call subcommands of a program using sh. This allows accessing commands like 'git show' by either chaining them as `sh.git('show', ...)` or using attribute access like `sh.git.show(...)`. ```python # equivalent sh.git("show", "HEAD") sh.git.show("HEAD") ``` -------------------------------- ### Customize Argument Preprocessing in sh.py Source: https://sh.readthedocs.io/en/latest/sections/special_arguments Shows how to use the `_arg_preprocess` option in sh.py to modify command arguments before they are passed to the program. This is an advanced feature typically used with 'bake' for custom wrapper creation. The provided example defines a simple processor that returns arguments and keyword arguments unchanged. ```python import sh def processor(args, kwargs): return args, kwargs my_ls = sh.bake.ls(_arg_preprocess=processor) ``` -------------------------------- ### Basic Piping with Function Composition in sh Source: https://sh.readthedocs.io/en/latest/sections/piping Demonstrates basic piping in sh using function composition. Commands are chained by passing the output of one to the `_in` argument of another. This method executes commands sequentially. ```python print(sort("-rn", _in=du(glob("*`), "-sb"))) # print(the number of folders and files in /etc print(wc("-l", _in=ls("/etc", "-1"))) ``` -------------------------------- ### Helper Functions Source: https://sh.readthedocs.io/en/latest/reference Documentation for utility helper functions. ```APIDOC ## Helper Functions ### Description Utility functions to assist with command execution and directory management. #### `which(command_name)` ##### Description Finds the full path to an executable command in the system's PATH. ##### Parameters * **command_name** (str) - The name of the command to find. ##### Returns * (str) - The full path to the command if found, otherwise None or raises an exception. #### `pushd(directory)` ##### Description Changes the current working directory and pushes the old directory onto a stack. ##### Parameters * **directory** (str) - The directory to change to. ##### Returns * None ``` -------------------------------- ### Implement Custom Logging Messages in sh.py Source: https://sh.readthedocs.io/en/latest/sections/special_arguments Illustrates how to replace the default command logging messages in sh.py with custom ones using the `_log_msg` option. The custom function receives the execution string, call arguments, and PID, allowing for flexible logging. The example demonstrates a function that simplifies the log message. ```python import logging import sh logging.basicConfig(level=logging.INFO) def custom_log(ran, call_args, pid=None): return ran sh.ls("-l", _log_msg=custom_log) ``` -------------------------------- ### Catch Signal Exceptions by Number or Name - Python Source: https://sh.readthedocs.io/en/latest/sections/exit_codes Provides an example of how to catch 'SignalException' in the 'sh' library using either the signal number or its symbolic name. It includes an assertion to verify that the exception class for a specific signal is equivalent whether referenced by its name (e.g., SIGKILL) or its corresponding number (e.g., 9). ```python assert sh.SignalException_SIGKILL == sh.SignalException_9 ``` -------------------------------- ### Process Execution Options Source: https://sh.readthedocs.io/en/latest/sections/special_arguments Configuration options related to how a new process is spawned and managed. ```APIDOC ## _new_session ### Description Determines if our forked process will be executed in its own session via `os.setsid()`. Changed in version 2.0.0: The default value of `_new_session` was changed from `True` to `False` because it makes more sense for a launched process to default to being in the process group of python script, so that it receives SIGINTs correctly. Note If `_new_session` is `False`, the forked process will be put into its own group via `os.setpgrp()`. This way, the forked process, and all of it’s children, are always alone in their own group that may be signalled directly, regardless of the value of `_new_session`. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_new_session** (boolean) - Optional - Determines if the forked process runs in its own session. ### Request Example ```python import sh # Example with _new_session=True (default behavior prior to v2.0.0) # sh.command("_new_session=True") # Example with _new_session=False (default behavior from v2.0.0) sh.command() ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _uid ### Description The user id to assume before the child process calls `os.execv()`. New in version 1.12.0. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_uid** (integer or None) - Optional - The user ID to assume for the child process. ### Request Example ```python import sh # Assume the child process runs as user with UID 1000 sh.command("_uid=1000") ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _preexec_fn ### Description A function to be run directly before the child process calls `os.execv()`. Typically not used by normal users. New in version 1.12.0. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_preexec_fn** (callable or None) - Optional - A function to execute before `os.execv()`. ### Request Example ```python import sh def preexec_setup(): print("Setting up before exec") sh.command("_preexec_fn=preexec_setup") ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _pass_fds ### Description A whitelist iterable of integer file descriptors to be inherited by the child. Passing anything in this argument causes `_close_fds` to be `True`. New in version 1.13.0. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_pass_fds** (iterable of integers or set) - Optional - A set of file descriptors to keep open. ### Request Example ```python import sys import sh # Keep standard output file descriptor open sh.command("_pass_fds={0}".format(sys.stdout.fileno())) ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _close_fds ### Description Causes all inherited file descriptors besides stdin, stdout, and stderr to be automatically closed. This option is automatically enabled when `_pass_fds` is given a value. New in version 1.13.0. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_close_fds** (boolean) - Optional - Whether to close inherited file descriptors. ### Request Example ```python import sh # Explicitly close file descriptors (default is True) sh.command("_close_fds=True") # Do not close file descriptors (only relevant if _pass_fds is not used) # sh.command("_close_fds=False") ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` -------------------------------- ### Execute Bash Builtins with sh Source: https://sh.readthedocs.io/en/latest/sections/faq Demonstrates two methods to execute bash builtins using the sh library. The first uses `sh.bash("-c", ...)` directly, while the second utilizes `sh.bash.bake("-c")` for creating a reusable builtin executor. Both require the `sh` library. ```python import sh sh.bash("-c", "your_builtin") ``` ```python import sh builtins = sh.bash.bake("-c") builtins("your_builtin") ``` -------------------------------- ### Redirecting to File-like Object Source: https://sh.readthedocs.io/en/latest/sections/redirection Shows how to redirect the standard output to a file-like object that supports a `.write(data)` method, such as `io.StringIO`. ```APIDOC ## Redirecting to File-like Object ### Description Redirects the STDOUT of a command to a file-like object that implements a `.write(data)` method, such as `io.StringIO`. ### Method POST (implicitly, as it's a function call that might involve I/O) ### Endpoint N/A (Python function call) ### Parameters #### Special Keyword Arguments - **_out** (object) - Required - A file-like object with a `.write(data)` method. ### Request Example ```python import sh from io import StringIO buf = StringIO() sh.ifconfig(_out=buf) print(buf.getvalue()) ``` ### Response #### Success Response (200) N/A (The command's output is captured by the file-like object). #### Response Example ``` [Output of ifconfig command] ``` ``` -------------------------------- ### Duplicate STDERR to STDOUT using _err_to_out Source: https://sh.readthedocs.io/en/latest/sections/special_arguments This example shows how to redirect the standard error (STDERR) stream to the same destination as the standard output (STDOUT) stream using the `_err_to_out=True` keyword argument. When set to `True`, both STDOUT and STDERR will be sent to the same file descriptor or target. This is useful for consolidating all output from a command into a single location, simplifying logging or analysis when the distinction between standard output and error messages is not critical. ```python import sh sh.command_with_errors(_err_to_out=True, _out="/tmp/combined_output.log") ``` -------------------------------- ### Redirect STDERR to a File using _err Source: https://sh.readthedocs.io/en/latest/sections/special_arguments This example demonstrates how to redirect the standard error (STDERR) stream of a command to a specified file or destination, similar to the `_out` argument for STDOUT. The `_err` keyword argument accepts the same types of values as `_out`: a string for a file name, a file object, a file descriptor, a StringIO object, or a callable. This allows for separate logging or handling of error messages generated by the executed command. ```python import sh sh.ls("/nonexistent_directory", _err="/tmp/error.log") ``` -------------------------------- ### Order Keyword Arguments in sh Commands Source: https://sh.readthedocs.io/en/latest/sections/faq Demonstrates how to correctly pass arguments to sh commands when argument order is important. It highlights the Python limitation of positional arguments after keyword arguments and provides the solution of using raw ordered arguments. ```python import sh # Incorrect usage: positional arguments after keyword arguments # sh.my_command(arg1="val1", "arg2", arg3="val3") # Correct usage: raw ordered arguments sh.my_command("--arg1=val1", "arg2", "--arg3=val3") ``` -------------------------------- ### Set Command Timeout using _timeout Source: https://sh.readthedocs.io/en/latest/sections/special_arguments This example illustrates how to set a time limit for a command's execution using the `_timeout` keyword argument. The value should be in seconds. If the command exceeds this specified duration, it will be terminated by the signal defined in `_timeout_signal` (which defaults to `signal.SIGKILL`). This is essential for preventing runaway processes from consuming excessive resources or indefinitely blocking script execution. The `_timeout_signal` argument can be used to specify a different signal if needed. ```python import sh import signal # Set timeout to 10 seconds, use SIGTERM if timeout occurs sh.long_running_command(_timeout=10, _timeout_signal=signal.SIGTERM) ``` -------------------------------- ### Bake Command for Reusability (Python) Source: https://sh.readthedocs.io/en/latest/index Explains the 'bake' feature in sh, which allows creating a pre-configured command function. This is useful for repeatedly calling a command with the same set of initial arguments, improving code readability and reducing repetition. ```python my_ls = sh.ls.bake("-l") # equivalent my_ls("/tmp") sh.ls("-l", "/tmp") ``` -------------------------------- ### Using pushd context manager in Python with sh Source: https://sh.readthedocs.io/en/latest/sections/command_class Illustrates the usage of the pushd function as a context manager, mimicking Bash's pushd command. It allows changing the current directory within a 'with' block, ensuring proper directory management. ```python import sh with sh.pushd("/tmp"): sh.touch("a_file") ``` -------------------------------- ### Handle Decoding Errors using _decode_errors Source: https://sh.readthedocs.io/en/latest/sections/special_arguments This example illustrates how to control how decoding errors are handled for the command's output using the `_decode_errors` keyword argument. Available since version 1.07.0, this argument accepts any value valid for Python's `bytes.decode()` method, such as 'strict' (the default, which raises an exception), 'ignore' (which skips problematic characters), or 'replace' (which substitutes them with a placeholder). This is crucial for robustly processing output that might contain malformed byte sequences. ```python import sh # Ignore characters that cannot be decoded sh.some_command(_decode_errors="ignore") ``` -------------------------------- ### Control Exception Output Truncation using _truncate_exc Source: https://sh.readthedocs.io/en/latest/sections/special_arguments This example shows how to control whether exception output is truncated when an error occurs during command execution. The `_truncate_exc` keyword argument, available since version 1.12.0, defaults to `True`, meaning exception output might be shortened to avoid excessively long error messages. Setting it to `False` ensures that the full exception output is preserved. This is useful for debugging complex issues where all details of the error message are required. ```python import sh # Keep the full exception output sh.command_that_might_fail(_truncate_exc=False) ``` -------------------------------- ### Connect Command to sys.stdout and sys.stdin using sh Source: https://sh.readthedocs.io/en/latest/sections/faq Illustrates how to connect a command's standard input, output, and error streams to Python's `sys.stdin`, `sys.stdout`, and `sys.stderr`. It also presents `_fg=True` as a more robust solution for foreground execution. ```python import sh import sys # Connecting to sys streams (may not always work as expected) # sh.your_command(_in=sys.stdin, _out=sys.stdout) # Using _fg=True for foreground execution (more reliable) sh.top(_fg=True) ``` -------------------------------- ### Sudo with Manual Password Input using sh.sudo Source: https://sh.readthedocs.io/en/latest/sections/sudo Illustrates using the raw `sh.sudo` command by baking in the password via the `_in` argument and using the `-S` flag. This approach manually configures sudo behavior and is primarily for educational purposes, as it largely replicates the functionality of `sh.contrib.sudo`. ```python import sh # password must end in a newline my_password = "password\n" # -S says "get the password from stdin" my_sudo = sh.sudo.bake("-S", _in=my_password) print(my_sudo.ls("root")) ``` -------------------------------- ### Handle Non-Zero Exit Codes using _ok_code Source: https://sh.readthedocs.io/en/latest/sections/special_arguments This example shows how to specify a list of acceptable exit codes for a command using the `_ok_code` keyword argument. By default, sh.py raises an exception for any non-zero exit code. However, some programs use non-zero exit codes to indicate success or specific conditions. This argument allows you to define a tuple or list of integers that will be considered 'ok' and will not trigger an exception, preventing the swallowing of potentially important execution results. ```python import sh sh.weird_program(_ok_code=[0,3,5]) ``` -------------------------------- ### Run Command in Background using _bg Source: https://sh.readthedocs.io/en/latest/sections/special_arguments This example demonstrates how to execute a command in the background using the `_bg=True` keyword argument. When a command is run in the background, it returns immediately, allowing your script to continue execution without waiting for the command to finish. To ensure the background command terminates and to handle any potential exceptions, you must explicitly call the `.wait()` method on the returned `RunningCommand` object. This is crucial for managing asynchronous operations and preventing the swallowing of background process errors if `_bg_exc` is set to `True`. ```python import sh cmd = sh.sleep(5, _bg=True) # Do other things here cmd.wait() ``` -------------------------------- ### Handle Specific and General Error Exit Codes - Python Source: https://sh.readthedocs.io/en/latest/sections/exit_codes Illustrates exception handling for command execution failures using the 'sh' library. It shows how to catch specific error codes (e.g., ErrorReturnCode_2) and the general base class for all error return codes (ErrorReturnCode). This allows for targeted error recovery or general error logging. ```python try: print(ls("/some/non-existant/folder")) except ErrorReturnCode_2: print("folder doesn\'t exist!") create_the_folder() except ErrorReturnCode: print("unknown error") ``` -------------------------------- ### Performance and Optimization Source: https://sh.readthedocs.io/en/latest/sections/special_arguments Options for tuning buffer sizes for improved performance. ```APIDOC ## _in_bufsize ### Description The STDIN buffer size. 0 for unbuffered, 1 for line buffered, anything else for a buffer of that amount. Default value: `0`. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_in_bufsize** (integer) - Optional - The buffer size for standard input. ### Request Example ```python import sh # Set standard input to be line buffered sh.command("_in_bufsize=1") # Set standard input to have a buffer of 4096 bytes # sh.command("_in_bufsize=4096") ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` -------------------------------- ### Handle Command Exit Codes (Python) Source: https://sh.readthedocs.io/en/latest/index Illustrates how to handle non-zero exit codes from system commands using sh. A try-except block is used to catch `sh.ErrorReturnCode` exceptions, allowing graceful handling of command failures, such as when a directory does not exist. ```python try: sh.ls("/doesnt/exist") except sh.ErrorReturnCode_2: print("directory doesn't exist") ``` -------------------------------- ### RunningCommand Class Source: https://sh.readthedocs.io/en/latest/sections/command_class Represents a Command instance that has been or is being executed. It wraps the low-level OProc and is returned when `_return_cmd=True`. ```APIDOC ## RunningCommand Class This represents a Command instance that has been or is being executed. It exists as a wrapper around the low-level OProc. Most of your interaction with sh objects are with instances of this class. It is only returned if `_return_cmd=True` when you execute a command. **Warning**: Objects of this class behave very much like strings. This was an intentional design decision to make the “output” of an executing Command behave more intuitively. Be aware that functions that accept real strings only, for example `json.dumps`, will not work on instances of RunningCommand, even though it look like a string. ### Methods #### `wait(_timeout =None_)` Block and wait for the command to finish execution and obtain an exit code. If the exit code represents a failure, we raise the appropriate exception. See exceptions. **Parameters**: - **timeout** (number) - Optional non-negative number to wait for the command to complete. If it doesn’t complete by the timeout, we raise TimeoutException. **Note**: - Calling this method multiple times only yields an exception on the first call. - This is called automatically by sh unless your command is being executed asynchronously, in which case, you may want to call this manually to ensure completion. - If an instance of Command is being used as the stdin argument (see piping), `wait()` is also called on that instance, and any exceptions resulting from that process are propagated up. #### `signal(_sig_num_)` Sends `_sig_num_` to the process. Typically used with a value from the `signal` module, like `signal.SIGHUP` (see `_signal(7)_`). **Parameters**: - **sig_num** (number) - The signal number to send. #### `signal_group(_sig_num_)` Sends `_sig_num_` to every process in the process group. Typically used with a value from the `signal` module, like `signal.SIGHUP` (see `_signal(7)_`). **Parameters**: - **sig_num** (number) - The signal number to send. #### `terminate()` Shortcut for `RunningCommand.signal(signal.SIGTERM)`. #### `kill()` Shortcut for `RunningCommand.signal(signal.SIGKILL)`. #### `kill_group()` Shortcut for `RunningCommand.signal_group(signal.SIGKILL)`. #### `is_alive()` Returns whether or not the process is still alive. **Return type**: - bool ### Properties #### `process` The underlying OProc instance. #### `stdout` A `@property` that calls `wait()` and then returns the contents of what the process wrote to stdout. #### `stderr` A `@property` that calls `wait()` and then returns the contents of what the process wrote to stderr. #### `exit_code` A `@property` that calls `wait()` and then returns the process’s exit code. #### `pid` The process id of the process. #### `sid` The session id of the process. This will typically be a different session than the current python process, unless `_new_session=False` was specified. #### `pgid` The process group id of the process. #### `ctty` The controlling terminal device, if there is one. ``` -------------------------------- ### Redirecting to Function Callback Source: https://sh.readthedocs.io/en/latest/sections/redirection Explains how to use a callback function as a target for redirection. The function can accept data chunks, an optional stdin queue, and an optional process reference. ```APIDOC ## Redirecting to Function Callback ### Description Redirects the STDOUT of a command to a callback function. The function can be defined with different signatures to receive data chunks, a queue for stdin communication, and a reference to the process object. ### Method POST (implicitly, as it's a function call that might involve I/O) ### Endpoint N/A (Python function call) ### Parameters #### Special Keyword Arguments - **_out** (function) - Required - A callback function that will process the command's output. #### Callback Function Signatures 1. `fn(_data_)`: Receives only the chunk of data from the process. 2. `fn(_data_, _stdin_queue_)`: Receives data and a `queue.Queue` for programmatic interaction with the process's stdin. 3. `fn(_data_, _stdin_queue_, _process_)`: Receives data, the stdin queue, and a `weakref.ref` to the process object. ### Request Example ```python import sh import queue import weakref # Example callback function def output_handler(_data_, _stdin_queue_=None, _process_=None): print(f"Received data: {_data_.decode()}") # Example of using stdin_queue if provided # if _stdin_queue_: # _stdin_queue_.put(b"some input\n") # Example of using process if provided # if _process_ and _process_.ref(): # print("Process object available") # Redirecting to the callback sh.ls("-l", _out=output_handler) ``` ### Response #### Success Response (200) N/A (The command's output is processed by the callback function). #### Response Example ``` Received data: total 4 -rw-r--r-- 1 user group 0 Jan 1 10:00 file1.txt -rw-r--r-- 1 user group 0 Jan 1 10:00 file2.txt ``` ``` -------------------------------- ### Communication and Output Handling Source: https://sh.readthedocs.io/en/latest/sections/special_arguments Options for managing standard input, output, and inter-process communication. ```APIDOC ## _in ### Description Specifies an argument for the process to use as its standard input. This may be a string, a `queue.Queue`, a file-like object, or any iterable. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_in** (string, queue.Queue, file-like object, or iterable) - Optional - The input for the standard input stream. ### Request Example ```python import sh from queue import Queue # Using a string as input sh.cat(_in="Hello, world!") # Using a queue input_queue = Queue() input_queue.put("Line 1\n") input_queue.put("Line 2\n") sh.wc("-l", _in=input_queue) ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _piped ### Description May be `True`, `"out"`, or `"err"`. Signals a command that it is being used as the input to another command, so it should return its output incrementally as it receives it, instead of aggregating it all at once. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_piped** (boolean or string) - Optional - Indicates if the output should be streamed. ### Request Example ```python import sh # Stream output incrementally sh.grep("pattern", "file.txt", _piped=True) ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _iter ### Description May be `True`, `"out"`, or `"err"`. Puts a command in iterable mode. In this mode, you can use a `for` or `while` loop to iterate over a command’s output in real-time. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_iter** (boolean or string) - Optional - Enables real-time iteration over command output. ### Request Example ```python import sh for line in sh.cat("/tmp/file", _iter=True): print(line) ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _iter_noblock ### Description Same as `_iter`, except the loop will not block if there is no output to iterate over. Instead, the output from the command will be `errno.EWOULDBLOCK`. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_iter_noblock** (boolean) - Optional - Enables non-blocking iteration over command output. ### Request Example ```python import sh import errno import time for line in sh.tail("-f", "stuff.log", _iter_noblock=True): if line == errno.EWOULDBLOCK: print("doing something else...") time.sleep(0.5) else: print("processing line!") ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _with ### Description Explicitly tells us that we’re running a command in a `with` context. This is only necessary if you’re using a command in a `with` context **and** passing parameters to it. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_with** (boolean) - Optional - Indicates the command is used within a `with` context. ### Request Example ```python import sh with sh.contrib.sudo(password="abc123", _with=True): print(sh.ls("/root")) ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` ```APIDOC ## _done ### Description A callback that is _always_ called when the command completes, even if it completes with an exit code that would raise an exception. After the callback is run, any exception that would be raised is raised. The callback is passed the RunningCommand instance, a boolean indicating success, and the exit code. New in version 1.11.0. ### Method (Implicitly used with sh.Command) ### Endpoint (N/A - Library Parameter) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body - **_done** (callable) - Optional - A callback function to execute upon command completion. ### Request Example ```python import sh from threading import Semaphore pool = Semaphore(10) def done_callback(cmd, success, exit_code): pool.release() print(f"Command finished with success: {success}, exit code: {exit_code}") def run_command_with_callback(arg): pool.acquire() return sh.your_parallel_command(arg, _bg=True, _done=done_callback) procs = [] for i in range(5): procs.append(run_command_with_callback(i)) [p.wait() for p in procs] ``` ### Response #### Success Response (200) (N/A - This is a configuration parameter, not a direct API response) #### Response Example (N/A) ``` -------------------------------- ### Pipe Command Output (Python) Source: https://sh.readthedocs.io/en/latest/index Shows how to chain commands using pipes with the sh library. The standard output of one command is used as the standard input for another, mimicking the behavior of shell pipes. ```python sh.wc("-l", _in=sh.ls("-1")) ``` -------------------------------- ### Exceptions Source: https://sh.readthedocs.io/en/latest/reference Documentation for custom exceptions used within the API. ```APIDOC ## Exceptions ### Description This section details the custom exceptions raised by the API. #### ErrorReturnCode ##### Description Raised when a command returns a non-zero exit code. ##### Attributes * **full_cmd** (str) - The full command that was executed. * **stdout** (str) - The standard output captured during execution. * **stderr** (str) - The standard error captured during execution. * **exit_code** (int) - The non-zero exit code returned by the command. #### SignalException ##### Description Raised when a process is terminated by a signal. #### TimeoutException ##### Description Raised when a command execution exceeds the specified timeout. #### CommandNotFound ##### Description Raised when a specified command cannot be found in the system's PATH. ``` -------------------------------- ### Redirecting to Filename Source: https://sh.readthedocs.io/en/latest/sections/redirection Demonstrates how to redirect the standard output of a command to a file. The file is opened in binary write mode ('wb'), truncating it if it already exists. ```APIDOC ## Redirecting to Filename ### Description Redirects the STDOUT of a command to a specified filename. The file is opened in binary write mode ('wb'). ### Method POST (implicitly, as it's a function call that might involve I/O) ### Endpoint N/A (Python function call) ### Parameters #### Special Keyword Arguments - **_out** (string) - Required - The filename to which STDOUT will be redirected. ### Request Example ```python import sh sh.ifconfig(_out="/tmp/interfaces") ``` ### Response #### Success Response (200) N/A (The command's output is written to the file, no direct response is returned by the `sh` function itself). #### Response Example N/A ``` -------------------------------- ### AsyncIO Execution with Sh Source: https://sh.readthedocs.io/en/latest/sections/asynchronous_execution Demonstrates how to execute commands asynchronously using Python's asyncio library with the `_async=True` kwarg. This allows for incremental awaiting of command output. Requires Python 3.7+ and the 'sh' library. ```python import asyncio import sh async def main(): await sh.sleep(3, _async=True) asyncio.run(main()) ``` -------------------------------- ### Run command with sudo and arguments in 'with' context Source: https://sh.readthedocs.io/en/latest/sections/with Demonstrates running a command within a 'with' context using sh.contrib.sudo while passing specific arguments. The '_with=True' parameter is crucial for commands to behave correctly within such contexts, as shown with the '-p' prompt for sudo. ```python with sh.contrib.sudo(k=True, _with=True): print(ls("/root")) ``` -------------------------------- ### Baking Arguments into sh.Command Source: https://sh.readthedocs.io/en/latest/sections/command_class Illustrates the `bake` method of the `Command` class. This method returns a new `Command` object with pre-set positional and keyword arguments. Any subsequent calls to this new object will automatically include these baked-in arguments. ```python from sh import ls long_ls = ls.bake("-l") print(ls("/var")) print(ls("/tmp")) ```