Esecuzione di script bash da Python


105

Ho un problema con il seguente codice:

callBash.py:

import subprocess
print "start"
subprocess.call("sleep.sh")
print "end"

sleep.sh:

sleep 10

Voglio che la "fine" venga stampata dopo 10 secondi. (So ​​che questo è un esempio stupido, potrei semplicemente dormire in Python, ma questo semplice file sleep.sh era solo un test)


Ho provato anche con "$! Bin / bash; sleep 10;"
user1638145

Non è chiaro quale problema stia cercando di porre questa persona, ma la domanda dovrebbe probabilmente rimanere perché ha accumulato come risposte un bagaglio storico di ipotesi più o meno valide. Probabilmente anche cercare il tuo errore specifico, e / o leggere questioni connesse come stackoverflow.com/questions/4256107/...
tripleee

Risposte:


91

Rendere eseguibile sleep.sh e aggiungerlo shell=Trueall'elenco dei parametri (come suggerito nelle risposte precedenti) funziona bene. A seconda del percorso di ricerca, potrebbe essere necessario aggiungere ./o un altro percorso appropriato. (Cioè, cambia "sleep.sh"in "./sleep.sh".)

Il shell=Trueparametro non è necessario (sotto un sistema Posix come Linux) se la prima riga dello script bash è un percorso per una shell; per esempio #!/bin/bash,.


48

Se sleep.shha lo shebang #!/bin/she ha i permessi di file appropriati, esegui chmod u+rx sleep.shper assicurarti che sia $PATHinserito, il tuo codice dovrebbe funzionare così com'è:

import subprocess

rc = subprocess.call("sleep.sh")

Se lo script non è nel PERCORSO, specificare il percorso completo, ad esempio, se si trova nella directory di lavoro corrente:

from subprocess import call

rc = call("./sleep.sh")

Se lo script non ha shebang, è necessario specificare shell=True:

rc = call("./sleep.sh", shell=True)

Se lo script non ha autorizzazioni eseguibili e non è possibile modificarlo, ad esempio eseguendolo, os.chmod('sleep.sh', 0o755)è possibile leggere lo script come file di testo e passare invece la stringa al subprocessmodulo:

with open('sleep.sh', 'rb') as file:
    script = file.read()
rc = call(script, shell=True)

34

In realtà, devi solo aggiungere l' shell=Trueargomento:

subprocess.call("sleep.sh", shell=True)

Ma attenzione -

Avvertimento Invocare la shell di sistema con shell = True può essere un rischio per la sicurezza se combinato con un input non attendibile. Vedere l'avvertenza in Argomenti utilizzati di frequente per i dettagli.

fonte


1
Non funzionerà se sleep.shnon è in PATH. E se è nel percorso e ha lo schema corretto, non è necessario shell=True. Vedi la mia risposta
jfs

16

Se qualcuno cerca di chiamare uno script con argomenti

import subprocess

val = subprocess.check_call("./script.sh '%s'" % arg, shell=True)

Ricordarsi di convertire gli argomenti in stringa prima di passare, utilizzando str (arg).

Questo può essere utilizzato per passare tutti gli argomenti desiderati:

subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)

10

Assicurati che sleep.shabbia i permessi di esecuzione ed eseguilo con shell=True:

#!/usr/bin/python

import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"

quindi era la shell = True mi mancava. Potresti spiegare perché non è sufficiente impostare #! Bin / bash nella prima riga dello scricpt sh?
user1638145

3
L'errore in #!bin/bashè mancante /. #!/bin/bashfunziona come noto in una risposta.
James Waldby - jwpat7

9

Se chmod non funziona, prova anche

import os
os.system('sh script.sh')
#you can also use bash instead of sh

prova da me grazie


La os.systemdocumentazione raccomanda specificamente di evitarlo a favore di subprocess(in questi giorni, subprocess.run()). Se non riesci a metterti subprocessal lavoro, è probabile che anche tu abbia problemi os.system().
tripleee

3

Aggiungendo una risposta perché sono stato indirizzato qui dopo aver chiesto come eseguire uno script bash da Python. Si riceve un errore OSError: [Errno 2] file not foundse lo script accetta parametri. Diciamo ad esempio che il tuo script ha preso un parametro sleep time: subprocess.call("sleep.sh 10")non funzionerà, devi passarlo come array:subprocess.call(["sleep.sh", 10])


Devi capire il vero significato dishell=True ma sì, di solito evitarlo è il tuo miglior gioco.
tripleee
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.