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 0806 2016
  2. Expect and autoexpect were both written by Don Libes, NIST.

  1. ...

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 i7c9fy3@srvc16"
expect -exact "ssh -q i7c9fy3@srvc16"
send -- "\r"
expect -exact "\r
i7c9fy3@srvc16's password: "
send -- ".my.pass.\r"
expect -exact "\r
Last login: Fri Jul 1 0821 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 $user@$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 i7c9fy3@srvc16
i7c9fy3@srvc16'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 "$user@$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