systemd 和终端启动程序的区别

Bre*_*ard 12 shell permissions systemd raspberry-pi raspbian

我很好奇这些程序之间的区别是什么;通过 systemctl 启用时使用 systemd 启动,而/etc/rc.local通过 CLI 或通过 CLI启动的启动。

例如,我最近在树莓派上使用 shairport-sync。最初,我通过启用 sudo systemctl 的 shairport-sync 将 shairport-sync 设置为启动。

后来我使用其中的一个功能在shairport-sync连接设备之前运行脚本并发布。

令我惊讶的是,执行时的脚本shairport-sync没有kill arecordaplay

然而,当我将通过终端执行,杀死了脚本运行脚本arecordaplay

为了进一步混淆自己,我shairport-sync通过终端杀死并启动它以查看正在发生的事情的输出。当我这样做时,当设备连接并杀死arecordaplay. 所以,作为一个修复我禁用shairport-syncsysmtectl,并设置它在运行/etc/rc.local作为一个快速修复。之后reboot它按我的预期运行。

这让我相信作为一部分运行systemd的程序与通过/etc/rc.local或 CLI启动时运行的程序之间存在一些差异。

为什么会发生这种情况?这是因为运行级别不同吗?什么黑魔法?

设备连接时运行的脚本shairport-sync如下:shairportstart.sh

#!/bin/sh
/usr/bin/sudo /bin/pkill arecord
if [ $(date +%H) -ge "18" -o $(date +%H) -le "7" ]; then
        /usr/bin/amixer set Speaker 40%
else
        /usr/bin/amixer set Speaker 100%
fi
/home/pi/shScripts/shairportfade.sh&

exit 0
Run Code Online (Sandbox Code Playgroud)

这是淡入淡出脚本: shairportfade.sh

#!/bin/sh
/usr/bin/amixer set Speaker 30-
for (( i=0; i<30; i++))
do  
    /usr/bin/amixer set Speaker 1+
done
exit 0
Run Code Online (Sandbox Code Playgroud)

设备断开连接时运行的脚本shairport-sync如下:shairportend.sh

#!/bin/sh
/usr/bin/amixer set Speaker 70%
/usr/bin/arecord -D plughw:1 -f dat | /usr/bin/aplay -D plughw:1 -f dat&
exit 0
Run Code Online (Sandbox Code Playgroud)

/var/log/syslog仅在 shairport-sync 最初作为systemd. 何时shairport-sync从 CLI 运行或/etc/rc.local不存在错误。

Jan 24 00:38:45 raspberrypi shairport-sync[617]: sudo: no tty present and no askpass program specified
Run Code Online (Sandbox Code Playgroud)

请注意,唯一的区别是shairport-sync最初如何启动,当设备连接或断开连接时shairport-sync继续运行。

Mar*_*erg 23

的变化“为什么事情不同的表现下systemd?” 是一个常见问题。

任何时候从 CLI 而不是从 systemd 运行的东西,都有一些广泛的可能性类别来解释差异。

  1. 不同的环境变量在衍生进程中的环境变量部分systemd记录了它传入man systemd.exec环境变量。如果您想自己检查差异,可以使用systemd-run /path/to/binary,它将在瞬态范围内运行您的应用程序,因为它将由 systemd 服务运行。你会得到输出如下:Running as unit: run-u160.service。然后您可以journalctl -u run-u160.service查看输出。修改您的应用程序以转储它接收的环境变量并将 CLI 运行与 systemd 运行进行比较。如果应用程序没有方便地修改,您可以只使用systemd-run env查看将传递的环境变量并查看生成的日志记录。如果您尝试启动 X11 GUI 应用程序,DISPLAY需要设置环境变量. 在这种情况下,请考虑使用桌面环境的“自动启动”功能而不是systemd.
  2. 资源限制。有关man systemd.resource-control可能限制资源消耗的配置值,请参阅。使用systemctl show your-unit-unit.service检查影响您尝试启动该服务的完整配置的值。
  3. 非交互式外壳。您的bashCLI 环境是一个交互式登录 shell。它源文件,就像.bashrcsystemd没有。除了设置环境变量之外,这些脚本还可以做许多其他事情,例如连接 SSH 代理,以便 SSH 操作不需要登录。另请参阅登录外壳和非登录外壳之间的区别?
  4. 没有 TTY。您的交互式会话连接到一些程序在提示输入密码时喜欢sudossh期望的 TTY 。另请参阅sudo: no tty present and no askpass program specified
  5. 相对与绝对路径。shell 中的相对二进制工作,但如 中所述man systemd.service, 的第一个参数ExecStart=必须是二进制文件的绝对路径。
  6. 受限制的命令行语法。Shell CLI 支持许多元字符,同时systemd具有非常有限的命令行语法。根据您的需要,您可以systemd通过 shell 显式运行命令来复制 Shell 语法:ExecStart=/bin/bash -c '/my/bash $(syntax) >/goes-here.txt'

这是一项功能,系统可以在具有资源控制的一致环境中运行您的代码。从长远来看,这有助于获得可重现、稳定的结果,而不会使硬件不堪重负。

  • @BrettReinhard 不要在 shell 脚本中调用 `sudo` 最好从终端运行 `sudo shairportstart.sh`,因为 systemd 以 root 身份运行脚本,不需要以 root 身份运行 sudo。 (2认同)