5

Python スクリプト内からインストール プログラムの実行が終了したことを検出しようとしています。具体的には、アプリケーションは Oracle 10gR2 データベースです。現在、Popen で subprocess モジュールを使用しています。理想的には、単に wait() メソッドを使用してインストールの実行が完了するのを待つだけですが、ドキュメントに記載されているコマンドは実際には子プロセスを生成して実際のインストールを処理します。失敗したコードのサンプル コードを次に示します。

import subprocess
OUI_DATABASE_10GR2_SUBPROCESS = ['sudo',
                                 '-u',
                                 'oracle',
                                 os.path.join(DATABASE_10GR2_TMP_PATH,
                                              'database',
                                              'runInstaller'),
                                 '-ignoreSysPrereqs',
                                 '-silent',
                                 '-noconfig',
                                 '-responseFile '+ORACLE_DATABASE_10GR2_SILENT_RESPONSE]
oracle_subprocess = subprocess.Popen(OUI_DATABASE_10GR2_SUBPROCESS)
oracle_subprocess.wait()

ここに同様の質問があります: Killing a subprocess including its children from pythonですが、選択された回答は子の問題に対処していません。代わりに、待機するアプリケーションを直接呼び出すようにユーザーに指示します。サブプロセスのすべての子を待機する特定のソリューションを探しています。サブプロセスの数が不明な場合はどうなりますか? すべての子サブプロセスが完了するのを待つという問題に対処する回答を選択します。

失敗の明確化: 子プロセスは、wait() コマンドの後も実行を継続します。これは、そのコマンドが最上位プロセス (この場合は「sudo」) のみを待機するためです。この問題で知られている子プロセスの簡単な図を次に示します: Python subprocess module -> Sudo -> runInstaller -> java -> (unknown)

4

4 に答える 4

3

わかりました、これは Unix でのみ機能するトリックです。これは、この質問に対する回答の 1 つに似ています: Ensuring subprocesses are dead on exiting Python program。アイデアは、新しいプロセス グループを作成することです。その後、グループ内のすべてのプロセスが終了するまで待機できます。

pid = os.fork()
if pid == 0:
    os.setpgrp()
    oracle_subprocess = subprocess.Popen(OUI_DATABASE_10GR2_SUBPROCESS)
    oracle_subprocess.wait()
    os._exit(0)
else:
    os.waitpid(-pid)

私はこれをテストしていません。プロセスグループのリーダーとなる追加のサブプロセスを作成しますが、それを避けることは(私が思うに)かなり複雑です。

この Web ページも役立つことがわかりました。 http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/

于 2011-05-23T20:58:17.523 に答える
2

pidを-1に設定してos.waitpidを使用すると、現在のプロセスのすべてのサブプロセスが終了するまで待機します。

import os
import sys
import subprocess


proc = subprocess.Popen([sys.executable,
                         '-c',
                         'import subprocess;'
                         'subprocess.Popen("sleep 5", shell=True).wait()'])

pid, status = os.waitpid(-1, 0)

print pid, status

これは、pstree <pid>フォークされたさまざまなサブプロセスの結果です。

python───python───sh───sleep

これがお役に立てば幸いです:)

于 2011-05-23T22:37:16.850 に答える
2

次のリンクhttp://www.oracle-wiki.net/startdocsruninstallerを確認してください。このリンクには、runInstaller コマンドに使用できるフラグの詳細が記載されています。

このフラグは 11gR2 で確実に使用できますが、そのバージョンでパッケージ化された runInstaller でこのフラグを試すための 10g データベースはありません。

よろしく

于 2011-07-12T14:30:32.107 に答える
1

どこを見ても、一般的なケースではこれを解決することは不可能だと言っているようです。私は、WindowsとLinuxのいくつかの答えを組み合わせて、必要なことを実行できる「pidmon」というライブラリを作成しました。

これをクリーンアップして、おそらく「pidmon」などと呼ばれるgithubに配置することを計画しています。起きたらリンクを貼るよ。

編集:http://github.com/dbarnett/python-pidmonで入手できます

waitpid引数を受け入れる特別な関数を作成したgraft_funcので、直接の子ではないときに待機するプロセスの種類を大まかに定義できます。

import pidmon
pidmon.waitpid(oracle_subprocess.pid, recursive=True,
        graft_func=(lambda p: p.name == '???' and p.parent.pid == ???))

waitpidまたは、ショットガンのアプローチとして、呼び出しが再び停止してから開始されたプロセスを待つには、次のようにします。

import pidmon
pidmon.waitpid(oracle_subprocess.pid, graft_func=(lambda p: True))

これはまだWindowsでほとんどテストされておらず、Windowsでは非常に遅いように見えることに注意してください(ただし、フォークしやすいgithubにあると言いましたか?)。これは少なくともあなたが始めるのに役立つはずです、そしてそれがあなたのためにまったくうまくいくなら、私はそれを最適化する方法についてたくさんのアイデアを持っています。

于 2011-05-27T15:35:47.003 に答える