Short version:
How to execute a linux command which requires input after execution using Python?
Long version:
I am building some fancy website stuff using Python to give my SVN server a way to be managed easier. (I can't remember all the linux commands)
So I want to create, delete and edit repo's and users using a webpage. I just came to the problem I do not know how to execute the following command using Python:
sudo htdigest /etc/apache2/dav_svn.htdigest "Subversion Repo" [username]
Well I know how to execute the command with os.system() or subprocess.Popen(), but the problem is that once that command is executed it asks to enter a password twice before continuing. Using multiple calls using os.system() or subprocess.Popen() won't work since they just create a new shell.
Is there a way in Python to let an argument be used once it is required?
It all depends, you can either use popen and handle bidirectional communication or if you are just waiting for known prompts, I would use pexpect:
So assuming, you wanted to spawn a program called myprocess and waited for the password prompt that had a > (greater than sign):
import pexpect
child = pexpect.spawn('myprocess')
child.expect('>')
child.sendline(password_var)
child.expect('>')
child.sendline(password_var)
Related
I have a terminal command I wish to execute from a python file.
However this command needs says it needs to be run as root (i.e sudo).
I am running this command from a python file by doing:
os.system(sudo pmset schedule wake "08/31/21 00:26:00")
its basically just telling my laptop to wakeup at a specific time.
As you know that this then requires requires a the users password to be manually input to execute the command. Is there a way of removing this from requiring a password? i was trying to enter my password in as an 'os.system' command but it wont take. it seems like only a manual input will work. any ideas?
If using subprocess, you have the option to run a command as shell, with the shell=True argument. However, this requires the python program to already be running with elevated privilages (run python with sudo), otherwise it is not permitted to start a subprocess with an elevated privilage.
You can read more about the docs: https://docs.python.org/3/library/subprocess.html#subprocess.run
Is it possible to execute a program within python, e.g. an interactive command, SSH, telnet, etc, and then release the control to the user so he is free to interact with the program. The control is returned to python after the program terminates?
os.system("ssh 3.4.5.6");
# user interact with the command until it terminates
print("All Done")
(Edit: sorry, I gave a bad example, the command I want to run is python and it didn't work for me. I will post a diff question)
Yes it is possible to execute a program within python and then release the control to the user, you will have to use os.system("your command") to run command and if that command requires interaction you will be able to do so on the cmd window.
Yes it is Possible to execute python program and let user to interact with it by os.system(command) .
I'm new in a company for IT and very few people here know Python so I can't ask then for help.
The problem: I need to create a script in Python that connects via ssh from my VM to my client server, after I access with my script I need to find a log file and search for a few data.
I tested my script within my Windows with a copy of that file and it searched everything that I need. However, I don't know how to do that connection via SSH.
I tried like this but I don't know where to start:
from subprocess import Popen, PIPE
import sys
ssh = subprocess.check_output(['ssh', 'my_server', 'password'], shell = True)
ssh.stdin.write("cd /path/")
ssh.stdin.write("cat file | grep err|error")
This generates a error "name 'subprocess' is not defined".
I don't understand how to use the subprocess nor how to begin to develop the solution.
Note: I can't use Paramiko because I don't have permission to install packages via pip or download the package manually.
You didn't import subprocess itself so you can't refer to it.
check_output simply runs a process and waits for it to finish, so you can't use that to run a process you want to interact with. But there is nothing interactive here, so let's use that actually.
The first argument to subprocess.Popen() and friends is either a string for the shell to parse, with shell=True; or a list of token passed directly to exec with no shell involved. (On some platforms, passing a list of tokens with shell=True actually happens to work, but this is coincidental, and could change in a future version of Python.)
ssh myhost password will try to run the command password on myhost so that's not what you want. Probably you should simply set things up for passwordless SSH in the first place.
... But you can use this syntax to run the commands in one go; just pass the shell commands to ssh as a string.
from subprocess import check_output
#import sys # Remove unused import
result = check_output(['ssh', 'my_server',
# Fix quoting and Useless Use of Cat, and pointless cd
"grep 'err|error' /path/file"])
I'd like to call a separate non-child python program from a python script and have it run externally in a new shell instance. The original python script doesn't need to be aware of the instance it launches, it shouldn't block when the launched process is running and shouldn't care if it dies. This is what I have tried which returns no error but seems to do nothing...
import subprocess
python_path = '/usr/bin/python'
args = [python_path, '&']
p = subprocess.Popen(args, shell=True)
What should I be doing differently
EDIT
The reason for doing this is I have an application with a built in version of python, I have written some python tools that should be run separately alongside this application but there is no assurance that the user will have python installed on their system outside the application with the builtin version I'm using. Because of this I can get the python binary path from the built in version programatically and I'd like to launch an external version of the built in python. This eliminates the need for the user to install python themselves. So in essence I need a simple way to call an external python script using my current running version of python programatically.
I don't need to catch any output into the original program, in fact once launched I'd like it to have nothing to do with the original program
EDIT 2
So it seems that my original question was very unclear so here are more details, I think I was trying to over simplify the question:
I'm running OSX but the code should also work on windows machines.
The main application that has a built in version of CPython is a compiled c++ application that ships with a python framework that it uses at runtime. You can launch the embedded version of this version of python by doing this in a Terminal window on OSX
/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python
From my main application I'd like to be able to run a command in the version of python embedded in the main app that launches an external copy of a python script using the above python version just like I would if I did the following command in a Terminal window. The new launched orphan process should have its own Terminal window so the user can interact with it.
/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python my_python_script
I would like the child python instance not to block the main application and I'd like it to have its own terminal window so the user can interact with it. The main application doesn't need to be aware of the child once its launched in any way. The only reason I would do this is to automate launching an external application using a Terminal for the user
If you're trying to launch a new terminal window to run a new Python in (which isn't what your question asks for, but from a comment it sounds like it's what you actually want):
You can't. At least not in a general-purpose, cross-platform way.
Python is just a command-line program that runs with whatever stdin/stdout/stderr it's given. If those happen to be from a terminal, then it's running in a terminal. It doesn't know anything about the terminal beyond that.
If you need to do this for some specific platform and some specific terminal program—e.g., Terminal.app on OS X, iTerm on OS X, the "DOS prompt" on Windows, gnome-terminal on any X11 system, etc.—that's generally doable, but the way to do it is by launching or scripting the terminal program and telling it to open a new window and run Python in that window. And, needless to say, they all have completely different ways of doing that.
And even then, it's not going to be possible in all cases. For example, if you ssh in to a remote machine and run Python on that machine, there is no way it can reach back to your machine and open a new terminal window.
On most platforms that have multiple possible terminals, you can write some heuristic code that figures out which terminal you're currently running under by just walking os.getppid() until you find something that looks like a terminal you know how to deal with (and if you get to init/launchd/etc. without finding one, then you weren't running in a terminal).
The problem is that you're running Python with the argument &. Python has no idea what to do with that. It's like typing this at the shell:
/usr/bin/python '&'
In fact, if you pay attention, you're almost certainly getting something like this through your stderr:
python: can't open file '&': [Errno 2] No such file or directory
… which is exactly what you'd get from doing the equivalent at the shell.
What you presumably wanted was the equivalent of this shell command:
/usr/bin/python &
But the & there isn't an argument at all, it's part of sh syntax. The subprocess module doesn't know anything about sh syntax, and you're telling it not to use a shell, so there's nobody to interpret that &.
You could tell subprocess to use a shell, so it can do this for you:
cmdline = '{} &'.format(python_path)
p = subprocess.Popen(cmdline, shell=True)
But really, there's no good reason to. Just opening a subprocess and not calling communicate or wait on it already effectively "puts it in the background", just like & does on the shell. So:
args = [python_path]
p = subprocess.Popen(args)
This will start a new Python interpreter that sits there running in the background, trying to use the same stdin/stdout/stderr as your parent. I'm not sure why you want that, but it's the same thing that using & in the shell would have done.
Actually I think there might be a solution to your problem, I found a useful solution at another question here.
This way subprocess.popen starts a new python shell instance and runs the second script from there. It worked perfectly for me on Windows 10.
You can try using screen command
with this command a new shell instance created and the current instance runs in the background.
# screen; python script1.py
After running above command, a new shell prompt will be seen where we can run another script and script1.py will be running in the background.
Hope it helps.
Is there any way to inject a command into a bash prompt in Linux? I am working on a command history app - like the Ctrl+R lookup but different. I am using python for this.
I will show a list of commands from history based on the user's search term - if the user presses enter, the app will execute the command and print the results. So far, so good.
If the user chooses a command and then press the right or left key, I want to insert the command into the prompt - so that the user can edit the command before executing it.
If you are on Linux, just fire up a bash console, press Ctrl+r, type cd(or something), and then press the right arrow key - the selected command will be shown at the prompt. This is the functionality I am looking for - but I want to know how to do that from within python.
You can do this, but only if the shell runs as a subprocess of your Python program; you can't feed content into the stdin of your parent process. (If you could, UNIX would have a host of related security issues when folks run processes with fewer privileges than the calling shell!)
If you're familiar with how Expect allows passthrough to interactive subprocesses (with specific key sequences from the user or strings received from the child process triggering matches and sending control back to your program), the same thing can be done from Python with pexpect. Alternately, as another post mentioned, the curses module provides full control over the drawing of terminal displays -- which you'll want if this history menu is happening within the window rather than in a graphical (X11/win32) pop-up.
See readline module. It implements all these features.
If I understand correctly, you would like history behaviour similar to that of bash in
a python app. If this is what you want the GNU Readline Library is the way to go.
There is a python wrapper GNU readline interface but it runs only on Unix.
readline.py is seem to be a version for Windows, but I never tried it.
ncurses with its python port is a way to go, IMHO.