Linux 如何启动不是原始流程子流程的新流程?
(OSX 10.7)我们使用的应用程序允许我们在应用程序中发生某些活动时指定要调用的脚本。我已经分配了一个bash脚本,它正在被调用,问题是我需要做的是执行一些命令,等待30秒,然后再执行一些命令。如果我让我的bash脚本执行“睡眠30”,那么整个应用程序会在等待脚本完成时冻结30秒 我尝试将30秒的等待(以及第二组命令)放入一个单独的脚本中,并调用“/secondScript&”,但应用程序仍然在那里等待30秒,什么也不做。我假设应用程序正在等待脚本和所有子进程终止 我尝试过从主脚本中调用第二个脚本的这些变体,它们都有相同的问题:Linux 如何启动不是原始流程子流程的新流程?,linux,bash,macos,daemon,Linux,Bash,Macos,Daemon,(OSX 10.7)我们使用的应用程序允许我们在应用程序中发生某些活动时指定要调用的脚本。我已经分配了一个bash脚本,它正在被调用,问题是我需要做的是执行一些命令,等待30秒,然后再执行一些命令。如果我让我的bash脚本执行“睡眠30”,那么整个应用程序会在等待脚本完成时冻结30秒 我尝试将30秒的等待(以及第二组命令)放入一个单独的脚本中,并调用“/secondScript&”,但应用程序仍然在那里等待30秒,什么也不做。我假设应用程序正在等待脚本和所有子进程终止 我尝试过从主脚本中调用第二
- nohup./secondScript&
- ((/第二脚本&)和)
- (./secondScript&)
- nohup脚本-q/dev/null secondScript&
[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
sleep 30 >&- 2>&- &
$ (urxvt -e ssh somehost&)
我从输出中得到的是:
Launching second script
Looking for jobs
[1]+ Running ./secondScript &
Sleeping for 1 second
Calling disown
Looking again for jobs
Main script complete
此时,调用应用程序在那里停留45秒,等待secondScript完成
p、 附言
如果在主脚本的顶部执行“ps”,则它返回的唯一内容是在单独的终端窗口中打开的交互式bash会话的进程ID
$SHELL的值为/bin/bash
如果我执行“ps-p$$”,它会正确地告诉我
PID TTY TIME CMD
26884 ?? 0:00.00 mainScript
如果我执行“lsof-p$$”,它会给出各种结果(我没有在这里粘贴所有列,假设它们不相关):
在Unix中执行此操作的典型方法是使用双fork。在bash中,您可以使用
( sleep 30 & )
(…)
创建子进程,和创建子进程。当子进程死亡时,孙子进程由init继承
如果这不起作用,那么您的应用程序就不会等待子进程
它可能等待的其他事情包括会话和打开锁定文件:
要创建新会话,Linux有一个setId
。在OS X上,您可能可以通过脚本
完成此操作,顺便说一句,它还创建了一个新会话:
# 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
在这种情况下,除了标准的FDs 0、1和2之外,还可以打开一个fd 5,其中包含父级可以等待的锁定文件
要关闭fd 5,可以使用exec 5>&-
。如果您认为锁文件可能是stdin/stdout/stderr本身,您可以使用nohup
将它们重定向到其他文件。另一种方法是放弃子文件
#!/bin/bash
yourprocess &
disown
据我所知,应用程序替换了普通的bashshell,因为它仍然在等待进程完成,即使init
应该处理这个子进程。
可能是“应用程序”拦截孤立处理,这通常由init
完成
在这种情况下,只有具有某些IPC的并行进程才能提供解决方案(请参阅我的另一个答案)如果所有其他方法都失败了:
创建命名管道
从“应用程序”启动独立的“慢速”脚本,确保以无休止的循环执行其任务,从管道读取开始。当它尝试读取时,它将被读取阻止
从应用程序启动其他脚本。当它需要调用“slow”脚本时,只需将一些数据写入管道。慢速脚本将独立启动,这样您的脚本就不会等待“慢速”脚本完成
因此,要回答这个问题:
bash-如何启动不是原始流程子流程的新流程?
简单:不要启动它,而是让一个独立的实体在引导期间启动它……比如init
,或者在或batch
中使用命令动态启动,我认为这取决于父进程如何检测子进程是否已完成。
在我的情况下(我的父进程是gnu make),我成功地关闭了stdout和stderr(稍微基于),如下所示:
[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
sleep 30 >&- 2>&- &
$ (urxvt -e ssh somehost&)
您也可以关闭stdin
sleep 30 <&- >&- 2>&- &
睡眠30&-2>&-&
或者另外拒绝您的子进程(不适用于Mac)
sleep30&-2>&-&disown
目前仅在kubuntu 14.04和Mac OSX上的bash中进行了测试。这里我有一个shell
└─bash(13882)
我开始这样的过程:
[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
sleep 30 >&- 2>&- &
$ (urxvt -e ssh somehost&)
我得到了一个进程树(该输出从pstree-p
截取):
其中,进程的父级位于pid 1下(systemd
)
但是,如果我这样做了(注意&
的位置):
然后该过程将是shell的子过程:
└─bash(13882)───urxvt(14181)───ssh(14182)
在这两种情况下,shell提示符都会立即返回,我可以退出
没有终止我上面启动的进程树
对于后一种情况,当
shell退出,因此其结果与第一个示例相同
├─urxvt(14181)───ssh(14182)
无论哪种方式,结果都是一个进程树,该进程树在shell之外。这个
唯一的区别是该流程树的初始父级
作为参考,您也可以使用
nohup urxvt-e ssh somehost&
urxvt-e ssh somehost&disown$代码>
两者都给出了与上面第二个示例相同的流程树
└─bash(13882)───urxvt(14181)───ssh(14182)
当shell终止时,进程tr