Подтвердить что ты не робот

Bash, в то время как прерывание чтения прерывается

Я стучал головой о стену какое-то время с этим.

Я хочу, чтобы SSH в набор машин и проверить, доступны ли они (прием соединений и не используется). Я создал небольшой script, tssh, который делает именно это:

#!/bin/bash

host=$1
timeout=${2:-1}

ssh -qo "ConnectTimeout $timeout" $host "[ \`who | cut -f1 | wc -l \` -eq 0 ] && exit 0 || exit 1"

Этот script работает правильно. Возврат 255, если возникла проблема с подключением, 1, если машина занята, и 0, если все хорошо. Если кто-то знает лучший способ сделать это, пожалуйста, дайте мне знать.

Итак, я попробую позвонить tssh на свой набор машин, используя цикл чтения while, и здесь все идет не так. Цикл завершается, как только tssh возвращает 0 и никогда не завершает полный набор.

while read nu ; do tssh "MYBOXES$nu" ; done < <(ruby -e '(0..20).each { |i| puts i }')

Сначала я подумал, что это проблема подоболочки, но, видимо, нет. Любая помощь, наряду с комментариями по стилю/контенту, была бы высоко оценена! Я знаю, что собираюсь ударить себя, когда узнаю, почему...

4b9b3361

Ответ 1

Не знаю, поможет ли это, но более чистый способ записи -

for nu in `ruby -e '(0..20).each { |i| puts i}'`; do
  tssh "MYBOXES$nu" 
done

Ответ 2

Крис прав. Источником взлома цикла был SSH с использованием stdin, однако правильные пушки в использовании метода циклирования.

Если вы зацикливаете входные данные (например, файл со списком имен хостов) и вызываете SSH, вам необходимо передать параметр -n, иначе ваш цикл на основе ввода не будет выполнен.

while read host; do
  ssh -n $host "remote command" >> output.txt
done << host_list_file.txt

Ответ 3

В конструкции

something | 
while read x; do 
    ssh ...
done

стандартный ввод, как видно в цикле while, представляет собой вывод something.

Поведение ssh по умолчанию - это чтение стандартного ввода. Это позволяет делать такие вещи, как

cat id_rsa.pub | ssh new_box "cat - >> ~/.ssh/authorized_keys"

Теперь, когда будет сказано, когда первое значение будет считано, первая команда ssh будет считывать весь ввод из something. Затем, к тому времени, когда закончится ssh, выход отсутствует, а read остановится.

Исправление составляет ssh -n ... например.

cat /etc/hosts | awk '{print $2}' | while read x; do
    ssh -n $x "do_something_on_the_machine"
done

Ответ 4

Я столкнулся с этим сегодня - rsh и/или ssh могут сломать цикл чтения из-за него, используя stdin. Я помещаю -n в строку ssh, которая останавливает его от попытки использовать stdin, и он исправил проблему.

Ответ 5

Я также не уверен, почему он терпит неудачу, но мне нравится xargs и seq:

seq 0 20 | xargs -n1 tssh MYBOXES

Ответ 6

Как упоминал Кайи, это действительно излишний вызов ruby ​​или seq (который не будет работать на BSD или OSX-машинах) только для вывода диапазона чисел. Если вы довольны использованием bash, вы можете:

for i in {0..20}; do
    # command
done

Я считаю, что это должно работать для bash 2.05b и выше.

Ответ 7

Я не могу поверить, что это результат 0, который нарушил ваш цикл, вы можете протестировать его, заменив команду tssh в цикле "/bin/true", которая также возвращает 0.

В отношении стиля я не понимаю, почему простая оболочечная оболочка script нуждается в рубине, perl, seq или jot или любом другом двоичном файле, который не находится на моем BSD.

вы также можете использовать встроенные оболочки для контурной конструкции, которая работает как минимум в ksh, bash:

for ((i=0; $i<=20; i++)); do
    tssh "MYBOXES$i"
done

Ответ 8

поговорите о "ограблении Питера, чтобы заплатить Павлу". Я много часов боролся, чтобы понять, почему мой ssh ​​убил мое что-то в цикле чтения.

Еще один способ придерживаться цикла чтения и сохранить ваш ssh в то же время - использовать переключатель "-n", чтобы сделать STDIN на ssh/dev/null. Работает как прелесть для меня:

#!/bin/bash
[...]
something|while read host
   do
      ssh -nx ${host} fiddleAround
   done

(Я всегда использую "-x", чтобы не тратить время на переговоры X в туннеле.)

Ответ 9

Большинство ответов относятся к ssh. Другие команды также захватывают stdin и не имеют опции -n. Это должно касаться любых других команд. Это также должно работать для ssh.

while read x; do 
    # Make sure command does not hijack stdin
    echo "" | command $x
done < /path/to/some/file