systemd: getty-like service for htop
htop is an interactive process monitoring program; she is an alternative to the top program. Everyone who works behind a Linux machine on board has used it at least once: whether it was searching for a process (and its subsequent killing) or carefully monitoring the resources used.
For convenience, this program can be kept always running: in a separate terminal window, in its tabs or on some desktop. But there is another solution: run it on a fixed VT, which you can switch to at any time. The advantage of this approach is a clean environment and independence from X / terminal.
It is possible (and correct) to do this using the initialization system, because we actually want to get a special getty-like service for htop.
How do VT1, ..., VT6 start?
agetty- this is such a program that opens the tty port, issues a prompt for authentication and transfers subsequent control to another program -
$ which agetty login | xargs ls -l -rwxr-xr-x 1 root root 44104 Sep 29 05:21 /usr/bin/agetty -rwxr-xr-x 1 root root 35968 Sep 29 05:21 /usr/bin/login
Traditional Linux initialization systems are configured to run a fixed amount
agettyat boot time. In most cases, six instances are created for six VTs: from tty1 to tty6, respectively. Systemd takes a different approach.
- The first is dynamic . The service instance is
getty@.servicelaunched on demand. That is, only if we need a specific VT. Logind is responsible for this, which when switching to ttyN starts a service
autovt@ttyN.servicethat is symlinked to
getty@.service. This logic works for tty2-tty6.
- The second is static . A specific service instance
getty@.serviceis automatically retracted through
getty.target, which gives us always running getty on tty1.
systemctl cat getty@.servicewill show the contents of this service. We are not going to consider it in detail, since this is not so important for us.
Accordingly, if we assume that we have one
htop@.service, then we can add it to the autoload in two ways: either make a symlink under the name
autovt@ttyN.service- then when switching to the selected VT, htop will start instead of getty, or disable
getty@ttyN.serviceand enable it instead
htop@ttyN.service- this always gives us running htop on a fixed VT.
Writing our own getty-like unit
Now go to
/etc/systemd/system- one of the directories where the units are located - and create our own service:
$ "$EDITOR" htop@.service
The presence of the suffix (
@) means that the service does not start by itself, but one of its instances. A suffix parammetrom passed into it (
It was already noted above that the content
getty@.serviceis not so important for us. That's right, because it can be included in our service:
Given that our service is getty-like, this construction saves us from unnecessary code copying.
It describes the general parameters applicable to any type of unit.
[Unit] Description=htop on %I Documentation=man:htop(1)
Everything is transparent here: the directive
Descriptionsets a short description of the unit, and the
Documentationpath to the documentation.
%IIs the name of the instance. It is important to note that both variables specifying the instance name are different in meaning:
%I- the same as
%i, but it does not escape escape sequences.
This section configures the service specifically. In other words, describes how to start the process.
[Service] Environment= Environment=TERM=linux HOME=/root ExecStart= ExecStart=/usr/bin/htop StandardInput=tty-fail StandardOutput=tty
We will leave the necessary inherited values of the directives alone, and we need to reset some (set an empty value for them) and define them ourselves. These include
Environment- setting variables, and
ExecStart, - actually, starting the process.
- This is an indication of systemd to start htop connected directly to the terminal.
By the way, you can add not an instant start, but with the expectation of input. To do this, create a simple script on the bash:
#!/bin/bash echo "Press a key to launch $(basename "$1")" read exec "$@"
All he does is wait for input and run some kind of program (which will be htop in our case). We place it anywhere, call it whatever you like, make it executable (
chmod +x) and edit
ExecStartin our service:
If you need to impose any restrictions on the rights, then of course you need to do this. To do this, we will create another service and another script, and now -
run_wait_su. We reconfigure them so that htop starts with the rights of a specific user and a specific group, and also requires an administrator password.
So, we create a new service and a new script based on the two previous ones:
$ cd /etc/systemd $ cp system/htop@.service system/htop_secure@.service $ cp scripts/run_wait scripts/run_wait_su
And we edit each of them. For the service in the Service section, change the value of Environment and set the username with its group:
User=kalterfive Group=users Environment=TERM=linux
And in the script, we turn to
#!/bin/bash echo "Press a key to launch $(basename "$1")" read exec su -c "$@"
Now our service is ready, it remains only to add it to startup:
$ systemctl daemon-reload $ systemctl disable firstname.lastname@example.org $ systemctl enable email@example.com
The first command updates the systemd configuration manager, and the second creates a symlink to our service in
Now we reboot (or manually kill
getty@and turn it on
htop@for the tty2 instance), switch to the second VT and observe the successfully launched htop. The demonstrated trick affects only a small part of systemd, as an initialization system, from the full scope of its capabilities, as a universal plumbing layer — a set of programs for solving completely different problems. Good luck!