我正在编写一个 runit 服务,根据这个答案在解锁时重新启动 picomhttps://unix.stackexchange.com/a/439492/161514
#!/bin/bash
OBJECT_PATH=/org/freedesktop/login1/session/$XDG_SESSION_ID
BUS_NAME=org.freedesktop.login1
UNLOCK="$OBJECT_PATH: $BUS_NAME.Session.Unlock ()"
MONITOR_COMMAND="gdbus monitor --system --dest $BUS_NAME --object-path $OBJECT_PATH"
log () {
echo "$(date +'%F %T.%3N') [$$]" "$@"
}
while read -r signal; do
log $signal
if [ "$signal" = "$UNLOCK" ]; then
log "Restaring picom after unlock."
SVDIR=$XDG_SERVICE_HOME sv restart picom
fi
done < <(exec $MONITOR_COMMAND)
问题是,当我停止服务时,gdbus 进程不会被终止。我可以猜测这是因为脚本本身有两个进程,然后 gdbus 和服务停止只会停止脚本而不是 gdbus。
我的问题是我可以以某种方式重写此服务来实现我想要的目的,以便停止服务 gdbus 监控也会停止吗?
答案1
经过一番搜索后,我意识到这是一个普遍问题,并非特定于 runit。我可以使用 coproc 将监控作为异步进程运行,并确保在我的主脚本中,如果出现任何术语信号,我将杀死我的子进程。
这是脚本,以防有人感兴趣
#!/usr/bin/env bash
OBJECT_PATH=/org/freedesktop/login1/session/$XDG_SESSION_ID
BUS_NAME=org.freedesktop.login1
UNLOCK="$OBJECT_PATH: $BUS_NAME.Session.Unlock ()"
MONITOR_COMMAND="gdbus monitor --system --dest $BUS_NAME --object-path $OBJECT_PATH"
log () {
echo "$(date +'%F %T.%3N') [$$]" "$@"
}
cleanup() {
# kill all processes whose parent is this process
pkill -P $$
}
for sig in INT QUIT HUP TERM; do
trap "
cleanup
trap - $sig EXIT
kill -s $sig "'"$$"' "$sig"
done
coproc $MONITOR_COMMAND
while read -r signal <&"${COPROC[0]}"; do
log $signal
if [ "$signal" = "$UNLOCK" ]; then
log "Restaring picom after unlock."
SVDIR=$XDG_SERVICE_HOME sv restart picom
fi
done
trap cleanup EXIT