Shell script Статус выхода ssh команды

В цикле в оболочке script я подключаюсь к различным серверам и запускаю некоторые команды. Например

#!/bin/bash
FILENAME=$1
cat $FILENAME | while read HOST
do
   0</dev/null ssh $HOST 'echo password| sudo -S 
   echo $HOST 
   echo $?      
   pwd
   echo $?'
done

Здесь я запускаю команды "echo $HOST" и "pwd", и я получаю статус выхода через "echo $?".

Мой вопрос в том, что я хочу иметь возможность сохранять статус выхода из команд, которые я запускаю удаленно в какой-то переменной, а затем (на основе того, была ли команда успешной или нет), напишите журнал в локальный файл.

Любая помощь и код оцениваются.

Ответ 1

ssh выйдет с кодом выхода удаленной команды. Например:

$ ssh localhost exit 10
$ echo $?
10

Итак, после завершения команды ssh вы можете просто проверить $?. Вы должны убедиться, что вы не замаскируете свое возвращаемое значение. Например, ваша команда ssh заканчивается:

echo $?

Это всегда будет возвращать 0. То, что вы, вероятно, хотите, это нечто большее:

while read HOST; do
  echo $HOST
  if ssh $HOST 'somecommand' < /dev/null; then
    echo SUCCESS
  else
    echo FAIL
done

Вы также можете записать его так:

while read HOST; do
  echo $HOST
  if ssh $HOST 'somecommand' < /dev/null
  if [ $? -eq 0 ]; then
    echo SUCCESS
  else
    echo FAIL
done

Ответ 2

Вы можете присвоить статус выхода переменной так же просто, как делать:

var_name= $?

Сразу после команды, которую вы пытаетесь проверить. Не echo $? до или новое значение $? будет кодом выхода echo (обычно 0).

Ответ 3

Интересный подход состоял бы в том, чтобы получить весь вывод каждого набора команд ssh в локальной переменной с использованием обратных ссылок или даже отдельно со специальным charachter (для простоты сказать ":" ) что-то вроде:

export MYVAR=`ssh $HOST 'echo -n ${HOSTNAME}\:;pwd'`

после этого вы можете использовать awk для разделения MYVAR в свои результаты и продолжить тестирование bash.

Ответ 4

Возможно, подготовьте файл журнала с другой стороны и передайте его в stdout, например:

ssh -n [email protected] 'x() { local ret; "[email protected]" >&2; ret=$?; echo "[`date +%Y%m%d-%H%M%S` $ret] $*"; return $ret; };
x true
x false
x sh -c "exit 77";'  > local-logfile 

В основном просто префикс все на пульте, который вы хотите вызвать с помощью этой x оболочки. Он также работает для условных выражений, так как он не изменяет код выхода команды.

Вы можете легко выполнить эту команду.

Этот пример записывает в журнал что-то вроде:

[20141218-174611 0] true
[20141218-174611 1] false
[20141218-174611 77] sh -c exit 77

Конечно, вы можете сделать его более понятным или адаптировать к вашим желаниям, как выглядит файл журнала. Обратите внимание, что нераскрытая нормальная stdout удаленных программ записывается в stderr (см. Перенаправление в x()).

Если вам нужен рецепт для улова и подготовки вывода команды для файла журнала, вот копия такого улавливателя из https://gist.github.com/hilbix/c53d525f113df77e323d - но да, это немного больший шаблон для "Запускать что-то в текущем контексте оболочки, постпроцессинг stdout + stderr без нарушения кода возврата":

# Redirect lines of stdin/stdout to some other function
# outfn and errfn get following arguments
# "cmd args.." "one line full of output"
: catch outfn errfn cmd args..
catch()
{
local ret o1 o2 tmp
tmp=$(mktemp "catch_XXXXXXX.tmp")
mkfifo "$tmp.out"
mkfifo "$tmp.err"
pipestdinto "$1" "${*:3}" <"$tmp.out" &
o1=$!
pipestdinto "$2" "${*:3}" <"$tmp.err" &
o2=$!
"${@:3}" >"$tmp.out" 2>"$tmp.err"
ret=$?
rm -f "$tmp.out" "$tmp.err" "$tmp"
wait $o1
wait $o2
return $ret
}

: pipestdinto cmd args..
pipestdinto()
{
local x
while read -r x; do "[email protected]" "$x" </dev/null; done
}

STAMP()
{
date +%Y%m%d-%H%M%S
}

# example output function
NOTE()
{
echo "NOTE `STAMP`: $*"
}

ERR()
{
echo "ERR `STAMP`: $*" >&2
}

catch_example()
{
# Example use
catch NOTE ERR find /proc -ls
}

См. вторую последнюю строку для примера (прокрутка вниз)