2016-09-20 18 views
0

シェルスクリプトの作成中に非常に奇妙なことに遭遇しています。シェルスクリプトの奇妙な出力

最初は次のスクリプトがあります。私はこのスクリプトを実行した

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値が表示されます。

最初の1分が経過した後、30秒ごとにそれが表示されますが、私は20160920_120232,と表示されます。出力があってはならないことを意味します。私の出力フォルダFIELD1は空です。

さらに奇妙なことに、これをデバッグしようとしている間に、私はログファイルに印刷するためにさらにechoステートメントを追加し、それらの行を削除しました。しかし、最初の1分が経過してから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

を行い、私はそれを再現しようとしましたが、できなかった、私が見ることができるようWorld一部を抽出しようとしています。 Threは、(あなたが持っているとコメントしたときに)このスクリプトが何らかの出力を生成する理由はありません。

例のカップルがあります。

  1. は、他の人が指摘したように、あなたのログファイルに
  2. を書いて、いくつかの他のスクリプトがあるかもしれません。あなたは他の端末
  3. 上で実行されているこのスクリプトのいくつかのインスタンスを残している可能性があり
  4. あなたは、可能性を排除「のps -aef」を行うとnに似ている可能性があり、すべてのプロセスをチェックアウトするために、一回5分

のcrontabからこのスクリプトを実行することができますあなたのスクリプトのame。 crontabから物事を捕まえるには、 "ps -aef"の出力をもっと長く(またはcrontabエントリをチェックインするだけで)見る必要があるかもしれません。

+0

ありがとう!私はこのスクリプトのいくつかのインスタンスをバックグラウンドで実行していました。一度私がそれらを殺すと、出力は期待どおりです。 – Rayne

2

確かに、それはねじ締めの実際の理由かもしれません。行番号22の間違った使用cutがあります。これは誤ってFIELD1をマングルしている可能性があります。

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

として使用されている必要があります

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

私は最後のコマンドが成功し、以下の私の観察だったかもしれないかどうかを確認するためにパイプされたコマンドの出力をキャプチャしてみました。

あなたは bash純粋主義者だった場合
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 

また、あなたがレガシー``スタイルのコマンドの拡張を避けてきたなど$(cmd)構文を使用し、

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

もう一つの簡単な方法は、使用を避けることだっただろうcut & echoとし、純粋なbash文字列操作を行います。

$lineには、:の制限されていない文字列が含まれていると仮定します。 "What Hell:Hello World"とあなただけ

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