Grep 不会在脚本中返回管道状态,但会在 shell 中返回。
查看包含的脚本:
#!/usr/bin/env bash
function testSshConnection() {
local SSH_CMD="ssh -o BatchMode=yes -o ConnectTimeout=3 $1@$2 2>&1 | grep \"Host key verification failed.\""
echo "RUNNING: $SSH_CMD"
$SSH_CMD
PIPE_RESULT="${PIPESTATUS[0]} ${PIPESTATUS[1]}"
echo "FUNCTION: PIPE_RESULT: ${PIPE_RESULT}"
PIPE_RESULT_ARRAY=($PIPE_RESULT)
PIPE0="${PIPE_RESULT_ARRAY[0]}"
PIPE1="${PIPE_RESULT_ARRAY[1]}"
local RC=${PIPE1:-$PIPE0}
echo "Returning RC=$RC"
return $RC
}
while ! testSshConnection root $1; do
PIPE_RESULT="${PIPESTATUS[0]} ${PIPESTATUS[1]}"
echo "WHILE: PIPE_RESULT: ${PIPE_RESULT}"
PIPE_RESULT_ARRAY=($PIPE_RESULT)
PIPE0="${PIPE_RESULT_ARRAY[0]}"
PIPE1="${PIPE_RESULT_ARRAY[1]}"
WAIT=4
echo "Waiting $SLEEP seconds for host $1 to be accessible on port 22"
sleep $WAIT
done
exit
脚本输出:
~ $ /tmp/test.sh 46.101.7.220
RUNNING: ssh -o BatchMode=yes -o ConnectTimeout=3 root@46.101.7.220 2>&1 | grep "Host key verification failed."
Host key verification failed.
FUNCTION: PIPE_RESULT: 255
Returning RC=255
WHILE: PIPE_RESULT: 255
Waiting 4 seconds for host 46.101.7.220 to be accessible on port 22
RUNNING: ssh -o BatchMode=yes -o ConnectTimeout=3 root@46.101.7.220 2>&1 | grep "Host key verification failed."
Host key verification failed.
FUNCTION: PIPE_RESULT: 255
Returning RC=255
WHILE: PIPE_RESULT: 255
...etc
在单独的 shell 中运行 ssh 命令的输出:
~ $ ssh -o BatchMode=yes -o ConnectTimeout=3 root@46.101.7.220 2>&1 | grep "Host key verification failed."
Host key verification failed.
~ $ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
255 0
为什么脚本中的 ssh 命令没有为 grep 命令返回 ${PIPESTATUS[1]}?
最佳答案
您需要使用 eval
来处理 $SSH_CMD
,就好像它是作为命令键入的一样。
eval "$SSH_CMD"
扩展变量后完成的唯一处理是分词和文件通配。它不处理 ecapes、管道、重定向、命令定界符等。因此当您执行该命令时,它相当于执行:
ssh -o BatchMode=yes -o ConnectTimeout=3 root@46.101.7.220 '2>&1' '|' grep '"Host' key verification 'failed."'
我已经引用了命令中包含 shell 元字符的部分,以表明它们在扩展变量后没有被特殊处理。
结果是命令“2>&1 | grep ...将被发送到远程主机。这将执行命令
2>&1和
grep ...` 在服务器上,而不是在客户端上,管道也在服务器上完成。
一个更简单的例子,试试这个:
data="foo | wc"
echo $data
这将打印foo | wc
从字面上看,它不会执行 echo foo
然后将其通过管道传递给 wc
。但如果你这样做:
eval "echo $data"
它会像你写的一样
echo foo | wc
有关详细信息,请参阅 Shell Operation 部分在 Bash 手册中。 |
和 >
等元字符的处理是在这一步中完成的:
- 将标记解析为简单和复合命令(参见 Shell Commands)。
扩展变量在下一步完成:
- 执行各种 shell 扩展(参见 Shell Expansions ),将扩展的标记分解为文件名列表(参见 Filename Expansion )以及命令和参数。
由于变量扩展发生在 寻找管道和重定向之后,这些操作不会在本地完成,它们将在 ssh< 发送命令时在远程系统上完成
.
关于linux - SSH 命令输出中使用的 Grep 不返回 PIPESTATUS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55816985/