2015-05-21 34 views
1

我想拿出的時候沒有發生過的文件夾中的任何寫活動我很喜歡看檢測一個很好的和簡單的方法沒有寫活動。任何腳本通知時,有文件夾

基本上,我想有是這樣的:

#!/bin/sh 

# colored red text (error) 
function errorMsg() { 
    echo '\033[0;31m'"$1"'\033[0m' 
} 

# check for folder to monitor argument 
if [ "$#" -ne 1 ] 
then 
    errorMsg "add experiment (folder) to monitor for activity!" 
exit 
fi 

# time out time, 3 minutes 
TIMEOUT_TIME=180 
LAST_CHECKED=0 

function refreshTimer() { 
    # when called, check seconds since epoch 
    CURRENT_TIME=date +%s 

    if [ CURRENT_TIME - LAST_CHECKED > TIMEOUT_TIME ] 
    then 
    echo "file write activity halted!" | mail -s "trouble!" "[email protected]" 
    fi 

    LAST_CHECKED=date +%s 
} 

# set last checked to now. 
LAST_CHECKED=date +%s 
# start monitoring for file changes, and update timer when new files are being written. 
fswatch -r ${1} | refreshTimer 

但bash的魔術各種需要我猜想,因爲fswatch是一個後臺任務,其輸出作爲管道創建一個子shell。 我也很需要一些定時器邏輯的...... 我想是這樣,其時的說法不斷被添加的時候有活動的setTimeout的,但我不知道如何給它的所有寫在一個腳本。

猛砸,Python和Ruby,任何可以使用的OSX自制安裝是好的,但越簡單越好(讓我明白髮生了什麼)。

+1

您需要使用'#!/ bin中/ bash'爲hashbang,或刪除所有'bash'只從您的腳本構建。 – chepner

+0

請澄清你的問題到底是什麼。我們不會爲您開發整個腳本,並且AFAIK軟件建議不在話下。 – l0b0

+0

@chepner我從頭頂寫了一些東西,使用了不同腳本的某些部分,但是,是的,你是對的:) @ l0b0,我不確定你不明白。我的用例是我運行模擬,他們把結果放在一個文件夾中(即寫入操作)。我可以用'''fswatch'''(可以使用自制軟件安裝)觀看。但是,我想知道什麼時候沒有任何寫入活動(這表明出現了問題)。我甚至試圖通過創建一個存根腳本來顯示我想要的東西。我不問軟件建議。我說任何解決方案都很好。 –

回答

1

試試下面的 - 注意,它需要bash

#!/usr/bin/env bash 

# colored red text (error) 
function errorMsg() { 
    printf '\033[0;31m%s\033[0m\n' "$*" >&2 
} 

# check for folder to monitor argument 
if [[ $# -ne 1 ]] 
then 
    errorMsg "add experiment (folder) to monitor for activity!" 
    exit 2 
fi 

# time-out: 3 minutes 
TIMEOUT_TIME=180 

# Read fswatch output as long as it is 
# within the timeout value; every change reported 
# resets the timer. 
while IFS= read -t $TIMEOUT_TIME -d '' -r file; do 
    echo "changed: [$file]" 
done < <(fswatch -r -0 "${1}") 

# Getting here means that read timed out. 
echo "file write activity halted!" | mail -s "trouble!" "[email protected]" 
  • fswatch無限期輸出線到stdout,必須由線讀取線採取新的輸出及時行動。
  • fswatch -0終止具有NUL(零字節)的行,其中read然後通過將行分隔符(分隔符)設置爲空字符串(-d '')來讀取。
  • < <(fswatch -r -0 "${1}")通過stdin <while循環提供輸入,其中read一次消耗stdin輸入一個NUL終止的行。
    • <(fswatch -r -0 "${1}")process substitution形成從由fswatch -r -0 "${1}"產生的輸出的「自組織文件」(在技術上,一個FIFO或命名的文件的描述符)(其手錶夾${1}的子樹(-r),用於文件的變化,並報告每個都以NUL(-0)終止)。
    • 由於無限期fswatch命令運行時,「臨時文件」將繼續提供意見,但通常只是間歇,根據文件系統的活動。
  • 每當read命令接收到超時週期(-t $TIMEOUT_TIME),它終止成功(退出代碼0),使將要執行的循環體中的一個新行,然後read被再次調用
    • 因此,每當一個線已被接收,則超時期間被有效地復位,因爲新read調用與所述超時週期重新開始。
    • 相反,如果接收到另一行前的超時期滿,read終止不成功 - 具有指示失敗,這會導致循環while終止非零退出代碼。
  • 因此,僅當read命令超時時纔會達到循環後的代碼。

至於你的原代碼

注:所討論的一些問題可能已經與shellecheck.net

    幫助檢測
  • echo '\033[0;31m'"$1"'\033[0m'
    • printf是在解釋電子商務時更好的選擇scape序列,因爲echo的行爲因殼和平臺而異;例如,使用bash運行腳本將而不是解釋它們(除非您還添加-e選項)。
  • function refreshTimer()
    • function語法是非標準的(不是POSIX兼容),所以你不應該有一個sh認領線使用它(這就是chepner在他的評論的意思)。在OSX上,您可以避開它,因爲bash充當sh大部分當以sh運行時,bashisms仍然可用,但在其他系統上不起作用。如果你知道你會用bash來運行,那麼最好使用0123bshebang線。
  • CURRENT_TIME=date +%s
    • 不能通過簡單地將命令是對分配的RHS分配從命令給一個變量輸出;相反,你需要一個command substitution;在這種情況下:CURRENT_TIME=$(date +%s)(帶反引號的舊語法 - CURRENT_TIME=`date +%s` - 也適用,但有缺點)。
  • [ CURRENT_TIME - LAST_CHECKED > TIMEOUT_TIME ]

    • [ ... ]和bash的[[ ... ]]條件語句>詞法比較和變量名必須是$ -prefixed;您必須使用算術以您的語法爲條件:((CURRENT_TIME - LAST_CHECKED > TIMEOUT_TIME))
    • 順便說一句,在shell編程中最好是better not to use all-uppercase variable names
  • fswatch -r ${1} | refreshTimer

    • refreshTimer將不會被調用,直到管道填滿了,因爲你沒有試圖(你會不會是其中能夠預測時間)來讀取逐行
    • 即使你解決這個問題,裏面refreshTimer變量將不會被保留,因爲refreshTimer運行在每次新的子shell,由於使用管道(|)的。在bash中,通過提供通過process substitution<(...))提供的輸入,可以解決此問題,您可以在上面的代碼中看到這些輸入。
+0

這看起來正是我想要的,但我沒有看到計時器重置的位置?你能詳細說明一下嗎?謝謝! –

+0

@MichaelTrouw:請看我更新的答案(現在穩定)。 – mklement0

+1

非常感謝@ mklement0的詳細解釋,以及do和donot關於我的真正糟糕的shell示例腳本。我仍然需要習慣'''while ... done'''的語法,儘管我明白腳本的作用。這正是我所期待的!如果我能+4這個答案,我會這樣做,詳細的解釋和有用的鏈接(總共4個)。 –

相關問題