我想循环命令的输出而不创建子 shell 或使用临时文件。
我的脚本的初始版本看起来像这样,但这不起作用,因为它创建了一个子 shell,并且该exit
命令终止子 shell 而不是所需的主脚本。它是一个更大的脚本的一部分,用于配置策略路由,如果它检测到会导致路由失败的条件,它就会停止执行。
sysctl -a 2>/dev/null | grep '\.rp_filter' | while read -r -a RPSTAT ; do
if [[ "0" != "${RPSTAT[2]}" ]] ; then
echo >&2 "RP Filter must be disabled on all interfaces!"
echo >&2 "The RP filter feature is incompatible with policy routing"
exit 1
fi
done
因此,建议的替代方案之一是使用这样的命令来避免使用子 shell。
while read BLAH ; do echo $BLAH; done </root/regularfile
所以在我看来,我也应该能够使用这样的命令来避免子 shell,并且仍然从我想要的程序中获得输出。
while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')
不幸的是,使用该命令会导致此错误。
-bash: syntax error near unexpected token `<(sysct ...
我真的很困惑,因为这确实有效。
cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')
我可以将该命令的输出保存到临时文件,并在临时文件上使用重定向,但我想避免这样做。
那么为什么重定向会给我一个错误,除了创建临时文件之外我还有其他选择吗?
答案1
你错过了一个<
。应该:
while read BLAH ; do echo $BLAH; done < <(sysctl -a 2>/dev/null | grep '\.rp_filter')
认为<(sysctl -a 2>/dev/null | grep '\.rp_filter')
是一个文件。
答案2
如果有人再次来到这里,请提供更多选择......
根据 shell,您可能可以在set -o errexit
命令(包括子 shell)以非零值退出时让父 shell 退出,而不会被困在块if
或尾随&&
或||
中,如
/bin/false || echo "ignoring error"
或者,您可以让子 shell 使用kill 和 $PPID 环境变量(如果可用)向父 shell 发出信号。
或者您可以将 while 块移动到函数中并返回 0/1 (在 while 块之后显式返回 0),然后像sysctl | grep | function || exit
.我想你也可以将返回值放在内联块中,但是函数是你的朋友。 ;)