Tcl Expect脚本 - 分叉的子进程不会退出,必须从shell中杀死

时间:2013-09-04 18:07:26

标签: process tcl fork expect

我已经做了大量的搜索和试验,试图自己解决这个问题,但我还没有找到答案。

背景:

我正在使用Tcl版本8.4和Expect软件包扩展版本5.45编写脚本。我正在学习期待并发生在“背景处理”一章(第17章,探索期待)中。在页374-375中,它描述了“fork”命令。事实证明,这提供了我试图实现的功能。我需要运行脚本的第一部分,其中可能需要也可能不需要用户输入。从那时起,我希望终端将控制权返回给shell(就像脚本进程已被后台处理一样),同时脚本继续启动另一个工具并在退出之前等待它退出。然后,一旦完成,脚本过程就会正常死亡。

问题:

使用expect的fork命令时,一切似乎都在乍一看。我得到了父进程和子进程。父进程按指示退出,终端返回到shell控件。子进程继续启动它本应该使用的工具。问题是一旦该工具退出,子进程也应退出,但事实并非如此。该过程保持“S”或睡眠状态。仅供参考,我最初使用期望命令“断开”给孩子,但我意识到我实际上并不希望孩子完全断开连接。在我的实验中,断开连接似乎对退出后儿童过程是否仍然没有任何影响。

实验:

我试着把它归结为绝对的基础知识。所以这不是我的脚本,而是一个表现出相同行为的简化测试用例。我不得不遗漏一些东西。这不是正常的行为。我需要帮助弄清楚我做错了什么导致了这种行为。

简化的脚本:

puts "Tcl version   : [info tclversion]"
puts "Expect version: [exp_version]"


while {1} {
   # If forking fails, retry every 10 seconds until it succeeds.
   if {[catch fork child_pid] == 0} {
      break
   }
   sleep 10
}

sleep 10

# Kills the parent process to return terminal control to shell
if {$child_pid != 0} {
   puts "[pid] Parent process exiting..."
   exit
}

# Redefine exit procedure for child so it kills the process for sure on exit
# I have no idea why exit doesn't work for a child process, but this seems to ensure it goes away on exit.
#exit -onexit {
#   puts "[pid] Killing PID..."
#   exec kill [pid]
#}

puts "[pid] Child process sleeping for 10 seconds..."
sleep 10

puts "[pid] Child process waking up and exiting..."
exit

运行输出:

:> expect temp_fork
Tcl version   : 8.5
Expect version: 5.45
31483 Child process sleeping for 10 seconds...
31472 Parent process exiting...

:> 31483 Child process waking up and exiting...

在另一个shell中,我运行了ps来帮助显示3点进程的进展情况。首先是在10秒睡眠期间,父母和孩子的过程都是活着的。第二个是在父进程退出之后,但是子进程正在休眠10秒。第三个是在孩子进程被假定退出之后,但由于某种原因,这个过程似乎还活着并且正在睡觉。

第一

:> ps u | grep expect
user   31472  0.2  0.0   6196  2524 pts/2    Sl+  19:33   0:00 /tools/oss/packages/x86_64-rhel5/expect/default/bin/expect temp_fork
user   31483  0.0  0.0   6196  1456 pts/2    S+   19:33   0:00 /tools/oss/packages/x86_64-rhel5/expect/default/bin/expect temp_fork

第二

:> ps u | grep expect
user   31483  0.0  0.0   6196  1576 pts/2    S    19:33   0:00 /tools/oss/packages/x86_64-rhel5/expect/default/bin/expect temp_fork

第三

:> ps u | grep expect
user   31483  0.0  0.0   6196  1700 pts/2    S    19:33   0:00 /tools/oss/packages/x86_64-rhel5/expect/default/bin/expect temp_fork

1 个答案:

答案 0 :(得分:0)

在子进程作业完成后,您应该从程序中的某个位置退出子进程。我不认为你在任何地方都这样做。我只是看到父进程调用了exit。

while {1} {
   # If forking fails, retry every 10 seconds until it succeeds.
   if {[catch fork child_pid] == 0} {
      # do your job with child process
      exit
   }
   sleep 10
}