Contents

在启动时运行Linux命令

1. 概述

在本教程中,我们将了解如何在 Linux 系统启动时运行命令或脚本。我们将介绍使用rc.local 文件、cron 作业和systemd 服务的不同方法。

2. 经典方法:rc.local文件

当我们启动一台运行 Linux 的机器时,第一个运行的进程是init 进程。init进程根据机器当前的状态运行某些脚本。这些状态称为运行级别。在每个运行级别期间,执行一系列*rc *脚本以使系统准备好使用或关闭。

rc.local脚本文件应该在大多数 UNIX 操作系统上可用。但是,**我们应该知道,在现代 Linux 发行版中,默认情况下它可能不可用。所以,我们必须手动配置它。 rc.local脚本将以系统管理员权限运行。**因此,以 root 身份运行脚本或命令会更容易。

2.1. 用法

让我们在系统启动后要执行的脚本中添加一个简单的命令:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Ensure that the script will "exit 0" on success or any other
# value on error.
#
# To enable or disable this script, just change the execution
# bits.
#
# By default, this script does nothing.
pgrep -x $(teamviewerd) || teamviewerd
exit 0

在脚本中,我们添加了一行以在系统启动后运行teamviewerd守护进程。请注意, exit 0之后的命令将不会执行。**有时,脚本中的命令即使正确也不会运行。在这种情况下,我们应该检查文件的执行权限并相应地修改它们。

2.2. 在现代 Linux 发行版上启用rc-local服务

大多数主流 Linux 发行版都使用systemd作为其初始化和服务管理器。** systemd有自己的方式在启动时执行自定义脚本。尽管如此,我们仍然可以创建一个简单的“rc-local” systemd进程,使我们能够在启动时运行rc.local脚本。**

在*/etc/systemd/system/rc-local.service*中新建一个文件,在文件中放入以下内容:

[Unit]
Description=/etc/rc.local Compatibility
ConditionPathExists=/etc/rc.local
[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99
[Install]
WantedBy=multi-user.target

保存文件后,我们应该使用systemctl 启用此服务:

$ systemctl enable rc.local

启用该服务后,我们需要创建rc.local文件并赋予它适当的权限

3.替代方案:Cron Job

crontab是一个文件,其中包含可以安排定期运行 的命令列表。我们在此文件中指定的任务是 cron 作业。通常,它们由安装在大多数发行版上的cron守护进程运行。

有不同的cron程序,它们都以相同的方式工作并使用类似的crontab格式。由我们选择一个并配置它。

3.1. 安装

如果服务器运行的是 Gentoo 等发行版,**可能会出现我们没有在服务器上安装cron程序的情况。**因此,我们需要手动安装和配置它。我们将安装称为cronie的轻量级cron实用程序。它可以在大多数存储库中以名称cronie获得,我们可以使用包管理器 安装它。

在 Ubuntu 和 Debian 上,我们可以使用apt

# apt install cronie

对于 Fedora 和 RHEL,我们可以使用yum

# yum install cronie

安装完成后,继续并验证它:

$ crond -V
cronie 1.5.7

现在,我们需要启用crond 服务,它基本上是系统启动时将运行的守护进程:

# systemctl enable crond

现在,我们已准备好在crontab中安排 cron 作业。

3.2. 用法

**一个简单的crontab可以由一行或多行组成。每行对应一个定期执行的任务。**让我们使用crontab命令创建一个crontab

$ crontab -e

首先,它应该是一个空文件。让我们添加几个任务,每次系统启动时都会运行这些任务:

@reboot pulseaudio -k && pulseaudio
@reboot redshift -c ~/.config/redshift/config.conf

**一个crontab条目由两个字段组成——时间字段和命令字段。时间字段指定何时运行相应的命令。在这个 crontab中,我们添加了@reboot,这表示我们要在系统启动后运行命令。

我们应该知道,上述命令将以普通用户身份执行。** -e选项告诉 crontab 编辑当前用户的crontab。**如果我们想以root 身份运行命令,我们应该以root 身份运行crontab命令,这将为root用户创建另一个crontab文件。

让我们创建一个在启动时以root身份执行 shell 脚本的任务:

$ sudo crontab -e
@reboot . /root/upgrade-system.sh

4.备选方案:systemd

systemd不仅仅是一个服务管理器和一个初始化系统,而是一个完整的实用程序集合,可以在 Linux 发行版上执行大部分任务。

systemd之前,我们需要针对不同的目的使用不同的工具,在某些情况下,这些工具不如systemd有效。如今,systemd已成为每个流行的 Linux 发行版的一部分,例如 Fedora、Ubuntu、Mint、Debian 等。因此,我们应该使用它而不是依赖外部工具。

4.1. 创建启动脚本

首先,我们需要一个脚本文件,其中包含我们希望在启动时运行的命令。稍后,我们将指定此文件在自定义systemd服务中运行。因此,让我们创建一个基本上启动通知守护程序的脚本文件:

pgrep dunst || setsid -f dunst

确保使该脚本可执行。

4.2. 创建system服务

现在我们的脚本已经准备就绪,我们需要创建一个system服务来获取我们的脚本文件。因此,让我们继续在*/lib/systemd/system中创建一个startup.service*文件:

$ touch /lib/systemd/system/startup.service

现在,让我们在这个文件中定义我们的服务:

[Unit]
Description=Startup Script
[Service]
ExecStart=/root/.local/bin/startup.sh
[Install]
WantedBy=multi-user.target

**我们可以修改ExecStart字段来指定我们的启动脚本的路径。**完成后,保存文件并启用此服务,这样它就会在我们的机器每次启动时运行:

# systemctl enable startup.service --now

systemd将启用此服务并立即运行它,因为我们添加了*–now*选项。

同样,我们可以创建多个服务以在启动时运行以用于不同的目的。