Uruchamianie skryptu bash z poziomu Pythona

106

Mam problem z następującym kodem:

callBash.py:

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

sleep.sh:

sleep 10

Chcę, aby „koniec” został wydrukowany po 10 sekundach. (Wiem, że to głupi przykład, mógłbym po prostu spać w Pythonie, ale ten prosty plik sleep.sh był tylko testem)

user1638145
źródło
Wypróbowałem też z „$! Bin / bash; sleep 10;”
user1638145,
Nie jest jasne, o jaki problem próbuje zapytać ten questien, ale pytanie powinno prawdopodobnie pozostać, ponieważ zebrało historyczną woreczek mniej lub bardziej dobrych domysłów jako odpowiedzi. Prawdopodobnie wyszukaj również swój konkretny błąd i / lub przeczytaj powiązane pytania, takie jak stackoverflow.com/questions/4256107/ ...
tripleee

Odpowiedzi:

91

Uruchamianie sleep.sh i dodanie shell=Truedo listy parametrów (jak sugerowano w poprzednich odpowiedziach) działa poprawnie. W zależności od ścieżki wyszukiwania może być konieczne dodanie ./lub innej odpowiedniej ścieżki. (Tj. Zmień "sleep.sh"na "./sleep.sh".)

shell=TrueParametr nie jest potrzebny (w systemie Linux) Posix jak gdyby pierwsza linia skryptu bash jest ścieżka do powłoki; na przykład #!/bin/bash.

James Waldby - jwpat7
źródło
48

Jeśli sleep.shma shebang #!/bin/shi ma odpowiednie uprawnienia do plików - uruchom, chmod u+rx sleep.shaby upewnić się, że jest w $PATHśrodku, a Twój kod powinien działać tak, jak jest:

import subprocess

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

Jeśli skryptu nie ma w PATH, podaj pełną ścieżkę do niego, np. Jeśli znajduje się w bieżącym katalogu roboczym:

from subprocess import call

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

Jeśli skrypt nie ma shebang, musisz określić shell=True:

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

Jeśli skrypt nie ma uprawnień do wykonywania i nie możesz go zmienić, np. Uruchamiając, os.chmod('sleep.sh', 0o755)możesz przeczytać skrypt jako plik tekstowy i subprocesszamiast tego przekazać ciąg do modułu:

with open('sleep.sh', 'rb') as file:
    script = file.read()
rc = call(script, shell=True)
jfs
źródło
34

Właściwie wystarczy dodać shell=Trueargument:

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

Ale strzeż się -

Ostrzeżenie Wywołanie powłoki systemowej z parametrem shell = True może stanowić zagrożenie bezpieczeństwa, jeśli jest połączone z niezaufanymi danymi wejściowymi. Szczegółowe informacje można znaleźć w ostrzeżeniu w sekcji Często używane argumenty.

źródło

zenpoy
źródło
1
Nie zadziała, jeśli sleep.shnie ma go w PATH. A jeśli jest na ścieżce i ma prawidłowy huk, nie potrzebujesz shell=True. Zobacz moją odpowiedź
jfs
16

Jeśli ktoś szuka wywołania skryptu z argumentami

import subprocess

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

Pamiętaj, aby przekonwertować argumenty na łańcuchy przed przekazaniem, używając str (arg).

Można tego użyć do przekazania dowolnej liczby argumentów:

subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)
Ponmudi VN
źródło
10

Upewnij się, że sleep.shma uprawnienia do wykonywania i uruchom go z shell=True:

#!/usr/bin/python

import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"
Adam Matan
źródło
więc to była powłoka = prawda przegapiłem. Czy możesz wyjaśnić, dlaczego nie wystarczy ustawić #! Bin / bash w pierwszej linii sh scricpt?
user1638145
3
#!bin/bashBrakuje błędu w /. #!/bin/bashdziała tak, jak zaznaczam w odpowiedzi.
James Waldby - jwpat7
9

Jeśli chmod nie działa, spróbuj także

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

test przeze mnie dzięki

Harry1992
źródło
os.systemDokumentacja wyraźnie zaleca unikanie go na korzyść subprocess(tych dniach subprocess.run()). Jeśli nie możesz dostać się subprocessdo pracy, prawdopodobnie będziesz miał również problemy os.system().
tripleee
3

Dodanie odpowiedzi, ponieważ skierowano mnie tutaj po zapytaniu, jak uruchomić skrypt bash z Pythona. OSError: [Errno 2] file not foundJeśli twój skrypt przyjmuje parametry, pojawia się błąd . Powiedzmy na przykład, że Twój skrypt przyjął parametr czasu uśpienia: subprocess.call("sleep.sh 10")nie zadziała, musisz przekazać go jako tablicę:subprocess.call(["sleep.sh", 10])

Matthew Lang
źródło
Musisz zrozumieć rzeczywiste znaczenie,shell=True ale tak, zazwyczaj unikanie tego jest najlepszą grą.
tripleee