如何连续运行 inotifywait 并将其作为 cron 或守护进程运行?
Posted
技术标签:
【中文标题】如何连续运行 inotifywait 并将其作为 cron 或守护进程运行?【英文标题】:How to run inotifywait continuously and run it as a cron or deamon? 【发布时间】:2016-02-06 12:29:14 【问题描述】:我构建了一个shell
脚本,它使用inotifywait
自动检测特定目录上的文件更改。当一个新的 PDF 文件被放到目录中时,这个脚本应该会关闭,然后它应该触发 ocropus-parser
以对其执行一些命令。代码:
#!/bin/sh
inotifywait -m ~/Desktop/PdfFolder -e create -e moved_to |
while read path action file; do
#echo "The file '$file' appeared in directory '$path' via '$action'"
# Check if the file is a PDF or another file type.
if [ $(head -c 4 "$file") = "%PDF" ]; then
echo "PDF found - filename: " + $file
python ocropus-parser.py $file
else
echo "NOT A PDF!"
fi
done
当我通过终端使用./filenotifier.sh
运行此脚本时,这非常有效,但是当我重新启动我的Linux
(Ubuntu 14.04)时,我的 shell 将不再运行,并且在重新启动后也不会重新启动。
我决定创建一个在启动时启动的初始化脚本(我认为)。我通过将文件filenotifier.sh
复制到init.d
来做到这一点:
sudo cp ~/Desktop/PdfFolder/filenotifier.sh /etc/init.d/
然后我给了文件正确的权限:
sudo chmod 775 /etc/init.d/filenotifier.sh
最后我把文件添加到update-rc.d
:
sudo update-rc.d filenotifier.sh defaults
但是,当我重新启动并将 PDF 放入文件夹 ~/Desktop/PdfFolder
时,什么都不会发生,而且脚本似乎没有运行。
我真的没有使用init.d
、update-rc.d
和deamon
的经验,所以我不确定出了什么问题,以及这是否是一个好方法。
谢谢, 延特
【问题讨论】:
您的意思是“cron”还是“crohn”?除了疾病,我找不到任何关于“克罗恩”的信息。cron
也可能是一种疾病,具体取决于它的配置方式。
@ErikAllik 感谢您的提醒,我已经更正了自己!还有 Frédéric,这已经让我觉得我使用 cron 做出了错误的选择?
@Yenthe,好吧,cron
并不是真正适合安排脚本在启动时运行的工具。修改 rc.local
(或您的发行版的等价物)似乎是一个更好的主意。
您是以root
还是其他用户的身份运行脚本。如果它由非 root 用户运行,则 ~/Desktop/PdfFolder
路径将不会指向预期位置(因为初始化脚本由 root
运行)。
【参考方案1】:
作为一个初始化脚本,您应该将LSB header 添加到您的脚本中,如下所示:
#!/bin/sh
### BEGIN INIT INFO
# Provides: filenotifier
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Something
# Description: Something else
### END INIT INFO
inotifywait -m ...
这样,您可以确保您的脚本在所有挂载点都可用时运行(感谢Required-Start: $remote_fs
)。如果您的主目录不在根分区上,这是必不可少的。
另一个问题是在你的初始化脚本中你使用的是~
:
inotifywait -m ~/Desktop/PdfFolder ...
~
扩展为当前用户主目录。初始化脚本以 root 身份运行,因此它将扩展为 /root/Desktop/PdfFolder
。请改用~<username>
:
inotifywait -m ~yenthe/Desktop/PdfFolder ...
(假设您的用户名是yenthe
。)
或者在开始之前切换用户(使用sudo
)。
$file
是没有目录路径的基本名称。在你的命令中使用"$path/$file"
:
"$(head -c 4 "$path/$file")"
python ocropus-parser.py "$path/$file"
也许可以考虑使用name
而不是file
,以避免混淆。
如果事情不正常,或者如果你想调查一些事情,记得使用ps
,像这样:
ps -ef | grep inotifywait
ps
会告诉您,例如,您的脚本是否正在运行,以及 inotifywait
是否使用正确的参数启动。
最后一点:使用"$file"
,而不是$file
;使用"$(head -c 4 "$file")"
,而不是$(head -c 4 "$file")
;使用read -r
,而不是read
。这些提示可以为您省去很多麻烦!
【讨论】:
非常感谢您的回答,这很好!我有一个奇怪的问题。当我从 Desktop/PdfFolder 运行 filenotifier.sh 时,它会正常工作并检测文件。当我从 /etc/init.d 中运行它并将文件放入文件夹中时,我会收到错误消息:head: cannot open ‘test.pdf’ for reading: No such file or directory
为什么会这样?它知道文件和路径,因为它可以打印名称。头部的代码现在看起来像这样:if [ "$(head -c 4 "$file")" = "%PDF" ]; then
@Yenthe: $file
是没有路径的基本名称。使用"$path/$file"
这很有意义。我想知道另外两件事:为什么我应该使用"$file"
代替$file
,为什么我应该使用read -r
代替read
?非常感谢您的时间和详细的回答!我见过的最好的答案之一。
@Yenthe: 如果$file
包含空格,那么它将扩展为多个参数(试试看)。如果$file
包含shell 代码,情况会更糟:该代码将被执行(不要尝试)! -r
选项告诉read
忽略反斜杠转义。尝试创建一个名为例如的文件\n
我从来不知道这个,非常感谢。顺便接受并支持您的答案!保持良好的工作。 :-)【参考方案2】:
为此,inotify
的开发人员创建了incron
。它是一个类似于 cron 的守护进程,它根据监视的文件/目录中的更改而不是时间事件来执行脚本。
【讨论】:
使用 incron 代替 inotifywait 有很大的好处吗?从本质上讲,它似乎与我制作 update-rc.d 并在其中添加命令一样吗? 最好维护。它有日志工具等。正如我所说,inotify 的开发人员(包括 inotifywait 之类的工具)创建了它。以上是关于如何连续运行 inotifywait 并将其作为 cron 或守护进程运行?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spring Boot 微服务 Extern log4j.properties 文件并将其作为 Linux 服务运行?
使用 plexus-compiler-eclipse 编译 java 类并将其作为 JUnit 测试运行