【问题标题】:How to start a background process with nohup using Fabric?如何使用 Fabric 使用 nohup 启动后台进程?
【发布时间】:2012-02-05 05:32:38
【问题描述】:

通过Fabric,我正在尝试使用下面的nohup 命令启动一个celerycam 进程。不幸的是,什么都没有发生。手动使用相同的命令,我可以启动该过程,但不能通过 Fabric。关于如何解决这个问题的任何建议?

def start_celerycam():
    '''Start celerycam daemon'''
    with cd(env.project_dir):
        virtualenv('nohup bash -c "python manage.py celerycam --logfile=%scelerycam.log --pidfile=%scelerycam.pid &> %scelerycam.nohup &> %scelerycam.err" &' % (env.celery_log_dir,env.celery_log_dir,env.celery_log_dir,env.celery_log_dir))

        

【问题讨论】:

    标签: python fabric


    【解决方案1】:

    我正在使用 Erich Heine 的建议来使用“dtach”,它对我来说效果很好:

    def runbg(cmd, sockname="dtach"):
        return run('dtach -n `mktemp -u /tmp/%s.XXXX` %s' % (sockname, cmd))
    

    这是在here找到的。

    【讨论】:

    • 我尝试了很多不同的方法。这是最终奏效的那个。
    • 我试过了,它有效!但是当我在 'cmd' 中添加 nohup 时,仍然无法正常工作,所以我只是删除了 nohup 和 '&'。
    • 如何查看分离执行的日志。可以配置吗?或者有具体的位置可以找吗?
    【解决方案2】:

    根据我的实验,解决方案是两个因素的组合:

    • 作为守护进程运行进程:nohup ./command &> /dev/null &
    • 使用 pty=False 进行织物运行

    所以,你的函数应该是这样的:

    def background_run(command):
        command = 'nohup %s &> /dev/null &' % command
        run(command, pty=False)
    

    您可以使用以下命令启动它:

    execute(background_run, your_command)
    

    【讨论】:

    • mesg: ttyname failed: Inappropriate ioctl for devic
    【解决方案3】:

    这是this issue 的一个实例。命令结束时,后台进程将被终止。不幸的是,在 CentOS 6 上不支持 pty-less sudo 命令。

    问题的最后一个条目提到使用sudo('set -m; service servicename start')。这将打开作业控制,因此后台进程被放入它们自己的进程组中。因此,它们不会在命令结束时终止。

    有关更多信息,请参阅this 链接。

    【讨论】:

    • +1:谢谢! pty=false 建议在 RHEL 上对我不起作用(因为 sudo 需要 TTY),但前缀 set -m; 效果很好!不过,我们能否获得更多关于set -m; 的影响的信息?那到底是在做什么/这个解决方案是如何工作的?有什么我应该警惕的吗?我以后应该进行一些清理工作吗?
    • 对我来说,run("nohup %s >& /dev/null < dev/null &" % cmd, pty=False)run ("set -m; nohup %s &" % cmd) 都为我工作。
    【解决方案4】:

    你只需要运行

    run("(nohup yourcommand >& /dev/null < /dev/null &) && sleep 1")
    

    【讨论】:

    • 哇,你是怎么找到这个的?一个稍微简单的版本也是(nohup yourcommand &amp;&gt; /dev/null &lt; /dev/null &amp;) &amp;&amp; /bin/true
    【解决方案5】:

    DTACH 是要走的路。这是您需要安装的软件,就像精简版的屏幕一样。 这是上面找到的“dtach”方法的一个更好的版本,它会在必要时安装 dtach。可以在here 找到它,您还可以在其中学习如何获取在后台运行的进程的输出:

    from fabric.api import run
    from fabric.api import sudo
    from fabric.contrib.files import exists
    
    
    def run_bg(cmd, before=None, sockname="dtach", use_sudo=False):
        """Run a command in the background using dtach
    
        :param cmd: The command to run
        :param output_file: The file to send all of the output to.
        :param before: The command to run before the dtach. E.g. exporting
                       environment variable
        :param sockname: The socket name to use for the temp file
        :param use_sudo: Whether or not to use sudo
        """
        if not exists("/usr/bin/dtach"):
            sudo("apt-get install dtach")
        if before:
            cmd = "{}; dtach -n `mktemp -u /tmp/{}.XXXX` {}".format(
                before, sockname, cmd)
        else:
            cmd = "dtach -n `mktemp -u /tmp/{}.XXXX` {}".format(sockname, cmd)
        if use_sudo:
            return sudo(cmd)
        else:
            return run(cmd)
    

    希望这对您有所帮助,就像它帮助我在远程 rasberry pi 上通过 fabric 运行 omxplayer 一样!

    【讨论】:

    • 你真的每个人都得到它来将结果泵送到一个 output_file 吗?您的代码似乎并未实际使用该参数。我正在尝试了解如何记录事件?
    • 嗨,我正在寻找一种获取输出日志的方法。你们是否设法找到将日志存储到输出文件的任何解决方案?
    【解决方案6】:

    你可以使用:

    run('nohup /home/ubuntu/spider/bin/python3 /home/ubuntu/spider/Desktop/baidu_index/baidu_index.py > /home/ubuntu/spider/Desktop/baidu_index/baidu_index.py.log 2>&1 &', pty=False)
    

    【讨论】:

      【解决方案7】:

      你可能会遇到this issue

      尝试在 sudo 命令中添加“pty=False”(我假设 virtualenv 正在调用 sudo 或在某处运行?)

      【讨论】:

      • 是的,即使使用 pty=False,它仍然挂起
      【解决方案8】:

      这对我有用:

      sudo('python %s/manage.py celerycam --detach --pidfile=celerycam.pid' % siteDir)
      

      编辑:我必须确保首先删除 pid 文件,所以这是完整的代码:

      # Create new celerycam
      sudo('rm celerycam.pid', warn_only=True)
      sudo('python %s/manage.py celerycam --detach --pidfile=celerycam.pid' % siteDir)
      

      【讨论】:

        【解决方案9】:

        nohup 对我不起作用,我没有在我想使用它的所有盒子上安装 tmuxdtach,所以我最终像这样使用 screen

        run("screen -d -m bash -c '{}'".format(command), pty=False)
        

        这告诉屏幕在运行您的命令的分离终端中启动一个 bash shell

        【讨论】:

          【解决方案10】:

          我可以通过在单独的本地 shell 脚本中运行 nohup ... &amp; 而不是 ssh 来规避这个问题。在fabfile.py

          @task
          def startup():
              local('./do-stuff-in-background.sh {0}'.format(env.host))
          

          do-stuff-in-background.sh:

          #!/bin/sh
          
          set -e
          set -o nounset
          
          HOST=$1
          
          ssh $HOST -T << HERE
             nohup df -h 1>>~/df.log 2>>~/df.err &
          HERE
          

          当然,您也可以将命令和标准输出/错误日志文件作为参数传递,以使该脚本更普遍有用。

          (在我的情况下,我没有安装 dtach 的管理员权限,screen -d -mpty=False / sleep 1 对我来说都不能正常工作。YMMV,尤其是因为我不知道 为什么这行得通...)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-09-29
            • 2012-01-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多