12

次のようなWebアプリから長時間実行されるスクリプトを生成します。

os.spawnle(os.P_NOWAIT, "../bin/producenotify.py", "producenotify.py", "xx",os.environ)

スクリプトは正常に生成されて実行されますが、スクリプトが終了するまで、Webアプリで使用されているポートを解放できません。つまり、Webアプリを再起動できません。プロセスを生成してWebアプリから完全に独立させるにはどうすればよいですか?

これはLinuxOS上にあります。

4

2 に答える 2

26

@mark がそれが Linux システムであることを明らかにしたように、スクリプトはこのレシピに従うことで簡単に完全に独立したもの、つまりデーモンにすることができます。(子プロセスの後に親で行うこともできます)。os.forkos.exec...

編集:いくつかの詳細を明確にするために、私の回答に対する@markのコメントについて:クックブックのレシピに従ってプロセスを「デーモン化」するためにスーパーユーザー権限は必要ありません。また、現在の作業ディレクトリを変更する必要もありません(レシピはそれ以上のことを行いますが、それは重要な部分ではありません-むしろ、fork_exitおよびsetsid呼び出しの適切な論理シーケンスです)。親プロセスの環境を使用するだけで終わらないさまざまなos.exec...バリアントがあるため、その部分も簡単です。 Python online docsを参照してください。e

他の人のコメントと回答で行われた提案に対処するには:私は信じてsubprocessおりmultiprocessing、それ自体は子プロセスをデーモン化しないと信じています。これは@markが必要とするもののようです。スクリプトはそれ自体でそれを行うことができますが、一部のコードはforks およびsetsidを実行する必要があるため、高レベルのコードと低レベルのコードを混在させるよりも、すべてのスポーンを低レベルのプレーンに保持する方が適切に思えます。手術の経過。

上記の URL にあるレシピを大幅に縮小および簡略化したバージョンを次に示します。このバージョンは、親で呼び出されてデーモンの子を生成するように調整されています。このようにして、コードを使用して Python 以外の実行可能ファイルを実行することもできます。与えられたように、コードは @mark が説明したニーズを満たす必要があります。もちろん、さまざまな方法で調整できます。詳細については、元のレシピとそのコメントと議論、およびそれが推奨する本を読むことを強くお勧めします。

import os
import sys

def spawnDaemon(path_to_executable, *args)
    """Spawn a completely detached subprocess (i.e., a daemon).

    E.g. for mark:
    spawnDaemon("../bin/producenotify.py", "producenotify.py", "xx")
    """
    # fork the first time (to make a non-session-leader child process)
    try:
        pid = os.fork()
    except OSError, e:
        raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno))
    if pid != 0:
        # parent (calling) process is all done
        return

    # detach from controlling terminal (to make child a session-leader)
    os.setsid()
    try:
        pid = os.fork()
    except OSError, e:
        raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno))
        raise Exception, "%s [%d]" % (e.strerror, e.errno)
    if pid != 0:
        # child process is all done
        os._exit(0)

    # grandchild process now non-session-leader, detached from parent
    # grandchild process must now close all open files
    try:
        maxfd = os.sysconf("SC_OPEN_MAX")
    except (AttributeError, ValueError):
        maxfd = 1024

    for fd in range(maxfd):
        try:
           os.close(fd)
        except OSError: # ERROR, fd wasn't open to begin with (ignored)
           pass

    # redirect stdin, stdout and stderr to /dev/null
    os.open(os.devnull, os.O_RDWR)  # standard input (0)
    os.dup2(0, 1)
    os.dup2(0, 2)

    # and finally let's execute the executable for the daemon!
    try:
      os.execv(path_to_executable, args)
    except Exception, e:
      # oops, we're cut off from the world, let's just give up
      os._exit(255)
于 2009-06-09T20:43:37.443 に答える
12

マルチプロセッシング ライブラリを使用して、プロセスを生成できます。基本的な例を次に示します。

from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
于 2009-06-09T23:10:20.050 に答える