如何在不關閉管道的情況下截斷 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最多將所需數量的資料傳遞到函數的標準輸出。如果還有更多數據,cat將丟棄它而不中斷du。的退出狀態du從陣列中檢索PIPESTATUS並由函數傳回。

注意:我的變數使用lower case;看這個答案


如果沒有函數,相同的解如下所示:

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

IMO 這樣的可讀性稍差一些。

答案2

這限制了您捕獲的數量,但我假設它以reads 退出狀態退出(我不知道它是否停止它會停止命令,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

我假設文件被觸及的事實意味著在捕獲請求的字元數後命令不會中斷。

也許您可以將退出狀態寫入子 shell 中的檔案中:

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

相關內容