一、了解开机程系统服务启动方式

(一)对于System V 调用init的启动流程(旧方式)

  1. 加载 BIOS 的硬件信息不迚行自我测试,并依据讴定取得第一个可开机的装置;
  2. 读取并执行第一个开机装置内 MBR 的 boot Loader (亦即是 grub, spfdisk 等程序);
  3. 依据 boot loader 的设定加载 Kernel ,Kernel 会开始侦测硬件不加载驱劢程序;
  4. 在硬件驱动成功后,Kernel 会主动调用 init 程序,而 init 会取得 run-level 信息;

    1. init 执行 /etc/rc.d/rc.sysinit 档案来准备软件执行的作业环境 (如网络、时区等);
    2. init 执行 run-level 的各个服务的启动 (script 方式)(/etc/r[0-6].d/或/etc/rc.d/rc[0-6].d/);
    3. init 执行 /etc/rc.d/rc.local 或/etc/rc.local 文件;
    4. init 执行终端机仿真程序 mingetty 来启动login 程序,最后就等待用户登入啦;

      (二)对于Systemed调用systemd流程(目前方式)

  5. 载入 BIOS 的硬件信息与进行自我测试,并依据设置取得第一个可开机的设备;

  6. 读取并执行第一个开机设备内 MBR 的 boot Loader (亦即是 grub2, spfdisk 等程序);
  7. 依据 boot loader 的设置载入 Kernel ,Kernel 会开始侦测硬件与载入驱动程序;
  8. 在硬件驱动成功后,Kernel 会主动调用 systemd 程序,并以 default.target 流程开机;
    1. systemd 执行 sysinit.target 初始化系统及 basic.target 准备操作系统;
    2. systemd 启动 multi-user.target 下的本机与服务器服务;
    3. systemd 执行 multi-user.target 下的 /etc/rc.d/rc.local 文件;
    4. systemd 执行 multi-user.target 下的 getty.target 及登陆服务;
    5. systemd 执行 graphical 需要的服务

二、设置开机自启:

(一)针对旧的服务启动System V 的调用init(新的方式也兼容)

1、针对: init 执行 /etc/rc.d/rc.local 或/etc/rc.local 文件;

编辑文件 /etc/rc.local(用户自定义开机启动程序)
输入命令:vim /etc/rc.local 将出现类似如下的文本片段:

  1. #!/bin/sh
  2. #
  3. # This script will be executed *after* all the other init scripts.
  4. # You can put your own initialization stuff in here if you don't
  5. # want to do the full Sys V style init stuff.
  6. touch /var/lock/subsys/local
  7. /etc/init.d/mysqld start #mysql开机启动
  8. /etc/init.d/nginx start #nginx开机启动
  9. /etc/init.d/php-fpm start #php-fpm开机启动
  10. /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
  1. ```bash
  2. pi@raspberrypi:/etc $ cd rcS.d
  3. pi@raspberrypi:/etc/rcS.d $ ls
  4. K01hwclock.sh K01rpcbind S01fake-hwclock S01kmod S01procps S01udev
  5. K01nfs-common S01alsa-utils S01keyboard-setup.sh S01networking S01raspi-config S01x11-common
  6. pi@raspberrypi:/etc $ ls rc6.d
  7. K01alsa-utils K01dhcpcd K01mysql K01nmbd K01rng-tools K01samba-ad-dc K01udev
  8. K01avahi-daemon K01fake-hwclock K01networking K01paxctld K01rpcbind K01smbd K01vsftpd
  9. K01bluetooth K01hwclock.sh K01nfs-common K01redis-server K01rsyslog K01triggerhappy
  10. pi@raspberrypi:/etc $ ls rc5.d
  11. S01avahi-daemon S01cron S01dphys-swapfile S01paxctld S01rng-tools S01samba-ad-dc S01sudo
  12. S01bluetooth S01dbus S01mysql S01raspi-config S01rsync S01smbd S01triggerhappy
  13. S01console-setup.sh S01dhcpcd S01nmbd S01redis-server S01rsyslog S01ssh S01vsftpd
  14. pi@raspberrypi:/etc $ ls rc4.d
  15. S01avahi-daemon S01cron S01dphys-swapfile S01paxctld S01rng-tools S01samba-ad-dc S01sudo
  16. S01bluetooth S01dbus S01mysql S01raspi-config S01rsync S01smbd S01triggerhappy
  17. S01console-setup.sh S01dhcpcd S01nmbd S01redis-server S01rsyslog S01ssh S01vsftpd
  18. .......
  19. pi@raspberrypi:/etc/init.d $ ls
  20. alsa-utils cron fake-hwclock mysql paxctld rng-tools samba-ad-dc triggerhappy
  21. avahi-daemon dbus hwclock.sh networking procps rpcbind smbd udev
  22. bluetooth dhcpcd keyboard-setup.sh nfs-common raspi-config rsync ssh vsftpd
  23. console-setup.sh dphys-swapfile kmod nmbd redis-server rsyslog sudo x11-common
  24. #实际上,/etc/rc[0-6/S].d/下的只是一个链接,执行的时候会到/etc/init.d/下找原始文件。
  25. pi@raspberrypi:/etc $ ls rcS.d -l
  26. total 0
  27. lrwxrwxrwx 1 root root 20 Feb 13 2020 K01hwclock.sh -> ../init.d/hwclock.sh
  28. lrwxrwxrwx 1 root root 20 Feb 13 2020 K01nfs-common -> ../init.d/nfs-common
  29. lrwxrwxrwx 1 root root 17 Feb 13 2020 K01rpcbind -> ../init.d/rpcbind
  30. lrwxrwxrwx 1 root root 20 Feb 13 2020 S01alsa-utils -> ../init.d/alsa-utils
  31. lrwxrwxrwx 1 root root 22 Feb 13 2020 S01fake-hwclock -> ../init.d/fake-hwclock
  32. lrwxrwxrwx 1 root root 27 Feb 13 2020 S01keyboard-setup.sh -> ../init.d/keyboard-setup.sh
  33. lrwxrwxrwx 1 root root 14 Feb 13 2020 S01kmod -> ../init.d/kmod
  34. lrwxrwxrwx 1 root root 20 Feb 13 2020 S01networking -> ../init.d/networking
  35. lrwxrwxrwx 1 root root 16 Feb 13 2020 S01procps -> ../init.d/procps
  36. lrwxrwxrwx 1 root root 22 Feb 13 2020 S01raspi-config -> ../init.d/raspi-config
  37. lrwxrwxrwx 1 root root 14 Feb 13 2020 S01udev -> ../init.d/udev
  38. lrwxrwxrwx 1 root root 20 Aug 4 20:10 S01x11-common -> ../init.d/x11-common
  • 创建自己的服务启动文件

在该目录下新建文件testboot,编辑内容:
在/etc/init.d/目录下新建一个服务脚本文件。在终端输入

  1. #!/bin/sh
  2. #/etc/init.d/testboot
  3. ### BEGIN INIT INFO
  4. # Provides:testboot
  5. # Required-Start:$remote_fs $syslog
  6. # Required-Stop:$remote_fs $syslog
  7. # Default-Start:2 3 4 5
  8. # Default-Stop:0 1 6
  9. # Short-Description: testboot
  10. # Description: This service is used to start my applaction
  11. ### END INIT INFO
  12. case "$1" in
  13. start)
  14. echo "start your app here."
  15. su pi -c "exec ~/testboot.sh"
  16. ;;
  17. stop)
  18. echo "stop your app here."
  19. ;;
  20. *)
  21. echo "Usage: service testboot start|stop"
  22. exit 1
  23. ;;
  24. esac
  25. exit 0
  1. pi@raspberry:~ $ sudo chmod 777 /etc/init.d/testboot //可执行权限
  2. pi@raspberry:~ $ sudo update-rc.d testboot defaults //该脚本作为服务设置开机自动加载

最后将该脚本作为服务设置开机自动加载:

pi@raspberry:~ $ sudo update-rc.d testboot defaults

3、通过/etc/ini.d目录下所有以“S”开头的文件

  1. 系统启动过程中会扫描/etc/ini.d目录下所有以“S”开头的文件并启动。
  2. 所以只需在/etc/init.d目录下编写一个文件名为:“S+编号+名称”的可执行脚本即可,在脚本中增加启动某个具体程序的语句即可。
  3. 文件名必须以“S”开头,编号代表了启动级别,越大越晚运行,取值建议在90~99之间。

例如:需要开机自启动的应用程序为/opt/myapp/bin/myapp
可编写S90myapp脚本并增加可执行权限,放到/etc/init.d目录下
文件内容可简单的写为:

  1. #!/bin/sh
  2. /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/ 了解更多。