成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

怎么正經的實現Shell腳本單例運行?

開發 后端
假設你的一個腳本已經在運行了,如果避免再次被執行呢?也就是如何實現單例運行?

[[327559]]

 作者:守望,linux應用開發者,目前在公眾號【編程珠璣】 分享Linux/C/C++/數據結構與算法/工具等原創技術文章和學習資源。

假設你的一個腳本已經在運行了,如果避免再次被執行呢?也就是如何實現單例運行?

看起來可行的方法

一個非常簡單的思路就是,新的腳本被執行時,先檢測當前腳本是否有其他實例正在運行,如果有則直接退出。

  1. #!/usr/bin/env bash 
  2. #test.sh 來源:公眾號編程珠璣 
  3. #獲取當前運行的test.sh腳本數 
  4. runCount=$(ps -ef|grep test.sh | grep -v grep -c) 
  5. if [ "${runCount}" -ge 1 ] 
  6. then 
  7.     echo -e "test.sh already running,num:${runCount}" 
  8.     exit 1; 
  9. fi 
  10. while true 
  11. do 
  12.     echo "test.sh run" 
  13.     sleep 1 
  14. done 

這里通過ps獲取到當前在運行的test.sh腳本數,如果大于1,說明已經有在運行的了。

但是你運行會發現,其程序數量不只是一個。

  1. $ ./test.sh 
  2. test.sh already running,num:2 

驚不驚喜?為什么為這樣呢?原因在于,shell腳本中一個命令執行相當于fork了一個進程執行,這里執行的是查找tesh.sh并grep的程序,另外還有一個就是當前運行的腳本程序,這樣的方式自然就會出現每次都有兩個了。

當然判斷條件這里你可以換一下,例如數量大于2,但終歸不太好。

文件鎖

實際上這種方法你已經在《如何讓你的程序同時只有一個在運行》介紹過了,只不過之前是用于編寫C/C++程序,而這里是用于shell腳本。

我們來回顧一下,這是一個怎樣的過程:

  • 1.運行前檢查是否有該鎖文件,并且文件中的進程正在運行
  • 2.如果有并且程序正在運行,則已經有實例在運行
  • 3.否則,無實例,創建鎖文件,寫入進程id
  • 4.退出時,刪除鎖文件

解釋一下第一條,為什么一定要確定鎖文件中的進程正在運行,因為,有些情況下如果運行的時候退出沒有刪除該文件,則會導致新的實例永遠無法運行。

  1. #!/usr/bin/env bash 
  2. #來源:公眾號編程珠璣 
  3. LOCKFILE=/tmp/test.lock 
  4. if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then 
  5.     echo " $0 already running" 
  6.     exit 
  7. fi 
  8.  
  9. # 確保退出時,鎖文件被刪除 
  10. trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT 
  11. #將當前程序進程id寫入鎖文件 
  12. echo $$ > ${LOCKFILE} 
  13.  
  14. # 做你需要的事情 
  15. sleep 1000 
  16.  
  17. # 刪除鎖文件 
  18. rm -f ${LOCKFILE} 

我們試著運行其中一個,然后另外一個窗口嘗試運行:

  1. $ ./test.sh 
  2.  ./test.sh already running 

由于已經有實例在運行,發現新的程序無法運行了。而等舊的腳本運行完之后,新的就可以運行了。

實際上這里面有幾個點非常巧妙:

  • kill -0 `cat \${LOCKFILE}` 這里用于檢測該進程是否存在,避免進程不在了,但是鎖文件還在,導致后面的腳本無法運行。
  • trap "rm -f \${LOCKFILE}; exit" INT TERM EXIT 用于確保腳本退出時,鎖文件會被刪除。
  • rm -f {LOCKFILE} 腳本最后需要刪除鎖文件

flock

說到鎖文件,這里就不得不提flock命令了。沒有前面的一些巧妙處理,我們很多時候會很難刪除原先創建的鎖文件,比如:

  • 腳本被意外中斷,沒來得及執行刪除
  • 多個腳本產生競爭,導致判斷異常,比如前面有一個腳本運行,判斷沒有鎖文件,下一步準備創建,但是另外一個腳本又先創建了,就會導致異常了。

因此我們可以考慮使用flock:

  1. #!/usr/bin/env bash 
  2. #來源:公眾號編程珠璣 
  3. LOCK_FILE=/tmp/test.lock 
  4. exec 99>"$LOCK_FILE" 
  5. flock -n 99 
  6. if [ "$?" != 0 ]; then 
  7.     echo "$0 already running" 
  8.     exit 1 
  9. fi 
  10. #腳本要做的其他事情 
  11. sleep 1024 

解釋一下:

  • exec 99>"$LOCK_FILE" 表示創建文件描述符99,指向鎖文件,為何是99?110其實也是可以的,只是為了和當前腳本可能打開的文件描述符沖突(例如和0,1,2沖突)。
  • flock -n 99 嘗試對該文件描述符加鎖,由操作系統保證原子性
  • 一旦flock失敗了,我們這里可以退出
  • 而即使鎖定了,腳本退出后,也會自動釋放

因此這里避免了鎖沒有釋放的情況。

另一種做法

查看flock的man手冊,我們發現它還有一個例子是這么做的:

  1. "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en  "$0"  "$0"  "$@" || : 

在腳本開頭加上上面這么一行就可以了。例如:

  1. #!/usr/bin/env bash 
  2. #來源:公眾號編程珠璣 
  3. "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en  "$0"  "$0"  "$@" || : 
  4. #腳本要做的其他事情 
  5. sleep 1024 

解釋一下:

  • 如果${FLOCKER}環境變量沒有設置,則嘗試將腳本本身加鎖,如果加鎖成功,則運行當前腳本,(并且帶上原有的參數),否則的話靜默退出。

總結

單例運行本身思路是很簡單的,就是探測當前是否有實例在運行,如果有,則退出,但是這里如何判斷,卻并不是那么容易。

最后,總結一下本文出現的一些該掌握的信息

  • $0 腳本名稱
  • $@ 腳本參數
  • $$ 當前腳本進程id
  • $? 上一條命令執行結果
  • 描述符0 標準輸入
  • 描述符1 標準輸出
  • 描述符2 標準錯誤
  • > 重定向

本文轉載自微信公眾號「 編程珠璣」,可以通過以下二維碼關注。轉載本文請聯系 編程珠璣公眾號。

 

責任編輯:武曉燕 來源: 編程珠璣
相關推薦

2020-05-26 10:28:36

shell腳本單例運行

2015-10-27 09:19:24

2014-08-13 14:48:01

LinuxShell腳本

2011-06-28 15:18:45

Qt 單例模式

2013-03-26 10:35:47

Objective-C單例實現

2022-08-10 11:02:56

Python單例模式

2021-09-07 10:44:35

異步單例模式

2018-04-03 15:38:07

Java單例模式模式設計

2024-03-06 13:19:19

工廠模式Python函數

2010-02-03 09:43:16

C++單例模式

2017-03-13 09:42:02

彩虹合唱團戴爾造夢系列

2020-09-23 06:00:04

ShellLinux郵件監控

2023-07-31 08:45:10

Shell腳本

2024-11-06 11:38:59

C#單例模式

2024-11-06 16:13:00

Python單例模式

2022-08-15 08:49:06

Go版本單例模式

2022-09-29 08:39:37

架構

2017-08-30 17:21:05

LinuxShell超時現象

2022-01-14 14:32:19

Shell腳本Js

2024-11-27 09:19:25

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本福利视频免费观看 | 91视频免费在观看 | 你懂的在线视频播放 | 91干b| 欧美激情一区二区 | 视频二区在线观看 | 亚洲毛片在线 | 亚洲精品久久久久久久久久吃药 | 粉嫩av久久一区二区三区 | 亚洲精品9999| 久久新视频| 欧美人妖网站 | 精品国产乱码久久久久久88av | 99久久精品国产一区二区三区 | 91精品国产自产在线老师啪 | 日韩免费网站 | 午夜精品久久久久久久久久久久久 | 成人片在线看 | 性色视频| 日本激情视频网 | 91.色| 亚洲视频不卡 | 神马影院一区二区三区 | 黄色毛片免费看 | 色网在线看 | 久久久999成人 | 精品亚洲一区二区三区 | 久久av网 | 毛片区| 老妇激情毛片免费 | 精品视频在线观看 | 欧美黄 片免费观看 | 中文字幕在线一区 | 东方伊人免费在线观看 | 中文字幕亚洲精品 | 欧美一二三 | av黄色在线| 久久亚洲欧美日韩精品专区 | 成人免费视频久久 | 国产精品久久久久久久模特 | 久久成人精品视频 |