惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
C
Cybersecurity and Infrastructure Security Agency CISA
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Know Your Adversary
Know Your Adversary
S
Securelist
I
Intezer
AWS News Blog
AWS News Blog
L
LINUX DO - 热门话题
P
Privacy International News Feed
Recent Announcements
Recent Announcements
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 聂微东
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
The GitHub Blog
The GitHub Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Schneier on Security
Schneier on Security
N
Netflix TechBlog - Medium
爱范儿
爱范儿
B
Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CERT Recently Published Vulnerability Notes
Hacker News: Ask HN
Hacker News: Ask HN
Google DeepMind News
Google DeepMind News
Engineering at Meta
Engineering at Meta
Blog — PlanetScale
Blog — PlanetScale
WordPress大学
WordPress大学
S
Secure Thoughts
K
Kaspersky official blog
N
News | PayPal Newsroom
O
OpenAI News
Last Week in AI
Last Week in AI
C
Check Point Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cyberwarzone
Cyberwarzone
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tor Project blog
大猫的无限游戏
大猫的无限游戏
Vercel News
Vercel News
D
Docker
Hugging Face - Blog
Hugging Face - Blog
T
Threat Research - Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
The Register - Security
The Register - Security
博客园 - 司徒正美
Martin Fowler
Martin Fowler
人人都是产品经理
人人都是产品经理
P
Palo Alto Networks Blog

Hyde Blog

Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog 关于我 关于我 Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog
Hyde Blog
Hyde · 2025-10-05 · via Hyde Blog

开机自启 ​

在工作中,我们经常有个需求,那就是在系统启动之后,自动启动某个脚本或服务。在 Windows 下,我们有很多方法可以设置开机启动,但在 Linux 系统下我们需要如何操作呢?

Linux 下同样可以设置开机启动,但可能需要我们敲一些命令(可能也有 UI 界面的设置方法,但我不熟,我更多是玩命令)。下面我们就介绍三种简单但可行的开机启动设置方法。

版权声明 ​

警告

本教程参考了One作者的教程,并结合自身实际部署过程中积累的经验编写而成。原始教程链接为Linux 系统设置开机自动运行脚本的方法),感谢原作者提供的宝贵参考资料。

本教程仅供学习和交流使用,任何人不得将本教程的内容用于商业用途。如需引用或转载,请务必注明原作者及本文出处。如侵权之处,请联系博主进行删除,谢谢~

部分内容引用One大佬的教程,感谢大佬的贡献。

方法一:修改 /etc/rc.d/rc.local 文件 ​

/etc/rc.d/rc.local 文件会在 Linux 系统各项服务都启动完毕之后再被运行。所以你想要自己的脚本在开机后被运行的话,可以将自己脚本路径加到该文件里。

提示

这种方法,在任何 Linux 系统上都可以使用。

  • 环境:

CentOS Linux 7.9 (2009) (Core)

  • 我们先来查看下这个文件的内容是什么

bash

cat  /etc/rc.d/rc.local

输出:

bash

#!/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.

#创建一个空文件 /var/lock/subsys/local,该文件的存在通常用来指示某个服务或任务已经成功运行
#这是旧版 Linux 系统中的一种惯例,但在现代系统中,它的作用已经非常有限。
touch /var/lock/subsys/local

这个脚本是位于 /etc/rc.d/rc.local 的示例文件,主要用于兼容性目的,特别是在 CentOS 7 中。/etc/rc.d/rc.local 是传统的启动脚本文件,允许用户在系统启动时执行自定义的脚本或命令,因此可以往里写开机要执行的命令或脚本。

警告

/etc/rc.local/etc/rc.d/rc.local的软链

  • 可执行权限: 要确保这个脚本在系统启动时被执行,需要给脚本添加可执行权限:

bash

chmod +x /etc/rc.d/rc.local

演示 ​

  • 首先,在根目录目录或指定的位置创建一个脚本文件,例如 /blog/start_all_containers.sh

bash

vim /blog/start_all_containers.sh
  • 添加脚本内容

bash

#!/bin/bash

# 定义一个函数来启动所有未运行的Docker容器
start_stopped_containers() {
    # 查找所有未运行的容器
    stopped_containers=$(docker ps -a -f "status=exited" -q)
    
    # 如果有未运行的容器,启动它们
    if [ ! -z "$stopped_containers" ]; then
        echo "启动所有未运行的Docker容器..."
        docker start $stopped_containers
    else
        echo "没有未运行的Docker容器需要启动。"
    fi
}

# 调用函数
start_stopped_containers
  • 保存退出后,确保文件有执行权限

bash

chmod +x /blog/start_all_containers.sh
  • 然后,我们再将脚本添加到 /etc/rc.d/rc.local 文件最后一行:

bash

vim /etc/rc.d/rc.local

bash

/blog/start_all_containers.sh

添加后的内容:

tsx

#!/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.

touch /var/lock/subsys/local

#这里添加刚刚在/blog文件夹下创建的"start_all_containers.sh"脚本
// highlight-next-line
/blog/start_all_containers.sh
  • 直接重启系统验证测试:

可以看到开机自启动所有未运行的Docker容器,输出如下:

bash

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                                                      COMMAND                   CREATED        STATUS              PORTS                                                                                                                                      NAMES
ba8627412252   ruyu-blog-hd                                               "java -jar /app/app.…"   37 hours ago   Up About a minute   0.0.0.0:8088->8088/tcp, :::8088->8088/tcp                                                                                                  ruyu-blog-hd
115838d43850   blog-ht                                                    "/docker-entrypoint.…"   2 days ago     Up About a minute   80/tcp, 0.0.0.0:81->81/tcp, :::81->81/tcp                                                                                                  blog-ht
3334358ca32b   blog-qt                                                    "/docker-entrypoint.…"   2 days ago     Up About a minute   0.0.0.0:80->80/tcp, :::80->80/tcp                                                                                                          blog-qt
d14e0fc37e68   filesite/machete                                           "/var/www/machete/do…"   2 days ago     Up About a minute   0.0.0.0:445->445/tcp, :::445->445/tcp, 9000/tcp, 0.0.0.0:1081->80/tcp, :::1081->80/tcp                                                     machete
19abde9750b1   registry.cn-shenzhen.aliyuncs.com/mogublog_business/frpc   "/bin/sh -c '/usr/bi…"   2 days ago     Up About a minute                                                                                                                                              frpc
e9f405df3cfe   binaryify/netease_cloud_music_api                          "docker-entrypoint.s…"   4 days ago     Up About a minute   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp                                                                                                  netease_cloud_music_api
de384f1f541f   hitokoto/api                                               "docker-entrypoint.s…"   4 days ago     Up About a minute   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp                                                                                                  hitokoto_hitokoto_api_1
86e5cf8d6306   redis:6.0.8                                                "docker-entrypoint.s…"   4 days ago     Up About a minute   6379/tcp                                                                                                                                   hitokoto_hitokoto_db_1
6726bc097856   minio/minio                                                "/usr/bin/docker-ent…"   4 days ago     Up About a minute   0.0.0.0:9000-9001->9000-9001/tcp, :::9000-9001->9000-9001/tcp                                                                              minio
d2c98432baa2   rabbitmq                                                   "docker-entrypoint.s…"   4 days ago     Up About a minute   4369/tcp, 0.0.0.0:5672->5672/tcp, :::5672->5672/tcp, 5671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp   rabbit
61da49911e67   redis:7.2.3                                                "docker-entrypoint.s…"   4 days ago     Up About a minute   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp                                                                                                  redis
ec44863c383e   mysql:8.0                                                  "docker-entrypoint.s…"   5 days ago     Up About a minute   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp                                                                                       mysql

完成这些步骤后,脚本将在系统启动时自动运行,并尝试启动所有未运行的 Docker 容器。

  • 有关 /etc/rc.d/rc.local 执行时机如下:

image-20220625120119559

方法二:使用 crontab ​

提示

这种方法,在任何 Linux 系统上都可以使用。

  • 环境:

CentOS Linux 7.9 (2009) (Core)

crontab 是 Linux 下的计划任务,当时间达到我们设定的时间时,可以自动触发某些脚本的运行。

我们可以自己设置计划任务时间,然后编写对应的脚本。但是,有个特殊的任务,叫作 @reboot ,我们其实也可以直接从它的字面意义看出来,这个任务就是在系统重启之后自动运行某个脚本。

演示 ​

下面是如何使用 crontab 来创建一个任务,以便定期启动所有未运行的 Docker 容器。

  1. 编写脚本

创建一个脚本文件,例如 /blog/start_stopped_docker_containers.sh

bash

vim /blog/start_stopped_docker_containers.sh

并添加启动未运行的 Docker 容器的内容:

bash

#!/bin/bash

# 定义一个函数来启动所有未运行的Docker容器
start_stopped_containers() {
    # 查找所有未运行的容器
    stopped_containers=$(docker ps -a -f "status=exited" -q)
    
    # 如果有未运行的容器,启动它们
    if [ ! -z "$stopped_containers" ]; then
        echo "启动所有未运行的Docker容器..."
        docker start $stopped_containers
    else
        echo "没有未运行的Docker容器需要启动。"
    fi
}

# 调用函数
start_stopped_containers
  • 保存退出后,确保文件有执行权限

bash

chmod +x /blog/start_stopped_docker_containers.sh
  1. 编辑 crontab

使用 crontab -e 打开 crontab 编辑器,然后添加以下行:

在打开的编辑器中,添加以下行在每次系统启动时,执行 /blog/start_stopped_docker_containers.sh 脚本

bash

@reboot /blog/start_stopped_docker_containers.sh
  • 然后,直接重启即可。运行的效果跟上面类似。

方法三:使用-systemd-服务(推荐) ​

  • 环境:

CentOS Linux 7.9 (2009) (Core)

警告

  • 次方法仅适用于 systemd 系统。如何区分是不是 systemd 系统?很简单,只需运行 ps aux|more 命令,查看 pid1 的进程是不是 systemd

ps aux|more 命令输出:

bash

[root@localhost ~]# ps aux|more
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.3  0.1 194092  7156 ?        Ss   21:54   0:04 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root          2  0.0  0.0      0     0 ?        S    21:54   0:00 [kthreadd]
root          4  0.0  0.0      0     0 ?        S<   21:54   0:00 [kworker/0:0H]
root          6  0.0  0.0      0     0 ?        S    21:54   0:00 [ksoftirqd/0]
root          7  0.0  0.0      0     0 ?        S    21:54   0:00 [migration/0]
root          8  0.0  0.0      0     0 ?        S    21:54   0:00 [rcu_bh]
root          9  0.7  0.0      0     0 ?        S    21:54   0:12 [rcu_sched]

演示 ​

使用 systemd 创建一个服务来在系统启动时运行脚本是一种更现代和灵活的方法。以下是如何创建一个 systemd 服务来启动未运行的 Docker 容器的步骤。

  1. 创建脚本

创建一个 systemd 启动服务单元文件

bash

vim /blog/start_stopped_docker_containers.sh

例如,你的脚本路径为 /blog/start_stopped_docker_containers.sh 添加以下内容:

bash

#!/bin/bash

# 定义一个函数来启动所有未运行的Docker容器
start_stopped_containers() {
    # 查找所有未运行的容器
    stopped_containers=$(docker ps -a -f "status=exited" -q)
    
    # 如果有未运行的容器,启动它们
    if [ ! -z "$stopped_containers" ]; then
        echo "启动所有未运行的Docker容器..."
        docker start $stopped_containers
    else
        echo "没有未运行的Docker容器需要启动。"
    fi
}

# 调用函数
start_stopped_containers

保存退出后,确保脚本具有执行权限:

bash

sudo chmod +x /blog/start_stopped_docker_containers.sh
  1. 创建 systemd 服务文件

警告

请注意,这时后缀是 .service ,而不是 .sh

bash

vim /etc/systemd/system/start-docker-containers.service

创建一个 systemd 服务单元文件,例如 /etc/systemd/system/start-docker-containers.service,并添加以下内容:

bash

[Unit]
Description=Start stopped Docker containers
After=network.target docker.service

[Service]
ExecStart=/blog/start_stopped_docker_containers.sh
Type=oneshot
RemainAfterExit=true

[Install]
WantedBy=multi-user.target

解释:

  • [Unit] 部分定义了服务的描述和依赖。After=network.target docker.service 表示该服务在网络和 Docker 服务启动后运行。
  • [Service] 部分定义了服务的执行方式。ExecStart 指定了要运行的脚本。Type=oneshot 表示脚本运行一次即完成。RemainAfterExit=true 确保服务在脚本执行后仍然处于活动状态。
  • [Install] 部分定义了服务的安装目标,WantedBy=multi-user.target 表示服务在多用户运行级别启动时启动。
  1. 重新加载 systemd 配置

在创建或修改服务文件后,重新加载 systemd 配置以使更改生效:

bash

sudo systemctl daemon-reload
  1. 启用并启动服务

启用服务,使其在每次系统启动时自动运行:

bash

sudo systemctl enable start-docker-containers.service

立即启动服务以测试它是否正常工作:

bash

sudo systemctl start start-docker-containers.service
  1. 检查服务状态

检查服务状态以确保它正在运行:

sudo systemctl status start-docker-containers.service

可以看到服务的当前状态以及最近的日志输出:

[root@localhost ~]# sudo systemctl status start-docker-containers.service
● start-docker-containers.service - Start stopped Docker containers
   Loaded: loaded (/etc/systemd/system/start-docker-containers.service; enabled; vendor preset: disabled)
   Active: active (exited) since 五 2024-09-06 23:35:42 PDT; 7s ago
  Process: 130731 ExecStart=/bin/bash /blog/start_stopped_docker_containers.sh (code=exited, status=0/SUCCESS)
 Main PID: 130731 (code=exited, status=0/SUCCESS)

9月 06 23:35:42 localhost.localdomain systemd[1]: Starting Start stopped Docker containers...
9月 06 23:35:42 localhost.localdomain bash[130731]: 没有未运行的Docker容器需要启动。
9月 06 23:35:42 localhost.localdomain systemd[1]: Started Start stopped Docker containers.

通过这些步骤,你将成功创建一个 systemd 服务,该服务在每次系统启动时运行脚本,以启动所有未运行的 Docker 容器。

方法四:/etc/rc.d/init.d目录

演示 ​

  1. 创建启动脚本

    /etc/rc.d/init.d 目录下创建一个新的启动脚本,例如 start-docker-containers

    bash

    vim /etc/rc.d/init.d/start-docker-containers.sh
  2. 编写脚本内容

    在脚本中添加以下内容:

    bash

    #!/bin/bash
    # chkconfig: 2345 99 01
    # description: Start stopped Docker containers
    
    ### BEGIN INIT INFO
    # Provides:          start-docker-containers
    # Required-Start:    $network $local_fs $remote_fs $docker
    # Required-Stop:     $network $local_fs $remote_fs
    # Default-Start:     3 4 5
    # Default-Stop:      0 1 2 6
    # Short-Description: Start stopped Docker containers at boot time
    # Description:       Starts all stopped Docker containers.
    ### END INIT INFO
    
    case "$1" in
        start)
            echo "Starting stopped Docker containers..."
         	#确保路径有这个文件   
            /usr/local/bin/start_stopped_docker_containers.sh
            ;;
        stop)
            echo "Stopping Docker containers (not implemented)..."
            ;;
        restart)
            echo "Restarting Docker containers (not implemented)..."
            ;;
        status)
            echo "Status of Docker containers (not implemented)..."
            ;;
        *)
            echo "Usage: $0 {start|stop|restart|status}"
            exit 1
            ;;
    esac
    
    exit 0

    解释:

    • chkconfig 行用于设置运行级别。
    • ### BEGIN INIT INFO### END INIT INFO 块提供了有关脚本的信息。
    • case "$1" 部分处理 start, stop, restart, 和 status 参数。
  3. 赋予脚本可执行权限

    使脚本可执行:

    bash

    sudo chmod +x /etc/rc.d/init.d/start-docker-containers.sh
  4. 设置脚本开机自启

    使用 chkconfig 工具来确保脚本在系统启动时运行(适用于基于 SysVinit 的系统):

    bash

    sudo chkconfig --add start-docker-containers.sh

    然后,确保脚本在所需的运行级别中启动(通常是 3, 4, 5):

    bash

    sudo chkconfig start-docker-containers.sh on
  5. /usr/local/bin目录下创建start_stopped_docker_containers.sh脚本

    vim /usr/local/bin/start_stopped_docker_containers.sh
  6. 编写脚本内容

    在脚本中添加以下内容:

    bash

    #!/bin/bash
    
    # 定义日志文件
    LOGFILE="/var/log/start_docker_containers.log"
    
    # 写入开始时间
    echo "Starting stopped Docker containers at $(date)" >> $LOGFILE
    
    # 获取所有停止的 Docker 容器
    stopped_containers=$(docker ps -a -q -f "status=exited")
    
    # 检查是否有停止的容器
    if [ -z "$stopped_containers" ]; then
      echo "No stopped Docker containers to start." >> $LOGFILE
    else
      # 启动每一个停止的容器
      for container in $stopped_containers; do
        echo "Starting container $container" >> $LOGFILE
        docker start $container >> $LOGFILE 2>&1
      done
    fi
    
    # 写入结束时间
    echo "Finished starting Docker containers at $(date)" >> $LOGFILE
  7. 赋予脚本可执行权限

    使脚本可执行:

    bash

    sudo chmod +x /usr/local/bin/start_stopped_docker_containers.sh
  8. 手动测试脚本

    你可以手动启动脚本来测试其是否工作正常:

    bash

    sudo /etc/rc.d/init.d/start-docker-containers.sh start
    
    输出:
    [root@localhost ~]# sudo /etc/rc.d/init.d/start-docker-containers.sh start
    Starting stopped Docker containers...

解释

  • 脚本内容:脚本用于在启动时执行 Docker 容器启动操作。
  • chkconfig 工具:用于管理系统服务的开机启动。
  • SysVinit:传统的初始化系统,通常在老旧系统中使用。

如果你的系统使用 systemd,建议优先使用 systemd 服务单元文件,因为 systemd 提供了更强大的服务管理功能。如果你的系统确实使用 SysVinit,这些步骤应该可以帮助你设置服务。