私は次のように定義されたsystemdサービスを持っています、それはうまくいきます:
[Unit]
Description=my service
After=network.target
[Service]
User=myuser
Group=mygroup
WorkingDirectory=/home/myuser/myapp
Environment="PATH=/home/myuser/myapp/.venv/bin"
ExecStart=/home/myuser/myapp/.venv/bin/python3 /home/myuser/myapp/run.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
これは、Python WebアプリケーションFlaskフレームワークに基づいています。通常、アプリケーションの標準出力では、着信要求が「ライブ」であることがわかります。実行すると、 python run.py
のようなアプリ。
サービスを開始した後、アプリのログを追跡したいと思います。
Sudo journalctl -f -u my_app.service
また、受信ログは非常に低速です。ログに表示されるまでに数分以上かかる場合があります。その後、それらはすべて適切なタイムスタンプを持っているので、消えているわけではありませんが、久しぶりです。
私が試したこと:
systemdサービスの出力をファイルにリダイレクトするには:
StandardOutput=file:/var/log/my_app/output.log
StandardError=file:/var/log/my_app/error.log
運が悪い-それらはうまくいくが、同じ遅い速度で
journalctlログをオフラインに高速にダンプしようとするとSyncIntervalSec
がデフォルトの5m
から5s
に設定されます-どちらも役に立ちませんでした
これらのログをアプリケーションからジャーナルにすばやく渡す方法はありますか?システム認証サービスなど、他のサービスに問題はありません。すぐにレコードが表示されます。私のjournald.conf
ファイルにはデフォルトのパラメーター(上記のものを除く)があり、私のsystemdはバージョン237で、Ubuntu 18.04を実行しています。
問題は、実際にはFlaskアプリケーションからのバッファリングにあり、systemdまたはjournaldがこれらのログをどのように取り込むかにはありません。
前述のように、コマンドラインで直接python3 run.py
を実行すると、ログが正しく表示され、タイムスタンプもログで正しく表示されるため、これは直感に反する可能性があります。
前者は、Unix/Linuxが通常(ユーザーとの対話を想定しているため)端末に接続するとバッファリングされないようにstdoutを設定するが、ファイル(StandardOutput=file:...
の場合)またはパイプ(デフォルトでジャーナルにログを記録している場合)
後者は、Python/Flaskロガーがタイムスタンプを追加しているためです。そのため、出力をバッファリングしていても、最終的にログに発行すると、すべてのタイムスタンプがそこにあります。
一部のアプリケーションは、これが通常問題であることを認識し、ログに使用するときにstdoutにバッファリングを適切に設定しますが、これは、使用しているこの特定のPython/Flask設定の場合とは異なるようです。
Pythonでは、stdoutをバッファなしモードにグローバルに変更するのはかなり簡単です。これは次の方法で実行できます。
-u
フラグ をpython3
に渡します。PYTHONUNBUFFERED=1
を設定します(これは、systemdサービスユニットで追加のEnvironment=PYTHONUNBUFFERED=1
行を使用して実行できます)。これが特定のケースで機能することを確認したので、それは素晴らしいことです。
同様の問題に悩まされているPython以外のアプリケーションには、unbuffer
やstdbuf
などのコマンドラインツールがあり、この同じ問題を解決できることがよくあります。
ソリューションは通常、アプリケーションの種類に固有であり、これはやや残念ですが、多くの場合、Stack Exchangeでグーグルまたは他の回答を探します(knowバッファリングが問題)は通常、有用な提案につながります。