2011-11-04 4 views
13

In Fabric, quando tento di utilizzare qualsiasi alias 'o funzione dal mio file .bash_profile, non vengono riconosciuti. Ad esempio il mio .bash_profile contiene alias c='workon django-canada', quindi quando digito c in iTerm o Terminal, viene eseguito workon django-canada.Perché Fabric non vede il mio .bash_profile?

mio fabfile.py contiene

def test(): 
    local('c') 

Ma quando provo fab test getta questo a me: [localhost] locale: c

/bin/sh: c: command not found 

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

Aborting. 

Funzioni tessuto funzionano bene. Devo specificare il mio profilo bash da qualche parte nel tessuto?

risposta

21

MODIFICA - Come risulta, questo è stato risolto in Fabric 1.4.4. Dal changelog:

[Caratteristica] #725: Aggiornamento locale di consentire di esclusione di cui guscio locale viene utilizzato. Grazie a Mustafa Khattab.

Quindi la domanda originale sarebbe stato riparato in questo modo:

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

ho lasciato la mia risposta originale al di sotto, che riguarda solo la versione in tessuto < 1.4.4.


Perché locale non utilizza bash. Puoi vederlo chiaramente nell'output

/bin/sh: c: command not found 

Vedere? Sta usando /bin/sh invece di /bin/bash. Questo perché il comando local di Fabric si comporta in modo leggermente diverso internamente rispetto a run. Il comando local è essenzialmente un wrapper attorno alla classe python subprocess.Popen.

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

E qui è il tuo problema. Il valore predefinito del Popen è /bin/sh. È possibile specificare una shell diversa se si sta chiamando il costruttore di Popen da soli, ma lo si sta usando tramite Fabric. E sfortunatamente per te, Fabric non ti dà modo di passare una shell, come /bin/bash.

Mi dispiace che non offra una soluzione, ma dovrebbe rispondere alla tua domanda.

EDIT

Ecco il codice in questione, tirato direttamente dal local funzione di tessuto definita nel file operations.py:

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

Come si può vedere, non passa in qualche cosa per la parola chiave eseguibile . Questo fa sì che usi l'impostazione predefinita, che è/bin/sh. Se fosse usato bash, sarebbe il seguente:

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

Ma non è così.Ecco perché nella documentazione per locale si dice quanto segue:

local è semplicemente un comodo wrapper attorno all'utilizzo del modulo di subprocesso Python integrato con shell = True attivato. Se devi fare qualcosa di speciale, considera l'utilizzo del modulo di sottoprocesso direttamente.

+1

Ma il file [Fabric docs] (http://docs.fabfile.org/en/0.9.0/usage/env.html#shell) dice: "shell Predefinito: **/bin/bash ** -l -c Valore utilizzato come shell wrapper nell'esecuzione di comandi con ad esempio esecuzione. Deve essere in grado di esistere nel modulo "" - ad esempio il predefinito utilizza l'opzione -c di Bash che accetta una stringa di comando come valore." –

+1

Sì, i documenti si riferiscono ai comandi run e sudo. Il comando locale funziona diversamente da quelli dietro le quinte. Ho modificato la risposta per mostrare il codice in questione. –

+0

Grazie per il chiarimento. È stato molto istruttivo –

4

Una soluzione è semplicemente quello di avvolgere qualsiasi comando si dispone intorno ad un comando bash:

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

Se avete bisogno di fare un sacco di questi, prendere in considerazione la creazione di un custom context manager.

+0

Grazie, funziona alla grande. –

0

Sembra che tu stia cercando di utilizzare virtualenvwrapper localmente. Avrai bisogno di rendere la vostra stringa di comando locale simile a questa:

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

Ecco un esempio dal sottoscritto that does that for you in a context manager.