Мне наконец удалось свести проблему, с которой я боролся в течение нескольких недель. Я использую SSH с «авторизованными ключами» для удаленного запуска команд. Все хорошо, кроме случаев, когда я делаю это в цикле. Цикл завершается после завершения любой итерации с помощью команды ssh.
Долгое время я думал, что это что-то странное, но теперь я обнаружил, что bash на самом деле ведет себя одинаково.
Небольшой пример программы для воспроизведения проблемы. Это извлечено из более крупной реализации, которая делает снимки и реплицирует их среди узлов в кластере.
#!/bin/bash
set -x
IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool
ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG " > /tmp/actionlist
#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
echo ${RMT_FILESYSTEM}@${MARKER}
[ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
echo Remote Command Return Code: $?
done
(Обратите внимание, что в выражении поиска grep есть символ TAB согласно определению поведения опции -H списка zfs.)
В моем примере есть несколько файловых систем ZFS для корня, где все «зоны» имеют свою корневую файловую систему в наборе данных с именем, аналогичным
БАССЕЙН / зоны / app1zone
БАССЕЙН / зоны / group2 / app2zone
и т.п.
Приведенный выше цикл должен создать моментальный снимок для каждого из выбранных наборов данных, но вместо этого он работает только для первого и затем завершается.
То, что программа находит нужное количество наборов данных, можно легко проверить, проверив файл «/ tmp / actionlist» после того, как скрипт существует.
Если команда ssh заменяется, например, командой echo, то цикл повторяется по всем входным строкам. Или мой любимый - добавь «эхо» к обидной команде.
Если я использую цикл for вместо него, он также работает, но из-за потенциального размера списка наборов данных это может вызвать проблемы с максимальной длиной расширенной командной строки.
Теперь я на 99,999% уверен, что только те циклы, в которых есть команды ssh, доставляют мне проблемы!
Обратите внимание, что итерация, в которой выполняется команда ssh, завершена! Это как если бы данные, переданные в цикл while, внезапно терялись ... Если первые несколько входных строк не выполняют команду ssh, то цикл продолжается до тех пор, пока он фактически не выполнит команду SSH.
На моем ноутбуке, где я тестирую это, у меня есть две виртуальные машины Solaris 10 только с двумя или тремя образцами наборов данных, но то же самое происходит в больших системах SPARC, где это должно быть запущено, и есть много наборов данных.
actionlist
. Попробуйте перенаправить стандартный ввод ssh на/dev/null
Ответы:
SSH может читать из стандартного ввода, съедая ваш список действий. Попробуйте перенаправить стандартный ввод ssh в / dev / null:
Как правило, при запуске команд, которые могут мешать стандартному вводу в
while read
цикле -style, мне нравится заключать все тело цикла в фигурные скобки:источник
( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )
отличается от фигурных скобок. Я имею в виду полученный результат, а не тот факт, что закрывающая фигурная скобка должна быть на новой строке ...-n
опция, которая заставляет его (эффективно) заново открывать свой стандартный ввод из / dev / null.sudo
с командой внутри цикла?