I have a problem with running non finishing process via ssh from python script. What I need to do:
Connect to remote server via ssh
Run mongod on this server
Finish script execution without killing mongod process
For now, I'm using subprocess.Popen in this way:
subprocess.Popen(['ssh', 'user#' + host, 'mongod', '-f', '/temp-mongo.conf', '&'])
Problem is that script ends before I'm asked about user password, so it finishes with Too many authentication failures for root.
I tried to use p = subprocess.Popen(...).communicate() and it'a almost ok, but then script waits for mongod command to be finished, what obviously won't happen.
What is proper way to do this? Can I do something to pass password automatically?
I agree with e4c5 that you should use a tool like Fabric for that. If you want to stay with the dirty way something like this should work:
subprocess.call('ssh user#%s "mongod -f /temp-mongo.conf &>/dev/null &"' % host,
shell=True)
Note that you need to do:
quotes around the remote call
add &>/dev/null which routes all output of mongod to /dev/null (without this it will block, not 100% sure why. Probably since the stdout of the shell is attached to the command)
use shell=True so the shell builds up the command for you (so you don't need to put a ", " instead of each space)
This also works with auth over public key (instead of writing the password by hand)
The proper way for SSH without having to enter passwords is to use public key authentication.
I would also look at Fabric for running commands via SSH.
And you aren't running the command in a shell environment on the server. If you run
ssh host ls &
the & will actually put ssh in the background, not ls on the host. Instead try doing
ssh host sh -c 'ls &'
Related
I am trying to escape a python interactive shell within an ssh server without closing the ssh connection, using exit(), quit() ctrl D closes the ssh connection
I'm assuming your connection is to a Linux/Unix server. If it's Windows, this won't help.
If you only close the python interpreter (ctrl-c for instance) it shouldn't close the SSH connection, since the python interpreter is running on top of the unix shell, which you are actually connected to.
The best way (or at least the easiest) to keep your SSH connection and keep any program running after you leave is to use a tool like tmux or screen (if your linux machine does not have tmux installed).
In order to do so, you can either start your program with $ screen python or start screen before you run anything, and it will start a screen session with bash running.
Then you can safely close the ssh connection, and, when you ssh back into the machine, use screen -r to return to where you leave.
You can easily import the pty module
import pty
and then spawn a new bash shell "/bin/bash" with the module using
pty.spawn("/bin/bash")
Note: "bash" in this context can be changed depending on what shell is avaliable on the server which could be "sh", "dash" or any other type of unix compatible shell
ssh -t
-t flag forces use of ptty. Control sequences will be sent directly to remote process
keygen etc. so I can just ssh remotehost w/o using password, shell =BASH
I am using a for loop to ssh over multiple nodes (remote host) and wish to execute a script but it dosent seem to work
for i in {1..10};
do
ssh -f node$i "python script.py $i"
done
the terminal script hangs up and nothing happens
Also I can manually ssh and use python. The PYTHONPATH etc are configured for enodes.
There was cshell on nodes, so i used .cshrc wit exec /bin/bash which atleast when i log manually gives me bash shell, so problem doesent seem to be there.
I
Instead of wrapping python script in a shell script, you should probably have a python script that connects to all the remote hosts via ssh and executes stuff.
Paramiko is a very good framework for this kind of use-case. It will be much easier to maintain your script this was in the long run.
Use -o BatchMode=yes
and maybe you need to force allocate pseudo-tty and -n to prevent reading from stdin
I am trying to open an interactive ssh shell through fabric.
Requirements:
Use fabrics hosts in the connection string to remote
Open fully interactive shell in current terminal
Works on osx and ubuntu
No need for data transfer between fabric/python and remote. So fabric task can end in background.
So far:
fabfile.py:
def test_ssh():
from subprocess import Popen
Popen('ssh user#1.2.3.4 -i "bla.pem"', shell=True)
In terminal:
localprompt$ fab test_ssh
localprompt$ tcsetattr: Input/output error
[remote ubuntu welcome here]
remoteprompt$ |
Then if I try to input a command on the remote prompt it is executed locally and I drop back to the local prompt.
Does anyone know a solution?
Note: I am aware of fabrics open_shell, but this does not work for me since the stdout lags behind, rendering this unusable.
A slight modification does the trick:
def test_ssh():
from subprocess import call
call('ssh user#1.2.3.4 -i "bla.pem"', shell=True)
As the answer to this question suggests the error suggests the error comes from the inability of ssh to connect to the stdin/out of a process in the background.
With call the fabric task does not end in the background, but I am fine with that as long as as it is not interfering with my stdin/out.
I want to run a python script on my server (that python script has GUI). But I want to start it from ssh. Something like this:
ssh me#server -i my_key "nohup python script.py"
... > let the script run forever
BUT it complains "unable to access video driver" since it is trying to use my ssh terminal as output.
Can I somehow make my commands output run on server machine and not to my terminal... Basically something like "wake-on-lan functionality" -> tell the server you want something and he will do everything using its own system (not sending any output back)
What about
ssh me#server -i my_key "nohup python script.py >/dev/null 2>&1"
You can use redirection to some remote logfile instead of /dev/null of course.
? :)
EDIT: GUI applications on X usually use $DISPLAY variable to know where they should be displayed. Moreover, X11 display servers use authorization to permit or disallow applications connecting to its display. Commands
export DISPLAY=:0 && xhost +
may be helpful for you.
Isn't it possible for you to rather use python ssh extension instead of calling external application?
It would:
run as one process
guarantee that invocation will be the same among all possible system
lose the overhead from "execution"
send everything trough ssh (you won't have to worry about input like "; possibly local executed command)
If not, go with what Piotr Wades suggested.
I want to connect to putty and want to do few step:
login to Putty
type few command to bring down the server
Traverse to the particular path
Remove the file from the directory
Again start the server
I need to write the code in windows. But my server is in linux.
How shall I proceed?
Thanks in advance
What you need is Paramiko, but it may be a little complicated for a beginner.
For simple, repetitive tasks you may use my script - it is located on GitHub (https://github.com/tadeck/ssh-matic) and was created to learn some Python. It is based on someone else's friendly SSH Python interface to Paramiko (code accessible here).
Using the mentioned SSH module connecting to server and executing a command is rather simple:
import ssh
server = ssh.Connection(host='host', username='user', private_key='key_path')
result = server.execute('your command')
Basically what you need is not PuTTy, but a SSH module to Python. This module should work both on Windows and Linux. Using my script you will only need to work on the command you want to invoke, plus adjust the code to your needs.
Good luck. Tell me if it helped.
from pywinauto.application import Application
import time
app = Application ().Start (cmd_line=u'putty -ssh user_name#10.70.15.175')
putty = app.PuTTY
putty.Wait ('ready')
time.sleep (1)
putty.TypeKeys ("password")
putty.TypeKeys ("{ENTER}")
time.sleep (1)
putty.TypeKeys ("ls")
putty.TypeKeys ("{ENTER}")
I am using python 2.7. Code is running on Windows, and connect to remote Linux. it is working in my environment.
You could do this:
# Use plink to open a connection to the remote shell
command = "plink.exe -ssh %s -batch" % credentials
sp = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
# Send commands to the shell as if they were read from a shell script
sp.stdin.write("command1\n")
sp.stdin.write("command2\n")
sp.stdin.close()
# read out the answers, if needed
ans = sp.stdout.read()
sp.wait()
For credentials, it is best to put the name of a PuTTY connection profile, ready with the username set and a SSH key.
you can use code similar to:
command = "plink.exe -ssh username#" + hostname + " -pw password -batch \"export DISPLAY='" + hostname + "/unix:0.0' ; "
which will open an ssh to the desired hostname using username and password
shutdown:
command += "sudo /sbin/halt\""
reboot:
command += "sudo /sbin/reboot\""
add your other commands using the same method as above,
run the command with:
pid = subprocess.Popen(command).pid
As pointed out by Tadeck, this will only work on a windows machine attempting to connect to a linux machine.