2010-09-21 71 views
3

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

在此先感谢。

编辑:

下面是我在做什么:

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运行的终端。其次,我想在多个不同的进程中多次运行类似的命令。

+1

这也应该适用于多个,展示你的代码。 – knitti 2010-09-21 21:11:27

+1

您可能需要使用'Popen'打开终端,如gnome-terminal,并使用标志来发送你想运行的命令。唯一的问题是,我不知道如何让终端在完成指定命令后保持“打开”状态。 – sholsapp 2010-09-21 21:19:00

+0

为什么要保持开放? – knitti 2010-09-21 21:43:40

回答

1

只要进程正在运行,这应该保持打开状态。如果你想simultanously启动多个,只需将它包装在一个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() 

编辑:由Mike https://stackoverflow.com/a/3765162/450517:双叉方法,这里介绍下将是启动守护进程的正确方式,即一个长期运行的进程,它不会按每个stdio进行通信。

+1

在这里使用线程毫无意义。 'Popen'不会阻塞,所以你会得到相同的结果,只需在主线程中运行3次'Popen'。问题是,主程序不等待任何进程终止等(在Linux至少)离开僵尸程序周围铺设。 – tdelaney 2015-04-17 00:14:13

+0

这不是从文档(https://docs.python.org/2/library/subprocess.html#subprocess.Popen),它woudn't块清晰,并且一个线程不会在这种情况下受到伤害。另外,那些不应该是僵尸,而是运行直到完成,然后终止,独立于启动过程。 – knitti 2015-04-17 11:23:20

1

简单的答案我可以想出是使用Python Popen推出类似的shell脚本:

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作为此部分)
  • 孩子p过程退出。
  • 现在祖父母和孙子之间没有任何联系,所以如果孙子终止了,你不会得到SIGCHLD信号,如果祖父母终止,它不会杀死所有孙子。

我可能在细节上,但这是主旨。背景(&)和disown ing bash应该完成相同的事情。

+0

很高兴看到这里描述的双叉法 – knitti 2015-04-17 11:28:31

0

这是一个糟糕的阻塞队列版本。你可以用collections.deque或类似的东西来表达它,或者更喜欢扭曲的延迟,或者没有。照出的部分包括:

  • 阻挡
  • 终止信号可能不会向下传播

季节的味道!

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)