How to use scp command in paramiko - python

I am using two commands in paramiko python module "find" and "scp".
Find command is working fine and giving the correct output but scp is not giving any output.
I tried with following code:
import paramiko
class SSH:
def ssh_Connection(self):
try:
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect('host_name',username='user',password='pass')
except Exception, e:
print "================================================"
print 'ERROR: Remote connection failed with %s' % e
print "================================================"
def ssh_Commands(self):
try:
stdin, stdout, stderr = self.ssh.exec_command('find /result/main/ -name "*new.txt*"')
for line in stdout:
a = line.strip('\n')
print a
if a:
cmd = 'scp -r %s redhat#192.168.56.32:/results/main/' % a
print cmd
stdin, stdout, stderr = self.ssh.exec_command(cmd)
print stdout.read()
print stderr.read()
self.ssh.close()
except Exception, e:
print "================================================"
print 'ERROR: Commands Execution failed with %s' % e
print "================================================"
if __name__ == "__main__":
a = SSH()
a.ssh_Connection()
a.ssh_Commands()
But this program is not working for me..
Throwing an error:
Host key verification failed.
lost connection
How can use scp in paramiko...any idea?

You can use SFTPClient of paramiko to copy files from local to remote server.
There is put method for of SFTPClient which will copy local file to the remote server.

The server (host_name) on which you are performing the commands doesn't have proper SSH access to the server you are trying to scp to (192.168.56.32), that's why it generates the error Host key verification failed (which means that the host key for 192.168.56.32 in the known_hosts file on host_name doesn't match the key that 192.168.56.32 is returning).
Either fix the host key, or try running scp like this:
scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -r %s ...
(also be aware that if the filenames contain spaces, your scp command will fail, use "%s" on your scp command line instead).

Related

How to skip lines when printing output from Paramiko SSH

So I built a program that prints out the login logs of my ubuntu server using tail -f.
The program uses Paramiko to connect via ssh and runs the command to tail the logs.
The program works but it prints out the motd from the server which is unnecessary.
I've tried splicing using itertools.
Tried using next().
Still doesn't work.
Here's my code:
import yaml, paramiko, getpass, traceback, time, itertools
from paramiko_expect import SSHClientInteraction
with open("config.yaml", "r") as yamlfile:
cfg = yaml.load(yamlfile, Loader=yaml.FullLoader)
def main():
command = "sudo tail -f /var/log/auth.log"
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
server_pw = getpass.getpass("Enter the password for your account %s on %s:" % (cfg['ssh_config']['username'], cfg['ssh_config']['host']))
sudo_pw = getpass.getpass("Enter the sudo password for %s on %s: " % (cfg['ssh_config']['username'], cfg['ssh_config']['host']))
ssh.connect(hostname = cfg['ssh_config']['host'], username = cfg['ssh_config']['username'], port = cfg['ssh_config']['port'], password = server_pw)
interact = SSHClientInteraction(ssh, timeout=10, display=False)
interact.send(command)
interact.send(sudo_pw + "\n")
with open(interact.tail(line_prefix=cfg['ssh_config']['servername']+': ')) as tail:
for line in itertools.islice(tail, 17, None):
print(line)
except KeyboardInterrupt:
print('Ctrl+C interruption detected, stopping tail')
except Exception:
traceback.print_exc()
finally:
try:
ssh.close()
except:
pass
if __name__ == '__main__':
main()
You get MOTD because you are opening an interactive shell session. I do not think you need that, quite on the contrary.
Use SSHClient.exec_command instead:
stdin, stdout, stderr = ssh.exec_command(command, get_pty=True)
stdin.write(sudo_pw + "\n")
stdin.flush()
for line in iter(stdout.readline, ""):
print(line, end="")
Related questions:
Get output from a Paramiko SSH exec_command continuously
Pass input/variables to command/script over SSH using Python Paramiko
What is the difference between exec_command and send with invoke_shell() on Paramiko?
Obligatory warning: Do not use AutoAddPolicy – You are losing a protection against MITM attacks by doing so. For a correct solution, see Paramiko "Unknown Server".

Go to bash mode in a remote server(networking operating system) using python

I want to automate getting current kernel version using python.I tried to ssh to server(networking operating system) using paramiko then tried to execute below commands
OS10# system bash
admin#OS10:~$ uname -r
3.16.51
Below is my python script
import sys
import time
import select
import paramiko
host = '100.97.100.12'
i = 1
while True:
print "Trying to connect to %s (%i/30)" % (host, i)
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=host,port=22,username="admin",password="admin",
timeout=float(10),allow_agent=False ,look_for_keys=False)
print "Connected to %s" % host
break
except paramiko.AuthenticationException:
print "Authentication failed when connecting to %s" % host
sys.exit(1)
except:
print "Could not SSH to %s, waiting for it to start" % host
i += 1
time.sleep(2)
# If we could not connect within time limit
if i == 30:
print "Could not connect to %s. Giving up" % host
stdin, stdout, stderr = ssh.exec_command("system bash")
ssh_output = stdout.read()
ssh_error = stderr.read()
print(ssh_output)
print(ssh_error)
ssh.close()
I am able to connect to host, but its not giving any error no output when executing the command .
Try executing:
/path/to/bash -c 'uname -r'
Where you can determine path/to/bash by SSHing to your server and looking at the path to bash on cat /etc/shells or which bash. Alternatively you could use chsh to change the default shell permanently.

How to run commands in REMOTE machine with the subprocess approach using passwordless authentication in python3?

I am trying to write a script which should perform some commands (defined by Payload) in a ssh enable remote computer. I want to have a passworless connection. So that I can use the public and private key authentication. I know how to do it in paramiko and its working. Is there any way to do it by subprocess and get the output? Is there any sample code for that?
My sample code is something like that. For example, I want to execute more connection later on.
import subprocess
def __init__ (type, options):
if type=="ssh":
ssh(options)
else if type="fsexec":
fsexec(options)
def ssh(self, ip, user, sshkey_file, payload):
try:
command = "ssh "
prog = subprocess.call(["ssh -i sshkey_file -t user#ip 'payload'"])
print(prog)
print("Returncode:", prog)
def fsexec(self, ip, user, sshkey_file, payload):
try:
command = "ssh "
prog = subprocess.call(["fsexec -t user#ip 'payload'"])
print(prog)
print("Returncode:", prog)
You should use the Paramiko library to log in with ssh and the keyfile.
I copied an exmaple from a gist (https://gist.github.com/batok/2352501):
import paramiko
k = paramiko.RSAKey.from_private_key_file("/Users/whatever/Downloads/mykey.pem")
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
print "connecting"
c.connect( hostname = "www.acme.com", username = "ubuntu", pkey = k )
print "connected"
commands = [ "/home/ubuntu/firstscript.sh", "/home/ubuntu/secondscript.sh" ]
for command in commands:
print "Executing {}".format( command )
stdin , stdout, stderr = c.exec_command(command)
print stdout.read()
print( "Errors")
print stderr.read()
c.close()

Wait until paramiko exec_command is finished

I've got a python script I'm trying to install a rpm package on but when I send the command to install it doesn't wait for the command to finish before restarting the service. I've read a lot of forums about using recv_exit_status() but I don't think I'm using it right.
This is what I have:
#!/usr/bin/python
import paramiko, os
from getpass import getpass
# Setting Variables
Hosts = [ '192.168.1.1', '192.168.1.2'] #IPs changed for posting
username = 'root'
print 'Enter root password on remote computer:'
password = getpass()
port = 22
File = 'Nessus-6.11.2-es7.x86_64.rpm'
for host in Hosts:
print 'Finished copying files. Now executing on remote computer'
#Setting up SSH session to run commands
remote_client = paramiko.SSHClient()
remote_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
remote_client.connect(host, username=username, password=password)
InstallNessus = 'rpm -U --percent %s'%File
stdin, stdout, stderr = remote_client.exec_command(InstallNessus)
stdout.channel.recv_exit_status()
lines = stdout.readlines()
for line in lines:
print line
stdin, stdout, stderr = remote_client.exec_command('systemctl restart nessusd.service')
remote_client.close()
I've tried using Fabric but I seem to be messing up my syntax somewhere.
add get_pty=True This will wait until command execution completed. stdin,stdout,stderr = self.ssh.exec_command(command,get_pty=True)
It's channel.recv_exit_status(), not stdout.channel.recv_exit_status().
However, since you are trying to run the same command over many servers, something like parallel-ssh is a better fit and much faster than paramiko, both sequentially and in parallel.
Code to do it is also much simpler, just:
from pssh.pssh2_client import ParallelSSHClient
hosts = ['192.168.1.1', '192.168.1.2']
_file = 'Nessus-6.11.2-es7.x86_64.rpm'
cmd = 'rpm -U --percent %s' % _file
client = ParallelSSHClient(hosts, user='<user>', password='<password>')
output = client.run_command(cmd)
for host, host_output in output.items():
for line in host_output.stdout:
print "Host %s: %s" % (host, line)
print "Host %s exit code %s" % (host, host_output.exit_code)
restart_out = client.run_command('systemctl restart nessusd.service')
# Just wait for completion
client.join(restart_out)
See documentation for further information.

Python / create ssh connection and change a file

I have the following code in python:
import pxssh
s = pxssh.pxssh()
try:
if not s.login ('x.x.x.x', 'root', 'password'):
print "SSH session failed on login."
print str(s)
else:
print "SSH session login successful"
s.sendline ('uptime')
s.prompt() # match the prompt
print s.before # print everything before the prompt.
s.logout()
except pxssh.ExceptionPxssh, e:
print "SSH conection failed"
print str(e)
and I success to do ssh connection.
Now, I want to append a key to a file which already exists in my system (in /root/.ssh/authorized_keys)
I don't find any way to do it with the pxssh API. How can I do it.
In the following code I'll assume that you have successfully connected to the remote machine via ssh. I have used this method for a similar purpose but with different data.
file_data = open("/root/.ssh/authorized_keys").read()
"""manipulate the contents of the file such that the variable new_key contains
the data you want to append to the file via ssh"""
#I'll assume the data to be abcd
new_key = "abcd"
#Constructing the command to pass via ssh
cmd = 'echo "' + new_key + '">>/root/.ssh/authorized_keys'
#note that I've used >> and not >, the former will append while the later will overwrite the file
#also the path given in the above command is the one on the remote ssh server and not your local machine
s.sendline(cmd)
s.prompt()
print s.before
#voilà your key is appended to the file on the remote server
#you can check that
s.sendline("cat /root/.ssh/authorized_keys")
s.prompt()
print s.before
Hope this helps.

Categories