Start a background process

server = machine.commands.run(
    "python3 -m http.server 8080 --bind 0.0.0.0",
    shell=True,
    cwd="/workspace",
    background=True,
)
print(server.pid)
nullspace machine exec mch_123 \
  --shell "python3 -m http.server 8080 --bind 0.0.0.0" --background
curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/exec" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"command": "python3 -m http.server 8080 --bind 0.0.0.0", "shell": true, "cwd": "/workspace", "background": true}'
Without callbacks, background commands start through the REST exec endpoint and return once the guest process has a PID. The command continues running inside the machine until it exits, is killed, or the machine is paused or destroyed.

Fetch logs and stop

logs = machine.commands.get_logs(server.pid)
print(logs.stdout)

machine.commands.kill(server.pid)
result = server.wait()
print(result.exit_code)
const logs = await machine.commands.getLogs(pid);
console.log(logs.stdout);

await machine.commands.kill(pid);
nullspace machine process logs mch_123 1234
nullspace machine process kill mch_123 1234
curl -X GET "${NULLSPACE_API_URL}/v1/machines/mch_123/processes/1234/logs" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}"

curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/processes/1234/kill" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}"
Background command objects also expose kill():
server.kill()
BackgroundCommand also supports:
  • server.get_logs() to fetch stdout, stderr, interleaved output, and optional exit_code.
  • server.wait() to block until exit. If there is no live WebSocket attached, it polls the process list and then fetches logs.
  • server.disconnect() to close a live stream without killing the process.
  • Iteration over (stdout_chunk, stderr_chunk, None) tuples; this polls logs for new output.

Live background output

Pass callbacks with background=True when you want the process to keep running and stream output immediately:
def on_stdout(chunk: str) -> None:
    print(chunk, end="")

server = machine.commands.run(
    "python3 -u worker.py",
    shell=True,
    background=True,
    on_stdout=on_stdout,
)
server.disconnect()
nullspace machine process attach mch_123 1234
This path uses the exec WebSocket to start the process and attach a reader to the returned PID. Live background streaming is not a plain REST call: it runs over GET /v1/machines/{id}/ws?channel=exec, so there is no curl equivalent. Use the REST GET /v1/machines/{id}/processes/{pid}/logs endpoint to fetch captured output after the process has started.

Use with preview URLs

url = machine.get_url(8080)
print(url)
const url = await machine.getUrl(8080);
console.log(url);
nullspace machine url mch_123 8080
curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/host" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"port": 8080}'
For web servers, bind to 0.0.0.0 inside the machine so preview URLs can reach the process.