Systemd 서비스가 bash 스크립트를 실행하지 못함

Systemd 서비스가 bash 스크립트를 실행하지 못함

Arch Linux에서 다음 Bash 스크립트를 실행하는 systemd 서비스를 만들려고 합니다.

#!/bin/bash

/bin/xbindkeys &
/bin/setxkbmap -layout gb

일부 온라인 지침을 통해 서비스를 저장하기 위해 myfirst.service호출되는 파일을 만들었습니다 . /etc/systemd/system파일 내용은 다음과 같습니다.

[Unit]
Description=Command Service

[Service]
ExecStart=/etc/startupjobscript
User=user1
Type=oneshot
Restart=on-abort
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

서비스는 /etc/startupjobscriptBash 스크립트를 실행해야 합니다. 그 후 서비스를 활성화하고 시작했습니다.

systemctl enable myfirst
systemctl start myfirst

그러나 어떤 이유로 작동하지 않으며 전혀 로드 및 실행되지 않는 것으로 나타났습니다.

편집 : 이것은sudo systemctl 상태 myfirst나에게 줘:

Warning: The unit file, source configuration file or drop-ins of myfirst.service changed on disk. Run 'systemctl daemon-reload' to reload units.
● myfirst.service - Command Service
     Loaded: loaded (/etc/systemd/system/myfirst.service; enabled; vendor preset: disabled)
     Active: failed (Result: exit-code) since Wed 2020-08-26 21:07:02 BST; 18min ago
    Process: 332 ExecStart=/etc/startupjobscript (code=exited, status=255/EXCEPTION)
   Main PID: 332 (code=exited, status=255/EXCEPTION)

Aug 26 21:07:01 archlinux systemd[1]: Starting Command Service...
Aug 26 21:07:02 archlinux startupjobscript[337]: Cannot open display "default display"
Aug 26 21:07:02 archlinux systemd[1]: myfirst.service: Main process exited, code=exited, status=255/EXCEPTION
Aug 26 21:07:02 archlinux systemd[1]: myfirst.service: Failed with result 'exit-code'.
Aug 26 21:07:02 archlinux systemd[1]: Failed to start Command Service.

답변1

X 서버와 통신하는 모든 것을 실행할 때 systemd 서비스는 약간 까다로워집니다. 이를 수행하는 두 가지 주요 방법이 있습니다.

  1. 사용자 서비스 실행
  2. 설정 $DISPLAY하고 도달할 때까지 시작하지 마십시오 graphical.target.

사용자 서비스로 실행하려면 myfirst.service으로 이동 ~/.config/systemd/system/한 다음 제거 User=하고 WantedBy=로 설정합니다 default.target. default.target사용자가 로그인하면 도착합니다. 언젠가는 graphical-session.target사용자가 데스크탑 환경에 로그인하면 도착할 것이지만 아직 사용할 수는 없습니다. 대신 default.target사용자가 로그인할 때 실행됩니다. 디스플레이 관리자를 사용하고 있다면 이 전에 x 세션을 가졌을 수도 있습니다.

[Unit]
Description=Command Service
After=default.target

[Service]
ExecStart=/bin/xbindkeys
ExecStartPost=/bin/setxkbmap -layout gb
Type=simple
Restart=on-abort

[Install]
WantedBy=default.target

--user이 장치를 사용할 때 다음과 같은 방법을 사용하십시오.

systemctl --user daemon-reload
systemctl --user start myfirst.service
systemctl --user enable myfirst.service

시스템 서비스로 유지하려면 해당 파일을 보관 /etc/systemd/system/하고, X 서버에 접속할 수 있도록 환경을 설정해 주어야 합니다. 결국은 성공해야 합니다 WantedBy=graphical.target. 이렇게 하면 X 서버가 시작될 때까지 X 서버에 연결을 시도하지 않습니다. 하지만 로그인할 때까지 .Xauthority가 유효한지 확신할 수 없기 때문에 항상 성공하는지 잘 모르겠습니다.

[Unit]
Description=Command Service
After=graphical.target

[Service]
ExecStart=/bin/xbindkeys
ExecStartPost=/bin/setxkbmap -layout gb
Type=simple
User=user1
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/user1/.Xauthority
Restart=on-abort

[Install]
WantedBy=graphical.target

여러 사용자 또는 여러 모니터가 있는 경우 시스템 전체 서비스가 약간 이상해질 수 있습니다. 사용자별 작업을 수행하는 것이 좋습니다. 데스크탑 환경에 있다면 이러한 변수를 무엇으로 설정할지 알아낼 echo $DISPLAY수 있습니다.echo $XAUTHORITY


systemd이러한 변경을 수행한 후에는 다음 변경을 시도하기 전에 해당 내용을 읽어야 합니다 start. 달리기:

systemctl daemon-reload

시도해 본 적이 있다면 systemctl disable myfirst.service먼저 시도해 보고 systemctl start myfirst.service효과가 있다는 것을 알게 되면 계속 진행하면 됩니다 systemctl enable myfirst.service. enable다시 시작하면 서비스가 호출되도록 심볼릭 링크가 생성됩니다 . 실험 상태에서 이러한 링크를 엉망으로 만들지 않으려면 다시 시작을 테스트할 준비가 될 때까지 활성화하지 마십시오.default.targetgraphical.target


/bin/xbindkeys &참고로 저는 귀하의 bash 스크립트에 있는 해당 줄에 대해 이상한 의심을 갖고 있습니다. 일반적으로 xbindkeys영원히 실행되나요? 그렇다면 ExecStart=다음과 같이 변경해야 할 수도 있습니다.

ExecStart=/bin/xbindkeys
ExecStartPost=/bin/setxkbmap -layout gb
Type=simple

위에서 제안한 단위를 이렇게 변경했습니다.

이렇게 하면 systemd가 프로세스를 포크하지 않고 직접 추적할 수 있습니다. Type=로 설정되어 있지 않기 때문에 forkingbash 스크립트가 종료되고 systemd가 PID를 추적하지 않아 xbindkeysPID를 고아 PID로 남겨두고 이를 방지할 수 없을 것으로 생각됩니다. xbindkeys이 작업의 일부로 떠난 경우 ExecStart서비스를 중지하면 xbindkeys가 종료됩니다(지금은 이를 수행할 수 없을 것 같습니다). 이 경우 더 이상 적용되지 Type=simple않으므로 설정해야 합니다 oneshot.

관련 정보