서비스가 실패했는지 systemd가 왜 알지 못합니까?

서비스가 실패했는지 systemd가 왜 알지 못합니까?

Ubuntu 18.04에서 스프링 부트 애플리케이션(다른 사람이 개발함 - 저는 Java 프로그래머가 아님)을 구성하려고 합니다. 개발자는 이전에 /etc/init.d서비스를 활성화하기 위해 심볼릭 링크를 추가했습니다. 부팅 시 정상적으로 시작되었습니다. 그러나 나중에 서비스가 실패하면 systemd는 계속 서비스가 실행 중이라고 보고합니다.

[email protected]:/var/log/apps# systemctl status crm-service
● crm-service.service - LSB: crm-service
   Loaded: loaded (/etc/init.d/crm-service; generated)
   Active: active (exited) since Wed 2020-04-15 12:27:15 BST; 3h 56min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 8656 ExecStop=/etc/init.d/crm-service stop (code=exited, status=0/SUCCESS)
  Process: 8703 ExecStart=/etc/init.d/crm-service start (code=exited, status=0/SUCCESS)

Apr 15 12:27:15 example.com systemd[1]: Starting LSB: crm-service...
Apr 15 12:27:15 example.com crm-service[8703]: /var/services/crm-service.conf: line 1: -Xms96M: command not found
Apr 15 12:27:15 example.com crm-service[8703]: Started [8747]
Apr 15 12:27:15 example.com systemd[1]: Started LSB: crm-service.

내가 볼때동일한 시스템 단위 파일이 문제를 해결할 수 있는 springboot 관련 내용이 인터넷에 게시된 것을 본 적이 없습니다.

  1. systemd가 서비스의 실제 상태를 확인하도록 하는 방법은 무엇입니까? (리스닝 소켓이 열리지만 임의의 높은 포트에서 열립니다)
  2. 시스템화해서 시도해 볼 수 있는 방법이 있나요?부드럽게실패한 것으로 알고 있는 서비스를 다시 시작하시겠습니까?

답변1

Systemd에는 비평가가 있으며 그 중 다수는 괜찮지만 그렇지 않습니다.Systemd는 시작 스크립트에서 분기된(또는 복제된) 모든 프로세스와 스레드를 추적할 수 있으며, 프로세스와 스레드가 남아 있지 않으면 서비스가 중단된 것으로 간주됩니다.

내가 본 첫 번째 문제는 systemd가 시작/중지 스크립트를 사용하지 않고 /etc/init.d단지 호환성 플러그인일 뿐이라는 것입니다. 대신 systemd는 모든 서비스에 대한 구성 파일인 단위 파일을 사용합니다.

systemd sysv init compat 모듈은 사실상 /etc/init.dinit 스크립트에 필요한 정보가 부족하기 때문에(또는 정보를 추출할 수 없기 때문에) 항상 가능한 것은 아닙니다.

compat 모듈이 작동하는 방식은 종료 코드가 0이 아니면 systemd가 init 스크립트가 실패한 것으로 간주하여 서비스가 작동할 수 없다는 것입니다. 0 종료 코드는 성공적인 실행을 의미합니다. 초기화 스크립트에 오류가 있으면 systemd를 속이고 실패하더라도 0 종료 코드를 제공합니다.

초기화 스크립트 오류의 가장 가능성 있는 원인은 백그라운드에서 프로세스를 시작한 다음 항상 0으로 종료된다는 것입니다. 사용자 지정 공급자가 작성한 대부분의 초기화 스크립트에 대한 나의 일반적인 경험은 아마도 대부분 개선의 여지가 많다는 것입니다. 그들을 믿지 말고 그들이 무엇을 하는지 보고 고치십시오. 귀하의 경우에는 확인하는 것이 좋습니다.

  • Java 애플리케이션을 시작하는 방법
  • 어디서 시작하나요
  • 어떤 사용자가 시작했는지

유닛 파일을 사용하여 동일한 기능을 재현합니다.

Initscript는 systemd에서 자동으로 다시 시작할 수 없지만 유닛 파일에서는 자동으로 다시 시작할 수 있습니다.

Java 프로그램이 무작위로 충돌하는 경우에도 심각한 문제가 됩니다. 모든 정상적인 Java 프레임워크는 자신의 치명적인 오류를 올바르게 처리합니다(모든 예외를 포착하고 기록하고 계속합니다).

init 스크립트의 또 다른 가능성이 높은 버그는 JVM(대부분: /usr/bin/java)을 찾을 수 없어서 이를 빈 문자열로 대체하여 JVM 플래그를 쉘로 시작하려고 시도한다는 것입니다. 명령 . 분명히 -Xms96M시스템에 명령이 없지만 /usr/bin/java -Xms96M ...작동할 것입니다.

Spring Boot 애플리케이션의 예제 단위 파일:

[Unit]
Description=Crm Spring Boot App Example
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/java -Xms96M ...other flags... your.spring.boot.jar
User=exampleuser
Group=examplegroup
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=exampleapp
WorkingDirectory=/path/to/app/home

[Install]
WantedBy=multi-user.target
Alias=exampleapp.service

또한 단위 파일은 Java 프로세스의 표준 출력과 오류를 시스템 로그로 리디렉션합니다.

응용 프로그램을 자동으로 다시 시작하려면 다음을 삽입하십시오.

RestartSec=5s
Restart=on-failure

[Service]섹션을 입력하세요.

체계적인 튜토리얼이 있습니다GoLinuxCloud.com.

관련 정보