[bash/expect] Expect geeft verkeerde waarde terug.

Pagina: 1
Acties:

  • mace
  • Registratie: Juni 2003
  • Laatst online: 25-01 14:46

mace

Sapere Aude

Topicstarter
Ik ben bezig met een script welke er voor moet zorgen dat ik via SSH commando's kan uitvoeren over meerdere hosts zonder dat ik heel vaak het wachtwoord moet invoeren.
Op het moment is ssh met shared keys niet mogelijk, en ik wil expect leren kennen dus ik wil het liever gewoon zo oplossen, het moet mogelijk zijn want mijn script werkt grotendeels goed.

Dit is de code:
Bash:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/sh

# initaliseer variabelen
username=root
password=''
hosts=$(seq 1 38) # van 1 tot 38

# Invoer van wachtwoord
clear
echo -n "Enter Password for $username: "
stty -echo
read password
stty echo
echo ""

# wandel door alle hosts heen
for host in $hosts; do
        host=linux-machine-$(printf %02d $host) # leading zero aan 1 t/m 9 plakken. 
        echo trying host $host
        expect_output=$(expect -c "
                set timeout -1
                spawn ssh root@$host
                match_max 100000
                expect  {
                        \"*yes\no*\" { send -- \"yes\r\" ; exp_continue }
                        \"*assword: \" { send -- \"$password\r\"; exp_continue }
                        \"~\]#\" { send -- \"hostname\r\" }
                        }
                exit

                " )
echo ""
echo $expect_output
done

# cleanup
username=
password=
host=
hosts=
expect_output=
exit 0

Zoals je ziet moet je een wachtwoord invoeren, deze is over alle machines gelijk, inloggen over ssh gaat goed en hostname wordt ook gewoon uitgevoerd, alleen de output van expect komt dus in de variabele $expect_output terecht, maar de output is dus niet de hostname van de machine maar de output van ssh, dus eigenlijk loopt de variabele één commando achter. Ik heb het idee dat ik in mijn expect scriptje nog iets extra moet uitvoeren maar ik weet niet wat.

Dit is de output:
Enter Password for root:
trying host linux-machine-01

 [root@linux-machine-01 ~]#1 14:31:39 2009 from xxx.xxx.xxx.xxx
trying host linux-machine-02

 [root@linux-machine-02 ~]#1 14:31:39 2009 from xxx.xxx.xxx.xxx
trying host linux-machine-03

 [root@linux-machine-03 ~]#1 14:31:39 2009 from xxx.xxx.xxx.xxx
trying host linux-machine-04

etc......


Dit is dus niet de uitvoer van hostname maar van ssh + de prompt :?, ik heb alleen geen flauw idee hoe ik dit moet oplossen, en ik heb me suf gegoogled maar ik kan niks vinden wat werkt.

Wat ik heb geprobeerd:

Aan het einde van mijn expect stukje dit soort dingen toevoegen:
-expecten op de hostname string en dan pas exit uitvoeren
-expect eof, hierop hangt hij.
-exp_continue achter het laatste expect statement zoals de bovenste 2.

-De timeout veranderen
-Sleep gebruiken.
-Nog een paar dingen die ik even vergeten ben. :$

Waar ik naartoe wil werken is dat er een aantal commando's uit een bestand geladen worden en dat die commando's op alle machines uitgevoerd worden, maar als ik de laatste output van de host niet kan uitlezen heeft dit niet zoveel zin.

OS is RHEL4

Het is vast iets stoms maar ik ben een expect-beginner dus bear with me please. :)

edit:

Debug output:

Enter Password for root:
trying host linux-machine-01
expect version 5.42.1
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {16212}

expect: does "" (spawn_id exp4) match glob pattern "*yes\no*"? no
"*assword: "? no
"~]#"? no

expect: does "root@linux-machine-01's password: " (spawn_id exp4) match glob pattern "*yes\no*"? no
"*assword: "? yes
expect: set expect_out(0,string) "root@linux-machine-01's password: "
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "root@linux-machine-01's password: "
send: sending "<root pass>\r" to { exp4 }
expect: continuing expect

expect: does "" (spawn_id exp4) match glob pattern "*yes\no*"? no
"*assword: "? no
"~]#"? no

expect: does "\r\n" (spawn_id exp4) match glob pattern "*yes\no*"? no
"*assword: "? no
"~]#"? no

expect: does "\r\nLast login: Wed Jul  1 15:03:28 2009 from xxx.xxx.xxx.xxx\r\r\n" (spawn_id exp4) match glob pattern "*yes\no*"? no
"*assword: "? no
"~]#"? no

expect: does "\r\nLast login: Wed Jul  1 15:03:28 2009 from xxx.xxx.xxx.xxx\r\r\n\u001b]0;root@linux-machine-01:~\u0007" (spawn_id exp4) match glob pattern "*yes\no*"? no
"*assword: "? no
"~]#"? no

expect: does "\r\nLast login: Wed Jul  1 15:03:28 2009 from xxx.xxx.xxx.xxx\r\r\n\u001b]0;root@linux-machine-01:~\u0007[root@linux-machine-01 ~]# " (spawn_id exp4) match glob pattern "*yes\no*"? no
"*assword: "? no
"~]#"? yes
expect: set expect_out(0,string) "~]#"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "\r\nLast login: Wed Jul  1 15:03:28 2009 from xxx.xxx.xxx.xxx\r\r\n\u001b]0;root@linux-machine-01:~\u0007[root@linux-machine-01 ~]#"
send: sending "hostname\r" to { exp4 }

 [root@linux-machine-01 ~]#1 15:03:28 2009 from xxx.xxx.xxx.xxx
trying host linux-machine-02


Zoals je ziet moet er nog een expect: "set expect_out(buffer)" bijkomen maar hoe doe ik dat?

[ Voor 25% gewijzigd door mace op 01-07-2009 15:30 ]


Verwijderd

ik heb in het verleden onderstaande gedaan.
misschien dat dit eenvoudiger werkt.

expect <<-EOF
spawn /usr/bin/ssh root@bladiebla
expect "Password: " { send "$ww\r" }
expect "# " { send "hostname\r" }
expect "# " { send "\r" }
EOF

  • mace
  • Registratie: Juni 2003
  • Laatst online: 25-01 14:46

mace

Sapere Aude

Topicstarter
Hmm, een heredoc, dat is ook een idee natuurlijk.