Запустите сценарий оболочки, используя ткань и текст сценария конвейера на стандартный ввод оболочки.

Есть ли способ выполнить многострочный сценарий оболочки, направив его на стандартный ввод удаленной оболочки в fabric? Или я всегда должен записывать его в удаленную файловую систему, затем запускать, а затем удалять? Мне нравится отправлять на стандартный ввод, так как он позволяет избежать временного файла. Если нет API-интерфейса фабрики (и похоже, что он не основан на моих исследованиях), предположительно, я могу просто использовать модуль ssh напрямую. По сути, я бы хотел, чтобы fabric.api.run не ограничивалась однострочной командой, которая передается оболочке в качестве аргумента командной строки, а вместо этого брала бы полный многострочный скрипт и записывала его в стандартный ввод удаленной оболочки.

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

ssh somehost /bin/sh < /tmp/test.sh

За исключением python, исходный код сценария не будет исходить из файла в локальной файловой системе, это будет просто многострочная строка в памяти. Обратите внимание, что это единственная логическая операция, и на удаленной стороне нет временного файла, а это означает, что непредвиденные сбои и сбои не оставляют потерянных файлов. Если бы в ткани была такая опция (о чем я и спрашиваю), не нужно было бы иметь временный файл с обеих сторон, и для этого потребовалась бы только одна операция ssh.


person Peter Lyons    schedule 21.07.2012    source источник
comment
Почему бы просто не сделать что-то вроде run('command1 && command2 && command2')?   -  person tshepang    schedule 31.07.2012
comment
Потому что A) это нелегко читать, писать или поддерживать как код оболочки в Python, B) && влияет на поток вашего кода так, как вы можете или не хотите, и C) мир уже полон существующих сценариев оболочки Я хочу запускать через ткань, не преобразовывая их в одну строку.   -  person Peter Lyons    schedule 31.07.2012


Ответы (4)


Вы можете использовать операции Fabric. вы можете использовать fabric.operations.put(local_path, remote_path, use_sudo=False,mirror_local_mode=False,mode=None)

чтобы скопировать файл сценария на удаленный путь, а затем выполнить его.

or,

вы можете использовать fabric.operations.open_shell, но это будет работать только для серии простых команд, для сценариев, включающих логический поток, лучше использовать операцию ввода и выполнять сценарий так же, как вы делаете это на локальном сервере.

person sabs6488    schedule 21.10.2013

Если сценарий находится в файле, вы можете прочитать его, а затем передать его содержимое в run. Переписывая пример Джаспера:

from fabric.api import run

script_file = open('myscript.sh')
run(script_file.read())
script_file.close()
person jslopez    schedule 25.03.2013
comment
да, но ткань с удаленной записью файла, а затем его запуском, а затем удалением как 3 отдельными операциями. - person Peter Lyons; 25.03.2013

Для чего это стоит, это работает отлично. Он использует нотацию многострочной строки python ''' и разрыв строки bash (\ перед новой строкой). Вы можете использовать точку с запятой для разделения независимых строк или только операций с конвейером, таких как &&

run('''echo hello;\
  echo testing;\
  echo is this thing on?;''')
run('''echo hello && \
  echo testing && \
  echo is this thing on?''')

Вот результат, который я получаю:

[[email protected]:49300] run: echo hello;      echo testing;      echo is this thing on?;
[[email protected]:49300] out: hello
[[email protected]:49300] out: testing
[[email protected]:49300] out: is this thing on?
[[email protected]:49300] out: 

[[email protected]:49300] run: echo hello &&       echo testing &&      echo is this thing on?
[[email protected]:49300] out: hello
[[email protected]:49300] out: testing
[[email protected]:49300] out: is this thing on?
[[email protected]:49300] out: 
person Hamy    schedule 23.02.2015
comment
как я могу передать значение пользовательского ввода/переменной в многострочной команде запуска? - person Spike; 31.08.2016

Нет встроенного способа сделать это. Вы можете запрограммировать это, хотя:

from fabric.api import run

scriptfilehandle = open('myscript.sh')
for line in scriptfilehandle:
    run(line)
person Jasper van den Bosch    schedule 17.08.2012
comment
Это не будет работать. Вы не можете запустить многострочный блок if/for/while, вызывая новый процесс оболочки для каждой строки. - person Peter Lyons; 17.08.2012
comment
Хорошая точка зрения. Конечно, мой ответ предполагал, что сценарий состоит из простых команд, без реальной логики. Мое предложение остается в силе: вы можете разделить задание на разные разделы и запускать их по отдельности. - person Jasper van den Bosch; 11.09.2012
comment
Но практически говоря, я бы сказал, что вариант, который вы сами предложили, «положить» файл, а не выполнять его удаленно, был бы лучше. Может быть, вы можете пояснить, почему это не вариант? - person Jasper van den Bosch; 11.09.2012
comment
Размещение удаленного файла и его выполнение — это вариант, и это обычный способ работы с тканью. Однако с прямым ssh вполне возможно запустить скрипт без временных файлов на обоих концах, что и быстрее, и безопаснее. У меня есть экспериментальный код, чтобы сделать это в фабрике с использованием API модуля ssh более низкого уровня, и это технически возможно. Мне просто нужно найти чистый способ интегрировать его с тканью. - person Peter Lyons; 11.09.2012