Выполните команду на удаленных хостах через ssh из скрипта bash - PullRequest
5 голосов
/ 04 декабря 2011

Я написал скрипт bash, который должен считывать имена пользователей и IP-адреса из файла и выполнять команду для них через ssh.

Это hosts.txt:

user1 192.168.56.232
user2 192.168.56.233

Это myScript.sh:

cmd="ls -l"

while read line
do
   set $line
   echo "HOST:" $1@$2
   ssh $1@$2 $cmd
   exitStatus=$?
   echo "Exit Status: " $exitStatus
done < hosts.txt

Проблема заключается в том, что выполнение останавливается после завершения работы первого хоста.,Это вывод:

$ ./myScript.sh
HOST: user1@192.168.56.232
total 2748
drwxr-xr-x 2 user1 user1    4096 2011-11-15 20:01 Desktop
drwxr-xr-x 2 user1 user1    4096 2011-11-10 20:37 Documents
...
drwxr-xr-x 2 user1 user1    4096 2011-11-10 20:37 Videos
Exit Status:  0
$

Почему он ведет себя так, и как я могу это исправить?

Ответы [ 4 ]

8 голосов
/ 04 декабря 2011

В вашем сценарии задание ssh получает тот же стандартный ввод, что и read line, и в вашем случае происходит сожжение всех строк при первом вызове.Таким образом, read line может видеть только первую строку ввода.

Решение: закройте стандартный ввод для ssh или лучше перенаправьте с /dev/null.(Некоторым программам не нравится закрытие стандартного ввода)

while read line
do
    ssh server somecommand </dev/null    # Redirect stdin from /dev/null
                                         # for ssh command
                                         # (Does not affect the other commands)
    printf '%s\n' "$line"
done < hosts.txt

Если вы не хотите перенаправлять из / dev / null для каждой отдельной работы в цикле, вы также можете попробовать выполнить одно из следующих действий:

while read line
do
  {
    commands...
  } </dev/null                           # Redirect stdin from /dev/null for all
                                         # commands inside the braces
done < hosts.txt


# In the following, let's not override the original stdin. Open hosts.txt on fd3
# instead

while read line <&3   # execute read command with fd0 (stdin) backed up from fd3
do
    commands...       # inside, you still have the original stdin
                      # (maybe the terminal) from outside, which can be practical.

done 3< hosts.txt     # make hosts.txt available as fd3 for all commands in the
                      # loop (so fd0 (stdin) will be unaffected)


# totally safe way: close fd3 for all inner commands at once

while read line <&3
do
  {
    commands...
  } 3<&-
done 3< hosts.txt
4 голосов
/ 04 декабря 2011

Проблема, с которой вы столкнулись, заключается в том, что процесс SSH потребляет весь стандартный ввод, поэтому read не видит ничего из ввода после выполнения первой команды ssh.Вы можете использовать флаг -n для SSH, чтобы предотвратить это, или вы можете перенаправить / dev / null на стандартный ввод команды ssh.

Для получения дополнительной информации см. Следующее: http://mywiki.wooledge.org/BashFAQ/089

3 голосов
/ 04 декабря 2011

Убедитесь, что команда ssh не читает из файла hosts.txt, используя ssh -n

1 голос
/ 04 декабря 2011

У меня ощущение, что ваш вопрос излишне многословен ..

По сути, вы должны быть в состоянии воспроизвести проблему с:

while read line
do
   echo $line
done < hosts.txt

, которая должна работать очень хорошо .. Вы редактируетеправильный файл?Есть ли в нем специальные символы?Проверьте это с помощью правильного редактора (например, vim).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...