多进程使用文件锁

文件锁

单进程内多线程可以通过抢占内存锁来保持互斥,在多进程中无法通过内存锁完成,其中的一个办法是可以通过文件锁实现。

大致的思路:每个进程当需要执行关键操作时需要判断是否有其他进程已经在执行,通过查看并创建本地特定文件来判断和抢占这次操作的执行权限,道理同锁机制一致。

以上思路中查看并创建需要是一个原子操作,才能保证中间不会被其他进程截胡。

例如:

1
2
3
4
5
6
7
8
#! /bin/bash
file="/tmp/proj_name"
if [ -f "$file" ]
then
touch $file
else
exit 1
fi

这种方法在检测和创建中可能被其他进程抢占,造成两个进程同时创建文件,因此不可取。

这里采用mkdir

1
2
3
4
5
#! /usr/bin/env bash
if ! mkdir /tmp/myscript.lock 2>/dev/null; then
echo "Myscript is already running." >&2
exit 1
fi

依靠mkdir的创建文件夹,如果文件夹存在则返回>0的错误可判断,执行完毕后别忘了删除文件夹,释放这个文件锁

trap

另外,还有一个命令trap,可以根据传入信号在程序退出做指定的操作,例如

1
2
3
4
5
6
7
8
trap 'echo "$$" > "/tmp/pid";exit' SIGINT
count=0
while :
do
sleep 1
count=$(expr $count + 1)
echo $count
done

程序在无限循环并每秒打印一个递增数字, 在进程收到SIGINT(ctrl + c)的中断信号后,将进程号输入到/tmp/pid文件中,trap可以完成一个进程最后的收尾工作,如清理日志和其他操作

flock

flock 分为共享锁和独享锁,共享锁之间可以同时存在,共享锁和独享锁以及独享锁之间不能够共存。

flock -x $file 获取某文件的独享锁,获取到则接着执行后面的语句,因为flock的参数是一个fd,在进程关闭后所有fd会被关闭,flock的锁也会随即消失,避免出现进程意外退出锁未释放的问题。

flock -n $fd, 设置成非阻塞模式,通过判断 $? 可以知道是否锁成功

flock机制是linux提供的现成的文件锁,比mkdir方便。