Background spawned process in Expect
background-process, expect, shell, tcl, unix
Solution
I had the same problem and figured this out.
When `expect` exits, it sends a `SIGHUP` (hangup signal) to the spawned subprocess. By default, this `SIGHUP` causes termination of the spawned process.
If you want the underlying process not to die from `SIGHUP` you have two easy options. Both work well:
1) Ask `expect` to make the underlying process ignore `SIGHUP` in the `spawn` line like this:
#!/usr/bin/expect -f
...
spawn -ignore HUP command args...
...
expect_background
2) Do it yourself - ignore `SIGHUP` in the underlying process itself:
Here's working script demonstrating method 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
Here's a running example:
$ ./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
And as expected in ps output, the perl process is backgrounded and alive.
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;}
Problem
I'm using expect to start an application on my server: ``` #!/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 } } ``` I can access the application on my server in the few seconds while the script is running, but as soon as it ends the application becomes unavailable. I've run expect in debug mode and get the following output towards the end: ``` 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 ``` I've tried using `exit 0`, `interact`, `exp_continue`, `disconnect`, `sleep 10` under the last pattern, as well as expecting `eof` but nothing seems to be working. I've also tried running `expect start-all.exp &` but that doesn't work either. When I run bin/start-all.sh manually, the script starts the necessary processes and then exits. However with expect those processes seem to get killed. How would I fix this issue?