시작 후 즉시 시스템 종료 서비스


15

OSSEC HIDS의 시스템 단위 파일을 작성 중입니다. 문제는 systemd가 서비스를 시작할 때 즉시 중지한다는 것입니다.

해당 ExecStart 지시문을 사용하면 모두 정상적으로 작동합니다.

ExecStart=/var/ossec/bin/ossec-control start

그러나 작은 개선을 할 때 OSSEC 로그에서 괜찮습니다. 시작 후에 SIG 15를받습니다.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'

다른 작은 변경 서비스를 수행하면 20 초 후에 SIG 15가 수신됩니다.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'

따라서 systemd는 서비스 시작 후 / bin / sh 프로세스를 종료하고 bin / sh는 OSSEC을 종료합니다.

이 문제를 어떻게 해결할 수 있습니까?


1
서비스의 종류는 무엇입니까?
Wieland

@ Wiieland, 나는 간단하고 포크하려고했지만 결과는 여전히 동일합니다.
Daniil Svetlov

답변:


37

준비 프로토콜 불일치

Wieland가 암시 한 것처럼 Type서비스는 중요합니다. 이 설정은 systemd가 준비된 서비스 준비 상태를 나타냅니다 . simple서비스는 즉시 준비로 간주됩니다. forking서비스는 초기 프로세스가 종료 한 후 아이를 포크 후 준비가 취해진 다. dbus서비스는 서버가 데스크톱 버스에 나타날 때 준비가되어 촬영됩니다. 기타 등등.

서비스와 일치하도록 서비스 유닛에 선언 된 준비 프로토콜을 얻지 못하면 문제가 발생합니다. 준비 프로토콜이 일치하지 않으면 서비스가 올바르게 시작되지 않거나 systemd에 의해 (보통) 실패로 진단됩니다. 서비스가 시스템 시작에 실패한 것으로 보이면 서비스 를 다시 비활성 상태로 다시 가져 오기 위해 장애의 일부로 실행중인 상태로 남아있을 수 있는 서비스의 모든 고아 추가 프로세스가 종료 되도록합니다. 상태.

당신은 정확히 이것을하고 있습니다.

우선, 간단한 것들 : 또는 sh -c일치하지 않습니다 . Type=simpleType=forking

에서 simple프로토콜, 초기 과정을 촬영 서비스 프로세스. 그러나 실제로 sh -c랩퍼는 실제 서비스 프로그램 을 하위 프로세스로 실행합니다 . 그래서 MAINPID잘못하고 ExecReload우선, 작동을 멈 춥니 다. 사용할 때Type=simple , 하나는 하나를 사용한다 sh -c 'exec …'또는 사용하지 sh -c 처음부터. 후자는 일부 사람들이 생각하는 것보다 올바른 과정입니다.

sh -c일치하지 않습니다 Type=forking. forking서비스 의 준비 프로토콜 은 매우 구체적입니다. 초기 프로세스는 자식을 포크 한 다음 종료해야합니다. systemd는이 프로토콜에 시간 초과를 적용합니다. 초기 프로세스가 할당 된 시간 내에 분기되지 않으면 준비가되지 않은 것입니다. 초기 프로세스가 할당 된 시간 내에 종료되지 않으면 실패입니다.

불필요한 공포 ossec-control

우리를 복잡한 것들로 인도합니다. ossec-control .

그것은 판명 이 시스템 5하다고 rc스크립트가 4과 10 사이 프로세스 오프 포크, 너무 자신의 차례 포크와 출구에있는 자신. 루프, 경쟁 조건, 이를 피하기위한 임의 의 s, 반 시작 상태에서 시스템을 질식시킬 수있는 장애 모드 등 rc단일 스크립트에서 전체 서버 프로세스 세트를 관리하려는 System 5 스크립트 중 하나입니다 . 그리고 사람들이 20 년 전에 AIX System Resource Controller 및 daemontools와 같은 것을 발명하게 한 다른 모든 공포들. 그리고 이디 오싱 크라 틱 과 동사 를 구현하기 위해 즉시 다시 쓰는 바이너리 디렉토리의 숨겨진 쉘 스크립트를 잊지 마십시오 .forsleepenabledisable

그래서 당신 /bin/sh -c '/var/ossec/bin/ossec-control start'이 일어날 때 :

  1. 시스템 포크는 서비스 프로세스가 될 것으로 예상되는 것을 포크합니다.
  2. 그것은 껍질 ossec-control입니다.
  3. 그것은 4-4 명의 손자를 포크로 만듭니다.
  4. 손자는 모두 포크로 빠져 나옵니다.
  5. 증손자 모두 포크와 출구를 동시에 나눕니다.
  6. ossec-control 종료합니다.
  7. 첫 번째 쉘이 종료됩니다.
  8. 서비스 프로세스는 있었다 증조 증조 손자,하지만 작업 일치의 방법이 있기 때문에 어느 쪽도 forking simple 준비 프로토콜, systemd가 전체 서비스를 고려하지가 아래로 다시 실패하고 닫힌다 것으로.

이 공포의 어느 것도 실제로 체계적으로 필요하지 않습니다. 그것도 없습니다.

체계화 된 템플릿 서비스 유닛

대신 매우 간단한 템플릿 단위를 씁니다. .

[단위]
Description = OSSEC HIDS % i 서버
이후 = network.target 

[서비스]
유형 = 단순
ExecStartPre = / usr / bin / env / var / ossec / bin / % p- % i -t
ExecStart = / usr / bin / env / var / ossec / bin / % p- % i -f

[설치]
WantedBy = 다중 사용자. 대상

이것을로 저장하십시오 /etc/systemd/system/ossec@.service.

다양한 실제 서비스는 이 템플릿의 인스턴스 이며 이름은 다음과 같습니다.

  • ossec@dbd.service
  • ossec@agentlessd.service
  • ossec@csyslogd.service
  • ossec@execd.service
  • ossec@agentd.service
  • ossec@logcollector.service
  • ossec@syscheckd.service
  • ossec@maild.service
  • ossec@analysisd.service
  • ossec@remoted.service
  • ossec@monitord.service

그런 다음 서비스 관리 시스템 에서 RedHat 버그 752774 와 함께 활성화 및 비활성화 기능 이 제공됩니다. 숨겨진 쉘 스크립트가 수정) .

 systemctl 활성화 ossec @ dbd ossec @ agentlessd ossec @ csyslogd ossec @ maild ossec @ execd ossec @ analysisd ossec @ logcollector ossec @ remoted ossec @ syscheckd ossec @ monitord

또한 systemd는 각 실제 서비스를 직접 알고 추적합니다. 로 로그를 필터링 할 수 있습니다 journalctl -u. 개별 서비스가 실패한시기를 알 수 있습니다. 어떤 서비스를 활성화하고 실행해야하는지 알고 있습니다.

그런데 : Type=simple-f옵션 여기가 다른 많은 경우에 한합니다. 야생에서 거의 서비스가 실제로 dint로 준비 상태나타내는 신호exit 는 거의 없으며, 이러한 서비스도 마찬가지입니다. 그러나 이것이 forking유형의 의미입니다. 메인의 야생에서 서비스는 단지 잘못되어서 악마가해야 할 지혜 개념을 받았기 때문에 포크와 출구입니다. 사실 그렇지 않습니다. 1990 년대 이후로는 없었습니다. 따라 잡을 시간입니다.

추가 자료


2
매우 자세한 답변! 또한 Requires=필요한 모든 인스턴스를 가진 "그룹화"대상 (예 : ossec.target)을 만든 다음 PartOf=ossec.targetossec @ .service 로 설정 하는 것이 좋습니다. ossec.target을 시작하고 중지하여 ossec을 시작하고 중지 할 수 있습니다.
intelfx

@JdeBP, 와우! 자세한 답변을 주셔서 감사합니다. 이 단위를 만들고 결과에 대해 여기에 글을 쓰길 바랍니다. 나는 더 쉬울 것이라고 생각했다. 그러나 당신이 옳습니다. ossec-controll은 초기 지옥입니다.
Daniil Svetlov

1
/ usr / bin / env를 래퍼로 사용하는 이유는 무엇입니까?
Marius Gedminas 2016 년

1

start service / app가 pid를 유지 관리하는 경우 Type = forking을 유지하고 pid 파일 위치를 지정하십시오.

[단위]
설명 = "부팅시 앱 실행"
After = network.target syslog.target auditd.service

[서비스]
유형 = 포킹
PIDFile = / var / run / apache2 / apache2.pid
ExecStart = / etc / init.d / apache2 시작
ExecStop = / etc / init.d / apache2 stop
StandardOutput = syslog
StandardError = syslog
재시작 = 실패
SyslogIdentifier = webappslog

[설치]
WantedBy = multi-user.target
Alias ​​= webapps


0

다소 관련이있는, 나는 체계화 된 서비스를 받았는데 그것은 30 년대 후에 체계화되어 그것을 "죽일"것입니다.

systemctl status service-namemain process exited, code=exited, status=1/FAILURE30 대가 지나면 보여줄 것 입니다.

동일한 "인터페이스에서 같은 환경 에서 수동으로"처럼 "절연"상태로 실행 됩니다.

그것은 밝혀졌다

Type=forking
...
Environment=ABC="TRUE"
ExecStart=/path/to/my_script_to_spawn_process.sh

그 안에 my_script_to_spawn_process.sh있었다

/bin/something > /dev/null 2>&1 &

작동하지만 출력 로그 정보를 삭제했습니다 (일반적으로 파일로 이동하거나 그렇지 않은 경우 가능 journalctl).

다른 곳으로 로그인하도록 변경 /bin/something > /tmp/my_file

그런 다음 /tmp/my_file실제 원인을 공개. Environment=ABC="true"bash에서와 같이 구문을 사용할 수 없다는 것은 (접선 적으로) 따옴표가 아니거나 따옴표 안에 키 값이 없어야합니다 Environment="ABC=true". 약 30 초 후에 프로세스가 "설정 단계에서"종료 된 것과 같은 따옴표 안에 있어야합니다.


-4

systemd의 데몬 모델은 단순하고 여러 개의 포크, 실행 및 설정을 수행하는 많은 기존 데몬과 호환되지 않습니다. 가장 일반적인 것은 데몬이 루트로 시작하여 일을 설정 한 다음 권한이 적은 UID로 전환하여 일상적인 작업을 수행하는 것입니다. 예를 들어 Pid 파일 초기화는 권한 문제로 인해 systemd에서 실패하는 것입니다. 해결 방법이 있지만 (수정 아님) 문서화가 잘못되었습니다.

JdeBP의 설명은 환영하지만 불완전하며 그것이 모든 ossec-control의 잘못이라는 주장은 단순히 사실이 아닙니다. 프로세스를 죽일 때 시스템 자체에서 문제 또는 의미있는 오류 메시지를 디버그하기 위해 잘리지 않은 로그 라인을 얻는 것조차 매우 사소한 문제입니다.


1
어쨌든 PID 파일은 어떤 용도로 사용됩니까? 주어진 서비스에 대해 존재하는 경우 해당 PID에 대한 실제 프로세스가 있거나 없을 수 있으며 올바른 PID가있는 프로세스가 존재하면 실제로 예상되는 서비스 일 수도 있고 아닐 수도 있습니다.
JoostM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.