incrond进程仅在脚本退出代码为1时退出?

4

配置

我在CentOS 7.6上安装了版本为0.5.12的incrond,并在/etc/incron.d/example中进行了如下配置:

/var/tmp/dir IN_CREATE sh /root/incron_script.sh $@/$#

我的/root/incron_script.sh文件包含以下简单内容:echo "$@" >> /tmp/incrond_log.log

这意味着,当我在var/tmp/dir目录中创建一个文件时,该文件的完整路径将被追加到/tmp/incrond_log.log文件中。就是这样。

问题定义

问题基本上是如果incrond被配置为调用一个shell脚本,那么除非该shell脚本以非0的状态退出,否则将会创建进程并且不会停止。 我所看到的是systemctl status incrond (或 ps aux | grep ...,同样的结果) 的输出结果。

例如,下面有2个已创建的进程。

[root@server ~]# systemctl status incrond
● incrond.service - Inotify System Scheduler
   Loaded: loaded (/usr/lib/systemd/system/incrond.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-12-11 13:39:55 +03; 11min ago
  Process: 16746 ExecStart=/usr/sbin/incrond (code=exited, status=0/SUCCESS)
 Main PID: 16747 (incrond)
    Tasks: 498
   Memory: 5.9M
   CGroup: /system.slice/incrond.service
           ├─13687 /usr/sbin/incrond
           ├─13747 /usr/sbin/incrond

测试

我们创建5个文件,检查它们的名称是否被追加到日志中(incrond正在工作),并检查有多少进程被生成。

mkdir -p /var/tmp/dir
rm -f /var/tmp/dir/*
echo -n > /tmp/incrond_log.log
systemctl restart incrond
for i in $(seq 1 5);
do
    touch /var/tmp/dir/a$i.txt
    sleep 0.5
    tail -n1 /tmp/incrond_log.log
    systemctl status incrond | grep /usr/sbin/incrond | wc -l
done

预期结果

我希望incrond会为在此目录创建的每个文件派生一个进程,但由于实际上没有太多要做的事情,所以立即退出。 如果日志显示文件路径在日志文件中,则这意味着incrond进程应该已经停止,因为它完成了其工作。 默认情况下,在systemctl status incrond中有2个进程,因此该命令的预期结果是:

/var/tmp/dir/a1.txt
2
/var/tmp/dir/a2.txt
2
/var/tmp/dir/a3.txt
2
/var/tmp/dir/a4.txt
2
/var/tmp/dir/a5.txt
2

实际结果

实际结果为:

/var/tmp/dir/a1.txt
3
/var/tmp/dir/a2.txt
4
/var/tmp/dir/a3.txt
5
/var/tmp/dir/a4.txt
6
/var/tmp/dir/a5.txt
7

诊断

问题表现为僵尸进程:

root      1540  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      1551  0.0  0.0  12784   672 ?        S    19:49   0:00 /usr/sbin/incrond
root      1553  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      1566  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      1576  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      2339  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      2348  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      2351  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      2355  0.0  0.0  12784   224 ?        S    19:49   0:00 /usr/sbin/incrond
root      5471  0.0  0.0      0     0 ?        Z    19:17   0:00 [incrond] <defunct>
root      5480  0.0  0.0      0     0 ?        Z    19:17   0:00 [incrond] <defunct>
root      5483  0.0  0.0      0     0 ?        Z    19:17   0:00 [incrond] <defunct>
root      5561  0.0  0.0      0     0 ?        Z    19:17   0:00 [incrond] <defunct>
root      8012  0.0  0.0      0     0 ?        Z    19:12   0:00 [incrond] <defunct>
root      8023  0.0  0.0      0     0 ?        Z    19:12   0:00 [incrond] <defunct>
root      8025  0.0  0.0      0     0 ?        Z    19:12   0:00 [incrond] <defunct>
root      8148  0.0  0.0      0     0 ?        Z    19:12   0:00 [incrond] <defunct>

这是我能够检查的范围。我不知道如何进一步查看。

解决方法

如果我使用exit 1而不是常规退出,进程会正确退出。因此,我的/root/incron_script变成了:echo "$@" >> /tmp/incrond_log.log && exit 1。 现在我的状态看起来像:

[root@server ~]# systemctl status incrond
● incrond.service - Inotify System Scheduler
   Loaded: loaded (/usr/lib/systemd/system/incrond.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-12-11 14:09:04 +03; 16s ago
  Process: 7882 ExecStart=/usr/sbin/incrond (code=exited, status=0/SUCCESS)
 Main PID: 7888 (incrond)
    Tasks: 6
   Memory: 220.0K
   CGroup: /system.slice/incrond.service
           └─7888 /usr/sbin/incrond

Dec 11 14:09:09 server.example.com incrond[7888]: PATH (/var/tmp/dir) FILE (a1.txt) EVENT (IN_CREATE)
Dec 11 14:09:09 server.example.com incrond[7888]: (system::example) CMD (sh /root/incron_script.sh /var/tmp/dir/a1.txt )
Dec 11 14:09:10 server.example.com incrond[7888]: PATH (/var/tmp/dir) FILE (a2.txt) EVENT (IN_CREATE)
Dec 11 14:09:10 server.example.com incrond[7888]: (system::example) CMD (sh /root/incron_script.sh /var/tmp/dir/a2.txt )
Dec 11 14:09:10 server.example.com incrond[7888]: PATH (/var/tmp/dir) FILE (a3.txt) EVENT (IN_CREATE)
Dec 11 14:09:10 server.example.com incrond[7888]: (system::example) CMD (sh /root/incron_script.sh /var/tmp/dir/a3.txt )
Dec 11 14:09:11 server.example.com incrond[7888]: PATH (/var/tmp/dir) FILE (a4.txt) EVENT (IN_CREATE)
Dec 11 14:09:11 server.example.com incrond[7888]: (system::example) CMD (sh /root/incron_script.sh /var/tmp/dir/a4.txt )
Dec 11 14:09:11 server.example.com incrond[7888]: PATH (/var/tmp/dir) FILE (a5.txt) EVENT (IN_CREATE)
Dec 11 14:09:11 server.example.com incrond[7888]: (system::example) CMD (sh /root/incron_script.sh /var/tmp/dir/a5.txt )

问题

这是预期的行为吗?为什么使用exit 0会保持进程的生存,而使用exit 1却不会?这个文档在哪里可以找到?你有什么进一步调试的建议吗?

更新

  • 2018-12-12: 添加了诊断(僵尸线程)

你的问题非常详细,感谢您提供这些信息。但很抱歉,它不符合SO的主题。但是,在superuser.com上它是符合主题的,那里会有更多人能够回答您的问题。 - hek2mgl
关于这个话题,我认为你的期望可能是错误的。incron 可能会在它们完成后保持分支并重用它们进行其他工作,这有点像池化。其他守护程序也会这样做,但我不确定 incron 是否也是如此。 - hek2mgl
啊,我明白了。 如果是这种情况的话,退出1表示我们需要完全停止fork,因为出现了问题,而退出0则表示如果需要重用fork,则可以保持fork的活动状态。 但是达到11,000个进程和400 MB的内存(并将其挂起数小时)确实不太好(如果我离开它,它可能会继续运行)。 因此,如果是这种情况,那么这就是incrond中池管理问题。 - Jbezos
哦!不,11,000个进程可以被视为一个问题,而不是池化! :) - hek2mgl
这似乎是RedHat发行版上incron 0.5.12的一个更大问题的一部分(incron/issues/52incron/issues/53)。 - Jbezos
1个回答

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接