【问题标题】:How to run a background process and do *not* wait?如何运行后台进程并且*不*等待?
【发布时间】:2016-08-31 16:17:54
【问题描述】:

我的目标很简单:启动 rsync 并且不要等待。

Debian 上的 Python 2.7.9

示例代码:

rsync_cmd = "/usr/bin/rsync -a -e 'ssh -i /home/myuser/.ssh/id_rsa' {0}@{1}:'{2}' {3}".format(remote_user, remote_server, file1, file1)
rsync_cmd2 = "/usr/bin/rsync -a -e 'ssh -i /home/myuser/.ssh/id_rsa' {0}@{1}:'{2}' {3} &".format(remote_user, remote_server, file1, file1)
rsync_path = "/usr/bin/rsync"
rsync_args = shlex.split("-a -e 'ssh -i /home/mysuser/.ssh/id_rsa' {0}@{1}:'{2}' {3}".format(remote_user, remote_server, file1, file1))
#subprocess.call(rsync_cmd, shell=True)     # This isn't supposed to work but I tried it
#subprocess.Popen(rsync_cmd, shell=True)    # This is supposed to be the solution but not for me
#subprocess.Popen(rsync_cmd2, shell=True)   # Adding my own shell "&" to background it, still fails
#subprocess.Popen(rsync_cmd, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True)  # This doesn't work
#subprocess.Popen(shlex.split(rsync_cmd))   # This doesn't work
#os.execv(rsync_path, rsync_args)           # This doesn't work
#os.spawnv(os.P_NOWAIT, rsync_path, rsync_args) # This doesn't work
#os.system(rsync_cmd2)                      # This doesn't work
print "DONE"

(我注释掉执行命令只是因为我实际上将所有的试验都保存在我的代码中,以便我知道我做了什么和没有做什么。显然,我会运行脚本右行未注释。)

这是怎么回事...我可以在服务器上观看传输,当传输完成时,我会在屏幕上打印“DONE”。

我希望在发出rsync 命令并开始传输后立即打印“DONE”。

看起来很直接。我遵循了其他帖子中概述的详细信息,例如 this 一个和 this 一个,但有些东西阻止了它为我工作。

提前谢谢。

(我已经尝试了在 StackExchange 中可以找到的所有内容,但我不觉得这是重复的,因为我仍然无法让它工作。我的设置有问题,需要帮助。)

【问题讨论】:

  • 似乎问题已得到解答here
  • @viach 的指针是你最好的选择。
  • This one 说“creationflags”仅适用于 Windows。您提供的链接也谈到了 Win32。
  • 您是否尝试过简化代码以查看问题所在? subprocess.call("sleep 10".split()) 在代码中有明显的延迟,而 subprocess.Popen("sleep 10".split()) 立即进入下一行。也许您的问题在其他地方并且很难看到?如果您将 rsync 调用更改为简单的睡眠调用,您的代码是否工作(在时间方面)?
  • 不相关:提及 "NOTHING that works for me"无用,除非您显示失败的确切代码示例,请描述您做了什么期望它会发生什么,而不是一步一步地发生。

标签: python subprocess background-process popen


【解决方案1】:

在 Ubuntu 中,即使 python 应用程序退出,以下命令也会继续工作。

url = "https://www.youtube.com/watch?v=t3kcqTE6x4A"  
cmd = f"mpv '{url}' && zenity --info --text 'you have watched {url}' &"
os.system(cmd)

【讨论】:

    【解决方案2】:

    我在使用 qnx 设备时遇到了类似的问题,我想要一个独立于主进程运行甚至在主进程终止后运行的子进程。 这是我发现实际有效的解决方案'creationflags=subprocess.DETACHED_PROCESS':

    import subprocess
    import time
    
    pid = subprocess.Popen(["python", "path_to_script\turn_ecu_on.py"], creationflags=subprocess.DETACHED_PROCESS)
    
    time.sleep(15)
    print("Done")
    

    文档链接:https://docs.python.org/3/library/subprocess.html#subprocess.Popen

    【讨论】:

    【解决方案3】:

    Popen() 启动一个子进程——它不会等待它退出。如果要等待子进程,则必须显式调用 .wait() 方法。从这个意义上说,所有子进程都是后台进程。

    另一方面,子进程可能会从父进程继承各种属性/资源,例如打开的文件描述符、进程组、其控制终端、某些信号配置等——这可能会导致阻止祖先进程退出,例如, Python subprocess .check_call vs .check_output 或者子进程可能会在 Ctrl-C(SIGINT 信号发送到前台进程组)或终端会话关闭 (SIGHUP) 时过早死亡。

    要完全解除子进程的关联,您应该将其设为daemon。有时介于两者之间可能就足够了,例如 redirect the inherited stdout in a grandchild so that .communicate() in the parent would return when its immediate child exits 就足够了。

    【讨论】:

    • 有没有办法继续发送正在运行的进程数据/命令?
    • @CharlieParker 自然,for example
    【解决方案4】:

    这里是 Python REPL 的经过验证的示例:

    >>> import subprocess
    >>> import sys
    >>> p = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(100)'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT); print('finished')
    finished
    

    如何通过另一个终端窗口验证:

    $ ps aux | grep python
    

    输出:

    user           32820   0.0  0.0  2447684   3972 s003  S+   10:11PM   0:00.01 /Users/user/venv/bin/python -c import time; time.sleep(100)
    

    【讨论】:

    • 这在解释器中也适用于我,但不适用于我的脚本。我必须开始把它拆毁并重建它。我也会按照上面@asav 的建议尝试Process()
    • 我在调用 Popen 后向日志打印了一条消息,如您的示例所示,我在日志中看到了我的消息。问题出在我还没有找到的其他地方,但像往常一样,您的建议帮助我确定 Popen 不是问题。谢谢您的帮助!我正在使用p = subprocess(rsync_dict, close_fds=True) 它是否像宣传的那样工作。
    • @harperville 我觉得行为的原因在于您的命令,它可能等待来自stdin 的一些输入。
    • 使用 stdout=DEVNULL 而不是 stdout=PIPE 否则子进程可能会在操作系统管道缓冲区填满时停止。
    • jfs 的回答暗示仅仅创建一个Popen 的实例就会使其自身分离,或者至少不会让你的python 脚本等待。如果是这样,为什么您的答案似乎比这复杂得多?此外,在最初的问题中,您发布了一个引用操作系统依赖关系的链接。您的答案是否与操作系统无关?
    猜你喜欢
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多