启动shell的多个进程

时间:2010-09-21 21:10:16

标签: python linux

我正在尝试使用python同时在多个单独的终端实例中启动命令。做这个的最好方式是什么?现在我正在尝试使用带有popen的子进程模块,该模块适用于一个命令但不适用于多个命令。

提前致谢。

编辑:

这是我正在做的事情:

from subprocess import*

Popen('ant -Dport='+str(5555)+ ' -Dhost='+GetIP()+ ' -DhubURL=http://192.168.1.113:4444 -Denvironment=*firefox launch-remote-control $HOME/selenium-grid-1.0.8', shell=True)

对我来说问题是这会在终端中启动一个java进程,我希望它继续运行indefinatley。其次,我想在多个不同的进程中多次运行类似的命令。

3 个答案:

答案 0 :(得分:1)

只要进程正在运行,它就应该保持打开状态。如果您想同时启动多个,只需将其包装在thread

未经测试的代码,但你应该得到一般的想法:


class PopenThread(threading.Thread):

    def __init__(self, port):
        threading.Thread.__init__(self)
        self.port=port

    def run(self):
        Popen('ant -Dport='+str(self.port)+ ' -Dhost='+GetIP()+ 
                ' -DhubURL=http://192.168.1.113:4444' 
                ' -Denvironment=*firefox launch-remote-control'
                ' $HOME/selenium-grid-1.0.8', shell=True)

if '__main__'==__name__:
    PopenThread(5555).start()
    PopenThread(5556).start()
    PopenThread(5557).start()

编辑:这里描述的双叉方法:迈克的https://stackoverflow.com/a/3765162/450517将是启动守护进程的正确方法,即一个长时间运行的进程,它不会每个stdio进行通信。

答案 1 :(得分:1)

我能想出的简单答案是让Python使用Popen来启动类似于的脚本脚本:

gnome-terminal --window -e 'ant -Dport=5555 -Dhost=$IP1 -DhubURL=http://192.168.1.113:4444 -Denvironment=*firefox launch-remote-control $HOME/selenium-grid-1.0.8' &
disown
gnome-terminal --window -e 'ant -Dport=5555 -Dhost=$IP2 -DhubURL=http://192.168.1.113:4444 -Denvironment=*firefox launch-remote-control $HOME/selenium-grid-1.0.8' &
disown
# etc. ...

有一种完全Python的方法可以做到这一点,但它很难看,只适用于类Unix操作系统,我没有时间编写代码。基本上,subprocess.Popen不支持它,因为它假定您要等待子进程完成,与子进程交互或监视子进程。它不支持“只是启动它,不要再打扰它了”的情况。

在类Unix操作系统中完成的方法是:

  • 使用fork生成子流程
  • 让子进程fork成为自己的子进程
  • 让孙子进程将I / O重定向到/dev/null,然后使用其中一个exec函数启动您真正想要启动的进程(可能可以使用Popen这部分)
  • 子进程退出。
  • 现在爷爷和孙子之间没有联系,所以如果孙子终止,你就不会得到SIGCHLD信号,如果祖父母终止了,就不会杀死所有的孙子。

我可能会关注细节,但这就是要点。 &中的背景(disown)和bash应该可以完成同样的事情。

答案 2 :(得分:0)

这是一个阻塞队列的糟糕版本。你可以使用collections.deque之类的方法来对它进行幻想,或者甚至可以使用Twisted deferreds,或者什么不是。可怜的部分包括:

  • 阻断
  • 杀死信号可能不会传播
季节尝试!

import logging
basicConfig = dict(level=logging.INFO, format='%(process)s %(asctime)s %(lineno)s %(levelname)s %(name)s %(message)s')
logging.basicConfig(**basicConfig)
logger = logging.getLogger({"__main__":None}.get(__name__, __name__))

import subprocess

def wait_all(list_of_Popens,sleep_time):
    """ blocking wait for all jobs to return.

    Args:
        list_of_Popens. list of possibly opened jobs

    Returns:
        list_of_Popens. list of possibly opened jobs

    Side Effect:
        block until all jobs complete.
    """
    jobs = list_of_Popens
    while None in [j.returncode for j in jobs]:
        for j in jobs:  j.poll()
        logger.info("not all jobs complete, sleeping for %i", last_sleep)
        time.sleep(sleep_time)  

    return jobs


jobs = [subprocess.Popen('sleep 1'.split()) for x in range(10)]
jobs = wait_all(jobs)