# System and processes

---

# System and processes

_Peios / Using Peios / Peiosutils / System and processes_

> The commands that report on the system, run other commands in a managed way, signal processes, and work with time, terminals, and storage.

This topic gathers the commands that deal with the **running system** rather than with files: reading the time, asking what hardware and system you are on, launching another command under some constraint, signalling a process, working with the terminal.

## The commands

**Time**

| Command | Purpose |
|---|---|
| [`date`](/peios/using-peios/peiosutils/system-and-processes/date.md) | Print — or set — the system date and time. |
| [`sleep`](/peios/using-peios/peiosutils/system-and-processes/sleep.md) | Pause for a given length of time. |
| [`uptime`](/peios/using-peios/peiosutils/system-and-processes/uptime.md) | Show how long the system has been running. |

**Running a command under a constraint**

| Command | Purpose |
|---|---|
| [`timeout`](/peios/using-peios/peiosutils/system-and-processes/timeout.md) | Run a command, and kill it if it runs too long. |
| [`nohup`](/peios/using-peios/peiosutils/system-and-processes/nohup.md) | Run a command so it survives the terminal closing. |
| [`nice`](/peios/using-peios/peiosutils/system-and-processes/nice.md) | Run a command at an adjusted scheduling priority. |
| [`stdbuf`](/peios/using-peios/peiosutils/system-and-processes/stdbuf.md) | Run a command with altered stream buffering. |
| [`chroot`](/peios/using-peios/peiosutils/system-and-processes/chroot.md) | Run a command with a different directory as its root. |

**Signalling processes**

| Command | Purpose |
|---|---|
| [`kill`](/peios/using-peios/peiosutils/system-and-processes/kill.md) | Send a signal to a process. |

**System identity and capacity**

| Command | Purpose |
|---|---|
| [`uname`](/peios/using-peios/peiosutils/system-and-processes/uname.md) | Print system information — the OS, the kernel, the machine. |
| [`arch`](/peios/using-peios/peiosutils/system-and-processes/arch.md) | Print the machine's hardware architecture. |
| [`hostname`](/peios/using-peios/peiosutils/system-and-processes/hostname.md) | Display — or set — the system's host name. |
| [`hostid`](/peios/using-peios/peiosutils/system-and-processes/hostid.md) | Print the host's numeric identifier. |
| [`nproc`](/peios/using-peios/peiosutils/system-and-processes/nproc.md) | Print how many processor cores are available. |

**Who you are**

| Command | Purpose |
|---|---|
| [`whoami`](/peios/using-peios/peiosutils/system-and-processes/whoami.md) | Print the name of the user a process is running as. |
| [`id`](/peios/using-peios/peiosutils/system-and-processes/id.md) | Print the user and group identity of a process, or of a named user. |
| [`groups`](/peios/using-peios/peiosutils/system-and-processes/groups.md) | Print the groups a user belongs to. |
| [`logname`](/peios/using-peios/peiosutils/system-and-processes/logname.md) | Print the login name of the user a process is running as. |

These report the **projection** of a token onto POSIX user and group numbers, which is what Linux programs see. The numbers grant nothing on their own — [`id`](/peios/using-peios/peiosutils/system-and-processes/id.md) explains what they can and cannot say, and [`token`](/peios/security-fundamentals/tokens/token-command.md) shows the identity underneath them.

**Storage and terminal**

| Command | Purpose |
|---|---|
| [`sync`](/peios/using-peios/peiosutils/system-and-processes/sync.md) | Flush cached writes out to persistent storage. |
| [`tty`](/peios/using-peios/peiosutils/system-and-processes/tty.md) | Print the name of the terminal on standard input. |
| [`stty`](/peios/using-peios/peiosutils/system-and-processes/stty.md) | Display or change terminal settings. |

## A note on changing the system

Most commands here only *report*. A few can *change* the running system — `date` can set the clock, `hostname` can set the host name. Changing system-wide state is a privileged operation: it succeeds only for a caller whose token holds the right to do it, and is refused otherwise. The pages for those commands say so where it applies, and [Privileges](/peios/security-fundamentals/privileges/overview.md) is the full picture.

## Where to start

[`uname`](/peios/using-peios/peiosutils/system-and-processes/uname.md) answers "what am I running on?". [`kill`](/peios/using-peios/peiosutils/system-and-processes/kill.md) is the one to read carefully — sending the wrong signal to the wrong process is a quick way to lose work.

---

# date

_Peios / Using Peios / Peiosutils / System and processes_

> Print or set the system date and time, with a flexible output format.

`date` prints the current date and time. With the right option, it can also *set* the system clock, display some other moment, or format a date however you need.

```
date [options] [+format]
```

```
$ date
Sun 17 May 2026 14:32:08 BST
$ date +%Y-%m-%d
2026-05-17
```

## Formatting the output

A `+format` argument controls the output. The format string is printed literally, except for `%` sequences, each of which is replaced by a piece of the date. The common ones:

| Sequence | Is replaced by |
|---|---|
| `%Y` `%m` `%d` | Year, month, day. |
| `%H` `%M` `%S` | Hour, minute, second. |
| `%F` | The full date — same as `%Y-%m-%d`. |
| `%T` | The time — same as `%H:%M:%S`. |
| `%A` `%a` | Weekday name, full and abbreviated. |
| `%B` `%b` | Month name, full and abbreviated. |
| `%j` | Day of the year. |
| `%s` | Seconds since 1970-01-01 UTC. |
| `%z` `%Z` | Numeric and named time zone. |
| `%%` | A literal `%`. |

The full set is long; `date --help` lists every sequence with an example.

## Displaying a different moment

| Option | Effect |
|---|---|
| `-d`, `--date=STRING` | Show the time described by `STRING` — `"yesterday"`, `"next Friday"`, `"@1615432800"` — instead of now. |
| `-r`, `--reference=FILE` | Show `FILE`'s last modification time. |
| `-f`, `--file=DATEFILE` | Like `-d`, but once for each line of `DATEFILE`. |
| `-u`, `--universal` | Work in Coordinated Universal Time (UTC) rather than the local zone. |

## Standard formats

| Option | Output |
|---|---|
| `-I`, `--iso-8601[=FMT]` | ISO 8601 — `FMT` is `date`, `hours`, `minutes`, `seconds`, or `ns`. |
| `-R`, `--rfc-email` | The format used in email headers. |
| `--rfc-3339=FMT` | RFC 3339 — `FMT` is `date`, `seconds`, or `ns`. |

## Setting the clock

| Option | Effect |
|---|---|
| `-s`, `--set=STRING` | Set the system clock to the time described by `STRING`. |

Setting the clock changes state for the whole system, so it is a **privileged** operation — it succeeds only for a caller whose token carries the right to set the time, and is refused otherwise. See [Privileges](/peios/security-fundamentals/privileges/overview.md).

## Exit status

| Code | Meaning |
|---|---|
| `0` | The date was printed or set. |
| `1` | An invalid date or format, or the clock could not be set. |

---

# sleep

_Peios / Using Peios / Peiosutils / System and processes_

> Pause for a given length of time.

`sleep` does nothing for a given length of time, then exits.

```
sleep number[suffix]...
```

```
$ sleep 5          # pause for five seconds
$ sleep 1.5h       # pause for an hour and a half
```

It is used to space things out — a pause between the steps of a script, a delay before a retry.

## Specifying the duration

`number` may be a whole number or a fraction. A `suffix` gives the unit:

| Suffix | Unit |
|---|---|
| `s` | Seconds. This is the default if no suffix is given. |
| `m` | Minutes. |
| `h` | Hours. |
| `d` | Days. |

Given more than one argument, `sleep` waits for the **sum** of them — `sleep 1m 30s` pauses for ninety seconds.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The full time elapsed. |
| `1` | A bad argument, or `sleep` was interrupted before the time was up. |

---

# timeout

_Peios / Using Peios / Peiosutils / System and processes_

> Run a command and kill it if it is still running after a time limit.

`timeout` runs a command with a time limit. If the command finishes in time, nothing special happens. If it is still running when the limit is reached, `timeout` kills it.

```
timeout [options] duration command...
```

```
$ timeout 30s slow-fetch https://example.com
```

It is the guard against a command that might hang — a network fetch, a script that could loop forever.

## The duration

`duration` is a number with an optional unit suffix: `s` for seconds (the default), `m` for minutes, `h` for hours, `d` for days. A duration of `0` disables the limit.

## How the command is stopped

When the limit is reached, `timeout` sends the command a `TERM` signal — a request to shut down cleanly. A well-behaved command stops there. A command that ignores `TERM` keeps running, which is what `-k` is for.

| Option | Effect |
|---|---|
| `-s`, `--signal=SIGNAL` | Send `SIGNAL` instead of `TERM` when the limit is reached. |
| `-k`, `--kill-after=DURATION` | If the command is *still* running `DURATION` after the first signal, send it a `KILL` signal — which cannot be ignored. |
| `--preserve-status` | Exit with the command's own status even when it timed out. |
| `--foreground` | Allow the command to keep reading from the terminal; do not time out the command's own children. |
| `-v`, `--verbose` | Report to standard error whenever a signal is sent. |

## Exit status

`timeout` passes through the command's exit status when the command finishes on its own. Otherwise:

| Code | Meaning |
|---|---|
| (command's own) | The command finished within the limit. |
| `124` | The command timed out. |
| `125` | `timeout` itself failed. |
| `126` | The command was found but could not be run. |
| `127` | The command was not found. |
| `137` | The command was ended by a `KILL` signal. |

---

# nohup

_Peios / Using Peios / Peiosutils / System and processes_

> Run a command so it keeps running after the terminal closes — and how the nohup.out it creates is secured.

`nohup` runs a command so that it **survives the terminal closing**. Normally, when a terminal session ends, the system sends a hangup signal to the commands running under it, and they stop. A command started with `nohup` ignores that signal and keeps running.

```
nohup [options] command [arg]...
```

```
$ nohup long-build &
```

It is how you start something that needs to outlast your session — a long build, a background job — without it being killed the moment you disconnect.

## Where the output goes

A command run with `nohup` is meant to outlive the terminal, so `nohup` cannot leave its streams attached to one. It redirects any stream that is still connected to a terminal:

- **Standard input**, if it is a terminal, is replaced with an empty source — the command reads nothing.
- **Standard output**, if it is a terminal, is appended to a file named `nohup.out` in the current directory. If that file cannot be opened there, `nohup` falls back to `nohup.out` in your home directory.
- **Standard error**, if it is a terminal, is sent to wherever standard output now goes.

Streams that you have already redirected yourself — to a file, or a pipe — are left as they are.

## How nohup.out is secured

When `nohup` has to **create** `nohup.out`, that file is a new file and needs a [security descriptor](/peios/security-fundamentals/security-descriptors/overview.md). `nohup` does not let it inherit one from the directory. It creates `nohup.out` with a deliberate, locked descriptor: **full access for the owner, and no one else**.

The reasoning is that `nohup.out` captures whatever the command writes, which the person running it has not chosen to share. A file that appears as a side effect should not be more open than its creator intended — so `nohup` gives it the safe default of owner-only, rather than whatever the surrounding directory would have handed down.

| Option | Effect |
|---|---|
| `--sddl=SDDL` | Create `nohup.out` with the security descriptor given as an SDDL string, instead of the owner-only default. |

`--sddl` only matters when `nohup` actually creates the file. If `nohup.out` already exists, `nohup` appends to it and leaves its existing security alone.

## Exit status

When `nohup` runs a command, it exits with **that command's** status once it finishes. The exception is a failure in `nohup` itself:

| Code | Meaning |
|---|---|
| (command's own) | The command ran; this is its exit status. |
| `125` | `nohup` could not set things up — it could not detach from the terminal, or could not open `nohup.out` anywhere. The command was not run. |

---

# nice

_Peios / Using Peios / Peiosutils / System and processes_

> Run a command at an adjusted scheduling priority.

`nice` runs a command at an adjusted **scheduling priority** — making it more, or less, willing to give the processor up to other work.

```
nice [options] [command [arg]...]
```

```
$ nice -n 15 big-batch-job
```

With no command, `nice` prints the current niceness.

## Niceness

A process has a *niceness* — a number from **-20** to **19**:

- A **high** niceness (toward 19) means the process is "nicer" to others — it yields the processor readily. Good for background work that should not get in the way.
- A **low** niceness (toward -20) means the process is favoured — it gets the processor more often.

By default `nice` adds **10** to the niceness, making the command run in the background more gracefully.

| Option | Effect |
|---|---|
| `-n`, `--adjustment=N` | Add `N` to the niceness instead of 10. `N` may be negative. |

Raising a command's niceness — running it *lower* priority — is always allowed. Lowering the niceness, to claim a *higher* priority than normal, is a privileged request and may be refused; when it is, `nice` warns and runs the command at the priority it was permitted.

## Exit status

When `nice` runs a command, it exits with **that command's** status. The exception is a failure in `nice` itself:

| Code | Meaning |
|---|---|
| (command's own) | The command ran; this is its exit status. |
| `0` | No command was given; the niceness was printed. |
| `125` | `nice` itself failed — for example, a bad adjustment value. |
| `126` | The command was found but could not be run. |
| `127` | The command was not found. |

---

# kill

_Peios / Using Peios / Peiosutils / System and processes_

> Send a signal to a process.

`kill` sends a **signal** to a process. Despite the name, a signal is not always fatal — it is a message, and some signals ask a process to do something other than stop.

```
kill [options] pid...
```

```
$ kill 4821                 # ask process 4821 to terminate
$ kill -KILL 4821           # force it to stop
```

A `pid` is a process identifier — the number a running process is known by.

## Signals

With no option, `kill` sends `TERM` — a polite request to shut down, which a well-behaved process honours by cleaning up and exiting. The signals you will use most:

| Signal | Meaning |
|---|---|
| `TERM` | Terminate. The default — a request to stop cleanly. |
| `KILL` | Stop immediately. Cannot be caught or ignored, so it cannot be refused — but the process gets no chance to clean up. The last resort. |
| `HUP` | Hang up. Conventionally tells a long-running service to reload its configuration. |
| `INT` | Interrupt — the signal a terminal sends on Ctrl-C. |
| `STOP` / `CONT` | Suspend the process / resume a suspended one. |

| Option | Effect |
|---|---|
| `-s`, `--signal=SIGNAL` | Send `SIGNAL` instead of `TERM`. |
| `-SIGNAL` | A shorthand — `-KILL` or `-9` both send `KILL`. |
| `-l`, `--list` | List the signal names. |
| `-L`, `--table` | List the signals as a table of numbers and names. |

Use `KILL` only when `TERM` has failed. A process killed outright cannot save its work or release what it holds.

## Exit status

| Code | Meaning |
|---|---|
| `0` | Every signal was sent. |
| `1` | A signal could not be sent — a process that does not exist, or one you are not permitted to signal. |

---

# uname

_Peios / Using Peios / Peiosutils / System and processes_

> Print system information — the operating system, the kernel, and the machine.

`uname` prints information about the system you are running on.

```
uname [options]
```

```
$ uname
Peios
$ uname -a
Peios host-01 1.4.0 #1 SMP 2026-05-10 x86_64 Peios
```

With no option, `uname` prints the operating-system name — `Peios`.

## What each option prints

| Option | Prints |
|---|---|
| `-s` | The kernel name. |
| `-o` | The operating-system name — `Peios`. |
| `-n` | The node name — the name this system is known by on the network. |
| `-r` | The kernel release. |
| `-v` | The kernel version. |
| `-m` | The machine's hardware name (its architecture). |
| `-p` | The processor type. |
| `-i` | The hardware platform. |
| `-a` | Everything — equivalent to `-mnrsvo`. |

Give several options and `uname` prints those fields, in a fixed order, on one line.

## The operating system is Peios

`uname -o`, and the operating-system field of `uname -a`, report `Peios`. This is the field a script should check when it wants to confirm what system it is on.

For the machine architecture alone, [`arch`](/peios/using-peios/peiosutils/system-and-processes/arch.md) is the shorter command — it prints exactly what `uname -m` prints.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The requested information was printed. |
| `1` | The system information could not be read. |

---

# arch

_Peios / Using Peios / Peiosutils / System and processes_

> Print the machine's hardware architecture.

`arch` prints the machine's hardware architecture — the kind of processor the system runs on.

```
arch
```

```
$ arch
x86_64
```

That is the whole command. It takes no options and prints a single name.

`arch` prints exactly what [`uname -m`](/peios/using-peios/peiosutils/system-and-processes/uname.md) prints. It exists as a short, obvious name for the one question "what architecture is this?" — convenient in a script that picks an architecture-specific path.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The architecture was printed. |
| `1` | The architecture could not be determined. |

---

# hostname

_Peios / Using Peios / Peiosutils / System and processes_

> Display or set the system's host name.

`hostname` displays the system's **host name** — the name the system is known by.

```
hostname [options] [name]
```

```
$ hostname
host-01.example.com
```

## What is displayed

By default `hostname` prints the fully qualified name. These options narrow or change what is shown:

| Option | Prints |
|---|---|
| `-f`, `--fqdn` | The fully qualified domain name — the full `host.domain` form. This is the default. |
| `-s`, `--short` | The short host name only — the part before the first dot. |
| `-d`, `--domain` | The DNS domain part only. |
| `-i`, `--ip-address` | The network address (or addresses) the host name resolves to. |

## Setting the host name

Given a `name` argument, `hostname` sets the system's host name to it.

```
$ hostname host-02
```

Changing the host name changes state for the whole system, so it is a **privileged** operation — it succeeds only for a caller whose token carries the right to do it, and is refused otherwise. See [Privileges](/peios/security-fundamentals/privileges/overview.md).

## Exit status

| Code | Meaning |
|---|---|
| `0` | The host name was displayed or set. |
| `1` | A failure — the name could not be read, set, or resolved. |

---

# hostid

_Peios / Using Peios / Peiosutils / System and processes_

> Print the host's numeric identifier.

`hostid` prints the host's numeric identifier, in hexadecimal.

```
hostid
```

```
$ hostid
007f0100
```

The host id is a number associated with the system. It takes no options and prints one value.

Where [`hostname`](/peios/using-peios/peiosutils/system-and-processes/hostname.md) gives the system's *name* — meant to be read by people — `hostid` gives a numeric value, used by software that wants a machine identifier in a fixed numeric form.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The host id was printed. |

---

# nproc

_Peios / Using Peios / Peiosutils / System and processes_

> Print how many processor cores are available.

`nproc` prints the number of processor cores available.

```
nproc [options]
```

```
$ nproc
8
```

By default it prints the number of cores available **to the current process** — which can be fewer than the machine has, if the process has been restricted to a subset. It is most often used to decide how many parallel jobs to run.

## Options

| Option | Effect |
|---|---|
| `--all` | Print the number of cores the *whole system* has, ignoring any restriction on the current process. |
| `--ignore=N` | Subtract `N` from the count — for leaving some cores free rather than using every one. |

The environment variables `OMP_NUM_THREADS` and `OMP_THREAD_LIMIT`, if set, also bound the number `nproc` reports.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The count was printed. |
| `1` | An option value was invalid. |

---

# uptime

_Peios / Using Peios / Peiosutils / System and processes_

> Show how long the system has been running.

`uptime` shows how long the system has been running, along with a few related figures.

```
uptime [options]
```

```
$ uptime
 14:32:08  up 6 days,  3:21,  load average: 0.18, 0.24, 0.21
```

The default line packs in three things:

- the **current time**;
- how long the system has been **up**;
- the **load average** — a rough measure of how busy the system has been over the last 1, 5, and 15 minutes.

If you know `uptime` from other systems you may be expecting a count of logged-in users between the uptime and the load average. Peios does not print one. That count comes from a login database (`utmp`) that Peios does not keep — logon sessions are a [KACS](/peios/security-fundamentals/access-decisions/overview.md) concept, and the tooling to report them is not built yet. Rather than print a figure that would always read `0 users`, the field is left out until it can be answered honestly.

## Options

| Option | Effect |
|---|---|
| `-p`, `--pretty` | Show just the uptime, in a readable phrase — `up 6 days, 3 hours, 21 minutes`. |
| `-s`, `--since` | Show the date and time the system started, rather than how long ago that was. |

## Exit status

| Code | Meaning |
|---|---|
| `0` | The uptime was printed. |
| `1` | The boot time could not be read. |

---

# sync

_Peios / Using Peios / Peiosutils / System and processes_

> Flush cached writes out to persistent storage.

`sync` flushes cached writes to persistent storage.

```
sync [options] [file...]
```

```
$ sync
```

When a program writes to a file, the data does not always reach the physical device immediately — for speed, the system holds recent writes in memory and writes them out a little later. `sync` forces that pending data out *now*, so that what is on the device matches what programs have written.

It is the command to run before doing something that should not lose recent writes — before powering off by hand, or before removing storage.

## Options

With no argument, `sync` flushes everything. The options narrow it:

| Option | Effect |
|---|---|
| `file...` | Flush only the given files, rather than everything. |
| `-d`, `--data` | For the given files, flush only the file data, not metadata that does not need it. |
| `-f`, `--file-system` | Flush the entire file system that contains each given file. |

## Exit status

| Code | Meaning |
|---|---|
| `0` | The flush completed. |
| `1` | A named file could not be reached. |

---

# tty

_Peios / Using Peios / Peiosutils / System and processes_

> Print the name of the terminal connected to standard input.

`tty` prints the name of the terminal connected to standard input.

```
tty [options]
```

```
$ tty
/dev/pts/3
```

If standard input is not a terminal — because it has been redirected from a file or a pipe — `tty` prints `not a tty` instead.

That second behaviour is the useful one: a script can run `tty` to find out whether it is being run interactively or as part of a pipeline, and behave accordingly.

## Options

| Option | Effect |
|---|---|
| `-s`, `--silent` | Print nothing; report the answer only through the exit status. |

## Exit status

| Code | Meaning |
|---|---|
| `0` | Standard input is a terminal. |
| `1` | Standard input is not a terminal. |
| `2` | A usage error. |

---

# stty

_Peios / Using Peios / Peiosutils / System and processes_

> Display or change terminal settings.

`stty` displays and changes the settings of a terminal — how it handles input, output, and special keys.

```
stty [options] [setting...]
```

```
$ stty
speed 38400 baud; line = 0;
-brkint -imaxbel iutf8
```

Run with no arguments, `stty` prints the settings that differ from the usual defaults. Given `setting` arguments, it changes them.

## Viewing the settings

| Option | Effect |
|---|---|
| `-a`, `--all` | Print *every* setting, in a readable layout. |
| `-g`, `--save` | Print every setting in a single compact line — a form that can be fed straight back to `stty` to restore them. |

The `-g` form is how you save and restore a terminal's state:

```
$ saved=$(stty -g)      # capture the current state
$ stty -echo            # ...change something...
$ stty "$saved"         # restore exactly what was saved
```

## Changing the settings

A `setting` argument turns something on or off, or assigns a value. A few common ones:

| Setting | Effect |
|---|---|
| `echo` / `-echo` | Show / hide typed characters — `-echo` is how a password prompt hides input. |
| `rows N` / `cols N` | Tell the terminal its size. |
| A number | Set the connection speed (baud rate). |

`stty` has a large catalog of settings; `stty -a` shows them all with their current values.

## Choosing the terminal

| Option | Effect |
|---|---|
| `-F`, `--file=DEVICE` | Operate on `DEVICE` instead of the terminal on standard input. |

## Exit status

| Code | Meaning |
|---|---|
| `0` | The settings were printed or changed. |
| `1` | A setting was invalid, or the terminal could not be accessed. |

---

# stdbuf

_Peios / Using Peios / Peiosutils / System and processes_

> Run a command with altered buffering on its standard streams.

`stdbuf` runs a command with **altered buffering** on its standard streams.

```
stdbuf [options] command...
```

```
$ slow-producer | stdbuf -oL grep error
```

## What buffering is, and why change it

A program usually does not write each piece of output the instant it is produced — it collects output in a buffer and writes it in batches, which is faster. The cost is *delay*: when a program's output feeds a pipe, that batching can hold lines back for a long time, which is unhelpful when you are watching a pipeline live.

`stdbuf` lets you override that batching for a command, so its output appears sooner.

## Setting the buffering

| Option | Stream |
|---|---|
| `-i`, `--input=MODE` | Standard input. |
| `-o`, `--output=MODE` | Standard output. |
| `-e`, `--error=MODE` | Standard error. |

`MODE` is one of:

| MODE | Buffering |
|---|---|
| `0` | Unbuffered — every write goes out immediately. |
| `L` | Line-buffered — output is flushed at the end of each line. Not valid for input. |
| a size | Fully buffered with a buffer of that many bytes. Accepts suffixes — `K`, `M`, and so on. |

`-oL` — line-buffered output — is the common case: it makes a command in a pipeline emit each line as it is finished.

## A limitation

`stdbuf` adjusts the *default* buffering. A command that manages its own stream buffering will override what `stdbuf` sets, and some commands do not use buffered streams at all — for those, `stdbuf` has no effect.

## Exit status

When `stdbuf` runs a command, it exits with **that command's** status. The exception is a failure in `stdbuf` itself:

| Code | Meaning |
|---|---|
| (command's own) | The command ran; this is its exit status. |
| (a `stdbuf`-level error code) | The command could not be started. |

---

# chroot

_Peios / Using Peios / Peiosutils / System and processes_

> Run a command with a different directory as its root.

`chroot` runs a command with a **different directory as its root** — its `/`. Inside that command, the chosen directory *is* the top of the file system, and nothing above it can be named or reached.

```
chroot newroot [command [arg]...]
```

```
$ chroot /mnt/system /bin/sh
```

With a `command`, `chroot` changes the root to `newroot` and runs the command there. With no command, it starts an interactive shell.

## What it does

A process normally sees the whole file system, rooted at the real `/`. After `chroot`, the named directory becomes that process's `/`: a path like `/etc/config` inside the command resolves to `newroot/etc/config`, and there is no path that reaches outside `newroot` at all.

It is used to work inside another installed system — repairing or configuring a system image by entering it — and to run a command confined to a known subtree.

For the command to be usable, `newroot` must already contain what the command needs: the command's own executable, and whatever libraries and files it depends on, all present *under* `newroot`.

## Options

| Option | Effect |
|---|---|
| `--skip-chdir` | Do not change the working directory to `/` after changing the root. Permitted only when `newroot` is the current `/`. |

## A privileged operation

Changing a process's root directory is a **privileged** operation. `chroot` succeeds only for a caller whose token carries the right to do it, and is refused otherwise — the ability to redraw a process's view of the file system is not something every principal holds. See [Privileges](/peios/security-fundamentals/privileges/overview.md).

## Exit status

`chroot` exits with the command's own status once it finishes. Otherwise:

| Code | Meaning |
|---|---|
| `125` | `chroot` itself failed — for example, `newroot` is not a directory. |
| `126` | The command was found but could not be run. |
| `127` | The command was not found. |

---

# whoami

_Peios / Using Peios / Peiosutils / System and processes_

> Print the name of the user a process is running as.

`whoami` prints the name of the user the calling process is running as.

```
whoami
```

```
$ whoami
jack
```

It takes no arguments. It is the same answer as `id -un`, which is all it has ever been.

## Where the name comes from

The name is resolved from the process's effective user ID, which is a projection of the [token's](/peios/security-fundamentals/tokens/overview.md) user SID. The lookup goes to the authority — there is no `/etc/passwd` to read — and comes back as the principal's canonical name. [Resolving names](/peios/security-fundamentals/managing-local-principals/resolving-names.md) is the full picture.

The name is the principal's; the *number* it was looked up by is not what grants anything. If you want the identity access is actually decided against, `id -Z` prints the SID.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The name was printed. |
| `1` | The user ID could not be resolved to a name. |

A failure here usually means the authority could not be reached rather than that the account is missing — identity does not resolve before the authority is running, which is the correct answer rather than a gap.

---

# id

_Peios / Using Peios / Peiosutils / System and processes_

> Print the user and group identity of a process, or of a named user.

`id` prints who a process is: its user, its primary group, the groups it belongs to, and its security context.

```
id [options] [USER]...
```

```
$ id
uid=5001000(jack) gid=5000513(Users) groups=5000513(Users),100(Everyone),101(Authenticated Users),1544(Administrators) context=S-1-5-21-1004336348-1177238915-682003330-1000:High
```

With no argument it reports the calling process. Given one or more users, it reports on those instead.

## The numbers are projections

This is the thing to understand before reading `id`'s output on Peios.

The `uid=` and `gid=` numbers are **projections** of the token's [SIDs](/peios/security-fundamentals/identity/sids.md). They are real, stable, and exactly what Linux programs see and what filesystems store — but **nothing is decided by them**. Access is decided against the SID the number was projected from, by the [access check](/peios/security-fundamentals/access-decisions/overview.md). A number here grants nothing.

That distinction is not academic, because the projection cannot carry everything a token holds:

- Groups whose SIDs are deliberately unnumbered — `Interactive`, `Network`, `Batch`, `Service` — **cannot appear at all**. They are what make a rule like "network logons cap at Low" expressible, and they have no gid by design.
- A group's **attributes** have nowhere to go. A deny-only group, which can block access through a deny entry but grant nothing through an allow entry, appears in `groups=` looking exactly like an ordinary membership.
- The **integrity level** and the **logon session** have no number either.

So two tokens can project to identical numbers and mean different things. The clearest case is a [filtered token](/peios/security-fundamentals/tokens/restricted-tokens.md): it carries the same user SID and the same group numbers as the token it came from, and differs only in attributes the projection cannot express.

That is why the default line ends with a **`context=`** field.

## The context field

`context=` is the authoritative half: the user SID access is actually decided against, and the integrity level.

```
context=S-1-5-21-1004336348-1177238915-682003330-1000:High
```

The integrity level is part of it precisely because the SID alone does not separate an elevated token from its filtered counterpart — both carry the same user SID, and the level is what differs.

If you know `id` from another Unix, this is the field that carries the SELinux context there. Peios has no SELinux; its security context is the [token](/peios/security-fundamentals/tokens/overview.md), so that is what the field holds.

`context=` is omitted when a user is named rather than the calling process — a named user has no token here to read — and when `POSIXLY_CORRECT` is set, so a caller that asked for the POSIX shape still gets it.

For the whole token rather than this summary, use [`token`](/peios/security-fundamentals/tokens/token-command.md).

## Options

| Option | Effect |
|---|---|
| `-u`, `--user` | Print only the effective user ID. |
| `-g`, `--group` | Print only the effective group ID. |
| `-G`, `--groups` | Print only the group IDs, space-separated. |
| `-n`, `--name` | With `-u`, `-g` or `-G`, print names instead of numbers. |
| `-r`, `--real` | With `-u`, `-g` or `-G`, print the real ID rather than the effective one. |
| `-z`, `--zero` | Separate entries with NUL rather than whitespace. Not allowed in the default format. |
| `-Z`, `--context` | Print only the security context. |
| `-p` | A readable, multi-line form. |
| `-P` | Print as a password-file entry. |
| `-a` | Ignored; accepted for compatibility. |
| `-A` | Not applicable on Peios — see below. |

`-n` and `-r` need one of `-u`, `-g` or `-G`; they do not change the default format.

### `-r` means something different here

On other Unixes the real/effective split is the setuid boundary. On Peios a setuid bit does not change a token, so that boundary does not exist. What the split tracks instead is [impersonation](/peios/security-fundamentals/impersonation/overview.md): the real IDs come from the process's own token, the effective ones from whatever token is in force.

`id` never impersonates, so in practice it reports the same either way and the `euid=`/`egid=` fields never appear. That is not a fault — there is genuinely nothing differing to report.

### `-A` is not applicable

`-A` reports BSD audit session properties. Peios audits through [its own event system](/peios/security-fundamentals/auditing/overview.md) and keeps no BSM session, so `-A` says so rather than silently succeeding at nothing.

## `id -G` and `id -G <yourself>` differ

Asking about yourself and asking about your *name* are two different questions here, and they give different answers:

- **`id -G`** reads your process's credential — the projection of your **token's** group set, which includes the groups the authority added when the token was minted: `Everyone`, `Authenticated Users`, and any `Administrators`-style aliases.
- **`id -G jack`** looks the name up through the [principal store](/peios/security-fundamentals/managing-local-principals/resolving-names.md), which returns **recorded** memberships only. The stapled groups are not recorded anywhere, because membership in them is a rule rather than a stored fact — so they do not come back.

On other systems these two differ only in the order they print. Here the second list is genuinely shorter, and neither is wrong.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The identity was printed. |
| `1` | A user could not be found, an option combination was rejected, or the context could not be read. |

---

# groups

_Peios / Using Peios / Peiosutils / System and processes_

> Print the groups a user belongs to.

`groups` prints the groups a user belongs to.

```
groups [USERNAME]...
```

```
$ groups
Users Everyone Authenticated Users Administrators

$ groups jack
jack : Users Administrators
```

With no argument it reports the calling process. Given names, it reports on those.

## Those two answers are both correct

The example above is not a mistake, and it is the thing worth knowing about this command on Peios.

**`groups`** reads the calling process's credential — the projection of its [token's](/peios/security-fundamentals/tokens/overview.md) group set. That set includes the groups the authority *stapled on* when the token was minted: `Everyone`, `Authenticated Users`, and the like.

**`groups jack`** looks the name up through the [principal store](/peios/security-fundamentals/managing-local-principals/resolving-names.md), which returns **recorded** memberships — the ones something actually wrote down.

The stapled groups are not recorded anywhere, because membership in them is a **rule**, not a stored fact. Everyone is in `Everyone`; nothing needs to record it, and nothing can enumerate it. So they appear in the first answer and not the second.

On other Unixes these two forms differ only in the order they print.

## What cannot appear

Both forms are lossy in the same way, and unavoidably so — a group can only be listed if it has a group ID, and some deliberately do not:

- `Interactive`, `Network`, `Batch` and `Service` are **unnumbered on purpose**. They describe *how* you signed in rather than who you are, which is what lets a rule like "network logons cap at Low" be written at all. You are in `Interactive` at the console and not over the network, so there is no static answer to record.
- A group's **attributes** are not representable. A deny-only group — one that can block access through a deny entry but grant nothing through an allow entry — is printed exactly like an ordinary membership.

[`token groups`](/peios/security-fundamentals/tokens/token-command.md) is the lossless view, with every SID and its attributes.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The groups were printed. |
| `1` | A named user could not be found, or the group list could not be read. |

A group ID with no name is printed as the bare number and sets the exit status, rather than stopping the listing.

---

# logname

_Peios / Using Peios / Peiosutils / System and processes_

> Print the login name of the user a process is running as.

`logname` prints the login name the calling process runs under.

```
logname
```

```
$ logname
jack
```

It takes no arguments.

## Login name, not current name

`logname` and [`whoami`](/peios/using-peios/peiosutils/system-and-processes/whoami.md) look like the same command and answer slightly different questions.

`whoami` reports the **effective** identity — whoever the process is acting as right now. `logname` reports the **login** identity: the principal the process's own token is for, regardless of any token it has since taken on. When a process is [impersonating](/peios/security-fundamentals/impersonation/overview.md) a client, `whoami` follows the impersonation and `logname` does not.

Most of the time nothing is impersonating and the two agree.

If you know `logname` from another Unix, note that it answers this from the token rather than from a login-record file. There is no `utmp` on Peios — nothing writes one — so the traditional source does not exist. The token is the record of who a process is, and it is a better one: it cannot drift from the identity access is actually checked against, because it *is* that identity.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The login name was printed. |
| `1` | No login name could be determined. |

---

# token

_Peios / Using Peios / Peiosutils / System and processes_

> The token command inspects and manipulates tokens — reading a token's contents, adjusting it, duplicating and restricting it, and driving impersonation.

`token` is the command-line tool for working with **tokens** directly. It reads a token's contents, adjusts it, produces derived tokens, and drives impersonation — the low-level operations this topic describes, exposed at a shell.

```
token subcommand [target] [arguments]
```

```
$ token                       # one-line summary of your own token
$ token show --all             # every field of your own token
$ token privs --pid 4821       # the privileges on process 4821's token
```

`token` is a direct, debug-level tool. Day to day you do not inspect tokens by hand — the system does. `token` is for diagnosing an access problem, for understanding what identity a process is really running under, and for building and testing identity setups. Run with no subcommand, it prints a one-line summary of your own token.

## Choosing which token

Almost every subcommand operates on a token, and these flags choose which one. With none, the target is your own.

| Flag | Target |
|---|---|
| `--self` | Your own token. The default. |
| `--real` | Your **primary** token specifically, rather than the effective one — relevant when your thread is impersonating. |
| `--pid PID` | The primary token of process `PID`. |
| `--tid TID` | The impersonation token of thread `TID` (used with `--pid`). |
| `--peer SOCK_FD` | The peer's captured token on a connected socket — see [Peer tokens](/peios/security-fundamentals/impersonation/peer-tokens.md). |

Reading another process's token is itself access-controlled: it succeeds only with the right authority over that process.

## Inspecting a token

### `show`

`token show` prints a token's contents. It is the default — bare `token` is `token show --short`.

| Flag | Effect |
|---|---|
| `--short` | A one-line summary. |
| `--all` | Every query class — the fullest dump. |

### Field accessors

Each of these prints one part of a token, for when you want just that piece:

| Subcommand | Prints |
|---|---|
| `user` | The user SID — who the token is. |
| `owner` | The default owner SID. |
| `group` | The primary group SID. |
| `groups` | The group list. |
| `privs` | The privileges, with their enabled state. |
| `caps` | The capabilities. |
| `claims` | The user and device claims. |
| `integrity` | The integrity level. |
| `logon` | The logon type and logon SID. |
| `source` | What minted the token. |
| `origin` | The originating session for a derived token. |
| `stats` | Token statistics — IDs, timestamps, the modification counter. |
| `default-dacl` | The token's default DACL. |

### `query`

`token query CLASS` performs a raw read of a single named token-info class and prints the result as JSON — the lowest-level inspection route, for tooling.

## Changing a token

### `adjust`

`token adjust` mutates a token in place:

| Form | Changes |
|---|---|
| `adjust privs NAME=STATE …` | Enable, disable, or remove privileges. `STATE` is `enabled`, `disabled`, or `removed`. |
| `adjust groups IDX=STATE …` | Enable or disable groups by their list index. |
| `adjust default --dacl SDDL` | Replace the token's default DACL. Also `--owner-idx` / `--group-idx`. |
| `adjust session ID` | Replace the token's session id. |

### `restrict`

`token restrict` produces a [restricted token](/peios/security-fundamentals/tokens/restricted-tokens.md) — a more limited variant of a token.

| Flag | Effect |
|---|---|
| `--drop-privs MASK\|NAMES` | Privileges to drop. |
| `--deny IDX,…` | Group indices to mark deny-only. |
| `--restrict SID,…` | The restricting SIDs to apply. |

### `duplicate`

`token duplicate` (alias `dup`) copies a token, optionally changing its `--type` (primary or impersonation), its impersonation `--level`, or its `--access` mask.

### `link` and `linked`

`token link` joins two tokens as an elevation pair — a full token and its filtered counterpart — given their file descriptors and a session id. `token linked` shows a token's elevation-linked counterpart, if it has one. See [Elevation](/peios/security-fundamentals/tokens/elevation.md).

## Impersonation

| Subcommand | Effect |
|---|---|
| `impersonate` | Begin impersonating the target token on the calling thread. With a trailing `-- command …`, run that command under the impersonating token. |
| `revert` | Drop any active impersonation on the calling thread. |

See [Impersonation](/peios/security-fundamentals/impersonation/overview.md) for the model these drive.

## Creating tokens

| Subcommand | Effect |
|---|---|
| `create SPEC` | Create a token from a binary token-spec (`SPEC` is a file, or `-` for standard input). |
| `install SPEC` | Create a token from a spec and install it as the caller's primary token. |

Creating and installing tokens is a privileged operation, reserved for the components that legitimately mint identity.

## Output options

| Flag | Effect |
|---|---|
| `--raw` | Render SIDs in raw `S-1-…` form only. |
| `--label` | Render SIDs as their labels where known, falling back to raw. |
| `--json` | Emit JSON instead of human-readable output. |

## `token` and the inspection surfaces

`token` is the convenient front-end. Underneath, it reads the same kernel surfaces and rules described in [Inspecting tokens](/peios/security-fundamentals/inspecting/tokens.md) — that page covers the query mechanism, the access rules for reading another process's token, and what cannot be inspected.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The operation succeeded. |
| `1` | A usage error. |
| non-zero | The operation failed — no such target, an access denial, or a bad spec. |

---

# logonse

_Peios / Using Peios / Peiosutils / System and processes_

> The logonse command lists logon sessions and their processes, creates and destroys them, and sets a process's mitigation flags.

`logonse` is the command-line tool for **logon sessions** — the kernel's records of authentication events that this topic describes. It lists the active sessions, shows which processes belong to one, creates and destroys sessions, and (as a related low-level job) sets a process's mitigation flags.

```
logonse subcommand [arguments]
```

```
$ logonse list
$ logonse show 4711
```

`logonse` is a low-level administrative and debugging tool. It requires a subcommand: `list`, `show`, `create`, `destroy`, or `psb`.

## Listing sessions

### `logonse list`

Enumerates the active logon sessions, and the process IDs in each.

```
$ logonse list
session 0     pids: [1, 2, 14, 22]
session 4711  pids: [820, 844, 901]
```

### `logonse show`

Shows the process IDs that belong to one session.

```
$ logonse show 4711
```

### A caveat on list and show

There is no syscall that enumerates logon sessions, and `logonse` does not read the kernel's sessions file (whose SD restricts it to Administrators and SYSTEM). `logonse list` and `logonse show` work by walking the running processes and reading each one's token to find which session it belongs to. That has two consequences worth knowing:

- It is **best-effort**. A session that has no running process — held alive only by a token file descriptor somewhere — will not appear, because there is no process to find it through.
- It is a **snapshot under change**. Processes start and exit while the walk runs, so the result is a close approximation of the moment, not a locked one.

For routine "who is signed in" use this is fine. For an authoritative listing, the kernel's own sessions surface — described in [Inspecting sessions](/peios/security-fundamentals/inspecting/sessions.md) — is the source of record.

## Creating and destroying sessions

### `logonse create`

Creates a new logon session for a user, described by a logon type, an authentication-package name, and the user's SID.

```
$ logonse create --logon-type interactive --auth-package Negotiate --user-sid S-1-5-21-...-1001
```

| Flag | Meaning |
|---|---|
| `--logon-type TYPE` | The kind of logon: `interactive`, `network`, `batch`, `service`, `network-cleartext`, or `new-credentials`. |
| `--auth-package STR` | The name of the authentication package that vouched for the logon. |
| `--user-sid SID` | The user the session belongs to, as an `S-1-…` SID or an SDDL alias such as `BA`. |

On success `logonse` prints the new session's id. Creating a session is a **privileged** operation — minting authentication records is reserved for the components that legitimately do so.

> [!NOTE]
> The tool builds the kernel's binary session spec from these fields for you. The underlying [wire format](/peios/using-peios/wire-formats-reference/token-and-session-specs.md) is unchanged; only the command-line surface is typed.

### `logonse destroy`

Destroys a session — but only an **empty** one, with no tokens still referencing it.

```
$ logonse destroy 4711
```

A session with live tokens cannot be destroyed this way; its tokens must go first. See [Session lifecycle](/peios/security-fundamentals/logon-sessions/lifecycle.md).

## Setting process mitigation flags

### `logonse psb`

`logonse psb` sets the **mitigation flags** in a process's Process Security Block.

```
$ logonse psb --pid 4821 --mitigations 0x1c0
```

| Flag | Meaning |
|---|---|
| `--pid PID` | The process to act on. |
| `--mitigations MASK` | The mitigation bitmask to apply, in hexadecimal or decimal. |

This subcommand is about process hardening rather than logon sessions — it lives in `logonse` because both deal with low-level per-process kernel state. For what the mitigation flags mean and how they behave, see [Process mitigations](/peios/security-fundamentals/process-mitigations/overview.md).

## Output options

| Flag | Effect |
|---|---|
| `--json` | Emit JSON instead of human-readable output. Accepted by every subcommand. |

## Exit status

| Code | Meaning |
|---|---|
| `0` | The operation succeeded. |
| `1` | A usage error, or the operation failed. |
