LoginSignup
2
2

More than 1 year has passed since last update.

Paramikoでget_pty=Trueにしてsudoコマンドを実行してパスワードを入力しても反応がないとき

Last updated at Posted at 2021-11-04

ことはじめ

  • 設定が間違ってないかどうか、全ホストのとあるconfigファイルをちょっと確認したかった
  • rootでしか表示できないファイルだったのでcatするにしてもsudo(パスワード入力)が必要だった
  • expectを使ったスクリプトよりpythonの方がわかりやすいと思った

現象

@kanedaq さんの

Pythonコードから多段SSHでホストに接続し、コマンドを実行してstdout出力を受け取る

とかを参考にコードを書いたのだけど、なぜか動かない。
動かないというかsudoパスワードを入力した後の結果が全く返ってこないという現象に出会った。

(おそらくの)原因

  • パスワードの入力タイミングが早すぎたのが原因と思われる
  • ちょっと反応の悪いホストの場合、sudoのパスワードプロンプトが表示されるのをちゃんと待ってからパスワードを入力する必要がある模様

解決策

  • 考えてみればそりゃそうかという感じだが、一律で5秒sleepをはさむとかすると対象ホストが増えれば増えるほど比例して待ち時間が長くなるのが嫌だった
  • なので、パスワードプロンプトが表示されるまで待って入力可能になった瞬間に入力するようにする

環境

  • 5.4.72-microsoft-standard-WSL2
  • Ubuntu 20.04.3 LTS
  • Python 3.8.5
  • Paramiko 2.7.2

リモートでsudoコマンドを実行する最低限のコード

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import paramiko
import time

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 接続
client.connect(
    hostname="hostname",
    username="testuser",
    password="password",
    port=22,
)

# cmd実行
cmd = "sudo whoami"
stdin, stdout, stderr = client.exec_command(cmd, get_pty=True)

while len(stdout.channel.in_buffer) == 0:
    # stdoutにパスワードプロンプトが出力されるまで待ち続ける
    continue

# とてつもなく反応が悪いホストの場合は入力可能になるまで更に待った方がいい?
# time.sleep(1)

# sudoパスワード入力
stdin.channel.send("password" + "\n")
# stdinだけ閉じる
stdin.channel.shutdown_write()

# 実行結果
# (留意点: get_pty=Trueにしているとstderrもこっちに出力されている)
print(stdout.read().decode().strip())

# 切断
client.close()
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2