Ejecutando el script bash desde dentro de Python


105

Tengo un problema con el siguiente código:

callBash.py:

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

sleep.sh:

sleep 10

Quiero que el "final" se imprima después de 10 segundos. (Sé que este es un ejemplo tonto, simplemente podría dormir dentro de Python, pero este simple archivo sleep.sh fue solo como una prueba)


También lo probé con "$! Bin / bash; sleep 10;"
user1638145

No está claro qué problema está tratando de plantear esta pregunta, pero la pregunta probablemente debería permanecer porque ha acumulado una bolsa de sorpresas histórica de más o menos buenas suposiciones como respuestas. Probablemente también busque su error específico y / o lea preguntas relacionadas como stackoverflow.com/questions/4256107/…
tripleee

Respuestas:


91

Hacer que sleep.sh sea ejecutable y agregarlo shell=Truea la lista de parámetros (como se sugiere en las respuestas anteriores) funciona bien. Dependiendo de la ruta de búsqueda, es posible que también deba agregar ./o alguna otra ruta adecuada. (Es decir, cambie "sleep.sh"a "./sleep.sh".)

El shell=Trueparámetro no es necesario (en un sistema Posix como Linux) si la primera línea del script bash es una ruta a un shell; por ejemplo #!/bin/bash,.


48

Si sleep.shtiene el shebang #!/bin/shy tiene los permisos de archivo adecuados, ejecútelo chmod u+rx sleep.shpara asegurarse de que esté dentro, $PATHentonces su código debería funcionar como está:

import subprocess

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

Si el script no está en la RUTA, especifique la ruta completa, por ejemplo, si está en el directorio de trabajo actual:

from subprocess import call

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

Si el script no tiene shebang, debe especificar shell=True:

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

Si el script no tiene permisos ejecutables y no puede cambiarlo, por ejemplo, al ejecutarlo os.chmod('sleep.sh', 0o755), puede leer el script como un archivo de texto y pasar la cadena al subprocessmódulo en su lugar:

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

34

En realidad, solo debes agregar el shell=Trueargumento:

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

Pero cuidado -

Advertencia Invocar el shell del sistema con shell = True puede ser un peligro para la seguridad si se combina con una entrada no confiable. Consulte la advertencia en Argumentos de uso frecuente para obtener más detalles.

fuente


1
No funcionará si sleep.shno está en PATH. Y si está en el camino y tiene el shebang correcto, entonces no es necesario shell=True. Vea mi respuesta
jfs

16

Si alguien busca llamar a un script con argumentos

import subprocess

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

Recuerde convertir los argumentos en una cadena antes de pasar, usando str (arg).

Esto se puede usar para pasar tantos argumentos como desee:

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

10

Asegúrese de que sleep.shtenga permisos de ejecución y ejecútelo con shell=True:

#!/usr/bin/python

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

así que fue el caparazón = Verdad que me perdí. ¿Podría explicar por qué no es suficiente establecer #! Bin / bash en la primera línea de sh scricpt?
user1638145

3
#!bin/bashFalta el error en /. #!/bin/bashfunciona como lo noto en una respuesta.
James Waldby - jwpat7

9

Si chmod no funciona, intente también

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

prueba por mi gracias


La os.systemdocumentación recomienda específicamente evitarlo a favor de subprocess(estos días subprocess.run()). Si no puede ir subprocessa trabajar, es probable que también tenga problemas os.system().
tripleee

3

Agregando una respuesta porque me dirigieron aquí después de preguntar cómo ejecutar un script bash desde python. Recibe un error OSError: [Errno 2] file not foundsi su secuencia de comandos admite parámetros. Digamos, por ejemplo, que su script tomó un parámetro de tiempo de suspensión: subprocess.call("sleep.sh 10")no funcionará, debe pasarlo como una matriz:subprocess.call(["sleep.sh", 10])


Tienes que entender el significado real deshell=True pero sí, normalmente evitarlo es tu mejor jugada.
tripleee
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.