노드 서버를 시작한 다음 시작 시 systemd(Wayland)에서 웹 브라우저를 시작합니다.

노드 서버를 시작한 다음 시작 시 systemd(Wayland)에서 웹 브라우저를 시작합니다.

저는 임베디드 Linux 장치에서 실행되도록 설계된 웹 기반 애플리케이션을 개발 중입니다. 장치가 시작되면 노드 서버(로컬 서비스)와 두 부분을 시작해야 합니다.기어 웹 브라우저서버 URL을 가리킵니다. 노드가 시작되고 연결을 수락하는 데 시간이 걸리기 때문에(약 8초),웹브라우저 실행이 준비될 때까지 지연해야 합니다..

systemd를 사용하기로 결정했습니다dbus 서비스 유형이를 달성하기 위한 아이디어는 노드 서버가 완전히 초기화될 때 dbus 이름을 가져와서 가능한 한 빨리 웹 브라우저를 시작할 수 있도록 하는 것입니다. 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

웹 브라우저의 서비스(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.service에 있음을 표시 한 후 .activatingactive

하지만 중지하고 실행하면 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). .예 .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

답변2

ExecStart=/usr/bin/node /opt/server/main.js 2>&1 |로거

예를 들어 여기서는 쉘 구문을 사용할 수 없습니다. 이 2>&1 | logger섹션은 허용되지 않습니다.
(stdout 및 stderr이 캡처되어 어쨌든 사용 systemctl status및/또는 journalctl볼 수 있으므로 실제로는 필요하지 않습니다...)

여기서 문제는 노드 서비스가 완전히 활성화될 때까지 기다리는 브라우저 서비스를 구현할 수 없다는 것입니다.

이렇게 하려면 연결을 수락할 준비가 되었을 때 "세마포어 파일" /tmp/node.server.ready(예: 빈 일반 파일)을 만드는 것이 좋습니다. 그런 다음 이 지시문을 사용하여 파일이 생성될 때 브라우저 단위를 시작하는 단위를
만듭니다 . *.path바라보다:Unit=browser.servicePathExists=/tmp/node.server.ready
man systemd.path

  • /tmp/node.server.ready⚠️노드 서버를 시작하기 전과 노드 서버가 중지되면 다시 이 파일을 삭제하세요 ...

그래서 당신은해야활성화만경로 유닛으로 끌어당겨 준비가 되면 server-node.service활성화됩니다 .browser.service

관련 정보