2012-07-21 7 views
9

¿Hay alguna forma de ejecutar un script de shell de varias líneas atornillándolo a la entrada estándar del shell remoto en fabric? ¿O debo escribirlo siempre en el sistema de archivos remoto, luego ejecutarlo y luego eliminarlo? Me gusta enviar a stdin ya que evita el archivo temporal. Si no hay una API de estructura (y parece que no se basa en mi investigación), presumiblemente puedo usar el módulo ssh directamente. Básicamente deseo fabric.api.run no se limitaba a un comando de 1 línea que pasa al shell como un argumento de línea de comando, sino que toma un script completo de múltiples líneas y lo escribe en la entrada estándar del shell remoto.Ejecutar script de shell utilizando texto de script de fabric y de canal en stdin de shell

Para aclarar Quiero el equivalente de tejido de esta línea de comandos:

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

Excepto en el pitón coude fuente del script no vendría de un archivo en el sistema de archivos local, no sería más que una cadena de varias líneas de memoria. Tenga en cuenta que esta es una operación lógica única y que no hay ningún archivo temporal en el lado remoto, lo que significa que los fallos inesperados y los bloqueos no dejan archivos huérfanos. Si hubiera una opción en el tejido (que es lo que estoy preguntando), no habría necesidad de un archivo temporal en ninguno de los lados y esto solo requeriría una sola operación ssh.

+0

¿Por qué no hacer algo como 'run ('comando1 && comando2 && comando2' ')? – Tshepang

+4

Porque A) no es fácil de leer o escribir o mantener como código shell-in-python, B) el && afecta el flujo de código en formas que puede o no desear y C) el mundo ya está lleno de shell existente scripts que quiero ejecutar a través de fabric sin convertirlos a una sola línea. –

Respuesta

0

No hay una forma incorporada de hacerlo. Se podría programarlo sin embargo:

from fabric.api import run 

scriptfilehandle = open('myscript.sh') 
for line in scriptfilehandle: 
    run(line) 
+5

Eso no funcionará. No puede ejecutar un bloque multilínea if/for/while invocando un nuevo proceso de shell para cada línea. –

+1

Buen punto. Por supuesto, mi respuesta asumió que el guión consistía en comandos simples, sin lógica real. Mi sugerencia sigue siendo que podría dividir el trabajo en diferentes secciones y ejecutarlas por separado. –

+1

Pero hablando en términos prácticos, diría que sería mejor la opción que usted sugirió de 'poner' el archivo que ejecutarlo remotamente.Quizás puedas aclarar por qué esa no era una opción. –

2

Si el script se encuentra en un archivo, se puede leer que, a continuación, pasar su contenido a run. Reescribiendo el ejemplo de Jasper:

from fabric.api import run 

script_file = open('myscript.sh') 
run(script_file.read()) 
script_file.close() 
+1

sí, pero fabric con escriba el archivo de forma remota, y luego ejecútelo, y luego elimínelo como 3 operaciones separadas. –

3

Puede usar las operaciones Fabric. puede usar fabric.operations.put(local_path, remote_path, use_sudo=False,mirror_local_mode=False,mode=None)

para copiar el archivo de script en la ruta remota y luego ejecutarlo.

o,

podría utilizar fabric.operations.open_shell, pero que va a trabajar sólo para la serie de comandos simples, las secuencias de comandos que implica flujo lógico, es mejor utilizar la operación puesto y ejecutar la secuencia de comandos tal como lo hace a nivel local servidor.

1

Por lo que vale, esto funciona perfectamente bien. Utiliza la notación de cadena multilínea de python ''' y el salto de línea de bash (\ antes de la nueva línea). Puede usar puntos y comas para separar las líneas independientes o sólo las operaciones de tuberías como &&

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

Aquí está la salida me sale:

[[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: 
+0

¿cómo puedo pasar la entrada personalizada/valor variable en el comando de ejecución de varias líneas? – Spike

Cuestiones relacionadas