for
Петля відмінно тут. Але зауважте, що це тому, що у файлі є назви машин, які не містять символів пробілу чи символів глобусу. for x in $(cat file); do …
не працює з переглядом рядків file
загалом, тому що оболонка спочатку розбиває вихід з команди cat file
де-небудь, де є пробіл, а потім розглядає кожне слово як глобульний візерунок, тому \[?*
далі розширюється. Ви можете зробити for x in $(cat file)
безпеку, якщо працюєте над цим:
set -f
IFS='
'
for x in $(cat file); do …
Пов'язане читання: Прокручування файлів із пробілами в іменах? ; Як я можу читати рядок за рядком зі змінної в bash? ; Чому while IFS= read
використовується так часто, а не IFS=; while read..
? Зауважте, що при використанні while read
безпечним синтаксисом для читання рядків є while IFS= read -r line; do …
.
Тепер перейдемо до того, що піде не так у вашій while read
спробі. Перенаправлення зі списку файлів серверів стосується всього циклу. Отже, коли він ssh
працює, його стандартний вхід надходить із цього файлу. Ssh-клієнт не може знати, коли віддалений додаток може прочитати зі свого стандартного входу. Отже, як тільки ssh-клієнт помітить деякий вхід, він надсилає цей вхід на віддалену сторону. Сервер ssh тоді готовий подати цей вхід у віддалену команду, якщо він цього хоче. У вашому випадку віддалена команда ніколи не читає жодного вводу, тому дані в кінцевому підсумку відкидаються, але сторона клієнта нічого про це не знає. Ваша спроба echo
спрацьовано, тому що echo
ніколи не читає жодного вводу, він залишає свій стандартний вхід сам.
Є кілька способів уникнути цього. Ви можете сказати ssh не читати зі стандартного вводу, з -n
опцією.
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
Фактично -n
опція говорить ssh
про переадресацію свого вводу з /dev/null
. Ви можете зробити це на рівні оболонки, і він буде працювати для будь-якої команди.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Спосіб заманливо входу у уникнути SSH пришестя з файлу поставити переадресацію на read
команді: while read server </home/kenny/list_of_servers.txt; do …
. Це не буде працювати, оскільки це призводить до того, що файл буде відкриватися знову щоразу, коли read
команда виконується (щоб він читав перший рядок файлу знову і знову). Перенаправлення повинно бути цілим циклом while, щоб файл відкривався один раз протягом тривалості циклу.
Загальне рішення полягає в наданні вводу в цикл дескриптора файлу, відмінного від стандартного вводу. Оболонка має конструкції для перевезення вводу і виведення з одного номера дескриптора на інший. Тут ми відкриваємо файл на дескрипторі файлу 3 і перенаправляємо read
стандартний вхід команди з дескриптора файлу 3. Клієнт ssh ігнорує відкриті нестандартні дескриптори, тому все добре.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
У bash read
команда має специфічну опцію для читання з іншого дескриптора файлу, тому ви можете писати read -u3 server
.
Пов'язане читання: Дескриптори файлів та сценарії оболонки ; Коли ви використовуєте додатковий дескриптор файлу?