Running Bash Script from Within Python

I have a problem with the following code:

callBash.py:

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

sleep.sh:

sleep 10

I want the "end" to be printed after 10s. (I know that this is a dumb example, I could simply sleep within python, but this simple sleep.sh file was just as a test)

2

7 Answers

Making sleep.sh executable and adding shell=True to the parameter list (as suggested in previous answers) works ok. Depending on the search path, you may also need to add ./ or some other appropriate path. (Ie, change "sleep.sh" to "./sleep.sh".)

The shell=True parameter is not needed (under a Posix system like Linux) if the first line of the bash script is a path to a shell; for example, #!/bin/bash.

0

If sleep.sh has the shebang #!/bin/sh and it has appropriate file permissions -- run chmod u+rx sleep.sh to make sure and it is in $PATH then your code should work as is:

import subprocess

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

If the script is not in the PATH then specify the full path to it e.g., if it is in the current working directory:

from subprocess import call

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

If the script has no shebang then you need to specify shell=True:

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

If the script has no executable permissions and you can't change it e.g., by running os.chmod('sleep.sh', 0o755) then you could read the script as a text file and pass the string to subprocess module instead:

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

Actually, you just have to add the shell=True argument:

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

But beware -

Warning Invoking the system shell with shell=True can be a security hazard if combined with untrusted input. See the warning under Frequently Used Arguments for details.

source

1

If someone looking for calling a script with arguments

import subprocess

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

Remember to convert the args to string before passing, using str(arg).

This can be used to pass as many arguments as desired:

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

Make sure that sleep.sh has execution permissions, and run it with shell=True:

#!/usr/bin/python

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

If chmod is not working then you can also try:

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

Adding an answer because I was directed here after asking how to run a bash script from python. You receive an error OSError: [Errno 2] file not found if your script takes in parameters. Lets say for instance your script took in a sleep time parameter: subprocess.call("sleep.sh 10") will not work, you must pass it as an array: subprocess.call(["sleep.sh", 10])

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest