Systemd: 서비스를 시작하려면 포트가 열릴 때까지 기다리거나 서비스 시작을 선언하세요.

Systemd: 서비스를 시작하려면 포트가 열릴 때까지 기다리거나 서비스 시작을 선언하세요.

다른 서비스(activemq)가 "활성"이어야 하고 연결을 시작하기 전에 연결을 수신하는 데 필요한 모든 포트가 있는 일부 서비스(A, B, C)가 있습니다. 서비스 B와 C는 A에 의존하며, 이는 다시 activemq와 수신 대기 포트(특히 포트 61616)에 의존합니다.

내가 겪고 있는 문제는 activemq가 모든 포트 열기를 완료하기 전에 systemd가 activemq 서비스를 "활성"으로 표시한다는 것입니다. 그래서 내 서비스 (A)가 시작되었다가 종료됩니다.

내가 시도한 것:

set: Restart=on-success (또는 항상) 작동하지만 모든 서비스( ABC )에 대해 이 작업을 수행해야 합니다. 나는 이 규칙을 적용하고 싶지 않습니다.

작동 방식은 서비스 A에 다음을 추가하는 것입니다.

ExecStartPre=/bin/sleep 30 

그러면 서비스 A가 올바르게 시작되므로 B와 C는 추가 구성이 필요하지 않습니다(모든 서비스 A, B, C에 대해 해당 "After=" 및 "Requires=" 설정 제외). 그러나 나는 이것이 정확하고 깨끗한 해결책이라고 생각하지 않습니다.

[서비스]에서 다른 옵션도 시도했지만 Type=fork 등과 같은 아무 것도 작동하지 않았습니다.

내가 원하는 것은:

  • 모든 포트(4개가 있음) 또는 최소한 마지막 포트(문제를 일으키는 포트)에서 수신 대기 중인 경우에만 activemq 서비스를 "활성"으로 표시하도록 systemd에 지시합니다. 61616 또는
  • 포트 61616(일종의 Require=tcp/61616 또는 이와 유사한 것)에서 수신 대기한 후에만 서비스 A를 시작하십시오.

activemq.service 파일은 다음과 같습니다.

[Unit]
Description=Activemq Servoce
After=local-fs.target                                                                                                                                                                      
After=network.target                                                                                                                                                                       

[Service]                                                                                                                                                                                  
Type=simple                                                                                                                                                                                
SuccessExitStatus=0 143                                                                                                                                                                    
ExecStart=/usr/bin/activemq console                                                                                                                                                        
User=activemq                                                                                                                                                                              
Group=activemq                                                                                                                                                                             
Restart=always
PrivateTmp=true

[Install]
WantedBy=multi-user.target

답변1

기반:

Systemd는 activemq가 모든 포트 열기를 완료할 때까지 activemq 서비스를 "활성"으로 표시합니다.

그리고:

[서비스 A]는 수신을 위해 activemq와 해당 포트(구체적으로 포트 61616)를 사용합니다.

...systemd의 서비스 상태 이해를 "프로세스 실행 중"에서 "프로세스 실행 중"으로 수정할 수 있습니다.그리고포트가 열려 있습니다.". 나에게 이것은 열린 포트를 확인하기 위해 모든 후속 장치 파일을 수정하는 것보다 더 간단해 보입니다. 한 가지 방법은 다음을 사용하는 것입니다.ExecStartPost 옵션이 사용 중 루프는 운영 체제가 포트가 수신되고 있음을 나타낼 때까지 기다립니다.

한 가지 예:

ExecStartPost=/usr/bin/timeout 30 sh -c 'while ! ss -H -t -l -n sport = :61616 | grep -q "^LISTEN.*:61616"; do sleep 1; done'

이는 ExecStart 후에 실행할 명령을 systemd에 제공합니다. 이 명령은 timeout기본 애플리케이션이 성공적으로 시작되지 않고 30초 이내에 포트에서 수신 대기하지 못하는 경우 오류 중지를 제공하기 위한 것입니다. 이 명령은 수신 대기 중인 포트를 테스트하는 timeout간단한 셸 루프를 래핑합니다 . sh -c ...쉘 루프 자체는 조건이 true가 될 때까지 실행되며 ss ... | grep ...각 테스트 사이에는 1초가 소요됩니다.sleep

이것ss주문하다다음 옵션을 사용할 수 있습니다.

  • -H-- 헤더 억제(이 옵션은 필수는 아니지만 노이즈를 제거하고 싶습니다)
  • -t-- TCP 소켓만 표시
  • -l-- 청취 소켓만 표시
  • -n-- 서비스 번호를 이름으로 해석하지 마세요 -- grep나중에 사용할 수 있도록 번호로 유지하세요.
  • sport = :61616-- 소스 포트가 61616인 항목으로 출력을 제한하는 필터

그런 다음 명령은 grep"LISTEN"으로 시작하고 그 뒤에 문자열 ":61616"이 오는 줄을 찾습니다. 이는 기본 응용 프로그램이 해당 포트에서 수신 대기를 시작했음을 나타냅니다. 이 -q플래그는 grep에게 성공 또는 실패만 보고하고 출력을 내보내지 않도록 지시합니다. 왜냐하면 우리는 라인이 존재하는지 여부에만 관심이 있기 때문입니다.

기본 애플리케이션 시작 중에 systemd는 ExecStartPost 명령이 종료될 때까지 "start-post" 상태를 표시합니다. 애플리케이션이 성공적으로 시작되고 30초 이내에 포트가 열리면 systemd는 상태를 "활성(실행 중)"으로 업데이트합니다. 오류가 발생하면 systemd는 (예에서) Restart=always전체 프로세스를 다시 시작하지만 그렇지 않으면 "실패(결과: 종료 코드)"를 보고하고 종료 코드 "(code=exited, status =124)"를 사용하여 ExecStartPost 명령을 가리킵니다. , 명령 시간이 초과되어 기본 프로세스가 종료됨을 나타냅니다.

관련 정보