Jak właściwie używać 'expect'?

0

Cześć.
Wykonałem sobie skrypt w shellu, który potrzebuje kilku logowań na inne serwery. Chciałbym dlatego skorzystać z narzędzia "expect", by móc podać hasło tylko 1 raz, a potem nieinteraktywnie podawać je przez pomocy "expect" podczas logowania przez ssh / uaktualnienia svn, itp.

Oto wynik działania "autoexpect":
`#!/usr/bin/expect -f
#

  1. This Expect script was generated by autoexpect on Fri Jul 1 08:20:06 2016
  2. Expect and autoexpect were both written by Don Libes, NIST.
    #
  3. ...

set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}

set timeout -1
spawn $env(SHELL)
match_max 100000
expect -exact "srvc15:/home/usr/scripts/Tools/da \$ "
send -- "ssh -q [email protected]"
expect -exact "ssh -q [email protected]"
send -- "\r"
expect -exact "\r
[email protected]'s password: "
send -- ".my.pass.\r"
expect -exact "\r
Last login: Fri Jul 1 08:19:21 2016 from srvc15\r
\r
\r
\r
Hostname: srvc16\r
Operating system: Linux-RedHat-RHEL-5\r
Additional infos: \r
***\r
\r
[r[999;999H[6n"
send -- "[40;119R"
srvc16:/home/i7c9fy3 \$ "
send -- "exit\r"
expect -exact "exit\r
logout\r
[H[2Jsrvc15:/home/usr/scripts/Tools/da \$ "
send -- ""
expect -exact "Use \"exit\" to leave the shell.\r
srvc15:/home/usr/scripts/Tools/da \$ "
send -- ""
expect eof`

Wiecie może, co to za dziwne "kody": [r[999;999H[6n?
Wiecie też może, po co wysyłany jest poniższy ciąg?
send -- "[40;119R"

Mój skrypt 'expect' wygląda tak:

#!/usr/bin/expect -f
set user [lrange $argv 0 0]
set server [lrange $argv 1 1]
set ssap [lrange $argv 2 2]
set timeout 3
spawn ssh -q -o NumberOfPasswordPrompts=1 [email protected]$server
expect {
    timeout { send_user "\nSSH timeout\n"; exit 1 }
    eof { send_user "\nSSH eof\n"; exit 2 }
    -re "\(yes/no\)" {  send -- "yes\r" }
    "assword:" {    send -- "$ssap\r"   }
}
#send -- "R"
expect {
    timeout { send_user "\nLogin failed. Password incorrect.\n"; exit 3 }
    eof { send_user "\nPassword eof\n"; exit 4 }
    -re "999H" {
        send_user " --- expect_out = $expect_out(0,string) --- "
        send_user "\nFound 999H => sending /r...\n"
        sleep 1
        send_user "1s sleeped\n"
        send -- ";96R"
        exp_continue
    }
    -re "/home/.*\$"    { send_user "\nIs DOLLAR = prompt\n"    }
}
send_user " - - expect_out = $expect_out(0,string) - - "
send_user "\n#yoU arE loggeD iN#\n"
send "exit 77\r"
#expect eof
close $spawn_id

Po wywołaniu login.exp i7c9fy3 srvc16 .my.pass. jest takie coś:

srvc16:/home/usr/scripts/Tools/da $ ./login.exp i7c9fy3 srvc16 .my.pass.
spawn ssh -q -o NumberOfPasswordPrompts=1 [email protected]
[email protected]'s password:
Last login: Fri Jul  1 08:20:33 2016 from srvc15

Hostname:             srvc16
Operating system:     Linux-RedHat-RHEL-5
Additional infos:
*******************************************************************************

--- expect_out = 999H ---
Found 999H => sending /r...
^[[40;119R1s sleeped
srvc16:/home/i7c9fy3 $
Is DOLLAR = prompt
 - - expect_out = :/home/i7c9fy3 $  - -
#yoU arE loggeD iN#
srvc15:/home/usr/scripts/Tools/da $ ;119R

Przed pojawieniem się 1s sleeped srvc16:/home/i7c9fy3 $ jest sek. przerwy (oczywiście). Dlaczego jednak po zalogowaniu pojawia się dodatkowo ;119R?
Bardzo proszę o pomoc.

0

Dzięki, alagner!
Zdaje się, iż to ;119R chyba w niczym nie przeszkadza.

Mam jednak kolejny problem. Po zalogowaniu się chciałbym coś uruchomić, ale nie bardzo wiem, jak. Teraz mam (część skryptu, o którym wspominałem na początku):

    echo -e "\nCollecting data..."
    for node in ${nodes[@]}; do
        echo -e -n "  "$tc_brown"${node}"$tc_normal"    "
        $dapath/login.exp i7c9fy3 $node $pass <<-EoSSH
        sudo /usr/local/bin/adm <<-EoSUDO
        echo "....... TEST ........."
        if [[ "$node" == "$thisnode" ]]; then
            . $dapath/da_multipath_l.sh $datmp
            ls -1 /dev/mapper/mpath*  > $datmp/mpath.list 2>/dev/null
            ls -l /dev/mapper/asm_s1* > $datmp/da_asm_s1.list__${node} 2>/dev/null
            ls -l /dev/mapper/asm_s2* > $datmp/da_asm_s2.list__${node} 2>/dev/null
            /sbin/multipath -ll > $datmp/multipath_to_pl.out 2>&1
        else
            if [ ! -d $datmp ]; then
                mkdir $datmp
            fi
            chmod 777 $datmp
            . $dapath/da_multipath_l.sh $datmp
            ls -1 /dev/mapper/mpath*  > $datmp/mpath.list__${node} 2>/dev/null
            ls -l /dev/mapper/asm_s1* > $datmp/da_asm_s1.list__${node} 2>/dev/null
            ls -l /dev/mapper/asm_s2* > $datmp/da_asm_s2.list__${node} 2>/dev/null
        fi
        exit
        EoSUDO
        exit
        EoSSH
        echo -e "  "$tc_green_b"["$tc_green"done"$tc_green_b"]"$tc_normal
    done

Niestety po zalogowaniu się kod pomiędzy "EoSSH" nie jest przekazywany do zdalnego serwera. Jak powinienem to właściwie uruchomić/przekazać?

0

Wybacz poślizg, ale wróciłem z roboty wczoraj totalnie zdechły ;)

Ad rem:
Ja bym to zrobił pi razy oko tak:

#!/usr/bin/expect -f

set user [lrange $argv 0 0]
set server [lrange $argv 1 1]
set ssap [lrange $argv 2 2]
set cmd [lrange $argv 3 3]
set timeout 7
spawn ssh -q -o NumberOfPasswordPrompts=1 "[email protected]$server"

expect {
    "(yes/no)?" { send "yes\r" ; send_user "added to hosts table\r" ; exp_continue  }
    -re "assword for.*" {    send -- "$ssap\r"    }
    timeout { send_user "\rSSH timeout\r"; exit 1 }
    eof { send_user "\rSSH eof\r"; exit 2 }
}

expect {
    "Last login" { send_user "Logged ok\r"} 
    timeout {exit 5}
}

expect {
    -re "\\\$ $" {send "[join $cmd " "]\r"}
}

expect {
    -re "\\\$ $" {puts "got prompt, exiting\r" ; send "exit\r"}
    timeout { puts "tmo expired\r"}
}
close $spawn_id

Problemem może być escape'owanie pewnych znaków, tym niemniej jest to pewna baza do dalszych działań.

Odpalasz to np. tak:

./test.exp alagner 192.168.0.4 tajnehaslo '\
for el in $(seq 1 3); do \                      
touch "$el"_test;\
done; \           
ls -al | grep test'
0
alagner napisał(a):

Wybacz poślizg, ale wróciłem z roboty wczoraj totalnie zdechły ;)
Nic nie szkodzi. I tak nie miałem dostępu do kompa do wczoraj.

alagner napisał(a):
expect {
-re "\\\$ $" {send "[join $cmd " "]\r"}
}

Do czego potrzebne są te nawiasy kwadratowe w "send"?

0

Robią z listy stringa. Tzn. nawiasy kwadratowe w TCL (bo Expect jest podzbiorem TCLa) robią tyle co $() albo ` `` w bashu: wstawiają w danym miejscu wyjście polecenia.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0