Назад | Перейти на главную страницу

Выполнение сценария удаленно с помощью «curl | bash »обратная связь

Я работаю над платформой, которая использует много таких команд: ssh login@server.com 'curl http://some_server/script.sh | bash'

Это действительно чисто и удобно для удаленного выполнения сценариев, однако я не вижу возможности получить код вывода / выхода сценария. Любой может что-то выяснить, чтобы убедиться, что сценарий был правильно выполнен (с хоста, запускающего точку зрения ssh).

Как отмечает @Zoredache, ssh передает статус удаленной команды как собственный статус выхода, поэтому обнаружение ошибок прозрачно работает через SSH. Однако два важных момента требуют особого внимания в вашем примере.

Первый, curl имеет тенденцию быть очень снисходительным, рассматривая многие ненормальные состояния как успех. Например, curl http://serverfault.com/some-non-existent-url-that-returns-404 на самом деле имеет статус выхода 0. Я считаю такое поведение нелогичным. Чтобы рассматривать эти условия как ошибки, мне нравится использовать -fsS флаги:

  • В --fail флаг подавляет вывод при сбое, так что bash не будет возможности выполнить страницу ошибки 404 веб-сервера, как если бы это был код.
  • В --silent --show-error флаги вместе обеспечивают разумное количество сообщений об ошибках. --silent подавляет все комментарии от curl. --show-error повторно включает сообщения об ошибках, которые отправляются в STDERR.

Во-вторых, у вас есть канал, а это означает, что сбой может произойти либо в первой, либо во второй команде. Из раздела про Конвейеры в bash (1):

Статус возврата конвейера - это статус выхода последней команды, если только pipefail опция включена (см. Набор Встроенный). Если pipefail включен, статус возврата конвейера - это значение последней (самой правой) команды для выхода с ненулевым статусом или ноль, если все команды завершаются успешно.

Боковое примечание: bash документация актуальна не потому, что вы bash, но потому что (я предполагаю) это оболочка входа в систему вашего удаленного пользователя и, следовательно, это программа, которая интерпретирует удаленную командную строку и обрабатывает выполнение конвейера. Если у пользователя другая оболочка входа в систему, обратитесь к документации по этой оболочке.

В качестве конкретного примера:

( echo whoami ; false ) | bash
echo $?

дает результат

login
0

демонстрируя, что bash в конце конвейера маскирует статус ошибки, возвращаемый false. Он вернет 0, пока он успешно выполняется whoami.

Напротив,

set -o pipefail
( echo whoami ; false ) | bash
echo $?

дает

login
1

так что сообщается об отказе в первой половине трубопровода.


Собирая все вместе, решение должно быть

ssh login@server.com 'set -s pipefail ; curl -fsS http://some_server/script.sh | bash'

Таким образом, вы получите ненулевой статус выхода, если любой из следующих результатов вернет ненулевое значение:

  • ssh
  • Оболочка удаленного входа
  • curl
  • В bash в конце конвейера

Кроме того, если curl -fsS обнаруживает ненормальный код состояния HTTP, затем он:

  • подавить его STDOUT, чтобы ничего не передавалось bash быть выполненным
  • вернуть ненулевое значение, которое правильно распространяется на всем пути
  • распечатать однострочное диагностическое сообщение в его STDERR, которое также распространяется на всем пути

Когда SSH вернется, он должен выдать код выхода из скрипта.

Пытаться ssh user@host 'echo "exit 2" | bash' ; echo $?. Вы должны увидеть значение 2 вернулся.

Просто напишите много хороших проверок ошибок в вашем скрипте и убедитесь, что ваш скрипт завершается с полезными ошибками и кодами выхода. Убедитесь, что ваш скрипт возвращает ненулевые коды выхода при любых ошибках.

Это ужасный взлом. Если вы хотите удаленное выполнение, используйте что-то, что выполняет удаленное выполнение должным образом, например func или mcollective.

Вот несколько вариантов, которые вы можете попробовать.

Другой способ - использовать echo $? запускается сразу после выполнения скрипта,

# ssh login@server.com 'curl http://some_server/script.sh | bash; echo $?' 

Это даст вам статус выхода скрипта. или Предоставляйте текст, только если статус выхода равен 0

# ssh login@server.com 'curl http://some_server/script.sh | bash && echo "Script Completed!"'

Появится сообщение «Сценарий завершен!» при успешном исполнении. или Отображать код ошибки, только если статус выхода не равен 0

# ssh login@server.com 'curl http://some_server/script.sh | bash || echo "Script Failed: $?"'

Будет отображено сообщение «Script Failed:». Как было предложено @Zoredache, добавление нескольких статусов выхода к вашему скрипту поможет вам определить, что пошло не так.

Все будет зависеть от того, что script.sh ДЕЛАЕТ / выполняет свою работу. Если он подробный (выполняет то, что имеет вывод), вы сможете увидеть их в STDOUT / STDERR в своем потоке ssh. Если если не измените его, сделайте это.