【问题标题】:How to run a script in the background even after I logout SSH?即使在我注销 SSH 后,如何在后台运行 Python 脚本?
【发布时间】:2011-02-27 20:54:50
【问题描述】:

我有 Python 脚本 bgservice.py,我希望它一直运行,因为它是我构建的 Web 服务的一部分。即使在我注销 SSH 后,如何让它继续运行?

【问题讨论】:

    标签: python service cron


    【解决方案1】:

    替代答案:tmux

    • ssh 进入远程机器
    • 在cmd中输入tmux
    • tmux 中启动你想要的进程,例如python3 main.py
    • Ctrl+b 离开tmux 会话,然后d

    现在可以安全地退出远程计算机。当您回来时使用tmux attach 重新进入tmux 会话。

    如果您想启动多个会话,请使用Ctrl+b 命名每个会话,然后使用$。然后输入您的会话名称。

    列出所有会话使用tmux list-sessions

    要附加一个正在运行的会话,请使用tmux attach-session -t <session-name>

    【讨论】:

      【解决方案2】:

      在后台运行 Python 脚本

      首先,您需要在 Python 脚本中添加 shebang 行,如下所示:

      #!/usr/bin/env python3
      

      如果您安装了多个 Python 版本,则此路径是必需的,/usr/bin/env 将确保采用您的 $$PATH 环境变量中的第一个 Python 解释器。你也可以硬编码你的 Python 解释器的路径(例如#!/usr/bin/python3),但这不灵活,在其他机器上也不能移植。接下来,您需要设置文件的权限以允许执行:

      chmod +x test.py
      

      现在您可以使用忽略挂断信号的nohup 运行脚本。这意味着您可以在不停止执行的情况下关闭终端。另外,不要忘记添加&,以便脚本在后台运行:

      nohup /path/to/test.py &
      

      如果您没有在文件中添加shebang,则可以使用以下命令运行脚本:

      nohup python /path/to/test.py &
      

      输出将保存在nohup.out 文件中,除非您像这里这样指定输出文件:

      nohup /path/to/test.py > output.log &
      nohup python /path/to/test.py > output.log &
      

      如果您将命令的输出重定向到其他地方 - 包括 /dev/null - 那就是它的位置。

      # doesn't create nohup.out
      
      nohup command >/dev/null 2>&1   
      

      如果您使用的是nohup,这可能意味着您想在后台运行命令,方法是在整个过程的末尾加上另一个&

      # runs in background, still doesn't create nohup.out
      
       nohup command >/dev/null 2>&1 &  
      

      您可以使用以下命令找到process 及其process ID

      ps ax | grep test.py
      
      # or
      # list of running processes Python
      
      ps -fA | grep python
      

      ps 代表process status

      如果你想停止执行,你可以用kill命令kill它:

      kill PID
      

      【讨论】:

      • 如果我希望它在退出 ssh 之前仍然接受来自 ssh 终端的标准输入怎么办?
      • 该主题谈论背景而不是标准执行。无论如何,我认为你的答案在这个great documentation
      【解决方案3】:

      试试这个:

      nohup python -u <your file name>.py >> <your log file>.log &
      

      你可以在screen中运行上面的命令,然后跳出屏幕。

      现在您可以通过以下方式跟踪您的 Python 脚本日志:tail -f &lt;your log file&gt;.log

      要杀死你的脚本,你可以使用 ps -auxkill 命令。

      【讨论】:

      • 如果我希望它在退出 ssh 之前仍然接受来自 ssh 终端的标准输入怎么办?
      【解决方案4】:

      你也可以使用Yapdi

      基本用法:

      import yapdi
      
      daemon = yapdi.Daemon()
      retcode = daemon.daemonize()
      
      # This would run in daemon mode; output is not visible
      if retcode == yapdi.OPERATION_SUCCESSFUL:
      print('Hello Daemon')
      

      【讨论】:

        【解决方案5】:

        这是一个在 python 中使用装饰器的简单解决方案:

        import os, time
        
        def daemon(func):
            def wrapper(*args, **kwargs):
                if os.fork(): return
                func(*args, **kwargs)
                os._exit(os.EX_OK)
            return wrapper
        
        @daemon
        def my_func(count=10):    
          for i in range(0,count):
             print('parent pid: %d' % os.getppid())
             time.sleep(1)
        
        
        my_func(count=10)
        #still in parent thread
        time.sleep(2)
        #after 2 seconds the function my_func lives on is own
        

        您当然可以将bgservice.py 文件的内容替换为my_func

        【讨论】:

        • 也许有必要捕获 SIGHUP 信号。然后在你的块中添加 signal.signal(signal.SIGHUP, handler)。
        • 是的,这似乎在这里不起作用。当父母退出时,孩子会死去。
        【解决方案6】:

        您可能会考虑将您的 python 脚本转换为适当的 python 守护程序,如 here 所述。

        python-daemon 是一个很好的工具,可用于将 python 脚本作为后台守护进程运行,而不是永久运行的脚本。您将需要稍微修改现有代码,但其简单明了。

        如果您在使用 python-daemon 时遇到问题,还有另一个实用程序 supervisor 可以为您做同样的事情,但在这种情况下,您不必编写任何代码(或修改现有代码),因为这是不合时宜的用于守护进程的盒子解决方案。

        【讨论】:

        • 简要说明如何解决问题通常是个好主意。
        【解决方案7】:

        如果您需要的是无论您是否登录,该进程都应该永远运行,请考虑将该进程作为守护进程运行。

        supervisord 是一个很好的开箱即用的解决方案,可用于守护任何进程。它有另一个控制实用程序supervisorctl,可用于监视由主管运行的进程。

        您无需编写任何额外代码或修改现有脚本即可完成这项工作。此外,详细的文档使这个过程更加简单。

        在 python-daemon 上摸索了几个小时后,supervisor 是在几分钟内为我工作的解决方案。

        希望这有助于尝试使 python-daemon 工作的人

        【讨论】:

          【解决方案8】:

          你也可以使用GNU screen,这是几乎每个 Linux/Unix 系统都应该有的。

          如果您使用的是 Ubuntu/Debian,它的增强变体 byobu 也相当不错。

          【讨论】:

            【解决方案9】:

            如果你已经启动了进程,不想在nohup下杀死它重新启动,可以将它发送到后台,然后disown它。

            Ctrl+Z(暂停进程)

            bg(后台重启进程

            disown %1(假设这是作业#1,使用jobs来确定)

            【讨论】:

            • 如何让它停止打印到标准输出?
            【解决方案10】:

            zsh shell 有一个选项可以让所有后台进程使用 nohup 运行。

            ~/.zshrc 中添加以下行:

            setopt nocheckjobs  #don't warn about bg processes on exit
            setopt nohup        #don't kill bg processes on exit
            

            那么你只需要像这样运行一个进程:python bgservice.py &amp;,你就不再需要使用 nohup 命令了。

            我知道没有多少人使用 zsh,但我会推荐它是一个非常酷的 shell。

            【讨论】:

              【解决方案11】:

              你可以不用,但我更喜欢screen

              【讨论】:

                【解决方案12】:

                运行nohup python bgservice.py &amp; 让脚本忽略挂断信号并继续运行。输出将放在nohup.out

                理想情况下,您可以使用supervise 之类的内容运行脚本,以便在(何时)死亡时重新启动它。

                【讨论】:

                • 当我使用 nohup 和 & 运行命令时,我收到消息 nohup: ignoring in put and appending output to nohup.out'`,当我按下 enter 时,进程以状态 1 退出。这是怎么回事?
                • 读取 nohup.out 中的输出。就我而言,这是一个权限问题,我需要使用 sudo
                • 该方法运行后如何停止bgservice?
                • @Shaegorath 将 pid 保存在某处,以便您稍后可以向进程发送信号。在您执行somecommand &amp; 之后,在某些shell(bash、zsh 等)中,它会像[1] 12345 一样打印pid。否则你可以使用$!
                • 我一直将 nohup 作为该问题的推荐解决方案,但我看到输出文件 nohup.out 是在 python 脚本结束后生成的。它不允许您在 python 脚本运行时附加结果。我也看不到您如何使用 nohup 为脚本提供输入。我没有测试线程的行为,但由于上述原因,这对我来说不是一个好的解决方案。所以我会继续寻找。有什么解决方案或建议吗?当我使用 ssh 重新登录时,我想与我的应用程序交互。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2014-06-03
                • 1970-01-01
                • 1970-01-01
                • 2022-12-22
                • 2017-11-24
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多