我怎样才能启动一个不是原来程序的subprocess?

OSX 10.7)我们使用的应用程序让我们分配在应用程序中发生某些活动时被调用的脚本。 我已经分配了一个bash脚本并被调用,问题是我需要做的是执行一些命令,等待30秒,然后再执行一些命令。 如果我有我的bash脚本做一个“睡眠30”整个应用程序冻结了30秒,等待我的脚本完成。

我试着把30秒的等待(和第二组命令)放到一个单独的脚本中,并调用“./secondScript&”,但是应用程序仍然在那里停留了30秒。 我假定应用程序正在等待脚本和所有subprocess终止。

我已经尝试过从主脚本中调用第二个脚本的这些变体,它们都有相同的问题:

  • nohup ./secondScript&
  • ((./secondScript&)&)
  • (./secondScript&)
  • nohup脚本-q / dev / null secondScript&

我没有能力改变应用程序,并告诉它启动我的脚本,而不是等待它完成。

我怎样才能启动一个进程(我宁愿这个进程使用脚本语言),使得新进程不是当前进程的subprocess?

谢谢,克里斯

ps我尝试了“disown”命令,它也没有帮助。 我的主要脚本是这样的:

[initial commands] echo Launching second script ./secondScript & echo Looking for jobs jobs echo Sleeping for 1 second sleep 1 echo Calling disown disown echo Looking again for jobs jobs echo Main script complete 

而我得到的输出是这样的:

 Launching second script Looking for jobs [1]+ Running ./secondScript & Sleeping for 1 second Calling disown Looking again for jobs Main script complete 

在这一点上调用应用程序坐在那里45秒,等待secondScript完成。

PPS

如果在主脚本的顶部,我执行“ps”,它返回的唯一东西就是在单独的terminal窗口中打开的交互式bash会话的进程ID。

$ SHELL的值是/ bin / bash

如果我执行“ps -p $$”,它正确地告诉我

 PID TTY TIME CMD 26884 ?? 0:00.00 mainScript 

如果我执行“lsof -p $$”,它给了我所有的结果(我没有粘贴所有的列,假设它们不相关):

 FD TYPE NAME cwd DIR /private/tmp/blahblahblah txt REG /bin/bash txt REG /usr/lib/dyld txt REG /private/var/db/dyld/dyld_shared_cache_x86_64 0 PIPE 1 PIPE -> 0xffff8041ea2d10 2 PIPE -> 0xffff 8017d21cb 3r DIR /private/tmp/blahblah 4r REG /Volumes/DATA/blahblah 255r REG /Volumes/DATA/blahblah 

Solutions Collecting From Web of "我怎样才能启动一个不是原来程序的subprocess?"

在Unix中这样做的典型方式是双叉。 在bash中,你可以这样做

 ( sleep 30 & ) 

(..)创建一个子进程,并创建一个孙子进程。 当子进程死亡时,孙子进程由init继承。


如果这不起作用,那么你的应用程序不会等待子进程。

其他可能正在等待的事情包括会话和打开的锁定文件:

为了创建一个新的会话,Linux有一个setsid 。 在OS X上,你可以通过script来完成,顺便也创建了一个新的会话:

 # Linux: setsid sleep 30 # OS X: nohup script -q -c 'sleep 30' /dev/null & 

要查找继承的文件描述符的列表,可以使用lsof -p yourpid ,它将输出如下所示的内容:

 sleep 22479 user 0u CHR 136,32 0t0 35 /dev/pts/32 sleep 22479 user 1u CHR 136,32 0t0 35 /dev/pts/32 sleep 22479 user 2u CHR 136,32 0t0 35 /dev/pts/32 sleep 22479 user 5w REG 252,0 0 1048806 /tmp/lockfile 

在这种情况下,除了标准FD 0,1和2之外,还可以打开带有锁定文件的fd 5,父文件可以等待。

要关闭fd 5,可以使用exec 5>&- 。 如果你认为锁文件本身可能是stdin / stdout / stderr,你可以使用nohup把它们重定向到别的东西。

另一种方法是放弃孩子

 #!/bin/bash yourprocess & disown 

据我所知,应用程序替换了正常的bash shell,因为它仍然在等待一个进程完成,即使init应该照顾这个子进程。 可能是“ 应用程序 ”拦截了通常由init完成的孤行处理。

在这种情况下,只有一些IPC的并行进程可以提供解决方案(请参阅我的其他答案)

我认为这取决于你的父进程如何检测你的子进程是否已经完成。 在我的例子中(我的父进程是gnu make),我通过关闭stdout和stderr(稍微根据其他人的回答 )来成功:

 sleep 30 >&- 2>&- & 

你也可能关闭stdin

 sleep 30 <&- >&- 2>&- & 

或者另外断定你的子进程(不适用于Mac)

 sleep 30 <&- >&- 2>&- & disown 

目前仅在kubuntu 14.04和Mac OSX上使用bash进行测试。

如果一切都失败了:

  1. 创建一个命名管道

  2. 启动与“ 应用程序无关的“慢速”脚本,确保在从管道读取开始的无限循环中执行它的任务。 当它试图读取它将被读取阻止。

  3. 从应用程序中,启动您的其他脚本。 当需要调用“慢”脚本时,只需要将一些数据写入管道。 慢脚本将独立启动,因此脚本不会等待“慢”脚本完成。

所以,要回答这个问题:
bash – 我怎么能启动一个不是原始程序的子进程?

简单的:不要启动它,而是让一个独立的实体在启动过程中启动它,比如init或者在batch命令at

在这里,我有一个壳

 └─bash(13882) 

我在哪里开始这样一个过程:

 $ (urxvt -e ssh somehost&) 

我得到一个进程树(这个输出从pstree -ppstree -p ):

 ├─urxvt(14181)───ssh(14182) 

进程在pid 1下面( systemd在我的情况)。

但是,如果我做了这个(注意&的地方):

 $ (urxvt -e ssh somehost)& 

那么这个过程将是shell的一个子节点:

 └─bash(13882)───urxvt(14181)───ssh(14182) 

在这两种情况下,shell提示立即返回,我可以exit没有终止我上面开始的进程树。

对于后一种情况,当shell退出时,进程树被重新映射到pid 1下面,所以最终结果与第一个示例相同。

 ├─urxvt(14181)───ssh(14182) 

无论哪种方式,结果都是一个超过shell的进程树。 唯一的区别是该进程树的初始父母。

作为参考,你也可以使用

  • nohup urxvt -e ssh somehost &
  • urxvt -e ssh somehost & disown $!

两者都提供了与上面第二个示例相同的进程树。

 └─bash(13882)───urxvt(14181)───ssh(14182) 

当shell被终止时,进程树像以前一样重新映射到pid 1。

nohup另外将进程的标准输出重定向到一个文件nohup.out ,如果这是一个有用的特性,它可能是一个更有用的选择。

否则,使用上面的第一个表单,您立即拥有一个完全分离的流程树。