【问题标题】:monitoring and searching a file with inotify, and command line tools使用 inotify 和命令行工具监视和搜索文件
【发布时间】:2020-04-19 14:03:49
【问题描述】:

日志文件由水下无人机在服务器上逐行写入。 T在水面时,无人机与服务器的通话速度很慢(例如在不稳定的电话线上约 200o/s)并且只是不时地(例如每约 6 小时一次)。根据消息,当无人机在线以及挂断其他命令时,我必须在服务器上执行命令。其他进程可能正在查看具有相似任务的相同文件。

在这个网站上可以找到很多类似的问题,但我建立的解决方案仍然不能令人满意。目前我正在用 bash 做这个

while logfile_drone=`inotifywait -e create --format '%f' log_directory`; do

    logfile=log_directory/${logfile_drone}

    while action=`inotifywait -q -t 120 -e modify  -e close --format '%e' ${logfile} ` ; do

        exidCode=$?
        lastLine=$( tail -n2  ${logFile} | head -n1 ) # because with tail -n1 I can got only part of the line. this happens quite often
        match =$( # match set to true if lastLine matches some pattern )

        if [[ $action == 'MODIFY' ]] && $match ; then # do something ; fi

        if [[ $( echo $action | cut -c1-5 ) == 'CLOSE' ]] ; then 
            # do something
            break
        fi  

        if [[ $exitCode -eq 2 ]] ; then break ; fi  

    done

    # do something after the drone has hang up

done # wait for a new call from the same or another drone

主要问题是:

  1. 第二个 inotify 丢失行,可能是因为其他进程正在查看同一文件。

  2. 我赶时间的方式似乎不起作用。

  3. 我无法同时监控 2 架无人机。

基本上,代码或多或少可以工作,但不是很健壮。我想知道问题 3 是否可以通过将第二个 while 循环放在调用时置于后台的函数中来管理。最后,我想知道高级语言(我熟悉 php,它具有用于 inotify 的 PECL 扩展)是否会做得更好。但是,我认为 php 不会比 bash 更好地解决问题 3。

这是我面临突然退出while循环问题的代码,根据Philippe's答案实现,否则效果很好:

    while read -r action ; do
        ...
        resume=$( grep -e 'RESUMING MISSION' <<< $lastLine )
        if [ -n "$resume" ] ; then
            ssh user@another_server "/usr/bin/php /path_to_matlab_command/matlabCmd.php --drone=${vehicle}" &
        fi

        if [  $( echo $action | cut -c1-5 ) == 'CLOSE' ] ; then ... ; sigKill=true ; fi
        ...
        if $sigKill ; then break; fi

    done < <(inotifywait -q -m -e modify  -e close_write   --format '%e' ${logFile})

当我用 ssh 注释该行时,脚本可以正确退出并由 CLOSE 触发中断,否则 while loop 在 ssh 命令后突然结束。由于matlab代码运行时间长,ssh被置于后台。

【问题讨论】:

    标签: bash tail inotifywait


    【解决方案1】:

    monitor mode (-m)inotifywait 在这里可能会更好:

    inotifywait -m -q -e create -e modify -e close log_directory |\
    while read -r dir action file; do
        ...
    done
    

    monitor mode (-m) 不缓冲,它只是将所有事件打印到标准输出。

    保留变量:

    while read -r dir action file; do
        echo $dir $action $file
    done < <(inotifywait -m -q -e create -e modify -e close log_directory)
    
    echo "End of script"
    

    【讨论】:

    • 是的Philippe,这种编码效率更高,似乎解决了之前丢行的问题。是因为inotifywait -m 缓冲了文件上发生的事件吗?不过我给了一个简化版的脚本,我要杀了这个inotifywait -m。这会导致擦除在 while 循环中分配的所有变量。如何保存它们?
    • 再次感谢Philippe。此解决方案避免杀死inotifywait,因为当脚本被触发退出时,一个简单的中断就足够了。但它产生了一个新问题。在while loop 内部,有一个ssh other_machine do_something &amp; 由在日志中找到的某个关键字触发,这使得while loop 中断。可能是因为ssh 将成功(或失败)消息发送回与&lt; &lt;(inotifywait ...) 冲突的脚本??
    • ssh 似乎没有问题。以下部分确实有问题,比如==应该是=
    • 奇怪。实际上,if [ $( echo $action | cut -c1-5 ) == 'CLOSE' ](不是标准的,这是真的,但是我已经改变了它)可以工作。带有 ssh 注释的脚本(没有其他更改)具有上述两种行为。我在模拟模式下对此进行了测试,因为我不想浪费与无人机的真实通信,这种通信仅每 6 小时发生一次。
    • 我刚刚重新完成了测试:使用 ssh,我得到了read: Erreur de lecture : 0 : Ressource temporairement non disponible 并退出了循环。如果脚本在 inotifywait 中自行杀死它,我会得到完全相同的消息。没有ssh,它可以正常工作。
    猜你喜欢
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    相关资源
    最近更新 更多