How to run this script in a more sophisticated way?

Asked

Viewed 137 times

-1

Good morning.

I am using this code to update the firmware of my company’s servers.

However, I wanted to use this same code to update a list of servers, not just one.

Follow the original code:

#!/usr/bin/python

from paramiko import SSHClient
import paramiko

    class SSH:
            def __init__(self):
                self.ssh = SSHClient()
                self.ssh.load_system_host_keys()
                self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                self.ssh.connect(hostname='blhp0032.locaweb.com.br',username='Administrator',password='SenhaServidor')

            def exec_cmd(self,cmd):
                stdin,stdout,stderr = self.ssh.exec_command(cmd)
                if stderr.channel.recv_exit_status() != 0:
                    print stderr.read()
                else:
                    print stdout.read()

    if __name__ == '__main__':
        ssh = SSH()
        ssh.exec_cmd("update image force http://firmware.tecnologia.ws/firmware/hpoa485.bin")

My question is the following: I tried to adapt the code to update a list, using Ubuntu commands, but no obitve success. Follows modified code:

#!/usr/bin/python

from paramiko import SSHClient
import paramiko
import sys

    class SSH:
        def processar(ip):

            def __init__(self):
                self.ssh = SSHClient()
                self.ssh.load_system_host_keys()
                self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                self.ssh.connect(hostname=ip,username='Administrator',password='SenhaServidor')

            def exec_cmd(self,cmd):
                stdin,stdout,stderr = self.ssh.exec_command(cmd)
                if stderr.channel.recv_exit_status() != 0:
                    print stderr.read()
                else:
                    print stdout.read()

    if __name__ == '__main__':
        ssh = SSH()
        ssh.exec_cmd("update image force http://firmware.tecnologia.ws/firmware/hpoa485.bin")


        if __name__ == "__main__":
            for ip in sys.argv[1:]: 
                processar(ip)

However, when I turn the wheel on the terminal cat lista.txt | xargs script.py it returns me the following error:

    Traceback (most recent call last):
  File "update_oa_teste.py", line 24, in <module>
    ssh.exec_cmd("update image force http://firmware.tecnologia.ws/firmware/hpoa485.bin")
AttributeError: SSH instance has no attribute 'exec_cmd'

Remembering that I created a file . txt in the same directory as the script, containing the list of servers on which I want to run the script’s SSH command.

Help me out, please.

Thank you!!

  • You know the Fabric Library?

  • Could you put the code with the correct indentation in the question? Incorrect indentation may be the cause of the error.

  • By the way, you had already asked practically this in How to use this script for a server list? - Python

  • Ansible, can change your life. Take a look. Have a great day.

1 answer

0

You don’t have to make it so complicated ip as a parameter of __init__ of its original class even, without creating more sublevels:

#!/usr/bin/python

from paramiko import SSHClient
import paramiko
import sys

class SSH:
    def __init__(self, ip):
        self.ssh = SSHClient()
        self.ssh.load_system_host_keys()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(hostname=ip, username='Administrator',password='SenhaServidor')

    def exec_cmd(self,cmd):
        stdin,stdout,stderr = self.ssh.exec_command(cmd)
        #if stderr.channel.recv_exit_status() != 0:
        #    print stderr.read()
        #else:
        #    print stdout.read()
        return stdin, stdout, stderr

if __name__ == '__main__':
    results = []

    for ip in sys.argv[1:]:
        ssh = SSH(ip)
        result = ssh.exec_cmd("update image force http://firmware.tecnologia.ws/firmware/hpoa485.bin")
        results.append(result)

    for stdin, stdout, stderr in results:
        if stderr.channel.recv_exit_status() != 0:
            print stderr.read()
        else:
            print stdout.read()

In addition, another modification was to take the recovery of results from the exec_cmd, to avoid the method waiting for results from one of the servers. The way I did, it will send the command to all servers first, and then wait for the results, so the command runs simultaneously on all servers.

  • Man, thank you so much. Really, it was pretty simple even hahahaha

Browser other questions tagged

You are not signed in. Login or sign up in order to post.