10

セロリを使用して、一連のサーバーでタスクをスケジュールおよび実行しようとしています。各タスクの実行時間はいくぶん長く (数時間) あり、サブプロセスを使用して、指定された入力で特定のプログラムを呼び出す必要があります。このプログラムは、stdout と stderr の両方で大量の出力を生成します。

プログラムによって生成された出力をほぼリアルタイムでクライアントに表示する方法はありますか? クライアントがサーバーにログインせずにサーバー上で実行されているタスクによって吐き出された出力を見ることができるように、出力をストリーミングしますか?

4

3 に答える 3

13

多くの要件と制約を指定しませんでした。すでにどこかに redis インスタンスがあると仮定します。

できることは、他のプロセスからの出力を 1 行ずつ読み取り、redis を介して公開することです。

テスト用echoにファイルにデータを入れる例を次に示します。/tmp/foo

import redis
redis_instance = redis.Redis()
p = subprocess.Popen(shlex.split("tail -f /tmp/foo"), stdout=subprocess.PIPE)

while True:
    line = p.stdout.readline()
    if line:
        redis_instance.publish('process log', line)
    else:
        break

別のプロセスで:

import redis

redis_instance = redis.Redis()
pubsub = redis_instance.pubsub()
pubsub.subscribe('process log')

while True:
    for message in pubsub.listen():
        print message  #  or use websockets to comunicate with a browser

プロセスを終了したい場合は、セロリのタスクが完了した後に「終了」を送信できます。

さまざまなチャネル ( の文字列subscribe) を使用して、さまざまなプロセスからの出力を分離できます。

必要に応じて、ログ出力を redis に保存することもできます。

redis_instance.rpush('process log', message)

後で完全に取得します。

于 2013-05-13T18:43:45.147 に答える
6

それを行う方法の1つは、stderrおよびstdoutに使用されるカスタムLoggerを作成することです(ドキュメントを参照してください:

from celery.app.log import Logger
Logger.redirect_stdouts_to_logger(MyLogger())

ロガーは、データベース、Memcached、Redis、またはデータの取得に使用する共有ストレージにデータを保存できます。

loggerの構造についてはわかりませんが、次のようなものが機能すると思います。

from logging import Logger

class MyLogger(Logger):
    def log(lvl, msg):
        # Do something with the message
于 2013-05-04T07:27:59.537 に答える
4

これは古い質問ですが、この特定のトピックに関するほとんど唯一の結果です。

これが私が行った方法です。Redisを介して特定のチャネルに公開する単純なファイルのようなオブジェクトを作成しました

class RedisFileObject(object):
    def __init__(self, _key):
        self.connection = redis.Redis()
        self.key = _key
        self.connection.publish('debug', 'Created channel %s' % self.key)

    def write(self, data):
        self.connection.publish(self.key, data)

    def close(self):
        pass

すべてのタスクがさまざまな機能を継承する BaseTask を持っています。これは stdout と stderr を Redis ファイルのようなオブジェクトに置き換えます。

def capture_output(self):
    sys.stdout = RedisFileObject(self.request.id)
    sys.stderr = RedisFileObject(self.request.id)

そこから stdout/stderr に書き込まれたものはすべて、タスク ID にちなんで名付けられた Redis チャネルに転送されます。

于 2014-12-02T15:39:41.493 に答える