---
title: Job
sidebar_label: Job
sidebar_position: 1
---

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lium.io/llms.txt
> Use this file to discover all available pages before exploring further.

<!-- Generated by scripts/generate_sdk_reference.py. Do not edit directly. -->

# Job

```python
from lium.sdk import Job
```

Defined in `lium.sdk.jobs`.

A command started in the background on a pod.

Returned by [`run_background()`](/developers/sdk/reference/client/lium#run_background) and [`job()`](/developers/sdk/reference/client/lium#job). Every method
opens one short SSH session; nothing is cached, so the answers reflect the
pod as it is now.

```python
Job(
    client: lium.sdk.client.Lium,
    pod: lium.sdk.models.PodInfo,
    *,
    name: str,
    pid: int,
    command: str,
    job_dir: str = '/workspace/logs'
)
```

## Attributes

| Name | Type | Description |
| --- | --- | --- |
| `pod` |  |  |
| `name` |  |  |
| `pid` |  |  |
| `command` |  |  |
| `job_dir` |  |  |
| `log_path` |  |  |
| `pid_file` |  |  |
| `id_file` |  |  |
| `exit_file` |  |  |
| `cmd_file` |  |  |

## Methods

| Method | Description |
| --- | --- |
| [`to_dict`](#to_dict) |  |
| [`status`](#status) | \{"state": "running" \| "exited" \| "gone", "exitcode": int \| None\}. |
| [`is_running`](#is_running) |  |
| [`poll`](#poll) | None while the job runs, its exit code once it ended (subprocess.Popen.poll semantics). |
| [`wait`](#wait) | Block until the job ends and return its exit code. |
| [`wait_for_port`](#wait_for_port) | Block until TCP port accepts connections inside the pod. |
| [`logs`](#logs) | The job's combined stdout/stderr; the last tail lines when given. Empty if no log yet. |
| [`kill`](#kill) | Send signal to the job's whole process group. Returns whether anything received it. |

### to_dict

```python
def to_dict() -> Dict[str, Any]:
```

### status

```python
def status() -> Dict[str, Any]:
```

``\{"state": "running" | "exited" | "gone", "exit_code": int | None\}``.

``gone`` means the process is not alive and left no exit code — killed as
a group, or the pod restarted underneath it (a PID that another process
took after the restart does not count as alive: the ``.id`` file decides).
A job with no ``.id`` file (started before the file existed) is ``gone`` too.

### is_running

```python
def is_running() -> bool:
```

### poll

```python
def poll() -> Optional[int]:
```

``None`` while the job runs, its exit code once it ended (``subprocess.Popen.poll`` semantics).

**Raises:**
 - **LiumError:**  the process is gone without an exit code.

### wait

```python
def wait(timeout: Optional[float] = None, *, poll_interval: float = 5) -> int:
```

Block until the job ends and return its exit code.

**Raises:**
 - **TimeoutError:**  still running after ``timeout`` seconds (the job keeps running).
 - **LiumError:**  the process vanished without writing an exit code.

### wait_for_port

```python
def wait_for_port(
    port: int,
    timeout: float = 600,
    *,
    host: str = '127.0.0.1',
    poll_interval: float = 3
) -> None:
```

Block until TCP ``port`` accepts connections inside the pod.

The probe and the job's liveness are read in the same SSH round trip, and
the job's state is judged first: a server that crashed while loading fails
this call at once, with its exit code and the last log lines, instead of
burning the whole timeout — even when another process holds the port. A
job that exited 0 with the port open counts as ready (it forked its
server and left).

**Raises:**
 - **LiumError:**  the job ended (or vanished) before the port answered.
 - **TimeoutError:**  the port did not answer within ``timeout`` seconds.

### logs

```python
def logs(tail: Optional[int] = None) -> str:
```

The job's combined stdout/stderr; the last ``tail`` lines when given. Empty if no log yet.

### kill

```python
def kill(signal: str = 'TERM') -> bool:
```

Send ``signal`` to the job's whole process group. Returns whether anything received it.

Nothing is signalled when the PID no longer belongs to the job (the pod
restarted and another process took the number) or when the job has no
``.id`` file to check it against; the call returns ``False``.
