Запуск сценария bash из Python

111

У меня проблема со следующим кодом:

callBash.py:

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

sleep.sh:

sleep 10

Я хочу, чтобы «конец» печатался через 10 секунд. (Я знаю, что это глупый пример, я мог бы просто спать в python, но этот простой файл sleep.sh был просто тестом)

user1638145
источник
Я также пробовал это с "$!
Bin
Неясно, о какой проблеме пытается спросить этот вопрос, но вопрос, вероятно, должен остаться, потому что он накопил исторический мешок с более или менее хорошими догадками в качестве ответов. Возможно, также найдите свою конкретную ошибку и / или прочтите связанные вопросы, такие как stackoverflow.com/questions/4256107/…
tripleee

Ответы:

93

Создание исполняемого файла sleep.sh и добавление shell=Trueв список параметров (как было предложено в предыдущих ответах) работает нормально. В зависимости от пути поиска вам также может потребоваться добавить ./или какой-либо другой подходящий путь. (То есть сменить "sleep.sh"на "./sleep.sh".)

shell=TrueПараметр не нужен ( в рамках системы Posix , как Linux) , если первая строка сценария Баш является путь к оболочке; например #!/bin/bash,.

Джеймс Уолдби - jwpat7
источник
50

Если sleep.shесть shebang #!/bin/shи соответствующие права доступа chmod u+rx sleep.shк файлу - запустите, чтобы убедиться, что он есть, $PATHтогда ваш код должен работать как есть:

import subprocess

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

Если скрипт отсутствует в PATH, укажите полный путь к нему, например, если он находится в текущем рабочем каталоге:

from subprocess import call

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

Если в скрипте нет shebang, необходимо указать shell=True:

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

Если у скрипта нет прав на исполнение и вы не можете его изменить, например, запустив его, os.chmod('sleep.sh', 0o755)вы можете прочитать скрипт как текстовый файл и subprocessвместо этого передать строку в модуль:

with open('sleep.sh', 'rb') as file:
    script = file.read()
rc = call(script, shell=True)
jfs
источник
34

На самом деле вам просто нужно добавить shell=Trueаргумент:

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

Но будьте осторожны -

Предупреждение. Вызов системной оболочки с параметром shell = True может представлять угрозу безопасности в сочетании с ненадежным вводом. См. Предупреждение в разделе "Часто используемые аргументы".

источник

зенпой
источник
1
Это не сработает, если sleep.shего нет в PATH. И если он находится на пути и у него правильный шебанг, тогда он вам не нужен shell=True. См. Мой ответ
jfs
18

Если кто-то ищет вызов скрипта с аргументами

import subprocess

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

Не забудьте преобразовать аргументы в строку перед передачей, используя str (arg).

Это можно использовать для передачи любого количества аргументов:

subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)
Понмуди В.Н.
источник
10

Убедитесь, что у sleep.shнего есть разрешения на выполнение, и запустите его с помощью shell=True:

#!/usr/bin/python

import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"
Адам Матан
источник
так это была оболочка = правда я пропустил. Не могли бы вы объяснить, почему недостаточно указать #! Bin / bash в первой строке sh scricpt?
user1638145 06
3
Ошибка #!bin/bashотсутствует /. #!/bin/bashработает как отмечаю в ответе.
Джеймс Уолдби - jwpat7
10

Если chmod не работает, попробуйте

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

тест мной спасибо

Гарри, 1992
источник
В os.systemдокументации специально рекомендуется избегать этого в пользу subprocess(в наши дни subprocess.run()). Если вы не можете приступить subprocessк работе, скорее всего, у вас тоже будут проблемы os.system().
Tripleee
3

Добавление ответа, потому что меня направили сюда после того, как я спросил, как запустить сценарий bash из python. Вы получите сообщение об ошибке, OSError: [Errno 2] file not foundесли ваш скрипт принимает параметры. Скажем, например, ваш скрипт принял параметр времени сна: subprocess.call("sleep.sh 10")не будет работать, вы должны передать его как массив:subprocess.call(["sleep.sh", 10])

Мэтью Лэнг
источник
Вы должны понимать истинное значение этого,shell=True но да, обычно избегать этого - ваша лучшая игра.
Tripleee