2010-07-19 11 views
8

¿Es posible hacer que el fabfile sea independiente?
No me gusta mucho ejecutar la herramienta externa 'fab'. Si me las arreglo para obtener la versión autónoma de fabfile puedo ejecutar el archivo desde el IDE (Eclipse/PyDev), fácilmente depurarlo, configuraciones de proyecto de uso y caminos etc.
¿Por qué no funciona:Fabfile independiente para la tela?

from fabric.api import run 

def host_type(): 
    run('uname -s') 

if __name__ == '__main__': 
    host_type()  

Respuesta

13

Finalmente encontré la solución (¡y es realmente simple!).
En mi fabfile, añadí:

from fabric.main import main 

if __name__ == '__main__': 
    import sys 
    sys.argv = ['fab', '-f', __file__, 'update_server'] 
    main() 

espero que esto ayuda a la gente ...

+0

¿Esto genera un subproceso como la solución de muksie? La razón principal por la que estaba explorando este tema es porque los subprocesos adicionales son algo que queremos eliminar. –

+1

Si modificas tu asignación de sys.argv, funcionará con cualquier conjunto de comandos. sys.argv [0] ya es el nombre del script, así que: sys.argv = ['fab', '-f'] + sys.argv – mqsoh

+0

Funciona siempre que el archivo tenga la extensión '.py'. No encontré la manera de hacerlo funcionar para cualquier extensión. – Wernight

2

esto no es una solución muy agradable, pero funcionará:

import subprocess 

def hello(): 
    print 'Hello' 

if __name__ == '__main__': 
    subprocess.call(['fab', '-f', __file__, 'hello']) 
+0

Sí, no muy agradable (¡pero muy original +1!). Además, no aborda stdio (por ejemplo, solicitud interactiva de contraseña (que supongo que se puede resolver)). –

+0

Secuestrar el comentario superior para decir que en las últimas versiones de la tela puede usar el comando 'execute' en lugar de' subprocess.call' http://fabric.readthedocs.org/en/1.4.3/usage/execution.html# ejecutar – tutuca

3

Si no recuerdo mal, no pude conseguir la API de tela para hacer lo que quería tampoco. Decidí abandonar la capa extra en su totalidad y utilizar Paramiko (la biblioteca SSH subyacente utilizado por Fabric) directamente:

import os 
import paramiko 

ssh = paramiko.SSHClient() 
ssh.load_system_host_keys() 
ssh.load_host_keys(os.path.expanduser('~/.ssh/known_hosts')) 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect('hostname.example.com', 22, 'username', 'password') 
ssh.save_host_keys(os.path.expanduser('~/.ssh/known_hosts')) 
stdin, stdout, stderr = ssh.exec_command('uname -s') 
print stdout.read() 

Si bien hay algunos pasos más involucrados, haciendo de esta manera le permite aprovechar la capa SSH directamente , en lugar de utilizar subprocess para spwan otra instancia de Python, o averiguar la API Fabric. Tengo varios proyectos, tanto web como consola, que usan Paramiko de esta manera y no he tenido demasiados problemas.

Paramiko es extensively documented.

+0

Lamentablemente, esta es la mejor respuesta para mí. ¡Gracias! –

2

bien Sintonicé el ejemplo anterior al pasado a través de argumentos argv es posible que desee pasar a los comandos locales y especificar una lista opcional de comandos por defecto en lugar de un nombre de comando codificado. Tenga en cuenta que el nombre de archivo debe tener una extensión .py o ¡fab no lo detectará como un archivo fab!

#!/usr/bin/env python 
from fabric.api import local 

default_commands = ['hello', ] 

def hello(): 
    print ('hello world') 

def hostname(): 
    local('hostname') 

if __name__ == '__main__': 
    import sys 
    from fabric.main import main 
    sys.argv = ['fab', '-f', __file__,] + default_commands + sys.argv[1:] 
    main() 
2

docs.fabfile.org/en/1.4.0/usage/library.html

"A medida que el artículo menciona, la clave es simplemente que se ejecutan, sudo y los otros operaciones sólo se ven en un lugar cuando se conecta: env.host_string. Todos los otros mecanismos para establecer hosts se interpretan por la herramienta fabulosa cuando se ejecuta, y no importa cuando se ejecuta como una biblioteca. "

Estaba viendo este mismo problema cuando encontré esto. Además, mientras miro recuerdo mencionar que cuando se utiliza en un fabfile, los cambios env no deberían estar en la misma definición que run, sudo. Quién sabe si esto todavía se aplica cuando se usa en el modo "biblioteca".

EDIT: He aquí un ejemplo de dicha aplicación

from fabric.api import env, run 

def main(): 
    run("uname -a") 

def setup(): 
    env.host_string = "[email protected]" 

if __name__ == '__main__': 
    setup() 
    main() 
2
# thanks to aaron, extending his code a little more 
# here is a little bit more of a graceful solution than running subprocess.call, and specifying multiple hosts 

from fabric.api import env, run 

def main(): 
    run("uname -a") 

def setup(): 
    env.hosts = ['host0','host1'] 

if __name__ == '__main__': 
    setup() 
    for host in env.hosts: 
     env.host_string = host 
     main() 
1

Añadir esto a la parte inferior de su archivo fab.

if __name__ == '__main__': 
    from fabric.main import main 
    import sys 

    sys.argv = ['fab', '-f', __file__] + sys.argv[1:] 

    main() 
2

Desde 1.5.0 hay una manera mejor forma de hacerlo que jugar un poco con argv.

import fabric.main 

def main(): 
    fabric.main.main(fabfile_locations=[__file__]) 

if __name__ == "__main__": 
    main() 

Esto también puede ser utilizado como un script de consola en setup.py

0

Ésta es mi versión modificada de Greg's answer que cambia el comportamiento por defecto para mostrar los comandos disponibles en vez de enumerar un montón de opciones de telas.

if __name__ == '__main__': 
    # imports for standalone mode only 
    import sys, fabric.main 

    # show available commands by default 
    if not sys.argv[1:]: 
     sys.argv.append('--list') 

    fabric.main.main(fabfile_locations=[__file__])