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

tcbh2hod  于 2023-06-24  发布在  Shell
关注(0)|答案(6)|浏览(152)

有人知道如何在bash脚本中锁定函数吗?我想做一些像在java(如同步),确保每个文件保存在监控文件夹是在任何时候都试图使用提交功能。
我的剧本摘录:

(...) 

 ON_EVENT () {
   local date = $1
   local time = $2
   local file = $3
   sleep 5
   echo "$date $time New file created: $file"
   submit $file
}

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

 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=$!

 trap "on_exit" 2 3 15

 while read date time file
do
  on_event $date $time $file &
done < "$FIFO"

 on_exit

我正在使用inotify来监视一个文件夹,当一个新文件被保存时。对于保存(接收)的每个文件,提交到VirusTotal服务(avsubmit.py)和TreathExpert(dbmgr.py)。并发访问将是理想的,以避免阻止每个新文件创建的监控文件夹,但锁定提交功能应该是足够的。
谢谢你们!

pftdvrlh

pftdvrlh1#

类似这样的东西应该可以工作:

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
7fhtutme

7fhtutme2#

任何使用rmtrap或类似工具组合使用的代码,在防止不体面的杀戮、恐慌、系统崩溃、新手系统管理员等方面都存在固有缺陷。该缺陷是在发生此类灾难性事件后需要手动清除锁,以便脚本再次运行。这对你来说可能是个问题,也可能不是。对于那些管理许多机器或希望偶尔有一个不插电的假期的人来说,这是一个问题。
使用文件描述符锁的现代解决方案已经存在了一段时间-I detailed it herea working example is on the GitHub here。如果出于任何监视或其他原因不需要跟踪进程ID,那么有一个关于自锁的有趣建议(我没有尝试过,不确定它的可移植性保证)。

rt4zxlrg

rt4zxlrg3#

您可以使用lock file来确定是否应提交文件。
ON_EVENT函数中,在调用submit函数之前,应该检查是否存在适当的锁文件。如果它确实存在,则返回,或者睡眠并稍后再次检查以查看它是否消失。如果它不存在,那么创建锁并调用submitsubmit函数完成后,删除锁文件。
有关实现细节,请参见this thread

nnsrf1az

nnsrf1az4#

但我喜欢的是,文件不能得到锁定停留在等待列表(缓存)上提交,然后或以后。
我目前有这样的东西:

lockfile="./lock" 

 on_event() {
  local date=$1
  local time=$2
  local file=$3
  sleep 5
  echo "$date $time New file created: $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 "Failed to acquire lockfile: $lockfile." 
     echo "Held by $(cat $lockfile)"
  fi
}

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

感谢你的评分

piwo6bdm

piwo6bdm5#

我用这种方法遇到了问题,并找到了更好的解决方案:
Procmail附带了一个lockfile命令,它可以实现我想要的功能:

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

lockfile将尝试创建指定的lockfile。如果存在,则将在5秒内重试,最多重复10次。如果可以创建文件,它将继续使用脚本。
另一个解决方案是debian中的lockfile-progs,例如直接来自手册页:

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
e5nqia27

e5nqia276#

如果你安装了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

相关问题