ожидать ssh без пароля

у меня есть файл с IP-адресами, расположением файлов и паролями. Я не могу использовать аутентификацию по ключу ssh, поэтому я ограничен использованием expect внутри скрипта bash. файл содержит следующую информацию, разделенную пробелами:

ip пароль местоположения

ip пароль местоположения

так далее

мой сценарий:

 VAR=$(expect -c "
        set fid [open "file.conf" w]
        set content [read $fid]
        close $fid
        set records [split $content "\n"]
        foreach rec $records {
        set fields [split $rec]
        lassign $fields\ ip location password
        puts "$ip"
        puts "$location"
        puts "$password"}
        spawn ssh $ip tail -f $location > /home/log_$ip 2>/dev/null &
        expect {
                ".*Are.*.*yes.*no.*" { send "yes\n" }
                "*?assword:*" { send "$password\r" }
           }
    ")

эхо "$VAR"

когда я запускаю скрипт, он выдает мне эту ошибку:

неверные # аргументы: должно быть "read channelId ?numChars?" или "read ?-nonewline? channelId" при выполнении "read", вызванного из "set content [read]"


person user2864207    schedule 24.10.2013    source источник
comment
может кто-нибудь, пожалуйста, помогите мне заставить tail -f работать в фоновом режиме   -  person user2864207    schedule 25.10.2013


Ответы (1)


Вам нужно заключить тело ожидания в одинарные кавычки, чтобы переменные ожидания не расширялись оболочкой до того, как ожидания начнут выполняться.

Кроме того, если вы нажмете на приглашение «есть... да... нет», вам нужно использовать exp_continue, чтобы вы могли продолжать ожидать запроса пароля.

НЕ ОТКРЫВАЙТЕ ФАЙЛ КОНФИГУРАЦИИ С БУКВОЙ "w" — вы уничтожите содержимое файла. Вы читаете из него, так откройте его для чтения

VAR=$(expect -c '
    set fid [open "file.conf" r]
    while {[gets $fid line] != -1} {
        lassign [split $line] ip location password
        puts "$ip"
        puts "$location"
        puts "$password"
        spawn ssh $ip tail -n 20 $location > /home/log_$ip 2>/dev/null &
        expect {
            -re "Are.*yes.*no" { send "yes\r"; exp_continue }
            -gl "*?assword:*" { send "$password\r" }
        }
    }
')

Я не уверен, что это сработает, когда вы перенаправите вывод порождения: я беспокоюсь, что ожидать, что не с чем будет работать. Если это не работает, удалите "> /home/log_$ip 2>/dev/null &" или используйте

spawn ssh $ip tail -n 20 $location 2>/dev/null | tee /home/log_$ip

Для фона вам, вероятно, придется сделать что-то вроде этого (не проверено)

expect -c '...' > /home/log_$ip 2>&1 &
expect_pid=$!

# ...

# later
wait $expect_pid
VAR=$(< /home/log_$ip)
do something with "$VAR"
person glenn jackman    schedule 24.10.2013
comment
это выглядит хорошо, на самом деле я использую tail -f и хочу, чтобы он работал в фоновом режиме, поэтому я добавил & к вашей строке spawn ssh $ip tail -f $location 2›/dev/null | tee /home/log_$ip, но он не работает. - person user2864207; 24.10.2013
comment
ваш ответ очень полезен, если бы я мог запустить команду в фоновом режиме. - person user2864207; 24.10.2013
comment
Вы можете запустить всю ожидаемую программу в фоновом режиме, но тогда $VAR ничего не захватит. - person glenn jackman; 24.10.2013
comment
мне нужен $VAR, потому что я запускаю сценарий bash. - person user2864207; 24.10.2013
comment
Если вы запустите его в фоновом режиме, вам придется перенаправить в файл, потому что вы не сможете зафиксировать вывод в переменной. Затем вам придется дождаться завершения фонового процесса, прежде чем вы сможете прочитать файл. - person glenn jackman; 25.10.2013
comment
Есть ли способ попросить пользователя ввести пароль один раз, а не брать пароль из файла? - person user2864207; 25.10.2013