我正在寻找一种方法来限制从子进程的输出初始化的 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
当读取前 10k 个输出时,替代方案OUT_DATA=$($COMMAND_TO_RUN | head -c 10000)
会取消该命令,并且我需要该命令运行完成以捕获其退出状态。
我可以很容易地在 中完成此操作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="$?"
我认为这种方式的可读性较差。
答案2
这会限制您捕获的数量,但我假设它以read
退出状态退出(我不知道它是否会停止,它会像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