Execute linux command in Python Flask - python

How can I execute linux command inside a Python function? I will run the python file in a linux-based server, and in some functions I want to have something like,
def function():
#execute some commands on the linux system, eg. python /path1/path2/file.py
# Or execute a shell script, eg. /path1/path2/file.sh
What python module do I need to achieve this?
Thanks in advance.

This code will create a flask server and allow you to run commands. You can also capture the output.
import subprocess
from flask import Flask
app = Flask(__name__)
def run_command(command):
return subprocess.Popen(command, shell=True, stdout=subprocess.PIPE).stdout.read()
#app.route('/<command>')
def command_server(command):
return run_command(command)
You can run it by saving above text in server.py
$ export FLASK_APP=server.py
$ flask run

Try the following:
import os, subprocess
# if you do not need to parse the result
def function ():
os.system('ls')
# collect result
def function(command):
out = subprocess.run(
command.split(" "),
stdout=subprocess.PIPE)
return out.stdout

Related

Subprocess run, check_output, Popen returns empty string when I run the script from a batch file and from Task Scheduler

I have a batch file which is running a python script and in the python script, I have a subprocess function which is being ran.
I have tried subprocess.check_output, subprocess.run, subprocess.Popen, all of them returns me an empty string only when running it using a batch file.
If I run it manually or using an IDE, I get the response correctly. Below is the code for subprocess.run:
response = subprocess.run(fileCommand, shell=True, cwd=pSetTableauExeDirectory, capture_output=True)
self.writeInLog(' Command Response: \t' + str(response))
Response is in stdout=b''
When ran in batch file and from task scheduler:
Command Response: CompletedProcess(args='tableau refreshextract
--config-file "Z:\XXX\tableau_config\SampleSuperStore.txt"',
returncode=0, stdout=b'', stderr=b'')
When ran manually or in IDE:
Command Response: CompletedProcess(args='tableau refreshextract
--config-file "Z:\XXX\tableau_config\SampleSuperStore.txt"',
returncode=0, stdout=b'Data source refresh completed.\r\n0 rows uploaded.\r\n', stderr=b'')
Batch file which runs the python program. Parameters are parsed to the python application
SET config=SampleSuperStore.txt
CALL C:\XXX\AppData\Local\Continuum\anaconda3\Scripts\activate.bat
C:\XXX\AppData\Local\Continuum\anaconda3\python.exe Z:\XXX\pMainManual.py "%config%"
Why is that??
--Complete python code---
try:
from pWrapper import wrapper
import sys
except Exception as e:
print(str(e))
class main:
def __init__(self):
self.tableauPath = 'C:\\Program Files\\Tableau\\Tableau 2018.3\\bin\\'
self.tableauCommand = 'tableau refreshextract --config-file'
def runJob(self,argv):
self.manual_sProcess(argv[1])
def manual_sProcess(self,tableauConfigFile):
new_wrapper = wrapper()
new_wrapper.tableauSetup(self.tableauPath,self.tableauCommand)
if new_wrapper.tableauConfigExists(tableauConfigFile):
new_wrapper.tableauCommand(tableauConfigFile)
if __name__ == "__main__":
new_main = main()
new_main.runJob(sys.argv)
Wrapper class:
def tableauCommand(self,tableauConfigFile):
command = self.setTableauExeDirectory + ' ' + self.refreshConfigCommand + ' "' + tableauConfigFile + '"'
self.new_automateTableauExtract.runCommand(tableauConfigFile,command,self.refreshConfigCommand,self.tableauFilePath,self.setTableauExeDirectory)
Automate Class:
def runCommand(self,pConfig,pCommand,pRefreshConfigCommand,pFilePath,pSetTableauExeDirectory):
try:
fileCommand = pRefreshConfigCommand + ' "' + pFilePath + '"'
response = subprocess.run(fileCommand, shell=True, cwd=pSetTableauExeDirectory, capture_output=True)
self.writeInLog(' Command Response: \t' + str(response))
except Exception as e:
self.writeInLog('Exception in function runCommand: ' + str(e))
UPDATE: I initially thought that the bat file was causing this issue but it looks like it works when running manually a batch file but not when it is set on task scheduler
Updated
First of all, if there is a need to run anaconda-prompt by calling activate.bat file, you can simply do as follows:
import subprocess
def call_anaconda_venv():
subprocess.call('python -m venv virtual.env')
subprocess.call('cmd.exe /k /path/venv/Scripts/activate.bat')
if __name__ == "__main__":
call_anaconda_venv()
The result of the above code would be a running instance of anaconda-prompt as required.
Now as Problem Seems Like:
I have a batch file which is running a python script and in the python script, I have a subprocess function which is being run.
I have implemented the same program as required; Suppose we have
Batch File ---> script.bat **** includes a command to run python script i.e test.py. ****
Python Script File ---> test.py **** includes a method to run commands using subprocess. ****
Batch File ---> sys_info.bat **** includes a command which would give the system information of my computer. ****
Now First, script.bat includes a command that will run the required python script as given below;
python \file_path\test.py
pause
Here, pause command is used to prevent auto-closing console after execution. Now we have test.py, python script which includes subprocess method to run required commands and get their output.
from subprocess import check_output
class BatchCommands:
#staticmethod
def run_commands_using_subprocess(commands):
print("Running commands from File: {}".format(commands))
value = check_output(commands, shell=True).decode()
return value
#staticmethod
def run():
commands_from_file = "\file-path\sys_info.bat"
print('##############################################################')
print("Shell Commands using >>> subprocess-module <<<")
print('##############################################################')
values = BatchCommands.run_commands_using_subprocess(commands_from_file)
print(values)
if __name__ == '__main__':
BatchCommands.run()
Now, in the end, I have a sys_info.bat file which includes commands to renew the IP-Adress of my computer. Commands in sys_info.bat file are as follows;
systeminfo
Place multiple commands in sys_info.bat file, then you can also run multiple commands at a time like:
ipconfig/all
ipconfig/release
ipconfig/reset
ipconfig/renew
ipconfig
Before to use the file, set all files directory paths, and run the batch file i.e script.py in command-prompt as follows;
Run command-prompt or terminal as an administrator.
run \file_path\script.py
Here is the result after running the batch file in the terminal.
This is happening because your ide is not running in a shell that works in the way that open subprocess is expecting.
If you set SHELL=False and specify the absolute path to the batch file it will run.
you might still need the cwd if the batch file requires it.

Unable to access / var / tmp in Subprocess via Django

I created a script that outputs the execution result of a shell script to a Web screen using Django and subprocess of python.
Specifically, the following two scripts were created.
test.py
#!/usr/bin/python
import sys,os
import subprocess
import syslog
command_list = ['/bin/sh', '/var/tmp/test.sh']
proc = subprocess.Popen(args=command_list,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=os.path.dirname(command_list[0]),
shell=False)
result = proc.communicate(input=None)
print str( result )
test.sh
#!/bin/bash
echo "begin"
cat /var/tmp/data.txt
data.txt
data1
data2
Unit tests were performed on the two scripts, and they were confirmed to work properly.
However, when I used test.py via Django, test.sh's "cat" command and data.txt existed,
“Cat: /var/tmp/data.txt: No such file or directory” is displayed.
What is the cause?
version
python 2.7.13
Django 1.11.20
When I set PrivateTmp to PrivateTmp = false, httpd can now access / var / tmp.
view /usr/lib/systemd/system/httpd.service
PrivateTmp=false
systemctl daemon-reload
service http restart

How to give cmd automated input via python

I want to give cmd automated input command here is my code
import subprocess
from subprocess import Popen, PIPE
p = subprocess.call("cmd",shell=True)
p = Popen('cmd', stdin=PIPE) # NOTE: no shell=True here
p.communicate(os.linesep.join(["apktool d aalpha.apk"]))
This opens cmd for me in the project directory i.e E:\myproject. Now I have this apktool in my project directory I am trying to run it automatically providing it the apktool run command in a way that I just open my python file and it executes the apktool.
Are you looking for something like this:
import subprocess;
commandA = 'start <path\file.png>';
p = subprocess.Popen(commandA, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT);

How to issue commands on remote hosts in parallel using Fabric without using a fabfile?

I have a Python script that uses Fabric to launch tests on remote hosts, get the otuput file of the tests, and do some parsing. The Python script is not a fabfile.
I would like to launch and run the tests in parallel. I've read about using the "#parallel" decorator but all the examples I've read has the script as a fabfile.
My code is something like this:
from fabric.api import *
# Copy the testfile on each of the hosts. This is sequential, it could be
# done in parallel but doing it in parallel is not that important
def copy_test(host_list, testfile_name):
for x in host_list:
env['host_string'] = x
target_testfile_name = "/tmp/" + testfile_name
put(testfile_name, target_testfile_name)
#parallel # Would this decorator work?
def run_test(host_list, testfile_name):
target_testfile_name = "/tmp/" + testfile_name
for x in host_list:
env['host_string'] = x
run(target_testfile_name)
if __name__ == '__main__':
HOSTS = ['10.10.10.10', '10.10.10.11', '10.10.10.12', '10.10.10.13']
testfile_name = "foo.py"
copy_test(HOSTS, testfile_name)
# I would like to launch run_test() in parallel
run_test(HOSTS, testfile_name)
This is a simplified version of the code. I have not included everything but I pass around configuration information of the hosts so that limits me in using this script as a fabfile where I issue something like:
"fab -H '10.10.10.10' copy_test"
"fab -H '10.10.10.10' run_test" -P
I could execute run_test() using the threading.Threads library but I would rather do that as a last resort.
As you can see, I am not running this as a fabfile.
Is there a way I could execute run_test() using Fabric's parallel execution model without executing my script as a "fabfile"?
I can't comment so i'll put an answer change your main to :
if __name__ == '__main__':
HOSTS = ['10.10.10.10', '10.10.10.11', '10.10.10.12', '10.10.10.13']
testfile_name = "foo.py"
execute(copy_test,HOSTS, testfile_name)
# I would like to launch run_test() in parallel
execute(run_test,HOSTS, testfile_name)
if you call the fonction with execute() and your fonction has the #parallel it'll be launched in parallel

getting subprocess result in variable

I am executing python script using subprocess.call() in pytho script. The script which gets executed using subproecss is a server process which send result back to calling client.
result = subprocess.call('python -m module/coref_resolution/src/coref/corenlp &', shell = True)
Is there any way to receive result from corenlp.py into result variable?
import shlex
cmd = shlex.split('your command')
output = subprocess.Popen( cmd, stdout = subprocess.PIPE).communicate()[0]

Categories

Resources