Execute shell command using Python subprocess - python

I want to execute the following command via a python script:
sudo cat </dev/tcp/time.nist.gov/13
I can execute this command via the command line completely fine. However, when I execute it using subprocess, I get an error:
Command ['sudo','cat','</dev/tcp/time.nist.gov/13'] returned non-zero exit status 1
My code is as follows
import subprocess
subprocess.check_output(['sudo','cat','</dev/tcp/time.nist.gov/13'])
As I mentioned above, executing the command via the command line gives the desired output without any error. I am using the Raspbian Jessie OS. Can someone point me in the right direction?

You don't want to use subprocess for this at all.
What does this command really do? It uses a bash extension to open a network socket, feeds it through cat(1) to reroute it to standard output, and decides to run cat as root. You don't really need the bash extension, or /bin/cat, or root privileges to do any of this in Python; you're looking for the socket library.
Here's an all-Python equivalent:
#!/usr/bin/env python3
import socket
s = socket.create_connection(('time.nist.gov', 13))
try:
print(s.recv(4096))
finally:
s.close()
(Note that all of my experimentation suggests that this connection works but the daytime server responds by closing immediately. For instance, the simpler shell invocation nc time.nist.gov 13 also returns empty string.)

Give this a try:
import subprocess
com = "sudo cat </dev/tcp/time.nist.gov/13"
subprocess.Popen(com, stdout = subprocess.PIPE, shell = True)

Related

How to solve 'AttributeError: 'module' object has no attribute 'run'' from subprocess.run()

I am creating a bash script which calls a python script that in turn runs other processes in bash using subprocess.run(). However, when the bash script runs the python script within it, in the line where subprocess.run is called, I get an error message:
run_metric = subprocess.run(command, shell=True, stdout = subprocess.PIPE, universal_newlines = True)
AttributeError: 'module' object has no attribute 'run'
1) I made sure I ran the script using python 3 by activating a conda environment with python=3.6, which should not bring me any problem to call subprocess.run. The interesting thing is that if I change subprocess.run() to subprocess.Popen() the script works, but I could not work out how to get run_metric.stdout properly.
2) I do not have any subprocess.py file within any directory I am working in
3) the result of print(subprocess.__file__) is showing me that python is not 3.6: /usr/lib/python2.7/subprocess.pyc
Also, I tried to use something like
from subprocess import run
and making sure in both the python script and the function I had import subprocess
The bash script is as follows:
SWC_FOLDER_PATH=$(pwd)
sudo chmod +x /media/leandroscholz/KINGSTON/Results_article/Tracing_data/run_metrics.py
echo "run /media/leandroscholz/Tracing_data/run_metrics.py ${SWC_FOLDER_PATH} /media/leandroscholz/KINGSTON/Results_article/TREEStoolbox_tree_fixed.swc"
python /media/leandroscholz/Tracing_data/run_metrics.py ${SWC_FOLDER_PATH} /media/leandroscholz/TREEStoolbox_tree_fixed.swc
And the python script I run calls a certain function that uses subprocess.run() this way (just part of the code where the problem arises):
import subprocess
import glob
import numpy as np
def compute_metrics(swc_folder_path, gt_file_path):
# first get list of files in swc_folder_path
swc_files = (glob.glob(swc_folder_path+"/*_fixed.swc"))
n_swc_files = len(swc_files)
workflow_dict = gets_workflow_dict(swc_files)
n_images = get_n_images(swc_files)
n_workflows = len(workflow_dict)
for swc in range(0,n_swc_files):
command = "java -jar /home/leandroscholz/DiademMetric.jar -G " + swc_files[swc] +" -T " + gt_file_path
run_metric = subprocess.run(command, shell=True, stdout = subprocess.PIPE, universal_newlines = True)
I am using subprocess.run within python because, in the end, I want to get a string of the run_metric.stdout after running the process in bash so I can later store it in an array and save it to a txt file.
I hope I was sufficiently clear and provided enough information.
Thanks!
After the comments received, I tested the output of print(subprocess.__file__), which showed that python being used was python2.7,
Thus, I changed the call of the python script from python script.py to python3 script.py. I've found this question, which also shows another way to call python programs from terminal.
Running Python File in Terminal

Connecting in SSH in a Python script

I am connected to a first Raspberry Pi (172.18.x.x) in SSH and I would like to launch a script on the first RPI but the script is on another Raspberry Pi (192.168.x.x).
First, I did the configuration to connect without password to the second RPI from the first one.
When I am on the first one, I am launching this command :
ssh pi#192.168.x.x 'sudo python script_RPI2.py'
And this is working correctly, I can check the correct results but I would like to launch this script in another script on the first RPI. So, I put the previous command in the file : script_RPI1.py.
Then, I am launching the script : sudo python script_RPI1.py
And I got the following error :
ssh pi#192.168.x.x
^
SyntaxError: invalid syntax
Anyone has an idea concerning my problem ?
How are you launching the script? What appears from the minimal information you gave is that you are trying or to do that command within the Python interactive interpreter or that you want to execute it in the interpreter and you forgot to surround it with quotes(") in order to make it as a string.
Try to explain a bit more please.
You want to run a bash command:
ssh pi#192.168.x.x 'sudo python script_RPI2.py'
you show do it in a .sh file as in the following example:
#!/bin/sh
ssh pi#192.168.x.x 'sudo python script_RPI2.py'
After saving this file just do ./name_of_file.sh, which will simply run your bash file in the terminal, if you want to run a python script that opens a terminal in another process and executes string that are terminal commands you should look at something like this:
from subprocess import call
call(["ls"])
This will execute ls in another terminal process and return the result back to you. Please check what you want to actually do and decide on one of these paths.
Modified the entire answer and actually put some extra time on the code. The full solution for you to integrate will look something like the code below. Note that the code is setup in a way that you can define the host to connect to, along with the command you want to execute in the remote RPi
import subprocess
import sys
remoteHost="pi#192.168.x.x"
command="python /path/to/script.py"
ssh = subprocess.Popen(["ssh", "%s" % remoteHost, command],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result = ssh.stdout.readlines()
if result == []:
error = ssh.stderr.readlines()
print >>sys.stderr, "ERROR: %s" % error
else:
print result
yourVar = result ### This is where you assign the remote result to a variable

Running a PowerShell cmdlet in a Python script

I have a Python script and I want to run a PowerShell cmdlet. I've looked online and the only thing I can find is running a PowerShell script, but I feel like writing a cmdlet to a script and then dot sourcing it for execution would take a lot longer than needed.
I've tried using subprocess.Popen in the following way:
cmd = subprocess.Popen(['C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe', ps_cmdlet])
But ps_cmdlet is a python string variable with a powershell cmdlet as its value. So, I'm obviously getting a "No such file or directory" error. Is there any way to run a powershell cmdlet in a python script without using things like IronPython?
Thanks!
This works rather well
import subprocess
pl = subprocess.Popen(['powershell', 'get-process'], stdout=subprocess.PIPE).communicate()[0]
print(pl.decode('utf-8'))
Try the following (ps_cmdlet is a python string):
subprocess.call(ps_cmdlet)
edit: Here is an example that will output your machine's ip configuration to Powershell:
ps_cmdlet = 'ipconfig'
subprocess.call(ps_cmdlet)
another edit: Another way that works for me is:
ps_cmdlet = 'whatever command you would enter in powershell'
p = subprocess.Popen(ps_cmdlet,stdout=subprocess.PIPE)
p.communicate()
import subprocess
process = subprocess.Popen([r"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe", "get-process"],
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
process_output = process.read().splitlines()
Above script would help in executing PS Cmdlets from Python.

How to call a self-defined command line function in Python

I'm trying to call a self-defined command line function in python. I defined my function using apple script in /.bash_profile as follows:
function vpn-connect {
/usr/bin/env osascript <<-EOF
tell application "System Events"
tell current location of network preferences
set VPN to service "YESVPN" -- your VPN name here
if exists VPN then connect VPN
repeat while (current configuration of VPN is not connected)
delay 1
end repeat
end tell
end tell
EOF
}
And when I tested $ vpn-connect in bash, vpn-connect works fine. My vpn connection is good.
So I created vpn.py which has following code:
import os
os.system("echo 'It is running.'")
os.system("vpn-connect")
I run it with python vpn.py and got the following output:
vpn Choushishi$ python vpn.py
It is running.
sh: vpn-connect: command not found
This proves calling self-defined function is somehow different from calling the ones that's pre-defined by the system. I have looked into pydoc os but couldn't find useful information.
A way would be to read the ./bash_profile before. As #anishsane pointed out you can do this:
vpn=subprocess.Popen(["bash"],shell=True,stdin= subprocess.PIPE)
vpn.communicate("source /Users/YOUR_USER_NAME/.bash_profile;vpn-connect")
or with os.system
os.system('bash -c "source /Users/YOUR_USER_NAME/.bash_profile;vpn-connect"')
Or try
import subprocess
subprocess.call(['vpn-connect'], shell = True)
and try
import os
os.system('bash -c vpn-connect')
according to http://linux.die.net/man/1/bash

executing an R script from python

I have an R script that makes a couple of plots. I would like to be able to execute this script from python.
I first tried:
import subprocess
subprocess.call("/.../plottingfile.R", shell=True)
This gives me the following error:
/bin/sh: /.../plottingfile.R: Permission denied
126
I do not know what the number 126 means. All my files are on the Desktop and thus I do not think that any special permissions would be needed? I thought that this error may have had something to do with cwd = none but I changed this and I still had an error.
Next I tried the following:
subprocess.Popen(["R --vanilla --args </.../plottingfile.R>"], shell = True)
But this too gave me an error with:
/bin/sh: Syntax error: end of file unexpected.
Most recently I tried:
subprocess.Popen("konsole | /.../plottingfile.R", shell = True)
This opened a new konsole window but no R script was ran. Also, I received the following error:
/bin/sh: /.../plottingfile.R: Permission denied
Thanks.
First thing first, make sure that you have your platttingfile.R script at a place where you can access. Typically it is the same directory.
I read in the internet that there is a utility that comes called RScript which is used to execute R script from the command line. So in order to run the script you would use python like this:
import subprocess
retcode = subprocess.call(['/path/to/RScript','/path/to/plottingfile.R'])
This would return the retcode 0 upon successful completion. If your plottingfile.R is returning some kind of an output, it will be thrown on STDOUT. If it pulling up some GUI, then it would come up.
If you want to capture stdout and stderr, you do it like this:
import subprocess
proc = subprocess.Popen(['/path/to/RScript','/path/to/plottingfile.R'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
Shell error 126 is an execution error.
The permission denied implies that you have a "permission issue" specifically.
Go to the file and make sure R/Python is able to access it.
I would try this out first:
$sudo chmod 777 /.../plottingfile.R
If the code runs, give it the correct but less accessible permission.
If this doesn't work, try changing R to Rscript.
have you tried chmod u+x /pathTo/Rscript.R ?
something likes this work usually for me:
subprocess.Popen("R --vanilla /PATH/plottingfile.R", shell = True)

Categories