使用与号 (&) 在后台运行子进程时,运行 bash 脚本不会返回到终端
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28281467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Running bash script does not return to terminal when using ampersand (&) to run a subprocess in the background
提问by theGuardian
I have a script (lets call it parent.sh) that makes 2 calls to a second script (child.sh) that runs a java process. The child.sh scripts are run in the background by placing an & at the end of the line in parent.sh. However, when i run parent.sh, i need to press Ctrl+C to return to the terminal screen. What is the reason for this? Is it something to do with the fact that the child.sh processes are running under the parent.sh process. So the parent.sh doesn't die until the childs do?
我有一个脚本(我们称之为 parent.sh),它对运行 Java 进程的第二个脚本(child.sh)进行了 2 次调用。child.sh 脚本在后台运行,方法是在 parent.sh 的行尾放置一个 &。但是,当我运行 parent.sh 时,我需要按 Ctrl+C 才能返回到终端屏幕。这是什么原因?是否与 child.sh 进程在 parent.sh 进程下运行的事实有关。所以 parent.sh 不会死,直到孩子死?
parent.sh
父文件
#!/bin/bash
child.sh param1a param2a &
child.sh param1b param2b &
exit 0
child.sh
子文件
#!/bin/bash
java com.test.Main
echo "Main Process Stopped" | mail -s "WARNING-Main Process is down." [email protected]
As you can see, I don't want to run the java process in the background because i want to send a mail out when the process dies. Doing it as above works fine from a functional standpoint, but i would like to know how i can get it to return to the terminal after executing parent.sh.
如您所见,我不想在后台运行 java 进程,因为我想在进程终止时发送邮件。从功能的角度来看,像上面那样做很好,但我想知道如何在执行 parent.sh 后让它返回到终端。
回答by theGuardian
What i ended up doing was to make to change parent.sh to the following
我最终做的是将 parent.sh 更改为以下内容
#!/bin/bash
child.sh param1a param2a > startup.log &
child.sh param1b param2b > startup2.log &
exit 0
I would not have come to this solution without your suggestions and root cause analysis of the issue. Thanks!
如果没有您的建议和对问题的根本原因分析,我就不会提出这个解决方案。谢谢!
And apologies for my inaccurate comment. (There was no input, I answered from memory and I remembered incorrectly.)
并对我的不准确评论表示歉意。(没有输入,我凭记忆回答,我记错了。)
回答by ptierno
The following link from the Linux Documentation Projectsuggests adding a wait
after your mail
command in child.sh
:
Linux 文档项目中的以下链接建议wait
在您的mail
命令后添加child.sh
:
http://tldp.org/LDP/abs/html/x9644.html
http://tldp.org/LDP/abs/html/x9644.html
Summary of the above document
以上文件摘要
Within a script, running a command in the background with an ampersand (&) may cause the script to hang until ENTER is hit. This seems to occur with commands that write to stdout. It can be a major annoyance.
....
....As Walter Brameld IV explains it:
As far as I can tell, such scripts don't actually hang. It just seems that they do because the background command writes text to the console after the prompt. The user gets the impression that the prompt was never displayed. Here's the sequence of events:
- Script launches background command.
- Script exits.
- Shell displays the prompt.
- Background command continues running and writing text to the console.
- Background command finishes.
- User doesn't see a prompt at the bottom of the output, thinks script is hanging.
在脚本中,在后台运行带有与号 (&) 的命令可能会导致脚本挂起,直到按下 ENTER。这似乎发生在写入标准输出的命令中。这可能是一个主要的烦恼。
....
....正如 Walter Brameld IV 所解释的那样:
据我所知,这些脚本实际上并没有挂起。似乎他们这样做是因为后台命令在提示后将文本写入控制台。用户得到的印象是提示从未显示过。这是事件的顺序:
- 脚本启动后台命令。
- 脚本退出。
- Shell 显示提示。
- 后台命令继续运行并将文本写入控制台。
- 后台命令完成。
- 用户在输出底部没有看到提示,认为脚本正在挂起。
If you change child.sh
to look like the following you shouldn't experience this annoyance:
如果您更改child.sh
为如下所示,您就不会遇到这种烦恼:
#!/bin/bash
java com.test.Main
echo "Main Process Stopped" | mail -s "WARNING-Main Process is down." [email protected]
wait
Or as @SebastianStigler states in a comment to your question above:
或者正如@SebastianStigler 在对上述问题的评论中所说的那样:
Add a
> /dev/null
at the end of the line with mail. mail will otherwise try to start its interactive mode.
> /dev/null
在邮件行的末尾添加一个。否则邮件将尝试启动其交互模式。
This will cause the mail command to write to /dev/null
rather than stdout
which should also stop this annoyance.
这将导致邮件命令写入/dev/null
而不是stdout
哪个也应该停止这种烦恼。
Hope this helps
希望这可以帮助
回答by Tim
The process was still linked to the controlling terminal because STDOUT needs somewhere to go. You solved that problem by redirecting to a file ( > startup.log ).
该进程仍然链接到控制终端,因为STDOUT 需要去某个地方。您通过重定向到文件 ( > startup.log ) 解决了该问题。
If you're not interested in the output, discard STDOUT completely ( >/dev/null ).
如果您对输出不感兴趣,请完全丢弃 STDOUT ( >/dev/null )。
If you're not interested in errors, either, discard both ( &>/dev/null ).
如果您对错误不感兴趣,也可以同时丢弃 ( &>/dev/null )。
If you want the processes to keep running even after you log out of your terminal, use nohup— that effectively disconnects them from what you are doing and leaves them to quietly run in the background until you reboot your machine (or otherwise kill them).
如果您希望进程在您退出终端后继续运行,请使用nohup- 这有效地将它们与您正在执行的操作断开并让它们在后台安静地运行,直到您重新启动机器(或以其他方式杀死它们)。
nohup child.sh param1a param2a &>/dev/null &
nohup child.sh param1a param2a &>/dev/null &