Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bashautom

PyPI version Python versions Downloads License: MIT Tests

Persistent bash sessions for Python.

Unlike subprocess.run() which spawns a new process every time, bashautom keeps a /bin/bash process alive so state (env vars, cwd, etc.) persists across commands.

from bashautom import Session

with Session() as s:
    s.execute("cd /opt/myproject")
    s.execute("source .env")
    s.execute("export BUILD_ID=42")
    result = s.execute("make build")

Why not just subprocess / pexpect?

subprocess.run() spawns a brand new shell for every call, no memory of cd, exported vars, or sourced files between commands. pexpect solves persistence but is built around interactive prompt-matching, which is overkill (and fragile) when you just want to run commands and get clean results back.

bashautom keeps one real /bin/bash process alive and gives you structured results (stdout, exit_code, success, duration) for each command, with timeouts and streaming built in, without you writing any expect-style pattern matching.

Install

pip install bashautom

Python 3.10+, Linux/macOS only.

Usage

from bashautom import Session

with Session() as s:
    result = s.execute("echo hello")
    print(result.stdout)
    print(result.exit_code)
    print(result.success)

Timeouts

Commands can be killed without destroying the session:

with Session() as s:
    result = s.execute("sleep 60", timeout=3)
    print(result.timed_out)

    # session still works
    s.execute("echo ok")

Streaming

from bashautom.session import StreamEvent

def on_output(event: StreamEvent):
    print(f"[{event.stream}] {event.data.strip()}")

with Session() as s:
    s.execute("for i in 1 2 3; do echo $i; sleep 0.5; done", stream_callback=on_output)

Multiple sessions

from bashautom import SessionManager

with SessionManager() as mgr:
    build = mgr.create("build", cwd="/opt/project")
    deploy = mgr.create("deploy", cwd="/opt/infra")

    build.execute("make release")
    deploy.execute("./deploy.sh")

Env helpers

with Session() as s:
    s.set_env("PROJECT", "bashautom")
    print(s.get_env("PROJECT"))
    print(s.get_cwd())
    print(s.pid)
    print(s.alive)

API

Session

  • execute(command, timeout=None, stream_callback=None) - run a command, returns CommandResult
  • send_signal(sig=SIGINT) - send a signal to the running process
  • get_cwd() / get_env(var) / set_env(var, value) - shell state access
  • close() - kill the session
  • pid, alive - process info

CommandResult

  • command, stdout, stderr - what ran and what came back
  • exit_code, success, timed_out - status
  • duration - wall time in seconds

SessionManager

  • create(name, ...) / get(name) / get_or_create(name, ...) - session lifecycle
  • close(name) / close_all() - cleanup
  • names, active - introspection

License

MIT

About

Persistent bash sessions for Python - stateful shell automation with timeouts, streaming, and multi-session support.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages