system-control 1 administrator commands nosh
system-control systemctl process system control jobs, sending commands to the system manager and service manager
`system-control` command arguments or options `systemctl` command arguments or options

## Description

`system-control` takes a subcommand as command that instructs it on what to do.

For limited systemd compatibility, it is also available as `systemctl`. Not all subcommands are supported, nor is placing subcommand options before the command.

The compatibility shims for upstart, SunOS, and others are provided by telinit 8. `system-control` provides no upstart or SunOS compatibility itself, and its various subcommands differ in meaning from most of the subcommands for upstart initctl 8 and SunOS svcadm 8.

It operates in one of two modes, controlled by the --user command line option:

- In "system" mode it operates on system-wide state and services. It potentially communicates with a System Manager process, which must be process #1 and which it expects to recognize the same signals as system-manager 1 does. It potentially communicates with a Service Manager process, such as service-manager 1 via a local domain socket at `/run/service-manager/control` and via the control/status API of the individual services.

- In "user" mode it operates on per-user state and services. It potentially communicates with a Session Manager process, which again it expects to recognize the same signals as per-user-manager 1 does. It potentially communicates with a Service Manager process, such as service-manager 1 via a local domain socket at `/run/user/$USER/service-manager/control` and via the control/status API of the individual services.

Services are defined by directories known as bundle directories. What they contain and where and how they are located is documented in service-bundle 5.

## Subcommands

### System information subcommands

`system-control` version

For compatibility with uses of `initctl`, the `version` subcommand displays the (compiled-in) version of the toolset. It does not contain the string "upstart".

### System control subcommands

`system-control` reboot -f--force `system-control` halt -f--force `system-control` powercycle -f--force `system-control` poweroff -f--force `system-control` emergency `system-control` rescue `system-control` normal `system-control` init --user -o --update -s --single -b --emergency -a -f -z string runlevel(s)

Those subcommands communicate with the system manager to change system state. `system-control` sends a signal to process #1 using the kill 2 system call. It will fail if it does not have the necessary privileges for sending a signal to that process.

The signals for each subcommand:

command | signal on FreeBSD and NetBSD | signal on Linux | signal on OpenBSD
--- | --- | --- | ---
`halt` | `SIGUSR1` | `SIGRTMIN + 3` | unsupported
`halt` -f | `SIGRTMIN + 13` | `SIGRTMIN + 13` | unsupported
`poweroff` | `SIGUSR2` | `SIGRTMIN + 4` | unsupported
`poweroff` -f | `SIGRTMIN + 14` | `SIGRTMIN + 14` | unsupported
`reboot` | `SIGINT` | `SIGRTMIN + 5` | SIGINT
`reboot` -f | `SIGRTMIN + 15` | `SIGRTMIN + 15` | SIGTSTP
`powercycle` | `SIGWINCH` | `SIGRTMIN + 7` | unsupported
`powercycle` -f | `SIGRTMIN + 17` | `SIGRTMIN + 17` | unsupported
`emergency` | `SIGRTMIN + 2` | `SIGRTMIN + 2` | unsupported
`rescue` | `SIGRTMIN + 10` then `SIGRTMIN + 1` | `SIGRTMIN + 10` then `SIGRTMIN + 1` | unsupported
`normal` | `SIGRTMIN + 10` then `SIGRTMIN + 0` | `SIGRTMIN + 10` then `SIGRTMIN + 0` | unsupported
`init` 2 3 4 5 m auto | `SIGRTMIN + 10` then `SIGRTMIN + 0` | `SIGRTMIN + 10` then `SIGRTMIN + 0` | unsupported
`init` 1 S s single | `SIGRTMIN + 10` then `SIGRTMIN + 1` | `SIGRTMIN + 10` then `SIGRTMIN + 1` | unsupported
`init` -s | `SIGRTMIN + 2` | `SIGRTMIN + 10` then `SIGRTMIN + 1` | unsupported
`init` -b | unsupported | `SIGRTMIN + 2` | unsupported
`init` b emergency | `SIGRTMIN + 2` | `SIGRTMIN + 2` | unsupported
`init` H h | SIGUSR1 | `SIGRTMIN + 3` | `SIGUSR1`
`init` C c | `SIGWINCH` | `SIGRTMIN + 7` | unsupported
`init` 0 | `SIGUSR2` | `SIGRTMIN + 4` | SIGUSR2
`init` 6 | `SIGINT` | `SIGRTMIN + 5` | SIGINT

OpenBSD lacks the ability to send real-time signals.

Exactly how the system power cycles, powers off, halts, reboots, switches to normal, emergency, or rescue modes, and so forth is entirely up to whatever is running as process #1, which is expected to be in charge of system state. These subcommands do nothing except send the signals to command the system manager. They do not directly enact any system state change themselves. In part this is because that would open up the possibility of the service manager killing the process that was (partway through) enacting the state changes, if a state change happened to affect the service running the `system-control` command.

The --force command line argument is used within the various targets and is intended to cause the system manager to proceed directly to the finalization action.

The `init` subcommand is spawned by system-manager 8 and per-user-manager 8 as their initial action. They pass it the command line arguments that they themselves were invoked with. As such, its command line syntax is modelled on what boot loaders and kernels tend to supply to process #1, which is a largely undocumented and non-standardized mixture of old-style runlevels and options.

In normal and rescue modes it sends two signals to process #1, instituting a two-phase initialization sequence similar to the `FILESYSTEMS` milestone mechanism in BSD operating systems. The first phase, the `sysinit` target, is expected to initialize as much of the system as necessary so that the second phase, the `normal` or `rescue` target, can find all service and target bundles, including those that are not on the root filesystem.

There is no q runlevel. This is deliberate. Its use case is running `telinit` q after updating `/etc/ttys` or `/etc/inittab`. Any script that is updating those files and then expecting the system manager to re-read them is not targetting the correct configuration mechanisms, and is in error. `/etc/inittab` was obsolete as of AT&T Unix System 5 Release 4.

LILO, the FreeBSD loader 8, GRUB, and others may cause -a or -f options to be passed. Their meanings are non-standard, largely or even wholly undocumented, inconsistent across platforms and toolsets, considered obsolete in their original forms, and without application here. The -z option is a dummy space-taker that is also used by such systems. All three options are ignored. The --update command line option is reserved for future use.

### job subcommands

`system-control` start activate --colour --verbose --pretend names `system-control` stop deactivate --colour --verbose --pretend names `system-control` isolate --colour --verbose --pretend names `system-control` reset --colour --verbose --pretend names

These subcommands process one or more jobs, sending messages to the service manager to start or to stop one or more services. Jobs processing tries to ensure that service dependencies are correctly maintained and processed. To control services directly and individually without regard for dependencies, use service-control 8.

The --verbose command line option causes information about actions taken and blocked/unblocked services to be written to standard error as jobs are processed. If the standard error is a terminal, `system-control` uses whatever it can find via the TerminalCapabilities 3 library to display various parts of the output in different colours, highlighting different events in different colours. The --colour command line option tells it to do this unconditionally, even if its standard error is not a terminal. The --pretend command line option tells it to only pretend that it is taking actions, and not actually take them.

The `reset` command is intended to be used by package installer programs. It is translated into either `start` or `stop` according to whether the service is enabled or disabled; and can be thought of, if one likes, as "reset to however the service is configured to be at bootstrap". This allows package installers to remain in blissful ignorance of whether a service should be started or stopped after installing the package for it. Instead, the package installer simply executes the `preset` command and then the `reset` command and the service is started or stopped according to whatever the administrator has chosen.

The `isolate` subcommand exists for compatibility, and is equivalent to `start`. Avoid using it.

#### Jobs and actions

Jobs comprise a set of actions. Each action is a ndividualstart or a stop command to the control API of a service/target as would be directly issued by service-control 8. Jobs are composed by starting with an action on a named service, and then following information in its service bundles to related services and targets, and in their service bundles in turn. The service bundles also determine the order in which the actions are taken.

A start action simply requests that the service manager bring the service/target to the "running" state, if it isn't already there. A stop action, however, is more complex. Initially it requests that the service manager bring the service/target to the "stopped" state (if it isn't already there). However, if that does not happen within 60 seconds, it requests that the service manager send the `SIGKILL` signal to the service/target.

### service autoboot configuration subcommands

`system-control` enable names `system-control` disable names `system-control` preset --prefix prefix --no-system --no-rcconf --rcconf-file filename --ttys --dry-run names

These subcommands enable or disable one or more services or targets, so that they do or do not automatically start when one of the standard targets is started and automatically stop when the shutdown standard target is started.

Each service bundle specifies a (symbolically linked) list of target bundles in its `wanted-by/` directory. Usually these will be the `workstation`, `server`, `users`, or `multi-user` standard targets. For each bundle, enabling the service involves symbolically linking its bundle directory into the target bundle's `wants/` list, and disabling the service involves removing that link.

Each service bundle also specifies a (symbolically linked) list of target bundles in its `stopped-by/` directory. Usually these will be the `shutdown` standard target. For each bundle, enabling the service involves symbolically linking its bundle directory into the target bundle's `conflicts/` and `after/` lists, and disabling the service involves removing those links.

The `preset` command is intended to be used by package installer programs. It is translated into either `enable` or `disable` according to a system/administrator-supplied preset flag (unless the --dry-run command line argument is used, causing it to take no actual action). This allows package installers to remain in blissful ignorance of whether a service should be enabled or disabled after installing the package for it. Instead, the package installer simply executes the `preset` command and the service is set to whatever enabled or disabled status the administrator has chosen.

The service/socket/target that is preset is prefix name, with prefix specifiable via the --prefix command line argument.

Preset information can be taken from one of several sources:

- (unless the --no-system command line option is set) systemd and system-manager preset information given in `*.preset` files. There are different sets of files for per-user and system-wide service management.

  - System-wide preset files are located in the following directories:

    1. `/usr/local/etc/system-control/presets/`

    2. `/etc/system-control/presets/`

    3. `/etc/systemd/system-preset/`

    4. `/usr/local/lib/systemd/system-preset/`

    5. `/usr/local/share/system-control/presets/`

    6. `/usr/pkg/etc/system-control/presets/`

    7. `/usr/share/system-control/presets/`

    8. `/usr/lib/systemd/system-preset/`

    9. `/lib/systemd/system-preset/`

  - Per-user preset files are located in the following directories:

    1. `/usr/local/etc/system-control/user-presets/`

    2. `/etc/system-control/user-presets/`

    3. `/etc/systemd/user-preset/`

    4. `/usr/local/lib/systemd/user-preset/`

    5. ``$HOME`/.config/system-control/presets/`

    6. `/usr/local/share/system-control/user-presets/`

    7. `/usr/pkg/etc/system-control/user-presets/`

    8. `/usr/share/system-control/user-presets/`

    9. `/usr/lib/systemd/user-preset/`

    10. `/lib/systemd/user-preset/`

  Contrary to its doco, systemd has four places for system-wide/user-level preset files, which form part of these lists. In addition to those locations, `preset` looks in extra directories where systemd presets can be overridden by system-control-specific information; allowing a system administrator or package writer to preset things one way for systemd and another way for the `preset` command. These extra directories follow the more conventional scheme of `/etc`, `/usr/share`, and `/usr/pkg/etc` for administrator-set, operating-system-set, and application-software-set stuff.

  As with systemd, earlier preset directories override later ones; the contents of files with lexically earlier names override the contents of files with lexically later names; and the default state, in the absence of an explicit preset, is "enabled". Directives are matched against prefix name.

- (unless the --no-rcconf command line option is set) rc.conf 5 preset information, specifically the `name_enable` variable, interpreting the values `true`, `1`, `yes`, and `on` as enable, and any other values (including specifically `false`, `0`, `no`, and `off`) as disable.

  By default in system-wide mode the `/etc/defaults/rc.conf`, `/etc/rc.conf`, and `/etc/rc.conf.local` files are used, but the --rcconf-file command line option overrides that list with the single replacement file filename. The default for per-user mode is the ``$HOME`/.config/rc.conf` file.

  The variable names are matched against just name to allow one to use a main service name as name and combine it with a log service template prefix such as `cyclog@` or `s6-multilog@`, on the grounds that traditional `/etc/defaults/rc.conf`, `/etc/rc.conf`, and `/etc/rc.conf.local` contents do not make explicit provision for separate logging services.

- (if the --ttys command line option is set) `/etc/ttys` preset information, specifically the `on` and `off` flags as enable and disable, respectively. The `onifconsole` flag is also recognized and processed with reference to the currently active console device (on BSD systems only). If `/etc/ttys` does not exist, as is usually the case on Linux operating systems, all TTYs default to preset disabled.

  The terminal names are matched against just name. This allows one to use an ordinary TTY device name as name and combine it with a "templatized" bundle name prefix such as `ttylogin@`, `getty@`, or `agetty@`.

- (if the --fstab command line option is set) `/etc/fstab` preset information, specifically the `noauto` flag as disable.

  The device and directory names are matched against just name, after unescaping it. This allows one to use an ordinary device or directory name as name and combine it with a "templatized" bundle name prefix such as `mount@`, `fsck@`, `swap@`, or `dump@`. This is designed in particular for use with service bundles generated by the `convert-fstab-services` subcommand.

### service status/control subcommands

`system-control` status names `system-control` show names `system-control` find names `system-control` try-restart try-reload-or-restart condrestart force-reload names `system-control` hangup names `system-control` is-active names `system-control` is-loaded names `system-control` is-enabled names `system-control` unload-when-stopped names

`system-control` takes each of the names, searches for the corresponding service bundle directory, constructs a list of directory names, and chains to other commands with those directory names as directories arguments:

status/control commands:

subcommand | chains to
--- | ---
`status` | service-status 1 -- directories
`show` | service-show 1 -- directories
`show-json` | service-show 1 --json -- directories
`find` | ls 1 -1d -- directories
`try-restart` `try-reload-or-restart` `force-reload` `condrestart` | service-control 1 --terminate -- directories
`hangup` | service-control 1 --hangup-main -- directories
`unload-when-stopped` | service-control 1 --exit -- directories
`is-active` | service-is-up 1 -- directories
`is-loaded` | service-is-ok 1 -- directories
`is-enabled` | service-is-enabled 1 -- directories

### script conversion subcommand

For brevity, this is documented on a standalone convert-systemd-units 1 manual page.

### fstab conversion subcommand

For brevity, this is documented on standalone convert-fstab-services 1 and write-volume-service-bundles 1 manual pages.

### conversion utility subcommand

`system-control` escape --format escfmt --prefix prefix name

The `escape` subcommand takes each name and converts it using the escaping rules used in the `convert-systemd-units` subcommand. Each escaped name is written to standard output, separated from its predecessor (if any) by a space and prefixed with prefix (which is not escaped).

The --escape-format option controls the escaping algorithm, according to the value of escfmt:

`systemd`

  This is the default escaping algorithm if no escaping algorithm is specified, and is the conventional systemd one that escapes `/` and `-`.

`old-alt`

  This is an old alternative algorithm that used to be used by `convert-systemd-units`, made available here for ease of use in upgrading old account names. It is similar to the `systemd` algorithm except that it escapes almost all non-alphanumerics, encoding them in hexadecimal. (e.g. `ossec@agentd` is converted to `ossec_x40agentd`.) The escape character is `_` on most systems, except those where `\` is known to be legal in account names; it is of course itself escaped.

`alt`

  This is the current alternative algorithm used by `convert-systemd-units`, where the escaped form is suitable for an account name in the system account database. It is similar to the `old-alt` algorithm except that for a few common characters a shorter non-hexadecimal escape is used. (e.g. `ossec@agentd` is converted to `ossec_aagentd`.)

`hash`

  This abbreviates to the initial letters of each alphanumeric word, and appends a base-36 encoded DJBT33A hash of all of the alphanumeric characters. (e.g. `tinysshd-makekey` is converted to `tm-atdegy`.) Differently punctuated versions of the same string of words will have the same hash, therefore, but short strings that differ in the alphanumerics will very likely have different hashes. An accidental but helpful property of this hash choice is that names that end in a series of ascending characters (e.g. 0, 1, 2, 3, 4, 5, 6, 7) will have likewise ascending encoded hash values.

`account`

  This is the `alt` form, except when it would be over the allowable length for a system account name, less 4 (left as room for a verbatim suffix such as `-log`), when the `hash` form is used instead. (e.g. `getty@tty00` is converted to `getty_atty00`, but `mdnsresponderposix` on NetBSD is converted to `m-j1xhb0`.)

For most operating systems, where `L_cuserid` and cuserid 3 are relics, and the account database in fact has no inherent account name field length limit because it is a Berkeley DB file, the allowable length is at least 32 characters.

### Nagios plug-in subcommand

`system-control` nagios-check-service --min-seconds seconds --critical-if-below-min name

This subcommand is intended for use as a Nagios plug-in. It queries the status API in the bundle directory for service/target name.

- If the service is up for longer than seconds seconds it returns a Nagios "OK" status.

- If the service is up, but for less than seconds seconds it returns a Nagios "WARNING" status and prints a line containing the service bundle directory name. It does the same if the service is still in the process of being loaded by the service manager, or in the starting or stopping states. The --critical-if-below-min command line option changes the status returned for such up services to "CRITICAL", but does not alter the treatment of starting or stopping services.

- If the service is unexpectedly down or unloaded, if the status API reports the service running in the future (because of clock skew somewhere), or if the service is in the failing state, it returns a Nagios "CRITICAL" status and prints a line containing the service bundle directory name.

### Kernel module management subcommands

`system-control` load-kernel-module module `system-control` unload-kernel-module module

These subcommands provide a minimal operating-system-neutral kernel module loading and unloading mechanism, for use in cross-platform service bundles. They devolve to the appropriate operating system commands, which are kldload 8 and kldunload 8 on FreeBSD, modload 8 and modunload 8 on NetBSD, and modprobe 8 (without or with the --remove option) on Linux.

### service program dump subcommands

`system-control` print-service-scripts names `system-control` cat names

`system-control` takes each of the names, searches for the corresponding service bundle directory, changes to the corresponding service directory, and runs grep 1 to dump the contents of the `start`, `stop`, `run`, and `restart` files.

### service environment manipulation subcommands

`system-control` set-service-env --full name var value `system-control` print-service-env --full name var

If the name service has an environment template subdirectory named `env/` (in the format understood by envdir 1), these subcommands can be used to manipulate that template.

- `set-service-env` name var value sets var to value in the template, the change not (of course) affecting any currently running service.

- `set-service-env` name var specifies that the template unset var, the change not (of course) affecting any currently running service.

- `print-service-env` name var prints (only) the value of var from the template.

- `print-service-env` name prints the whole template as list of var=value entries.

The --full command-line option switches to an alternative format for the environment template subdirectory, as understood by envdir 1 when its option of the same name is used.

### filesystem table query subcommands

`system-control` get-mount-what where `system-control` get-mount-where what

These subcommands query the flat file table in `/etc/fstab` (see fstab 5). They fill a gap left by the getent 1 command, which has no subcommand for reading this table. Like that command, they query the on-disc administrative database of what is configured to be mounted; not the kernel's list of currently active mounts.

- For a given mount-point where `get-mount-what` prints the volume that is configured to be mounted upon it.

- For a given volume what `get-mount-where` prints the point where it is configured to be mounted.

## Author

Jonathan de Boyne Pollard