KnowHow

技術的なメモを中心にまとめます。
検索にて調べることができます。

RokcyLinuxでシェルコマンドを実行するpythonプログラムのサンプルコード

登録日 :2024/04/06 09:55
カテゴリ :Python基礎

subprocessを使ってLinuxサーバでシェルコマンドを実行するためのベースとなるコードを作成した。
これをベースに、Linuxサーバで自動的にコマンドを発行して管理するために活用している。
管理サーバから、クライアントノードのステータスを確認する場合、コマンドのタイムアウト時間を設けておく方がいいところを工夫している。

#!/usr/bin/python3

import subprocess
from subprocess import PIPE
import signal

"""
submit shell command
"""

class ShellCommand(object):
    def __init__(self):
        self.stdout = False
        self.stderr = False
        self.returncode = False
        self.command = False

    def submit_command(self, command):
        self.command = command
        result = subprocess.run(self.command, shell=True, stdout=PIPE, stderr=PIPE)
        self.stdout = result.stdout.decode('utf-8')
        self.stderr = result.stderr.decode('utf-8')
        self.returncode = result.returncode

        if result.returncode != 0:
            raise Exception(self.stderr)


class ExecuteShellCommand(object):
    def __init__(self, timeout, command):
        self._timeout = timeout
        self._command = command
        self._command_result = False
        self._errlog = False

    def _signal_handler(self, signum, frame):
        raise Exception({"Time out! ": self._command})

    def execute_command(self):
        signal.signal(signal.SIGALRM, self._signal_handler)
        signal.alarm(self._timeout)

        shell_command = ShellCommand()

        try:
            shell_command.submit_command(self._command)
            self._command_result = shell_command.stdout
        except Exception as e:
            self._errlog = {'[ERROR]:':str(e)}
            print(self._errlog)

        del shell_command


"""
test code
"""
def test_shell_command():

    timeout = 2
    command = 'ls -l'
    shellcommand = ExecuteShellCommand(timeout, command)
    shellcommand.execute_command()
    print(shellcommand._command_result)

if __name__ == '__main__':

    test_shell_command()

少々、クラスの分離がいまいちだったので、以下のように少し見直した。shellcommadのオブジェクトを引数で受け取るようにしている。

#!/usr/bin/python3

from abc import ABC, abstractmethod
import subprocess
from subprocess import PIPE
import signal

"""
submit shell command
"""

class ShellCommand(object):
    def __init__(self):
        self.stdout = False
        self.stderr = False
        self.returncode = False
        self.command = False

    def submit_command(self, command):
        self.command = command
        result = subprocess.run(self.command, shell=True, stdout=PIPE, stderr=PIPE)
        self.stdout = result.stdout.decode('utf-8')
        self.stderr = result.stderr.decode('utf-8')
        self.returncode = result.returncode

        if result.returncode != 0:
            raise Exception(self.stderr)


class ExecuteShellCommand(object):
    def __init__(self, timeout: int, command: str, shellcommand: ShellCommand):
        self._timeout = timeout
        self._command = command
        self._shellcommand = shellcommand
        self._command_result = False
        self._errlog = False

    def _signal_handler(self, signum, frame):
        raise Exception({"Time out! ": self._command})

    def execute_command(self):
        signal.signal(signal.SIGALRM, self._signal_handler)
        signal.alarm(self._timeout)

        try:
            self._shellcommand.submit_command(self._command)
            self._command_result = self._shellcommand.stdout
        except Exception as e:
            self._errlog = {'[ERROR]:':str(e)}
            print(self._errlog)


"""
test code
"""
def test_shell_command():

    timeout = 2
    command = 'ls -l'
    shellcommand = ShellCommand()
    shell = ExecuteShellCommand(timeout, command, shellcommand)
    shell.execute_command()
    print(shell._command_result)


if __name__ == '__main__':

    test_shell_command()