我正在运行带有 Raspbian (Bullseye)、Logitech Media Server (LMS) 8.2.0 和 Squeezelite 1.9.9 的 RPi 4b。为了在连接某个 USB 设备时自动启动 Squeezelite 进程,我定义了以下udev
规则:
SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="154e/300a/3", RUN+="/usr/bin/DAC_start.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="154e/300a/3", RUN+="/usr/bin/DAC_stop.sh"
这是我的DAC_start.sh
脚本:
#!/bin/sh
######### DAC_start.sh #########
date >> /tmp/udev.log
echo "Starting Squeezelite" >> /tmp/udev.log
sleep 5s
/usr/bin/squeezelite -o hw:CARD=ND8006,DEV=0 -D -n MediaPlayer -d all=debug -f /tmp/sq.log | at now
###############################
这是我的DAC_stop.sh
脚本:
#!/bin/sh
######### DAC_stop.sh #########
date >> /tmp/udev.log
echo "Stopping Squeezelite ..." >> /tmp/udev.log
pkill squeezelite
###############################
当我手动执行(以 pi 和 root 身份)时,这两个脚本都工作正常:Squeezelite 成功连接到 LMS 和 USB 设备,可以播放音乐。当我连接 USB DAC(我可以从日志文件中看到)时,这些udev
规则也有效并被触发。然而,当squeezelite启动时udev
,squeezelite似乎无法连接到我的LMS服务器,该服务器位于同一LAN上,实际上是在同一台机器上。这是 Squeezelite 日志文件(我认为更重要的消息位于最底部,但为了方便您复制所有消息,以防我忽略某些内容):
/usr/bin/squeezelite -o hw:CARD=ND8006,DEV=0 -D -n MediaPlayer -d all=debug -f /tmp/sq.log
[16:22:50.362611] stream_init:454 init stream
[16:22:50.362971] stream_init:455 streambuf size: 2097152
[16:22:50.376806] output_init_alsa:936 init output
[16:22:50.377007] output_init_alsa:976 requested alsa_buffer: 40 alsa_period: 4 format: any mmap: 1
[16:22:50.377081] output_init_common:360 outputbuf size: 3528000
[16:22:50.377333] output_init_common:384 idle timeout: 0
[16:22:50.410804] test_open:301 sample rate 1536000 not supported
[16:22:50.410907] test_open:301 sample rate 1411200 not supported
[16:22:50.411049] test_open:301 sample rate 32000 not supported
[16:22:50.411085] test_open:301 sample rate 24000 not supported
[16:22:50.411118] test_open:301 sample rate 22500 not supported
[16:22:50.411151] test_open:301 sample rate 16000 not supported
[16:22:50.411184] test_open:301 sample rate 12000 not supported
[16:22:50.411216] test_open:301 sample rate 11025 not supported
[16:22:50.411249] test_open:301 sample rate 8000 not supported
[16:22:50.411330] output_init_common:426 supported rates: 768000 705600 384000 352800 192000 176400 96000 88200 48000 44100
[16:22:50.500287] output_init_alsa:1002 memory locked
[16:22:50.500456] output_init_alsa:1008 glibc detected using mallopt
[16:22:50.501072] output_init_alsa:1026 unable to set output sched fifo: Operation not permitted
[16:22:50.501080] output_thread:685 open output device: hw:CARD=ND8006,DEV=0
[16:22:50.501156] decode_init:153 init decode
[16:22:50.502046] alsa_open:354 opening device at: 44100
[16:22:50.502132] register_dsd:908 using dsd to decode dsf,dff
[16:22:50.502166] register_alac:549 using alac to decode alc
[16:22:50.502198] register_faad:663 using faad to decode aac
[16:22:50.502229] register_vorbis:385 using vorbis to decode ogg
[16:22:50.502325] register_opus:328 using opus to decode ops
[16:22:50.502361] register_flac:336 using flac to decode ogf,flc
[16:22:50.502392] register_pcm:483 using pcm to decode aif,pcm
[16:22:50.502433] register_mad:423 using mad to decode mp3
[16:22:50.502463] decode_init:194 include codecs: exclude codecs:
[16:22:50.503117] alsa_open:425 opened device hw:CARD=ND8006,DEV=0 using format: S32_LE sample rate: 44100 mmap: 1
[16:22:50.503159] discover_server:795 sending discovery
[16:22:50.503272] alsa_open:516 buffer: 40 period: 4 -> buffer size: 1764 period size: 441
[16:22:50.503349] discover_server:799 error sending disovery
[16:22:55.504955] discover_server:795 sending discovery
[16:22:55.505246] discover_server:799 error sending disovery
[16:23:00.510091] discover_server:795 sending discovery
[16:23:00.510360] discover_server:799 error sending disovery
[16:23:05.515053] discover_server:795 sending discovery
[16:23:05.515329] discover_server:799 error sending disovery
[16:23:10.519882] discover_server:795 sending discovery
[16:23:10.520185] discover_server:799 error sending disovery
[16:23:15.528387] discover_server:795 sending discovery
[16:23:15.528659] discover_server:799 error sending disovery
[16:23:20.535819] discover_server:795 sending discovery
[16:23:20.536007] discover_server:799 error sending disovery
[16:23:25.541079] discover_server:795 sending discovery
[16:23:25.541333] discover_server:799 error sending disovery
[16:23:30.549470] discover_server:795 sending discovery
[16:23:30.549640] discover_server:799 error sending disovery
[16:23:35.559568] discover_server:795 sending discovery
[16:23:35.559857] discover_server:799 error sending disovery
[16:23:40.568356] discover_server:795 sending discovery
[16:23:40.568646] discover_server:799 error sending disovery
[16:23:45.576730] discover_server:795 sending discovery
[16:23:45.577009] discover_server:799 error sending disovery
[16:23:50.586202] discover_server:795 sending discovery
[16:23:50.586502] discover_server:799 error sending disovery
[16:23:55.596574] discover_server:795 sending discovery
[16:23:55.596872] discover_server:799 error sending disovery
[16:24:00.604989] discover_server:795 sending discovery
[16:24:00.605269] discover_server:799 error sending disovery
[16:24:05.615978] discover_server:795 sending discovery
[16:24:05.616278] discover_server:799 error sending disovery
[16:24:10.625168] discover_server:795 sending discovery
[16:24:10.625472] discover_server:799 error sending disovery
[16:24:15.633952] discover_server:795 sending discovery
[16:24:15.634246] discover_server:799 error sending disovery
[16:24:20.642357] discover_server:795 sending discovery
[16:24:20.642648] discover_server:799 error sending disovery
[16:24:25.650821] discover_server:795 sending discovery
[16:24:25.651113] discover_server:799 error sending disovery
[16:24:30.662745] discover_server:795 sending discovery
[16:24:30.663055] discover_server:799 error sending disovery
[16:24:35.670289] discover_server:795 sending discovery
[16:24:35.670566] discover_server:799 error sending disovery
[16:24:40.674134] discover_server:795 sending discovery
[16:24:40.674460] discover_server:799 error sending disovery
[16:24:45.679650] discover_server:795 sending discovery
[16:24:45.679984] discover_server:799 error sending disovery
[16:24:50.689070] discover_server:795 sending discovery
[16:24:50.689366] discover_server:799 error sending disovery
[16:24:55.697415] discover_server:795 sending discovery
[16:24:55.697709] discover_server:799 error sending disovery
[16:25:00.705845] discover_server:795 sending discovery
[16:25:00.706128] discover_server:799 error sending disovery
[16:25:05.714279] discover_server:795 sending discovery
[16:25:05.714583] discover_server:799 error sending disovery
[16:25:10.723306] discover_server:795 sending discovery
[16:25:10.723601] discover_server:799 error sending disovery
[16:25:15.728709] discover_server:795 sending discovery
[16:25:15.728977] discover_server:799 error sending disovery
似乎 Squeezelite 在启动时udev
无法访问 LAN?我还尝试使用-s 192.168.1.20
参数(这是我的 LMS 的 IP)启动 Squeezelite ,但没有成功。它仍然无法连接到 LMS 服务器。有什么想法我做错了吗?
我在带有 piCore OS(这是一个 Tiny Core Linux 发行版)的 RPi 上使用了上述方法,它的工作方式非常神奇......
答案1
从man udev
:
运行{类型}
[...]
根据类型,将程序添加到处理完特定事件的所有规则后要执行的程序列表中:
这只能用于运行时间非常短的前台任务。长时间运行事件进程可能会阻止该设备或从属设备的所有进一步事件。
启动守护进程或其他长时间运行的进程不适合 udev;分叉的进程,无论是否分离,都将在事件处理完成后被无条件终止。
因此,即使您可以让它访问 LAN(这可能很困难,udev 运行的进程在某种程度上受到限制的环境中),但这也不是启动和停止诸如queuelite之类的东西的正确方法。
尝试例如 systemd 服务,如下所示这个答案。
答案2
正如 @dirkt 已经建议的那样,将 Squeezelite 作为udev
进程启动并不是一个好主意:LAN 访问在udev
某种程度上受到限制,而且该进程无论如何都会在一段时间后被终止。这是将 Squeezelite 作为服务启动的首选方式。
为此,udev
需要定义如下规则:
# cat /etc/udev/rules.d/50-DAC.rules
SUBSYSTEM=="usb", ACTION=="bind", ENV{PRODUCT}=="154e/300a/3", TAG+="systemd", ENV{SYSTEMD_WANTS}="DAC_sql_start.service"
SUBSYSTEM=="usb", ACTION=="unbind", ENV{PRODUCT}=="154e/300a/3", TAG+="systemd", ENV{SYSTEMD_WANTS}="DAC_sql_stop.service"
请注意,我使用了bind
resp。unbind
USB 设备的操作(就我而言)被证明比add
相应的更强大。remove
。另外,由于我不明白的原因,我不得不把ENV{...}
它放在一边......SYSTEMD_WANTS
对应的服务需要定义如下:
# cat /lib/systemd/system/DAC_sql_start.service
[Unit]
Description=Squeezelite by DAC script (start)
[Service]
ExecStart=/usr/bin/DAC_sql.sh start
# cat /lib/systemd/system/DAC_sql_stop.service
[Unit]
Description=Squeezelite by DAC script (stop)
[Service]
ExecStart=/usr/bin/DAC_sql.sh stop
我修改了shell脚本DAC_sql.sh
如下:
# cat /usr/bin/DAC_sql.sh
#!/bin/sh
######### DAC_sql.sh #########
#sleep 5s
case $1 in
"start")
#date >> /tmp/DAC.log
#echo "Starting Squeezelite..." >> /tmp/DAC.log
/usr/bin/squeezelite -o hw:CARD=ND8006,DEV=0 -s 127.0.0.1 -D -n MediaPlayer #-d all=debug -f /tmp/sq.log;;
;;
"stop")
#date >> /tmp/DAC.log
#echo "Stopping Squeezelite..." >> /tmp/DAC.log
systemctl stop DAC_sql_start
;;
esac
##############################
现在它可以按预期工作:每当 USB 设备打开(绑定到系统中)时,Squeezelite 都会作为服务启动。当 USB 设备关闭(与系统解除绑定)时,Squeezelite 服务将停止。