Контекст
Добавям няколко части към съществуваща работеща система. Има контролна машина (локален компютър с 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, но проблемът ми изглежда е специфичен само за определени типове фонови задачи. Опитах:
- добавяне на заспиване
- работи с pty=False
- замяна на
nohup
сdtach -n
: същите симптоми - Четох за команди като top failing в Fabric със stdin, пренасочен към /dev/null, не съм съвсем сигурен какво да правя с това. Играх си с различни комбинации или (не) пренасочвания на STDIN, STDOUT и STDERR
Изглежда, че ми свършват идеите.
Платът изглежда прекалено много за това, което правим. Дори не използваме метода „fabfile“, защото е интегриран в nose
рамка и аз ги изпълнявам, извиквайки nosetests
. Може би трябва да прибегна до изпускане на Fabric в полза на ръчни SSH команди, въпреки че не ми харесва идеята за смяна на работеща система, тъй като тя не поддържа един от по-новите ми модули.