天天看點

How to configure services within Systemd that can be restarted outside of Systemd?

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.           

繼續閱讀