基于Ubuntu 18.04

二、问题描述

      在使用较新版本的Ubuntu系统中,之前写入rc.local的开机执行命令不执行了。经探究发现,Ubuntu自18.04版本后改用systemd管理系统,不再用initd管理系统,默认也没有/etc/rc.local文件。

三、问题分析

      先用systemctl status rc-local查看状态

rc.local中的命令不能执行_Linux系统

      设置rc-local开机自启,输出如下错误信息:

rc.local中的命令不能执行_Linux系统_02

      大概意思是rc-local服务文件没有install字段的相关信息,这些相关信息包括WantedBy, RequiredBy, Also, Alias。如果不写则系统不认为它是一个systemd服务。

      打开文件/lib/systemd/system/rc-local.service(如无此文件则新建),做如下配置:


[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

[Install]
WantedBy=multi-user.target
# 指的是表示该服务所属 target
Alias=rc-local.service1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.


      其中Unit字段描述服务的启动顺序&依赖关系,Service字段描述如何启动,Install字段描述如何安装该服务。具体参数说明如下:

1.[Unit]

Description描述

After:在network.target启动后才启动,即网络启动完成后执行/etc/rc.local文件

ConditionFileIsExecutable:指定执行文件


2.[Service]

Type设置进程的启动类型。可以有如下设置:

  • simple:默认值,执行ExecStart指定的命令,启动主进程

  • forking:以fork方式从父进程创建子进程,创建后父进程会立即退出

  • oneshot:一次性进程,Systemd会等当前服务退出,再继续往下执行

  • dbus:当前服务通过D-Bus启动

  • notify:当前服务启动完毕,会通知Systemd,再继续往下执行

  • idle:若有其他任务执行完毕,当前服务才会运行

EnvironmentFile变量所在文件

ExecStart: 指定服务启动的命令,在每个配置文件中只能使用一次。需要使用绝对路径

Restart 指定什么情况下重启服务。可以有如下设置:

  • no(默认值):退出后不会重启

  • always:除了用systemctl stop 或等价的服务停止操作命令,其他情况都可以重启

  • on-success:只有正常退出时(退出状态码为0),才会重启

  • on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启(守护进程,推荐值)

  • on-abnormal:只有被信号终止和超时,才会重启(对于允许发生错误退出的服务,推荐值)

  • on-abort:只有在收到没有捕捉到的信号终止时,才会重启

  • on-watchdog:超时退出,才会重启

ExecStop: 停止服务所需要执行的命令。需要使用绝对路径

ExecReload:重新加载服务文件所需执行的命令。需要使用绝对路径

TimeoutSec:定义Systemd停止当前服务之前等待的秒数

RemainAfterExit:该字段如设为yes,表示进程退出以后,服务仍然保持执行。

GuessMainPID:一个布尔值,指定systemd在无法可靠确定服务的主PID时是否应该猜测它。除非设置了Type=forking且未设置PIDFile,否则此选项将被忽略,默认为yes


3.[Install]

Alias服务别名

WangtedBy: 表示该服务所在的Target,它的值是一个或多个Target,使用systemctl enable时unit符号链接会放入/etc/systemd/system目录下面以Target名 + .wants后缀构成的子目录中

Target的含义是服务组,表示一组服务。

WantedBy=multi-user.target指Unit所在的Target是multi-user.target(多用户模式)

这个设置非常重要,因为执行systemctl enable是会将Unit链接到/etc/systemd/system/multi-user.target.wants目录之中,实现开机启动的功能

      具体的配置清单可以看 官方文档


      给rc.local添加可执行权限,之后启动并查看状态:

rc.local中的命令不能执行_Linux系统_03

      这样rc.local中的命令就能正常执行了。