如何写单实例运行脚本

wen 实用脚本 27

本文目录导读:

如何写单实例运行脚本

  1. 使用 PID 文件(最常用)
  2. 使用文件锁(flock)
  3. 使用 mkdir 原子操作
  4. 使用 ps 命令检查进程
  5. 使用 /proc 文件系统(Linux专用)
  6. 推荐使用方式
  7. 注意事项

使用 PID 文件(最常用)

#!/bin/bash
# 单实例运行 - PID文件方式
APP_NAME="myapp"
PID_FILE="/var/run/${APP_NAME}.pid"
# 检查是否已有实例运行
if [ -f "$PID_FILE" ]; then
    PID=$(cat "$PID_FILE")
    if kill -0 "$PID" 2>/dev/null; then
        echo "错误: 程序已在运行 (PID: $PID)"
        exit 1
    else
        # 清理过时的PID文件
        rm -f "$PID_FILE"
    fi
fi
# 创建PID文件
echo $$ > "$PID_FILE"
# 清理函数
cleanup() {
    rm -f "$PID_FILE"
    exit 0
}
trap cleanup EXIT
# 主要业务逻辑
echo "程序开始运行 (PID: $$)"
while true; do
    # 你的业务代码
    echo "运行中..."
    sleep 5
done

使用文件锁(flock)

#!/bin/bash
# 单实例运行 - flock文件锁方式
LOCK_FILE="/tmp/myapp.lock"
# 尝试获取锁
exec 200>"$LOCK_FILE"
if ! flock -n 200; then
    echo "错误: 程序已在运行"
    exit 1
fi
echo "程序开始运行 (PID: $$)"
# 主要业务逻辑
trap 'echo "程序退出"; exit 0' INT TERM
while true; do
    echo "运行中..."
    sleep 5
done

使用 mkdir 原子操作

#!/bin/bash
# 单实例运行 - mkdir原子操作方式
LOCK_DIR="/tmp/myapp.lockdir"
# 尝试创建锁目录(原子操作)
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
    echo "错误: 程序已在运行"
    exit 1
fi
# 清理函数
cleanup() {
    rm -rf "$LOCK_DIR"
    exit 0
}
trap cleanup EXIT
echo "程序开始运行 (PID: $$)"
# 主要业务逻辑
trap 'echo "程序退出"' INT TERM
while true; do
    echo "运行中..."
    sleep 5
done

使用 ps 命令检查进程

#!/bin/bash
# 单实例运行 - ps命令检查
APP_NAME="myapp"
PID_FILE="/tmp/${APP_NAME}.pid"
# 检查是否已有实例
if [ -f "$PID_FILE" ]; then
    PID=$(cat "$PID_FILE")
    # 检查进程是否存在且确实是我们的程序
    if ps -p "$PID" -o comm= | grep -q "$APP_NAME" 2>/dev/null; then
        echo "错误: 程序已在运行 (PID: $PID)"
        exit 1
    fi
fi
# 保存PID
echo $$ > "$PID_FILE"
# 程序主逻辑
echo "程序开始运行 (PID: $$)"
# 你的业务代码

使用 /proc 文件系统(Linux专用)

#!/bin/bash
# 单实例运行 - /proc文件系统方式
LOCK_FILE="/tmp/myapp.pid"
# 检查并记录PID
if [ -f "$LOCK_FILE" ]; then
    OLD_PID=$(cat "$LOCK_FILE")
    # 检查/proc中进程是否存在
    if [ -d "/proc/$OLD_PID" ]; then
        echo "错误: 程序已在运行 (PID: $OLD_PID)"
        exit 1
    fi
fi
echo $$ > "$LOCK_FILE"
# 清理
cleanup() {
    rm -f "$LOCK_FILE"
    exit 0
}
trap cleanup EXIT
# 主程序
echo "程序开始运行 (PID: $$)"

推荐使用方式

对于简单脚本,推荐使用 flock 方式,因为它:

  • 原子操作,安全可靠
  • 自动清理锁文件(进程退出时)
  • 跨平台性好
#!/bin/bash
# 推荐的单实例脚本模板
LOCK_FILE="/tmp/$(basename "$0").lock"
exec 200>"$LOCK_FILE"
if ! flock -n 200; then
    echo "错误: 脚本已在运行"
    exit 1
fi
echo "脚本开始执行 (PID: $$)"
# 你的业务逻辑
trap 'echo "脚本退出"' EXIT
# ...

注意事项

  1. PID文件位置:使用 /var/run/ 需要root权限,普通用户用 /tmp/
  2. 锁文件清理:确保在脚本退出时清理锁文件
  3. 信号处理:正确处理 SIGINT、SIGTERM 等信号
  4. 权限控制:多用户环境下注意锁文件权限
  5. 性能考虑:频繁检查PID可能影响性能

选择哪种方式取决于你的具体需求和运行环境。

抱歉,评论功能暂时关闭!