Ubuntu 18.04.4 LTS 开机运行自定义脚本

采用传统的rc.local方式实现开机脚本自动运行,但在Ubuntu 18.04安装后,默认不存在rc.local脚本,故需要进行恢复。

步骤一:添加rc-local.service服务脚本

Ubuntu中也支持使用systemd对服务进行管理,所以我们通过定义一个新的服务脚本,并设置此脚本开机运行,再在此脚本中调用rc.local即可。

创建/etc/systemd/system/rc-local.service服务脚本
运行下述命令,生成服务脚本
cat > /etc/systemd/system/rc-local.service << EOF
[Unit]
Description=/etc/rc.local Compatibility
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
Alias=rc-local.service
EOF
步骤二:创建rc.local脚本
cat > /etc/rc.local << EOF
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
exit 0
EOF
步骤三:赋予rc.local可执行权限
chmod +x /etc/rc.local
步骤四:添加自启脚本或命令并测试

将所需要执行的命令或脚本写入exit 0之前即可,如:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
sed -ri 's@(nameserver )[0-9].*@\1202.99.192.68@' /etc/resolv.conf
bash /home/centos/
exit 0

systemd服务脚本简析

服务脚本后缀名

.service:用于定义系统服务,封装服务的启动、停止、重启及重载

.target:对Unit进行逻辑分组,用于模拟实现运行级别

.device:对应/dev目录下的设备,用于定义设备之间的依赖关系

.mount:用于定义文件系统挂载点

.automount:用于控制自动挂载(即当某目录被访问时系统自动挂载该目录),取代了传统的autofs

.path:用于监控指定目录是否发生变化,并触发其它Unit运行

.scope:这类Unit不是用户创建的,而是systemd自行生成的,用于描述系统服务之间的分组信息

.slice:用于描述CGroup

.snapshotsystemctl snapshot创建的一个Unit运行状态快照(服务快照)

.socket:监控系统或网络中的socket消息,用于实现基于网络数据自动触发的服务启动

配置区段

[Unit]:用于定义Unit的描述信息、依赖关系、服务文档等

[Service]:用于定义服务的具体管理和操作方法

[Install]:这部分配置需通过systemctl enable命令激活并通过systemctl disable命令禁用,通常配置与某个特定级别的target关联,使之随之共同运行(开机自启)

[Unit]

大部分字段均支持空格分隔的单元列表

Description:此Unit的描述信息,通常为一句简短的话

Documentation:指定此Unit的说明文档或帮助手册,可以是一个或多个文档的URI路径,可接受http://https://file://info:man:五种URI类型(接受一个空格分隔的单元列表)

ConditionFileIsExecutable:检测指定文件是否存在并且是一个可执行文件,需使用绝对路径,并支持!前缀表示逻辑反转

Requires:此Unit所依赖的其它Unit列表,列在其中的Unit将会在此Unit启动的同时被启动,如果列表中有任意一个Unit启动失败,那么这个Unit也会被终止(接受一个空格分隔的单元列表)

Wants:与Requires类似,只是在此Unit启动时,触发启动列表中的每个Unit模块,但不去考虑这些模块是否启动成功(接受一个空格分隔的单元列表)

After:与Requires类似,只是在此Unit启动之前,先启动当前列表中的所有Unit模块,只有当列表中的模块全部启动之后,才会启动此Unit(接受一个空格分隔的单元列表)

Before:与After相反,在启动此列表中的Unit之前,都会先确认当前Unit已经在运行(接受一个空格分隔的单元列表)

BindsTo:与Requires类似,但是是一种更强的关联,此Unit不仅随着列表中Unit的启动与终止,并且当列表中的Unit有任意一个出现意外终止或重启,此Unit也会随着终止与重启(接受一个空格分隔的单元列表)

PartOf:属于BindsTo的子集,仅在列出的Unit模块失败或重启时,终止会重启当前Unit,而不会随着列表中的Unit启动而启动(接受一个空格分隔的单元列表)

Conflicts:定义Unit之间的冲突关系,表示当前Unit与列表中的任何Unit均不能共存,也就是说当此Unit启动时,列表中的所有Unit都将被停止,而当列表中的某个Unit启动时,此Unit也同样将被终止(接受一个空格分隔的单元列表)

[Install]

WantedBy、RequiredBy:当对此Unit执行systemctl enable后,将会在列表中的Unit的.wants/.requires/目录下创建一个指向此Unit的软链接(接受一个空格分隔的单元列表)

相当于在列表中的每个Unit服务脚本中的WantsRequires字段中添加了此Unit,如此一来,当列表中的任意一个Unit启动时,都会尝试启动此Unit。列表中的Unit通常为系统启动级别的target,就相当于系统一启动,就自动启动此Unit,以达到开机自动启动服务的目的

Alias:别名,接受空格分隔的别名列表

Also:当这个服务被enable/disable时,将自动enable/disable此列表中的每个Unit模块

[Service]

此区段为“.service”文件独有

Type:服务类型,常用有simple(默认)和forking

类型

特点

simple

默认,适用大部分场景,关注Unit本身

forking

Unit启动后会通过fork调用创建子进程,并终止Unit本身进程

RemainAfterExit:值为truefalse(也支持yesno),默认为false,当值为true时,systemd负责启动服务进程,之后即便服务进程终止了,systemd仍认为此Unit正在运行中

此配置主要给一些非常驻内存型服务使用,这些服务启动注册后立即退出,然后等待请求消息,按需启动提供服务

ExecStart:必填字段,指定Unit的启动命令,在每个服务脚本中仅能出现一次

start参数也可省略

ExecStartPre:在执行ExecStart之前的准备工作

ExecStartPost:在执行ExecStart之后的收尾工作

ExecStop:停止(stop)Unit时所需执行的命令

ExecStopPost:在执行ExecStop之后的收尾工作

TimeoutStartSec:启动Unit时等待的时间(秒),如果超时仍未成功启动,则systemd判定Unit启动失败,将值设置为“0”,则关闭超时检测

此配置对于Docker容器托管的应用比较重要,由于Docker首次运行时需拉取镜像文件,由于网络原因可能造成严重超时,易被systemd误判为启动失败而终止

TimeoutStopSec:停止Unit时等待的时间(秒),如果超时仍未成功停止,systemd将会使用SIGKILL信号强行杀死服务

TimeoutSec:停止Unit之前需要等待的时间(秒)

Environment:为Unit添加环境变量

EnvironmentFile:指定加载一个Unit所需的环境变量列表文件

文件中的每一行都是一个环境变量的定义,Key=Value形式,也支持$Key形式,从当前环境中获取Value

GuessMainPID:在无法明确该Unit的主进程时,systemd是否应猜测此Unit的PID(可能错误),默认值为yes

该配置仅在Type=forking但未设置PIDFile(指定Unit的PID文件路径)时生效,如PID猜测错误,Unit的失败检测与自动重启也将失效

PIDFile:指定此Unit的PID文件路径(默认位于*/run*目录下),systemd会在此Unit启动完成后,从此文件读取主进程PID值,并在Unit停止后删除它

所有ExecStart字段之前的配置,都可以加上一个连词号-,表示“抑制错误”,即当错误发生的时候,不影响其余配置执行,如:EnvironmentFile=-/root/env.txt,表示即使当/root/env.txt文件不存在时,也不会抛出错误