首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Shell 腳本防重複運行:grep 過濾自身進程的正確姿勢

     編輯:程式設計綜合問答

現象:`ps x | grep "import.sh" | grep -c "import.sh"` 計數恆為 2,導致誤判腳本已在運行。

根因分析

管道執行時,Shell 會為每個命令創建子進程。`grep "import.sh"` 進程本身的命令行包含 `"import.sh"` 字符串,**會匹配到自己**,導致計數 +1。

# 進程列表示例
PID   CMD
1234  /bin/bash /path/import.sh
5678  grep import.sh   ← 這行也包含 "import.sh",被計數

標準解法:排除 grep 進程

count=$(ps x | grep "import.sh" | grep -v "grep" | grep -c "import.sh")
# 或更簡潔:
count=$(pgrep -f "import.sh" | wc -l)  # pgrep 默認不匹配自身
# 或使用 flock(推薦,原子級鎖):
exec 200>/var/lock/import.lock
flock -n 200 || { echo "腳本已在運行"; exit 1; }

方案對比

方案優點缺點
`grep -v grep`兼容性好,無額外依賴競態條件:檢查到執行間隙可被繞過
`pgrep -f`語義清晰,自動排除自身部分嵌入式系統無 pgrep
`flock` 文件鎖**原子操作**,無競態,釋放自動需支援 flock 的文件系統(ext4/xfs/NFSv4+)
`mkdir` 鎖目錄POSIX 原子操作,極高兼容性需手動清理陰殘留目錄

生產級模板(flock 版)

#!/bin/bash
LOCK_FILE="/var/lock/$(basename $0).lock"
exec 200>"$LOCK_FILE"
flock -n 200 || { echo "[$(date)] $0 已在運行,退出"; exit 1; }

# 你的業務邏輯
echo "[$(date)] 開始執行..."
sleep 10
echo "[$(date)] 執行結束"

# 腳本結束自動釋放鎖(FD 關閉)

核心原則:**用文件系統鎖替代進程掃描**,解決「檢查-執行」非原子性導致的並發缺陷。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved