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

怎么正經(jīng)的實(shí)現(xiàn)shell腳本單例運(yùn)行?

系統(tǒng) Linux
假設(shè)你的一個(gè)腳本已經(jīng)在運(yùn)行了,如果避免再次被執(zhí)行呢?也就是如何實(shí)現(xiàn)單例運(yùn)行?

假設(shè)你的一個(gè)腳本已經(jīng)在運(yùn)行了,如果避免再次被執(zhí)行呢?也就是如何實(shí)現(xiàn)單例運(yùn)行?

[[327604]]

看起來(lái)可行的方法

一個(gè)非常簡(jiǎn)單的思路就是,新的腳本被執(zhí)行時(shí),先檢測(cè)當(dāng)前腳本是否有其他實(shí)例正在運(yùn)行,如果有則直接退出。

  1. runCount=$(ps -ef|grep test.sh | grep -v grep -c) 
  2. if [ "${runCount}" -ge 1 ] 
  3. then 
  4.     echo -e "test.sh already running,num:${runCount}" 
  5.     exit 1; 
  6. fi 
  7. while true 
  8. do 
  9.     echo "test.sh run" 
  10.     sleep 1 
  11. done 

這里通過(guò)ps獲取到當(dāng)前在運(yùn)行的test.sh腳本數(shù),如果大于1,說(shuō)明已經(jīng)有在運(yùn)行的了。

但是你運(yùn)行會(huì)發(fā)現(xiàn),其程序數(shù)量不只是一個(gè)。

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

驚不驚喜?為什么為這樣呢?原因在于,shell腳本中一個(gè)命令執(zhí)行相當(dāng)于fork了一個(gè)進(jìn)程執(zhí)行,這里執(zhí)行的是查找tesh.sh并grep的程序,另外還有一個(gè)就是當(dāng)前運(yùn)行的腳本程序,這樣的方式自然就會(huì)出現(xiàn)每次都有兩個(gè)了。

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

文件鎖

實(shí)際上這種方法你已經(jīng)在《如何讓你的程序同時(shí)只有一個(gè)在運(yùn)行》介紹過(guò)了,只不過(guò)之前是用于編寫C/C++程序,而這里是用于shell腳本。

我們來(lái)回顧一下,這是一個(gè)怎樣的過(guò)程:

  • 運(yùn)行前檢查是否有該鎖文件,并且文件中的進(jìn)程正在運(yùn)行
  • 如果有并且程序正在運(yùn)行,則已經(jīng)有實(shí)例在運(yùn)行
  • 否則,無(wú)實(shí)例,創(chuàng)建鎖文件,寫入進(jìn)程id
  • 退出時(shí),刪除鎖文件

解釋一下第一條,為什么一定要確定鎖文件中的進(jìn)程正在運(yùn)行,因?yàn)椋行┣闆r下如果運(yùn)行的時(shí)候退出沒(méi)有刪除該文件,則會(huì)導(dǎo)致新的實(shí)例永遠(yuǎn)無(wú)法運(yùn)行。

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

我們?cè)囍\(yùn)行其中一個(gè),然后另外一個(gè)窗口嘗試運(yùn)行:

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

由于已經(jīng)有實(shí)例在運(yùn)行,發(fā)現(xiàn)新的程序無(wú)法運(yùn)行了。而等舊的腳本運(yùn)行完之后,新的就可以運(yùn)行了。

實(shí)際上這里面有幾個(gè)點(diǎn)非常巧妙:

  • kill -0 `cat \${LOCKFILE}` 這里用于檢測(cè)該進(jìn)程是否存在,避免進(jìn)程不在了,但是鎖文件還在,導(dǎo)致后面的腳本無(wú)法運(yùn)行。
  • trap "rm -f \${LOCKFILE}; exit" INT TERM EXIT 用于確保腳本退出時(shí),鎖文件會(huì)被刪除。
  • rm -f {LOCKFILE} 腳本最后需要?jiǎng)h除鎖文件

flock

說(shuō)到鎖文件,這里就不得不提flock命令了。沒(méi)有前面的一些巧妙處理,我們很多時(shí)候會(huì)很難刪除原先創(chuàng)建的鎖文件,比如:

  • 腳本被意外中斷,沒(méi)來(lái)得及執(zhí)行刪除
  • 多個(gè)腳本產(chǎn)生競(jìng)爭(zhēng),導(dǎo)致判斷異常,比如前面有一個(gè)腳本運(yùn)行,判斷沒(méi)有鎖文件,下一步準(zhǔn)備創(chuàng)建,但是另外一個(gè)腳本又先創(chuàng)建了,就會(huì)導(dǎo)致異常了。

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

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

解釋一下:

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

因此這里避免了鎖沒(méi)有釋放的情況。

另一種做法

查看flock的man手冊(cè),我們發(fā)現(xiàn)它還有一個(gè)例子是這么做的:

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

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

  1. #!/usr/bin/env bash 
  2. [ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en  "$0"  "$0"  "$@" || : 
  3. #腳本要做的其他事情 
  4. sleep 1024 

解釋一下:如果${FLOCKER}環(huán)境變量沒(méi)有設(shè)置,則嘗試將腳本本身加鎖,如果加鎖成功,則運(yùn)行當(dāng)前腳本,(并且?guī)显械膮?shù)),否則的話靜默退出。

總結(jié)

單例運(yùn)行本身思路是很簡(jiǎn)單的,就是探測(cè)當(dāng)前是否有實(shí)例在運(yùn)行,如果有,則退出,但是這里如何判斷,卻并不是那么容易。

最后,總結(jié)一下本文出現(xiàn)的一些該掌握的信息:

  • $0 腳本名稱
  • $@ 腳本參數(shù)
  • $$ 當(dāng)前腳本進(jìn)程id
  • $? 上一條命令執(zhí)行結(jié)果
  • 描述符0 標(biāo)準(zhǔn)輸入
  • 描述符1 標(biāo)準(zhǔn)輸出
  • 描述符2 標(biāo)準(zhǔn)錯(cuò)誤
  • > 重定向

 

責(zé)任編輯:趙寧寧 來(lái)源: 編程珠璣
相關(guān)推薦

2020-05-26 08:04:24

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單例實(shí)現(xiàn)

2022-08-10 11:02:56

Python單例模式

2018-04-03 15:38:07

Java單例模式模式設(shè)計(jì)

2021-09-07 10:44:35

異步單例模式

2024-03-06 13:19:19

工廠模式Python函數(shù)

2010-02-03 09:43:16

C++單例模式

2017-03-13 09:42:02

彩虹合唱團(tuán)戴爾造夢(mèng)系列

2022-08-15 08:49:06

Go版本單例模式

2024-11-06 11:38:59

C#單例模式

2024-11-06 16:13:00

Python單例模式

2020-09-23 06:00:04

ShellLinux郵件監(jiān)控

2023-07-31 08:45:10

Shell腳本

2022-09-29 08:39:37

架構(gòu)

2017-08-30 17:21:05

LinuxShell超時(shí)現(xiàn)象

2022-01-14 14:32:19

Shell腳本Js

2021-11-02 22:04:58

模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91久久精品日日躁夜夜躁欧美 | 伊人手机在线视频 | 成人日韩av | 久久av影院| 久草在线中文888 | 亚洲一一在线 | 久久久精品在线 | 狠狠艹| 羞羞的视频免费观看 | 色吊丝2288sds中文字幕 | 国产精品视频一区二区三区不卡 | 国产成人免费视频网站视频社区 | 欧美日本免费 | 国产一区二区在线播放 | 亚洲日日 | 天天干天天谢 | jvid精品资源在线观看 | 91亚洲精品国偷拍自产在线观看 | 欧美a∨| 成人午夜精品 | 一区二区久久 | 欧美成人影院 | 久久久久久久久久久91 | 亚洲精品在线免费观看视频 | 欧美在线二区 | 黄色毛片在线播放 | 国产欧美在线一区二区 | 国产99久久 | 国产精品美女久久久久久免费 | 超碰成人免费观看 | 国产人成精品一区二区三 | 精品国产乱码久久久久久牛牛 | 3p视频在线观看 | 1区2区视频| 国产精品成av人在线视午夜片 | 99精品国产一区二区三区 | www.一区二区三区 | 人人做人人澡人人爽欧美 | 中文字幕视频在线看5 | 日韩精品视频在线免费观看 | 精久久久久 |