GNU/Linux >> Linux の 問題 >  >> Linux

Linux で Python スクリプトをサービスまたはデーモンのように実行する方法

ここには 2 つのオプションがあります。

<オール>
  • 適切な cron ジョブ を作成する それはあなたのスクリプトを呼び出します。 Cron は、設定したスケジュールに従って定期的にスクリプトを起動する GNU/Linux デーモンの一般名です。スクリプトを crontab に追加するか、スクリプトへのシンボリック リンクを特別なディレクトリに配置すると、デーモンがスクリプトをバックグラウンドで起動するジョブを処理します。ウィキペディアで詳細を読むことができます。さまざまな cron デーモンがありますが、GNU/Linux システムには既にインストールされている必要があります。

  • ある種の Python アプローチ を使用する (たとえば、ライブラリ)スクリプトがそれ自体をデーモン化できるようにします。はい、単純なイベント ループが必要です (イベントがタイマー トリガーであり、スリープ機能によって提供される可能性があります)。

  • 2. を選択することはお勧めしません。実際には、cron 機能を繰り返すことになるからです。 Linux システムのパラダイムは、複数の単純なツールが相互作用して問題を解決できるようにすることです。 (定期的にトリガーすることに加えて) デーモンを作成する必要がある追加の理由がない限り、他のアプローチを選択してください。

    また、ループでデーモン化を使用してクラッシュが発生した場合、その後誰もメールをチェックしません (この回答へのコメントで Ivan Nevostruev が指摘したように)。一方、スクリプトが cron ジョブとして追加された場合は、再びトリガーされます。


    ここから取ってきた素敵なクラスは次のとおりです:

    #!/usr/bin/env python
    
    import sys, os, time, atexit
    from signal import SIGTERM
    
    class Daemon:
            """
            A generic daemon class.
    
            Usage: subclass the Daemon class and override the run() method
            """
            def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
                    self.stdin = stdin
                    self.stdout = stdout
                    self.stderr = stderr
                    self.pidfile = pidfile
    
            def daemonize(self):
                    """
                    do the UNIX double-fork magic, see Stevens' "Advanced
                    Programming in the UNIX Environment" for details (ISBN 0201563177)
                    http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
                    """
                    try:
                            pid = os.fork()
                            if pid > 0:
                                    # exit first parent
                                    sys.exit(0)
                    except OSError, e:
                            sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
                            sys.exit(1)
    
                    # decouple from parent environment
                    os.chdir("/")
                    os.setsid()
                    os.umask(0)
    
                    # do second fork
                    try:
                            pid = os.fork()
                            if pid > 0:
                                    # exit from second parent
                                    sys.exit(0)
                    except OSError, e:
                            sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
                            sys.exit(1)
    
                    # redirect standard file descriptors
                    sys.stdout.flush()
                    sys.stderr.flush()
                    si = file(self.stdin, 'r')
                    so = file(self.stdout, 'a+')
                    se = file(self.stderr, 'a+', 0)
                    os.dup2(si.fileno(), sys.stdin.fileno())
                    os.dup2(so.fileno(), sys.stdout.fileno())
                    os.dup2(se.fileno(), sys.stderr.fileno())
    
                    # write pidfile
                    atexit.register(self.delpid)
                    pid = str(os.getpid())
                    file(self.pidfile,'w+').write("%s\n" % pid)
    
            def delpid(self):
                    os.remove(self.pidfile)
    
            def start(self):
                    """
                    Start the daemon
                    """
                    # Check for a pidfile to see if the daemon already runs
                    try:
                            pf = file(self.pidfile,'r')
                            pid = int(pf.read().strip())
                            pf.close()
                    except IOError:
                            pid = None
    
                    if pid:
                            message = "pidfile %s already exist. Daemon already running?\n"
                            sys.stderr.write(message % self.pidfile)
                            sys.exit(1)
    
                    # Start the daemon
                    self.daemonize()
                    self.run()
    
            def stop(self):
                    """
                    Stop the daemon
                    """
                    # Get the pid from the pidfile
                    try:
                            pf = file(self.pidfile,'r')
                            pid = int(pf.read().strip())
                            pf.close()
                    except IOError:
                            pid = None
    
                    if not pid:
                            message = "pidfile %s does not exist. Daemon not running?\n"
                            sys.stderr.write(message % self.pidfile)
                            return # not an error in a restart
    
                    # Try killing the daemon process       
                    try:
                            while 1:
                                    os.kill(pid, SIGTERM)
                                    time.sleep(0.1)
                    except OSError, err:
                            err = str(err)
                            if err.find("No such process") > 0:
                                    if os.path.exists(self.pidfile):
                                            os.remove(self.pidfile)
                            else:
                                    print str(err)
                                    sys.exit(1)
    
            def restart(self):
                    """
                    Restart the daemon
                    """
                    self.stop()
                    self.start()
    
            def run(self):
                    """
                    You should override this method when you subclass Daemon. It will be called after the process has been
                    daemonized by start() or restart().
                    """
    

    Linux
    1. LinuxのbashコマンドをPERLスクリプトで実行する方法は?

    2. シェルからPythonスクリプトを実行する方法

    3. Linuxでpythonプログラムを実行可能にするために何を使用しますか

    1. LinuxでPerlスクリプトをシステムデーモンとして実行するにはどうすればよいですか?

    2. バックグラウンドでスクリプトを実行する方法 (linux openwrt)?

    3. Pythonスクリプトを使用してLinuxターミナルを終了するには?

    1. Linux –画面上でスクリプトを実行する方法ロック/ロック解除?

    2. スクリプトをルートとして遡及的に実行する方法は?

    3. PHPスクリプトをデーモンプロセスとして実行