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

时间:2011-02-08 17:29:12

标签: bash function shell concurrency

有谁知道如何锁定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)。 并发访问将是理想的,以避免阻止在受监视文件夹中创建的每个新文件,但锁定提交功能应该足够。

谢谢你们!

6 个答案:

答案 0 :(得分:4)

这样的事情应该有效:

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)"
then

答案 1 :(得分:3)

使用rmtrap或类似设施相结合的任何代码本质上都存在针对不合理的杀戮,恐慌,系统崩溃,新手系统管理员等的缺陷。缺陷是需要手动清理锁经过这样的灾难性事件后,脚本再次运行。这对您来说可能是也可能不是问题。对于那些管理许多机器或希望偶尔有一个不插电假期的人来说,这是一个问题。

使用文件描述符锁定的现代解决方案已经存在了一段时间 - I detailed it herea working example is on the GitHub here。如果您因任何监控或其他原因无需跟踪进程ID,there is an interesting suggestion for a self-lock(我没有尝试过,也不确定其可移植性保证)。

答案 2 :(得分:1)

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

ON_EVENT函数中,您应该在调用submit函数之前检查相应的锁定文件是否存在。如果它确实存在,那么返回,或者睡觉并稍后再次检查以查看它是否已经消失。如果它不存在,则创建锁并调用submitsubmit函数完成后,删除锁定文件。

有关实施细节,请参阅this thread

答案 3 :(得分:0)

但是我喜欢那些文件无法锁定等待列表(缓存)以便稍后提交。

我目前有这样的事情:

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 }

再次感谢你......

答案 4 :(得分:0)

我采用这种方法,找到了更好的解决方案:

Procmail附带一个 lockfile 命令,可以执行我想要的操作:

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

lockfile将尝试创建指定的lockfile。如果它存在,它将在5秒后重试,这将重复最多10次。如果可以创建flile,它继续使用脚本。

另一个解决方案是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

答案 5 :(得分: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