Connecting in SSH in a Python script - python

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

Related

Python script located in rc.local on Raspbian is not getting started on startup

This is my Python script (main.py):
#! /usr/bin/env python
import time
# ..... some file imports from the same folder .....
try:
# .... Some setup code
while True:
if turnOffRequestHandler.turnOffIsRequested():
break;
time.sleep(1)
except BaseException as e:
pass
finally:
# ..... Some code to dispose resources
And the way I try to invoke it on each startup was to first edit rc.local to become similar to this:
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
python3 /home/pi/Desktop/ProjectFolder/sample/main.py &
exit 0
and then make my python script executable by navigating to the containing directory and executing the following command:
chmod 755 main.py
And then, I expected after a reboot of the system to get my script running. I can not tell if it runs or not. What I can tell is that it is supposed to call some web endpoints. I am now wondering if it actually got executed but the wifi just did not get connected yet.
How could I diagnose that? Because, when I try to execute manually (after the system booted up and Wifi got connected) like this:
pi#raspberrypi:~ $ /etc/rc.local
it is getting it started and everything works as expected.
EDIT: Is it possible to be something related to the fact that the script that I try to execute makes a reference inside of it to files which are located in the same folder (which is different than /etc/..)?.
I would try simple bash script with 'echo "something" >> to_file'.
you can redirect your output (like print "something") to a file while using the script.
change your script like this:
python3 /home/pi/Desktop/ProjectFolder/sample/main.py &> logfile.txt
and in your file use normal print to print in your file with 1 problem.
you have to flush the output while your code is running in order to see output file:
import sys
sys.stdout.flush()
edit
if you are using python 3.3 or above, there is an alternaive approach - print has argument to flush the output.

Execute shell command using Python subprocess

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)

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.

Create an alias in bash when exiting a python script

I have written a shell in python (using the cmd module) and when using this shell, certain information about commands run ect. is outputted to a text file. I would like to write a piece of code that creates an alias to view the text file in my bash shell (eg as if I had executed the following command:
alias latest.trc='less <path to file>
My best current effort is:
x="alias %s = 'less %s'" % (<alias name>, <path>)
y=shlex.split(x)
atexit.register(subprocess.call, y)
This works to execute some commands on exit, eg if x="echo 'bye'" but I get the error
OSError: [Errno 2] No such file or directory
The path I am entering is certainly valid and if I run x directly from the command line it works.
Any help either with why my code is hitting an error or a better way to achieve the same effect would be greatly appreciated.
You get an error because alias is a bash command, not an executable. You must run subprocess.call inside a shell:
import subprocess
import atexit
import shlex
x="alias %s = 'less %s'" % ('a', 'whatever')
y=shlex.split(x)
atexit.register(lambda args: subprocess.call(args, shell=True), y)
But, given the fact that subprocess spawns a new process, whatever changes are made to the environment it runs into, are lost on exit.
You'd better instead create a file where you put all these aliases and source it by hand when you need to use them.

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