在 Linux/Unix 系統管理中,優雅地停止特定進程是一項基本且關鍵的技能。本文介紹一個通用的 Bash 腳本 process_stopper.sh,它能夠根據進程名或完整命令行參數,精準地停止屬於當前用戶的進程,避免誤傷其他用戶的同名進程。
SIGTERM (signal 15) 讓進程釋放資源、保存狀態,等待 2 秒後若進程仍存活,再強制發送 SIGKILL (signal 9) 徹底終止。#!/bin/sh
# 來源: https://code.google.com/p/mooon
# 1. 參數檢查
if test $# -ne 1; then
printf "\033[1;33musage: $0 process_cmdline\033[m\n"
exit 1
fi
process_cmdline=$1 # 目標進程命令行
cur_user=$(whoami) # 當前用戶名
uid=$(id -u "$cur_user") # 當前用戶 UID
# 2. 取得進程名 (命令行的第一個欄位)
process_name=$(basename "$(echo "$process_cmdline" | cut -d' ' -f1)")
# 3. 獲取符合條件的 PID 列表
# ps -C 指定進程名, h 隱藏標題, -o euser,pid,args 輸出有效用戶、PID、完整命令
# awk 過濾: 用戶匹配 且 命令行包含傳入參數
pid_set=$(ps -C "$process_name" h -o euser,pid,args |
awk -v uid="$uid" -v cur_user="$cur_user" -v cmd="$process_cmdline" '
($1 == uid || $1 == cur_user) && match($0, cmd) { print $2 }
')
# 4. 循環發送信號終止進程
for pid in $pid_set; do
kill "$pid" # SIGTERM
sleep 2
kill -9 "$pid" # SIGKILL
done
腳本強制要求一個參數 process_cmdline。透過 whoami 和 id -u 獲取當前用戶身份,確保後續 ps 篩選時只鎖定屬於該用戶的進程。
cut -d' ' -f1 取命令行第一個空格前的內容 (可執行文件路徑),再用 basename 取得純進程名,供 ps -C 使用。
使用 ps -C "$process_name" h -o euser,pid,args 列出該進程名下所有進程的「有效用戶、PID、完整命令行」。隨後 awk 執行兩層過濾:
$1 == uid || $1 == cur_user (兼容數字 UID 與用戶名兩種輸出格式)。match($0, cmd) 確保完整命令行包含用戶傳入的特徵字串,實現精準定位。循環中先 kill $pid (預設 SIGTERM),給予進程 2 秒緩衝時間處理善後工作 (如 flush buffer、釋放鎖);超時後 kill -9 $pid 強制回收資源。這是生產環境推薦的標準停止流程。
# 停止名為 my_server 的進程
./process_stopper.sh my_server
# 停止帶特定參數的 java 進程
./process_stopper.sh "java -jar app.jar --port=8080"
chmod +x process_stopper.sh。kill 改為批次處理 (如 kill $pid_set),但失去逐個等待 2 秒的優雅特性。這個腳本體積小巧、邏輯清晰,是系統管理員和開發人員工具箱中實用的「瑞士軍刀」。