这个问题我搞了一天多(加上写shell脚本一些错误和运行权限的问题)
总结经验:查找问题的时候注意解决方法的时间!!!我近乎把网上能找到的方法都试了一遍,就登录自启动那个方法依然是有效的,到了最后,突然灵机一动发现是版本的问题,才找到了方法。
原因:ubuntu 16.10 开始不再使用 initd 管理系统,改用 systemd …
所以在 Ubuntu 19 系统不能像其它 Ubuntu 16 一样采用编辑 rc.local 文件来设置开机启动脚本
解决方案:
systemd 默认读取 /etc/systemd/system 下的配置文件,该目录下的文件会链接 /lib/systemd/system/ 下的文件,先看看有没有 /etc/systemd/system/rc-local.service 文件, 没有就创建一个,然后输入如下代码,保存
# 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
Alias=rc-local.service
简单介绍一下配置文件的意思
[Unit] 段: 启动顺序与依赖关系
[Service] 段: 启动行为,如何启动,启动类型
[Install] 段: 定义如何安装这个配置文件,即怎样做到开机启动
Ubuntu 19.10 默认是没有 /etc/rc.local 这个文件的,需要自己创建一下
sudo touch /etc/rc.local
记得 rc.local脚本首行一定要添加:
#!/bin/sh -e
#rc.local
#然后就在里面写自己的shell脚本了,可以重定向到日志文件,方便查看服务启动有没有正常
echo "服务启动成功" > /usr/local/rc.log
exit 0
给rc.local运行权限
chmod +x /etc/rc.local
可以先自己运行下看脚本是否有问题(记得把日志文件删除)
sudo /etc/./rc.local
最后启动系统服务
sudo systemctl enable rc-local
enable是开机自启动的意思,disable是关闭开机自启动的意思
查看服务开机自启动有没有设置成功
systemctl is-enabled rc-local.service
如果返回static是说明服务不能设置开机自启动
开启服务
systemctl start rc-local.service
查看服务运行状态
systemctl status rc-local.service
然后重启电脑或者服务器,使用 cat 查看是否输出 “/usr/local/rc.log” ,如果有的话就是添加成功了,如果失败的话再看看是不是漏了步骤
cat /usr/local/rc.log
服务启动成功
步骤跟方案一的差不多,先创建 /etc/systemd/system/frpc.service 文件,输入:
[Unit]
Description=frpc
After=multi-user.target
[Service]
TimeoutStartSec=30
ExecStart=/root/frp_0.22.0_linux_amd64/frpc -c /root/frp_0.22.0_linux_amd64/frpc.ini
ExecStop=/bin/kill $MAINPID
[Install]
WantedBy=multi-user.target
ExecStart记得更改为你要运行的shell命令
Description是服务名
After=multi-user.target意思是在系统正常运行后再启动本服务(这个设置挺重要的,可以避免一些莫名其妙的错误)
其他步骤基本和方案一类似,这里就不细讲了
#修改服务之后systemctl的重加载
systemctl daemon-reload
#查看启动失败的服务列表
systemctl --failed
#查看开机自启动的服务列表
systemctl list-unit-files|grep enabled
#重启一个服务
sudo systemctl restart frpc.service
#重载一个服务
sudo systemctl reload nginx.service
[Unit]
Description : 服务的简单描述
Documentation : 服务文档
Before、After:定义启动顺序。Before=xxx.service,代表本服务在xxx.service启动之前启动。After=xxx.service,代表本服务在xxx.service之后启动。
Requires:这个单元启动了,它需要的单元也会被启动;它需要的单元被停止了,这个单元也停止了。
Wants:推荐使用。这个单元启动了,它需要的单元也会被启动;它需要的单元被停止了,对本单元没有影响。
[Service]
Type=simple(默认值):systemd认为该服务将立即启动。服务进程不会fork。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket激活型。
Type=forking:systemd认为当该服务进程fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便systemd能够跟踪服务的主进程。
Type=oneshot:这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。
Type=notify:与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 libsystemd-daemon.so 提供。
Type=dbus:若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。
Type=idle: systemd会等待所有任务(Jobs)处理完成后,才开始执行idle类型的单元。除此之外,其他行为和Type=simple 类似。
PIDFile:pid文件路径
ExecStart:指定启动单元的命令或者脚本,ExecStartPre和ExecStartPost节指定在ExecStart之前或者之后用户自定义执行的脚本。Type=oneshot允许指定多个希望顺序执行的用户自定义命令。
ExecReload:指定单元停止时执行的命令或者脚本。
ExecStop:指定单元停止时执行的命令或者脚本。
PrivateTmp:True表示给服务分配独立的临时空间
Restart:这个选项如果被允许,服务重启的时候进程会退出,会通过systemctl命令执行清除并重启的操作。
RemainAfterExit:如果设置这个选择为真,服务会被认为是在激活状态,即使所以的进程已经退出,默认的值为假,这个选项只有在Type=oneshot时需要被配置。
[Install]
Alias:为单元提供一个空间分离的附加名字。
RequiredBy:单元被允许运行需要的一系列依赖单元,RequiredBy列表从Require获得依赖信息。
WantBy:单元被允许运行需要的弱依赖性单元,Wantby从Want列表获得依赖信息。
Also:指出和单元一起安装或者被协助的单元。
DefaultInstance:实例单元的限制,这个选项指定如果单元被允许运行默认的实例。