Autostart via systemd units instead of /etc/rc.local - #32
kkaazzuukkii4 wants to merge 1 commit into
Conversation
|
Keep in mind that Debian 14 Forky (the respective systemd version), removes support for A future-prove autostart method should use an own systemd service, or it should be make clear that the SysV init system is required, which will exclude like 99% of relevant production systems. |
rc.local is a dead end. Debian 14 (Forky) drops rc-local.service entirely, and it has been deprecated for a long time before that, so patching the rc.local path only buys a release or two. Replace it with two units written by fn_autostart: raspimjpeg.service the camera backend raspimjpeg-schedule.service the scheduler, BindsTo the backend /dev/shm is a tmpfs and is emptied on every boot, so the working directory is created by an ExecStartPre. It needs the "+" prefix to run as root, since the unit itself runs as www-data and could not chown otherwise. The two "sleep 4" delays are gone; ordering is expressed as a dependency and Restart=on-failure covers a backend that is not ready yet. ExecStart invokes the Python entry point directly rather than the /usr/bin/ raspimjpeg symlink. That symlink points at a wrapper which backgrounds the process and exits, so under Type=simple systemd considers the service finished and tears down the cgroup about a second after boot. Type=forking with the wrapper's PIDFile was tried too and is worse: the wrapper sleeps before writing the pid file, so systemd races it and reads a stale pid, which breaks every stop/start cycle after the first. The direct invocation is what the project itself intends -- an identical, commented-out line already exists in this installer. It also puts the backend's output in the journal instead of a private log file. fn_autostart strips any leftover "#START RASPIMJPEG SECTION" block from /etc/rc.local, otherwise an upgraded system starts the camera twice. fn_stop now stops the services through systemd before falling back to the pid file, because SIGKILL on a running unit is a failure and Restart=on-failure would resurrect the camera in the middle of an install. start.sh and stop.sh go through systemctl for the same reason, and their "killall php" is dropped -- it killed unrelated PHP processes and the scheduler is a managed service now. Verified on Raspberry Pi 3 Model B / Raspberry Pi OS Bookworm 64-bit with Camera Module 3, deliberately on the slower board so the removal of the sleeps is exercised. After a reboot both services come up with exactly one process each, /dev/shm/mjpeg has the right ownership, capture works, the legacy rc.local block is gone, and stop.sh followed by start.sh leaves a single process rather than a duplicate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6ed9645 to
04ff216
Compare
|
@MichaIng You're right — patching the rc.local path would only have bought a release or two. Replaced the mechanism instead; the PR is updated. Two units now, with One thing that isn't obvious from the diff, so I've put it in a comment there too: Verified through reboots on a Pi 3 — the slower board, so the removed sleeps actually get exercised. |
Problem
On Raspberry Pi OS Bookworm and later, the camera never starts after a reboot.
fn_autostartappends to/etc/rc.local, which Debian 12+ no longer ships, so the file is created without a shebang and systemd cannot execute it (status=203/EXEC).The first version of this PR added the missing shebang. @MichaIng pointed out that this is a dead end — Debian 14 removes
rc-local.serviceentirely. He's right, so this replaces the mechanism instead.Change
Two units written by
fn_autostart:raspimjpeg.service(backend) andraspimjpeg-schedule.service(scheduler,BindsTothe backend)./dev/shmis a tmpfs emptied on every boot, so the working directory is created by anExecStartPresleep 4delays are gone; ordering is a dependency, andRestart=on-failurecovers a backend that isn't ready yetfn_autostartstrips any leftover#START RASPIMJPEG SECTIONfrom/etc/rc.local, or an upgraded system starts the camera twicefn_stop,start.shandstop.shgo through systemd.killall phpis dropped — it killed unrelated PHP processesExecStartdeliberately does not use the/usr/bin/raspimjpegsymlink: that wrapper backgrounds the process and exits, soType=simpletears down the cgroup 1.269s after start (measured,status=0/SUCCESS, soRestart=on-failurenever fires).Type=forkingwith itsPIDFilefails differently. The reasoning for this and the other non-obvious choices is recorded in comments in the diff, so they don't get "tidied" back into bugs later.Verification
Raspberry Pi 3 Model B / Bookworm 64-bit / Camera Module 3 — deliberately the slower board, so removing the sleeps is actually exercised. Units generated by the installer, then rebooted:
active, untouchedmain.py1,schedule.php1 — no duplicates/dev/shm/mjpeg777 www-data:www-datarc.localblockstop.shthenstart.shsystemd-analyze verifyDisclosure: investigated and written with the help of Claude and Codex. All testing was run on my own hardware and the output above is real, not generated.