Запуск нескольких процессов оболочки - PullRequest
3 голосов
/ 22 сентября 2010

Я пытаюсь использовать 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 в терминале, который я хочу, чтобы продолжать работать неопределенно.Во-вторых, я хочу выполнить похожую команду несколько раз в нескольких разных процессах.

Ответы [ 3 ]

1 голос
/ 22 сентября 2010

Простой ответ, который я могу придумать, - это заставить 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 свой собственный подпроцесс
  • Пусть процесс внука перенаправит ввод / вывод на /dev/null, а затем использует одну из функций exec, чтобы запустить процесс, который вы действительно хотите запустить (возможно, сможет использовать Popen для этой части)
  • Дочерний процесс завершается.
  • Теперь нет никакой связи между бабушкой и дедушкой и внуком, поэтому, если внук завершается, вы не получаете сигнал SIGCHLD, а если дедушка завершает работу, он не убивает всех внуков.

Я мог бы быть в деталях, но это суть. Фоновая обработка (&) и disown в bash должны выполнять одно и то же.

1 голос
/ 22 сентября 2010

Это должно оставаться открытым, пока процесс запущен. Если вы хотите запустить несколько одновременно, просто оберните их в поток

непроверенный код, но вы должны получить общее представление:


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.

0 голосов
/ 22 сентября 2010

Вот плохая версия очереди блокировки. Вы можете добавить его в коллекцию collection.deque и т. П., Или еще больше полюбить Twisted deferreds, или нет. Crummy части включают в себя:

  • блокировка
  • сигналы убийства могут не распространяться вниз

сезон по вкусу!

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...