Linux中 service 命令淺析

Service命令在不同的Linux發(fā)行版中都有不同的實現(xiàn)骚灸,并且同一發(fā)行版不同的版本號之間功能也不盡相同
但無論怎么變化虱朵,Service命令永遠都只是一組腳本
下面對比的是 CentOS6.5蓖康、CentOS8.3以及Ubuntu20.04蓉坎,Service命令的代碼變化

//CentOS6.5 位于/sbin/service
#!/bin/sh

. /etc/init.d/functions

VERSION="$(basename $0) ver. 0.91"
USAGE="Usage: $(basename $0) < option > | --status-all | \
[ service_name [ command | --full-restart ] ]"
SERVICE=
SERVICEDIR="/etc/init.d"
OPTIONS=

if [ $# -eq 0 ]; then
   echo "${USAGE}" >&2
   exit 1
fi

cd /
while [ $# -gt 0 ]; do
  case "${1}" in
    --help | -h | --h* )
       echo "${USAGE}" >&2
       exit 0
       ;;
    --version | -V )
       echo "${VERSION}" >&2
       exit 0
       ;;
    *)
       if [ -z "${SERVICE}" -a $# -eq 1 -a "${1}" = "--status-all" ]; then
          cd ${SERVICEDIR}
          for SERVICE in * ; do
            case "${SERVICE}" in
              functions | halt | killall | single| linuxconf| kudzu)
                  ;;
              *)
                if ! is_ignored_file "${SERVICE}" \
            && [ -x "${SERVICEDIR}/${SERVICE}" ]; then
                  env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" status
                fi
                ;;
            esac
          done
          exit 0
       elif [ $# -eq 2 -a "${2}" = "--full-restart" ]; then
          SERVICE="${1}"
          if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
            env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" stop
            env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" start
            exit $?
          fi
       elif [ -z "${SERVICE}" ]; then
         SERVICE="${1}"
       else
         OPTIONS="${OPTIONS} ${1}"
       fi
       shift
       ;;
   esac
done

if [ -f "${SERVICEDIR}/${SERVICE}" ]; then
   env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}
else
   echo $"${SERVICE}: unrecognized service" >&2
   exit 1
fi

//CentOS8.3 位于/sbin/service 實際鏈接指向 /usr/sbin/service
#!/bin/bash

. /etc/init.d/functions

VERSION="$(basename $0) ver. 1.1"
USAGE="Usage: $(basename $0) < option > | --status-all | \
[ service_name [ command | --full-restart ] ]"
SERVICEDIR="/etc/init.d"
ACTIONDIR="/usr/libexec/initscripts/legacy-actions"
SERVICE=
ACTION=
OPTIONS=

if [ $# -eq 0 ]; then
   echo "${USAGE}" >&2
   exit 1
fi

cd /
while [ $# -gt 0 ]; do
  case "${1}" in
    --help | -h | --h* )
       echo "${USAGE}" >&2
       exit 0
       ;;
    --version | -V )
       echo "${VERSION}" >&2
       exit 0
       ;;
    --ignore-dependencies)
       export SYSTEMCTL_IGNORE_DEPENDENCIES=1
       shift
       ;;
    --skip-redirect)
       export SYSTEMCTL_SKIP_REDIRECT=1
       shift
       ;;
    *)
       if [ -z "${SERVICE}" -a $# -eq 1 -a "${1}" = "--status-all" ]; then
          cd ${SERVICEDIR}
          for SERVICE in * ; do
            case "${SERVICE}" in
              functions | halt | killall | single| linuxconf| kudzu)
                  ;;
              *)
                if ! is_ignored_file "${SERVICE}" \
            && [ -x "${SERVICEDIR}/${SERVICE}" ]; then
                  env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" status
                fi
                ;;
            esac
          done
          exit 0
       elif [ $# -eq 2 -a "${2}" = "--full-restart" ]; then
          SERVICE="${1}"
          if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
            env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" stop
            env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" start
            exit $?
          fi
       elif [ -z "${SERVICE}" ]; then
         SERVICE="${1}"
       elif [ -z "${ACTION}" ]; then
         ACTION="${1}"
       else
         OPTIONS="${OPTIONS} ${1}"
       fi
       shift
       ;;
   esac
done

if [ -f "${SERVICEDIR}/${SERVICE}" ]; then
   # LSB daemons that dies abnormally in systemd looks alive in systemd's eyes due to RemainAfterExit=yes
   # lets reap them before next start
   if [ "${ACTION}" = "start" ] && \
   systemctl show -p ActiveState ${SERVICE}.service | grep -q '=active$' && \
   systemctl show -p SubState ${SERVICE}.service | grep -q '=exited$' ; then
       /bin/systemctl stop ${SERVICE}.service
   fi
   # Workaround to be able to "stop" network.service when it's in inactive state using service instead of systemctl
   # Useful for manual testing of network
   if [ "${SERVICE}" = 'network' ] && [ "${ACTION}" = 'stop' ] && \
   [ "$(systemctl show -p ActiveState network.service --value)" = 'inactive' ] && \
   [ "$(systemctl show -p SourcePath network.service --value)" = '/etc/rc.d/init.d/network' ]; then
       export SYSTEMCTL_SKIP_REDIRECT=1
   fi
   env -i PATH="$PATH" TERM="$TERM" SYSTEMCTL_IGNORE_DEPENDENCIES=${SYSTEMCTL_IGNORE_DEPENDENCIES} SYSTEMCTL_SKIP_REDIRECT=${SYSTEMCTL_SKIP_REDIRECT} "${SERVICEDIR}/${SERVICE}" ${ACTION} ${OPTIONS}
elif [ -n "${ACTION}" ] && [ -x "${ACTIONDIR}/${SERVICE}/${ACTION}" ]; then
   env -i PATH="$PATH" TERM="$TERM" SYSTEMCTL_IGNORE_DEPENDENCIES=${SYSTEMCTL_IGNORE_DEPENDENCIES} SYSTEMCTL_SKIP_REDIRECT=${SYSTEMCTL_SKIP_REDIRECT} "${ACTIONDIR}/${SERVICE}/${ACTION}" ${OPTIONS}
elif `echo $ACTION | grep -Eqw "start|stop|restart|try-restart|reload|force-reload|status|condrestart"` ; then
   SERVICE_MANGLED=$(/usr/bin/systemd-escape --mangle ${SERVICE})
   echo $"Redirecting to /bin/systemctl ${ACTION}${OPTIONS:+ }${OPTIONS} ${SERVICE_MANGLED}" >&2
   exec /bin/systemctl ${ACTION} ${OPTIONS} ${SERVICE_MANGLED}
else
   echo $"The service command supports only basic LSB actions (start, stop, restart, try-restart, reload, force-reload, status). For other actions, please try to use systemctl." >&2
   exit 2
fi

//Ubuntu20.04 位于/usr/sbin/service
#!/bin/bash

###########################################################################
# /usr/bin/service
#
# A convenient wrapper for the /etc/init.d init scripts.
#
# This script is a modified version of the /sbin/service utility found on
# Red Hat/Fedora systems (licensed GPLv2+).
#
# Copyright (C) 2006 Red Hat, Inc. All rights reserved.
# Copyright (C) 2008 Canonical Ltd.
#   * August 2008 - Dustin Kirkland <kirkland@canonical.com>
# Copyright (C) 2013 Michael Stapelberg <stapelberg@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# On Debian GNU/Linux systems, the complete text of the GNU General
# Public License can be found in `/usr/share/common-licenses/GPL-2'.
###########################################################################


is_ignored_file() {
    case "$1" in
        skeleton | README | *.dpkg-dist | *.dpkg-old | rc | rcS | single | reboot | bootclean.sh)
            return 0
        ;;
    esac
    return 1
}

VERSION="`basename $0` ver. 1.57"
USAGE="Usage: `basename $0` < option > | --status-all | \
[ service_name [ command | --full-restart ] ]"
SERVICE=
ACTION=
SERVICEDIR="/etc/init.d"
OPTIONS=
is_systemd=


if [ $# -eq 0 ]; then
   echo "${USAGE}" >&2
   exit 1
fi

if [ -d /run/systemd/system ]; then
   is_systemd=1
fi

cd /
while [ $# -gt 0 ]; do
  case "${1}" in
    --help | -h | --h* )
       echo "${USAGE}" >&2
       exit 0
       ;;
    --version | -V )
       echo "${VERSION}" >&2
       exit 0
       ;;
    *)
       if [ -z "${SERVICE}" -a $# -eq 1 -a "${1}" = "--status-all" ]; then
          cd ${SERVICEDIR}
          for SERVICE in * ; do
            case "${SERVICE}" in
              functions | halt | killall | single| linuxconf| kudzu)
                  ;;
              *)
                if ! is_ignored_file "${SERVICE}" \
            && [ -x "${SERVICEDIR}/${SERVICE}" ]; then
                        out=$(env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" status 2>&1)
                        retval=$?
                        if echo "$out" | egrep -iq "usage:"; then
                          #printf " %s %-60s %s\n" "[?]" "$SERVICE:" "unknown" 1>&2
                          echo " [ ? ]  $SERVICE" 1>&2
                          continue
                        else
                          if [ "$retval" = "0" -a -n "$out" ]; then
                            #printf " %s %-60s %s\n" "[+]" "$SERVICE:" "running"
                            echo " [ + ]  $SERVICE"
                            continue
                          else
                            #printf " %s %-60s %s\n" "[-]" "$SERVICE:" "NOT running"
                            echo " [ - ]  $SERVICE"
                            continue
                          fi
                        fi
                  #env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" status
                fi
                ;;
            esac
          done
          exit 0
       elif [ $# -eq 2 -a "${2}" = "--full-restart" ]; then
          SERVICE="${1}"
          # On systems using systemd, we just perform a normal restart:
          # A restart with systemd is already a full restart.
          if [ -n "$is_systemd" ]; then
             ACTION="restart"
          else
             if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
               env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" stop
               env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" start
               exit $?
             fi
          fi
       elif [ -z "${SERVICE}" ]; then
         SERVICE="${1}"
       elif [ -z "${ACTION}" ]; then
         ACTION="${1}"
       else
         OPTIONS="${OPTIONS} ${1}"
       fi
       shift
       ;;
   esac
done

run_via_sysvinit() {
   # Otherwise, use the traditional sysvinit
   if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
      exec env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" ${ACTION} ${OPTIONS}
   else
      echo "${SERVICE}: unrecognized service" >&2
      exit 1
   fi
}

update_openrc_started_symlinks() {
   # maintain the symlinks of /run/openrc/started so that
   # rc-status works with the service command as well
   if [ -d /run/openrc/started ] ; then
      case "${ACTION}" in
      start)
         if [ ! -h /run/openrc/started/$SERVICE ] ; then
            ln -s $SERVICEDIR/$SERVICE /run/openrc/started/$SERVICE || true
         fi
      ;;
      stop)
         rm /run/openrc/started/$SERVICE || true
      ;;
      esac
   fi
}

# When this machine is running systemd, standard service calls are turned into
# systemctl calls.
if [ -n "$is_systemd" ]
then
   UNIT="${SERVICE%.sh}.service"
   # avoid deadlocks during bootup and shutdown from units/hooks
   # which call "invoke-rc.d service reload" and similar, since
   # the synchronous wait plus systemd's normal behaviour of
   # transactionally processing all dependencies first easily
   # causes dependency loops
   if ! systemctl --quiet is-active multi-user.target; then
       sctl_args="--job-mode=ignore-dependencies"
   fi

   case "${ACTION}" in
      restart|status|try-restart)
         exec systemctl $sctl_args ${ACTION} ${UNIT}
      ;;
      start|stop)
         # Follow the principle of least surprise for SysV people:
         # When running "service foo stop" and foo happens to be a service that
         # has one or more .socket files, we also stop the .socket units.
         # Users who need more control will use systemctl directly.
         for unit in $(systemctl list-unit-files --full --type=socket 2>/dev/null | sed -ne 's/\.socket\s*[a-z]*\s*$/.socket/p'); do
             if [ "$(systemctl -p Triggers show $unit)" = "Triggers=${UNIT}" ]; then
                systemctl $sctl_args ${ACTION} $unit
             fi
         done
         exec systemctl $sctl_args ${ACTION} ${UNIT}
      ;;
      reload)
         _canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
         if [ "$_canreload" = "CanReload=no" ]; then
            # The reload action falls back to the sysv init script just in case
            # the systemd service file does not (yet) support reload for a
            # specific service.
            run_via_sysvinit
         else
            exec systemctl $sctl_args reload "${UNIT}"
         fi
         ;;
      force-stop)
         exec systemctl --signal=KILL kill "${UNIT}"
         ;;
      force-reload)
         _canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
         if [ "$_canreload" = "CanReload=no" ]; then
            exec systemctl $sctl_args restart "${UNIT}"
         else
            exec systemctl $sctl_args reload "${UNIT}"
         fi
         ;;
      *)
         # We try to run non-standard actions by running
         # the init script directly.
         run_via_sysvinit
         ;;
   esac
fi

update_openrc_started_symlinks
run_via_sysvinit

可以看得出肿孵,無論是Red Hat系還是Debian系唠粥,service命令的前半部分的邏輯都是十分相似的优炬,不同的是后面部分,CentOS8.3在后面加上了 systemctl 命令的邏輯厅贪,這個命令在 CentOS6.5中是沒有的蠢护,而 Ubuntu的后面部分也是自己特色的實現(xiàn),不過這些這里暫且不表养涮,這里只淺析一下 service --status-all 這個參數(shù)在不同發(fā)行版中的不同表現(xiàn)

if [ -z "${SERVICE}" -a $# -eq 1 -a "${1}" = "--status-all" ]; then
          cd ${SERVICEDIR}
          for SERVICE in * ; do
            case "${SERVICE}" in
              functions | halt | killall | single| linuxconf| kudzu)
                  ;;
              *)
                if ! is_ignored_file "${SERVICE}" \
            && [ -x "${SERVICEDIR}/${SERVICE}" ]; then
                  env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" status
                fi
                ;;
            esac
          done
          exit 0
......

從這一段代碼可以看出葵硕,service加上--status-all參數(shù)后,就會將 /etc/init.d/ 目錄下的所有腳本帶上 status 參數(shù)循環(huán)執(zhí)行一遍然后再對輸出進行過濾格式化贯吓,但詭異的是懈凹,CentOS8.3 把 /etc/init.d/ 目錄下的所有應用啟動腳本全部刪除了,空空如也


沒有啟動腳本了

所以在 CentOS8.3 中悄谐,執(zhí)行 service --status-all 是沒有任何輸出的介评,不信大家可以試一下,這時如果想得知哪個服務是否安裝了爬舰,只能使用 ps -aux 查看進程或者使用 netstat -tnlp 查看某個端口了们陆,又或者使用包管理工具 rpm 來查看
CentOS6.5 和 Ubuntu20.04下這個命令是沒有問題的

root@localhost:~# service --status-all
 [ + ]  aegis
 [ + ]  apache2
 [ - ]  apache-htcacheclean
 [ + ]  apparmor
 [ + ]  atd
 [ + ]  chrony
 [ - ]  console-setup.sh
 [ + ]  cron
 [ + ]  dbus
 [ - ]  fio
 [ + ]  grub-common
 [ - ]  hwclock.sh
 [ - ]  irqbalance
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ - ]  nginx
 [ - ]  ntp
 [ - ]  plymouth
 [ - ]  plymouth-log
 [ + ]  procps
....
Ubuntu20.04

當系統(tǒng)引入 systemctl 命令之后,service本質上就是對 systemctl 進行了一次包裝情屹,實際都是執(zhí)行這個命令來調用.service配置文件(位于 /usr/lib/systemd/system )進行控制操作坪仇,這一點 Ubuntu20.04 和 CentOS8.3 很像,不像 CentOS6.5 垃你,腳本中是直接與應用二進制文件打交道椅文。
所以對服務的操控可以有兩種寫法(后者直接使用了 systemctl 命令調用 .service 配置文件)

  1. service apache2 start

2.systemctl start apache2.service

service的控制單元是一個個的 .service 配置文件,每個 .service 文件對應一個服務的控制操作惜颇,.service文件的書寫有一定的規(guī)范皆刺,下面是 Ubuntu20.04下 apache2.service 的配置內容( CentOS 中是 httpd.service )

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=https://httpd.apache.org/docs/2.4/

[Service]
Type=forking
Environment=APACHE_STARTED_BY_SYSTEMD=true
ExecStart=/usr/sbin/apachectl start
ExecStop=/usr/sbin/apachectl stop
ExecReload=/usr/sbin/apachectl graceful
PrivateTmp=true
Restart=on-abort

[Install]
WantedBy=multi-user.target

可以看出,service 配置文件才是真正與二進制文件進行關聯(lián)的

再來看看 /etc/init.d/apache2 腳本

再次說明凌摄,CentOS8.3 是沒有這個腳本的羡蛾,而 CentOS6.5 是直接與二進制文件進行交互,這里就以 Ubuntu20.04 進行說明
前面說過望伦,service --status-all 實際上是將這個目錄下的腳本全部循環(huán)加上 status 參數(shù)執(zhí)行一遍林说,也就是說
/etc/init.d/apache2 status 這條命令是會被執(zhí)行的

root@localhost:~# /etc/init.d/apache2 status
● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2021-06-28 13:49:56 CST; 20h ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 6856 ExecReload=/usr/sbin/apachectl graceful (code=exited, status=0/SUCCESS)
   Main PID: 2003 (apache2)
      Tasks: 55 (limit: 2193)
     Memory: 8.4M
     CGroup: /system.slice/apache2.service
             ├─2003 /usr/sbin/apache2 -k start
             ├─6860 /usr/sbin/apache2 -k start
             └─6861 /usr/sbin/apache2 -k start

Jun 28 13:49:56 localhost systemd[1]: Starting The Apache HTTP Server...
Jun 28 13:49:56 localhost apachectl[2002]: AH00558: apache2: Could not reliably determine t…ssage
Jun 28 13:49:56 localhost systemd[1]: Started The Apache HTTP Server.
Jun 29 00:01:00 localhost systemd[1]: Reloading The Apache HTTP Server.
Jun 29 00:01:00 localhost apachectl[6859]: AH00558: apache2: Could not reliably determine t…ssage
Jun 29 00:01:00 localhost systemd[1]: Reloaded The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.

以上是直接執(zhí)行 /etc/init.d/apache2 status 的輸出結果,但為何執(zhí)行 service --status-all 又變成了列表形式的呢屯伞,那時因為對輸出結果進行了一系列變換格式化操作,現(xiàn)在我們看下為何 /etc/init.d/apache2 status 的輸出結果是這樣豪直,本質上是哪部分代碼被執(zhí)行了
用文本編輯器打開 /etc/init.d/apache2 腳本劣摇,大概在 53 行處

. /lib/lsb/init-functions  //實際上指向 /usr/lib/lsb/init-functions

輸出的功能性代碼就在這個引入腳本里,再打開這個腳本弓乙,在末尾處

for hook in $(run-parts --lsbsysinit --list /lib/lsb/init-functions.d 2>/dev/null); do
    [ -r $hook ] && . $hook || true
done

又是循環(huán)執(zhí)行了腳本末融,再次打開 /lib/lsb/init-functions.d (實際指向是 /usr/lib/lsb/init-functions.d )


init-functions.d

這里面的腳本都會執(zhí)行一遍钧惧,重點就是那個 systemd ,用文本編輯器打開勾习,最后幾行代碼

    case "$argument" in
        start|stop|restart|reload|force-reload|try-restart|status)
            systemctl_redirect $executable $argument
            exit $?
            ;;
    esac

systemctl_redirect 這個函數(shù)的實現(xiàn)在 systemd 文本的前半部分

systemctl_redirect () {
    local s
    local rc
    local prog=${1##*/}
    local command=$2

    case "$command" in
        start)
            s="Starting $prog (via systemctl)"
            ;;
        stop)
            s="Stopping $prog (via systemctl)"
            ;;
        reload|force-reload)
            s="Reloading $prog configuration (via systemctl)"
            ;;
        try-restart)
            s="Restarting $prog if running (via systemctl)"
            ;;
        restart)
            s="Restarting $prog (via systemctl)"
            ;;
    esac

    service="${prog%.sh}.service"

    # avoid deadlocks during bootup and shutdown from units/hooks
    # which call "invoke-rc.d service reload" and similar, since
    # the synchronous wait plus systemd's normal behaviour of
    # transactionally processing all dependencies first easily
    # causes dependency loops
    if ! OUT=$(systemctl is-system-running 2>/dev/null) && [ "$OUT" != "degraded" ]; then
        sctl_args="--job-mode=ignore-dependencies"
    fi

    [ "$command" = status ] || log_daemon_msg "$s" "$service"
    /bin/systemctl --no-pager $sctl_args $command "$service" //這行才是重點
    rc=$?
    [ "$command" = status ] || log_end_msg $rc

    return $rc
}

/bin/systemctl --no-pager $sctl_args $command "$service"這一行才是重點浓瞪,大概在全文的 82 行左右
如果把里面的變量替換展開,最后執(zhí)行的命令行大概就是這樣
/bin/systemctl --no-pager status apache2.service
直接運行這條命令巧婶,可以得到和 /etc/init.d/apache2 status 一樣的輸出

結論

沒想到 service --staus-all 最后還是依賴于 systemctl 這個命令乾颁,不過 /etc/init.d 里面大量的腳本只是為了使 service --staus-all 這條命令有效,是不是有點浪費艺栈,如果像 CentOS8.3 那樣直接刪掉英岭,是不是更顯得簡潔,你覺得呢湿右?

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末诅妹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子毅人,更是在濱河造成了極大的恐慌吭狡,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丈莺,死亡現(xiàn)場離奇詭異赵刑,居然都是意外死亡,警方通過查閱死者的電腦和手機场刑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進店門般此,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人牵现,你說我怎么就攤上這事铐懊。” “怎么了瞎疼?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵科乎,是天一觀的道長。 經常有香客問我贼急,道長茅茂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任太抓,我火速辦了婚禮空闲,結果婚禮上,老公的妹妹穿的比我還像新娘走敌。我一直安慰自己碴倾,他們只是感情好,可當我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著跌榔,像睡著了一般异雁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上僧须,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天纲刀,我揣著相機與錄音,去河邊找鬼担平。 笑死示绊,一個胖子當著我的面吹牛,可吹牛的內容都是我干的驱闷。 我是一名探鬼主播耻台,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼空另!你這毒婦竟也來了盆耽?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扼菠,失蹤者是張志新(化名)和其女友劉穎摄杂,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體循榆,經...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡析恢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了秧饮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片映挂。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖盗尸,靈堂內的尸體忽然破棺而出柑船,到底是詐尸還是另有隱情,我是刑警寧澤泼各,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布鞍时,位于F島的核電站,受9級特大地震影響扣蜻,放射性物質發(fā)生泄漏逆巍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一莽使、第九天 我趴在偏房一處隱蔽的房頂上張望锐极。 院中可真熱鬧,春花似錦吮旅、人聲如沸溪烤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽檬嘀。三九已至,卻和暖如春责嚷,著一層夾襖步出監(jiān)牢的瞬間鸳兽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工罕拂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留揍异,地道東北人。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓爆班,卻偏偏與公主長得像衷掷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子柿菩,可洞房花燭夜當晚...
    茶點故事閱讀 45,442評論 2 359

推薦閱讀更多精彩內容