Session.enter()
Session.enter() opens an interactive program in the current Session. Use it for REPLs, database clients, password-driven commands, and long-running programs that receive input after they start. It works locally, over SSH, and inside su() or sudo() contexts.
Enter 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")
print(str(console.stdout))
finally:
session.close(strict=True)
input(text) sends a line. expect(pattern) waits for matching output. exit= specifies what SSHScript sends when the context ends.
The full Session signature is:
session.enter(
command,
expect=None,
password=None,
exit=None,
shell=True,
get_pty=True,
prompt=None,
)
shell=True and get_pty=True make most interactive applications behave as they do in a terminal. Set get_pty=False only when the application works without a terminal and a PTY causes a problem.
Wait for prompts and results
with session.enter(
"python3 -i",
exit="quit()",
get_pty=False,
) as console:
console.expect("python")
console.input("print('READY')")
console.expect("READY", stderr=False)
expect(pattern, timeout=None, stdout=True, stderr=True, silent=False) checks stdout and stderr by default. Disable one stream when a match must come from the other.
If a program changes its prompt after starting:
with session.enter("python3", exit="quit()") as console:
console.set_prompt(">>>")
console.input("print('prompt set')")
console.expect("prompt set")
Answer an initial password prompt
expect= and password= can handle a prompt during context setup:
from getpass import getpass
password = getpass("sudo password: ")
with session.enter(
"sudo python3",
expect="password",
password=password,
prompt=">>>",
exit="quit()",
) as console:
console.input("print('privileged Python')")
console.expect("privileged Python")
Keep secrets out of command arguments and source files. Use getpass for an interactive run or retrieve the secret from the deployment environment’s secret manager.
Supply a password to mysqldump
Some commands are not interactive shells but still stop for terminal input. For example, mysqldump -p asks for its password only after the process has started. enter() can wait for that prompt and send the password without placing it on the command line.
import os
import shlex
from getpass import getpass
from sshscript import Session
database_password = getpass("MySQL password: ")
remote_dump = "/tmp/application-backup.sql"
os.makedirs("./downloads", exist_ok=True)
dump_command = (
"mysqldump -u backup -p --all-databases > "
+ shlex.quote(remote_dump)
)
local = Session()
try:
with local.connect("backup@example.net") as remote:
with remote.enter(dump_command) as process:
process.expect("password")
process.input(database_password)
remote.exec_command(
"test -s " + shlex.quote(remote_dump),
shell=True,
)
if remote.exitcode != 0:
raise RuntimeError("mysqldump did not create a non-empty file")
remote.download(remote_dump, "./downloads/")
finally:
local.close(strict=True)
The redirection requires shell mode, which is the default for enter(). mysqldump finishes after receiving the password, so this case does not need an exit= action. Verify the file before downloading or restoring it, remove the remote staging file when finished, and use a more specific prompt pattern when the client has localized output.
End the program deliberately
| Value | Typical use |
|---|---|
exit="quit()" | Python or another REPL with a quit command |
exit=chr(4) | Ctrl-D / EOF for Python and Unix consoles |
exit=chr(3) | Ctrl-C for tail -F, tcpdump, or similar programs |
exit=None | A command that finishes on its own |
For a continuous producer, combine enter() with Streaming Output.
Nest remote and privileged Sessions
from sshscript import Session
local = Session()
try:
with local.connect("ops@example.net") as remote:
with remote.sudo(password=password) as root:
with root.enter(
"python3",
prompt=">>>",
exit=chr(4),
) as console:
console.input("import os; print(os.getuid())")
console.expect("0")
finally:
local.close(strict=True)
Each inner context returns to its predecessor when it exits.
Optional Dollar syntax
Inside a .spy file:
with $.enter("python3", prompt=">>>", exit="quit()"):
$.input("print(2 + 3)")
$.expect("5")
The shorthand $print(2 + 3) also sends a line while $.enter() is active. Use $.input() when explicit interaction is easier to maintain.
Last Updated: 2026-09-14 18:02:02