-
Star
(127)
You must be signed in to star a gist -
Fork
(30)
You must be signed in to fork a gist
-
-
Save bortzmeyer/1284249 to your computer and use it in GitHub Desktop.
#!/usr/bin/python | |
# All SSH libraries for Python are junk (2011-10-13). | |
# Too low-level (libssh2), too buggy (paramiko), too complicated | |
# (both), too poor in features (no use of the agent, for instance) | |
# Here is the right solution today: | |
import subprocess | |
import sys | |
HOST="www.example.org" | |
# Ports are handled in ~/.ssh/config since we use OpenSSH | |
COMMAND="uname -a" | |
ssh = subprocess.Popen(["ssh", "%s" % HOST, 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 | |
What does this line do?
print >>sys.stderr, "ERROR: %s" % error
Specifically, I'm stumped by >>. You can't google those symbols unfortunately... I know you can use >> and << for bit shifting, but what's going on in this case? Thanks.
print >> or "print chevron" is part of the python 2.x syntax for the print statement. The first argument is a file-like object (sys.stderr in this case) and the second a string expression to be written to the file-like object.
@geoffreybrown, thanks that makes sense. And I can now do a web search on "python print chevron" to get more details! The tricky part of this was that you can't easily do a web search on >>.
I want to run this command "unlock_user"
But its creating the command string as "unlock-user\n', '\r\n'"
a from __future__ import print_function
and print("ERROR: %s" % error, file=sys.stderr)
would probably be preferable.
Nonsense. Paramiko is not especially buggy. I have been using it for years. The documentation could use some help, and more examples, but it works great!
If you just need to run a single SSH call, sure -- just wrap SSH command in subprocess.
But if you need to execute a suite of SSH commands, using a variety of keys and users -- like if you are doing QA integration testing -- then I would bite the bullet and use Paramiko (or even easier, I hear, is Fabric)
I don't want to come out from the remote machine. Can somebody please help?
Thanks,
Santosh
Im just a bit confused about
if result == []:
What is the if condition here ? What does it mean ?
@jeunii it looks like it's checking if the stdout returned is empty (if the command didn't return any output)
Hi,
I'm trying to use subprocess.call() from AWS lambda and I'm having problems.
My cmd_to_execute contain 'sudo'.
This is my piece of code:
call(['ssh', '-i', '/tmp/keyname.pem', 'user@hostIP','sudo python3.5 /home/ubuntu/code.py'], shell=True)
Someone has an idea to make it succeed?
Thanks!
Paramiko is not that buggy compared to the level of fuss required to get this to work.
Try doing something like nesting a connection using netcat, forwarding through direct-tcpip, etc. Even a simple key/password authentication becomes a nightmare. Also, this script assumes that there is an ssh
binary present. Which is not true 90% of the times (windows users, embeded systems, stripped down versions of Unix).
the script does work well for the most of command using SSH, however for some it fails since it recognizes as error when the banner is displayed as you can see below. Does anybody know how to fix that? Thanks.
blabla@blabla00623:blabla/users/carlos/scripts> ./test_ssh.py
ERROR: ['\n', ' +----------------------------------------------------------------------------+\n', ' | WARNING |\n', ' | The programs and data stored on this system are licensed to, or are |\n', ' | private property of, blabla and are lawfully available only to authorized |\n', ' | users for approved purposes. Unauthorized access to any program or data |\n', ' | on this system is not permitted, and any unauthorized access beyond this |\n', ' | point may lead to prosecution and/or disciplinary action. |\n', ' | This system may be monitored at any time for operational reasons. ]
Hello All, I am completely out of scripting and programming background, so apologize for throwing a dum question here.
I am on Python 2.7.10. I wanted to have a .py script for ssh'ing into multiple remote servers.
My requirement. I wanted to establish the below using
ssh -i (KEY) USERNAME@SERVERIP -p (PORTNUMBER)
after ssh'ing I want auth the passphrase for the Key.
Can someone help me, please?
Hello from the future.
For the benefit of others that are seeing this post 7 years after it was written, there are now alternatives that are not junk.
parallel-ssh is a high-level library that builds on a new libssh2 wrapper, ssh2-python, making it easy to use.
The motivation for writing it was exactly as the OP had found all those years ago - all existing clients were junk. In addition, no clients were available that could feasibly scale to multiple hosts (tens, hundreds, thousands).
from pssh.clients import ParallelSSHClient
client = ParallelSSHClient(['www.example.org'])
output = client.run_command('uname -a')
for host, host_out in output.items():
for line in host_out.stdout:
print line
There is also a single host client (pssh.clients.SSHClient
) for cases where concurrency is not needed.
See documentation for more examples. Connection retries, exceptions, SFTP, SCP, tunneling/proxying, ssh agents et al are all supported.
Disclaimer - author of both.
the script does work well for the most of command using SSH, however for some it fails since it recognizes as error when the banner is displayed as you can see below. Does anybody know how to fix that? Thanks.
@cacm1975. Suppress the banner via ssh. Try to use '-q' option.
Not working for me!
Traceback (most recent call last):
File "C:/Users/girishlc/AppData/Local/Programs/Python/Python35-32/ssh7.py", line 11, in
stderr=subprocess.PIPE)
File "C:\Users\girishlc\AppData\Local\Programs\Python\Python35-32\lib\subprocess.py", line 947, in init
restore_signals, start_new_session)
File "C:\Users\girishlc\AppData\Local\Programs\Python\Python35-32\lib\subprocess.py", line 1224, in _execute_child
startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified
@girishlc
Try this version:
from __future__ import print_function
import os
import subprocess
import platform
PRIVATE_KEY_LOCATION = "C:/Users/johndoe/.ssh/id_rsa"
USER = "johndoe"
HOST = "192.168.1.1"
COMMAND="uname -a"
# Ports are handled in ~/.ssh/config since we use OpenSSH
system32 = os.path.join(os.environ['SystemRoot'], 'SysNative' if platform.architecture()[0] == '32bit' else 'System32')
ssh_path = os.path.join(system32, 'OpenSSH/ssh.exe')
ssh = subprocess.Popen([ssh_path, '-i', PRIVATE_KEY_LOCATION, "{}@{}".format(USER, HOST)],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
std_data = ssh.communicate(COMMAND)
I ran into this problem as well.
See:
https://bugs.python.org/issue8557
https://stackoverflow.com/questions/41630224/python-does-not-find-system32
i am using py script like below:
import subprocess
import sys
HOST="root@192.168.1.25"
COMMAND="ls / -ltrh"
ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
shell=True,
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)
the print command prints output but evenything is inside bracket and bunch on newline,tabs and other characters...How do i properly format this output? I tried result.decode('utf-8') but i get an error that decode is not available...any idea?
[b'total 20K\n', b'drwxr-xr-x. 2 root root 6 Apr 11 00:59 srv\n', b'drwxr-xr-x. 2 root root 6 Apr 11 00:59 mnt\n', b'drwxr-xr-x. 2 root
root 6 Apr 11 00:59 media\n', b'drwxr-xr-x. 2 root root 6 Apr 11 00:59 home\n', b'lrwxrwxrwx. 1 root root 7 Sep 26 18:18 bin -> usr/b
in\n', b'lrwxrwxrwx. 1 root root 9 Sep 26 18:18 lib64 -> usr/lib64\n', b'lrwxrwxrwx. 1 root root 7 Sep 26 18:18 lib -> usr/lib\n', b'lrwx
rwxrwx. 1 root root 8 Sep 26 18:18 sbin -> usr/sbin\n', b'drwxr-xr-x. 13 root root 155 Sep 26 18:18 usr\n', b'dr-xr-xr-x. 5 root root 4.0K
Sep 26 18:26 boot\n', b'drwxr-xr-x. 19 root root 267 Sep 26 22:26 var\n', b'drwxr-xr-x. 3 root root 16 Sep 27 20:26 opt\n', b'dr-xr-xr-x. 11
0 root root 0 Sep 29 04:08 proc\n', b'dr-xr-xr-x. 13 root root 0 Sep 29 04:08 sys\n', b'drwxr-xr-x. 19 root root 3.1K Sep 29 18:22 dev\n',
b'drwxr-xr-x. 24 root root 740 Sep 30 05:22 run\n', b'drwxr-xr-x. 79 root root 8.0K Sep 30 05:22 etc\n', b'drwxrwxrwt. 9 root root 4.0K Sep 30
07:19 tmp\n', b'dr-xr-x---. 3 root root 170 Sep 30 07:21 root\n']
@taigrr use SSH keys; see
ssh(1)
andssh-copy-id(1)
I agree with this... but what if we dont have keys? or the ability to use keys due to a corporate env and RSA revolving password?
@girishlc
Try this version:from __future__ import print_function import os import subprocess import platform PRIVATE_KEY_LOCATION = "C:/Users/johndoe/.ssh/id_rsa" USER = "johndoe" HOST = "192.168.1.1" COMMAND="uname -a" # Ports are handled in ~/.ssh/config since we use OpenSSH system32 = os.path.join(os.environ['SystemRoot'], 'SysNative' if platform.architecture()[0] == '32bit' else 'System32') ssh_path = os.path.join(system32, 'OpenSSH/ssh.exe') ssh = subprocess.Popen([ssh_path, '-i', PRIVATE_KEY_LOCATION, "{}@{}".format(USER, HOST)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std_data = ssh.communicate(COMMAND)
I ran into this problem as well.
See:
https://bugs.python.org/issue8557
https://stackoverflow.com/questions/41630224/python-does-not-find-system32
how does this convert over to Android file system?
Your script works perfectly from my kodi on windows and ssh's into a raspberry pi. I'm trying to get this working from an android Xiamoi Mi box. Any suggestions? :)
this gist aged well. ELL OH ELL
edit: good luck with all your forked processes. i'm happy with paramiko.
Hi All ,
I need a help . I am using below code as I want ssh to run few commands in bash mode . But I am getting errors .
import subprocess
import sys
HOST="root@192.168.1.2". # change the IP as per ur testing
COMMAND="ls / -ltrh"
print("Type ",type(COMMAND))
ssh = subprocess.Popen(["ssh", "%s" % HOST, "%s" %COMMAND],
shell=True,
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)
(venv) [rrshanke@slc10gon ADW]$ python ssh_try.py
('Type ', <type 'str'>)
ERROR: ['usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n', ' [-D [bind_address:]port] [-E log_file] [-e escape_char]\n', ' [-F configfile] [-I pkcs11] [-i identity_file]\n', ' [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]\n', ' [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]\n', ' [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n', ' [user@]hostname [command]\n']
(venv) [rrshanke@slc10gon ADW]$
I am not sure what is wrong . Please help me
ssh = subprocess.Popen(["ssh", "%s" % HOST, "%s" %COMMAND],
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
You should read the documentation. https://docs.python.org/3/library/subprocess.html Executive summary: shell=True
is both dangerous and a bad idea in most cases. From a Python program, shell=False
is the right solution most of the time. (See in the doc, around "If shell is True, it is recommended to pass args as a string rather than as a sequence.")
SSH without third-party library
Here is my take on SSH without using third-party library. I leveraged a concept of fork
system call in UNIX [1].
# Create an ssh session with python
import os
import shlex
def create_ssh(host, user):
"""Create a ssh session"""
ssh = "/usr/bin/ssh -t {user}@{host} ".format(user=user, host=host)
# Now, fork a child from current process
# This is a basic concept from Operating System class.
pid = os.fork()
if pid == 0: # a child process
print("Executing: %s" %(ssh))
cmd = shlex.split(ssh)
os.execv(cmd[0], cmd)
os.wait(pid, 0)
print("ssh session is finished. :)")
if __name__ == "__main__":
create_ssh(
host="remote_host",
user="remote_user")
Amazing
Still populating top three google results when searching for 'python3 connect ssh and run script' :)
Still true today. Amazing how badly libraries like paramiko and fabric fail at such a simple task.
Still a valid chain but still finding it hard to reliably send password from Osx or linux
thank you
Can tell how amazing it is when this solution still works today.
Thanks a lot.
try paramiko