Grep在脚本中不返回pipestatus,但在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]}?
答案 0 :(得分:1)
您需要使用eval
来处理$SSH_CMD
,就像将其作为命令键入一样。
eval "$SSH_CMD"
扩展变量后唯一要做的处理是分词和文件遍历。它不处理转义符,管道,重定向,命令定界符等。因此,当您执行该命令时,它等效于执行:
ssh -o BatchMode=yes -o ConnectTimeout=3 root@46.101.7.220 '2>&1' '|' grep '"Host' key verification 'failed."'
我已经引用了包含shell元字符的命令部分,以表示在扩展变量后,它们没有得到特殊处理。
其结果是,命令“ 2>&1 | grep ... will be sent to the remote host. This will execute the commands
2>&1 and
grep ...`在服务器上而不是在客户端上通过管道传输也可以在服务器上完成。
举一个简单的例子,试试这个:
data="foo | wc"
echo $data
这将按字面意义打印foo | wc
,它将不会执行echo foo
,然后将其通过管道传输到wc
。但是,如果您这样做:
eval "echo $data"
它就像您写的一样
echo foo | wc
有关更多详细信息,请参见《 Bash手册》中的Shell Operation部分。在此步骤中完成对|
和>
之类的元字符的处理:
扩展变量将在下一步完成:
由于变量扩展发生在 查找管道和重定向之后,因此这些操作不会在本地完成,因此当ssh
发送命令时,这些操作将在远程系统上完成