2016-01-01 20 views
7

Esempio:È possibile utilizzare le funzioni definite nella shell da python?

#!/bin/bash 

function my_test(){ 
    echo this is a test $1 
} 

my_test 1 

python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))" 

uscita:

this is a test 1 
/bin/sh: my_test: command not found 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "/usr/lib/python3.5/subprocess.py", line 629, in check_output 
    **kwargs).stdout 
    File "/usr/lib/python3.5/subprocess.py", line 711, in run 
    output=stdout, stderr=stderr) 
subprocess.CalledProcessError: Command 'my_test 2' returned non-zero exit status 127 
+0

Perché non salvare la funzione 'my_test' in un file di shell separato ed eseguire' python -c' con quella chiamata di script di shell da un altro? – vrs

+1

'/ bin/sh' non supporta la parola chiave' function'. Usa '#!/Bin/bash' (o qualche altra shell) per il tuo shebang. – chepner

+0

Posso chiederti perché dovresti chiamare una funzione definita solo in quella shell? – nacho4d

risposta

9

avete bisogno di esportare la funzione di shell, quindi sarà ereditato da conchiglie bambino.

#!/bin/sh 

function my_test(){ 
    echo this is a test $1 
} 

my_test 1 

export -f my_test 
python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))" 
+0

Grazie, funziona ma mi chiedevo se esistesse un modo per ereditarlo da python senza toccare lo script della shell. Immagino che questo non sia possibile, giusto? – orestisf

+0

Puoi mettere la funzione in un altro script? Quindi puoi usare 'source scriptname' prima di provare a chiamare la funzione. – Barmar

+0

Python non sa nulla di script o funzioni della shell. Dice solo alla shell di eseguire il comando. Se la funzione non è nell'ambiente della shell, non può eseguirla. Quindi devi fare qualcosa per farlo entrare nell'ambiente. – Barmar

0

È possibile utilizzare il modulo os.

import os 
os.system("anything what you would like to do in the shell") 
+0

Non vedo come questo aiuti l'importazione di "python -c"; print (os.system ('my_test 2')) "' output ancora 'sh: my_test: comando non trovato' – orestisf

-2

Il modulo os è sicuramente il modo più semplice e non causa molti problemi in una shell.

2

Esportando una funzione, che non è supportata da tutte le shell, inserisce il codice nel blocco ambiente . Questo è un blocco neutro rispetto alla lingua del testo , che viene copiato da padre a figlio quando viene creato un nuovo processo.

Questa era la base di ShellShock.

Il problema è che i due linguaggi Bash e Python sono completamente diversi, quindi una funzione scritta in uno non sarà direttamente eseguibile dall'altro senza traduzione. Il processo figlio potrebbe eseguire la scansione del blocco di ambiente cercando la funzione, quindi tradurlo e compilarlo nella propria lingua. Un sacco di lavoro e potrebbe facilmente essere un problema di sicurezza.

Se vuoi solo andare Bash-> Python-> Bash, l'esportazione della funzione dal primo script Bash dovrebbe farlo, perché verrà copiata in ogni blocco di ambiente. Tuttavia, in un commento si specifica anche che non si desidera che il primo script lo esporti.

Ebbene si poteva leggere il codice funzione che utilizza Python in una stringa di testo, quindi metterlo nell'ambiente bloccare da soli (questo è ciò che fa export nella shell). Utilizzare il dizionario os.environ.

Il nome effettivo utilizzato dipende dalla versione di Bash. La vulnerabilità di ShellShock ha comportato numerose modifiche. Meglio creare una funzione di test, esportarla, quindi usare per trovare il suo nome completo. Ad esempio sulla mia versione una funzione semplice denominata gash viene visualizzata nel blocco di ambiente come BASH_FUNC_gash%%.

BASH_FUNC_gash%%=() { echo 'Hollow world' 
} 

Ad esempio:

import os 
import subprocess 

fun_body="""() { echo 'Hollow world' 
} 
""" 
os.environ['BASH_FUNC_gash%%'] = fun_body 

p1 = subprocess.Popen('./myscript.sh') 

p1.wait() 

Lo script (myscript.sh) contiene:

#!/bin/bash 
gash 

In alternativa si poteva guardare il vostro disegno di nuovo. Mescolare i linguaggi è sempre problematico, perché non scrivere tutto in Python?

Problemi correlati