Files
zhaopin/scripts/stop-tasks.sh
T

142 lines
5.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# stop-tasks.sh — 随时叫停/重启统一入口 v1.0(2026-08-26)
#
# 用法:
# bash stop-tasks.sh stop # 停止全部(hr1+hr2)
# bash stop-tasks.sh stop hr1 # 只停 hr1
# bash stop-tasks.sh restart hr2 # 重启 hr2(先干净停,再启动)
# bash stop-tasks.sh status # 查询状态(含卡死检测)
#
# 三层停止机制:
# 1. 优雅:创建 STOP.flag 旗标 → runner/scrape 每轮检查自行退出(最多等45秒)
# 2. 强杀:SIGTERM → 3秒 → SIGKILL,父runner和子scrape都杀
# 3. 验证:杀完复查 ps,任何残留即报错;同时清理旗标防止影响下次启动
set -u
STATE_DIR=/opt/data/logs/recruitment/state
LOG_DIR=/opt/data/logs/recruitment
SCRIPTS=/opt/data/skills/recruitment-resume-screener/scripts
STOP_FLAG=$STATE_DIR/STOP.flag
mkdir -p "$STATE_DIR"
# 进程发现:宽匹配(nohup/环境变量/直接参数三种启动方式都能覆盖)
find_pids() { # $1=acct 或空=全部
local pat="daily-runner|zhaopin-scrape"
[ -n "${1:-}" ] && pat="daily-runner.*$1|ACCOUNT=$1"
ps aux | grep -E "$pat" | grep -v -E "grep|stop-tasks" | awk '{print $2}'
}
kill_wait() { # $@ = pids
[ $# -eq 0 ] && return 0
kill "$@" 2>/dev/null || true
for i in 1 2 3; do sleep 1; ps -p "$@" >/dev/null 2>&1 || return 0; done
kill -9 "$@" 2>/dev/null || true
sleep 1
}
verify_none() { # $1=acct 或空;返回0=干净
local left
left=$(find_pids "${1:-}")
if [ -n "$left" ]; then
echo "❌ 仍有残留进程: $(echo $left | tr '\n' ' ')"
echo "$left" | while read -r p; do
ps -p "$p" -o pid,stat,etime,cputime,cmd --no-headers 2>/dev/null
done
return 1
fi
return 0
}
do_stop() {
local target="${1:-}"
echo "🛑 停止筛选任务${target:+($target)}..."
touch "$STOP_FLAG" # 第1层:优雅退出信号
local pids; pids=$(find_pids "$target")
if [ -n "$pids" ]; then
echo " 等待进程优雅退出(最多45秒): $(echo $pids | tr '\n' ' ')"
for i in $(seq 1 45); do
sleep 1
pids=$(find_pids "$target")
[ -z "$pids" ] && break
done
fi
pids=$(find_pids "$target")
if [ -n "$pids" ]; then
echo " 仍有进程,强制终止: $(echo $pids | tr '\n' ' ')"
kill_wait $pids # 第2层:TERM→KILL
fi
rm -f "$STOP_FLAG" # 清旗标,不影响下次启动
if verify_none "$target"; then # 第3层:验证
echo "✅ 已全部停止,验证无残留"
return 0
else
echo "⚠️ 建议稍后重跑 status 确认;若仍残留,联系管理员检查"
return 1
fi
}
do_start() { # $1=acct
local acct="$1" port label
[ "$acct" = "hr1" ] && { port=9223; label=Chrome; } || { port=9225; label=Edge; }
# 启动前防重
local existing; existing=$(find_pids "$acct")
if [ -n "$existing" ]; then
echo "⚠️ $acct 已在运行(PID $(echo $existing | tr '\n' ' ')),先停止再重启"
do_stop "$acct"
fi
# 清掉旧状态,标记新运行
rm -f "$STATE_DIR/state-$acct.json"
cd "$SCRIPTS"
ACCOUNT=$acct CDP_PORT=$port nohup node daily-runner.js "$acct" "$port" \
> "$LOG_DIR/runner-$acct-$(date +%F-%H%M%S).log" 2>&1 &
local pid=$!
sleep 3
if ps -p "$pid" >/dev/null 2>&1; then
echo "✅ $acct($label) 已启动 PID=$pid 日志=$(ls -t $LOG_DIR/runner-$acct-*.log | head -1)"
return 0
else
echo "❌ $acct 启动失败,查看日志: $(ls -t $LOG_DIR/runner-$acct-*.log | head -1)"
tail -5 "$(ls -t $LOG_DIR/runner-$acct-*.log | head -1)"
return 1
fi
}
do_restart() {
do_stop "$1" && do_start "$1"
}
do_status() {
echo "📋 筛选任务状态($(TZ=Asia/Shanghai date '+%F %T'))"
local found=0
for acct in hr1 hr2; do
local pids; pids=$(find_pids "$acct")
if [ -n "$pids" ]; then
found=1
echo " $acct: ▶️ 运行中"
echo "$pids" | while read -r p; do
local info
info=$(ps -p "$p" -o pid,stat,etime,cputime,cmd --no-headers 2>/dev/null | cut -c1-120)
# 卡死检测:cputime 为 00:00 且 etime>10min
local et cpu
et=$(echo "$info" | awk '{print $3}'); cpu=$(echo "$info" | awk '{print $4}')
local mark=""
[ "$cpu" = "00:00:00" ] && case "$et" in *:*:*) mark=" ⚠️疑似卡死(cputime=0)";; esac
echo " $info$mark"
done
local st; st=$(cat "$STATE_DIR/state-$acct.json" 2>/dev/null || echo "无状态文件")
echo " 状态: $(echo "$st" | head -c 200)"
else
echo " $acct: ⏹️ 未运行(状态: $(cat "$STATE_DIR/state-$acct.json" 2>/dev/null | head -c 120 || echo '无'))"
fi
done
[ "$found" = "0" ] && echo " (全部停止)"
[ -f "$STOP_FLAG" ] && echo " ⚠️ 存在停止旗标 STOP.flag(新批次将被阻止启动)"
}
case "${1:-status}" in
stop) do_stop "${2:-}" ;;
start) do_start "${2:?用法: start hr1|hr2}" ;;
restart) do_restart "${2:?用法: restart hr1|hr2}" ;;
status) do_status ;;
*) echo "用法: $0 stop [hr1|hr2] | start hr1|hr2 | restart hr1|hr2 | status"; exit 1 ;;
esac