用脚本实现程序互斥运行

wen 实用脚本 2

方法1:使用锁文件(推荐)

#!/bin/bash
# mutex_run.sh - 使用锁文件实现互斥
LOCKFILE="/tmp/myapp.lock"
# 检查锁文件是否存在
if [ -f "$LOCKFILE" ]; then
    # 检查进程是否还在运行
    if kill -0 $(cat "$LOCKFILE") 2>/dev/null; then
        echo "程序已在运行 (PID: $(cat $LOCKFILE))"
        exit 1
    else
        echo "检测到旧的锁文件,删除中..."
        rm -f "$LOCKFILE"
    fi
fi
# 创建锁文件并写入当前PID
echo $$ > "$LOCKFILE"
# 确保程序退出时删除锁文件
cleanup() {
    rm -f "$LOCKFILE"
    exit
}
trap cleanup EXIT
# 在这里放置你的程序代码
echo "程序开始运行 (PID: $$)"
sleep 30  # 模拟程序运行
echo "程序运行结束"

方法2:使用flock(Linux专用)

#!/bin/bash
# flock_mutex.sh - 使用flock实现互斥
LOCKFILE="/tmp/myapp_flock.lock"
# 尝试获取锁
exec 200>"$LOCKFILE"
if ! flock -n 200; then
    echo "程序已被其他实例运行"
    exit 1
fi
# 程序主体
echo "程序开始运行 (PID: $$)"
sleep 30
echo "程序运行结束"
# 释放锁
flock -u 200

方法3:使用mkdir原子操作

#!/bin/bash
# mkdir_mutex.sh - 使用mkdir的原子性
LOCKDIR="/tmp/myapp_mutex"
# 尝试创建目录(原子操作)
if ! mkdir "$LOCKDIR" 2>/dev/null; then
    echo "程序正在运行中"
    exit 1
fi
# 确保退出时删除目录
trap 'rm -rf "$LOCKDIR"' EXIT
# 程序主体
echo "程序开始运行 (PID: $$)"
sleep 30
echo "程序运行结束"

方法4:使用系统信号量(Linux)

#!/bin/bash
# sem_mutex.sh - 使用信号量实现互斥
SEM_NAME="myapp_sem"
# 创建信号量
if ! semaphore_ac "$SEM_NAME" 2>/dev/null; then
    # 如果没有semaphore工具,使用备用方案
    echo "程序已在运行"
    exit 1
fi
# 程序主体
echo "程序开始运行"
sleep 30
echo "程序运行结束"
# 释放信号量
semaphore_re "$SEM_NAME"

方法5:使用Python实现(跨平台)

#!/usr/bin/env python3
# mutex.py - Python实现互斥运行
import os
import sys
import fcntl
import time
class Mutex:
    def __init__(self, lock_file="/tmp/python_app.lock"):
        self.lock_file = lock_file
        self.fd = None
    def acquire(self):
        try:
            self.fd = open(self.lock_file, 'w')
            fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
            return True
        except (IOError, OSError):
            return False
    def release(self):
        if self.fd:
            fcntl.flock(self.fd, fcntl.LOCK_UN)
            self.fd.close()
            os.remove(self.lock_file)
def main():
    mutex = Mutex()
    if not mutex.acquire():
        print("程序已在运行")
        sys.exit(1)
    try:
        print(f"程序开始运行 (PID: {os.getpid()})")
        time.sleep(30)  # 模拟程序运行
        print("程序运行结束")
    finally:
        mutex.release()
if __name__ == "__main__":
    main()

方法6:使用Shell脚本封装

#!/bin/bash
# wrapper.sh - 封装任意命令的互斥运行
LOCKFILE="/tmp/command_lock"
TARGET_COMMAND=$@
if [ -z "$TARGET_COMMAND" ]; then
    echo "用法: $0 <命令>"
    exit 1
fi
# 尝试获取锁
if [ -f "$LOCKFILE" ]; then
    if kill -0 $(cat "$LOCKFILE") 2>/dev/null; then
        echo "命令 '$TARGET_COMMAND' 已在运行"
        exit 1
    fi
fi
echo $$ > "$LOCKFILE"
trap 'rm -f "$LOCKFILE"; exit' EXIT INT TERM
# 执行目标命令
$TARGET_COMMAND

使用建议

  1. 生产环境推荐:使用 flock(方法2)或锁文件(方法1)

    用脚本实现程序互斥运行

  2. 防止死锁:添加超时机制

    # 带超时的锁文件检查
    LOCKFILE="/tmp/app.lock"
    TIMEOUT=5

等待锁释放(最多等待5秒)

for i in $(seq 1 $TIMEOUT); do if [ -f "$LOCKFILE" ]; then if kill -0 $(cat "$LOCKFILE") 2>/dev/null; then if [ $i -eq $TIMEOUT ]; then echo "等待超时,退出" exit 1 fi sleep 1 else rm -f "$LOCKFILE" break fi else break fi done


3. **日志记录**:添加运行日志
```bash
echo "$(date): 程序启动 (PID: $$)" >> /var/log/app_start.log

选择哪种方法取决于你的具体需求:

  • 简单场景:锁文件法
  • Linux系统:flock或信号量
  • 跨平台需求:Python实现
  • 原子操作要求:mkdir法

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