質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

6086閲覧

Python Paramiko SSHExceptionエラーの例外処理

minhouse10

総合スコア41

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/12/16 04:01

編集2017/12/16 15:07

Pythonオブジェクト指向プログラミングは勉強の段階の身なのですが、以下ParamikoモジュールによるSSH接続と接続先の複数のLinuxサーバー上でコマンド実行し結果を返す処理を行うプログラムを知人の助けを借りて作成しました。(別txtファイルから接続先サーバーIPと実行コマンドを読み込む仕様です)

追加したい機能はSSH接続に失敗した際にエラー例外処理を行い、エラー内容とメッセージを出力後、処理を最後まで継続するように変更する事です。現在はSSH処理が失敗した段階で以降の処理が停止してしまう状態です。

https://www.programcreek.com/python/example/7495/paramiko.SSHException
上記ページを参照し試行錯誤してみてはみますが、オブジェクト指向で書かれた処理にどう綺麗に当該処理を加える事ができるのか今のところ上手くいっておりません。

ご教授の程よろしくお願いいたします。

YouheiSakurai様のご回答によりTimeoutError発生後も停止せずに以下任意のエラー出力と共に処理継続する事が確認できました!

SSH connection failed for xx.xx.xx.xxx

修正後のコード:

#Modules import paramiko from contextlib import suppress from paramiko import SSHException #Variables USER = 'UserID' PSWD = 'password' #Classes and Functions class InputReader: def __init__(self, commands_path, hosts_path): self.commands_path = commands_path self.hosts_path = hosts_path def read(self): self.commands = self.__readlines(self.commands_path) self.hosts = self.__readlines(self.hosts_path) def __readlines(self, path): with open(path) as f: # return map(lambda v: v.strip(), f.readlines()) return [v.strip() for v in f.readlines()] #List comprehension class CommandExecuter: def __init__(self, host, command): self.host = host self.command = command def execute(self): with suppress(TimeoutError): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(self.host, username=USER, password=PSWD) stdin, stdout, stderr = ssh.exec_command(self.command) errors = stderr.readlines() lines = [v.strip() for v in stdout.readlines()] return lines print('## SSH connection failed for %s ##' % h + '\n') #Main Procedure if __name__ == '__main__': reader = InputReader("commands2.txt", "systems2.txt") reader.read() for h in reader.hosts: for c in reader.commands: executer = CommandExecuter(h, c) results = executer.execute() print("IP:{0}({1}):".format(h, c) + '\n') if results != None: for i in results: print(i + '\n')

修正前のコード:

import paramiko #Variables USER = 'UserID' PSWD = 'password' #Classes and Functions class InputReader: def __init__(self, commands_path, hosts_path): self.commands_path = commands_path self.hosts_path = hosts_path def read(self): self.commands = self.__readlines(self.commands_path) self.hosts = self.__readlines(self.hosts_path) def __readlines(self, path): with open(path) as f: return [v.strip() for v in f.readlines()] #List comprehension class CommandExecuter: def __init__(self, host, command): self.host = host self.command = command def execute(self): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(self.host, username=USER, password=PSWD) stdin, stdout, stderr = ssh.exec_command(self.command) errors = stderr.readlines() '''if len(errors) != 0: #raise Exception(errors)''' lines = [v.strip() for v in stdout.readlines()] #ssh.close() return lines #Main Procedure if __name__ == '__main__': reader = InputReader("commands.txt", "systems.txt") reader.read() for h in reader.hosts: for c in reader.commands: executer = CommandExecuter(h, c) results = executer.execute() print("{0}({1}):".format(h, c)) if results != None: for i in results: print(i) print('\n')

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

contextlib.suppressを使えば見通しよくエラーを無視できますよ

python

1from contextlib import suppress 2from paramiko import SSHException 3 4 5with suppress(SSHException): 6 ... # SSHに関する処理、例外が発生したらwithブロックを抜ける 7print('とりあえず完了')

投稿2017/12/16 04:52

YouheiSakurai

総合スコア6142

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

minhouse10

2017/12/16 13:40

YouheiSakurai様、ご回答頂き本当にありがとうございました! 早速実装し、たま実行の結果ここにてご報告させて頂きます。
minhouse10

2017/12/16 15:12 編集

YouheiSakurai様、頂いたアドバイスに沿って、contextlibにより期待した結果を得る事ができました。ただエラーは適当な存在しないアドレスを使って検証したところ、TimeoutErrorとなったためその点、SSHExceptionではなくTimeoutErrorとする必要がありました。今回おかげ様で素早く解決する事ができました。改めてありがとうございました。
guest

0

自己解決

from contextlib import suppress
from paramiko import SSHException

上記contextlibのsuppressメソッドにより、あるホストに対するSSH接続タイムアウト処理発生時の処理を停止せず、エラーのみを出力するコードに変更できた。
修正後のコード添付済み

投稿2017/12/16 15:11

minhouse10

総合スコア41

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問