프로토콜 불일치 준비

프로토콜 불일치 준비

systemdOSSEC HIDS용 유닛 파일을 작성 중입니다 . 문제는 systemd서비스를 시작하면 즉시 중지된다는 것입니다.

다음 명령을 사용하면 ExecStart모든 것이 잘 작동합니다.

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

그러나 다음과 같은 작은 개선 사항을 적용했을 때 SIG 15부팅 후 받은 OSSEC 로그에서 이러한 사실을 발견했습니다.

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

또 다른 작은 변경을 하면 서비스는 SIG 1520초 후에 이를 수신합니다.

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

그래서 저는 서비스가 시작된 후 프로세스를 종료하고 systemd./bin/sh/bin/shOSSEC

이 문제를 어떻게 해결할 수 있나요?

답변1

프로토콜 불일치 준비

Wieland가 암시하듯 Type이 서비스 품질은 중요합니다. 이 설정은 무엇을 의미하나요?계약 준비systemd는 서비스가 대화할 수 있을 것으로 기대합니다. simple서비스는 즉시 준비되는 것으로 간주됩니다. forking초기 프로세스가 하위 프로세스로 분기된 후 종료되면 서비스는 준비된 것으로 간주됩니다. dbus데스크탑 버스에 서버가 있으면 서비스가 준비된 것으로 간주됩니다. 등.

서비스 기능과 일치하는 서비스 단위에서 준비 프로토콜을 선언하지 않으면 문제가 발생할 수 있습니다. 준비 프로토콜 불일치로 인해 서비스가 올바르게 시작되지 않거나 (더 일반적으로) systemd에서 오류로 진단될 수 있습니다. 서비스를 시작할 수 없는 것으로 간주되면 systemd는 다음을 보장합니다.서비스의 각 고아 추가 프로세스오류의 일부로(해당 관점에서) 실행 중이었을 수 있는 서비스는 서비스를 비활성 상태로 적절하게 되돌리기 위해 종료됩니다.

그것이 바로 당신이 하는 일입니다.

첫째, 간단한 것: sh -c일치하지 Type=simple않거나 Type=forking.

simple프로토콜 에서 초기 프로세스는 다음과 같습니다.서비스 프로세스. 그러나 실제로 sh -c래퍼는 실제 서비스 프로그램을 실행합니다.자식 프로세스로. 첫째, 문제가 발생하여 작동이 중단됩니다 MAINPID. ExecReload를 사용할 때는 또는 를 Type=simple사용해야 합니다.sh -c 'exec …'사용하지 마세요 sh -c첫 번째. 후자는 일부 사람들이 생각하는 것보다 더 사실인 경우가 많습니다.

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

불필요한 공포ossec-control

이것은 우리에게 복잡한 것, 즉 스크립트를 소개합니다 ossec-control.

그것은 밝혀rc이는 4~10개의 프로세스를 분기하고 자체적으로 분기하고 종료하는 System 5 스크립트입니다 . 이는 루프, 경쟁 조건, 이를 피하려는 임의의 s 및 시스템을 절반 부팅 상태로 둘 수 있는 실패 모드를 rc사용하여 하나의 스크립트에서 전체 서버 프로세스를 관리하려고 시도하는 System 5 스크립트 중 하나입니다. 다른 모든 무서운 것들 AIX 시스템 리소스 컨트롤러(System Resource Controller) 및 daemontools와 같은 것들은 20년 전에 발명되었습니다. 특별한 기능 과 동사를 구현하기 위해 동적으로 다시 작성되는 바이너리 디렉토리에 숨겨진 쉘 스크립트를 잊지 마십시오 .forsleepenabledisable

다음 과 /bin/sh -c '/var/ossec/bin/ossec-control start'같은 경우에는 어떻게 되나요?

  1. systemd는 기대하는 서비스 프로세스를 포크합니다.
  2. 그게 지각이고, 두 갈래로 갈라져 있어요 ossec-control.
  3. 그러면 4~10명의 손주가 탄생하게 됩니다.
  4. 손자들은 모두 차례로 포크하고 나갔다.
  5. 증손자는 모두 분기하여 병렬로 종료합니다.
  6. ossec-control그만두다.
  7. 첫 번째 쉘이 종료됩니다.
  8. 서비스 프로세스는좋아 좋아 -손자이지만 이것이 작동하는 방식 때문에 잘 어울립니다.어느 것도 아니다이것forking ...도 아니다준비 프로토콜에 따라 simplesystemd는 전체 서비스가 실패한 것으로 간주하고 다시 종료합니다.

systemd에서는 이러한 끔찍한 일이 실제로 전혀 필요하지 않습니다. 아무것도 아님.

systemd 템플릿 서비스 단위

대신 아주 간단하게 작성하세요.템플릿 단위:

[단위]
설명=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/[email protected]

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

그런 다음 기능을 활성화 및 비활성화합니다.서비스 관리 시스템에서 직접(그리고Red Hat 오류 752774수정됨) 쉘 스크립트를 숨기지 않고.

systemctl 활성화 ossec@dbd ossec@agentlessd ossec@csyslogd ossec@maild ossec@execd ossec@analyticd ossec@logcollector ossec@remote ossec@syscheckd ossec@monitord

또한 systemd는 각 실제 서비스에 대한 직접적인 가시성과 추적 기능을 갖추고 있습니다. 이는 로그를 필터링하는 데 사용될 수 있습니다 journalctl -u. 단일 서비스가 언제 실패하는지 알 수 있습니다. 어떤 서비스를 활성화하고 실행해야 하는지 알고 있습니다.

참고: 여기의 Type=simple옵션은 -f다른 많은 경우와 마찬가지로 정확합니다. 현장 서비스가 거의 없음실제로 그들이 준비가 되었음을 보여줍니다.덕분에 exit여기서도 그렇지 않습니다. 그러나 그것이 forking유형에 관한 것입니다. 야생에서의 서비스는 대부분 단지 포크하고 종료하는 것입니다. 왜냐하면 이것이 데몬이 해야 할 일이라는 일부 오해 때문입니다. 실제로는 그렇지 않습니다. 1990년대 이후로는 그렇지 않았습니다. 이제 따라잡을 시간입니다.

추가 읽기

답변2

시작 서비스/애플리케이션이 PID를 유지 관리하는 경우 Type=forkingPID 파일 위치를 유지하고 제공하십시오.

[Unit]
Description="Run app on boot"
After=network.target syslog.target auditd.service

[Service]
Type=forking
PIDFile=/var/run/apache2/apache2.pid
ExecStart=/etc/init.d/apache2 start
ExecStop=/etc/init.d/apache2 stop
StandardOutput=syslog
StandardError=syslog
Restart=on-failure
SyslogIdentifier=webappslog

[Install]
WantedBy=multi-user.target
Alias=webapps

답변3

다소 관련이 있는 것은 systemd 서비스가 있는데 systemd가 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실제 이유가 밝혀졌습니다. (접선) bash 에서와 같은 구문을 사용할 수 없습니다 Environment=ABC="true". 따옴표가 없어야 하거나 키 값이 모두 따옴표 안에 있어야 합니다. Environment="ABC=true"이로 인해 프로세스가 약 30초 후에 "설정 단계에서" 종료되었습니다.

답변4

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

JdeBP의 설명은 환영하지만 불완전하며 그는 이것이 모두 ossec-control의 잘못이라고 주장하는데 이는 사실이 아닙니다. 문제를 디버깅하기 위해 프로세스를 종료할 때 검열되지 않은 로그 라인을 얻거나 systemd 자체에서 의미 있는 오류 메시지를 얻는 등 매우 사소한 것조차도 문제가 될 수 있습니다.

관련 정보