You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Shell脚本添加逻辑,杀死旧进程避免多实例运行?

解决nohup启动脚本重复运行的问题

方案一:使用PID文件(推荐)

这种方法通过记录脚本的进程ID到文件,启动时校验文件中的PID是否对应正在运行的目标脚本进程,确保同一时间仅一个实例运行,可靠性更高。

修改后的脚本如下:

#!/bin/sh
# 定义PID文件路径,可放在/tmp或脚本同目录
PID_FILE="/tmp/my_script.pid"

# 检查PID文件是否存在
if [ -f "$PID_FILE" ]; then
    OLD_PID=$(cat "$PID_FILE")
    # 验证PID对应的进程是否存在且为当前脚本
    if ps -p "$OLD_PID" -o cmd= | grep -q "$0"; then
        echo "发现已有进程在运行(PID: $OLD_PID),正在终止..."
        kill "$OLD_PID"
        # 等待进程终止,可选
        sleep 2
        # 若进程未正常终止,强制杀死
        if ps -p "$OLD_PID" > /dev/null; then
            kill -9 "$OLD_PID"
        fi
    fi
    rm -f "$PID_FILE"
fi

# 将当前脚本PID写入文件
echo $$ > "$PID_FILE"

# 脚本退出时自动清理PID文件,避免残留无效记录
trap 'rm -f "$PID_FILE"; exit' INT TERM EXIT

# 原脚本逻辑
i=0
while true
do
    echo $i
    ((i++))
    sleep 1
done

关键说明:

  • $$ 表示当前脚本的进程ID
  • trap 命令捕获退出信号,确保脚本无论正常结束还是被强制终止,都能删除PID文件
  • 额外校验进程命令行,避免PID复用导致误杀其他无关进程

方案二:通过ps命令过滤并杀死旧进程

如果不想依赖PID文件,可直接通过ps命令匹配当前脚本的运行进程,排除自身后清理旧进程。

修改后的脚本:

#!/bin/sh
# 获取脚本短文件名,避免路径干扰匹配结果
SCRIPT_NAME=$(basename "$0")

# 查找所有运行中的当前脚本进程,排除grep自身和当前执行的进程
OLD_PIDS=$(ps -ef | grep "$SCRIPT_NAME" | grep -v grep | grep -v $$ | awk '{print $2}')

if [ -n "$OLD_PIDS" ]; then
    echo "发现已有进程在运行:$OLD_PIDS,正在终止..."
    kill $OLD_PIDS
    # 可选:强制清理未终止的进程
    sleep 2
    for PID in $OLD_PIDS; do
        if ps -p "$PID" > /dev/null; then
            kill -9 "$PID"
        fi
    done
fi

# 原脚本逻辑
i=0
while true
do
    echo $i
    ((i++))
    sleep 1
done

关键说明:

  • 多次grep过滤是为了排除grep自身进程和当前正在启动的脚本进程,避免误杀
  • 该方法依赖进程命令行的匹配,若存在同名脚本可能出现误杀,不如PID文件方案可靠

注意事项

  • 两种方案均仅针对当前脚本的进程操作,不会影响其他运行的Shell脚本
  • 脚本中的sleep是子进程,杀死脚本的父进程后,子进程会被系统接管并自动终止,无需单独处理

内容的提问来源于stack exchange,提问作者lucky1928

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:15:34