Run one command on another machine
pb exec runs an exact command on a machine you name and hands back what it printed and how it exited. It is the piece you put in
scripts, CI jobs and agent tools.
$ pb exec studio -- systemctl is-active api
active
$ echo $?
0 $ pb exec studio --cwd /srv/api -- git pull --ff-only
Already up to date. $ pb studio -- uptime - 1
The remote program's output, and its exit code as your exit code.
- 2
--cwdsets where it runs. - 3
The short form, for typing by hand.
Use it in scripts
A non-zero exit there is a non-zero exit here, so set -e works. Output and errors stay separate.
pb wait blocks until a machine is ready; pb ping says whether the path is direct or relayed.
#!/bin/sh
set -e
# Wait until the build machine answers, at most five minutes.
pb wait build-01 --for transport
# Run the tests there. A failing test fails this script.
pb exec build-01 --cwd /src/app --timeout 20m -- make test
# Ship the result and restart the service on the server.
pb send ./dist/app.tar.gz --to web-01
pb exec web-01 -- sudo systemctl restart app Commands
pb exec <machine> [flags] -- <argv...>
-- <argv...> | Everything after -- is run exactly as given. No shell on the way, so nothing is expanded or split twice. |
|---|---|
--cwd /path | Absolute working directory on the remote machine. |
--env NAME=value | One extra variable for this run. Repeatable. Your ENV values are already there. |
--timeout 20m | Ends the remote command when the time is up. |
--pty | Gives the command a terminal, for programs that insist on one. |
--json | Output, errors and the exit status as JSON Lines events (paperboat.exec-event/v1). |
When it cannot run, it says why
Scripts break on vague errors. These are the cases pb tells apart.
The machine is offline
A plain message naming the machine. Nothing was started.
A secret could not be delivered
If the machine should receive ENV values and cannot, the command does not start half-configured. You get the specific ENV error.
The outcome is unknown
If the connection is lost after the command started, pb reports that it may have run. With --json, that is a field you can branch on.
Questions
How is this different from ssh host command?
No keys, no open port, and no shell quoting: the arguments after -- arrive as the exact argument list. You also get a real timeout, JSON output, and a clear answer when the outcome is unknown.
How do I use a pipe or a redirect on the remote side?
Run a shell yourself: pb exec studio -- sh -c 'journalctl -u api | tail -n 50'. Pipes on your side of the command work as usual, and stdin is passed through.
What if the machine reboots or the network dies mid-command?
pb says the outcome is unknown instead of guessing. It never reports success for a command it could not confirm, so your script can decide whether running it again is safe.
Can a command run for a long time?
Yes. Commands that run for more than half an hour return their final output and exit code. For work you want to watch or come back to, use a terminal session.
Who is allowed to run commands on a machine?
You, on your own machines. For anyone else, exec is one capability you grant per machine, separate from terminal or SSH. See teams and access.
Related
Start with the machine in front of you
Install Paperboat here, then on a second machine. Free for personal use, no card needed.
$ curl -fsSL https://get.pprbt.dev/install | bash > irm https://get.pprbt.dev/install.ps1 | iex