パイプを閉じずにbash変数の割り当てを切り捨てる方法

パイプを閉じずにbash変数の割り当てを切り捨てる方法

サブプロセスの出力から初期化される Bash 変数に保存されるデータの量を制限する方法を探しています。

この潜在的な解決策の問題点は、切り捨てる前に出力全体を保存することです。

#!/bin/bash

COMMAND_TO_RUN="du /"

OUT_DATA=$($COMMAND_TO_RUN)
OUT_RESULT=$?

if [[ $OUT_RESULT -ne 0 ]]; then
    echo "${OUT_DATA:0:10000}" | head mail -s "Command failed" [email protected]
fi

代替案ではOUT_DATA=$($COMMAND_TO_RUN | head -c 10000)、出力の最初の 10k が読み取られたときにコマンドがキャンセルされ、終了状態をキャプチャするためにコマンドを完了まで実行する必要があります。

では簡単に実行できますpythonが、bash唯一の解決策を期待しています。また、ディスクへの書き込みに頼らずに実行できることも期待しています。

答え1

関数を使用します。読みやすくするために、以下の例ではコマンドなどをハードコードしています。

truncated_du() {
   du / | { head -c 10000; cat >/dev/null; }
   return "${PIPESTATUS[0]}"
}

out_data="$(truncated_du)"
out_result="$?"

head関数の stdout に最大で必要な量のデータを渡します。それ以上のデータがある場合は、cat関数を中断せずに破棄しますdu。関数の終了ステータスは配列duから取得されPIPESTATUS、関数によって返されます。

注: 私の変数はlower case; を使用します。この答え


関数がない場合、同じ解決策は次のようになります。

out_data="$(
   du / | { head -c 10000; cat >/dev/null; }
   exit "${PIPESTATUS[0]}"
)"
out_result="$?"

私の意見では、この方法では少し読みにくくなります。

答え2

これによりキャプチャする量が制限されますが、read終了ステータス s で終了すると想定しています (終了ステータスが尊重されないため、次のようにコマンドが停止するかどうheadかはわかりません: `

IFS= read -r -d '' -n $chars_to_capture foo < <($command)

コマンドは完了まで実行されるように見えますが、コマンドの終了ステータスは取得されず、read役に立たない終了ステータスが取得されます。

$ IFS= read -r -d '' -n 19 foo < <(seq 50; touch somefile; exit 42); echo "exit=$?"; ls -l somefile
exit=0
-rw-r--r-- 1 glennjackman staff 0 Jul 22 22:04 somefile

ファイルがタッチされるということは、要求された文字数がキャプチャされた後もコマンドが中断されないことを意味すると想定します。

おそらく、サブシェル内のファイルに終了ステータスを書き込むことができます。

IFS= read -r -d '' -n 10000 out_data < <( $command_to_run; echo $? > statusfile )
if [[ -f statusfile ]] && [[ "$(<statusfile)" != "0" ]]; then
    printf "%s\n" "$out_data" | head mail -s "Command failed" [email protected]
    rm statusfile
fi

関連情報