8

I've created and deployed a Flask App with Apache2 server WSGI in which now would like to run a .sh script from the App. However, from calling from python code, it doesn't execute.

Here is the test.sh:

#!/bin/bash
echo "hi from shell script"

Here is my python flask app code index.py (runs when App is opened) but nothing is printed or executed:

import subprocess
subprocess.call('/var/www/FlaskApp/FlaskApp/scripts/test.sh')

To check that there is not errors in my code, I've check flask error logs, and no errors. Also, I created a script called test_shell_script.py with same python code as above (but not flask app code) and it runs great like this:

# test_shell_script.py
import subprocess
subprocess.call('/var/www/FlaskApp/FlaskApp/scripts/test.sh')

And then run it with python: python3 /var/www/FlaskApp/FlaskApp/test_shell_script.py

hi from shell script

I did change the permissions as well:

-rwxr-xr-x 1 root root 364 Nov 19 17:48 ../scripts/test.sh

What am I missing here which is not allowing my Flask app to run shell commands from the python code?

jKraut
  • 2,325
  • 6
  • 35
  • 48
  • What kind of error do you get? This looks similar: https://stackoverflow.com/questions/4256107/running-bash-commands-in-python, can you try the `subprocess.Popen` suggestion? – Seraf Nov 19 '18 at 19:04
  • Receive no error. I've tried subprocess.Popen and even os.system – jKraut Nov 19 '18 at 19:09
  • You gave permission to root for the file `run_sql.sh` but the file name you are trying to run is `test.sh` – Seraf Nov 19 '18 at 19:15
  • @Seraf - sorry that was a typo, fixed it now – jKraut Nov 19 '18 at 19:19
  • Weird, the user that runs the Flask app is root? (Probably yes but still asking) – Seraf Nov 19 '18 at 19:25
  • @Seraf - yes it's root – jKraut Nov 19 '18 at 19:27
  • I just ran a simple flask app and I'm calling the api endpoint, I see `hi from shell script` on my terminal on the `GET http://127.0.0.1:5000/` can you show me the API endpoint code you are trying to call? I also took permission with `chmod 777`. Also if nothing executes it might be just a typo in the route? Can you make the endpoint return something so you're sure that it's called – Seraf Nov 19 '18 at 19:54

1 Answers1

13

To show command output inside Python, there are two popular methods:

  1. check_output(): It runs command with arguments and return its output. (official documentation)
  2. subprocess.communicate(): Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. (official documentation)

I could view the shell file output using both methods using Python 3.5 in an Ubuntu machine.

app.py:

import subprocess
from subprocess import Popen, PIPE
from subprocess import check_output
from flask import Flask

def get_shell_script_output_using_communicate():
    session = Popen(['./some.sh'], stdout=PIPE, stderr=PIPE)
    stdout, stderr = session.communicate()
    if stderr:
        raise Exception("Error "+str(stderr))
    return stdout.decode('utf-8')

def get_shell_script_output_using_check_output():
    stdout = check_output(['./some.sh']).decode('utf-8')
    return stdout

app = Flask(__name__)

@app.route('/',methods=['GET',])
def home():
    return '<pre>'+get_shell_script_output_using_check_output()+'</pre>'

app.run(debug=True)

some.sh:

#!/bin/bash
echo "hi from shell script"
echo "hello from shell script"

Output screenshot:

enter image description here

Mirko Conti
  • 588
  • 4
  • 17
arshovon
  • 13,270
  • 9
  • 51
  • 69
  • In `get_shell_script_output_using_communicate()` stderr also needs to be decoded using `raise Exception("Error "+str(stderr.decode('utf-8')))` – abulka Mar 12 '21 at 00:50