【问题标题】:Bash Grep Quiet SSH OutputBash Grep 安静的 SSH 输出
【发布时间】:2026-01-19 22:50:02
【问题描述】:

我正在尝试匹配 SSH 命令的输出,但由于某种原因它无法正常工作。我正在使用 authorized_keys 将登录限制为一个命令 - 这是一个带有参数的包装脚本。

这是我的代码:

for i in `seq 2 254`; do
  myoutput=$( ssh system@server01 ip 192.168.0.$i )
  echo "$myoutput"
  echo "$myoutput" | grep -q "not found"
  if [ $? -eq 0 ]; then
    echo 192.168.0.$i
    exit
  fi
done

这是脚本的输出:

192.168.0.2 not found in DB.  Try searching live (--forcelive)
192.168.0.3 not found in DB.  Try searching live (--forcelive)
192.168.0.4 not found in DB.  Try searching live (--forcelive)

这应该在第一个实例中停止并回显 IP,但它会继续进行,因为所有 grep 都返回 1 而不是 0。SSH 命令本身(没有 grep)每次都返回 0。

为什么 grep 的响应编码错误?有没有更好的方法来完成我想做的事情?

【问题讨论】:

  • #1。您错过了代码末尾的done。 #2,请缩进for循环。 #3,不要使用return作为变量名,因为它明显与shell内置冲突。
  • #4 而不是if [ $? -eq 0 ]; then 尝试做if echo "$return" | grep -q "not found"; then 或更好if grep -q <<< "$return"; then
  • if 检查命令的返回值。只是我们太习惯于看到 test 命令 ([) 或内置的 shell [[,以至于我们忘记了任何返回码都可以。
  • 这个内容很可能在 stderr 上,而不是在 stdout 上。
  • 顺便说一句,你知道你使用的ip 命令的退出状态是否会根据它是否找到东西而变化吗?通常,检查命令的退出状态比尝试解释其输出要好得多。

标签: bash ssh


【解决方案1】:

您尝试搜索的内容几乎肯定在 stderr 上,因此您的替换根本没有捕获它;因此,它通过调用 ssh 的同一命令发送到控制台,而不是放在 myoutput 变量中。

考虑使用重定向2>&1 将stderr 重定向到stdout,如下所示:

myoutput=$( ssh system@server01 "ip 192.168.0.$i" 2>&1 )

顺便说一句,如果您对调用 ssh 超过 200 次的开销感到满意,我会认真考虑这样重写:

for ((i=2; i<254; i++)); do
  if ssh system@server01 "ip 192.168.0.$i" 2>&1 | grep -q 'not found'; then
    echo "192.168.0.$i"
    exit
  fi
done

为什么?

  • seq 既不是 bash 内置的,也不是 POSIX 指定的。因此,它甚至不能保证存在,更不用说以任何特定方式表现了。
  • 由 ssh 传递到远程系统的命令行被构建为由连接参数生成的单个字符串。因此,只传递一个带有您希望执行的确切代码的字符串是对幕后发生的事情的更诚实的表示,并避免了通过忘记 ssh really 对其命令所做的事情而产生的错误行。
  • 当您可以简单地直接测试命令是否成功时,使用 $? 是一种不好的形式。

如果您不受authorized_keys 的限制,顺便说一句,您最好将脚本评估移至远程系统,例如:

ip_found=$(ssh system@server01 bash -s <<'EOF'
  for ((i=2; i<254; i++)); do
    content=$(ip "192.168.0.$i" 2>&1)
    if [[ $content = *"not found"* ]]; then
      echo "192.168.0.$i"
      exit 0
    fi
  done
  exit 1
EOF
)

echo "Remote system found $ip_found"

...由于您受到如此限制,出于性能原因,您可能会考虑使用SSH multiplexing 在您的许多查询中重用一个经过身份验证的连接。

【讨论】:

  • 如果输出来自echo "$myoutput"这一行,那就不可能了
  • 当然,但我的观点是,OP 几乎可以肯定 错误 他们假设输出来自echo。除非他们使用set -x 运行他们的脚本,否则他们不确定。
  • 有道理。即使stdout 不是因为$(...),仍会打印stderrecho 不会在每个条目之间添加额外的换行符吗?
  • 哦——这个问题我确实没有很好的答案。
  • 感谢您的精彩回答和建议!