mkdir锁机制下如何关联路径x与创建进程?查询持锁进程方法
这个需求很典型——用mkdir做原子互斥锁是轻量级并发控制的常用手段,但要追踪锁的持有者确实需要额外的关联逻辑。下面给你两种可行的实现方案,从最直接可靠的到灵活备选的都有:
方案一:在锁目录内写入PID文件(最推荐)
这是最简单也最易维护的方式,核心思路是持有锁的进程成功创建目录后,立即把自己的PID写入目录内的一个文件,其他进程通过读取这个文件就能直接拿到持有者ID。
获取锁的完整流程
LOCK_DIR="/path/to/your/lock/x" # 原子创建目录:mkdir是系统级原子操作,同一路径只能被一个进程成功创建 if mkdir "$LOCK_DIR" 2>/dev/null; then # 将当前进程PID写入目录内的pid.txt(只有持有锁的进程能写这个文件,无竞争) echo $$ > "$LOCK_DIR/pid.txt" echo "成功获取锁,当前PID: $$" # -------------------------- # 这里写入你的业务逻辑代码 # -------------------------- # 释放锁:先删除PID文件,再删除锁目录 rm "$LOCK_DIR/pid.txt" rmdir "$LOCK_DIR" else echo "锁已被其他进程持有,无法获取" fi
查询锁持有者的流程
LOCK_DIR="/path/to/your/lock/x" if [ -d "$LOCK_DIR" ]; then # 读取PID文件内容 PID=$(cat "$LOCK_DIR/pid.txt" 2>/dev/null) if [ -n "$PID" ]; then # 验证进程是否还存活:kill -0 不发送任何信号,仅检查进程是否存在 if kill -0 "$PID" 2>/dev/null; then echo "当前锁由进程 $PID 持有" else echo "锁目录存在,但持有者进程 $PID 已退出(僵尸锁)" fi else echo "锁目录存在,但未找到PID文件(可能被意外删除)" fi else echo "当前无进程持有锁" fi
关键注意事项
- 锁目录权限:创建时可以用
mkdir -m 755 "$LOCK_DIR",确保其他进程能读取PID文件 - 僵尸锁处理:如果持有锁的进程意外崩溃,目录和PID文件会残留,你可以在查询脚本中添加自动清理逻辑(比如检测到进程已死时,直接删除锁目录)
方案二:用
lsof辅助查询(无需额外文件,但可靠性稍差) 如果不想创建PID文件,也可以用lsof命令查找哪个进程持有锁目录的打开句柄——但前提是持有锁的进程要保持对目录的打开状态(否则lsof无法追踪)。
修改后的获取锁流程(保持目录打开)
LOCK_DIR="/path/to/your/lock/x" if mkdir "$LOCK_DIR" 2>/dev/null; then # 打开目录并保留文件描述符(比如fd 10),确保进程持有目录句柄 exec 10<>"$LOCK_DIR" echo "成功获取锁,当前PID: $$" # -------------------------- # 这里写入你的业务逻辑代码 # -------------------------- # 释放锁:先关闭文件描述符,再删除目录 exec 10>&- rmdir "$LOCK_DIR" else echo "锁已被其他进程持有" fi
查询持有者的命令
LOCK_DIR="/path/to/your/lock/x" # 查找打开该目录的进程PID(-t 参数只返回PID) PID=$(lsof -t -d 0-999 "$LOCK_DIR" 2>/dev/null) if [ -n "$PID" ]; then echo "锁由进程 $PID 持有" else if [ -d "$LOCK_DIR" ]; then echo "锁目录存在,但无进程持有(可能是僵尸锁)" else echo "当前无锁持有" fi fi
方案缺点
- 依赖进程保持目录打开:如果持有锁的进程没有保留目录句柄,
lsof就查不到持有者,可靠性远不如PID文件方案 - 权限限制:
lsof需要较高权限,普通用户可能无法查看其他用户的进程信息
为什么不能通过目录元数据直接获取PID?
很多人会尝试用stat命令查看目录的创建信息,但遗憾的是:
- 绝大多数Unix-like系统的目录元数据(比如inode)不会记录创建它的进程PID,
stat能看到的ctime是目录状态改变的时间,和创建者PID无关 - 少数系统(如BSD)有
st_birthtime记录创建时间,但依然没有PID相关信息
因此,写入PID文件是最稳定可靠的实现方式。
内容的提问来源于stack exchange,提问作者Alexander Mills
相关产品推荐
相关产品推荐

