systemd-rc-local启动出错

上一级页面:index-wsl

rc.local简介

rc.local 是一个早期的产物用来进行启动配置的管理(还可以进行开机自启动服务的管理)

rc.local ,使用上很简单,就是添加执行权限,同时添加自己的shell 代码就可以了

软硬件环境

  • ubuntu 18.04 64bit
  • anaconda with python 3.6

问题描述

在使用较新版本的ubuntu系统中发现,原来写入/etc/rc.local文件中的开机命令不执行了?经过一番研究,发现原来ubuntu16.04版本后就不再使用initd管理系统,而改用systemd

分析问题

通过systemctl命令查看rc-local的状态

1
sudo systemctl status rc-local

输出错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 rc-local.service - /etc/rc.local Compatibility
Loaded: loaded (/lib/systemd/system/rc-local.service; enabled-runtime; vendor preset: enabled)
Drop-In: /lib/systemd/system/rc-local.service.d
└─debian.conf
Active: failed (Result: exit-code) since Thu 2018-11-01 10:56:36 CST; 1h 59min ago
Docs: man:systemd-rc-local-generator(8)
Process: 1961 ExecStart=/etc/rc.local start (code=exited, status=203/EXEC)

11 01 10:56:36 ubuntu systemd[1]: Starting /etc/rc.local Compatibility...
11 01 10:56:36 ubuntu systemd[1961]: rc-local.service: Failed to execute command: Exec format error
11 01 10:56:36 ubuntu systemd[1961]: rc-local.service: Failed at step EXEC spawning /etc/rc.local: Exec format e
11 01 10:56:36 ubuntu systemd[1]: rc-local.service: Control process exited, code=exited status=203
11 01 10:56:36 ubuntu systemd[1]: rc-local.service: Failed with result 'exit-code'.
11 01 10:56:36 ubuntu systemd[1]: Failed to start /etc/rc.local Compatibility.

告诉我,不该给/etc/rc.local可执行权限,因为执行时报错了

尝试启用,会报错

1
sudo systemctl enable rc-local

输出错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
xugaoxiang@ubuntu:~$ sudo systemctl enable rc-local
The unit files have no installation config (WantedBy, RequiredBy, Also, Alias
settings in the [Install] section, and DefaultInstance for template units).
This means they are not meant to be enabled using systemctl.
Possible reasons for having this kind of units are:
1) A unit may be statically enabled by being symlinked from another unit's
.wants/ or .requires/ directory.
2) A unit's purpose may be to act as a helper for some other unit which has
a requirement dependency on it.
3) A unit may be started when needed via activation (socket, path, timer,
D-Bus, udev, scripted systemctl call, ...).
4) In case of template units, the unit is meant to be enabled with some
instance name specified.

大意是说rc-local服务文件中没有Install字段的相关信息,如WantedByRequiredByAlsoAlias。如果不写呢,系统就不认为它是一个systemd服务。

解决方法一:在systemd中使能rc-local服务

默认的service文件都是存在与/etc/systemd/system目录下,有点像某种服务的配置文件。注意到/lib/systemd/system下也有个rc-local.service,我们借用这个模板来进行修改,当然你也可以从头开始编写

1
sudo cp /lib/systemd/system/rc-local.service /etc/systemd/system/rc-local.service

如果没有/lib/systemd/system/rc-local.service也无所谓,接着往下看

1
sudo vim /etc/systemd/system/rc-local.service

修改内容如下,主要是,底部添加Install字段信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#  SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.local is executable.
[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

其中Unit字段主要描述服务的启动顺序以及依赖关系,Service字段主要描述如何启动,Install字段描述如何安装这个服务。

编辑/etc/rc.local

ubuntu 18.04系统默认已经将/etc/rc.local文件移除了,因此,我们需要手动创建一个,

1
sudo vim /etc/rc.local

将需要开机执行的命令写入到文件中,例如

1
2
3
4
5
#!/bin/bash
# 上面这行在文件头,没有的自己加
#
# 例子如下
# /usr/bin/sslocal -c /home/xugaoxiang/Tools/ss/ss.json &

同样的,别忘了,给/etc/rc.local加上可执行的权限

1
sudo chmod a+x /etc/rc.local

启用rc-local

然后执行

1
sudo systemctl enable rc-local
1
2
xugaoxiang@ubuntu:~$ sudo systemctl enable rc-local
Created symlink /etc/systemd/system/multi-user.target.wants/rc-local.service → /etc/systemd/system/rc-local.service.

接着启动这个服务并查看它的状态

1
2
sudo systemctl start rc-local.service
sudo systemctl status rc-local.service

命令输出如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
● rc-local.service - /etc/rc.local Compatibility
Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: enabled)
Drop-In: /lib/systemd/system/rc-local.service.d
└─debian.conf
Active: active (running) since Thu 2018-11-01 13:17:08 CST; 2s ago
Docs: man:systemd-rc-local-generator(8)
Process: 10810 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
Tasks: 1 (limit: 4915)
CGroup: /system.slice/rc-local.service
└─10811 /usr/bin/python /usr/bin/sslocal -c /home/xugaoxiang/Tools/ss/ss.json

11月 01 13:17:08 ubuntu systemd[1]: Starting /etc/rc.local Compatibility...
11月 01 13:17:08 ubuntu systemd[1]: Started /etc/rc.local Compatibility.
11月 01 13:17:08 ubuntu rc.local[10810]: INFO: loading config from /home/xugaoxiang/Tools/ss/ss.json
11月 01 13:17:08 ubuntu rc.local[10810]: 2018-11-01 13:17:08 INFO loading libcrypto from libcrypto.so.1.1
11月 01 13:17:08 ubuntu rc.local[10810]: 2018-11-01 13:17:08 INFO starting local at 127.0.0.1:1080

可以看到rc.local中的脚本已经被正确执行了。

解决方法二:不使用rc.local

去除可执行权限

1
chmod -x /etc/rc.local

分析rcX.d

1
ll /etc

Pasted%20image%2020220613094912.png

rcX.d按照优先级0-6顺序,可以建立软连接到rc0.d/文件夹中

1
2
cd /etc/rc0.d/
sudo ln -s ../init.d/XXXXX.sh .

启动顺序:

  1. 执行运行级别目录rcX.d下的脚本 。

  2. 执行/etc/rc.d/rc目录和/etc/rc.d/rcX.d目录下的脚本。 X为缺省运行级别。

  3. 执行/etc/rc.d/rc.local 。执行用户自定义启动脚本。你可以把你想设置和启动的东西放到这里。

参考、引用、致谢

systemd系统开机运行rc.local_迷途小书童的Note的博客-CSDN博客