How to execute Shell Script from Flask App [duplicate] - python

This question already has answers here:
Store output of subprocess.Popen call in a string [duplicate]
(15 answers)
Closed 4 years ago.
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?

To show command output inside Python, there are two popular methods:
check_output(): It runs command with arguments and return its output. (official documentation)
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:

Related

Start a background shell script from python

I would like to connect a remote machine and run background script in that machine from python.
I tried:
os.system("ssh root#10.0.0.1 \' nohup script.sh & \')
But it seems not working. And if I put nohup in script.sh, and simply run
os.system("ssh root#10.0.0.1 \' script.sh \'")
The nohup command would not work in either cases.
I'm confused why so, and is there anybody knows how to do background job from python or it's just impossible doing it this way?
What kind of errors are you getting? What version of Python are you using?
You should take a look at this Python subprocess - run multiple shell commands over SSH
import subprocess
sshProcess = subprocess.Popen(["ssh", "root#10.0.0.1"],
stdin=subprocess.PIPE,
stdout = subprocess.PIPE,
universal_newlines=True,
bufsize=0)
sshProcess.stdin.write("nohup script.sh &")
For example you have a local script (python, bash, etc. Here I am demonstrating you using a python script)
First you create a python file locally. Lets say hello.py
# 'hello.py'
import os
print os.system('hostname')
Secondly now a python script which would execute the above hello.py on a remote machine
import pathos
copy = pathos.core.copy('hello.py', destination='abc.remote.com:~/hello.py')
exec = pathos.core.execute('python hello.py', host='.remote.com')
print exec.response()

Run Python Script Automatically at Startup - Ubuntu 16.04

I'm on Ubuntu 16.04.1, and I have a python script to download image files from websites, the codes are as follows:
import sys
import os
import time
import json
import shlex, subprocess
import signal
import random
R = 0
r = 0
targets = ['192.0.78.13', '134.109.133.7', '216.58.212.227', '54.246.159.107', '185.60.216.35', '98.136.103.24']
if __name__ == "__main__":
while True:
cmd = 'wget -A pdf,jpg,png -m -p -E -k -K -np --delete-after '
R = random.randint(0,5)
cmd += targets[R]
args = shlex.split(cmd)
p = subprocess.Popen(args, shell=False)
time.sleep(2.0)
# killing all processes in the group
os.kill(p.pid, signal.SIGTERM)
if p.poll() is None: # Force kill if process
os.kill(p.pid, signal.SIGKILL)
r = random.randint(3,20)
time.sleep(r-1)
it run perfectly with command "python webaccess.py", now I want to run it automatically on startup in the background.
I've tried two methods but all of them are fail (the scripty does not run):
Use crontab using the guide here: Run Python script at startup in Ubuntu
#reboot python /bin/web1.py &
Edit the rc.local using the guide here: https://askubuntu.com/questions/817011/run-python-script-on-os-boot
python /bin/web1.py &
Is there any way to solve this?
Thank you in advance.
your rc.local method should work, check using your full python path. if that is default /usr/bin/python
/use/bin/python your_file_py
also you said you verified python webaccess.py do verify it from outside the folder of script.
also note that scrips in rc.local are executed by root
so check path_to_python python_file from root #

How can I run my Flask app step by step to debug it?

I want to run IPython interactively while running my Flask app. I tried ipython -i app.py but I don't get a prompt until after the app exits. I want to do this so I can debug each step of the program. How can I run my app and be able to examine it?
The -i flag runs the given program and then puts you in an interactive session after it has run. There is no way to debug the program using this flag.
Instead, you want to use a debugger. python -m pdb app.py will start pdb, a console debugger. There are other debuggers available, such as the graphical one built into IDEs such as PyCharm and PyDev, or more advanced console ones such as pudb.
Implemented with thread
from flask import Flask
import thread
data = 'foo'
app = Flask(__name__)
#app.route("/")
def main():
return data
def flaskThread():
app.run()
if __name__ == "__main__":
thread.start_new_thread(flaskThread,())
And open the IPython Command prompt and type the command run -i filename.py

python throwing ImportError while running from apache

I have a python script in my cgi-bin where I am calling another perl script which in turn calls a python script to perform some tests. It works perfectly fine when I run it from the command line, but throws import error: no module named paramiko when I run from Apache. I have even printed:
import site
sys.path.append('/usr/local/lib/python2.7/site-packages/')
import paramiko
from paramiko import SSHClient
in my python script, but I get an error when I run from browser.
My python code which calls the perl script is as below:
def execute_ACL():
print "Going to execute"
for line in run_command("perl systemtcpcheck.pl acl/config_files/G2AXStageg2ax-stage.hosts acl/config_files/G2AXStageg2ax-live.tests"):
print(line)
def run_command(command):
p = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
return p.communicate()
Can anyone please suggest a solution ?

processing output of time command in a python script

I am trying to write a python script that benchmarks several pieces of code. The issue is when the script is run the output of the command id different from what I would get it I run it directly at bash prompt.
Here is the code for the python script
import subprocess
import re
import os
app = os.getcwd() + "/" + "myapp"
testPopen = subprocess.Popen(args=['/usr/bin/time',app],
stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=False)
testPopen.wait()
Here is the ouput of above code
real 1.0
user 0.8
sys 0.0
When you run time myapp from the bash prompt, you are using bash's time command. (Type help time to see that bash understands it as a bash command.)
When you run the python script you are using /usr/bin/time, which is a different program. (Type man time or which time to see that time is also a program. How confusing!)
To get the python script to use the bash time command:
import shlex
testPopen = subprocess.Popen(shlex.split('bash -c "time {a}"'.format(a = app)),
stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=False)
out,err = testPopen.communicate()
print(err)

Categories

Resources