【问题标题】:What is the easiest way to "detach/daemonize" a Bash script?“分离/守护” Bash 脚本的最简单方法是什么?
【发布时间】:2011-05-21 04:05:24
【问题描述】:

我要做的是编写一个 Bash 脚本,在使用 mac say 命令之前 sleps 一段时间说一些文字。

我希望能够运行该命令,然后关闭终端,这样它仍然会在设定的时间说话。我研究了 nohup、分离、启动并将进程置于后台,但所有这些解决方案仍然会导致进程在终端关闭后终止。我应该以某种方式制作某种僵尸子进程来执行此操作吗?什么是最好的解决方案?谢谢

# Simple Example of main code
sleep 10;
say hello;
exit;

【问题讨论】:

    标签: bash process daemon sleep detach


    【解决方案1】:
    nohup yourscript.sh 10 "hello" &
    
    #     ^your script  ^^your parameter 1
    #                      ^^^^^^^your parameter 2
    

    这会将脚本与终端分离,并且在终端关闭时不会被终止。注意末尾的&;您可以正常将参数传递给您的脚本。那么 yourscript.sh 可能是:

    #!/bin/bash
    
    sleep $1;
    say "$2";
    exit;
    

    【讨论】:

    • 我忽略了在我的脚本中时间和消息是可变的。如果我像这样运行命令,我将永远看不到我的提示,也无法输入变量。 ://
    【解决方案2】:

    你需要同时使用 nohup 和 background。我刚刚在 OS-X 上尝试了这个以验证它是否有效:

    nohup ./say-hello.sh &
    

    【讨论】:

    • 我忽略了在我的脚本中时间和消息是可变的。如果我像这样运行命令,我将永远看不到我的提示,也无法输入变量。 ://
    【解决方案3】:

    Bash 手册第 3.7.6 节说:

    shell 在收到 SIGHUP 后默认退出。在退出之前,一个交互式外壳 将 SIGHUP 重新发送到所有正在运行或已停止的作业。停止的作业被发送 SIGCONT 到 确保他们收到 SIGHUP。防止 shell 发送 SIGHUP 信号 对于特定的工作,应该使用 disown 内置函数将其从工作表中删除(参见 第 7.2 节 [Job Control Builtins],第 88 页)或使用disown -h 标记为不接收 SIGHUP。

    因此,使用nohupdisown 应该可以解决问题。或者你可以这样做:

    trap "" 1
    sleep 10
    say hello
    

    'trap' 行忽略信号 1,SIGHUP;你也可以写成'trap "" HUP"。

    【讨论】:

    • 谢谢,我不知道 SIGHUP,但这是有道理的。这对于我正在尝试做的事情非常有效。 :)
    【解决方案4】:

    如果您不以nohup 开头,正如已经建议的那样,您将需要使用disown ...

    $ ./say-hello.sh &
    [1] 12345
    $ disown -h %1
    

    您需要记下作业编号(上例中的第二行,作业编号在括号中,另一行是进程ID),以便您可以将其传递给disown

    【讨论】:

    • 我正在尝试使脚本尽可能独立,以便没有 bash 甚至终端经验的人可以运行它。我想如果我把它放在另一个脚本中,虽然这是可行的。谢谢!
    【解决方案5】:

    按照 Piskvor 的建议使用 nohup yourscript.sh &

    但是,请注意,您将无法重新“控制”您的流程。因此,如果您确实需要它,我建议您将日志记录添加到文件中,以便您了解程序在做什么。

    如果没有kill -9,可能无法杀死您的程序,这可能有点残酷。如果您不希望这样,我建议每分钟左右收集一个像end.txt 这样的文件。如果你的程序检测到它的工作目录中存在这样的文件,它应该正常退出。

    【讨论】:

    • kill -15 - SIGTERM(可以被捕获和处理,用于优雅终止)而不是kill -9 - SIGKILL(不能被捕获或忽略)呢?
    • @Piskvor:这也是可能的,但您必须实现该行为。如果这不是问题,那将是可取的。
    【解决方案6】:

    您的脚本可能如下所示:

    #!/bin/bash
    read -p "Text: " text
    read -p "Delay: " delay
    nohup bash -c "sleep $delay; say \"$text\" &"
    

    然后你就可以正常运行你的脚本了:

    $ your_script
    Text: hello
    Delay: 10
    

    外部脚本将退出,但 Sleep&Say™ 将在后台运行。

    【讨论】:

      【解决方案7】:

      根据您对“简单”的定义,答案可能是daemon

      【讨论】:

        【解决方案8】:

        这里的所有解决方案都非常好,但它们没有提供一种简单的方法来“查看”程序中发生的事情,而不进行会填满硬盘驱动器的重定向。

        使用screen,您可以非常轻松地运行脚本,关闭您的终端/ssh 会话,然后再返回,再次“附加”到脚本。这样做很容易。

        安装

        先安装screen

        sudo apt-get install screen
        

        分离

        然后放入你的 bash 文件

        #!/usr/bin/env bash
        screen -S myscreen -d -m bash -c 'ls; exec bash'
        

        (用你的程序替换ls)它将创建(-S)一个名为myscreen的“屏幕”,并通过运行``-c```中的命令将其分离(-d)选项。然后,如果您想稍后连接到此屏幕:

        稍后再附上

        screen -rd myscreen
        

        如果您想列出当前正在运行的所有屏幕:

        screen -ls
        

        注意:如果您想在完成后关闭屏幕,请删除命令末尾的bash

        【讨论】:

          猜你喜欢
          • 2010-09-12
          • 1970-01-01
          • 2010-09-07
          • 2013-09-28
          • 2014-07-05
          • 1970-01-01
          • 2010-09-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多