ノードサーバーを起動し、起動時にsystemd(Wayland)でWebブラウザを起動します。

ノードサーバーを起動し、起動時にsystemd(Wayland)でWebブラウザを起動します。

私は組み込みLinuxデバイスで動作するように設計されたWebベースのアプリケーションを開発しています。デバイスが起動したら、ノードサーバー(ローカルサービス)と2つの部分を起動する必要があります。ギアWebブラウザサーバーのURLを指します。ノードが起動して接続を受け入れるのに時間がかかるため(約8秒)、Webブラウザの実行が準備されるまで遅延する必要があります。

systemdを使用することにしましたdbus サービスタイプこれを達成するためのアイデアは、ノードサーバーが完全に初期化されたときにdbus名を取得し、できるだけ早くWebブラウザを起動できるようにすることです。 dbusに名前でノードサーバー実装を登録し、server.node次のようにノードサービス(server-node.service)を設定しました。

[Unit]
Description=starts node backend

[Service]
BusName=server.node
EnvironmentFile=/etc/server/server-node.conf
ExecStart=/usr/bin/node /opt/server/main.js 2>&1 | logger
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -2 $MAINPID
KillMode=process
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target

Webブラウザのサービス(browser.service)は次のとおりです。

[Unit]
Description=starts cog web browser
Requires=server-node.service
After=server-node.sevice

[Service]
Type=simple
EnvironmentFile=/etc/server/cog.conf
#ExecStartPre=/bin/sleep 20
ExecStart=/usr/bin/cog http://localhost:3000/ui
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -2 $MAINPID
KillMode=process
Restart=on-failure
RestartSec=2s

[Install]
WantedBy=graphical-session.target

ここで問題はブラウザサービスは、ノードサービスが完全に有効になるまで待つことはできません。systemctl start server-node.serviceコマンドを実行すると時間がかかり(systemdがdbusに登録されるのを待っていることを意味します)、実行するとそのコマンドがステータスになっていることを示しますsystemctl status server-node.serviceactivatingactive

しかし、停止して実行するとsystemctl start browser.service両方のサービスが起動しますが、ブラウザが最初から起動します。、サーバーにまだ接続できないため、HTTPエラーが表示されます。その行のコメントを外すと、ExecStartPre=ブラウザを起動する前に20秒間スリープ状態になり、すべてがうまく機能しますが、ハードコーディングされた遅延を使用したくありません。

私も試しましたBindsTo=server-node.service 指示するしかし、同じことが起こります。


修正する

これはmain.tsサーバーを初期化して使用する場所です。NestJsイベントフレームワーク:

async function bootstrap() {
      // Prepare the environment
      // .........
      await app.listen(port, 'localhost').then(() => {
        if (env === 'DEV') {
          Logger.log(`| ${env} server listening on: http://localhost:${port}  `);
        } else {
          Logger.log(`| ${env} server listening on port ${port}  `);
        }
        // Grab the execution context to emit the app initialized event
        // https://stackoverflow.com/a/53484892/1199132
        app.get(EventEmitter2).emit('app.initialized');
      });
}
bootstrap();

その後、dbus.service.tsイベントがキャプチャされapp.initialized処理されたときにdbusに名前を登録するには、次のようにします。dbus ネイティブライブラリ:

@OnEvent('app.initialized', { async: true })
register () {
    Logger.log('Requesting dbus name ' + this.busName, this.constructor.name);
    // Request the bus name
    // See https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-messages
    this.bus.requestName(this.busName, 0, (err, name) => {
        if (err) {
            Logger.error('Error registering dbus name: ' + err, DbusService.name);
        } else {
            Logger.log('Registered dbus name with response: ' + name, DbusService.name);
        }
    });
}

dbus 名がリストされます。show system dbus nameを使用する場合busctl list

ベストアンサー1

たぶんこれがあなたに必要なものかもしれません。次のようになります。

DBusサービス

DBusシステムバスから名前を取得するサービスの場合は、Type = dbusを使用し、それに応じてBusName =を設定します。サービスはフォーク(デーモン化)してはいけません。システムバスから名前を取得すると、systemdはサービスが初期化されたと見なします。次の例は、一般的なDBusサービスを示しています。

[Unit]
Description=Simple DBus service

[Service]
Type=dbus
BusName=org.example.simple-dbus-service
ExecStart=/usr/sbin/simple-dbus-service

[Install]
WantedBy=multi-user.target

バスアクティベーション可能サービスの場合は、systemdサービスファイルに[Install]セクションを含めずに、対応するDBusサービスファイルにSystemdService =オプションを使用します(例:/usr/share/dbus-1/system-services/org)。 .yes .simple-dbus-service.service):

[D-BUS Service]
Name=org.example.simple-dbus-service
Exec=/usr/sbin/simple-dbus-service
User=root
SystemdService=simple-dbus-service.service

おすすめ記事