Фонов процес от скрипт на python, изпълнен дистанционно с Fabric

Контекст

Добавям няколко части към съществуваща работеща система. Има контролна машина (локален компютър с Linux), която изпълнява някои тестови скриптове, които включват изпращане на много команди до няколко различни машини дистанционно чрез SSH. Тестовата рамка е написана на Python и използва Fabric за достъп до различните машини.

Всички команди се обработват с обща функция за извикване, опростена по-долу:

def cmd(host, cmd, args):
    ...
    with fabric.api.settings(host_string=..., user='root', use_ssh_config=True, disable_known_hosts=True):
        return fabric.api.run('%s %s' % (cmd, args))

Действителните команди, изпратени до всяка машина, обикновено включват изпълнение на съществуващ скрипт на Python от отдалечената страна. Тези скриптове на Python изпълняват някои задачи, които включват извикване на външни команди (с помощта на system и subprocess). Командата run(), извикана на тестовия компютър, ще се върне, когато отдалеченият скрипт на Python е готов.

В един момент имах нужда от един от онези отдалечени скриптове на Python, за да стартирам фонова задача: стартиране на openvon сървър и клиент с помощта на openvpn --config /path/to/config.openvpn. В нормален скрипт на Python просто бих използвал &:

system('openvpn --config /path/to/config.openvpn > /var/log/openvpn.log 2>&1 &')

Когато този скрипт се извиква отдалечено чрез Fabric, човек трябва изрично да използва nohup, dtach, screen и други подобни, за да изпълни заданието във фонов режим. Получих го да работи с:

system("nohup openvpn --config /path/to/config.openvpn > /var/log/openvpn.log 2>&1 < /dev/null &"

Често задавани въпроси за Fabric разглежда някои подробности за това. Работи добре за определени фонови команди.

Проблем: не работи за всички типове фонови команди

Тази техника не работи за всички команди, от които се нуждая. В някои скриптове трябва да стартирам фонова команда atop (това е top на стероиди) и да пренасоча нейния stdout към файл.

Моят код (забележка: използване на atop -P за анализируем изход):

system('nohup atop -P%s 1 < /dev/null | grep %s > %s 2>&1 &' % (dataset, grep_options, filename))

Когато скриптът, съдържащ тази команда, бъде извикан дистанционно чрез Fabric, горният процес незабавно се убива. Изходният файл е генериран, но е празен. Извикването на същия скрипт, докато сте влезли в отдалечената машина чрез SSH, работи добре, командата atop изхвърля периодично данни в моя изходен файл.

Малко търсене в гугъл и ровене ме доведе до интересна информация за фонови задачи, използващи Fabric, но проблемът ми изглежда е специфичен само за определени типове фонови задачи. Опитах:

Изглежда, че ми свършват идеите.

Платът изглежда прекалено много за това, което правим. Дори не използваме метода „fabfile“, защото е интегриран в nose рамка и аз ги изпълнявам, извиквайки nosetests. Може би трябва да прибегна до изпускане на Fabric в полза на ръчни SSH команди, въпреки че не ми харесва идеята за смяна на работеща система, тъй като тя не поддържа един от по-новите ми модули.


person Sébastien Dawans    schedule 12.07.2013    source източник


Отговори (1)


В моята среда изглежда, че работи

from fabric.api import sudo

def atop():
    sudo('nohup atop -Pcpu 1 </dev/null '
        '| grep cpu > /tmp/log --line-buffered 2>&1 &',
        pty=False)

резултат:

fabric:~$ fab atop -H web01
>>>[web01] Executing task 'atop'
>>>[web01] sudo: nohup atop -Pcpu 1 </dev/null | grep cpu > /tmp/log --line-buffered 2>&1 &
>>>
>>>Done.

web01:~$ cat /tmp/log 
>>>cpu web01 1374246222 2013/07/20 00:03:42 361905 100 0 5486 6968 0 9344927 3146 0 302 555 0 2494 100
>>>cpu web01 1374246223 2013/07/20 00:03:43 1 100 0 1 0 0 99 0 0 0 0 0 2494 100
>>>cpu web01 1374246224 2013/07/20 00:03:44 1 100 0 1 0 0 99 0 0 0 0 0 2494 100
...

Командата atop може да се нуждае от супер потребител. това не работи

from fabric.api import run

def atop():
    run('nohup atop -Pcpu 1 </dev/null '
        '| grep cpu > /tmp/log --line-buffered 2>&1 &',
        pty=False)

От друга страна тази работа.

from fabric.api import run

def atop():
    run('sudo nohup atop -Pcpu 1 </dev/null '
        '| grep cpu > /tmp/log --line-buffered 2>&1 &',
        pty=False)
person Yuichiro    schedule 19.07.2013