upstart、SysVinit、Systemd //TODO

了解Linux系统的发展历程,能够更好的了解系统,掌握系统。

systemvinit -- > upstart -- > systemd

UPSTART(https://www.cnblogs.com/plxx/p/5493073.html  这个link也不错)

upstart 启动过程

前言

众所周知,/sbin/init 是linux内核启动后运行的首个用户进程,早期的init程序由sysvinit包提供。 SysVinit软件包包含了一组控制系统最基本函数的进程,它包含了系统初始化程序init,init 是系统启动时被kernel最先启动的进程,它控制着其它所有进程的启动、运行以及停止。Sysvinit 中的init daemon 是一个基于运行级别的初始化程序,它使用了运行级别(如单用户、多用户等)并通过从 /etc/rc?.d 目录到 /etc/init.d 目录的初始化脚本的链接来启动与终止系统服务。例如大家熟悉的级别3进入text模式,级别5为graphis模式;以及/etc/rc?.d 目录下数字代表启动的优先级,K代表停止某个服务,S代表启动服务等。

Ubuntu 从6.10版本开始使用 upstart来代替sysvinit, upstart包提供了新的init daemon。Upstart init daemon 本质上不是基于运行级别的启动init进程,但为了跟传统的sysvinit兼容,upstart提供了兼容的runlevel和telinit等工具,以及也使用/etc/rc?.d 作为启动或者停止某个服务。但运行级别3不在是text模式,而且也不能通过改变运行级别来改变进入text模式。

Upstart 初探

Upstart 跟Sysvinit 本质上一样,都是用于linux开机自动启动某些后台服务,同时还承担监控这些服务运行状态的功能。但Sysvinit中的init daemon 不能解决诸如系统接收到打印机等热插拔事件安装时来启动某种特定的服务这类问题,而upstart则可以。

ustart init daemon 是基于事件的,当系统中的什么情况发生变化时,它会运行某个特定的程序。这里被运行的程序多半是用来启动或终止服务的脚本。这个配置方式和systemv 在系统进入某个运行级别的时候运行init脚本的链接的概念实际上是非常类似的,只不过 upstart 更加灵活一些。Upstart 不仅能在运行级别改变的时候启动或终止服务,也能在接收到系统发生其他改变的信息的时候启动或终止服务。这些系统的改变被称为“事件”。例如,当 upstart 从 udev 接收到运行时文件系统加载、打印机安装或其他类似的设备添加或删除的信息,并采取相应的行动。Upstart 也可以在系统启动、关闭或某个任务状态改变的时候启动或关闭服务。

在upstart中存在如下几个概念:

Process: process 是由jobs定义的services或者task,它将被init daemon 运行。 每个job可以定义一个或者多个不同的process,分别在其生命周期的不同状态运行。Process 定义如下:

Exec COMMAND 

Scritp … end script 

Pre-start exec|script 

Post-start exec|script

Pre-stop exec|script 

Post-stop exec|script

Event: 事件,事件(event)是 init 可以得到的状态变更信息。几乎系统所有的内部或外部状态变更都可以触发一个事件。比如,引导程序会触发启动(startup)事件,系统进入运行级别2会 触发运行级别2(runlevel 2)事件,而文件系统加载则会触发路径加载(path-mounted)事件,拔掉或安装一个热插拔或USB设备(如打印机)也会触发一个时间。用户还可 以通过 initctl emit 命令来手动触发一个事件。事件定义格式如下:

start  on Event [[KEY=] Value … and| or …] 

stop  on Event [[KEY=] Value … and| or …]

Job: 一个工作(job)是 init 可以理解的一系列指令。典型的指令包括一个程序(二进制文件或是脚本)和事件的名称。Upstart init daemon 会在事件触发的时候运行相应的程序。用户可以分别用 initctl start 和 stop 命令手动启动或终止一项工作。工作又可以分为任务和服务。

My  job 示例

用户也可以自己定义一个事件,并让一个工作被这个事件触发。如下的 myjob 工作定义文件定义了一个被 hithere 事件触发的工作:

$cat /etc/event.d/myjob

start on hithere script          

echo “Hi there, here I am!” > /tmp/myjob.out          

date >> /tmp/myjob.out

end script

myjob 文件提供了另一种运行命令的方法:在 script 和 end script 关键字之间包含了两行命令。这两个关键字常常导致 init 去运行 /bin/sh。例中的命令将一条消息和日期输出到了 /tmp/myjob.out 文件。现在可以使用 initctl emit 命令触发这个工作。如下,init 展示了 myjobs 在我们的触发下所经历的各个状态:

$sudo initctl emit hithere

$cat /tmp/myjob.out 

Hi there, here I am!

Sun Apr 24 13:25:43 CST 2011

$sudo initctl list  | grep myjob 

myjob (stop) waiting

在上面的例子里,cat 展示了 myjob 产生的输出,initctl 展示了工作的状态。同样也可以用 initctl start myjob(或直接用 start myjob)来运行它。initctl start 十个非常有用的命令,这样你就可以在没有事件的情况下启动一个工作。比如,你可以用 initctl start mudat 来直接运行前面例子中的 mudat 工作而不会触发 runlevel 2 事件。

Upstart 事件监控实现

在init daemon 中需要监测某个进程的状态,例如存在repasw机制,监测getty进程是否退出,如果退出则需要再次启动getty以便用户登录。 为实现对事件的监测,要么采用轮询要么采用事件驱动的回调机制,upstart采用事件驱动机制。为实现基于事件驱动的机制,通常涉及跨进程调用,Upstart利用dbus来完成iPC通信。但upstart init daemon启动时dbus-daemon并没有运行,实际dbus-daemon是由upstart来启动。因此,upstart 采用  private D-bus 连接(unxi:address=/com/ubuntu/upstart)来实现IPC;其它进程(如telinit等)通过该连接来通知init daemon 产生某个事件。

Upstart init daemon 运行时会产生startup事件,在/etc/init下很多job都start on 该事件,其中比较著名的是:

rc-default job . 该job会调用telinit N来登录N用户级别,同时产生runevel事件。而runevel事件触发ttyN job,从而调用getty程序。对于图形界面的登录程序如gdm的触发为另外的条件,后面再续。

为完成监控内核事件,例如usb的热插拔,upstart提供upstart-udev-bridge.conf job来完成该功能,即在/etc/init 下存在upstart-udev-bridge.conf 文件。当udev event发生时,该job将产生 upstart事件通知init。这类事件通常采用如下格式:

“-device-

因此upstart-udev-bridge.conf 可能为:

net-device-added net-device-removed graphics-device-added drm-device-added

用户自动登录和定制XWindows

在工作中,常常存在如下需求:

开机运行linux,自动登录,无需输入用户名密码;

登录后自动运行我们的GUI软件,且无需ubuntu等桌面环境

在使用upstart的ubuntu系统中,控制登录的脚本主要是:

/etc/init/ttyN.conf

/etc/init/gdm.conf

Gdm.conf用户启动gdm,即ubuntu的图形桌面;由于我们并不需要桌面,因此首先删除gdm.conf. 删除gdm.conf将不能启动linux GUI桌面,但由于我们开机运行的GUI软件本质还是一个X11 Client程序,因此需要启动X Server。这时可以startx 脚本就派生用场了,在传统的用户text模式下,大都通过startx进入GUI系统。因此我们可以配置.xinitrc 脚本: 例如如下:

// user gui programmer

Metacity

为保证用户登录后即运行startx,可以在~/.bash_profile 中写入:

exec startx

上述过程保证了用户登录后即运行startx 启动了用户程序,但如何实现用户自动登录呢? 这需要修改/etc/init/ttyN.conf ,默认使用getty程序登录,该程序不支持用户自动登录。Linux下有一个叫minigetty 程序支持该功能,下载并修改/etc/init/ttyN.conf 文件,大致如下:

Exec /sbin/mingetty –autologin root tty1

其它init 实现

Systemd是一个比upstart设计思路更超前的init系统,见http://0pointer.de/blog/projects/systemd.html。   其核心是为了加快linux的启动速度,研究如何并行化启动init以后的用户进程,可以参考http://linuxtoy.org/archives/more-than-upstart-systemd.html

//SysVinit(https://blog.csdn.net/weixin_34040079/article/details/92395376 这个link也不错)

刚开始网上查/etc/rc.local能实现开机自动运行脚本..但是不知道为啥..

后来偶然在rc?.d/README发现了玄机...再后来一直顺着README的方向看下去...终于明白了

Ubuntu 的 运行级别

0 系统停机

1 单用户或系统维护状态

2~5 多用户

6 重新启动

我们通常运行的2~5级别

/etc/rc2.d/README 摘要

The scripts in this directory are executed each time the system enters

this runlevel.

The scripts are all symbolic links whose targets are located in

/etc/init.d/ .

To disable a service in this runlevel, rename its script in this

directory so that the new name begins with a 'K' and a two-digit

number, and run 'update-rc.d script defaults' to reorder the scripts

according to dependencies.  A warning about the current runlevels

being enabled not matching the LSB header in the init.d script will be

printed.  To re-enable the service, rename the script back to its

original name beginning with 'S' and run update-rc.d again.

For a more information see /etc/init.d/README.

这个目录的脚本在系统进入这个运行级别的时候就被启动.

这些脚本全是目标位于/etc/init.d/的符号链接

S??XXX, S代表启动,K代表停止,??数字代表顺序

root@ubuntu:/etc/rc2.d# ll

total 20

drwxr-xr-x  2 root root  4096  7月 27 10:21 ./

drwxr-xr-x 131 root root 12288  7月 27 10:04 ../

-rw-r--r--  1 root root  677  6月  4  2013 README

lrwxrwxrwx  1 root root    20  7月 25 22:19 S20kerneloops -> ../init.d/kerneloops*

lrwxrwxrwx  1 root root    27  7月 25 22:19 S20speech-dispatcher -> ../init.d/speech-dispatcher*

lrwxrwxrwx  1 root root    15  7月 25 22:19 S50rsync -> ../init.d/rsync*

lrwxrwxrwx  1 root root    15  7月 25 22:19 S50saned -> ../init.d/saned*

lrwxrwxrwx  1 root root    19  7月 25 22:19 S70dns-clean -> ../init.d/dns-clean*

lrwxrwxrwx  1 root root    18  7月 25 22:19 S70pppd-dns -> ../init.d/pppd-dns*

lrwxrwxrwx  1 root root    14  7月 25 22:19 S75sudo -> ../init.d/sudo*

lrwxrwxrwx  1 root root    21  7月 25 22:19 S99grub-common -> ../init.d/grub-common*

lrwxrwxrwx  1 root root    18  7月 25 22:19 S99ondemand -> ../init.d/ondemand*

lrwxrwxrwx  1 root root    18  7月 25 22:19 S99rc.local -> ../init.d/rc.local*

可以看出S99rc.local 会启动 /etc/init.d/rc.local 且是最后执行的

来到/etc/init.d,查看README

Configuration of System V init under Debian GNU/Linux

Most Unix versions have a file here that describes how the scripts

in this directory work, and how the links in the /etc/rc?.d/ directories

influence system startup/shutdown.

For Debian, this information is contained in the policy manual, chapter

"System run levels and init.d scripts".  The Debian Policy Manual is

available at:

    http://www.debian.org/doc/debian-policy/#contents

The Debian Policy Manual is also available in the Debian package

"debian-policy".  When this package is installed, the policy manual can be

found in directory /usr/share/doc/debian-policy. If you have a browser

installed you can probably read it at

    file://localhost/usr/share/doc/debian-policy/

Some more detailed information can also be found in the files in the

/usr/share/doc/sysv-rc directory.

Debian Policy dictates that /etc/init.d/*.sh scripts must work properly

大多数的Unix版本在这里的文件描述了这个文件夹的脚本怎样工作 --- (额,这句貌似在说README,废话么)

 ...xxx.xxx..xxx一堆跟前面的README重复的话

直接来到它说的网站,来到http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit

粘一下(字很小,建议查看源网站):

9.3 System run levels and init.d scripts

9.3.1 Introduction

The /etc/init.d directory contains the scripts executed by init at boot time and when the init state (or "runlevel") is changed (see init(8)).

There are at least two different, yet functionally equivalent, ways of handling these scripts. For the sake of simplicity, this document describes only the symbolic link method. However, it must not be assumed by maintainer scripts that this method is being used, and any automated manipulation of the various runlevel behaviors by maintainer scripts must be performed using update-rc.d as described below and not by manually installing or removing symlinks. For information on the implementation details of the other method, implemented in the file-rc package, please refer to the documentation of that package.

These scripts are referenced by symbolic links in the /etc/rcn.d directories. When changing runlevels, init looks in the directory /etc/rcn.d for the scripts it should execute, where n is the runlevel that is being changed to, or S for the boot-up scripts.

The names of the links all have the form Smmscript or Kmmscript where mm is a two-digit number and script is the name of the script (this should be the same as the name of the actual script in /etc/init.d).

When init changes runlevel first the targets of the links whose names start with a K are executed, each with the single argument stop, followed by the scripts prefixed with an S, each with the single argument start. (The links are those in the /etc/rcn.d directory corresponding to the new runlevel.) The K links are responsible for killing services and the S link for starting services upon entering the runlevel.

For example, if we are changing from runlevel 2 to runlevel 3, init will first execute all of the K prefixed scripts it finds in /etc/rc3.d, and then all of the S prefixed scripts in that directory. The links starting with K will cause the referred-to file to be executed with an argument of stop, and the S links with an argument of start.

The two-digit number mm is used to determine the order in which to run the scripts: low-numbered links have their scripts run first. For example, the K20 scripts will be executed before the K30 scripts. This is used when a certain service must be started before another. For example, the name server bind might need to be started before the news server inn so that inn can set up its access lists. In this case, the script that starts bind would have a lower number than the script that starts inn so that it runs first:

    /etc/rc2.d/S17bind

    /etc/rc2.d/S70inn

The two runlevels 0 (halt) and 6 (reboot) are slightly different. In these runlevels, the links with an S prefix are still called after those with a K prefix, but they too are called with the single argument stop.

9.3.2 Writing the scripts

Packages that include daemons for system services should place scripts in /etc/init.d to start or stop services at boot time or during a change of runlevel. These scripts should be named /etc/init.d/package, and they should accept one argument, saying what to do:

start

start the service,

stop

stop the service,

restart

stop and restart the service if it's already running, otherwise start the service

reload

cause the configuration of the service to be reloaded without actually stopping and restarting the service,

force-reload

cause the configuration to be reloaded if the service supports this, otherwise restart the service.

The start, stop, restart, and force-reload options should be supported by all scripts in /etc/init.d, the reload option is optional.

The init.d scripts must ensure that they will behave sensibly (i.e., returning success and not starting multiple copies of a service) if invoked with start when the service is already running, or with stop when it isn't, and that they don't kill unfortunately-named user processes. The best way to achieve this is usually to use start-stop-daemon with the --oknodo option.

Be careful of using set -e in init.d scripts. Writing correct init.d scripts requires accepting various error exit statuses when daemons are already running or already stopped without aborting the init.d script, and common init.d function libraries are not safe to call with set -e in effect[81]. For init.d scripts, it's often easier to not use set -e and instead check the result of each command separately.

If a service reloads its configuration automatically (as in the case of cron, for example), the reload option of the init.d script should behave as if the configuration has been reloaded successfully.

The /etc/init.d scripts must be treated as configuration files, either (if they are present in the package, that is, in the .deb file) by marking them as conffiles, or, (if they do not exist in the .deb) by managing them correctly in the maintainer scripts (see Configuration files, Section 10.7). This is important since we want to give the local system administrator the chance to adapt the scripts to the local system, e.g., to disable a service without de-installing the package, or to specify some special command line options when starting a service, while making sure their changes aren't lost during the next package upgrade.

These scripts should not fail obscurely when the configuration files remain but the package has been removed, as configuration files remain on the system after the package has been removed. Only when dpkg is executed with the --purge option will configuration files be removed. In particular, as the /etc/init.d/package script itself is usually a conffile, it will remain on the system if the package is removed but not purged. Therefore, you should include a test statement at the top of the script, like this:

    test -f program-executed-later-in-script || exit 0

Often there are some variables in the init.d scripts whose values control the behavior of the scripts, and which a system administrator is likely to want to change. As the scripts themselves are frequently conffiles, modifying them requires that the administrator merge in their changes each time the package is upgraded and the conffile changes. To ease the burden on the system administrator, such configurable values should not be placed directly in the script. Instead, they should be placed in a file in /etc/default, which typically will have the same base name as the init.d script. This extra file should be sourced by the script when the script runs. It must contain only variable settings and comments in SUSv3 sh format. It may either be a conffile or a configuration file maintained by the package maintainer scripts. See Configuration files, Section 10.7 for more details.

To ensure that vital configurable values are always available, the init.d script should set default values for each of the shell variables it uses, either before sourcing the /etc/default/ file or afterwards using something like the : ${VAR:=default} syntax. Also, the init.d script must behave sensibly and not fail if the /etc/default file is deleted.

Files and directories under /run, including ones referred to via the compatibility paths /var/run and /var/lock, are normally stored on a temporary filesystem and are normally not persistent across a reboot. The init.d scripts must handle this correctly. This will typically mean creating any required subdirectories dynamically when the init.d script is run. See /run and /run/lock, Section 9.1.4 for more information.

9.3.3 Interfacing with the initscript system

Maintainers should use the abstraction layer provided by the update-rc.d and invoke-rc.d programs to deal with initscripts in their packages' scripts such as postinst, prerm and postrm.

Directly managing the /etc/rc?.d links and directly invoking the /etc/init.d/ initscripts should be done only by packages providing the initscript subsystem (such as sysv-rc and file-rc).

9.3.3.1 Managing the links

The program update-rc.d is provided for package maintainers to arrange for the proper creation and removal of /etc/rcn.d symbolic links, or their functional equivalent if another method is being used. This may be used by maintainers in their packages' postinst and postrm scripts.

You must not include any /etc/rcn.d symbolic links in the actual archive or manually create or remove the symbolic links in maintainer scripts; you must use the update-rc.d program instead. (The former will fail if an alternative method of maintaining runlevel information is being used.) You must not include the /etc/rcn.d directories themselves in the archive either. (Only the sysvinit package may do so.)

By default update-rc.d will start services in each of the multi-user state runlevels (2, 3, 4, and 5) and stop them in the halt runlevel (0), the single-user runlevel (1) and the reboot runlevel (6). The system administrator will have the opportunity to customize runlevels by simply adding, moving, or removing the symbolic links in /etc/rcn.d if symbolic links are being used, or by modifying /etc/runlevel.conf if the file-rc method is being used.

To get the default behavior for your package, put in your postinst script

    update-rc.d package defaults

and in your postrm

    if [ "$1" = purge ]; then

    update-rc.d package remove

    fi

. Note that if your package changes runlevels or priority, you may have to remove and recreate the links, since otherwise the old links may persist. Refer to the documentation of update-rc.d.

This will use a default sequence number of 20. If it does not matter when or in which order the init.d script is run, use this default. If it does, then you should talk to the maintainer of the sysvinit package or post to debian-devel, and they will help you choose a number.

For more information about using update-rc.d, please consult its man page update-rc.d(8).

9.3.3.2 Running initscripts

The program invoke-rc.d is provided to make it easier for package maintainers to properly invoke an initscript, obeying runlevel and other locally-defined constraints that might limit a package's right to start, stop and otherwise manage services. This program may be used by maintainers in their packages' scripts.

The package maintainer scripts must use invoke-rc.d to invoke the /etc/init.d/* initscripts, instead of calling them directly.

By default, invoke-rc.d will pass any action requests (start, stop, reload, restart...) to the /etc/init.d script, filtering out requests to start or restart a service out of its intended runlevels.

Most packages will simply need to change:

    /etc/init.d/<package>

          <action>

in their postinst and prerm scripts to:

    if which invoke-rc.d >/dev/null 2>&1; then

    invoke-rc.d package <action>

    else

    /etc/init.d/package <action>

    fi

A package should register its initscript services using update-rc.d before it tries to invoke them using invoke-rc.d. Invocation of unregistered services may fail.

For more information about using invoke-rc.d, please consult its man page invoke-rc.d(8).

9.3.4 Boot-time initialization

There used to be another directory, /etc/rc.boot, which contained scripts which were run once per machine boot. This has been deprecated in favour of links from /etc/rcS.d to files in /etc/init.d as described in Introduction, Section 9.3.1. Packages must not place files in /etc/rc.boot.

9.3.5 Example

An example on which you can base your /etc/init.d scripts is found in /etc/init.d/skeleton.

翻译如下:

介绍

/etc/init.d目录包含着当运行级别改变时在boot时启动的脚本(不是重点)

有两点不同...一堆废话夹中间...出于易读考虑,这篇文档只描述符号链接方法.xxx xxx...

不同运行级别的自动化操作必须用update-rc.d来安装或者删除符号链接.

然后...K代表停止,S代表执行,数字代表顺序(前面已说过)

写脚本

包含系统服务daemon(后台程序)的packages(包)应该把脚本放在/etc/init.d来开启和停止服务at boot time 或者 during  a change of runlevel,

这些脚本应该被命名为/etc/init.d/package,他们应该接受这些参数

start

start the service,

stop

stop the service,

restart

stop and restart the service if it's already running, otherwise start the service

reload

cause the configuration of the service to be reloaded without actually stopping and restarting the service,

force-reload

cause the configuration to be reloaded if the service supports this, otherwise restart the service.

在init.d里面的脚本都应该支持这些参数.

管理链接(重要)

By default update-rc.d will start services in each of the multi-user state runlevels (2, 3, 4, and 5) and stop them in the halt runlevel (0), the single-user runlevel (1) and the reboot runlevel (6).

默认update-rc.d会在多人运行级别(2,3,4,5)和在停止级别(halt level(0)),单人级别(1)开启服务命令!:

update-rc.d package defaults 添加链接

and in your postrm 在你的发出的移除命令中

if [ "$1" = purge ]; then

    update-rc.d package remove

    fi

可以看出 update-rc.d package remove是移除链接 参数-f代表强制(如果init.d没有该脚本)

init.d脚本例子:

An example on which you can base your /etc/init.d scripts is found in /etc/init.d/skeleton.

----------------另外我知道的比如/etc/init.d/mysqld start 可以写为 service mysqld start

============================================rc.local实现开机启动脚本原理================================================

root@ubuntu:/etc/rc2.d# ll

total 20

drwxr-xr-x  2 root root  4096  7月 27 10:21 ./

drwxr-xr-x 131 root root 12288  7月 27 10:04 ../

-rw-r--r--  1 root root  677  6月  4  2013 README

lrwxrwxrwx  1 root root    20  7月 25 22:19 S20kerneloops -> ../init.d/kerneloops*

lrwxrwxrwx  1 root root    27  7月 25 22:19 S20speech-dispatcher -> ../init.d/speech-dispatcher*

lrwxrwxrwx  1 root root    15  7月 25 22:19 S50rsync -> ../init.d/rsync*

lrwxrwxrwx  1 root root    15  7月 25 22:19 S50saned -> ../init.d/saned*

lrwxrwxrwx  1 root root    19  7月 25 22:19 S70dns-clean -> ../init.d/dns-clean*

lrwxrwxrwx  1 root root    18  7月 25 22:19 S70pppd-dns -> ../init.d/pppd-dns*

lrwxrwxrwx  1 root root    14  7月 25 22:19 S75sudo -> ../init.d/sudo*

lrwxrwxrwx  1 root root    21  7月 25 22:19 S99grub-common -> ../init.d/grub-common*

lrwxrwxrwx  1 root root    18  7月 25 22:19 S99ondemand -> ../init.d/ondemand*

lrwxrwxrwx  1 root root    18  7月 25 22:19 S99rc.local -> ../init.d/rc.local*

有了上部分的理论基础,从上面S99rc.local可看出,系统会在开机时启动/etc/init.d/rc.local看看/etc/init.d/rc.local有什么东西

#! /bin/sh

### BEGIN INIT INFO

# Provides:          rc.local

# Required-Start:    $all

# Required-Stop:

# Default-Start:    2 3 4 5

# Default-Stop:

# Short-Description: Run /etc/rc.local if it exist

### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh

. /lib/lsb/init-functions

do_start() {

        if [ -x /etc/rc.local ]; then

                [ "$VERBOSE" != no ] && log_begin_msg "Running local boot scripts (/etc/rc.local)"

                /etc/rc.local

                ES=$?

                [ "$VERBOSE" != no ] && log_end_msg $ES

                return $ES

        fi

case "$1" in

    start)

        do_start

        ;;

    restart|reload|force-reload)

        echo "Error: argument '$1' not supported" >&2

        exit 3

        ;;

    stop)

        ;;

    *)

        echo "Usage: $0 start|stop" >&2

        exit 3

        ;;

esac

可以看出,/etc/init.d/rc.local会执行/etc/rc.local这个脚本里面的内容,也难怪在/etc/rc.local添加脚本会顺利的执行

————————————————

版权声明:本文为CSDN博主「me10zyl」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/me10zyl/article/details/38168003

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容