我制作了一个脚本,其中一个函数通过 ssh 从远程服务器接收信息:
session_check() {
ssh -o BatchMode=yes $USER@$SERVER my_command | grep "value" > /dev/null
}
按照计划,访问将使用密钥,但如果密钥未加载到远程计算机上,我会得到:
Permission denied (publickey,password)
我不能使用返回0或1,因为如果访问服务器成功,但命令不成功,也会以相同的方式返回1。我需要以某种方式隐藏“权限被拒绝”消息,并设置一个只有在收到此类消息时才会满足的条件。
我希望我写清楚了。提前致谢!
更新
我弄清楚了如何使用 stderr ( 2>> (grep "value")
),但我仍然无法将它与上面的函数一起使用。所以我需要将 stderr 重定向到某个地方以供以后使用。但为了以某种方式从服务器上执行命令中获得 ruselt(如果可以连接到服务器)。我怀疑这通常是不可能用一个命令来实现的,我需要先检查连接是否成功,然后再执行该命令。你怎么认为?
答案1
在您的脚本中,因为您使用的是管道,所以您已经忽略了my_command
;的退出状态。管道的退出状态将是管道中最后一个命令的退出状态。
不过,Bash 允许您检查管道中任何命令的退出代码;现在您只需确保您的远程命令始终成功。因为您已经忽略了它的退出状态,所以我们不会引入任何新的错误。
session_check() {
ssh -o BatchMode=yes $USER@$SERVER 'my_command; exit 0' | grep -q "value"
local rc=$?
if [[ ${PIPESTATUS[0]} != 0 ]]; then
return 127
fi
return $rc
}
如果你也想获得退出状态my_command
,那将会变得更加困难;也许然后将其分成两个单独的命令。
session_check() {
status=$(ssh -o BatchMode=yes $USER@$SERVER 'my_command; echo $?') &&
sed '$d' <<<"$status" | grep -q "value"
return $(sed -n '$p' <<<"$status")
}
请注意我们如何将退出代码作为ssh
命令的最后一行文本输出偷偷取出,然后重复遍历它。为了提高效率,这可能应该被重构,但至少展示了一种在需要时实现它的方法。
请注意,我们在这里使用了几个仅 Bash 的功能;脚本需要有#!/bin/bash
,而不是#!/bin/sh
在 shebang 中。
对这种欺骗的需要表明,在 shell 处理模型中的受控错误处理方面,您已接近可行的边界。也许您想尝试用 Python 等现代脚本语言重写部分或全部内容。