一、了解开机程系统服务启动方式
(一)对于System V 调用init的启动流程(旧方式)
- 加载 BIOS 的硬件信息不迚行自我测试,并依据讴定取得第一个可开机的装置;
- 读取并执行第一个开机装置内 MBR 的 boot Loader (亦即是 grub, spfdisk 等程序);
- 依据 boot loader 的设定加载 Kernel ,Kernel 会开始侦测硬件不加载驱劢程序;
在硬件驱动成功后,Kernel 会主动调用 init 程序,而 init 会取得 run-level 信息;
载入 BIOS 的硬件信息与进行自我测试,并依据设置取得第一个可开机的设备;
- 读取并执行第一个开机设备内 MBR 的 boot Loader (亦即是 grub2, spfdisk 等程序);
- 依据 boot loader 的设置载入 Kernel ,Kernel 会开始侦测硬件与载入驱动程序;
- 在硬件驱动成功后,Kernel 会主动调用 systemd 程序,并以 default.target 流程开机;
- systemd 执行 sysinit.target 初始化系统及 basic.target 准备操作系统;
- systemd 启动 multi-user.target 下的本机与服务器服务;
- systemd 执行 multi-user.target 下的 /etc/rc.d/rc.local 文件;
- systemd 执行 multi-user.target 下的 getty.target 及登陆服务;
- systemd 执行 graphical 需要的服务
二、设置开机自启:
(一)针对旧的服务启动System V 的调用init(新的方式也兼容)
1、针对: init 执行 /etc/rc.d/rc.local 或/etc/rc.local 文件;
编辑文件 /etc/rc.local(用户自定义开机启动程序)
输入命令:vim /etc/rc.local 将出现类似如下的文本片段:
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
/etc/init.d/mysqld start #mysql开机启动
/etc/init.d/nginx start #nginx开机启动
/etc/init.d/php-fpm start #php-fpm开机启动
/etc/init.d/memcached start #memcache开机启动
在文件末尾(exit 0之前)加上你开机需要启动的程序或执行的命令即可
(执行的程序需要写绝对路径,添加到系统环境变量的除外),
如:/usr/local/thttpd/sbin/thttpd -C /usr/local/thttpd/etc/thttpd.conf
2、针对:init 执行 run-level 的各个服务的启动 (/etc/r[0-6].d/或/etc/rc.d/rc[0-6].d/)
- 先了解/etc/r[0-6].d/或/etc/rc.d/rc[0-6].d/下的文件与/etc/init.d/下的文件关系 ```bash pi@raspberrypi:/etc $ ls |grep rc*.d grep: rc1.d: Is a directory grep: rc2.d: Is a directory grep: rc3.d: Is a directory grep: rc4.d: Is a directory grep: rc5.d: Is a directory grep: rc6.d: Is a directory grep: rcS.d: Is a directory
```bash
pi@raspberrypi:/etc $ cd rcS.d
pi@raspberrypi:/etc/rcS.d $ ls
K01hwclock.sh K01rpcbind S01fake-hwclock S01kmod S01procps S01udev
K01nfs-common S01alsa-utils S01keyboard-setup.sh S01networking S01raspi-config S01x11-common
pi@raspberrypi:/etc $ ls rc6.d
K01alsa-utils K01dhcpcd K01mysql K01nmbd K01rng-tools K01samba-ad-dc K01udev
K01avahi-daemon K01fake-hwclock K01networking K01paxctld K01rpcbind K01smbd K01vsftpd
K01bluetooth K01hwclock.sh K01nfs-common K01redis-server K01rsyslog K01triggerhappy
pi@raspberrypi:/etc $ ls rc5.d
S01avahi-daemon S01cron S01dphys-swapfile S01paxctld S01rng-tools S01samba-ad-dc S01sudo
S01bluetooth S01dbus S01mysql S01raspi-config S01rsync S01smbd S01triggerhappy
S01console-setup.sh S01dhcpcd S01nmbd S01redis-server S01rsyslog S01ssh S01vsftpd
pi@raspberrypi:/etc $ ls rc4.d
S01avahi-daemon S01cron S01dphys-swapfile S01paxctld S01rng-tools S01samba-ad-dc S01sudo
S01bluetooth S01dbus S01mysql S01raspi-config S01rsync S01smbd S01triggerhappy
S01console-setup.sh S01dhcpcd S01nmbd S01redis-server S01rsyslog S01ssh S01vsftpd
.......
pi@raspberrypi:/etc/init.d $ ls
alsa-utils cron fake-hwclock mysql paxctld rng-tools samba-ad-dc triggerhappy
avahi-daemon dbus hwclock.sh networking procps rpcbind smbd udev
bluetooth dhcpcd keyboard-setup.sh nfs-common raspi-config rsync ssh vsftpd
console-setup.sh dphys-swapfile kmod nmbd redis-server rsyslog sudo x11-common
#实际上,/etc/rc[0-6/S].d/下的只是一个链接,执行的时候会到/etc/init.d/下找原始文件。
pi@raspberrypi:/etc $ ls rcS.d -l
total 0
lrwxrwxrwx 1 root root 20 Feb 13 2020 K01hwclock.sh -> ../init.d/hwclock.sh
lrwxrwxrwx 1 root root 20 Feb 13 2020 K01nfs-common -> ../init.d/nfs-common
lrwxrwxrwx 1 root root 17 Feb 13 2020 K01rpcbind -> ../init.d/rpcbind
lrwxrwxrwx 1 root root 20 Feb 13 2020 S01alsa-utils -> ../init.d/alsa-utils
lrwxrwxrwx 1 root root 22 Feb 13 2020 S01fake-hwclock -> ../init.d/fake-hwclock
lrwxrwxrwx 1 root root 27 Feb 13 2020 S01keyboard-setup.sh -> ../init.d/keyboard-setup.sh
lrwxrwxrwx 1 root root 14 Feb 13 2020 S01kmod -> ../init.d/kmod
lrwxrwxrwx 1 root root 20 Feb 13 2020 S01networking -> ../init.d/networking
lrwxrwxrwx 1 root root 16 Feb 13 2020 S01procps -> ../init.d/procps
lrwxrwxrwx 1 root root 22 Feb 13 2020 S01raspi-config -> ../init.d/raspi-config
lrwxrwxrwx 1 root root 14 Feb 13 2020 S01udev -> ../init.d/udev
lrwxrwxrwx 1 root root 20 Aug 4 20:10 S01x11-common -> ../init.d/x11-common
- 创建自己的服务启动文件
在该目录下新建文件testboot,编辑内容:
在/etc/init.d/目录下新建一个服务脚本文件。在终端输入
#!/bin/sh
#/etc/init.d/testboot
### BEGIN INIT INFO
# Provides:testboot
# Required-Start:$remote_fs $syslog
# Required-Stop:$remote_fs $syslog
# Default-Start:2 3 4 5
# Default-Stop:0 1 6
# Short-Description: testboot
# Description: This service is used to start my applaction
### END INIT INFO
case "$1" in
start)
echo "start your app here."
su pi -c "exec ~/testboot.sh"
;;
stop)
echo "stop your app here."
;;
*)
echo "Usage: service testboot start|stop"
exit 1
;;
esac
exit 0
pi@raspberry:~ $ sudo chmod 777 /etc/init.d/testboot //可执行权限
pi@raspberry:~ $ sudo update-rc.d testboot defaults //该脚本作为服务设置开机自动加载
最后将该脚本作为服务设置开机自动加载:
pi@raspberry:~ $ sudo update-rc.d testboot defaults
3、通过/etc/ini.d目录下所有以“S”开头的文件
- 系统启动过程中会扫描/etc/ini.d目录下所有以“S”开头的文件并启动。
- 所以只需在/etc/init.d目录下编写一个文件名为:“S+编号+名称”的可执行脚本即可,在脚本中增加启动某个具体程序的语句即可。
- 文件名必须以“S”开头,编号代表了启动级别,越大越晚运行,取值建议在90~99之间。
例如:需要开机自启动的应用程序为/opt/myapp/bin/myapp
可编写S90myapp脚本并增加可执行权限,放到/etc/init.d目录下
文件内容可简单的写为:
#!/bin/sh
/opt/myapp/bin/myapp &
如果程序启动之前需要设置一些环境变量,或者进行其他初始化,或者加载某些外设驱动或者库等等,最好编写一个独立的程序启动脚本来完成以上工作,如启动程序的脚本为startmyapp,内容如下(注意,脚本需要可执行权限):
#!/bin/sh
insmod xxx.ko udevtrigger
export XXX=
export YYY=
pt/myapp/bin/myapp
4、自己写一个shell脚本
将写好的脚本(.sh文件)放到目录 /etc/profile.d/ 下,系统启动后就会自动执行该目录下的所有shell脚本。
(二)针对新的方式Systemed的调用unit
在树莓派上创建一个 .service 文件。
vim myscript.service
[Unit]
Description=SVN service
After=network.target
[Service]
Type=forking
WorkingDirectory=/home/pi/toshiba/SVN
ExecStart=svnserve -d -r ./
TimeoutSec=0
RemainAfterExit=yes
SysVStartPriority=99
[Install]
WantedBy=multi-user.target
//在上面的范例中,服务会去以 Python 3 来运行 /home/pi/myscript 目录下面的 main.py 脚本。
用这种方法,你不仅可以配置 Python 脚本,只需要将 ExecStart 这行改为需要启动的任何程序或脚本即可。
##将这个文件用 root 用户保存到 /etc/systemd/system 目录:
sudo cp myscript.service /etc/systemd/system/myscript.service
##然后就可以用下面的命令尝试启动服务了:
sudo systemctl start myscript.service
##停止服务:
sudo systemctl stop myscript.service
##设置开机时自动运行:
sudo systemctl enable myscript.service
##systemctl 命令还可以用来重启或禁用它。
注意事项: 1、启动顺序取决于他们的依赖关系。如果是依赖于网络的服务,应当在引导过程中尽可能晚一点启动。
使用 man systemctl
命令或访问 https://fedoramagazine.org/what-is-an-init-system/ 了解更多。