【问题标题】:Running bash script does not return to terminal when using ampersand (&) to run a subprocess in the background使用与号 (&) 在后台运行子进程时,运行 bash 脚本不会返回终端
【发布时间】:2015-02-02 15:48:37
【问题描述】:

我有一个脚本(我们称之为 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." user@email.com    

如您所见,我不想在后台运行 java 进程,因为我想在进程终止时发送邮件。从功能的角度来看,按照上述方式执行此操作很好,但我想知道在执行 parent.sh 后如何让它返回到终端。

【问题讨论】:

  • 它需要是 ctrl-c 还是按回车也会给你一个提示? ps 说在你按 ctrl-c 的地方运行的是什么?
  • java 程序是否需要任何输入?改成java com.test.Main < /dev/null会有帮助吗?
  • 在带有mail 的行尾添加> /dev/nullmail 将尝试启动其交互模式。
  • @theGuardian,如果它需要输入,你希望它如何背景化?它必须有一个控制终端句柄。
  • 正如@CharlesDuffy 所说,如果脚本接受输入,它如何在后台运行?它将从哪里获得输入?你没有提供任何东西(你用 ctrl-c 杀死它,我希望你实际上必须击中它两次)。

标签: bash shell scripting background-process ampersand


【解决方案1】:

该进程仍链接到控制终端,因为STDOUT 需要去某个地方。您通过重定向到文件 (> startup.log) 解决了这个问题。

如果您对输出不感兴趣,请完全丢弃 STDOUT (>/dev/null)。

如果您对错误不感兴趣,也可以丢弃两者 (&>/dev/null)。

如果您希望这些进程在您退出终端后继续运行,请使用 nohup - 这可以有效地将它们与您正在做的事情断开连接,让它们在后台安静地运行,直到您重新启动您的机器(或以其他方式杀死它们)。

nohup child.sh param1a param2a &>/dev/null &

【讨论】:

    【解决方案2】:

    我最终做的是将 parent.sh 更改为以下内容

    #!/bin/bash
    child.sh param1a param2a > startup.log &
    child.sh param1b param2b > startup2.log &
    exit 0
    

    如果没有您的建议和对问题的根本原因分析,我不会提出这个解决方案。谢谢!

    并为我的不准确评论道歉。 (没有输入,我凭记忆回答,记错了。)

    【讨论】:

    • 我遇到了同样的问题,这对我有用。如果您不需要收集输出,则将 & 替换为 > /dev/null & 也可以。
    【解决方案3】:

    来自Linux Documentation Project 的以下链接建议在child.sh 中的mail 命令之后添加wait

    http://tldp.org/LDP/abs/html/x9644.html

    以上文档总结

    在脚本中,在后台运行带有与号 (&) 的命令 可能会导致脚本挂起,直到 ENTER 被击中。这似乎发生在 写入标准输出的命令。这可能是一个很大的烦恼。

    ....
    ....

    正如 Walter Brameld IV 解释的那样:

    据我所知,这样的脚本实际上并没有挂起。这只是 似乎他们这样做是因为后台命令将文本写入 提示后的控制台。用户得到的印象是 提示从未显示。以下是事件的顺序:

    1. 脚本启动后台命令。
    2. 脚本退出。
    3. Shell 显示提示。
    4. 后台命令继续运行并将文本写入 控制台。
    5. 后台命令完成。
    6. 用户在输出底部没有看到提示,认为是脚本 正在挂起。

    如果您将child.sh 更改为如下所示,您应该不会遇到这种烦恼:

    #!/bin/bash
    java com.test.Main
    echo "Main Process Stopped" | mail -s "WARNING-Main Process is down." user@gmail.com
    wait
    

    或者正如@SebastianStigler 在对您上述问题的评论中所说:

    在邮件行尾添加> /dev/null。否则邮件将尝试启动其交互模式。

    这将导致邮件命令写入/dev/null 而不是stdout,这也应该停止这种烦恼。

    希望对你有帮助

    【讨论】:

    • OP也可以在最后一次调用child.sh之后添加wait命令(就在exit 0之前,效果一样。
    猜你喜欢
    • 1970-01-01
    • 2015-08-19
    • 1970-01-01
    • 2023-03-24
    • 2011-09-19
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多