私はpythonのサブプロセスとsshからさまざまなlinuxコマンドを実行しようとしています。コマンドを実行し、stderr
とstdout
の長さをチェックして、コマンドが成功したかどうかを確認したいと考えています。たとえば、エラーがなければ成功したとします。問題は、最初の接続後にすべての出力がstdout
になることです。Pythonのサブプロセス(間違って?)sshのstderrとstdoutをマージする
私はparamikoを使用しようとしましたが、信頼できない認証動作を続けました。このアプローチはもっとうまくいくように思えます。以下のようなものを出力
import subprocess
import os
import pty
from select import select
class open_ssh_helper(object):
def __init__(self, host="127.0.0.1", user="root"):
self.host = host
self.user = user
self.cmd = ['ssh',
user +'@'+host,
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null"]
self.prompt = '~#'
self.error = ''
self.output = ''
self.mtty_stdin, self.stty_stdin = pty.openpty()
self.mtty_stdout, self.stty_stdout = pty.openpty()
self.mtty_stderr, self.stty_stderr = pty.openpty()
self.ssh = subprocess.Popen(self.cmd,
shell=False,
stdin=self.stty_stdin,
stdout=self.stty_stdout,
stderr=self.stty_stderr)
self._read_stderr()
self._read_stdout()
def _reader(self, read_pty):
char = ""
buf = ""
while True:
rs, ws, es = select([read_pty], [], [], 0.5)
if read_pty in rs:
char = os.read(rs[0], 1)
buf += char
else:
break
return buf
def _read_stderr(self):
self.error = self._reader(self.mtty_stderr)
def _read_stdout(self):
self.output = self._reader(self.mtty_stdout)
def execute(self, command):
os.write(self.mtty_stdin, command)
self._read_stderr()
self._read_stdout()
if __name__=='__main__':
ss = open_ssh_helper('10.201.202.236', 'root')
print "Error: \t\t: " + ss.error
print "Output: \t: " + ss.output
ss.execute("cat /not/a/file\n")
print "Error: \t\t: " + ss.error
print "Output: \t: " + ss.output
:エラー行として印刷されるそのようなファイルやディレクトリ:/ない/ A /ファイル:
Error: : Warning: Permanently added '10.201.202.236' (ECDSA) to the list of known hosts.
Debian GNU/Linux 8
BeagleBoard.org Debian Image xxxx-xx-xx
Support/FAQ: http://elinux.org/Beagleboard:BeagleBoneBlack_Debian
Output: : Last login: Thu Oct 5 07:32:06 2017 from 10.201.203.29
[email protected]:~#
Error: :
Output: : cat /not/a/file
cat: /not/a/file: No such file or directory
[email protected]:~#
私の希望は、ライン猫ということでしたその上に。しかし、何らかの理由でstdoutが出力とエラーの両方を出力しているようです。
ありがとう@Duncan。あなたの答えは正しい 私はparamikoが 'stderr'を返す理由をさらに調べました。私は、 'ssh hostname command'構造体を使用すると、コマンドがローカルで実行されたかのように戻ることを知りました。その場合、リターンコードと 'stderr'と' stdout'はすべてアクセス可能です。 元のコードでは、sshシェルを開き、シェル経由でリモートシステムにコマンドを渡そうとしました。ダンカンが指摘したように、それはうまくいきません。 究極の解決策は、subprocess.call()を正しく使用することを学ぶことでした – shedfly