在没有子 shell 的情况下迭代 bash 中命令的输出

在没有子 shell 的情况下迭代 bash 中命令的输出

我想循环命令的输出而不创建子 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.我想你也可以将返回值放在内联块中,但是函数是你的朋友。 ;)

相关内容