Shell脚本进程锁机制解析

 更新时间:2025年11月30日 09:51:37   作者:Redmi人儿  
本文主要介绍了Shell脚本中的进程锁机制,用于确保同一时间只有一个实例在运行,通过解析命令行参数、创建锁文件并使用flock命令对文件描述符加锁,感兴趣的可以了解一下

这段 Shell 脚本主要实现了进程锁机制,用于确保同一时间只有一个实例在运行。让我逐行解读:

代码功能分析

1. 命令行参数解析 (第9-21行)

while getopts "m:o:r:" arg; do
    case $arg in
    # ... 参数处理逻辑(代码中省略了具体内容)
    esac
done
  • 使用 getopts 解析命令行参数
  • 支持三个带参数的选项:-m-o-r
  • 具体处理逻辑在代码中被省略了

2. 文件锁机制 (第23-34行)

这是代码的核心部分:

LOCK_FILE="/tmp/gen_emmc_img.lock"

echo "Waiting for lock for model gen_emmc_img..." 
exec 200>"$LOCK_FILE"      # 将文件描述符200重定向到锁文件
flock 200                  # 对文件描述符200加锁
echo "Lock acquired for gen_emmc_img!"

锁机制的工作原理:

  • 创建锁文件 /tmp/gen_emmc_img.lock
  • 使用 flock 命令对文件描述符200加锁
  • 如果锁已被占用,脚本会阻塞等待直到锁可用

3. 清理和锁释放 (第30-34行)

_cleanup_flock() {
    echo "Releasing lock for gen_emmc_img!"
    flock -u 200           # 释放文件描述符200的锁
}
trap _cleanup_flock EXIT   # 设置陷阱,在脚本退出时自动调用清理函数

设计目的

这种设计主要用于:

  • 防止并发冲突:确保同一时间只有一个 gen_emmc_img.sh 进程在运行
  • 资源保护:在生成 eMMC 镜像时避免多个进程同时操作导致的冲突
  • 自动清理:使用 trap 确保即使脚本异常退出也能释放锁

典型应用场景

在嵌入式开发或系统镜像生成过程中,这种锁机制很常见,用于保护:

  • 对存储设备的独占访问
  • 临时文件的创建和使用
  • 系统关键资源的访问

这是一个很经典的 Shell 脚本并发控制实现!

好的,我来深度解读第23-34行的文件锁机制。这部分代码确实比较巧妙,让我详细分解:

逐行深度解析

第23行:定义锁文件路径

LOCK_FILE="/tmp/gen_emmc_img.lock"
  • 在系统的临时目录创建一个锁文件
  • 文件名包含脚本名称,避免与其他脚本冲突

第26行:文件描述符重定向

exec 200>"$LOCK_FILE"

这是关键的一步:

  • exec 命令在当前shell进程中执行重定向
  • 200> 表示将文件描述符200重定向到锁文件
  • 如果文件不存在会自动创建,存在则截断
  • 文件描述符200是一个任意选择的大于2的数字(避免与stdin=0, stdout=1, stderr=2冲突)

第27行:获取文件锁

flock 200

flock 命令的工作原理:

  • 对文件描述符200指向的文件加锁
  • 这是** advisory lock**(建议性锁),不是强制性锁
  • 如果锁已被其他进程持有,当前进程会阻塞等待
  • 锁的释放发生在文件描述符关闭时

第30-33行:清理函数

_cleanup_flock() {
    echo "Releasing lock for gen_emmc_img!"
    flock -u 200  # 显式释放锁
}

第34行:陷阱设置

trap _cleanup_flock EXIT

trap 的作用:

  • 注册一个信号处理程序
  • EXIT 是一个伪信号,在shell退出时触发
  • 无论脚本正常结束还是异常退出,都会调用 _cleanup_flock

锁机制的工作原理示意图

进程A启动
    ↓
exec 200>lockfile  # 创建文件描述符
    ↓  
flock 200          # 加锁成功,继续执行
    ↓
[执行关键代码...]
    ↓
脚本结束 → trap触发 → flock -u 200 → 释放锁
进程B启动(当A持有锁时)
    ↓
exec 200>lockfile  # 创建文件描述符
    ↓  
flock 200          # 阻塞等待...
    ↓              # 当进程A释放锁后
flock返回 → 获得锁,继续执行

为什么需要这样设计?

1.原子性操作

# 如果没有flock,你可能会这样写(有竞态条件):
if [ ! -f "$LOCK_FILE" ]; then
    touch "$LOCK_FILE"    # 这里可能有多个进程同时通过检查
    # 执行任务...
    rm "$LOCK_FILE"
fi

2.自动清理保障

即使脚本被 Ctrl+C 中断、发生错误退出,trap EXIT 也能确保锁被释放。

3.避免僵尸锁

传统方法可能因为进程崩溃而留下锁文件,导致系统永久锁定。这里使用内核管理的文件锁,进程退出后锁自动释放。

实际执行流程示例

# 终端1:运行脚本
$ ./gen_emmc_img.sh
Waiting for lock for model gen_emmc_img...
Lock acquired for gen_emmc_img!
[正在执行...]

# 终端2:同时运行另一个实例  
$ ./gen_emmc_img.sh
Waiting for lock for model gen_emmc_img...
# 这里会阻塞等待,直到终端1的脚本结束

# 当终端1脚本结束时:
Releasing lock for gen_emmc_img!
# 终端2立即获得锁并继续执行

文件锁的优势

  1. 跨进程同步:不同shell实例之间可以同步
  2. 自动清理:进程退出时锁自动释放
  3. 内核级别:比基于文件的标记更可靠
  4. 可移植性:大多数Unix-like系统都支持

这种设计在需要保证单实例运行的脚本中非常常见,特别是在处理硬件操作(如eMMC烧录)时尤为重要。

到此这篇关于Shell脚本进程锁机制解析的文章就介绍到这了,更多相关Shell 进程锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • linux bash字符串处理大全

    linux bash字符串处理大全

    linux bash字符串处理大全,需要的朋友可以参考下
    2013-02-02
  • linux下忘记mysql密码的几种找回方法(推荐)

    linux下忘记mysql密码的几种找回方法(推荐)

    这篇文章主要介绍了linux下忘记mysql密码的几种找回方法,需要的朋友可以参考下
    2017-11-11
  • SED单行脚本快速参考(流编辑器)

    SED单行脚本快速参考(流编辑器)

    sed是一个非交互式的流编辑器。所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出
    2013-01-01
  • putty实现自动登录的方法(ssh和ssh2)

    putty实现自动登录的方法(ssh和ssh2)

    这篇文章主要介绍putty实现自动登录的方法,需要的朋友可以参考下
    2013-02-02
  • 利用expect命令实现Shell自动化交互的方法详解

    利用expect命令实现Shell自动化交互的方法详解

    我们通过Shell可以实现简单的控制流功能,如:循环、判断等。下面这篇文章主要给大家介绍了关于利用expect命令实现Shell自动化交互的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-12-12
  • Linux中cp命令的使用详解

    Linux中cp命令的使用详解

    cp 命令是 Linux 中一个重要的命令,你可能经常会用到它,所以本文主要来和大家讲讲cp命令的具体使用,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-08-08
  • 使用shell检查并修复mysql数据库表的脚本

    使用shell检查并修复mysql数据库表的脚本

    这篇文章主要介绍了使用shell检查并修复mysql数据库表的脚本,需要的朋友可以参考下
    2014-03-03
  • Shell中实现整数自增的几种方法示例

    Shell中实现整数自增的几种方法示例

    Linux Shell中写循环时,常常要用到变量的自增,下面这篇文章主要给大家分享了关于Shell中实现整数变量自增的几种方法,包括declare -i来声明、使用let命令、使用(())以及使用expr命令等等方法,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-08-08
  • shell字符串比较判断是否为数字

    shell字符串比较判断是否为数字

    本文阐述:shell中整数比较方法及字符串的比较方法,如等于,不等于,大于,大于等于,小于,等等
    2013-01-01
  • Linux for循环之列表for循环详解

    Linux for循环之列表for循环详解

    文章详细介绍了Linux shell中的for循环结构,重点分析列表for循环的三种形式:数字列表、字符串列表、命令列表及脚本传参列表,通过使用seq命令和跳步方式实现循环控制,并说明字符串列表的使用方法
    2025-09-09

最新评论