linux 系统开机自启动脚本执行

参考:Run a Script on Startup in Linux

一、crontab

Linux 定时任务 crontab 实现秒级定时以及@reboot 的一些问题
如何查看 crontab 的日志记录
Running a script during booting/startup; init.d vs cron @reboot

  • 使用crontab -e命令编辑 crontab 文件,添加如下内容:
1
@reboot /bin/bash SCRIPT_PATH

系统重启后会自动执行脚本

  • 注意:

    • 可能得使用 root 权限才能正常自启动执行
    • 假如说执行脚本中有重定向到某个文件或终端的情况
      • 重定向到文件:可能得需要程序执行完才能看到重定向到文件的内容
      • 重定向到终端:这得需要执行脚本的时候存在该终端,否则可能会因为打不开终端而导致执行失败
  • 关于 crontab

    • 可以执行任何命令或脚本
    • 任何用户都可以添加,不只局限于 root 用户
    • on a Debian system with systemd: cron’s @reboot is executed during multi-user.target. on a Debian system with SysV (not systemd), crontab(5) mention: Please note that startup, as far as @reboot is concerned, is the time when the cron(8) daemon startup. In particular, it may be before some system daemons, or other facilities, were startup. This is due to the boot order sequence of the machine.
  • crontab 日志记录

    文件位置:/var/log/cron.log

    1
    2
    $ tail -f /var/log/cron.log	# 查看日志信息
    # 注意:有可能会出现没有这个日志文件的情况,我这里就没有这个文件

    另一种方法:

    文件目录位置:/var/spool/mail/,其中存放着不同用户的 crontab 执行的日志情况

    使用tail -f /var/spool/mail/root 即可查看 root 用户最近的 crontab 执行情况,其他用户同理

二、rc.local

参考文章:

  • rc.local 文件

    • 文件位置:/etc/rc.local,在/etc/rc.d/下有它的软连接
    • 文件原始内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/bin/bash
    # THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
    #
    # It is highly advisable to create own systemd services or udev rules
    # to run scripts during boot instead of using this file.
    #
    # In contrast to previous versions due to parallel execution during boot
    # this script will NOT be run after all other services.
    #
    # Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
    # that this script will be executed during boot.

    这里推荐我们使用 systemd 服务或 udev 规则而不是直接使用该文件,虽然不推荐直接使用,但是我们也是可以使用的,不过它的缺点是引导期间并行

  • 配置 rc.local 文件

    正常情况下,rc.local 服务应该是开启了的,如果没有开启则使用sudo systemctl enable rc-local打开该服务;除此之外,该文件应该也具有执行权限,若没有则执行sudo chmod +x /etc/rc.local即可

    1
    2
    3
    /bin/date >> /tmp/date1.log	# 写入当前时间至 date1.log
    /bin/sleep 10 # 睡眠 10s
    /bin/date >> /tmp/date2.log # 写入当前时间至 date2.log

    做完以上步骤后,重启系统时将会自动执行上述命令(当然也可以用自定义脚本替代上述命令)

  • 查看脚本执行日志(错误信息)

    1
    2
    $ journalctl -e -u rc-local.service
    $ sudo cat /var/log/syslog | grep -i rc.local
  • 注意

    rc.local 脚本在操作系统启动时只执行一次,执行过程时没有环境变量,需要把命令的完整路径加上才能成功执行

    rc.local 是一个脚本,是按顺序执行的,执行完一个程序后才会执行下一个程序,如果某程序不是后台程序,就应该加&让程序运行在后台,否则 rc.local 会挂起

    在带有 SysV(不是 systemd)的 Debian 系统上:rc.local(几乎)是最后一个启动的服务,但在带有 systemd 的 Debian 系统上:默认情况下 rc.local 在 network.target 之后执行(不是 network-online.target !)

    该脚本是在系统初始化级别脚本运行之后再执行的,因此可以安全地在里面添加我们想在系统启动之后执行的脚本

三、init.d

参考文章:

Linux 开机自启动
Linux 设置开机自启动
linux 服务器开机自启动某个脚本程序(可设定启动优先级的高级启动方式)

  • 关于 init.d

    • init.d 也称为 SysV 脚本,用于在系统初始化和关闭期间启动和停止服务(/etc/init.d/ 脚本也可以在启用 systemd 的系统上运行以实现兼容性)
    • 默认情况下,该脚本在启动和关闭期间执行
    • 该 init.d 脚本不仅仅是一个简单的脚本,而应该支持启动和停止等
  • (系统环境是 Ubuntu 18.04)/etc/rc#.d目录下都是到 /etc/init.d/ 目录的部分脚本的软链接。每个运行级别要执行哪些服务就在相对应的目录下,比如运行级别 5 要启动的服务就都放在 rc5.d 下,但是放在这个 rc5.d 下的都是一些软链接文件,链接到 /etc/init.d/ 中相对应的文件,真正干活的是 /etc/init.d/ 里的脚本,#代表一个指定的初始化运行级别,范围为 0~6

  • 运行级别

    0:系统停机状态,系统默认运行级别不能设为 0,否则不能正常启动
    1:单用户工作状态,root 权限,用于系统维护,禁止远程登陆
    2:多用户状态(没有 NFS)
    3:完全的多用户状态(有 NFS),登陆后进入控制台命令行模式
    4:系统未使用,保留
    5:X11 控制台,登陆后进入图形 GUI 模式
    6:系统正常关闭并重启,默认运行级别不能设为 6,否则不能正常启动

  • 在这些目录之下,包含了许多对进程进行控制的脚本。这些脚本要么以 K## 开头,要么以 S## 开头:

    • K:kill,系统将终止对应的服务
    • S:start,系统将启动对应的服务
    • ##:同一运行级别下脚本执行的顺序,数值小的先执行,数值大的后执行。很多时候这些执行顺序是很重要的,比如要启动 Apache 服务,就必须先配置网络接口
  • init.d 文件夹下的脚本文件 test 格式如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/bin/bash

    case "$1" in
    start)
    echo "Starting myscript"
    # 执行你的启动代码
    ;;
    stop)
    echo "Stopping myscript"
    # 执行你的停止代码
    ;;
    *)
    echo "Usage: /etc/init.d/myscript {start|stop}"
    exit 1
    ;;
    esac

    exit 0

    在上述示例中,你需要将startstop函数中的代码替换为你自己的启动和停止代码。同时,确保修改脚本文件权限,使其可执行

  • 在 Ubuntu/debain 里,可以使用 update-rc.d 命令来把示例脚本安装到各个运行等级中(这里需要将对应脚本文件放到/etc/init.d目录下)

    1
    $ sudo update-rc.d test defaults 99

    update-rc.d 后面有三个参数,分别是/etc/init.d 下的脚本名字,默认安装方式,运行的优先级。优先级的数字越大,表示越迟运行,这里我们把自己写的服务放在最后运行

    如果上述代码不能生效,得手动在/etc/rc#.d(#表示对应的运行等级)目录下建立一个软链接,指向/etc/init.d目录下对应的脚本,命名格式是:开头必须大写 S(表示启动服务),后面跟的数字 99,是我们设定的启动序号,即优先级,后面名字无限定

    如果要卸载随机启动的服务,执行下面命令即可:

    1
    $ sudo update-rc.d -f test remove

    现在,当系统启动时,脚本将自动执行。你可以使用sudo service test start来手动启动它,使用sudo service test stop来停止它,使用sudo service test restart来重启它

四、systemd

4.1 使用 systemd 管理开机自启脚本

参考文章:

Systemctl 是一个 systemd 工具,主要负责控制 systemd 系统和服务管理器,systemd 即为 system daemon, 是 linux 下的一种 init 软件

Systemd 是一个系统管理守护进程、工具和库的集合,用于取代 System V 初始进程。Systemd 的功能是用于集中管理和配置类 UNIX 系统

在 Ubuntu 18.04 系统中,可以按照以下步骤使用 systemctl 设置开机自启动脚本:

  1. 创建一个启动脚本文件(例如 startup.sh)并编辑它:

    1
    $ vim /path/to/startup.sh

    在脚本文件中添加希望在开机时执行的命令或脚本

  2. 添加执行权限给脚本文件:

    1
    $ chmod +x /path/to/startup.sh
  3. 创建一个 systemd 服务单元文件(例如 myservice.service)并编辑它:

    1
    $ sudo nano /etc/systemd/system/myservice.service

    在服务单元文件中添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [Unit]
    Description=My Service
    After=network.target

    [Service]
    ExecStart=/path/to/startup.sh

    [Install]
    WantedBy=default.target

    举例(arp静态绑定):
    arpfixed.service

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [Unit]
    Description=ARP_Fixed Service
    After=network.target

    [Service]
    ExecStart=/home/project_public/arp_fixed.sh

    [Install]
    WantedBy=default.target

    /home/project_public/arp_fixed.sh脚本内容:

    1
    2
    3
    4
    #!/bin/bash
    sleep 120 # 延时2min
    # 绑定静态arp
    arp -s 192.168.1.81 90:2b:34:ab:00:01
  4. 保存并关闭服务单元文件

  5. 启用服务(设置开机自启动):

    1
    $ sudo systemctl enable myservice.service
  6. 重新加载 systemd 配置:

    1
    $ sudo systemctl daemon-reload

    做完以上步骤,当重启系统时,startup.sh 脚本将会自动执行

    • systemctl 常用命令
    1
    2
    3
    4
    5
    6
    7
    $ sudo systemctl reboot	# 重启系统
    $ sudo systemctl rescue # 进入救援模式(单用户状态)
    $ sudo systemctl start nginx # 开启 nginx 服务
    $ sudo systemctl restart nginx # 重启
    $ sudo systemctl stop nginx # 停止
    $ sudo systemctl reload nginx # 重新加载
    $ sudo systemctl status nginx # 查询状态

4.2 查看服务启动日志

参考文章:

journalctl 用来查询 systemd-journald 服务收集到的日志。systemd-journald 服务是 systemd init 系统提供的收集系统日志的服务

  • journalctl
1
$ journalctl -u 服务名
  • 系统日志
1
2
$ cat /var/log/message
$ cat /var/log/syslog
  • linux常用日志文件
1
2
3
4
5
6
7
8
/var/log/message 系统启动后的信息和错误日志,是 Red Hat Linux 中最常用的日志之一
/var/log/syslog 系统启动日志,Ubuntu 系统
/var/log/secure 与安全相关的日志信息
/var/log/maillog 与邮件相关的日志信息
/var/log/cron 与定时任务相关的日志信息
/var/log/spooler 与 UUCP 和 news 设备相关的日志信息
/var/log/boot.log 守护进程启动和停止相关的日志消息
/var/log/wtmp 该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件