Run multiple commands in a single ssh session usin

2019-08-10 12:50发布

问题:

I am trying to run several commands in a single ssh session and save the output of each command in a different file.

The code that works (but it saves all the output in a single file)

conn = Popen(['ssh',host, "ls;uname -a;pwd"], stdin=PIPE, stdout = open ('/output.txt','w'))
mypassword = conn.communicate('password')

Codes that I am trying to work but not working...

cmd = ['ls', 'pwd', 'uname']
conn = Popen(['ssh',host, "{};{};{}".format(cmd[0],cmd[1],cmd[2])], stdin=PIPE, stdout = output.append('a')) 
mypassword = conn.communicate('password')

print (output)
length = range(len(output))
print length
for i in output:
open("$i",'w') 

and

cmd = ['ls', 'pwd', 'uname']
conn = Popen(['ssh',host, "{};{};{}".format(cmd[0],cmd[1],cmd[2])], stdin=PIPE, stdout = output())
mypassword = conn.communicate('password')

def output():

    for i in cmd:
        open(i,'w') 
    return

Not sure what is the best way of doing it. Should I save it in an array and then save each item in a separate file or should I call a function that will do it? NOTE that the commands I want to run do not have small output like given in examples here (uname, pwd); it is big as tcpdump, lsof etc.

回答1:

A single ssh session runs a single command e.g., /bin/bash on the remote host -- you can pass input to that command to emulate running multiple commands in a single ssh session.

Your code won't run even a single command. There are multiple issues in it:

  1. ssh may read the password directly from the terminal (not its stdin stream). conn.communicate('password') in your code writes to ssh's stdin therefore ssh won't get the password.

    There are multiple ways to authenticate via ssh e.g., use ssh keys (passwordless login).

  2. stdout = output.append('a') doesn't redirect ssh's stdout because .append list method returns None.

    It won't help you to save output of several commands to different files. You could redirect the output to remote files and copy them back later: ls >ls.out; uname -a >uname.out; pwd >pwd.out.

    A (hacky) alternative is to use inside stream markers (echo <GUID>) to differentiate the output from different commands. If the output can be unlimited; learn how to read subprocess' output incrementally (without calling .communicate() method).

  3. for i in cmd: open(i,'w') is pointless. It opens (and immediately closes on CPython) multiple files without using them.

    To avoid such basic mistakes, write several Python scripts that operate on local files.



回答2:

SYS_STATS={"Number of CPU Cores":"cat /proc/cpuinfo|grep -c 'processor'\n",
               "CPU MHz":"cat /proc/cpuinfo|grep 'cpu MHz'|head -1|awk -F':' '{print $2}'\n",
               "Memory Total":"cat /proc/meminfo|grep 'MemTotal'|awk -F':' '{print $2}'|sed 's/ //g'|grep -o '[0-9]*'\n",
               "Swap Total":"cat /proc/meminfo|grep 'SwapTotal'|awk -F':' '{print $2}'|sed 's/ //g'|grep -o '[0-9]*'\n"}


def get_system_details(self,ipaddress,user,key):
        _OutPut={}
        values=[]
        sshProcess = subprocess.Popen(['ssh','-T','-o StrictHostKeyChecking=no','-i','%s' % key,'%s@%s'%(user,ipaddress),"sudo","su"],
                                      stdin=subprocess.PIPE, stdout = subprocess.PIPE, universal_newlines=True,bufsize=0)

        for element in self.SYS_STATS1:
            sshProcess.stdin.write("echo END\n")
            sshProcess.stdin.write(element)

        sshProcess.stdin.close()
        for element in sshProcess.stdout:
            if element.rstrip('\n')!="END":
                values.append(element.rstrip('\n'))
        mapObj={k: v for k, v in zip(self.SYS_STATS_KEYS, values)}

        return mapObj


标签: python ssh popen