#bash #expect #send
#bash #ожидать #Отправить
Вопрос:
У меня есть список из 400 серверов, и мне нравится проверять существование учетной записи unix с помощью expect to loop
Я написал скрипт bash, который использует команду expect, но он возвращает мне сообщение об ошибке, значение которого я не понимаю
#!/bin/bash
fic_serv="test.txt"
echo "Passwd"
stty -echo
read -s passwd
stty echo
suffix="suffix"
account="acc"
for server in `cat $fic_serv`
do
prompt="[$acc@$server ~]$ "
expect -c "
spawn ssh -o StrictHostKeyChecking=no $account@$server.$suffix
expect "Password: "
send "$passwdr"
expect $prompt
send "logoutr"
"
done
[acc@serv ~]$ couldn't read file "
send "passwdr"
expect [acc@server ~]$
send "logoutr"
": no such file or directory
(Я изменил значение)
Комментарии:
1. Я обновил свой ответ; пожалуйста, дайте мне знать, если у вас по-прежнему будут проблемы.
2. На другом примечании: я думаю, что это опечатка :
prompt="[$acc@$server ~]$ "
. Вы либо имелиprompt="[acc@$server ~]$ "
в виду, либоprompt="[$account@$server ~]$ "
Ответ №1:
Вы должны использовать while
, not for
, для анализа файлов в Bash. Используйте «перенаправление» для обработки файла как стандартного ввода и чтения по одной строке за раз.
while read server; do
...
done < $fic_serv
Ваша основная проблема в том, что Expect интерпретирует ваш "
s как «конец сценария». Экранируйте их, как в "
, или используйте {}
, как в:
expect -c "
spawn ssh -o StrictHostKeyChecking=no $account@$server.$suffix
expect {Password: }
send {$passwdr}
expect $prompt
send {logoutr}
"
Комментарии:
1. Но одинарная кавычка
'
не имеет смысла ожидать. Эквивалентом является{ }
, например, использованиеexpect {Password: }
2. Здравствуйте, я исправил это, и теперь это работает, но все еще есть проблема: похоже, он не отправляет пароль, потому что соединение не установлено…. Он переходит непосредственно к следующему ssh, не отображая ничего об этой проблеме?
3. Используйте флаг
-d
iagnostic для точной отладки происходящего.4. ожидаемый: соответствует ли «» (spawn_id exp7) глобальному шаблону «[acc @server ~] $ «? нет, кажется, что переменная prompt не передается через expect…
Ответ №2:
Если вам нужно управлять 400 серверами, я настоятельно рекомендую вам использовать ansible
.
Вы могли бы просто поместить список хостов в файл, давайте вызовем его inventory
и выполним следующую команду:
ansible -i inventory -m shell -a "id acc" all
Ответ №3:
Использование here-docs в оболочке для встраивания кода для другого языка обычно лучше, чем цитирование ада, а совместное использование переменных через среду проще и безопаснее, чем расширение параметров:
export account passwd
while IFS= read -r server; do
export prompt="[$acc@$server ~]$ "
export host="$server.$suffix"
expect << 'END_EXPECT'
spawn ssh -o StrictHostKeyChecking=no $env(account)@$env(host)
expect "Password: "
send "$env(passwd)r"
expect $env(prompt)
send "logoutr"
expect eof
END_EXPECT
done < "$fic_serv"
Как показано, мне нравится делать отступы в heredoc, чтобы сделать его более очевидным.
И в зависимости от сообщения об ошибке или запроса на вход в систему может быть больше логики, указывающей, что имя учетной записи и / или пароль неверны.
Комментарии:
1. Похоже, возникла проблема: ожидайте: для опции требуется аргумент — ‘c’ использование: ожидайте [-div] [-c cmds] [[-f] cmdfile] [аргументы] ожидайте: для опции требуется аргумент — ‘c’ использование: ожидайте [-div] [-c cmds][[-f] cmdfile] [аргументы] ожидать: для параметра требуется аргумент — ‘c’ использование: ожидать [-div] [-c cmds] [[-f] cmdfile] [аргументы]
2. Я все время забываю об этом: при чтении команд из stdin не используйте -c
3. Я не знаком с heredoc, но это работает!! Спасибо
4. Это конструкция оболочки. Это особая форма перенаправления ввода: вы в основном перенаправляете из файла, за исключением того, что содержимое файла находится внутри скрипта. См. gnu.org/software/bash/manual/bash.html#Here-Documents