2016-09-20 112 views
0

編寫shell腳本時遇到了一件很奇怪的事情。shell腳本中的奇怪輸出

最初我有以下腳本。

OUTPUT_FOLDER=/home/user/output 
HOST_FILE=/home/user/host.txt 
LOG_DIR=/home/user/log 
SLEEPTIME=60 

mkdir -p $OUTPUT_FOLDER 

while true 
do 
    rm -f $OUTPUT_FOLDER/* 
    DATE=`date +"%Y%m%d"` 
    DATETIME=`date +"%Y%m%d_%H%M%S"` 
    pssh -h $HOST_FILE -o $OUTPUT_FOLDER 
    while read host 
    do 
     numline=0 
     while read line 
     do 
      if [[ $numline == 0 ]] 
      then 
       FIELD1=`echo $line | cut -d':' -f2 | cut =d' ' -f2` 
      fi 
      ((numline+=1)) 
     done < ${OUTPUT_FOLDER}/${host} 
     echo "$DATETIME,$FIELD1" >> ${LOG_DIR}/${DATE}.log 
    done < $HOST_FILE 
    sleep $SLEEPTIME 
done 

當我運行該腳本,每60秒,我會看到我的日誌文件中的$DATETIME,$FIELD1值。

非常奇怪的是,每隔30秒鐘左右,在第一分鐘過後,我會看到20160920_120232,,這意味着有輸出的地方不應該有,我猜是因爲我刪除了內容我的輸出文件夾,FIELD1是空的。

更奇怪的是,當試圖調試這個時,我添加了幾條echo語句來打印到我的日誌文件中,然後我刪除了這些行。但是,在第一分鐘過後,它們每30秒左右繼續打印一次。

什麼是陌生人還是那個我,然後註釋掉一切while true塊內,也就是

OUTPUT_FOLDER=/home/user/output 
HOST_FILE=/home/user/host.txt 
LOG_DIR=/home/user/log 
SLEEPTIME=60 

mkdir -p $OUTPUT_FOLDER 

while true 
do 
: << 'END' 
    rm -f $OUTPUT_FOLDER/* 
    DATE=`date +"%Y%m%d"` 
    DATETIME=`date +"%Y%m%d_%H%M%S"` 
    pssh -h $HOST_FILE -o $OUTPUT_FOLDER 
    while read host 
    do 
     numline=0 
     while read line 
     do 
      if [[ $numline == 0 ]] 
      then 
       FIELD1=`echo $line | cut -d':' -f2 | cut =d' ' -f2` 
      fi 
      ((numline+=1)) 
     done < ${OUTPUT_FOLDER}/${host} 
     echo "$DATETIME,$FIELD1" >> ${LOG_DIR}/${DATE}.log 
    done < $HOST_FILE 
    sleep $SLEEPTIME 
END 
done 

即使這個劇本,在那裏我期待什麼可打印到我的日誌文件,我請參閱我之前刪除的echo聲明以及空行FIELD1。我檢查了我每次都運行正確的腳本版本。

這是怎麼回事?

+2

有沒有你不知道的後臺進程? – Jokester

+0

您在進行更改後是否重新啓動了此過程?並確保舊的過程真的沒有運行? – yaccz

+0

'fuser -k/path/to/file',確保寫入該文件的所有內容都已經死了,是你的朋友。或者只是'fuser/path/to/file',並確保包含句柄的進程列表符合您的期望。 –

回答

1

我試圖重現它並不能。這個腳本沒有理由(當你有評論時)產生任何輸出。

有幾個情況:

  1. 正如其他人所指出的,可能有一些其他的腳本寫日誌文件
  2. 您可能將在其他終端
  3. 運行此腳本的幾個實例
  4. 您可從crontab中運行此腳本每5分鐘

爲了排除可能性一次,做一個「PS -aef」,並檢查了所有可能像第n過程你的腳本的一部分。爲了從crontab中獲得一些東西,你可能需要觀察「ps -aef」的輸出時間(或者只是檢查crontab條目)。

+0

謝謝!事實證明,我確實有這個腳本的一些實例在後臺運行。一旦我殺了他們,產量如預期。 – Rayne

2

我不確定,它可能是擰緊的真正原因。行號22中的cut的使用不正確,這可能會無意中破壞FIELD1

FIELD1=`echo $line | cut -d':' -f2 | cut =d' ' -f2` 
#          ^incorrect usage of the delimiter '-d' flag 
應作爲

FIELD1=`echo $line | cut -d':' -f2 | cut -d' ' -f2` 
#          ^Proper usage of the '-d' flag with space delimiter 

我試圖捕捉到管道命令的輸出,看看最後的命令可能成功,下面是我的觀察已經使用

echo $line | cut -d':' -f2 | cut =d' ' -f2;echo "${PIPESTATUS[@]}" 
cut: =d : No such file or directory  # --> Error from the failed 'cut' command 
0 0 1         # --> Return codes of each of the command being piped 

另外,如果你是一個bash純粹的,你已經避免了傳統``風格的命令擴展和使用$(cmd)語法一樣,

FIELD1=$(echo "$line" | cut -d':' -f2 | cut -d' ' -f2) 

另一種更簡單的方式會一直避免使用cut & echo並做純bash字符串操作。

假設您的$line包含:不受限制的字符串,例如, "What Hell:Hello World"和你正在試圖提取World一部分,我可以看到,只是做

FIELD1="${line##* }" # Strips-off characters until last occurrence of whitespace