シェルスクリプト - 出力をファイルにリダイレクトして最初に実行した場合、結果は予想とは異なります。

シェルスクリプト - 出力をファイルにリダイレクトして最初に実行した場合、結果は予想とは異なります。

私は時々ファイルから2行、5行.. 100行などを返すコマンドの出力をリダイレクトしました。後で他の条件を確認するには、if条件でこのファイルを使用します。

奇妙なことは、期待どおりにデータを取得するためにスクリプトを複数回実行する必要があることです。スクリプトを初めて実行すると、何も返されません。これが最初の実行で予想される結果を提供しない理由を説明してください。

コードはAIX用で、次のとおりです。

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
        chmod 777 /tmp/DISKREQ.TMP
        cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ.TMP
        cat /tmp/DISKREQ.TMP | while read line
        do
                        FSIZE_DISKREQ=`df -g | awk '$7 == "'$line'" {print $3;}'`
                        if [[ $FSIZE_DISKREQ -lt 2 ]]; then
                        echo
                         echo " Instance Home Directory $line = $FSIZE_DISKREQ "
                        else
                        echo
                                echo " Instance Home Directory $line "
                        fi
        done
else
echo
        echo "No Instance Home directory Mounted"
fi

ベストアンサー1

cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ.TMP

パイプラインのコンポーネントは並列に実行されます。したがって、この行は3つのコマンドを並列に実行します。

  • cat /tmp/DISKREQ.TMP
  • awk '{print$6}'
  • awk 'length($0) == 22' > /tmp/DISKREQ.TMP

最初のコマンドは/tmp/DISKREQ.TMP読み取り用に開いています。 3番目のコマンドは、/tmp/DISKREQ.TMP他の操作を実行する前に切り捨てられます。時間によっては、cat少なくともファイルの先頭を読み取る時間がある場合とない場合があります。

解決策:入力と同じファイルに書き込まないでください。 (名前を再利用できるより複雑で壊れやすい解決策があります。ここでは複雑な作業を行う必要がないため、解決策を提供しません。)

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
    cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ2.TMP
    cat /tmp/DISKREQ2.TMP | while read line

(使用しないでくださいchmod 777。これは問題を解決せず、実際に問題が発生する可能性があります。)

ただし、これらの一時ファイルがすべて必要なわけではないため、そのファイルを削除すると問題を完全に回避できます。 2番目の一時ファイルを削除するには、awkチェーンをwhileループに直接パイプするだけです。また、役に立たない用途を削除し、両方のcatスクリプトawkを1つにマージしました。

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
    </tmp/DISKREQ.TMP awk 'length($6) == 22 {print $6}' | while read line
    do

完全に削除しawkてループでフィルタリングすることもできますwhile read。これについては読者に練習として残しておきます。

最初の一時ファイルを削除するには、ロジックを少し変更する必要があります。何も見つからないと処理する行がないため、whileループ本体は実行されません。ただし、この場合、メッセージを表示するにはいくつかのロジックが必要です。 awkでgrepディレクティブを使用できます。END

df -gt | grep /home/prods/db2/ |
awk 'length($6) == 22 {print $6}
     END {if (NR==0) print "No Instance Home directory Mounted"}' |
while read line; do …

grep通貨とを組み合わせることができますawk。 (読者のための練習用です。)またはフルフィルタリングをシェルで実行することもできます。私はこれが/home/prods/db2/常に6列の始まりだと思います。

found=0
df -gt |
while read device total used available percent mountpoint; do
    [[ $mountpoint == /home/prods/db2/* ]] || continue
    ((++found))
    [[ ${#mountpoint} -eq 22 ]] || continue
done
if ((found == 0)); then echo "No Instance Home directory Mounted"; fi

おすすめ記事