Exec¶
Run a command inside a running machine. There is one engine: a job on the guest. Scope: full. The machine must be running (otherwise 409).
SDK — sb.run()¶
Waits until the command finishes. Default timeout 120 seconds, ceiling 24 hours, enforced in the machine. The SDK talks to /execs so a proxy cannot kill the job by dropping one HTTP request.
| Field | Python | JS |
|---|---|---|
| Exit code | exit_code | exitCode |
| Output | stdout / stderr | stdout / stderr |
| Success? | ok | — |
| Hit 32 MiB cap? | truncated | truncated |
REST — the job¶
POST /v1/machines/{id}/execs → 202
GET /v1/machines/{id}/execs
GET /v1/machines/{id}/execs/{exec_id}
GET /v1/machines/{id}/execs/{exec_id}/output?stream=stdout&offset=0
DELETE /v1/machines/{id}/execs/{exec_id}
You mint exec_id. Re-sending the same id is 409, not a second run.
curl -sS -X POST "https://api.sistemo.io/v1/machines/$ID/execs" \
-H "Authorization: Bearer $SISTEMO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"exec_id":"build-1","script":"npm ci && npm run build","timeout_sec":3600}'
| Field | Default | Notes |
|---|---|---|
exec_id | required | 1–64 letters, digits, ., -, _ |
script | required | Shell command |
timeout_sec | 120 | Max 86400 (24 h) |
States: running (exit_code is null) · succeeded · failed · cancelled · expired (hit timeout_sec, exit 124) · lost (we cannot say; exit_code stays null).
Output is base64, byte offsets, 32 MiB per stream, truncated if cut. Cancel is SIGTERM, then SIGKILL after 10 s. Up to 16 jobs at once per machine — the 17th answers 409.
Notes¶
- Stopping or destroying the machine ends every job on it.
- Exec has its own rate limit; on
429, back off (Errors).
Limits¶
| Concurrent commands per machine | 16 |
| Default lifetime | 120 s |
| Maximum lifetime | 24 h |
| Output kept per stream | 32 MiB |
| Start rate | 5/s, burst 20, per account |
Starting a 17th command on one machine returns 409 — wait for one to finish, or spread the work over more machines. sb.run() counts against this too: it is a job like any other, so sixteen parallel run() calls on one machine is the ceiling.
When the machine cannot say what happened¶
A command whose machine died — rebooted, ran out of memory, was destroyed — comes back as lost, not failed.
failed means it ran and returned non-zero. lost means we can say neither that it ran nor that it did not, so it is not safe to retry blindly and not safe to treat as done.
job = sb.start("./migrate.sh")
job.wait()
if job.lost:
... # find out what actually happened before re-running
elif job.ok:
...
Use the job handle from sb.start() for this check: lost and ok are on it in every published SDK release. ⚠ exit_code stays None (null in JS) on a lost job — never 0, never -1 — and ok is false. sb.run() reports a lost command as exit_code == -1, which is a placeholder rather than a status: -1 is also something a real command can exit with, so do not branch on it.