当存在来自不同来源的两个文件时,我需要启动一个命令。每个文件可能在不同的时间到达,但我希望在收到两个文件时触发命令。我尝试使用 incrond 来执行此操作,观察两个目录中的 IN_CLOSE_WRITE 和 IN_MOVED_TO。
/dir/path1 IN_CLOSE_WRITE,IN_MOVED_TO command
/dir/path2 IN_CLOSE_WRITE,IN_MOVED_TO command
问题是:当第一个监视触发后,如何等待第二个监视?
例如:
时间:12:05 UTC - 文件1 到达路径1 命令正在等待路径2 监视
时间:12:09 UTC - 文件2 到达路径2 命令启动
该命令是用 Go 编码的,但我找不到任何能帮助我的东西。
更具体地说,该系统的工作原理如下:有两个远程服务器以 6 小时为周期,以相同的周期在 pcap 中记录数据。它们记录相同的信息,但来自不同的 VLAN。记录完成后,它们将上传到主服务器的两个不同目录中。需要上传两个记录才能进行比较和混合它们,丢弃重复的数据包。记录并不总是以相同的顺序上传,也不会同时到达。这取决于远程服务器和主服务器之间的通信。
文件名始终是相同的模式:_yyyymmddTHHMMSS.pcap。例如,文件开始录制 2020-10-15 18:01:00:
文件1:vlan1_20201015T180100.pcap
文件2:vlan2_20201015T180100.pcap
我正在寻找与 incrond 和 bash 相关的解决方案或 Go 命令内的解决方案。解决方案或线索,因为我目前处于停滞状态。
答案1
我会创建一个由 incrond 调用的包装脚本,类似
if [ -f /dir/path1 -a -f /dir/path2 ]; then
command
else
echo "both files don't exist yet"
fi
每次文件触发 IN_CLOSE_WRITE 或 IN_MOVED_TO 时都会运行此操作,但只有当两个文件都存在时才会运行。
更新
根据评论,似乎有必要跟踪上传文件的完成状态。(我没有测试以下内容)这个想法是记录上传文件的完成情况,并且
#!/bin/bash
# $@ set to event filename by incrond
filepath=$@
# this assumes both files are in the same directory, otherwise you would
# have to do some logic which switches directories as well as filename
# check file matches pattern
if [[ "${filepath}" =~ vlan.*\.pcap$ ]]; then
# mark current file as completed
if [ ! -f "${filepath}.complete" ]; then
touch "${filepath}.complete"
fi
filename=$(basename ${filepath})
dirname=$(dirname ${filepath})
# find other filename by toggling vlan number
vlan_num=${filename:4:1}
[[ "${vlan_num}" == "1" ]] && vlan_alt=2 || vlan_alt=1
# construct the other filename
other_file=${dirname}$/{filename:0:4}${vlan_alt}${filename:5}
echo $other_file;
# see if other filename completion file exists
if [ -f "${other_file}.complete" ]; then
command
else
# other file not uploaded yet
echo "completion file for both files not exists"
fi
else
echo "file didn't match pattern"
fi
答案2
另一个解决方法是使用 lsof。此解决方案必须以 root 身份运行。
root 密码
/path/to/vlan1 IN_CLOSE_WRITE,IN_MOVED_TO /usr/local/bin/monitor.sh $@/$# /path/to/vlan2
/path/to/vlan2 IN_CLOSE_WRITE,IN_MOVED_TO /usr/local/bin/monitor.sh $@/$# /path/to/vlan1
包装脚本
#!/bin/bash
# monitor.sh
FILE_FINISHED=$1
FIND_PATH=$2
f=`basename $FILE_FINISHED`
FILE2=`ls $FIND_PATH/*${f:11:13}*`
STATUS=$?
if [ $STATUS -eq 0 ]
then
lsof $FILE2 > /dev/null 2>&1
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Command"
else
echo "Still uploading"
fi
else
echo "File not exist"
fi