web-dev-qa-db-ja.com

Paramikoでインタラクティブコマンドを実行する

私はparamikoを介してインタラクティブなコマンドを実行しようとしています。 cmdの実行はパスワードの入力を試みますが、paramikoのexec_commandを介してパスワードを指定する方法がわからず、実行がハングします。 cmd実行が入力をインタラクティブに予期する場合、値を端末に送信する方法はありますか?

ssh = paramiko.SSHClient()
ssh.connect(server, username=username, password=password)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("psql -U factory -d factory -f /tmp/data.sql")

誰もこれがどのように対処できるか知っていますか?ありがとうございました。

37
Sharmila

完全なparamikoディストリビューションには、多くの優れた demos が付属しています。

Demosサブディレクトリで、demo.pyおよびinteractive.pyインタラクティブなTTYの完全な例がありますが、これはおそらくあなたの状況にとってはやりすぎでしょう。

上記の例ではssh_stdinは、標準のPythonファイルオブジェクトのように機能するため、ssh_stdin.writeは、チャネルが開いている限り機能します。

標準入力に書き込む必要はありませんでしたが、ドキュメントでは、コマンドが終了するとすぐにチャネルが閉じられるため、標準のstdin.writeパスワードを送信するメソッドはおそらく機能しません。チャネル自体には、より詳細な制御を可能にする低レベルのparamikoコマンドがあります- SSHClient.exec_command メソッドはすべての詳細な部分に実装されています。

30
James Brady

ssh 、Paramikoのフォークを使用して、インタラクティブなsshセッションを作成しようとすると、同じ問題が発生しました。

私は周りを掘り下げてこの記事を見つけました:

更新されたリンク(リンクが404を生成する前の最後のバージョン): http://web.archive.org/web/20170912043432/http ://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/

あなたの例を続けるには、あなたがすることができます

ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("psql -U factory -d factory -f /tmp/data.sql")
ssh_stdin.write('password\n')
ssh_stdin.flush()
output = ssh_stdout.read()

この記事では、exec_commandに関する完全にインタラクティブなシェルについて説明します。これはソースの例よりも使いやすいことがわかりました。

オリジナルリンクhttp://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different /

10
afrosteve

両方の世界(expectとsshラッパー)を最大限に活用するには、Pexpectが必要です。

5
ax25
ssh = paramiko.SSHClient()
ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(server_IP,22,username, password)


stdin, stdout, stderr = ssh.exec_command('/Users/lteue/Downloads/uecontrol-CXC_173_6456-R32A01/uecontrol.sh -Host localhost ')
alldata = ""
while not stdout.channel.exit_status_ready():
   solo_line = ""        
   # Print stdout data when available
   if stdout.channel.recv_ready():
      # Retrieve the first 1024 bytes
      solo_line = stdout.channel.recv(1024) 
      alldata += solo_line
   if(cmp(solo_line,'uec> ') ==0 ):    #Change Conditionals to your code here  
     if num_of_input == 0 :
      data_buffer = ""    
      for cmd in commandList :
       #print cmd
       stdin.channel.send(cmd)        # send input commmand 1
      num_of_input += 1
     if num_of_input == 1 :
      stdin.channel.send('q \n')      # send input commmand 2 , in my code is exit the interactive session, the connect will close.
      num_of_input += 1 
print alldata
ssh.close()              

Stdout.channel.recv_ready()をチェックせずに直接使用するとstdout.read()がハングする理由:in while stdout.channel.exit_status_ready():

私の場合、リモートサーバーでコマンドを実行した後、セッションはユーザーの入力を待っており、入力「q」の後、接続を閉じます。ただし、 'q'を入力する前に、stdout.read()はEOFを待機します。バッファが大きい場合、この方法は機能しないようです。

  • whileでstdout.read(1)を試しましたが、動作します
    whileでstdout.readline()を試しましたが、それも動作します。
    stdin、stdout、stderr = ssh.exec_command( '/ Users/lteue/Downloads/uecontrol')
    stdout.read()はハングします
3
kevin yu

私はparamikoに精通していませんが、これはうまくいくかもしれません:

ssh_stdin.write('input value')
ssh_stdin.flush()

Stdinの詳細:

http://docs.python.org/library/sys.html?highlight=stdin#sys.stdin

3
monkut

例を見て、同様の方法で行います

http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/ から入手):=):

    ssh.connect('127.0.0.1', username='jesse', 
        password='lol')
    stdin, stdout, stderr = ssh.exec_command(
        "Sudo dmesg")
    stdin.write('lol\n')
    stdin.flush()
    data = stdout.read.splitlines()
    for line in data:
        if line.split(':')[0] == 'AirPort':
            print line
0
Paweł Wojtal

このメソッドを使用して、「OK」またはパスワードなどの確認メッセージを送信できます。これは、例を使用した私のソリューションです。

def SpecialConfirmation(command, message, reply):
    net_connect.config_mode()    # To enter config mode
    net_connect.remote_conn.sendall(str(command)+'\n' )
    time.sleep(3)
    output = net_connect.remote_conn.recv(65535).decode('utf-8')
    ReplyAppend=''
    if str(message) in output:
        for i in range(0,(len(reply))):
            ReplyAppend+=str(reply[i])+'\n'
        net_connect.remote_conn.sendall(ReplyAppend)
        output = net_connect.remote_conn.recv(65535).decode('utf-8') 
    print (output)
    return output

CryptoPkiEnroll=['','','no','no','yes']

output=SpecialConfirmation ('crypto pki enroll TCA','Password' , CryptoPkiEnroll )
print (output)
0
Karate Mohammed