Systemd: Difference between revisions
(Clarifications on some systemctl commands) |
(Shutdown on idle timeout) |
||
Line 162: | Line 162: | ||
#!/bin/sh |
#!/bin/sh |
||
set -eu |
set -eu |
||
# set_rtc_wakeup $(($1 - 120)) |
|||
if [ "$5" = 1 ] |
if [ "$5" = 1 ]; then |
||
then |
|||
sudo systemd-mount -u /dev/disk/by-label/VDR |
sudo systemd-mount -u /dev/disk/by-label/VDR |
||
sudo sh |
sudo sh /etc/systemd/system/vdr-keep-alive.sh stop |
||
# sudo systemctl poweroff |
|||
sudo udisksctl power-off -b /dev/disk/by-label/VDR |
sudo udisksctl power-off -b /dev/disk/by-label/VDR |
||
# elif [ "$2" -ge 86400 ]; then |
|||
else |
|||
sudo systemd-mount -u /dev/disk/by-label/VDR |
|||
sudo sh /etc/systemd/system/vdr-keep-alive.sh stop |
|||
sudo systemctl poweroff |
|||
fi |
fi |
||
</pre> |
</pre> |
||
The comment <code># set_rtc_wakeup</code> can be replaced with something that schedules a wake-up on timer if the system is equipped with a suitable real time clock device. In the example, the wake-up time is 120 seconds (2 minutes) before the next scheduled recording. |
|||
The <code>if</code> condition is looking for explicit user action to shut down VDR. Any other requests (such as shutdown due to an inactivity timeout) will be ignored. |
The <code>if</code> condition is looking for explicit user action to shut down VDR. Any other requests (such as shutdown due to an inactivity timeout) will be ignored. |
||
Line 174: | Line 182: | ||
If unmounting the file system succeeds, the script will re-enable the shutdown and reboot targets, and finally power off the drive. Thanks to the declared dependency, the VDR service will be shut down (and the shell that is running the script terminated) as part of the <code>udisksctl</code> command. That is, explicit <code>sudo systemctl stop vdr</code> is not needed. |
If unmounting the file system succeeds, the script will re-enable the shutdown and reboot targets, and finally power off the drive. Thanks to the declared dependency, the VDR service will be shut down (and the shell that is running the script terminated) as part of the <code>udisksctl</code> command. That is, explicit <code>sudo systemctl stop vdr</code> is not needed. |
||
If you want the system to be shut down immediately, uncomment the line <code>sudo systemctl poweroff</code>. The script will instead just power off the drive. A subsequent push of the power button will shut down the system. If you unplug and replug the USB cable to the storage (possibly a different disk), VDR can start up automatically. |
|||
The second part of the script (after an <code>else</code> or <code>elif</code> line) handles shutdown due to inactivity timeout. If the storage can be unmounted, the system will be shut down directly by <code>systemctl</code>. |
|||
If there is no real-time clock device for scheduling wake-up, you might want to omit the second part, to prevent an automatic shutdown before a recording is supposed to start. It would then be the user's responsibility to shut down or wake up the system between recordings. You might want to have an automatic shutdown if the next scheduled recording is in distant enough future. That you can achieve by replacing the <code>else</code> with the commented-out <code>elif</code> line: shut down if there is no recording starting in the next 24 hours (86400 seconds). |
|||
===Notes=== |
===Notes=== |
||
You can still execute the following commands to stop or start the VDR service, for example, for upgrading VDR or plugins: |
You can still execute the following commands to stop or start the VDR service, for example, for upgrading VDR or plugins: |
Revision as of 08:18, 10 April 2023
Introduction
The main aim of systemd (a "system and service manager") is to unify service configuration and behavior across Linux distributions. It bootstraps the user space and manages user processes. It also provides replacements for various daemons and utilities, including device management, login management, network connection management, and event logging.
Since 2015, the majority of Linux distributions have adopted systemd, having replaced other init systems such as SysV init.
Preventing shutdown and reboot while VDR is running
By default, the power button on a remote control that is managed by a kernel LIRC driver will be mapped to systemd-logind
. Unless you have overridden the default HandlePowerKey=poweroff
in /etc/systemd/logind.conf
, the system would be shut down immediately when you hit a power button on any input device (remote control, keyboard, or power button on the computer case).
Often, VDR is the main application on the system. You would not want the system to be accidentally shut down or rebooted while someone is watching TV, or a recording is in progress. System shutdown would be initiated by a script that would be invoked by VDR itself; see the -s
parameter of ExecStart
below.
To disable or enable the normal handling of shutdown and reboot, you can use the following script, say, /etc/systemd/system/vdr-keep-alive.sh
. Executing it will require super user privileges.
#!/bin/sh TARGETS=" /lib/systemd/system/poweroff.target.d /lib/systemd/system/reboot.target.d /lib/systemd/system/halt.target.d " CONF=vdr-keep-alive.conf case "$1" in start) for t in $TARGETS do if [ ! -f "$t/$CONF" ] then if [ ! -d "$t/" ] then mkdir "$t" fi echo "[Unit]\nRefuseManualStart=yes" > "$t/$CONF" fi done ;; stop) for t in $TARGETS do rm -f "$t/$CONF" done ;; esac exec systemctl daemon-reload
You can execute this script as follows:
sudo /etc/systemd/system/vdr-keep-alive.sh start sudo /etc/systemd/system/vdr-keep-alive.sh stop
You might want to make the TARGETS
above to include suspend
, hibernate
, or others mentioned in man 7 systemd.special
.
Making Systemd start up VDR
Before systemd, you might have edited /etc/gettydefs
to prevent a virtual console from being associated with a normal login prompt, and then have init
invoke a shell script that would invoke VDR, often named runvdr
. With systemd, all you need is a single file, say, /etc/systemd/system/vdr.service
, with contents like the following:
[Unit] Description=Video Disk Recorder After=systemd-user-sessions.service plymouth-quit-wait.service After=rc-local.service After=getty@tty1.service Conflicts=getty@tty1.service Conflicts=shutdown.target ConditionPathExists=/video/video [Service] User=pi ExecStartPre=+/etc/systemd/system/vdr-keep-alive.sh start ExecStart=/usr/local/bin/vdr --no-kbd --lirc=/dev/lirc0 -Prpihddevice -v /video/video -s /var/lib/vdr/vdr-shutdown.sh TimeoutStartSec=infinity Type=idle Restart=on-failure RestartSec=1s TTYVTDisallocate=yes [Install] WantedBy=display-manager.service
Adjustments
User=
refers to the user account that will run the VDR service.ExecStart=
must refer to the full VDR invocation.ConditionPathExists=
is for the directory that contains the recordings, matching the-v
parameter inExecStart
. If the recordings cannot be mounted, the service would not start up.
The shutdown script (named /var/lib/vdr/vdr-shutdown.sh
in the above example) could do at least one of the following:
- Invoke
sudo /etc/systemd/system/vdr-keep-alive.sh stop
to allow normal reboot and shutdown. - Adjust Nvram_wakeup to have the system start up automatically on the next scheduled recording.
- Invoke
sudo systemctl stop vdr
orsudo systemctl halt
to shut down VDR or the entire system. This will also terminate the shell that runs the script!
Installation
sudo systemctl enable vdr sudo systemctl start vdr
or just (according to man systemctl
):
sudo systemctl enable --now vdr
Example: Auto-starting VDR with swappable video storage
On a small system like the Raspberry_Pi, the internal storage is just large enough for the basic installation and system configuration. For recordings, you might want to use a USB-powered HDD or SSD.
You might make a virtue out of necessity and implement swappable video directories. One USB SSD might not be large enough for your entire collection of recordings. So, why not implement swappable storage, with the following user interface?
- When you plug in the USB cable (or it is attached on system startup), VDR will start up automatically.
- When you press the power button, VDR will shut down and the USB storage will be powered off, so that it can be safely unplugged.
- When you plug in the USB cable again, VDR will start up again. This could be a different drive.
Preparations
Create a file system and label it VDR
. Create the subdirectory video
inside it.
Below, we assume that the storage devices that you want to initialize is /dev/sdd. Substitute the correct name for sdd
below, and ensure that you are accessing the right device!
sudo mkfs.ext4 /dev/sdd1 sudo tune2fs -L /dev/sdd1 sudo mount /dev/sdd1 /mnt mkdir /mnt/video sudo umount /mnt
On the VDR system, create a mount point for the storage devices that have been prepared as above.
sudo mkdir -m 000 /video
Automatically mounting storage when it is plugged in
You might think of a simple /etc/fstab
entry like this:
LABEL=VDR /video ext4 defaults,noatime,nofail 0 1
But, we want the file system to be mounted automatically when it is labeled VDR. To achieve that, we create a file /etc/systemd/system/video.mount
(the name must match the mount point /video
):
[Unit] BindsTo=dev-disk-by\x2dlabel-VDR.device After=dev-disk-by\x2dlabel-VDR.device Requires=systemd-fsck@dev-disk-by\x2dlabel-VDR.service After=systemd-fsck@dev-disk-by\x2dlabel-VDR.service [Mount] Where=/video What=/dev/disk/by-label/VDR Type=ext4 Options=defaults,noatime,nofail [Install] WantedBy=dev-disk-by\x2dlabel-VDR.device
The magic .device
unit refers to the path /dev/disk/by-label/VDR
, which will become available when a device containing a file system labeled VDR
is attached. We use that name also in the What=
directive.
Now we are ready to enable the unit:
sudo systemctl enable video.mount
To check the status, you may find the following commands useful:
systemctl status journalctl -u video.mount journalctl -xe
Automatically starting VDR when the storage is plugged in
We also want VDR to start automatically once the file system has been mounted. To do that, the following lines have to be added to /etc/systemd/system/vdr.service
:
[Install] WantedBy=dev-disk-by\x2dlabel-VDR.device
If you had the following lines at the end of the file, they can be removed:
[Install] WantedBy=display-manager.service
To notify systemd of the update:
sudo systemctl reenable vdr
Last, we need a VDR shutdown script /var/lib/vdr/vdr-shutdown.sh
that will power off the storage so that it can be safely detached:
#!/bin/sh set -eu # set_rtc_wakeup $(($1 - 120)) if [ "$5" = 1 ]; then sudo systemd-mount -u /dev/disk/by-label/VDR sudo sh /etc/systemd/system/vdr-keep-alive.sh stop # sudo systemctl poweroff sudo udisksctl power-off -b /dev/disk/by-label/VDR # elif [ "$2" -ge 86400 ]; then else sudo systemd-mount -u /dev/disk/by-label/VDR sudo sh /etc/systemd/system/vdr-keep-alive.sh stop sudo systemctl poweroff fi
The comment # set_rtc_wakeup
can be replaced with something that schedules a wake-up on timer if the system is equipped with a suitable real time clock device. In the example, the wake-up time is 120 seconds (2 minutes) before the next scheduled recording.
The if
condition is looking for explicit user action to shut down VDR. Any other requests (such as shutdown due to an inactivity timeout) will be ignored.
If anything is using the file system, unmounting will fail, and thanks to set -e
the entire script will be terminated. It could be nice to display a message on the VDR screen in this case. The culprit could be VDR itself playing a recording, or it could be a shell whose current working directory is within the file system.
If unmounting the file system succeeds, the script will re-enable the shutdown and reboot targets, and finally power off the drive. Thanks to the declared dependency, the VDR service will be shut down (and the shell that is running the script terminated) as part of the udisksctl
command. That is, explicit sudo systemctl stop vdr
is not needed.
If you want the system to be shut down immediately, uncomment the line sudo systemctl poweroff
. The script will instead just power off the drive. A subsequent push of the power button will shut down the system. If you unplug and replug the USB cable to the storage (possibly a different disk), VDR can start up automatically.
The second part of the script (after an else
or elif
line) handles shutdown due to inactivity timeout. If the storage can be unmounted, the system will be shut down directly by systemctl
.
If there is no real-time clock device for scheduling wake-up, you might want to omit the second part, to prevent an automatic shutdown before a recording is supposed to start. It would then be the user's responsibility to shut down or wake up the system between recordings. You might want to have an automatic shutdown if the next scheduled recording is in distant enough future. That you can achieve by replacing the else
with the commented-out elif
line: shut down if there is no recording starting in the next 24 hours (86400 seconds).
Notes
You can still execute the following commands to stop or start the VDR service, for example, for upgrading VDR or plugins:
sudo systemctl stop vdr sudo systemctl start vdr
If you use these commands, the storage device will remain mounted in the file system, and the status of the reboot and shutdown targets will not change.
If the power button is pressed while VDR is not running, the system will be shut down. The power LED indicator on the USB storage device will become an indicator on whether VDR is running. In other words, an extremely slow "double click" of the power button on the remote control unit will power off the system.