cron.d 脚本启动后就停止了

cron.d 脚本启动后就停止了

许多堆栈帖子似乎暗示了类似的事情:

* * * * * root /usr/bin/pgrep -f 'socat -T10 TCP4-LISTEN:22222,fork UDP4:localhost:22223' || (/usr/bin/socat -T10 TCP4-LISTEN:22222,fork UDP4:localhost:22223 &)

可以作为cron文件中的一行程序工作(例如/etc/cron.d/mycron),但在使用标准的 Ubuntu 22.04 上根本不起作用。如果我直接执行它,或者将它放入脚本文件中,然后从 cron 运行脚本文件(使用或,同样的事情),cron它显然可以正常工作。bashsh

* * * * * root /bin/sh /root/myscript.sh

从尝试获取日志来看,它看起来像进程被启动,但随后被杀死。我尝试了许多不同级别的包围,&最后有和没有。都没有用。我做错了什么?

答案1

分析

您的 cron 运行sh -c …,其中表示单个参数是您在 crontab 中放置在 之后的字符串* * * * * root。此字符串显然包含您要传递给 的模式pgrep。实际上pgrep至少找到此sh进程并报告成功,socat未执行并sh退出。

如果/bin/sh /root/myscript.sh后面的参数sh -c不包含模式。这就是此方法有效的原因。

请注意,的参数pgrep也匹配模式,但从pgrep不报告自己匹配。如果报告了,它实际上就毫无用处了。通过pgrep在 crontab 中直接使用,您可以设置一种情况,即它总是找到其父级(sh)并且不知道它不应该找到。


解决方案

使用此行:

* * * * * root /usr/bin/pgrep -f '^socat -T10 TCP4-LISTEN:22222,fork UDP4:localhost:22223$' || (/usr/bin/socat -T10 TCP4-LISTEN:22222,fork UDP4:localhost:22223 &)

^位于模式开头的命令匹配开头,$位于模式结尾的命令匹配结尾。现在只有完全匹配的命令socat -T10 TCP4-LISTEN:22222,fork UDP4:localhost:22223才会匹配;sh -c …否则不会匹配。


简化

我认为这个特定的命令您可以简单地每分钟异步运行它:

* * * * * root /usr/bin/socat -T10 TCP4-LISTEN:22222,fork UDP4:localhost:22223 &

socat如果监听的端口已被占用,则要点是退出。但是 Cron 不会看到失败,因为whatever &它始终返回退出状态 0。

请注意,一般来说,您不能盲目地使用这种简化。我们的socat自动退出这一事实至关重要。除了每分钟启动的socat(甚至socat使用不同的参数)之外的工具可能会存活并积累。一般来说pgrep很有用。

相关内容