Bug 612728

Summary: please extend /etc/rc.d/init.d/functions to warn the user when he runs a sysv init script directly in a systemd environment
Product: [Fedora] Fedora Reporter: Lennart Poettering <lpoetter>
Component: initscriptsAssignee: Bill Nottingham <notting>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: low    
Version: 14CC: adam, alexandr.kara, iarlyy, jcm, jonathan, mattdm, mlichvar, notting, plautrba, rvokal, walters
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: initscripts-9.17-2.fc14 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-08-26 23:06:16 EDT Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Description Lennart Poettering 2010-07-08 17:10:05 EDT
When systemd is used it is highly recommended to start/stop services via systemd instead of having the user directly run /etc/init.d/foo, in order to ensure that the service is properly run inside its own cgroup and so on.

In order to warn the user when he nonetheless runs those scripts directly, I'd like to request the following addition to the /etc/rc.d/init.d/functions script near the top:

if [ $PPID -ne 1 -a \
        x"$(basename $0)" != xservice ] && \
        /bin/mountpoint -q /cgroup/systemd ; then

        echo "Please do not invoke this init script ($0) directly!" > /dev/stderr
        echo -e "Use a command like the following instead:\n"
        echo -e "\t$ systemctl start $(basename $0).service"
        echo -e "\t$ systemctl stop $(basename $0).service"
        echo -e "\t$ systemctl status $(basename $0).service"
        echo -e "\t...\n"
        echo "See systemctl(1) for more information."
        exit 6
fi

This prints a warning and terminates the script early with error code 6 ("program is not configured" according to LSB) if the user tries to invoke a shell script which sources the functions file. 

In this shell fragment we check the PPID to distuingish whether the script is started from the init system itself (which we let go through) or from user context. We also check whether $0 is "service", to avoid confusion when the user uses /sbin/service to invoke a script, since /sbin/service also sources the functions file.

Finally, we check whether the systemd cgroup file system is mounted, which should be a reliable check whether the system was booted up with systemd.
Comment 1 Bill Nottingham 2010-07-08 17:17:59 EDT
This sounds like it would break *way* too much backwards compatibility, automated scripts, etc.

We could certainly change the /sbin/service script to poke systemd if it's running.
Comment 2 Lennart Poettering 2010-07-08 17:22:30 EDT
Well, the thing is that nobody uses /sbin/service...
Comment 3 Bill Nottingham 2010-07-08 17:23:50 EDT
In my experience, it's about 60/40 in favor of people who use /sbin/service. Certainly, a good chunk of random online documentation refers to it.
Comment 4 Lennart Poettering 2010-07-08 17:24:39 EDT
Could you please elaborate what uses you think this would break? Would this change be acceptable to you if we'd ensure that $0 starts with /etc/init.d before we do this? Or would it be acceptable to you if we'd just print the warning to stderr in big letters but would still go on running this? Or would it be acceptable if we'd turn the direct invocations into systemctl invocations?
Comment 5 Bill Nottingham 2010-07-08 17:31:08 EDT
Either of the latter two; I don't like it being a hard error.

As you intimate, there are some scripts that source /etc/init.d/functions that aren't init scripts, and we'd need to make sure that still works without errors as well.
Comment 6 Lennart Poettering 2010-07-08 18:43:43 EDT
Ok, here's my second try:

<snip>
if [ $PPID -ne 1 ] && /bin/mountpoint -q /cgroup/systemd ; then

        case "$0" in

        /etc/init.d/*|/etc/rc.d/init.d/*)

                BASENAME="$(/bin/basename $0)"

                echo "Please do not invoke this init script ($0) directly!" > /dev/stderr
                echo -e "Use commands like the following instead:\n"
                echo -e "\t$ systemctl start $BASENAME.service"
                echo -e "\t$ systemctl stop $BASENAME.service"
                echo -e "\t$ systemctl status $BASENAME.service"
                echo -e "\t...\n"
                echo -e "See systemctl(1) for more information.\n"

                if  [ "x$1" = xstart -o \
                        "x$1" = xstop -o \
                        "x$1" = xrestart -o \
                        "x$1" = xreload -o \
                        "x$1" = xstatus ] ; then

                        COMMAND=$1

                        # systemctl's native status command is more verbose than the classic
                        # SysV 'status', hence we turn this into 'check' here.
                        [ $COMMAND = status ] && COMMAND=check

                        echo -e "For compatibility the following command will now be invoked:\n"
                        echo -e "\t$ systemctl -q $COMMAND $BASENAME.service\n"
                        exec /bin/systemctl -q $COMMAND "$BASENAME.service"
                fi
                ;;

        esac
fi
</snip>

This now verifies the executed script is indeed an init script, and then tries to convert the command into systemctl if possible, and otherwise go on with the normal script.

Is this acceptible?
Comment 7 Bill Nottingham 2010-07-09 13:42:52 EDT
I'd want to set up a machine and do some verification, but it sounds good in theory.
Comment 8 Lennart Poettering 2010-07-21 09:00:55 EDT
ping?
Comment 9 Colin Walters 2010-07-21 11:57:56 EDT
One independent thing I think we should have done 10 years ago is make the /etc/init.d/foo scripts, if run directly by an admin, transparently redirect to /sbin/service foo "$@".

This would fix several bugs - namely that /etc/init.d/foo often doesn't e.g. clean the environment, and so you can end up with weird crud from the current root shell in the running daemon.

Maybe have /etc/init.d/functions do:

if test -z "$__MAGIC_SERVICE_ENVIRONMENT"; then
  exec /sbin/service $0 "$@"
fi

and /sbin/service does setenv("__MAGIC_SERVICE_ENVIRONMENT", "1") and runs the /etc/init.d script (which in turn unsets the environment variable before execing the daemon).
Comment 10 Bill Nottingham 2010-07-27 14:04:38 EDT
Hm, if we do that, then we might want to do the redirection as:

init.d/functions -> /sbin/service -> systemctl.
Comment 11 Bug Zapper 2010-07-30 08:29:02 EDT
This bug appears to have been reported against 'rawhide' during the Fedora 14 development cycle.
Changing version to '14'.

More information and reason for this action is here:
http://fedoraproject.org/wiki/BugZappers/HouseKeeping
Comment 12 Lennart Poettering 2010-08-10 09:05:48 EDT
Bill, what are your plans on this?

My original patch could use various updates before you merge this if you decide to merge it, i.e. we now support a number of additional sysv-comaptible verbs (i.e. "condrestart" and suchlike), so if you decide to merge this my patch would need more updating.

I am not too concerned by the issues Colin pointed out given that if we start things from systemd the environment will be guaranteed to be cleaned. systemd is much more thorough in providing a clean execution context to start things in then even /sbin/service could offer.
Comment 13 Bill Nottingham 2010-08-11 10:49:23 EDT
Still in favor of the concept, so updated versions would be nice.
Comment 14 Miroslav Lichvar 2010-08-20 08:11:40 EDT
Will be this and bug #616857 supported indefinitely? Or should applications that enable and start services like system-config-date support both chkconfig/service and systemctl?
Comment 15 Bill Nottingham 2010-08-20 10:46:36 EDT
chkconfig should be modified to support poking systemctl, so that downstream things don't require guessing where a service is configured.
Comment 16 Jon Masters 2010-08-20 15:00:35 EDT
Besides, chkconfig is the well-known, documented way to do things on Red Hat systems. A large chunk of documentation and user knowledge will otherwise need to be rewritten to ensure people know about systemd.
Comment 17 Bill Nottingham 2010-08-25 14:05:34 EDT
*** Bug 627328 has been marked as a duplicate of this bug. ***
Comment 18 Fedora Update System 2010-08-25 16:25:52 EDT
initscripts-9.17-1.fc14 has been submitted as an update for Fedora 14.
http://admin.fedoraproject.org/updates/initscripts-9.17-1.fc14
Comment 19 Fedora Update System 2010-08-25 22:14:18 EDT
initscripts-9.17-1.fc14 has been pushed to the Fedora 14 testing repository.  If problems still persist, please make note of it in this bug report.
 If you want to test the update, you can install it with 
 su -c 'yum --enablerepo=updates-testing update initscripts'.  You can provide feedback for this update here: http://admin.fedoraproject.org/updates/initscripts-9.17-1.fc14
Comment 20 Fedora Update System 2010-08-26 13:49:42 EDT
systemd-8-2.fc14,initscripts-9.17-2.fc14 has been submitted as an update for Fedora 14.
http://admin.fedoraproject.org/updates/systemd-8-2.fc14,initscripts-9.17-2.fc14
Comment 21 Fedora Update System 2010-08-26 23:05:54 EDT
initscripts-9.17-2.fc14, systemd-8-3.fc14 has been pushed to the Fedora 14 stable repository.  If problems still persist, please make note of it in this bug report.