Python RPCリモートコールスクリプトのRPyC概要

3513 ワード

最近、クラスタの各ノード上のスクリプトをリモートで実行し、スクリプトの実行結果を取得する必要があるモニタリング要件があり、セキュリティのためにアカウントパスワードをノードホストにログインする必要がなく、リモートスクリプトモジュールを呼び出すだけの方法で実現できることが要求されています.
pythonによるリモートコールスクリプトの方法をまとめます.
  • ホストにログインしてスクリプトを実行し、pythonモジュールはpssh、pexpect、paramiko
  • をサポートする.
  • リモートメソッドで呼び出す(ホストにログインする必要はありません)、pythonモジュールrpyc、分散
  • をサポート
  • socket方式、少し複雑で、ネットワークプロトコルを熟知する必要があり、起点は比較的高い
  • rpycはリモートコール、分散計算をサポートし、複雑なsocketプログラミングをより少ないコード量で実現します.本稿では、rpycを紹介し、demoを実現するために使用します.
    コードで説明:
    要件:クラスタの各ノード上のserver側のスクリプトをそれぞれ実行し、client側に実行結果を返します.
    #Monitor_RPC_Client.py
    ...
    hostDict = {'*.*.*.189': 12345, '*.*.*..188': 12345, '*.*.*..187': 12345}
    
    class ProcessWorker(Thread):
        def __init__(self, queue):
            Thread.__init__(self)
            self.queue = queue
    
        def run(self):
            while True:
                host, port, localPath = self.queue.get()
                try:
                    c = rpyc.connect(host, port)
                    localFileSize = c.root.getLocalFileSize(localPath, glob30minAgo)
                    localFileSizeDict[host] = localFileSize
                    c.close()
                except Exception, e:
                    print '{0} → {1}:{2} occur a Error:{3}
    '.format(self.getName(), host, port, e) def getLocalSize(localPath):     queue = Queue()     for x in range(3):         worker = ProcessWorker(queue)         worker.daemon = True         worker.start()     for (host, port) in hostDict.items():         queue.put((host, port, localPath))     time.sleep(3)     # queue.join() ... #Monitor_RPC_Server.py ... datePattern = re.compile(r'\d{4}(?:-\d{2}){4}') def get_ip_address(ifname):     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)     return socket.inet_ntoa(fcntl.ioctl(         s.fileno(),         0x8915,  # SIOCGIFADDR         struct.pack('256s', ifname[:15])     )[20:24]) class remote_call_func(Service):     def on_connect(self):         print "[{0}]\t--------------<<< on_connect".format(getNowTime())     def on_disconnect(self):         print "[{0}]\t-------------->>> on_disconnect".format(getNowTime())     def exposed_getLocalFileSize(self, path, glob30minAgo):         exitCode, execResult = commands.getstatusoutput("ls -lrt " + path + "`|awk '{s+=$5}END{print s}'")         dateTime30minAgo = (datetime.datetime.now() - datetime.timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S")         print "[{0}] → {1} → {2}".format(dateTime30minAgo, path, format(execResult, ','))         return execResult rpycServer = ThreadedServer(remote_call_func, hostname=get_ip_address('eth0'), port=12345, auto_register=False) rpycServer.start()

    公式文書には似たような例が多いので、詳しくは説明しませんが、3点に注意してください.
  • serverエンド定義メソッドはクライアントに呼び出される必要があります.exposedで始まるメソッドを定義する必要があります.そうしないと、AttributeError:'remote_call_script’ object has no attribute ‘exposed_iamshell’
  • server側のデフォルトでは認証メカニズムは設定されていません.認証が必要な場合は、ThreadedServerのauthenticatorパラメータとSSLモジュール
  • の2つの方法が推奨されます.
  • pip install rpyc、import rpycがエラーを報告した場合yum install openssl-devel、python
  • を再コンパイル、インストール
    もちろん、タイムアウト、検証失敗など、多くの異常処理も考慮する必要があります.
    Refer:
    [1]pythonリモートコールスクリプト(一)
    http://www.dbunix.com/?p=3262
    http://rpyc.readthedocs.org/en/latest/tutorial.html
    [2]pythonラーニング-pythonでshellコマンドを実行する
    http://zhou123.blog.51cto.com/4355617/1312791
    [3]celeryタスクの統一収集・配布実行を実現
    http://blog.csdn.net/vintage_1/article/details/47664187