Grep, используемый при выводе команды SSH, не возвращает PIPESTATUS - PullRequest
0 голосов
/ 23 апреля 2019

Grep не возвращает pipestatus в сценарии, но возвращает в оболочке.

См. Включенный сценарий:

#!/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

Вывод команды 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 в сценарии не возвращает $ {PIPESTATUS [1]} для команды grep?

1 Ответ

1 голос
/ 23 апреля 2019

Вам нужно использовать eval для обработки $SSH_CMD, как если бы оно было введено как команда.

eval "$SSH_CMD"

Единственная обработка, выполняемая после расширения переменной, - это разбиение по словам и глобализация файла. Он не обрабатывает ecap, каналы, перенаправления, разделители команд и т. Д. Поэтому, когда вы выполнили эту команду, она была эквивалентна выполнению:

ssh -o BatchMode=yes -o ConnectTimeout=3 root@46.101.7.220 '2>&1' '|' grep '"Host' key verification 'failed."'

Я процитировал части команды, которые содержат метасимволы оболочки, чтобы указать, что они не обрабатываются специально после расширения переменной.

Результатом этого является то, что команда "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. Обработка метасимволов, таких как | и >, выполняется на этом шаге:

  1. Разбирает токены на простые и составные команды (см. Команды оболочки ).

Расширение переменных выполняется на следующем шаге:

  1. Выполняет различные расширения оболочки (см. Расширения оболочки ), разбивая развернутые токены на списки имен файлов (см. Расширение имени файла ), а также команды и аргументы.

Поскольку расширение переменной происходит после поиска каналов и перенаправления, эти действия не будут выполняться локально, они будут выполняться в удаленной системе, когда команда отправляется ssh.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...