У вас есть два способа получить статус возврата процесса ssh
с использованием стандартных функций оболочки: либо запустить его синхронно, либо вызвать встроенную функцию wait
. Когда вы запускаете
(ssh $userAtServer "ls $targetDir/$targetFile" > $sshOutputFile ; lsReturnValue=$?) &
, это устанавливает только lsReturnValue
в подоболочке, и вы не можете получить никакой информации, кроме статуса возврата, обратно в родительскую оболочку. Таким образом, вам придется запустить exit $ lsReturnValue
из подоболочки и получить статус возврата подоболочки из родительской оболочки; а затем весь фоновый процесс можно упростить до ssh $ userAtServer "ls $ targetDir / $ targetFile"> $ sshOutputFile &
в любом случае.
Этот фрагмент оболочки, разрешающий команде тайм-аут, не очень хороший, потому что он не сохраняет статус возврата. В Linux используйте утилиту timeout
.
Без утилиты timeout
это становится немного сложнее. Вам нужно запустить два подпроцесса: тот, который вас интересует, и тот, который запускает sleep
для части тайм-аута. Если один из процессов возвращается, он должен убить другой и позволить оболочке продолжить работу. К сожалению, встроенная функция wait
ожидает завершения работы всех подпроцессов, если вы вызываете ее без аргументов. Один из способов синхронизировать два процесса - заставить их записывать в канал и уничтожать их, как только в канале появляются некоторые данные.
lsReturnValue=$(
{
{ ssh $userAtServer "ls $targetDir/$targetFile" > $sshOutputFile
echo $?; } &
{ sleep 5; echo timeout; } &
} | head -n 1)
if [ "$lsReturnValue" = "timeout" ]; then …
Если вы отправляете команды на несколько серверов, серьезно подумайте об использовании многосерверной структуры ssh , такой как mussh, clusterssh и т. Д.
Because you're piping into the while loop, a sub shell is created to run the while loop. Now this child process has it's own copy of the environment and can't pass any variables back to its parent (as in any unix process).
В этом случае перенаправление done < "$tmpFile"
вынуждает bash генерировать подчиненную -оболочку (как для канала ).
Цитата из область видимости переменных bash в Stack Overflow.
Во втором примере используется цикл while
с перенаправленным вводом.
Он читается как < "$tmpFile"
, и многие оболочки создают для этого случая дополнительную оболочку -. Вы можете попробовать запустить этот скрипт с помощью ksh93
. ksh93
не создает вложенную оболочку -в этом случае.
В вашем конкретном случае причина совсем в другом:
в первом примере вы читаете одну строку из ввода
во втором примере вы читаете до EOF
Команда read
считывает ввод, затем разбивает ввод на IFS
символов, а затем присваивает слова переменным аргументам read
.
Если слов в качестве параметров команды read
больше, чем переменных, последняя переменная получает конкатенацию остальных слов.
Если слов меньше, чем переменных, другим переменным присваивается пустое значение.
Поскольку вы нажали EOF
, у вас не было считанного слова, кроме одной или нескольких переменных в качестве аргумента для read
. Это приводит к тому, что всем переменным присваивается пустое значение.
Итак, произошло нечто, чего вы не ожидали.:EOF
приводит к завершению цикла while
, и вы не видите команды echo
внутри цикла while
, а только последнюю команду echo
после while
. ] в этом случае EOF
.
Этот окончательный вариант echo
теперь печатает содержимое переменной, которое было очищено от нажатия EOF
.