2013-07-29 27 views
9

我用期待我的服务器上启动应用程序:背景衍生的过程中期待

!/usr/bin/expect 

set timeout -1 

spawn "bin/start-all.sh" 
expect { 
    -re "Found MongoDB in" { send "y\r"; exp_continue } 
    -re "Found Hadoop in" { send "y\r"; exp_continue } 
    -re "Going to start Hadoop" { interact } 
} 

我可以在脚本运行时我的服务器上访问在几秒钟内的应用,但只要它结束应用程序变得不可用。

我已经运行预计在调试模式,得到下面的输出接近尾声:

expect: does "vendors area. Do you want to start it? [y/n] y\r\n" (spawn_id exp6) match regular expression "Found MongoDB in"? Gate "Found MongoDB in"? gate=no 
"Found Hadoop in "? Gate "Found Hadoop in "? gate=no 
"Going to start Hadoop"? Gate "Going to start Hadoop"? gate=no 
Going to start Hadoop... 

expect: does "vendors area. Do you want to start it? [y/n] y\r\nGoing to start Hadoop...\r\n" (spawn_id exp6) match regular expression "Found MongoDB in"? Gate "Found MongoDB in"? gate=no 
"Found Hadoop in "? Gate "Found Hadoop in "? gate=no 
"Going to start Hadoop"? Gate "Going to start Hadoop"? gate=yes re=yes 
expect: set expect_out(0,string) "Going to start Hadoop" 
expect: set expect_out(spawn_id) "exp6" 
expect: set expect_out(buffer) "vendors area. Do you want to start it? [y/n] y\r\nGoing to start Hadoop" 
tty_raw_noecho: was raw = 0 echo = 1 
interact: received eof from spawn_id exp6 
tty_set: raw = 0, echo = 1 
tty_set: raw = 5, echo = 0 

我已经尝试使用exit 0interactexp_continuedisconnectsleep 10最后的模式下,以及期待eof,但似乎没有任何工作。我也尝试过运行expect start-all.exp &,但那也行不通。

当我手动运行bin/start-all.sh时,脚本启动必要的过程,然后退出。但是,预计这些进程似乎会被杀死。我将如何解决这个问题?

+0

有很多的细节,但目前尚不清楚你想要实现什么。 –

+1

这是一个很长的镜头,但你有没有在最后尝试'期待eof'? –

+0

恐怕我不熟悉这个start-all.sh脚本。在Expect的PTY中运行时,它可能会做一些奇怪的事情,导致它过早终止。 – user108471

回答

0

我发现在几乎所有情况下,程序在Expect中运行奇怪的一件事是在屏幕实例中产生一个shell并从那里运行程序。

spawn screen bash 
send "bin/start-all.sh\r" 

试着这样做,看看它是否能解决您的早熟问题。

+0

使用此解决方案,您可能会多次执行expect脚本之后运行大量屏幕会话。 – Bogdan

+0

@Bogdan不一定。根据原始问题,当手动运行脚本时,它会在脚本结束时愉快退出而不会终止已启动的子进程。如果在屏幕会话中运行相同的脚本就像手动运行脚本一样,那么最终应该能够终止屏幕会话而不杀死这些进程。那些屏幕会话不需要长时间运行。 – user108471

5

我有同样的问题,并想通了。

expect退出时,它发送SIGHUP(挂断信号)到衍生的子过程。默认情况下,此SIGHUP导致产生的进程终止。

如果您希望底层进程不会从SIGHUP死掉,您有两个简单的选项。这两个工作做好:

1)请expect,使底层程序忽略SIGHUPspawn一行:

#!/usr/bin/expect -f 
... 
spawn -ignore HUP command args... 
... 
expect_background 

2)做自己 - 在底层过程本身忽略SIGHUP

这里的工作脚本演示方法2:

#!/usr/bin/expect -f 
# 
# start a process and background it after it reaches a certain stage 
# 
spawn perl -e "\$SIG{HUP} = 'IGNORE'; for (\$a='A';; \$a++) {print qq/value is \$a\\n/; sleep 1;}" 

set timeout 600 

# Detailed log so we can debug (uncomment to enable) 
# exp_internal -f /tmp/expect.log 0 

# wait till the subprocess gets to "G" 
expect -ex "value is G" 

send_user "\n>>> expect: got G\n" 

# when we get to G, background the process 
expect_background 

send_user ">>> spawned process backgrounding successful\n" 
exit 0 

这里有一个跑步ning示例:

$ ./expect-bg 
spawn perl -e $SIG{HUP} = 'IGNORE'; for ($a='A';; $a++) {print qq/value is $a\n/; sleep 1;} 
value is A 
value is B 
value is C 
value is D 
value is E 
value is F 
value is G 

>>> expect: got G 
>>> spawned process backgrounding successful 

正如ps输出中所预期的那样,perl进程是后台运行并存活的。

USER  PID %CPU %MEM VSZ RSS TTY  STAT START TIME COMMAND 
hankm  6700 0.0 0.0 17696 2984 ?  Ss 18:49 0:00 perl -e $SIG{HUP} = 'IGNORE'; for ($a='A';; $a++) {print qq/value is $a\n/; sleep 1;} 
+0

完美,谢谢你提到这个! –