Почему переменная global when set with `read variable` внутри цикла `while`, но local when set with `while read variable`?

У вас есть два способа получить статус возврата процесса 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 и т. Д.

0
21.08.2018, 16:50
2 ответа

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.

-2
28.01.2020, 02:23

Во втором примере используется цикл whileс перенаправленным вводом.

Он читается как < "$tmpFile", и многие оболочки создают для этого случая дополнительную оболочку -. Вы можете попробовать запустить этот скрипт с помощью ksh93. ksh93не создает вложенную оболочку -в этом случае.

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

  • в первом примере вы читаете одну строку из ввода

  • во втором примере вы читаете до EOF

Команда readсчитывает ввод, затем разбивает ввод на IFSсимволов, а затем присваивает слова переменным аргументам read.

Если слов в качестве параметров команды readбольше, чем переменных, последняя переменная получает конкатенацию остальных слов.

Если слов меньше, чем переменных, другим переменным присваивается пустое значение.

Поскольку вы нажали EOF, у вас не было считанного слова, кроме одной или нескольких переменных в качестве аргумента для read. Это приводит к тому, что всем переменным присваивается пустое значение.

Итак, произошло нечто, чего вы не ожидали.:EOFприводит к завершению цикла while, и вы не видите команды echoвнутри цикла while, а только последнюю команду echoпосле while. ] в этом случае EOF.

Этот окончательный вариант echoтеперь печатает содержимое переменной, которое было очищено от нажатия EOF.

-2
28.01.2020, 02:23

Теги

Похожие вопросы