Skip to content

三个脚本的实现启动、停止、重启一个可执行程序,并记录其PID

示例目录结构

markdown
dir/
├── app.linux    # 可执行文件
├── conf/
│   ├── config.yml
├── start.sh
├── stop.sh
├── restart.sh
├── app.log     # 运行脚本自动生成 程序运行时输入日志的记录到这里
└── app.pid     # 运行脚本自动生成 进程pid

1. start.sh

bash
#!/bin/bash

# 获取脚本所在目录的绝对路径
__DIRNAME=$(dirname "$(readlink -f "$0")")

APP_NAME="app名称"
START_COMMAND="${__DIRNAME}/app.linux"  # 仅包含命令路径
ARGS="run ${__DIRNAME}/conf/config.yml"                            # 参数单独保存
PID_FILE="${__DIRNAME}/app.pid"
LOG_FILE="${__DIRNAME}/app.log"

# 检查是否已经运行
if [ -f "$PID_FILE" ]; then
    PID=$(cat "$PID_FILE")
    if kill -0 "$PID" >/dev/null 2>&1; then
        echo "程序 $APP_NAME 已经在运行 (PID: $PID)"
        exit 1
    else
        echo "发现陈旧的 PID 文件,清理后启动..."
        rm -f "$PID_FILE"
    fi
fi

# 启动程序并记录 PID 输入日志到LOG_FILE
nohup $START_COMMAND $ARGS > "$LOG_FILE" 2>&1 &
echo $! > "$PID_FILE"

echo "程序 $APP_NAME 已启动 (PID: $!)"

2. stop.sh

  • 停止时检查现在pid实际运行命令是否包含start.sh中的启动命令
bash
#!/bin/bash

# 获取脚本所在目录的绝对路径
__DIRNAME=$(dirname "$(readlink -f "$0")")

APP_NAME="app名称"
PID_FILE="${__DIRNAME}/app.pid"
# 关键:匹配进程实际运行的预期包含命令(示例中匹配 "app.linux" 关键字)
EXPECTED_CMD="app.linux"

# 检查 PID 文件是否存在
if [ ! -f "$PID_FILE" ]; then
    echo "错误:PID 文件不存在,程序可能未运行"
    exit 1
fi

# 读取 PID 并检查有效性
PID=$(cat "$PID_FILE")
if [ -z "$PID" ]; then
    echo "错误:PID 文件内容为空,清理并退出"
    rm -f "$PID_FILE"
    exit 1
fi

# 检查 PID 是否存在
if ! kill -0 "$PID" >/dev/null 2>&1; then
    echo "警告:进程 $PID 不存在,清理 PID 文件"
    rm -f "$PID_FILE"
    exit 1
fi

# 关键验证:检查 PID 对应的进程是否是目标程序
PROCESS_CMD=$(ps -p "$PID" -o cmd=)  # 获取进程完整命令行
if [[ "$PROCESS_CMD" != *"$EXPECTED_CMD"* ]]; then
    echo "错误:PID $PID 不属于 $APP_NAME,进程命令不包含:$EXPECTED_CMD,实际进程命令为:$PROCESS_CMD"
    exit 1
fi

# 执行终止操作
kill "$PID"
echo "程序 $APP_NAME (PID: $PID) 已终止"
rm -f "$PID_FILE"

3. restart.sh

bash
#!/bin/bash

# 获取脚本所在目录的绝对路径
__DIRNAME=$(dirname "$(readlink -f "$0")")

"${__DIRNAME}/stop.sh"
sleep 1  # 可选:等待进程完全停止
"${__DIRNAME}/start.sh"

使用方法:

  1. 将上述脚本保存为 start.sh, stop.sh, restart.sh
  2. 替换 APP_NAME="myapp" 为你的可执行程序名称
  3. 赋予执行权限:
    bash
    chmod +x start.sh stop.sh restart.sh
  4. 启动程序:
    bash
    ./start.sh
  5. 停止程序:
    bash
    ./stop.sh
  6. 重启程序:
    bash
    ./restart.sh

关键点说明:

  1. PID 文件:脚本通过 app.pid 文件记录进程ID
  2. 日志记录:程序输出会重定向到 app.log
  3. 防重复启动start.sh 会检查现有进程是否运行
  4. 陈旧 PID 处理stop.sh 会自动清理无效的 PID 文件
  5. 权限要求:确保脚本和程序有可执行权限
  6. unix换行符:确保脚本文件使用 Unix 换行符(LF),避免 Windows 换行符(CRLF)的问题

可以根据实际需求调整日志路径、等待时间等参数。

/src/technology/dateblog/2025/05/20250527-%E4%B8%89%E4%B8%AA%E8%84%9A%E6%9C%AC%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%90%AF%E5%8A%A8%E3%80%81%E5%81%9C%E6%AD%A2%E3%80%81%E9%87%8D%E5%90%AF%E4%B8%80%E4%B8%AA%E5%8F%AF%E6%89%A7%E8%A1%8C%E7%A8%8B%E5%BA%8F%EF%BC%8C%E5%B9%B6%E8%AE%B0%E5%BD%95%E5%85%B6pid.html