I have a very simple problem but cant seem to get a simple solution anywhere.
I have an application running on my Pi which I start by typing into terminal and passing some arguments. For example:
sudo $HOME/Projects/myExampleApp MD_DWNC2378
This results in the console application starting and as expected, can take keyboard inputs.
Now, what I want to do is repeat the process described so far from a python application. My python application should be able to open the myExampleApp in terminal, get a reference to the console window and then direct any commands from my Python application as a keyboard press to myExampleApp.
On a windows platform, pywinauto library does the job.
What is the best option for doing what I described on linux running on my Pi 3?
Any suggestions would be very helpful.
Have a look at https://docs.python.org/2/library/cmd.html for receiving commands. Your application can be run with subprocess as suggested by another user:
import cmd
import sys
import subprocess
class Controller(cmd.Cmd):
cmd = 'while true; do cat /dev/stdin;sleep 1;done'
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
def default(self, cmd):
self.p.stdin.write(cmd+"\n")
a=self.p.stdout.readline()
sys.stdout.write("subprocess returned {}".format(a))
sys.stdout.flush()
if __name__ == '__main__':
try:
Controller().cmdloop()
except:
print('Exit')
Running this script will present you with a CLI interface. Any command sent in will be forwarded to the stdin of your application (simulated by the shell script shown).
If you don't need to process the returning stdout you can skip the self.p.stdout.readline() call. If you need the returning data, it may be beneficial to change the readline() call to read(), this will read until the application sends an EOF.
The sudo requirement of your application can probably be overcome by running the python script with sudo. I'm no security expert, but be aware of the security risks of running the script as sudo, as well as the shell=True parameter of the Popen call.
Related
Use case
On a unix server , when login manually ,opens a command shell of its own to run the command.
I am trying to automate this by using paramiko , however , somehow i am not able to execute the command on command shell using paramiko
What i have done ?
I created a simple script which is able to make connection, but its not executing command on Vshell as the ouput is always coming empty.
import paramiko
import sys
ssh_client=paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=sys.argv[1],port=sys.argv[2],username=sys.argv[3],password=sys.argv[4])
command="show hwid"
stdin,stdout,stderr=ssh_client.exec_command(command)
out=stdout.read()
print out
err=stderr.read()
print err
ssh_client.close()
The same script runs perfectly fine , when its used on server where vshell is not being used
Anyhelp or suggestion on this?
stdin,stdout,stderr=ssh_client.exec_command(command)
Regarding this line of code, I suspect that the SSH server is not properly configured to allow commands to be executed in this way (this is the equivalent of ssh myserver show hwid, rather than typing it into the terminal after login).
You might want to imitate the behaviour of typing the command in after logging into the server, and for that I think this is appropriate:
shell = ssh_client.invoke_shell()
stdin, stdout, stderr = shell.exec_command(command)
Within my python script I need to launch several processes :
1) I need to run another python script ( a flask app with the command python app.py)
2)then I need to launch the command ngrok http 5000 and from this command output get the url on which ngrok is forwarding.
I have tried to use the subprocess module, but when it executes :
subprocess.Popen( "python app/app.py",shell=True)
it launches the interactive shell and blocks the execution of my script.
What is the correct way to achieve this ?
Just instead of Popen function, should to use the call function.
subprocess.call('python app.py', shell=True)
Also see the documentation subprocess docs
I created a python script that I'm running on my server which provides a simple command line interface for running custom configuration scripts. I'm using the cmd module to do this and it's been working great so far:
from cmd import Cmd
class MyPrompt(Cmd):
def do_run1(self, args):
print("running config1")
def do_run2(self, args):
print("running config2")
if __name__ == '__main__':
prompt = MyPrompt()
prompt.prompt = '> '
prompt.cmdloop('Starting prompt...')
I also created another script which will open a TCP server and listen for remote clients in a new thread.Clients can send configuration commands to the server and the server will execute them and send back any output. Right now the client is very basic. It can send anything and does not have access to the nice interface that the cmd module provides.It's also up to the server to parse the received message and figure out the command that the client wants to run (via a long if else parser).
I'm trying to combine these 2 scripts, but I'm having a lot of trouble figuring out the best way to do so. I want to allow someone on the server to use the cmd lscript locally, but I also want the cmd script to accept remote clients and give them access to the cmd prompt at the same time. Also, I need a way for commands entered locally and the commands sent by remote clients to be added to a queue in order for the configuration commands to be run one at a time (each command takes a few minutes to run and cannot be executed in parallel).
Can anyone provide some examples or guidance on how I can extend my cmd script to support remote connections? I have no idea where to start and would be very appreciative of any help!
You're probably better off investigating and learning Ansible.
Whilst I don't have experience with it, it's been highly recommended to me and it is implemented in and uses Python.
The documentation seems to be quite good.
(I don't use it because I haven't had the need to do this sort of thing - I generally do applications development)
On a RHEL 6.7 server running Python 2.6.6 I am trying to start and stop the Apache webserver as an unprivileged user in a Python script.
The command I am using is "sudo service httpd " where parameter is "start", "stop" or "status".
p = subprocess.Popen("sudo service httpd start", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
This line alone does not work. Adding a
p.communicate()
lets the commands work as desired. Can somebody tell me why?
UPDATE:
The sudoers file contains a line that allows my user to run these commands passwordless.
Neither code works (with and without .communicate()).
You should use instead (assuming passwordless sudo for these commands):
import subprocess
subprocess.check_call("sudo service httpd start".split())
The reasons:
subprocess functions do not run the shell by default and therefore the string is interpreted as a name of the command: you should use a list to pass multiple command-line arguments on POSIX
Popen() starts the command and returns immediately without waiting for it to finish i.e., it may happen before httpd is started. Assuming Popen() call is fixed, .communicate() waits for the child process to terminate and therefore it returns after httpd is started (whether it was successful or not).
There are different reasons for that to happen:
1. the user is in sudoers and configured to not insert password.
sudo remembers your password for some time (depending on your system configuration), see: https://unix.stackexchange.com/questions/37299/how-does-sudo-remember-you-already-entered-roots-password
does it work in a brand new terminal session?
I want to write a python script which can launch an application.The application being launched can also read python commands which I am passing through another script.
The problem I am facing is that I need to use two python scripts, one to launch an application and second one to run commands in launched application.
Can I achieve this using a single script? How do I tell python to run next few lines of script in launched application?
In general, you use subprocess.Popen to launch a command from python. If you set it as non-blocking, it'll let you keep running python statements. You also have access to the running subprocesses stdin and stdout so you can interact with the running application.
If I understand what you're asking, it'd look something like this:
import subprocess
app = subprocess.Popen(["/path/to/app", "-and", "args"], stdin=subprocess.PIPE)
app.stdin.write("python command\n")