> ## Documentation Index
> Fetch the complete documentation index at: https://e2b-docs-background-codegen-example.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Running commands in background

To run commands in background, pass the `background` option to the `commands.run()` method. This will return immediately and the command will continue to run in the sandbox.
You can then later kill the command using the `commands.kill()` method.

<CodeGroup>
  ```js JavaScript & TypeScript highlight={7} theme={null}
  import { Sandbox } from 'e2b'

  const sandbox = await Sandbox.create()

  // Start the command in the background
  const command = await sandbox.commands.run('echo hello; sleep 10; echo world', {
    background: true,
    onStdout: (data) => {
      console.log(data)
    },
  })

  // Kill the command
  await command.kill()
  ```

  ```python Python highlight={6} theme={null}
  from e2b import Sandbox

  sandbox = Sandbox.create()

  # Start the command in the background
  command = sandbox.commands.run('echo hello; sleep 10; echo world', background=True)

  # Get stdout and stderr from the command running in the background.
  # You can run this code in a separate thread or use command.wait() to wait for the command to finish.
  for stdout, stderr, _ in command:
      if stdout:
          print(stdout)
      if stderr:
          print(stderr)

  # Kill the command
  command.kill()
  ```
</CodeGroup>

## Reconnect to a background command

A background command keeps running inside the sandbox even after the SDK disconnects. Because sandboxes are long-lived, you can start a long task in one process, return immediately, and reconnect from a completely different process later to wait for it and collect the result.

This is a common pattern for kicking off slow work (code generation, a build, a data job) from a serverless function or API handler: you start the command, store the sandbox ID and process ID, and let a later request pick the work back up.

The example below starts a long-running command (`run-codegen` here is a placeholder for your own binary or script) and returns the two identifiers you need to reconnect: the sandbox ID and the command's process ID (`pid`).

<CodeGroup>
  ```js JavaScript & TypeScript highlight={11} theme={null}
  import { Sandbox } from 'e2b'

  // Start the task and return right away with the IDs needed to reconnect.
  async function startGeneration(prompt: string) {
    const sandbox = await Sandbox.create({ timeoutMs: 15 * 60_000 })

    // Redirect output to a file so it survives after we disconnect.
    const handle = await sandbox.commands.run(
      `run-codegen ${JSON.stringify(prompt)} > /home/user/gen.log 2>&1`,
      { background: true, timeoutMs: 0 }
    )

    return { sandboxId: sandbox.sandboxId, pid: handle.pid }
  }

  // From a separate process, reconnect and wait for the result.
  async function collectGeneration(sandboxId: string, pid: number) {
    const sandbox = await Sandbox.connect(sandboxId)
    const handle = await sandbox.commands.connect(pid)
    await handle.wait()
    return sandbox.files.read('/home/user/gen.log')
  }
  ```

  ```python Python highlight={9} theme={null}
  import shlex
  from e2b import Sandbox

  # Start the task and return right away with the IDs needed to reconnect.
  def start_generation(prompt: str):
      sandbox = Sandbox.create(timeout=15 * 60)

      # Redirect output to a file so it survives after we disconnect.
      handle = sandbox.commands.run(
          f"run-codegen {shlex.quote(prompt)} > /home/user/gen.log 2>&1",
          background=True,
          timeout=0,
      )

      return {"sandbox_id": sandbox.sandbox_id, "pid": handle.pid}


  # From a separate process, reconnect and wait for the result.
  def collect_generation(sandbox_id: str, pid: int):
      sandbox = Sandbox.connect(sandbox_id)
      handle = sandbox.commands.connect(pid)
      handle.wait()
      return sandbox.files.read("/home/user/gen.log")
  ```
</CodeGroup>

A few details make this reliable across processes:

* **Redirect output to a file.** The streamed `stdout`/`stderr` from a background command is only delivered to the process that started it. Writing to a file (`> /home/user/gen.log 2>&1`) gives you durable output you can read after reconnecting.
* **Disable the command timeout.** `timeoutMs: 0` (`timeout=0` in Python) removes the command's connection time limit so it isn't killed while running long. Set the sandbox `timeoutMs`/`timeout` high enough to outlast the whole job (15 minutes above). See [sandbox persistence](/docs/sandbox/persistence) if you need it to survive even longer.
* **Persist the IDs.** Return or store `sandboxId` and `pid` (for example in a database or the response of an API call). They are all a later process needs to call `Sandbox.connect()` and `commands.connect()`.

`commands.connect(pid)` reattaches to the running command, and `handle.wait()` blocks until it finishes. If you don't know the `pid`, you can look up running processes with `sandbox.commands.list()`.
