Re: Running VDR from systemd on Raspberry Pi OS

Marko Mäkelä <[email protected]> Wed, 28 Dec 2022 12:13:50 +0200
Newsgroups gmane.linux.vdr
Message-ID <Y6wW3oc7zoKRltxJ@jyty>
Tue, Dec 27, 2022 at 11:15:29PM +0100, Martin Dummer wrote:
>
>Am 27.12.22 um 21:49 schrieb Marko Mäkelä:
>>
>>First, I removed the custom /etc/fstab entry. Everything will be
>>controlled by systemd as follows:
>
>
>On systemd-systems, each line  in /etc/fstab is automatically converted
>by a binary "systemd-fstab-generator" into "xxx.mount" units.

That is correct. I converted the fstab-generated video.mount file to a 
custom one.

>So what you do here
[...]
>is more or less the same as one line in /etc/fstab.

It is, except for the [Unit] keys BindsTo and After, and the [Install] 
key WantedBy, which causes the file system to be mounted automatically 
and the dependent service started once a matching storage device is 
plugged in.

Years ago, executing commands when USB storage was plugged in could be 
achieved by writing udev rules. In fact, I first attempted that, but I 
did not come up with a solution that would work both on system startup 
and when the storage is plugged into an already running system. The 
systemd mount unit and the service unit, with declared dependencies on 
/dev/disk/by-label/VDR do exactly what I need, without being tied to a 
specific USB ID.

When it comes to the power button, I found a Python 2.7 script 
https://github.com/ryran/reboot-guard that can disable or enable 
shutdown, reboot, halt, by creating or removing simple configuration 
files. Because this script is not packaged in Debian, and Python 2 is 
kind of obsolete, I wrote a shell script to achieve the same:

sudo tee /etc/systemd/system/vdr-keep-alive.sh << "EOF"
#!/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
EOF

Whether the override is in place can be checked with commands like 
"systemctl cat shutdown.target". On my system, "sudo reboot" would be 
silently ignored, while "sudo systemctl reboot" would display verbose 
messages, suggesting to check "systemctl status reboot.target" for 
details.

Furthermore, I learned about ExecStartPre and ExecStop. The former can 
be used for preparatory steps, such as blocking the shutdown and reboot 
commands with the above script. ExecStop seems to be unusable for this 
type of a service. I moved those steps to be part of the shutdown script 
that will be invoked by VDR:

tee /var/lib/vdr/vdr-shutdown.sh << "EOF"
#!/bin/sh
set -eu
if [ "$5" = 1 ]
then
   sudo systemd-mount -u /dev/disk/by-label/VDR
   sudo /etc/systemd/system/vdr-keep-alive.sh stop
   sudo udisksctl power-off -b /dev/disk/by-label/VDR
fi
EOF

Thanks to the declared dependencies, the udisksctl command will actually 
stop VDR.

The "set -e" at the start of the script ensures that if the file system 
cannot be unmounted (due to VDR playing back a recording, or any other 
process accessing the file system), the script will be aborted at the 
first step, and VDR will keep running.

Finally, here is the revised service file. It now includes 
Conflicts=shutdown.target to ensure an orderly shutdown of VDR in case 
the logic to disable shutdown is disabled:

sudo tee /etc/systemd/system/vdr.service << "EOF"
[Unit]
Description=Video Disk Recorder
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service
[email protected]
BindsTo=dev-disk-by\x2dlabel-VDR.device
After=dev-disk-by\x2dlabel-VDR.device
After=video.mount
[email protected]
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=dev-disk-by\x2dlabel-VDR.device
EOF

With this setup, any USB based storage that contains a partition that 
contains a file system labeled VDR that contains the subdirectory 
"video" becomes special as follows:

1. The first virtual console (/dev/tty1) is always reserved for VDR.
2. If the storage is not available on startup, there will be no timeout 
or waiting (like with /etc/fstab there would be).
3. If the storage is available on startup or plugged in at any later 
time, it will be mounted in /video. If /video/video exists, VDR will be 
started and the shutdown, reboot, halt actions disabled.
4. If VDR is shut down from its user interface, the file system will be 
unmounted, the storage powered off, and the shutdown, reboot, halt 
actions re-enabled.

The drive LED becomes a proxy indicator for "VDR is running"; there is 
no need to turn on the screen to check that.

To restart VDR, just unplug the USB cable (after the USB drive LED has 
turned off) and plug the cable back in, optionally using a different 
drive.

To shut down the entire system, simply press the Power button once more 
while the USB drive LED is off (or the drive is disconnected).

In my old PC based system, I had an ATtiny microcontroller board that 
would run on standby power, listen to the IR receiver, and start up the 
system via WoL or PCI PME when the power button was pressed. While 
something similar would be possible with the Raspberry Pi (using GPIO 3, 
or pin 5 on the connector), I think that the current setup is good 
enough for me, with the IR receiver mounted on the TV HAT with 3 loose 
wires and poking out of the Pi TV HAT case. With a daughter board for 
the IR receiver and an SMD microcontroller using 4 loose wires, it 
should be doable.

	Marko

_______________________________________________
vdr mailing list
[email protected]
https://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr