https://access.redhat.com/solutions/2978271
SOLUTION 已驗證 - 已更新 2017年六月22日04:24 -
English
環境
- Red Hat Enterprise Linux 7
- Custom Systemd Unit files
問題
- I have created a systemd script for our environment which starts and stops the processes fine with a server reboot. Daily we restart some of those processes with a separate script which causes systemd to think the service status is inactive. Is there a way to force systemd to run a stop of the service even if it thinks the current status is inactive (dead)?
- Is there a way to make systemd understand the processes are still active (running) even after a separate script has restarted the processes?
決議
The option needed within the systemd unit file
[Service]
definitions is
RemainAfterExit=yes
.
From the description in the man pages:
Raw
RemainAfterExit=
Takes a boolean value that specifies whether the service
shall be considered active even when all its processes
exited. Defaults to no.
根源
With the action of allowing systemd to start the service, but then managing it externally to systemd, systemd assumes that the service has entered a dead state. By setting the above, the end result should be that systemd will still consider the service active regardless of the actions taken in the interim.
Note: This does not avoid the issues documented in the article below. Though the shutdown scripts will be executed during system shutdown using the resolution documented, it will not isolate processes that have been externally restarted from being shutdown in the indicated manner.
When restarting a service outside of systemd, why are the processes killed in a non-graceful manner during a subsequent system shutdown and reboot?
Please see the following example:
/root/test
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int parent;
int fd;
int retval;
char buffer[8];
printf("Parent = %d\n", getpid());
parent = fork();
if (parent > 0) {
printf("Forked %d\n", parent);
retval = snprintf(buffer, sizeof(buffer), "%d\n", parent);
fd = open("/tmp/test.pid", O_CREAT|O_CLOEXEC|O_RDWR);
retval = write(fd, buffer, sizeof(buffer));
close(fd);
} else {
while (1) {
sleep(1);
}
}
return 0;
}
/root/testkill.sh
#!/bin/bash
PID=$(cat /tmp/test.pid)
echo "Killing $PID" >> /tmp/test.log
kill $PID
/etc/systemd/system/test.service
[Unit]
Description=Testing the remainafterexit option
[Service]
Type=forking
PIDFile=/tmp/test.pid
ExecStartPre=/bin/bash -c "echo Started $MAINPID"
ExecStart=/root/test
ExecStop=/bin/bash /root/testkill.sh
ExecStopPost=/bin/bash -c "echo Stopped $MAINPID"
KillMode=none
Testing the above:
# systemctl start test
# systemctl status test
● test.service - Testing the remainafterexit option
Loaded: loaded (/etc/systemd/system/test.service; static; vendor preset: disabled)
Active: active (running) since Wed 2016-12-07 12:33:20 EST; 12s ago
Process: 5673 ExecStart=/root/test (code=exited, status=0/SUCCESS)
Process: 5672 ExecStartPre=/bin/bash -c echo Started $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 5676 (test)
CGroup: /system.slice/test.service
└─5676 /root/test
Dec 07 12:33:20 example.hostname.com systemd[1]: Starting Testing the remainafterexit option...
Dec 07 12:33:20 example.hostname.com bash[5672]: Started
Dec 07 12:33:20 example.hostname.com test[5673]: Parent = 5673
Dec 07 12:33:20 example.hostname.com test[5673]: Forked 5676
Dec 07 12:33:20 example.hostname.com systemd[1]: Started Testing the remainafterexit option.
Without the
RemainAfterExit
option:
# bash /root/testkill.sh
# systemctl status test
● test.service - Testing the remainafterexit option
Loaded: loaded (/etc/systemd/system/test.service; static; vendor preset: disabled)
Active: failed (Result: exit-code) since Wed 2016-12-07 12:34:18 EST; 2s ago
Process: 5685 ExecStopPost=/bin/bash -c echo Stopped $MAINPID (code=exited, status=0/SUCCESS)
Process: 5682 ExecStop=/bin/bash /root/testkill.sh (code=exited, status=1/FAILURE)
Process: 5673 ExecStart=/root/test (code=exited, status=0/SUCCESS)
Process: 5672 ExecStartPre=/bin/bash -c echo Started $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 5676 (code=killed, signal=TERM)
Dec 07 12:33:20 example.hostname.com systemd[1]: Starting Testing the remainafterexit option...
Dec 07 12:33:20 example.hostname.com bash[5672]: Started
Dec 07 12:33:20 example.hostname.com test[5673]: Parent = 5673
Dec 07 12:33:20 example.hostname.com test[5673]: Forked 5676
Dec 07 12:33:20 example.hostname.com systemd[1]: Started Testing the remainafterexit option.
Dec 07 12:34:18 example.hostname.com bash[5682]: /root/testkill.sh: line 6: kill: (5676) - No such process
Dec 07 12:34:18 example.hostname.com systemd[1]: test.service: control process exited, code=exited status=1
Dec 07 12:34:18 example.hostname.com bash[5685]: Stopped
Dec 07 12:34:18 example.hostname.com systemd[1]: Unit test.service entered failed state.
Dec 07 12:34:18 example.hostname.com systemd[1]: test.service failed.
With the
RemainAfterExit
# systemctl start test
# bash /root/testkill.sh
# systemctl status test
● test.service - Testing the remainafterexit option
Loaded: loaded (/etc/systemd/system/test.service; static; vendor preset: disabled)
Active: active (exited) since Wed 2016-12-07 12:35:07 EST; 8s ago
Process: 5732 ExecStart=/root/test (code=exited, status=0/SUCCESS)
Process: 5730 ExecStartPre=/bin/bash -c echo Started $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 5735 (code=killed, signal=TERM)
Dec 07 12:35:07 example.hostname.com systemd[1]: Starting Testing the remainafterexit option...
Dec 07 12:35:07 example.hostname.com bash[5730]: Started
Dec 07 12:35:07 example.hostname.com test[5732]: Parent = 5732
Dec 07 12:35:07 example.hostname.com test[5732]: Forked 5735
Dec 07 12:35:07 example.hostname.com systemd[1]: Started Testing the remainafterexit option.
# /root/test
Parent = 5740
Forked 5741
# systemctl stop test
# systemctl status test
● test.service - Testing the remainafterexit option
Loaded: loaded (/etc/systemd/system/test.service; static; vendor preset: disabled)
Active: inactive (dead)
Dec 07 12:34:18 example.hostname.com systemd[1]: Unit test.service entered failed state.
Dec 07 12:34:18 example.hostname.com systemd[1]: test.service failed.
Dec 07 12:35:07 example.hostname.com systemd[1]: Starting Testing the remainafterexit option...
Dec 07 12:35:07 example.hostname.com bash[5730]: Started
Dec 07 12:35:07 example.hostname.com test[5732]: Parent = 5732
Dec 07 12:35:07 example.hostname.com test[5732]: Forked 5735
Dec 07 12:35:07 example.hostname.com systemd[1]: Started Testing the remainafterexit option.
Dec 07 12:36:19 example.hostname.com systemd[1]: Stopping Testing the remainafterexit option...
Dec 07 12:36:19 example.hostname.com bash[5749]: Stopped
Dec 07 12:36:19 example.hostname.com systemd[1]: Stopped Testing the remainafterexit option.