web-dev-qa-db-ja.com

Paramikoの単一セッションで複数のコマンドを実行するにはどうすればよいですか? (Python)

def exec_command(self, command, bufsize=-1):
    #print "Executing Command: "+command
    chan = self._transport.open_session()
    chan.exec_command(command)
    stdin = chan.makefile('wb', bufsize)
    stdout = chan.makefile('rb', bufsize)
    stderr = chan.makefile_stderr('rb', bufsize)
    return stdin, stdout, stderr

Paramikoでコマンドを実行する場合、exec_commandを実行すると常にセッションがリセットされます。 Sudoまたはsuを実行し、別のexec_commandを実行するときにそれらの特権を保持したい。別の例は、exec_command( "cd /")を試みてからexec_commandを再度実行し、ルートディレクトリに配置することです。 exec_command( "cd /; ls -l")のようにできることは知っていますが、別の関数呼び出しで行う必要があります。

38
Takkun

非インタラクティブなユースケース

これはnon-interactiveの例です... cd tmpls、次にexit

import sys
sys.stderr = open('/dev/null')       # Silence silly warnings from paramiko
import paramiko as pm
sys.stderr = sys.__stderr__
import os

class AllowAllKeys(pm.MissingHostKeyPolicy):
    def missing_Host_key(self, client, hostname, key):
        return

Host = '127.0.0.1'
USER = ''
PASSWORD = ''

client = pm.SSHClient()
client.load_system_Host_keys()
client.load_Host_keys(os.path.expanduser('~/.ssh/known_hosts'))
client.set_missing_Host_key_policy(AllowAllKeys())
client.connect(Host, username=USER, password=PASSWORD)

channel = client.invoke_Shell()
stdin = channel.makefile('wb')
stdout = channel.makefile('rb')

stdin.write('''
cd tmp
ls
exit
''')
print stdout.read()

stdout.close()
stdin.close()
client.close()

インタラクティブなユースケース
インタラクティブなユースケースがある場合、この回答は役に立ちません...個人的には、インタラクティブセッションにpexpectまたはexscriptを使用します。

36
Mike Pennington

厳密に言えば、できません。 ssh仕様によると:

セッションは、プログラムのリモート実行です。プログラムは、シェル、アプリケーション、システムコマンド、または組み込みサブシステムの場合があります。

これは、コマンドが実行されると、セッションが終了することを意味します。 1つのセッションで複数のコマンドを実行することはできません。ただし、できることは、リモートシェル(== 1つのコマンド)を起動し、stdinなどを介してそのシェルと対話することです(pythonスクリプトを実行することと、インタラクティブ通訳)

18
Steven

_\n_文字で区切られたコマンド文字列を作成してみてください。それは私のために働いた。ために。例えばssh.exec_command("command_1 \n command_2 \n command_3")

13
Sandeep

そのためには、クライアントでシェルを呼び出してコマンドを送信します。参照してください こちら
ページにはpython 3.5。のコードがあります。pythin2.7で動作するようにコードを少し変更しました。参照用のコードをここに追加します。

import threading, paramiko

strdata=''
fulldata=''

class ssh:
    Shell = None
    client = None
    transport = None

    def __init__(self, address, username, password):
        print("Connecting to server on ip", str(address) + ".")
        self.client = paramiko.client.SSHClient()
        self.client.set_missing_Host_key_policy(paramiko.client.AutoAddPolicy())
        self.client.connect(address, username=username, password=password, look_for_keys=False)
        self.transport = paramiko.Transport((address, 22))
        self.transport.connect(username=username, password=password)

        thread = threading.Thread(target=self.process)
        thread.daemon = True
        thread.start()

    def close_connection(self):
        if(self.client != None):
            self.client.close()
            self.transport.close()

    def open_Shell(self):
        self.Shell = self.client.invoke_Shell()

    def send_Shell(self, command):
        if(self.Shell):
            self.Shell.send(command + "\n")
        else:
            print("Shell not opened.")

    def process(self):
        global strdata, fulldata
        while True:
            # Print data when available
            if self.Shell is not None and self.Shell.recv_ready():
                alldata = self.Shell.recv(1024)
                while self.Shell.recv_ready():
                    alldata += self.Shell.recv(1024)
                strdata = strdata + str(alldata)
                fulldata = fulldata + str(alldata)
                strdata = self.print_lines(strdata) # print all received data except last line

    def print_lines(self, data):
        last_line = data
        if '\n' in data:
            lines = data.splitlines()
            for i in range(0, len(lines)-1):
                print(lines[i])
            last_line = lines[len(lines) - 1]
            if data.endswith('\n'):
                print(last_line)
                last_line = ''
        return last_line


sshUsername = "SSH USERNAME"
sshPassword = "SSH PASSWORD"
sshServer = "SSH SERVER ADDRESS"


connection = ssh(sshServer, sshUsername, sshPassword)
connection.open_Shell()
connection.send_Shell('cmd1')
connection.send_Shell('cmd2')
connection.send_Shell('cmd3')
time.sleep(10)
print(strdata)    # print the last line of received data
print('==========================')
print(fulldata)   # This contains the complete data received.
print('==========================')
connection.close_connection()
2
Nagabhushan S N
cmd = 'ls /home/dir'
self.ssh_stdin, self.ssh_stdout, self.ssh_stderr = self.ssh.exec_command(cmd)
print self.ssh_stdout.read()
cmd2 = 'cat /home/dir/test.log'
self.ssh_stdin2, self.ssh_stdout2, self.ssh_stderr2 = self.ssh.exec_command(cmd2)
print self.ssh_stdout2.read()
2
user2661518