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.
Пов'язане читання: Дескриптори файлів та сценарії оболонки ; Коли ви використовуєте додатковий дескриптор файлу?