如何在 Udev 事件上运行长时间进程?

如何在 Udev 事件上运行长时间进程?

我想运行一个点对点连接 USB 调制解调器时进行连接,因此我使用以下udev规则:

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="16d8",\
    RUN+="/usr/local/bin/newPPP.sh $env{DEVNAME}"

(我的调制解调器显示/devttyACM0

新PPP.sh:

#!/bin/bash
/usr/bin/pon prov $1 >/dev/null 2>&1 &

问题:

udev事件触发,并且 newPPP.sh 正在运行,但newPPP.sh进程在大约 4-5 秒后被终止。ppp没有时间连接(拨号超时为10秒)。

如何才能运行长时间的进程而不被杀死?

我尝试使用nohup,但它也不起作用。

系统:Arch Linux

更新

我找到了解决方案这里, 谢谢马克斯施莱普齐格

我用来at now运行与 udev 进程分离的工作。

但有一个问题仍然没有得到解答:为什么有效nohup而不&有效?

答案1

如果您运行一个具有 systemd 支持的不错的发行版,最简单且技术上最安全的方法是使用设备单元

这样,systemd 将完全控制长时间运行的脚本,甚至能够在设备关闭/删除后正确终止进程 - 分离进程意味着您放弃对进程状态的完全控制及其历史。

除此之外,您还可以通过运行来检查设备及其附加服务的状态systemctl status my-ppp-thing.device

也可以看看这篇博文有关更多示例和详细信息。

答案2

如今,udev 使用 cgroup 来搜索并销毁生成的任务。一种解决方案是使用“现在”或“批量”。另一个解决方案是做双叉并将进程“迁移”到另一个 cgroup。这是一个示例 python 代码(类似的代码可以用任何语言编写):

os.closerange(0, 65535)  # just in case
pid = os.fork()
if not pid:
  pid = os.fork()  # fork again so the child would adopted by init
  if not pid:
    # relocate this process to another cgroup
    with open("/sys/fs/cgroup/cpu/tasks", "a+") as fd:
      fd.write(str(os.getpid()))
    sleep(3)  # defer execution by XX seconds
    # YOUR CODE GOES HERE
sleep(0.1)  # get forked process chance to change cgroup

调试输出可以发送到例如系统日志。

答案3

我让它与setsid一起工作。我的 udev 规则的 RUN 部分:

RUN+="/bin/bash script.sh"

然后在脚本中:

#!/bin/bash
if [ "$1" != "fo_real" ]; then
  /usr/bin/setsid $(/usr/bin/dirname $0)/$(/usr/bin/basename $0) fo_real &
  exit
fi

Rest of script is here....

对脚本的第一次调用返回退出状态 0,但对脚本的第二次调用继续运行,且 PPID = 1。

答案4

不知道为什么它被杀死,但我发现这个有效:

RUN+="/bin/bash -c 'YOUR_SCRIPT &'"

似乎当 Bash 只剩下后台作业时,它本身就会进入后台。

相关内容