Module API Tutorial
Next-release API: This page describes the updated source checkout. The published 3.1.4 wheel retains the earlier command/config/check behavior.
This tutorial introduces SSHScript v3.1 through its primary Python Session API. The optional Dollar syntax is shown only after the module workflow.
Install SSHScript
SSHScript v3.1 requires Python 3.11 or newer. Version 3.1.4 is the current Production/Stable release on PyPI. Complete Installation and Verification and confirm that both the CLI and Python import report 3.1.4 before using this tutorial.
Execute a local command
from sshscript import Session
session = Session()
try:
stdout, stderr, exitcode = session.exec_command("hostname", shell=False)
print(str(stdout).strip())
print(session.exitcode)
finally:
session.close(strict=True)
The latest command result is available as session.stdout, session.stderr, and session.exitcode. Each new command replaces those properties.
Build a command safely
exec_command() accepts a nonempty string or a list/tuple of string arguments. Pass argv directly for argument-preserving execution; shlex.join() with shell=False remains valid when an existing caller uses a string:
import shlex
from sshscript import Session
arguments = ["printf", "%s\n", "hello world"]
command = shlex.join(arguments)
session = Session()
try:
session.exec_command(command, shell=False)
print(str(session.stdout), end="")
finally:
session.close(strict=True)
Do not pass arguments directly; list and tuple commands raise TypeError.
Use shell features deliberately
With shell=None, the default, SSHScript automatically detects pipelines, redirection, expansion, and other shell syntax.
session.exec_command("printf 'alpha\\nbeta\\n' | grep beta")
Set shell=False for argument-preserving execution, shell=True to force the POSIX shell, or shell="bash" for a Bash-only command. Locally, shell=False launches without a shell. Remotely, SSHScript safely re-quotes the arguments and sends exec ... through the server’s command shell; shell operators are not interpreted as user shell syntax.
Connect to a remote host
from sshscript import Session
local = Session()
try:
with local.connect("ops@example.net") as remote:
stdout, stderr, exitcode = remote.exec_command("hostname", shell=False)
print(str(stdout).strip())
finally:
local.close(strict=True)
SSHScript loads system host keys and rejects unknown or changed host keys by default. Add the server key to known_hosts before connecting. See Connections, Authentication, and Bastions for authentication, trusted bootstrap, and nested connections.
Compose privileged contexts
The object returned by connect() owns the remote command context:
from getpass import getpass
from sshscript import Session
local = Session()
try:
with local.connect("ops@example.net") as remote:
password = getpass("sudo password: ")
with remote.sudo(password=password) as root:
root.exec_command("id -u")
print(str(root.stdout).strip())
finally:
local.close(strict=True)
The inner context exits the privileged shell; the outer context closes the remote Session. Host policy still controls whether sudo is permitted.
Automate an interactive program
from sshscript import Session
session = Session()
try:
with session.enter(
"python3",
prompt=">>>",
exit="quit()",
) as console:
console.input("print('hello from SSHScript')")
console.expect("hello from SSHScript")
finally:
session.close(strict=True)
Use enter() for REPLs, database tools, password prompts, and long-running programs. See Interactive Programs with Session.enter() for prompt matching and safe password input.
Transfer files
File transfer uses the active connected Session:
import os
from sshscript import Session
os.makedirs("./reports", exist_ok=True)
local = Session()
try:
with local.connect("ops@example.net") as remote:
remote.upload(
"./release.tar.gz",
"/var/tmp/releases/",
makedirs=True,
)
remote.download(
"/var/tmp/report.txt",
"./reports/",
)
finally:
local.close(strict=True)
See Uploading and Downloading Files for path and overwrite behavior.
Run a .spy file
The CLI runs exactly one regular Python or .spy file:
sshscript maintenance.spy
Larger programs use ordinary Python imports, including scoped peer .spy imports where necessary, rather than multiple CLI paths. See CLI and Environment Variables.
Optional Dollar syntax
Inside a .spy file, the same session model has a concise notation:
with $.connect("ops@example.net"):
$hostname
print($.stdout.strip())
In v3.1, one $ handles both direct commands and shell features. The former $$ form is deprecated. See the Dollar Syntax Reference if this notation suits the project.
Last Updated: 2026-09-26 16:11:31