Voer commando’s uit via ssh met Python

Ik ben een script aan het schrijven om enkele commandoregelcommando’s in Python te automatiseren. Op dit moment bel ik als volgt:

cmd = "some unix command"
retcode = subprocess.call(cmd,shell=True)

Ik moet echter enkele opdrachten uitvoeren op een externe computer. Handmatig zou ik inloggen met ssh en vervolgens de opdrachten uitvoeren. Hoe zou ik dit automatiseren in Python? Ik moet inloggen met een (bekend) wachtwoord op de externe machine, dus ik kan niet zomaar cmd = ssh user@remotehostgebruiken. Ik vraag me af of er een module is die ik zou moeten gebruiken?


Antwoord 1, autoriteit 100%

Ik verwijs je naar paramiko

zie deze vraag

ssh = paramiko.SSHClient()
ssh.connect(server, username=username, password=password)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmd_to_execute)

Als je ssh-sleutels gebruikt, doe dan:

k = paramiko.RSAKey.from_private_key_file(keyfilename)
# OR k = paramiko.DSSKey.from_private_key_file(keyfilename)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=host, username=user, pkey=k)

Antwoord 2, autoriteit 22%

Of je kunt gewoon commands.getstatusoutput:

  commands.getstatusoutput("ssh machine 1 'your script'")

Ik heb het veel gebruikt en het werkt geweldig.

Gebruik in Python 2.6+ subprocess.check_output.


Antwoord 3, autoriteit 17%

Houd het simpel. Geen bibliotheken vereist.

import subprocess
subprocess.Popen("ssh {user}@{host} {cmd}".format(user=user, host=host, cmd='ls -l'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

Antwoord 4, autoriteit 9%

Ik vond paramiko een beetje te laag niveau en Fabric niet bijzonder geschikt om als bibliotheek te worden gebruikt, dus heb ik mijn eigen bibliotheek samengesteld met de naam spurdie paramiko gebruikt om een iets mooiere interface te implementeren:

import spur
shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
result = shell.run(["echo", "-n", "hello"])
print result.output # prints hello

Als je binnen een shell moet rennen:

shell.run(["sh", "-c", "echo -n hello"])

Antwoord 5, autoriteit 4%

Iedereen heeft al aangegeven (aanbevolen) het gebruik van paramikoen ik deel alleen een python-code (API zou je kunnen zeggen) waarmee je meerdere opdrachten in één keer kunt uitvoeren.

om commando’s uit te voeren op verschillende nodes, gebruik: Commands().run_cmd(host_ip, list_of_commands)

Je zult één TODO zien, die ik heb bewaard om de uitvoering te stoppen als een van de opdrachten niet wordt uitgevoerd, ik weet niet hoe ik het moet doen. deel alsjeblieft je kennis

#!/usr/bin/python
import os
import sys
import select
import paramiko
import time
class Commands:
    def __init__(self, retry_time=0):
        self.retry_time = retry_time
        pass
    def run_cmd(self, host_ip, cmd_list):
        i = 0
        while True:
        # print("Trying to connect to %s (%i/%i)" % (self.host, i, self.retry_time))
        try:
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            ssh.connect(host_ip)
            break
        except paramiko.AuthenticationException:
            print("Authentication failed when connecting to %s" % host_ip)
            sys.exit(1)
        except:
            print("Could not SSH to %s, waiting for it to start" % host_ip)
            i += 1
            time.sleep(2)
        # If we could not connect within time limit
        if i >= self.retry_time:
            print("Could not connect to %s. Giving up" % host_ip)
            sys.exit(1)
        # After connection is successful
        # Send the command
        for command in cmd_list:
            # print command
            print "> " + command
            # execute commands
            stdin, stdout, stderr = ssh.exec_command(command)
            # TODO() : if an error is thrown, stop further rules and revert back changes
            # Wait for the command to terminate
            while not stdout.channel.exit_status_ready():
                # Only print data if there is data to read in the channel
                if stdout.channel.recv_ready():
                    rl, wl, xl = select.select([ stdout.channel ], [ ], [ ], 0.0)
                    if len(rl) > 0:
                        tmp = stdout.channel.recv(1024)
                        output = tmp.decode()
                        print output
        # Close SSH connection
        ssh.close()
        return
def main(args=None):
    if args is None:
        print "arguments expected"
    else:
        # args = {'<ip_address>', <list_of_commands>}
        mytest = Commands()
        mytest.run_cmd(host_ip=args[0], cmd_list=args[1])
    return
if __name__ == "__main__":
    main(sys.argv[1:])

Bedankt!


Antwoord 6, autoriteit 3%

paramikowerkte eindelijk voor mij na het toevoegen van een extra regel, wat erg belangrijk is (regel 3):

import paramiko
p = paramiko.SSHClient()
p.set_missing_host_key_policy(paramiko.AutoAddPolicy())   # This script doesn't work for me unless this line is added!
p.connect("server", port=22, username="username", password="password")
stdin, stdout, stderr = p.exec_command("your command")
opt = stdout.readlines()
opt = "".join(opt)
print(opt)

Zorg ervoor dat het paramiko-pakket is geïnstalleerd.
Originele bron van de oplossing: Bron


Antwoord 7, autoriteit 2%

Ik heb paramikoeen heleboel (leuk) en pxssh(ook leuk). Ik zou het ook aanraden. Ze werken een beetje anders, maar hebben een relatief grote overlap in gebruik.


Antwoord 8, autoriteit 2%

Het geaccepteerde antwoord werkte niet voor mij, dit is wat ik in plaats daarvan heb gebruikt:

import paramiko
import os
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# ssh.load_system_host_keys()
ssh.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
ssh.connect("d.d.d.d", username="user", password="pass", port=22222)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("ls -alrt")
exit_code = ssh_stdout.channel.recv_exit_status() # handles async exit error 
for line in ssh_stdout:
    print(line.strip())

total 44
-rw-r--r--.  1 root root  129 Dec 28  2013 .tcshrc
-rw-r--r--.  1 root root  100 Dec 28  2013 .cshrc
-rw-r--r--.  1 root root  176 Dec 28  2013 .bashrc
...

Als alternatief kunt u sshpass:

gebruiken

import subprocess
cmd = """ sshpass -p "myPas$" ssh [email protected] -p 22222 'my command; exit' """
print( subprocess.getoutput(cmd) )

Referenties:

  1. https://github.com/onyxfish/relay/issues/11
  2. https://stackoverflow.com/a/61016663/797495

Opmerkingen:

  1. Zorg ervoor dat je minimaal één keer handmatig verbinding maakt met het externe systeem via ssh (ssh root@ip) en accepteer de openbare sleutel, dit is vele malen de reden om geen verbinding te kunnen maken met behulp van paramikoof andere geautomatiseerde ssh-scripts.

Antwoord 9

Werkt perfect…

import paramiko
import time
ssh = paramiko.SSHClient()
#ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.106.104.24', port=22, username='admin', password='')
time.sleep(5)
print('connected')
stdin, stdout, stderr = ssh.exec_command(" ")
def execute():
       stdin.write('xcommand SystemUnit Boot Action: Restart\n')
       print('success')
execute()

10

U kunt een van deze opdrachten gebruiken, dit zal u ook helpen om een ​​wachtwoord te geven.

cmd = subprocess.run(["sshpass -p 'password' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected] ps | grep minicom"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print(cmd.stdout)
OR
cmd = subprocess.getoutput("sshpass -p 'password' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected] ps | grep minicom")
print(cmd)

11

Gebruiker vragen om de opdracht in te voeren volgens het apparaat dat ze inloggen.
De onderstaande code is gevalideerd door Pep8online.com.

import paramiko
import xlrd
import time
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
loc = ('/Users/harshgow/Documents/PYTHON_WORK/labcred.xlsx')
wo = xlrd.open_workbook(loc)
sheet = wo.sheet_by_index(0)
Host = sheet.cell_value(0, 1)
Port = int(sheet.cell_value(3, 1))
User = sheet.cell_value(1, 1)
Pass = sheet.cell_value(2, 1)
def details(Host, Port, User, Pass):
    time.sleep(2)
    ssh.connect(Host, Port, User, Pass)
    print('connected to ip ', Host)
    stdin, stdout, stderr = ssh.exec_command("")
    x = input('Enter the command:')
    stdin.write(x)
    stdin.write('\n')
    print('success')
details(Host, Port, User, Pass)

Antwoord 12

#Reading the Host,username,password,port from excel file
import paramiko 
import xlrd
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
loc = ('/Users/harshgow/Documents/PYTHON_WORK/labcred.xlsx')
wo = xlrd.open_workbook(loc)
sheet = wo.sheet_by_index(0)
Host = sheet.cell_value(0,1)
Port = int(sheet.cell_value(3,1))
User = sheet.cell_value(1,1)
Pass = sheet.cell_value(2,1)
def details(Host,Port,User,Pass):
    ssh.connect(Host, Port, User, Pass)
    print('connected to ip ',Host)
    stdin, stdout, stderr = ssh.exec_command("")
    stdin.write('xcommand SystemUnit Boot Action: Restart\n')
    print('success')
details(Host,Port,User,Pass)

Antwoord 13

Hieronder voorbeeld, indien u gebruikersinvoer wilt voor hostnaam, gebruikersnaam, wachtwoord en poortnummer.

 import paramiko
  ssh = paramiko.SSHClient()
  ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  def details():
  Host = input("Enter the Hostname: ")
  Port = input("Enter the Port: ")
  User = input("Enter the Username: ")
  Pass = input("Enter the Password: ")
  ssh.connect(Host, Port, User, Pass, timeout=2)
  print('connected')
  stdin, stdout, stderr = ssh.exec_command("")
  stdin.write('xcommand SystemUnit Boot Action: Restart\n')
  print('success')
  details()

Other episodes