2011-11-04 19 views
13

En Fabric, cuando trato de usar cualquier alias o funciones de mi archivo .bash_profile, no se reconocen. Por ejemplo, mi .bash_profile contiene alias c='workon django-canada', así que cuando escribo c en iTerm o Terminal, se ejecuta workon django-canada.¿Por qué Fabric no ve mi .bash_profile?

Mi fabfile.py contiene

def test(): 
    local('c') 

Pero cuando intento fab test arroja esto a mí: [localhost] locales: c

/bin/sh: c: command not found 

Fatal error: local() encountered an error (return code 127) while executing 'c' 

Aborting. 

Otras funciones de la tela funcionan bien. ¿Debo especificar mi perfil de bash en alguna parte de la estructura?

Respuesta

21

EDITAR - Como resultado, esto se corrigió en Fabric 1.4.4. Desde el registro de cambios:

[Función] #725: Se actualizó localmente para permitir la anulación de qué shell local se utiliza. Gracias a Mustafa Khattab.

Así que la pregunta original se fija de esta manera:

def test(): 
    local('c', shell='/bin/bash') 

He dejado mi respuesta original a continuación, que se refiere únicamente a la versión de tela < 1.4.4.


Porque local no usa bash. Puede verlo claramente en su salida

/bin/sh: c: command not found 

Ver? Está utilizando /bin/sh en lugar de /bin/bash. Esto se debe a que el comando local de Fabric se comporta de forma un poco diferente internamente que run. El comando local es esencialmente un contenedor alrededor de la clase subprocess.Popen python.

http://docs.python.org/library/subprocess.html#popen-constuctor

Y aquí es su problema. Popen se establece de manera predeterminada en /bin/sh. Es posible especificar un shell diferente si está llamando al constructor Popen, pero lo está usando a través de Fabric. Y desafortunadamente para ti, Fabric no te da ningún medio para pasar en un shell, como /bin/bash.

Lo siento, pero no le ofrece una solución, pero debería responder a su pregunta.

EDITAR

Aquí está el código en cuestión, sacó directamente de la función del tejido local definido en el archivo operations.py:

p = subprocess.Popen(cmd_arg, shell=True, stdout=out_stream, 
    stderr=err_stream) 
(stdout, stderr) = p.communicate() 

Como se puede ver, que no pasa en nada por la palabra clave ejecutable . Esto hace que use el valor predeterminado, que es/bin/sh. Si usara bash, se vería así:

p = subprocess.Popen(cmd_arg, shell=True, stdout=out_stream, 
    stderr=err_stream, executable="/bin/bash") 
(stdout, stderr) = p.communicate() 

Pero no es así.Por eso dicen lo siguiente en la documentación para local:

local es simplemente una envoltura de conveniencia alrededor del uso del módulo de subproceso incorporado Python con shell = True activated. Si necesita hacer algo especial, considere usar el módulo de subproceso directamente.

+1

Pero los [documentos de la tela] (http://docs.fabfile.org/en/0.9.0/usage/env.html#shell) dicen: "shell Predeterminado: **/bin/bash ** -l -c Valor utilizado como envoltorio de shell al ejecutar comandos con, por ejemplo, ejecutar. Debe poder existir en el formulario "" - por ejemplo, el valor predeterminado utiliza la opción -c de Bash que toma una cadena de comando como su valor." –

+1

Sí, los documentos se refieren a los comandos run y sudo. El comando local funciona diferente de los que están detrás de las escenas. He editado la respuesta para mostrar el código en cuestión. –

+0

Gracias por la aclaración. Fue muy informativo –

4

Una solución es simplemente para envolver el comando que tiene a su alrededor un comando bash:

@task 
def do_something_local(): 
    local("/bin/bash -l -c 'run my command'") 

Si tiene que hacer un montón de ellos, considerar la creación de un custom context manager.

+0

Gracias, esto funciona genial. –

0

Parece que está intentando usar virtualenvwrapper localmente. Tendrá que hacer su cadena de comando local de aspecto:

local("/bin/bash -l -c 'workon django-canada && python manage.py runserver'") 

He aquí un ejemplo por su servidor that does that for you in a context manager.

Cuestiones relacionadas