24

I am trying to run both Python and bash commands in a bash script. In the bash script, I want to execute some bash commands enclosed by a Python loop:

#!/bin/bash

python << END
for i in range(1000):
    #execute‬ some bash command such as echoing i
END

How can I do this?

alex
  • 6,818
  • 9
  • 52
  • 103
Md. Zakir Hossan
  • 517
  • 2
  • 6
  • 17

3 Answers3

41

Use subprocess, e.g.:

import subprocess
# ...

subprocess.call(["echo", i])

There is another function like subprocess.call: subprocess.check_call. It is exactly like call, just that it throws an exception if the command executed returned with a non-zero exit code. This is often feasible behaviour in scripts and utilities.

subprocess.check_output behaves the same as check_call, but returns the standard output of the program.


If you do not need shell features (such as variable expansion, wildcards, ...), never use shell=True (shell=False is the default). If you use shell=True then shell escaping is your job with these functions and they're a security hole if passed unvalidated user input.

The same is true of os.system() -- it is a frequent source of security issues. Don't use it.

dom0
  • 7,356
  • 3
  • 28
  • 50
  • 9
    Why is not recommendable to use import os? – Luis Ramon Ramirez Rodriguez Apr 25 '16 at 01:27
  • @LuisRamonRamirezRodriguez, `os.system()` provides less control than the `subprocess.Popen` interface -- most importantly, it provides no way to pass data out-of-band from code (or to provide a literal argv array), making it hard to avoid shell injection vulnerabilities. – Charles Duffy Jan 26 '17 at 16:44
  • 1
    @dom0, `shell=True` is the wrong thing for your `subprocess.call(["echo", i], shell=True)` example: The shell script that's run is just `echo`, with no arguments, and the `i` is passed as an argument to the shell that the script doesn't refer to. – Charles Duffy Jan 26 '17 at 16:45
  • I edited the answer so as to propose the secure way first. – dom0 May 18 '17 at 20:57
18

Look in to the subprocess module. There is the Popen method and some wrapper functions like call.

  • If you need to check the output (retrieve the result string):

    output = subprocess.check_output(args ....)
    
  • If you want to wait for execution to end before proceeding:

    exitcode = subprocess.call(args ....)
    
  • If you need more functionality like setting environment variables, use the underlying Popen constructor:

    subprocess.Popen(args ...)
    

Remember subprocess is the higher level module. It should replace legacy functions from OS module.

1

I used this when running from my IDE (PyCharm).

import subprocess

subprocess.check_call('mybashcommand', shell=True)
Ger Mc
  • 630
  • 3
  • 11
  • 22