시스템 서비스는 종료하지 않고 실행


30

jekyll에 대한 내 자신의 서비스를 만들었고 서비스를 시작할 때 ctrl+ 프로세스를 강제 실행하기 때문에 백그라운드 프로세스로 실행되지 않는 것 같습니다 c. --watch 때문에 전경에 그대로 있습니다. 주변을 돌아 다니면서 백그라운드에서 실행되도록하는 방법을 잘 모르겠습니다. 이견있는 사람?

# /etc/systemd/system/jekyll-blog.service

[Unit]
Description=Start blog jekyll

[Service]
Type=forking
WorkingDirectory=/home/blog
ExecStart=/usr/local/bin/jekyll build --watch --incremental -s /home/blog -d /var/www/html/blog &
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
User=root
Group=root

[Install]
WantedBy=multi-user.target

systemd는 프로세스를 시작하고 사용중인 경우 다른 프로세스를 분기 할 것으로 예상합니다 Type=forking. 또한 execStart쉘 확장으로 실행되지 않으므로 &결국 백그라운드 플래그로 이해되지 않습니다.
grochmal

내 나쁜 & 나는 그것을 테스트했다. 입력이 간단해야합니까?
madmanali93

2
내가 실수하지 않으면 jekyll은 레일 타입의 것, 즉 루비의 작은 웹 서버입니다. 예, Type=simple적절할 것입니다. 또한 이것은 적어도 인터넷 연결 시스템 (귀하의 경우가 아닐 수도 있음)에서는 루트로 실행되는 응용 프로그램이 아닙니다.
grochmal

고마워 간단하게 일했다. 또한이 명령은 jekyll이 서버에서 제공되지 않도록 Apache 용 정적 html을 생성합니다. 루트로 실행하면 괜찮을 것이라고 생각합니다. 논쟁의 여지가 확실하지 않습니다.
madmanali93

오 그래, 그게 뭐야 --incremental:). 예, 파일을 루트로 재생성하는 데 보안 문제가 없습니다. 물론 이러한 파일은 사용자가 제공하지 않은 것으로 간주됩니다.
grochmal

답변:


54

Systemd는 다양한 서비스 유형을 구체적으로 다음 중 하나에서 처리 할 수 ​​있습니다.

  • simple -자체 실행 백그라운드가 아니며 쉘에 계속 붙어있는 장기 실행 프로세스.
  • forking -일반적인 데몬을 실행하여 프로세스를 실행하는 프로세스에서 분리하여 효과적으로 백그라운드 화합니다.
  • oneshot -단기 프로세스가 종료 될 것으로 예상됩니다.
  • dbus -단순하지만 프로세스 시작 완료 알림이 dbus를 통해 전송됩니다.
  • notify -단순하지만 프로세스 시작 완료 알림이 inotify를 통해 전송됩니다.
  • idle -단순하지만 작업이 디스패치 된 후 바이너리가 시작됩니다.

귀하의 경우 Type=forkingsystemd가 프로세스 자체를 포크하고 상위 프로세스가 종료되기를 기다리고 있음을 선택했습니다. 이는 프로세스가 성공적으로 시작되었음을 나타냅니다. 그러나 프로세스 가이 작업을 수행하지 않습니다-포 그라운드에 남아 있으므로 systemctl start프로세스가 충돌 할 때까지 무기한 중단됩니다.

대신 Type=simple기본값 인을 원하므로 선을 완전히 제거하여 동일한 효과를 얻을 수 있습니다. 이 모드에서 systemd는 프로세스가 시작될 때까지 기다리지 않으며 (이 상황이 언제 발생했는지 알 수 없으므로) 즉시 실행 및 종속 서비스를 계속합니다. 귀하의 경우에는 아무것도 없으므로 이것이 중요하지 않습니다.

보안에 관한 작은 참고 사항 :

서비스를 루트로 실행하고 있으며 권한이없는 사용자로 서비스를 실행하는 것보다 덜 안전하므로 권장하지 않습니다. 그 이유 는 jekyll에 명령 실행 (허용되는 코드를 통해)을 실행할 수있는 취약점이있는 경우 시스템을 완전히 소유하기 위해 다른 작업을 수행 할 필요가 없기 때문입니다. 반면, 권한이없는 사용자로 실행되는 경우 공격자는 해당 사용자만큼 많은 피해를 입을 수 있으며 이제 시스템을 완전히 소유하려면 루트 권한을 얻어야합니다. 그것은 단지 공격자가 가야 할 여분의 계층을 추가합니다.

웹 서버를 실행하는 동일한 사용자로 간단하게 실행할 수 있지만 이로 인해 다른 잠재적 인 공격에 노출 될 수 있습니다. 웹 서버에 사용자가 시스템의 파일을 조작 할 수있는 취약점이있는 경우 생성 된 html 파일 또는 최악의 소스 파일을 수정하여 서버가 원하는 것을 제공 할 수 있습니다. 그러나 생성 된 파일과 소스 파일을 웹 서버에서만 읽을 수 있고 권한이없는 다른 사용자가 쓸 수있는 경우 웹 서버를 공격하여 쉽게 수정할 수 없습니다.

그러나 단순히이 서버에서 정적 파일을 제공하고 서버를 최신 상태로 유지하는 경우 이러한 공격은 매우 드물지만 여전히 가능합니다. 시스템이 얼마나 중요한지에 따라 위험을 설정하고 오버 헤드를 설정하는 것은 귀하의 책임입니다. 그러나이 두 가지 팁은 설정이 매우 간단하고 유지 보수 오버 헤드가 없습니다.


0

@ Michael Daffin 의 솔루션 외에도 다음 예제와 같이 daemonize 도구를 사용하여 사용법을 얻을 수 있습니다 forking.

내가 데몬 화하고 systemd를 제어하고 싶은 작은 쉘 스크립트가 주어지면 다음과 같이 저장했습니다 /home/pi/testscript.sh.

#!/bin/bash

while true;
do
    sleep 1
    echo -n "."
done

아직없는 경우 다음과 같이 daemonize를 설치하십시오.

sudo apt install daemonize

이제 파일 서비스 정의 파일을 작성하십시오.

sudo vi /etc/systemd/system/testomat.service
# It is not recommended to modify this file in-place, because it will
# be overwritten during package upgrades. If you want to add further
# options or overwrite existing ones then use
# $ systemctl edit testomat.service
# See "man systemd.service" for details.

# copied from https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service and modified by Michael 

[Unit]
Description=Test service
After=network.target

[Service]
ExecStart=daemonize -p /run/testomat/testomat.pid -o /home/pi/testscript.log /home/pi/testscript.sh
TimeoutSec=1200

# Make sure the config directory is readable by the service user
PermissionsStartOnly=true

# Process management
####################
Type=forking
PIDFile=/run/testomat/testomat.pid
Restart=on-failure
GuessMainPID = true

# Directory creation and permissions
####################################

# Run as pi:pi
User=pi
Group=pi

# /run/testomat
RuntimeDirectory=testomat
RuntimeDirectoryMode=0710

# /var/lib/testomat
StateDirectory=testomat
StateDirectoryMode=0710

# Hardening measures
####################

# Provide a private /tmp and /var/tmp.
PrivateTmp=true

# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full

# Allow access to /home, /root and /run/user
# Chosing "false" is actually no hardening, this is just to demonstrate the usage of a service. Well, I could have omitted it. True. :)
ProtectHome=false

# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true

# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true

# Deny the creation of writable and executable memory mappings.
MemoryDenyWriteExecute=true

[Install]
WantedBy=multi-user.target

새로 생성 된 서비스는 systemd에 발표되어야합니다.

systemctl daemon-reload

이제 서비스와 스크립트 포크를 시작할 수 있습니다. 예상대로 서비스 시작은 즉시 셸로 돌아옵니다. 결과는 분명하다 :

$ tail -f testscript.log 
.....................


systemd가 서비스 시작을 돌보는 대신 daemonize+ 를 사용하면 어떤 이점이 있습니까? 포크로 작성된 레거시 프로그램을 지원하기 위해 systemd에서 일종의 호환성 설정입니다. Type=forkingType=simpleType=forking
Johan Myréen

나는 그것이 동등한 해결책이라고 생각한다. 방금 OP에 대체 솔루션을 제공하고 /etc/init.d 시간에 이미 사용했던이 도구에 대해 알고 싶었습니다. 프로세스를 데몬 화하는 방법에 대한 질문이기도합니다.
Michael
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.