在后台运行inotifywait

7

我有一段从linuxaria.com复制的代码作为示例,对我来说运行良好,但问题在于当我退出终端时,inotifywait停止了。我想让它在后台运行,即使退出终端也能运行。我该怎么做?

#!/bin/sh

# CONFIGURATION
DIR="/tmp"
EVENTS="create"
FIFO="/tmp/inotify2.fifo"


on_event() {
  local date=$1
  local time=$2
  local file=$3

  sleep 5

  echo "$date $time Fichier créé: $file"
}

# MAIN
if [ ! -e "$FIFO" ]
then
  mkfifo "$FIFO"
fi

inotifywait -m -e "$EVENTS" --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %f' "$DIR" >       "$FIFO" &
INOTIFY_PID=$!


while read date time file
do
  on_event $date $time $file &
done < "$FIFO"
5个回答

7
你可以使用screennohup运行脚本,但我不确定这会有什么帮助,因为该脚本似乎没有将其输出记录到任何文件中。
nohup bash script.sh </dev/null >/dev/null 2>&1 &

或者

screen -dm bash script.sh </dev/null >/dev/null 2>&1 &

放弃(disown)也可以使用:
bash script.sh </dev/null >/dev/null 2>&1 & disown

您只需测试哪个版本不允许在终端退出时挂起或挂断命令。

如果您想将输出记录到文件中,可以尝试这些版本:

nohup bash script.sh </dev/null >/path/to/logfile 2>&1 &
screen -dm bash script.sh </dev/null >/path/to/logfile 2>&1 &
bash script.sh </dev/null >/path/to/logfile 2>&1 & disown

7
我把它制作成了一个“服务”。这样,我就可以像普通服务一样停止/启动它,并且它也会在重新启动后启动。
这是在Centos发行版上创建的,所以我不确定它是否可以立即在其他发行版上运行。
在服务目录中创建一个具有可执行权限的文件:
/etc/init.d/servicename
#!/bin/bash

# chkconfig: 2345 90 60

case "$1" in
start)
   nohup SCRIPT.SH > /dev/null 2>&1 &
   echo $!>/var/run/SCRIPT.SH.pid
   ;;
stop)
   pkill -P `cat /var/run/SCRIPT.SH.pid`
   rm /var/run/SCRIPT.SH.pid
   ;;
restart)
   $0 stop
   $0 start
   ;;
status)
   if [ -e /var/run/SCRIPT.SH.pid ]; then
      echo SCRIPT.SH is running, pid=`cat /var/run/SCRIPT.SH.pid`
   else
      echo SCRIPT.SH is not running
      exit 1
   fi
   ;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0

需要将所有大写字母替换为您的脚本名称。

# chkconfig: 2345 90 60使得在系统重新启动时启动服务成为可能。在像Ubuntu这样的发行版中,这可能无法正常工作。


5

我发现最好的方法是创建一个systemd服务。

/lib/systemd/system/checkfile.service中创建systemd文件:

sudo vim /lib/systemd/system/checkfile.service

将这段内容粘贴到那里:

[Unit]
Description = Run inotifywait in backgoround

[Service]
User=ubuntu
Group=ubuntu
ExecStart=/bin/bash /path_to/script.sh
RestartSec=10

[Install]
WantedBy=multi-user.target

/path_to/script.sh 中,你可以这样写:

inotifywait -m /path-to-dir -e create -e moved_to |
    while read dir action file; do
        echo "The file '$file' appeared in directory '$dir' via '$action'" >> /dir/event.txt
    done

确保您的文件可被用户执行:

sudo chmod +x /path_to/script.sh

创建两个文件后,请使用以下命令重新加载systemd管理器配置:
sudo systemctl daemon-reload

现在你可以使用启动/停止/启用您的脚本:

sudo systemctl enable checkfile
sudo systemctl start checkfile

在执行之前,请确保替换文件/目录/用户/组的值。


谢谢,这对我很有帮助。我想监视一个文件夹以获取新文件,并通过 Telegram 发送文件名。 - alneven

1

用-m替换为

-d -o /dev/null

例如:

inotifywait -d -o /dev/null -e "$EVENTS" --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %f' >"$DIR" > "$FIFO" & INOTIFY_PID=$!

您可以在以下网址查看inotifywait帮助手册:

https://helpmanual.io/help/inotifywait/


请注意,在使用inotifywait -d时,您不能添加任何管道操作。它只会将输出打印到文件中-> 在这种特定情况下,它实际上什么都不做,因为您将输出设置为空。因此,inotifywait的-d用法非常有限。 - Airstriker

0

即使要监视的文件尚不存在或在此期间被删除,也能正常工作的方法(只需监视整个目录而不是单个文件,然后对特定文件执行操作):

nohup inotifywait -m -e close_write /var/opt/some_directory/ |
while read -r directory events filename; do
  if [ "$filename" = "file_to_be_watched.log" ]; then
    # do your stuff here; I'm just printing the events to file
    echo "$events" >> /tmp/events.log
  fi
done &

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