rc.loacl指定非root用户启动指令(linux) 基于Systemd的rc.local配置(Centos7) 以及 crontab方式@reboot xxx-command
20180926 Chenxin
起因:
之前已经赋权755给rc.local文件,但发现开机启动的时候,centos7(systemd模式)只是将rc.local文件里的systemctl start xxx的成功启动了(只有apache和jenkins).
而其他的比如redis,mysql等服务均没有启动成功(在messages文件里可以看到启动成功的信息,但之后貌似自己就消失了).
怀疑是/etc/rc.local文件,没有在末尾 exit 0 原因.
开机时的messages文件如下:
Sep 26 12:09:51 MiWiFi-R3P-srv systemd: Starting /etc/rc.d/rc.local Compatibility... #开始启动rc.local
Sep 26 12:09:51 MiWiFi-R3P-srv systemd: Starting OpenSSH server daemon...
...
Sep 26 12:09:52 MiWiFi-R3P-srv rc.local: 1277:C 26 Sep 12:09:52.273 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
Sep 26 12:09:52 MiWiFi-R3P-srv rc.local: 1277:C 26 Sep 12:09:52.274 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=1277, just started
Sep 26 12:09:52 MiWiFi-R3P-srv rc.local: 1277:C 26 Sep 12:09:52.274 # Configuration loaded #这里已经启动了redis,但最终却没有redis进程
...
Sep 26 12:09:55 MiWiFi-R3P-srv jenkins: Starting Jenkins [ OK ] #启动Jenkins
Sep 26 12:09:55 MiWiFi-R3P-srv systemd: Started LSB: Jenkins Automation Server. #完成启动Jenkins
Sep 26 12:09:56 MiWiFi-R3P-srv rc.local: Starting MySQL.... SUCCESS! #启动了mysql
Sep 26 12:09:56 MiWiFi-R3P-srv systemd: Starting The Apache HTTP Server... #启动apache
Sep 26 12:09:57 MiWiFi-R3P-srv systemd: Started The Apache HTTP Server. #完成启动apache
Sep 26 12:09:57 MiWiFi-R3P-srv rc.local: No suitable Java Virtual Machine could be found on your system. #这里好像是报错
Sep 26 12:09:57 MiWiFi-R3P-srv rc.local: The version of the JVM must be at least 1.8 and at most 1.8.
Sep 26 12:09:57 MiWiFi-R3P-srv rc.local: Please define INSTALL4J_JAVA_HOME to point to a suitable JVM.
Sep 26 12:09:57 MiWiFi-R3P-srv systemd: rc-local.service: control process exited, code=exited status=83 #以下都是rc.lcoal失败提示
Sep 26 12:09:59 MiWiFi-R3P-srv systemd: Failed to start /etc/rc.d/rc.local Compatibility.
Sep 26 12:09:59 MiWiFi-R3P-srv systemd: Unit rc-local.service entered failed state.
Sep 26 12:09:59 MiWiFi-R3P-srv systemd: rc-local.service failed.

rc-local.service文件
系统上有2个rc-local.service文件
diff /lib/systemd/system/rc-local.service /usr/lib/systemd/system/rc-local.service 2个文件完全相同.修改的话,改/usr下的.

[root@MiWiFi-R3P-srv ~]# cat /usr/lib/systemd/system/rc-local.service

This file is part of systemd.

This unit gets pulled automatically into multi-user.target by

systemd-rc-local-generator if /etc/rc.d/rc.local is executable.

[Unit]
Description=/etc/rc.d/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.d/rc.local
After=network.target

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

[Install] #新加入部分.[Install]为新增内容,"multi-user.target"代表init3,"graphical.target"代表5
WantedBy=multi-user.target

rc.local文件
编辑/etc/rc.local文件.
[root@MiWiFi-R3P-srv ~]# cat /etc/rc.local

!/bin/bash

THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES

touch /var/lock/subsys/local

source /etc/profile
/usr/local/svn/bin/svnserve -d -r /svn-data/svn-new
/usr/local/redis/src/redis-server /usr/local/redis/redis.conf
/usr/local/mysql/support-files/mysql.server start
/bin/systemctl start httpd.service
/bin/systemctl start jenkins
sudo -u xbzj /other-data/nexus/nexus-3.12.1-01/bin/nexus start
exit 0 #新加入部分(不知道是否有用,未验证)

扩展说明: 指定非root用户执行开机启动方法
su - admin -c "ps axfu"
sudo -u admin ps axfu 或 sudo -u admin -s ps axfu

赋权
[root@MiWiFi-R3P-srv ~]# chmod 755 /etc/rc.local #这里可能是个软连接 /etc/rc.local -> rc.d/rc.local

创建rc.local服务
[root@MiWiFi-R3P-srv system]# systemctl enable rc-local
Created symlink from /etc/systemd/system/multi-user.target.wants/rc-local.service to /usr/lib/systemd/system/rc-local.service. #在rc-local.service文件里需要[Install],才会生成该软连接.

首次当场启动rc.local
systemctl start rc-local #启动rc.local里服务(当场启动)
systemctl status rc-local #查看刚刚手动启动后的状态或报错等信息(抓取/var/log/messages内容),或 systemctl status rc-local.service
[root@MiWiFi-R3P-srv system]# systemctl status rc-local
rc-local.service - /etc/rc.d/rc.local Compatibility
Loaded: loaded (/usr/lib/systemd/system/rc-local.service; enabled; vendor preset: disabled)
Active: active (exited) (Result: exit-code) since Wed 2018-09-26 17:41:26 CST; 26min ago
Main PID: 8373 (code=exited, status=1/FAILURE) ...
验证
reboot服务器加以验证是否正确(此步骤暂未验证).
20181008 机器重启,验证生效.

扩展知识
cron方式的开机自动启动
注意@reboot xxx-command, 所以写 rc.local 的东西, 也可以使用 @reboot 写在 crontab 里面.用这个方式设计服务器开机自启.

@reboot Run once, at startup. #这个可以用于reboot后,自动运行一次
@yearly Run once a year, “0 0 1 1 *”每年一次,同 @annually (same as @yearly)
@monthly Run once a month, “0 0 1 * *”每月
@weekly Run once a week, “0 0 * * 0” 每周
@daily Run once a day, “0 0 * * *”每天一次,同 @midnight (same as @daily)
@hourly Run once an hour, “0 * * * *”每小时.如@hourly /usr/local/awstats.sh #使用@hourly对应的是 0 * * * * 每个小时运行一次

自定义systemd服务
systemctl脚本存放在:/usr/lib/systemd/
有系统system和用户user之分.开机就能运行的程序,存在system里,即/usr/lib/systemd/system/.
服务以.service结尾,一般会分为3部分:[Unit] [Service] [Install]

以启动tomcat项目为例:
/usr/lib/systemd/system/tomcat.service

[Unit] #[Unit]部分主要是对这个服务的说明,包括Description和After
Description=tomcatapi #Description用于描述服务
After=network.target #After用于描述服务类别

[Service] #[Service]部分是服务的关键,是服务的一些具体运行参数的设置.注意,这里的启动/重启/停止命令全部要求使用绝对路径,使用相对路径则会报错.
Type=forking #后台运行的形式
PIDFile=/usr/local/tomcat/tomcat.pid #存放PID的文件路径
ExecStart=/usr/local/tomcat/bin/startup.sh #服务的运行命令
ExecReload= #重启命令
ExecStop=/usr/local/tomcat/bin/shutdown.sh #停止命令
PrivateTmp=true #表示给服务分配独立的临时空间

[Install] #服务安装的相关设置
WantedBy=multi-user.target #设置为多用户的

服务脚本编写完成后,以754的权限保存在/usr/lib/systemd/system目录下(系统里默认很多都是644),这时就可以利用systemctl进行测试了.

服务加入开机自启动:systemctl enable tomcat

systemd常用指令
参考: http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html

systemctl status
systemctl list-units
systemctl list-units --type=service

列出正在运行的 Unit

$ systemctl list-units

列出所有Unit,包括没有找到配置文件的或者启动失败的

$ systemctl list-units --all

列出所有没有运行的 Unit

$ systemctl list-units --all --state=inactive

列出所有加载失败的 Unit

$ systemctl list-units --failed

列出所有正在运行的、类型为 service 的 Unit

$ systemctl list-units --type=service

显示某个 Unit 是否正在运行

$ systemctl is-active application.service

显示某个 Unit 是否处于启动失败状态

$ systemctl is-failed application.service

显示某个 Unit 服务是否建立了启动链接

$ systemctl is-enabled application.service

每一个 Unit 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit 。
Systemd 默认从目录/etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。
systemctl enable命令用于在上面两个目录之间,建立符号链接关系。
$ systemctl enable clamd@scan.service

等同于

$ ln -s '/usr/lib/systemd/system/clamd@scan.service' '/etc/systemd/system/multi-user.target.wants/clamd@scan.service'
如果配置文件里面设置了开机启动,systemctl enable命令相当于激活开机启动。
与之对应的,systemctl disable命令用于在两个目录之间,撤销符号链接关系,相当于撤销开机启动。
$ systemctl disable clamd@scan.service
配置文件的后缀名,就是该 Unit 的种类,比如sshd.socket。如果省略,Systemd 默认后缀名为.service,所以sshd会被理解成sshd.service。

systemctl list-unit-files命令用于列出所有配置文件。

systemctl cat命令可以查看配置文件的内容。