2015-07-13 37 views
1

我目前正在創建一個鎖文件夾,它在我的腳本運行時創建,我也將文件移動到子文件夾中進行處理。腳本結束時會調用一個TRAP,它會刪除鎖定文件夾和內容,所有這些都可以正常工作。有一天我們有一個問題,當有人從一臺服務器上拉下電源時,我的TRAP從來沒有被調用,所以當重新啓動時,鎖定文件夾仍然存在,這意味着我的腳本無法重新啓動,直到它們被手動刪除。檢查腳本是否已在運行的最佳方法是什麼?我當前使用的進程ID的這種做法:創建鎖文件shell

if ! mkdir $LOCK_DIR 2>/dev/null; then # Try to create the lock dir. This should pass successfully first run. 
    # If the lock dir exists 
    pid=$(cat $LOCK_DIR/pid.txt) 
    if [[ $(ps -ef | awk '{print $2}' | grep $pid | grep -v grep | wc -l) == 1 ]]; then 
     echo "Script is already running" 
     exit 1 
    else 
     echo "It looks like the previous script was killed. Restarting process." 
     # Do some cleanup here before removing dir and re-starting process. 

    fi 
fi 

# Create a file in the lock dir containing the pid. Echo the current process id into the file. 
touch $LOCK_DIR/pid.txt 
echo $$ > $LOCK_DIR/pid.txt 

# Rest of script below 
+0

檢查'man 1 lockfile lockfile-check lockfile -create lockfile-remove lockfile-touch' – anishsane

+2

使用'flock'命令。 'man flock'包含示例 – hek2mgl

+0

根據我的理解,使用mkdir也是一個原子操作,因爲我需要該目錄的每個運行,所以它可能被用作主鎖「文件」。我不確定我會如何與當前的實施聯繫起來? –

回答

1

檢查/ proc /和cmdline是一個很好的調用 - 尤其是當你只是檢查沒有進程id的進程而不是進程實際上是你的腳本時。

你仍然可以用你的ps命令來做到這一點 - 這將提供某種形式的平臺不可知論。

COMMAND=$(ps -o comm= -p $pid) 
if [[ $COMMAND == my_process ]] 
then 
    ..... 

請注意,ps的命令行參數將其限制爲只有沒有標題的命令。

+0

看起來不錯!適合我目前的實施,似乎解決了我的問題。儘管返回的進程名稱格式爲「proc_name」。爲什麼它缺少sh的文件擴展名,但包括點? –

+0

我可能剛剛回答了這個問題。看起來好像ps對進程名稱的長度有限制? –

+0

您可以指定列的寬度。根據手冊頁ps -o comm:100 = -p $ pid應該這樣做。 但它沒有。 ps -o command = -p $ pid 會給你包括參數在內的完整命令。 –

0

許多系統現在使用的tmpfs對於像/ TMP目錄。因此這些目錄在重啓後總是會被清除。

如果使用您的pid文件,請注意您可以輕鬆看到在/proc/$pid/cmdline/proc/$pid/exe的該pid下運行的命令 。

+0

不幸的是,考慮到我們的服務器結構,我不想在tmp文件夾中進行處理。 所以在這種情況下,我可以用下面的ps代替ps,但我認爲那裏沒有太多的東西可以獲得? : ls/proc | grep $ pid | wc -l –

+0

您不必將所有內容都放在/ tmp中,只是一個鎖定文件。你不需要'ls/proc'。每個進程都有一個目錄。因此,'cat/proc/$ pid/cmdline'顯示了pid $ pid正在運行的命令。 – meuh

+0

請注意,Linux下的鎖現在預計會在'/ run/lock/...'下進行,每次重啓之間總是會被刪除。 –