确保同一时间只有一个shell脚本实例在运行的方法

2023-11-15 07:53:20 浏览数 (2)

问:

有什么快速简便的方法可以确保在给定的时间内只有一个shell脚本实例在运行?

答:

方法一 使用flock(1)在文件描述符上创建一个独占锁。

代码语言:javascript复制
#! /bin/bash

(
  # Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
  flock -x -w 10 200 || exit 1

  # 在这里放置脚本的主逻辑部分

) 200>/var/lock/.myscript.exclusivelock

这样可以确保 ( 和 ) 之间的代码一次只由一个进程运行,并且该进程不会为获取锁而等待太长时间。

flock命令是Linux的文件锁命令,可以通过一个锁文件,来控制在shell中逻辑的互斥性。 flock命令的常见选项包括:

  • -s:获取共享锁,有时称为读锁。
  • -x:获取独占锁,有时称为写锁。这是默认值。
  • -n:获取锁失败时立即返回,而不是等待锁被释放。
  • -w:等待锁释放的时间,单位为秒。

方法二 是一个使用锁定文件并将PID回显到其中的实现。

代码语言:javascript复制
SCRIPT_NAME=$(basename "$0")
LOCKFILE=/tmp/${SCRIPT_NAME}.lock
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
    echo "already running"
    exit
fi

# make sure the lockfile is removed when we exit and then claim it
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
echo $$ > ${LOCKFILE}

# 在这里放置脚本的主逻辑部分
sleep 100

rm -f ${LOCKFILE}

这里的技巧是kill -0,它不传递任何信号,只是检查具有给定PID的进程是否存在。此外,对trap的调用将确保锁定文件被删除,即使你的进程被杀死(kill -9除外)。

参考文档:

  • stackoverflow question 185451
  • https://www.man7.org/linux/man-pages/man1/flock.1.html
  • 如何在Bash中提取文件名和扩展名

相关阅读:

  • Bash中$$ $! $# $0 $? $* $@ 等各种符号的含义
  • 如何使用bash脚本并行运行多个程序
  • 如何从Bash脚本本身中获得其所在的目录
  • 如何在Bash中连接字符串变量
  • 如何编写bash脚本以便在进程死机时重新启动进程

0 人点赞