ssh to a device with super user with paramiko [duplicate] - python

This question already has an answer here:
Executing command using "su -l" in SSH using Python
(1 answer)
Closed 1 year ago.
I am trying to make script to ssh my device with r/o user and then super user and execute a command.Below are the steps i did on my putty
login as admin ( r/o user) and password.
sudo su and than password
execute a command
print output of executed command
i tried below code to make it working but i didn't get any output.
import paramiko
import pandas as pd
import openpyxl
from paramiko import AuthenticationException
from paramiko.ssh_exception import SSHException, NoValidConnectionsError
import socket
import time
import os
import inspect
import datetime
start = time.time()
print("Starting................................Please Wait")
df=pd.DataFrame(columns=["ip","Status","Remarks"])
ips = ['10.11.8.71']
root = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
#ips = open (root+ "/440_ip.txt")
for ipp in ips:
ip = ipp.strip()
port=22
username='admin'
#password='AeGEBUx66m_1ND'
#cmd='interface wireless set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 rate-set=configured rx-chains=0,1 scan-list=5825-5875 security-profile=iB440 ssid=iBw supported-rates-a/g="" basic-rates-a/g=""'
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,timeout=5,password='HeWGEUx66m=_4!ND')
stdin, stdout, stderr = ssh.exec_command('sudo bash', get_pty = True)
time.sleep(0.1)
stdin.write('HeWGEUx66m=_4!ND\n')
stdin.flush()
stdin.write('whoami\n')
#time.sleep(1)
stdin.flush()
dd = stdout.readlines()
print(dd)
ssh.close()
After running the code there is no error, seems it stuck in some loop.,
Starting................................Please Wait
Using ssh with plink in single line command
C:\Users\Administrator\AppData\Local\Programs\Python\Python38>plink.exe -ssh -t admin#10.11.8.71 sudo bash admin#10.11.8.71's password: Access granted. Press Return to begin session. Password: bash-3.2# whoami root bash-3.2#```

To make it working properl i used channels from paramiko, and it worked like charm.
import paramiko
from paramiko import *
from paramiko.channel import Channel
import time
import os
import inspect
import datetime
from socket import *
import pandas as pd
df = pd.DataFrame(columns=["Ip","Status",'Remarks'])
root = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
#ips = ['10.23.0.30', '10.23.0.11','10.23.0.12','10.23.0.13']
ips = open(root+ "\\ahip.txt")
for ipp in ips:
ip = ipp.strip()
print(ip)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(ip, port=22,timeout = 5,username='op', password='C#Uj!AnX')
channel:Channel = ssh.invoke_shell()
#print(type(channel))
channel_data = str()
while True:
#channel.recv_ready():
#time.sleep(1)
channel_data += str(channel.recv(999))
channel.send("su -\n")
time.sleep(1)
#channel_data += str(channel.recv(999))
# if "Password" in channel_data:
channel.send("HeWGEUx\n")
time.sleep(3)
#channel_data += str(channel.recv(999))
channel.send("/bs/lteCli\n")
time.sleep(3)
channel.send("logger threshold set cli=6\n")
time.sleep(4)
channel.send("db set stackCfg [1] EnCLPC=0\n")
time.sleep(4)
channel.send("db get stackCfg EnCLPC\n")
time.sleep(3)
#channel.send("db get stackCfg EnCLPC\n")
time.sleep(.1)
channel_data += str(channel.recv(99999))
str2 = 'Done'
df.loc[ip]=[ip,str2,channel_data]
#print(channel_data)
channel.close()
ssh.close()
break
except (timeout ,AuthenticationException):
print(ip+'not done')
str1 = 'Not Done'
df.loc[ip]=[ip,'failed',str1]

Related

Telnetlib doesn't exit on huge output

I am trying to collect show tech-support from multiple devices using telnetlib only. And it works with a tiny issue. It collects the full output of the show tech-support command and exports it to a text file (export_text_support() is a simple with open() statement).
The entire output of the two switches in my lab is 32,768 and 16,325 lines for the show tech-support command. I get the entire output, BUT the tiny issue is that the session is not exited calling tn.write(b"exit\n") upon completion. It exits when exec-timeout is hit on the switch (when the session becomes idle), which is 10 minutes for both switches, not when there is nothing else to read from the tn.
I tried the same code below for shorter outputs like show running-config and I see the #exit (with a blank line at the end) in the file I export.
Short output
...
365 !
366 end
367
368 Switch#
369 Switch#exit
370
Huge output
....
16321 423 entries printed
16322
16323
16324
16325 Switch#
(As you can notice exit is not seen in the huge output sample and there is no blank line in the end)
This is my snippet
from telnetlib import Telnet
host = ""
username = ""
password = ""
def get_tech_support(host: str) -> None:
with Telnet(host=host, port=23) as tn:
# Check for credentials
if username:
tn.read_until(b"Username: ")
tn.write(username.encode("ascii") + b"\n")
if password:
tn.read_until(b"Password: ")
tn.write(password.encode("ascii") + b"\n")
# Some commands
commands = ["\n", "terminal width 115", "terminal length 0"]
[tn.write(command.encode("ascii") + b"\n") for command in commands]
# The main command
cmd = "show tech-support"
# Send the main command
tn.write(cmd.encode("ascii") + b"\n")
hostname = tn.read_until(b"#")
tn.write(b"\nexit\n")
command_output = tn.read_all().decode("ascii")
result = dict(
ip=host, hostname=hostname, command=cmd, command_output=command_output
)
export_tech_support(command_output=result) # Export the show command output
How can I make the session exits automatically upon completion for verbose outputs and avoid waiting for the exec-timeout to be hit (10 minutes in my case)
There is an issue with telnetlib and paramiko when we are extracting large output and configs.
This happens due to the console connection closing while running the script, so you have to look for a solution to maintain the console connection. I would suggest netmiko ,as netmiko version >= 1.0 also has Telnet support now.
For the example , you can check this script:
from pprint import pprint
import yaml
from netmiko import (
ConnectHandler,
NetmikoTimeoutException,
NetmikoAuthenticationException,
)
def send_show_command(device, commands):
result = {}
try:
with ConnectHandler(**device) as ssh:
ssh.enable()
for command in commands:
output = ssh.send_command(command)
result[command] = output
return result
except (NetmikoTimeoutException, NetmikoAuthenticationException) as error:
print(error)
if __name__ == "__main__":
device = {
"device_type": "cisco_ios_telnet", #Refer netmiko device type
"host": "192.168.100.1",
"username": "cisco",
"password": "cisco123",
"secret": "cisco", #if not required remove this
}
result = send_show_command(device, ["sh clock", "sh ip int br"])
pprint(result, width=120)

ssh to remote machine with password in script via python

I am working with remote machine. I had to ssh everytime i need verification of file update time and there are multiple scripts which will do ssh to the remote machine.
I look over internet but couldn't find according to my requirements.
I am trying to find a python script which uses ssh and the password is also in the script because my python scripts will check every 5 minutes the file modification times and i cannot enter password everytime the script execute.
I tried these codes from SO and internet but couldn't fulfil my need.
Establish ssh session by giving password using script in python
How to execute a process remotely using python
Also I enter into one remote machine through ssh simply.then I am trying to ssh but via python script to another remote machine cox this python script also include code to check the modification time of different files.. mean i already ssh to one remote machine and then i want to run some python scripts from there which checks file modification time of files on another remote machine.
Is there a simple way to ssh remote machine along with password in python script. .
I would be grateful.
If you want to try paramiko module. Here is a sample working python script.
import paramiko
def start_connection():
u_name = 'root'
pswd = ''
port = 22
r_ip = '198.x.x.x'
sec_key = '/mycert.ppk'
myconn = paramiko.SSHClient()
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
my_rsa_key = paramiko.RSAKey.from_private_key_file(sec_key)
session = myconn.connect(r_ip, username =u_name, password=pswd, port=port,pkey=my_rsa_key)
remote_cmd = 'ifconfig'
(stdin, stdout, stderr) = myconn.exec_command(remote_cmd)
print("{}".format(stdout.read()))
print("{}".format(type(myconn)))
print("Options available to deal with the connectios are many like\n{}".format(dir(myconn)))
myconn.close()
if __name__ == '__main__':
start_connection()
Adding my program as well here which relies on the user password and displays the status on different output files.
#!/bin/python3
import threading, time, paramiko, socket, getpass
from queue import Queue
locke1 = threading.Lock()
q = Queue()
#Check the login
def check_hostname(host_name, pw_r):
with locke1:
print ("Checking hostname :"+str(host_name)+" with " + threading.current_thread().name)
file_output = open('output_file','a')
file_success = open('success_file','a')
file_failed = open('failed_file','a')
file_error = open('error_file','a')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(host_name, username='root', password=pw_r, timeout=5)
#print ("Success")
file_success.write(str(host_name+"\n"))
file_success.close()
file_output.write("success: "+str(host_name+"\n"))
file_output.close()
# printing output if required from remote machine
#stdin,stdout,stderr = ssh.exec_command("hostname&&uptime")
#for line in stdout.readlines():
# print (line.strip())
except paramiko.SSHException:
# print ("error")
file_failed.write(str(host_name+"\n"))
file_failed.close()
file_output.write("failed: "+str(host_name+"\n"))
file_output.close()
#quit()
except paramiko.ssh_exception.NoValidConnectionsError:
#print ("might be windows------------")
file_output.write("failed: " + str(host_name + "\n"))
file_output.close()
file_failed.write(str(host_name+"\n"))
file_failed.close()
#quit()
except socket.gaierror:
#print ("wrong hostname/dns************")
file_output.write("error: "+str(host_name+"\n"))
file_output.close()
file_error.write(str(host_name + "\n"))
file_error.close()
except socket.timeout:
#print ("No Ping %%%%%%%%%%%%")
file_output.write("error: "+str(host_name+"\n"))
file_output.close()
file_error.write(str(host_name + "\n"))
file_error.close()
ssh.close()
def performer1():
while True:
hostname_value = q.get()
check_hostname(hostname_value,pw_sent)
q.task_done()
if __name__ == '__main__':
print ("This script checks all the hostnames in the input_file with your standard password and write the outputs in below files: \n1.file_output\n2.file_success \n3.file_failed \n4.file_error \n")
f = open('output_file', 'w')
f.write("-------Output of all hosts-------\n")
f.close()
f = open('success_file', 'w')
f.write("-------Success hosts-------\n")
f.close()
f = open('failed_file', 'w')
f.write("-------Failed hosts-------\n")
f.close()
f = open('error_file', 'w')
f.write("-------Hosts with error-------\n")
f.close()
with open("input_file") as f:
hostname1 = f.read().splitlines()
#Read the standard password from the user
pw_sent=getpass.getpass("Enter the Password:")
start_time1 = time.time()
for i in hostname1:
q.put(i)
#print ("all the hostname : "+str(list(q.queue)))
for no_of_threads in range(10):
t = threading.Thread(target=performer1)
t.daemon=True
t.start()
q.join()
print ("Check output files for results")
print ("completed task in" + str(time.time()-start_time1) + "seconds")

SSH connection not persistent

I have the following script which SSH's into a network server and executes some commands, for some reason the SSH connection opens but by the time the commands are executed it closes (I think), as a result the commands are failing with below error? Can anyone provide info how to make the SSH connection persistent?
#!/usr/bin/python
import os
import sys
import json
import fileinput
import pwd
from subprocess import Popen, PIPE, STDOUT
import re
import paramiko
import MySQLdb
resource = r'qca-cdit-01'
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(resource, username='username', password='passwordname')
#chan = ssh.get_transport().open_session()
chan = ssh.invoke_shell()
chan.get_pty()
commandstringlist = \
['/local/mnt/workspace/LA_host_builds/AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.01.01.081.031_msm8992',
'cd frameworks/base',
'git fetch ssh://cdit#review-android.company.com:29418/platform/frameworks/base refs/changes/21/1260821/2 && git cherry-pick FETCH_HEAD']
for cmd_val in commandstringlist:
#chan.exec_command(cmd_val)
chan.send(cmd_val)
print(chan.recv(1024))
error:
Traceback (most recent call last):
File "ssh_test.py", line 21, in <module>
chan.get_pty()
File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 60, in _check
return func(self, *args, **kwds)
File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 177, in get_pty
self._wait_for_event()
File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 1086, in _wait_for_event
raise e
paramiko.ssh_exception.SSHException: Channel closed
Every command you execute using exec_command has a channel of its own and therefore a context of its own. That context includes the working directory. You change the working directory in one context and then try to use it in another. Instead, use the same channel for all the commands. You can either open a channel and use it, or just issue all the commands at once.
commandstringlist = ['cd /local/mnt/workspace/test2 && cd data/log && git fetch ssh://username#review-android.company.com:29418/platform/data/log refs/changes/21/1260821/2 && git cherry-pick FETCH_HEAD']
Here are a few other questions that should explain this in more detail.
https://unix.stackexchange.com/questions/80821/why-does-cd-command-not-work-via-ssh
https://superuser.com/questions/46851/keeping-working-directory-across-ssh
https://stackoverflow.com/a/6770272/492773
The trick is to change to the directory before executing the command. You can easily integrate it into your execute_command:
def execute_command (cmd, pwd=None):
if pwd:
cmd = 'cd "%s";%s' % (pwd, cmd)
print cmd
si,so,se = ssh.exec_command(cmd)
print os.getcwd()
print "printing so"
soreadList = so.readlines()
print soreadList
print "printing se"
errList = se.readlines()
print errList
The command is run by a shell on the remote machine, so any shell tricks like setting environment variables could be added also.
Simply do :
#!/usr/bin/python
import os
import sys
import json
import fileinput
import pwd
from subprocess import Popen, PIPE, STDOUT
import re
import paramiko
import MySQLdb
resource = r'qca-cdit-01'
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(resource, username='username', password='passwordname')
#chan = ssh.get_transport().open_session()
chan = ssh.invoke_shell()
commandstringlist = \
['\n/local/mnt/workspace/LA_host_builds/AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.01.01.081.031_msm8992\n',
'\ncd frameworks/base\n',
'\ngit fetch ssh://cdit#review-android.company.com:29418/platform/frameworks/base refs/changes/21/1260821/2 && git cherry-pick FETCH_HEAD\n']
for cmd_val in commandstringlist:
#chan.exec_command(cmd_val)
chan.send(cmd_val)
print(chan.recv(8192))
which worked for me. (You forgot .send() doesn’t add lines automatically)
Can anyone provide info how to make the SSH connection persistent?
The following is an example of how to make an SSH connection persistent by attempting to execute a command and then falling back on connecting then executing the command when errors occur.
import paramiko
class sshConnection:
def __init__( self, host, un, pw ):
self.host = host
self.un = un
self.pw = pw
def connect( self ):
self.ssh = paramiko.SSHClient()
self.ssh.load_system_host_keys()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect(self.host, username=self.un, password=self.pw)
def cmd ( self, cmd, tries=0 ):
self.si, self.so, self.se = None, None, None
try:
self.si, self.so, self.se= self.ssh.exec_command(cmd)
except Exception, e:
if tries > 3:
raise
self.connect( )
self.cmd( cmd, tries+1 )
return self.si, self.so, self.se
conn = sshConnection( "host","username","password" )
si, out, err = conn.cmd("ls -al")
print "\n".join(map ( lambda x: x.strip(), out.readlines()) )

Enter an ssh password using the standard python library (not pexpect)

Related questions that are essentially asking the same thing, but have answers that don't work for me:
Make python enter password when running a csh script
How to interact with ssh using subprocess module
How to execute a process remotely using python
I want to ssh into a remote machine and run one command. For example:
ssh <user>#<ipv6-link-local-addr>%eth0 sudo service fooService status
The problem is that I'm trying to do this through a python script with only the standard libraries (no pexpect). I've been trying to get this to work using the subprocess module, but calling communicate always blocks when requesting a password, even though I supplied the password as an argument to communicate. For example:
proc = subprocess.Popen(
[
"ssh",
"{testUser1}#{testHost1}%eth0".format(**locals()),
"sudo service cassandra status"],
shell=False,
stdin=subprocess.PIPE)
a, b = proc.communicate(input=testPasswd1)
print "a:", a, "b:", b
print "return code: ", proc.returncode
I've tried a number of variants of the above, as well (e.g., removing "input=", adding/removing subprocess.PIPE assignments to stdout and sterr). However, the result is always the same prompt:
ubuntu#<ipv6-link-local-addr>%eth0's password:
Am I missing something? Or is there another way to achieve this using the python standard libraries?
This answer is just an adaptation of this answer by Torxed, which I recommend you go upvote. It simply adds the ability to capture the output of the command you execute on the remote server.
import pty
from os import waitpid, execv, read, write
class ssh():
def __init__(self, host, execute='echo "done" > /root/testing.txt',
askpass=False, user='root', password=b'SuperSecurePassword'):
self.exec_ = execute
self.host = host
self.user = user
self.password = password
self.askpass = askpass
self.run()
def run(self):
command = [
'/usr/bin/ssh',
self.user+'#'+self.host,
'-o', 'NumberOfPasswordPrompts=1',
self.exec_,
]
# PID = 0 for child, and the PID of the child for the parent
pid, child_fd = pty.fork()
if not pid: # Child process
# Replace child process with our SSH process
execv(command[0], command)
## if we havn't setup pub-key authentication
## we can loop for a password promt and "insert" the password.
while self.askpass:
try:
output = read(child_fd, 1024).strip()
except:
break
lower = output.lower()
# Write the password
if b'password:' in lower:
write(child_fd, self.password + b'\n')
break
elif b'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
write(child_fd, b'yes\n')
else:
print('Error:',output)
# See if there's more output to read after the password has been sent,
# And capture it in a list.
output = []
while True:
try:
output.append(read(child_fd, 1024).strip())
except:
break
waitpid(pid, 0)
return ''.join(output)
if __name__ == "__main__":
s = ssh("some ip", execute="ls -R /etc", askpass=True)
print s.run()
Output:
/etc:
adduser.conf
adjtime
aliases
alternatives
apm
apt
bash.bashrc
bash_completion.d
<and so on>

source command does not take effect

I have a cluster of machines, and I write a Python script to change the hostname; the code follows.
What puzzles me is that the source command only takes effect on some machines, not all. After I repeat several times, then all hostname take effect [BTW: I can change the hostname in /etc/hostname, but the hostname service do not take effect.]
import paramiko
import time
import threading
import os
cmd0 = "sudo source /root/.bashrc"
cmd1 = "sudo service hostname stop"
cmd2 = "sudo service hostname start"
def executeit(ip):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, 22, "root")
ssh.exec_command(cmd0)
stdin, stdout, stderr = ssh.exec_command(cmd1)
out = stdout.readlines()
for o in out:
print(o)
time.sleep(1)
ssh.exec_command(cmd2)
ssh.close()
print("=======")
def main():
fr = open("info.txt", "r")
contents = fr.read().splitlines()
fr.close()
for ip in contents:
t = threading.Thread(target=executeit, args=(ip,))
t.start()
main()

Categories