Bash脚本函数中的并发或锁访问

3

有人知道如何在bash脚本中锁定函数吗?我想做类似于Java中的同步(synchronize)操作,确保每个保存在监视文件夹中的文件都被暂停,直到尝试使用submit函数。

以下是我的脚本摘录:

(...)

ON_EVENT () { 本地日期 = $1 本地时间 = $2 文件 = $3 睡眠 5 回显“$date $time 新文件已创建:$file” 提交 $file }

提交 () { 文件 = $1 python avsubmit.py -f $file -v python dbmgr.py -a $file }

如果 [ ! -e“$FIFO”]; 然后 mkfifo“$FIFO” fi

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

陷阱"on_exit"2 3 15

当读取日期时间文件时 做 on_event $date $time $file & 完成 <“$FIFO”

on_exit

我正在使用inotify监视文件夹,当保存新文件时。对于每个保存的文件(接收),请将其提交到VirusTotal服务(avsubmit.py)和TreathExpert(dbmgr.py)。 并发访问是理想的,以避免阻塞在监视文件夹中创建的每个新文件,但锁定提交函数应该足够。

谢谢你们!

6个回答

6

应该可以像这样:

if (set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then
   trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
   # Your code here
   rm -f "$lockfile"
   trap - INT TERM EXIT
else
   echo "Failed to acquire $lockfile. Held by $(cat $lockfile)"
fi

3
任何在使用rmtrap或类似设施相结合的代码都存在着不完善的因素,如不优雅的退出、紧急情况、系统崩溃、新手系统管理员等。这个缺陷是由于脚本在此类灾难性事件发生后需要手动清除锁定才能再次运行。对于管理多台机器或希望偶尔放松一下的人来说,这可能是一个问题。现代解决方案使用文件描述符锁已经有一段时间了- 我在这里详细介绍了它,并且GitHub 上也有一个工作示例。如果您不需要为任何监视或其他原因跟踪进程 ID,有一个有趣的自锁建议(我没有尝试过,也不确定它的可移植性保证)。

谢谢。我刚刚使用了你的羊群解决方案的一个版本。效果很好。 - DoxyLover

1

您可以使用锁文件来确定是否应提交该文件。

在您的ON_EVENT函数中,在调用submit函数之前,应检查是否存在适当的锁文件。如果存在,则返回或休眠并稍后再次检查以查看它是否已消失。如果不存在,则创建锁并调用submit。在submit函数完成后,删除锁文件。

有关实现详细信息,请参见此线程


0

但我喜欢文件不能被锁定,停留在等待列表(缓存)中,以便随后提交。

我目前有类似这样的东西:

lockfile="./lock"

on_event() { local date=$1 local time=$2 local file=$3 sleep 5 echo "$date $time 新文件已创建: $file" if (set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT submit_samples $file rm -f "$lockfile" trap - INT TERM EXIT else
echo "无法获取锁定文件: $lockfile." echo "被 $(cat $lockfile) 占用" fi }

submit_samples() { local file=$1 python avsubmit.py -f $file -v python dbmgr.py -a $file }

再次感谢您...


0

如果你已经安装了GNU Parallel http://www.gnu.org/software/parallel/,你可以这样做:

inotifywait -q -m -r -e CLOSE_WRITE --format %w%f $DIR | 
parallel -u python avsubmit.py -f {}\; python dbmgr.py -a {}

当文件被写入(并关闭)时,它最多会在每个CPU上运行一个Python。这样,您可以绕过所有锁定,并获得额外的好处,即避免潜在的竞争条件,其中文件立即被覆盖(如何确保检查了第一和第二个版本?)。

您可以通过以下方式简单地安装GNU Parallel:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

观看GNU Parallel的介绍视频以了解更多信息: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

0

我在使用这种方法时遇到了问题,后来找到了更好的解决方案:

Procmail带有一个lockfile命令,可以实现我想要的功能:

lockfile -5 -r10 /tmp/lock.file
do something very important
rm -f /tmp/lock.file

lockfile 将尝试创建指定的锁定文件。如果它已经存在,它将在 5 秒钟后重试,最多重试 10 次。如果可以创建该文件,则继续执行脚本。

另一种解决方案是 Debian 中的 lockfile-progs,例如直接从 man 页面:

Locking a file during a lengthy process:

     lockfile-create /some/file
     lockfile-touch /some/file &
     # Save the PID of the lockfile-touch process
     BADGER="$!"
     do-something-important-with /some/file
     kill "${BADGER}"
     lockfile-remove /some/file

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