04 VIM 编辑器与 Shell 命令脚本
- 介绍如何使用 VIM 编辑器来编写和修改文档,然后通过逐步配置主机名称、系统网卡以及软件仓库等文件,帮助大家加深 VIM 编辑器中诸多命令、快捷键与模式的理解。
- 在 Shell 脚本中以多种方式接收用户输入的信息,能够对输入值进行文件、数字、字符串的判断比较。在熟练使用“与、或、非”三种逻辑操作符的基础上,大家还要充分学习
if、for、while、case条件测试语句,并通过 10 多个实战脚本的实操练习,达到在工作中灵活运用的水准。 - 通过实战的方式演示了使用
at命令与crond计划任务服务来分别实现一次性的系统任务设置和长期性的系统任务设置,在分钟、小时、日期、月份、年份的基础上实现工作的自动化,从而让日常的工作更加高效。
VIM 文本编辑器
- VIM 的发布:VIM 的发布最早可以追溯到 1991 年,英文全称为 Vi Improved。它也是 Vi 编辑器的提升版本,其中最大的改进当属添加了代码着色功能,在某些编程场景下还能自动修正错误代码。
Vi基于一个名为Ex的行编辑器。Vi和Ex都是由 Bill Joy 开发的。 - 文本编辑器:在 Linux 系统中一切都是文件,而配置一个服务就是在修改其配置文件的参数。而且在日常工作中大家也肯定免不了要编写文档,这些工作都是通过文本编辑器来完成的。
- 目的:让读者切实掌握 Linux 系统的运维方法,而不是仅仅停留在“会用某个操作系统”的层面上,我们这里选择使用 VIM 文本编辑器,它默认会安装在当前所有的 Linux 操作系统上,是一款超棒的文本编辑器。
VIM 编辑器的 3 种模式
- 命令模式:控制光标移动,可对文本进行复制、粘贴、删除和查找等工作。
普通模式(Normal Mode)。这个命令在文档中是这样的::h Normal,:h mode-switching。 - 输入模式:正常的文本录入。
插入模式(Insert Mode)。这个命令在文档中是这样的::h Insert,:h i_<Esc>,:h o,:h O,:h a,:h A,:h I。 - 末行模式:保存或退出文档,以及设置编辑环境。
命令行模式(Command-line Mode)。这个命令在文档中是这样的::h Command-line、:h cmdline-lines。
- 在每次运行 VIM 编辑器时,默认进入命令模式,此时需要先切换到输入模式后再进行文档编写工作。
- 每次在编写完文档后需要先返回命令模式,然后再进入末行模式,执行文档的保存或退出操作。
- 在 VIM 中,无法直接从输入模式切换到末行模式。
命令模式中的命令
技巧
所有的命令都需要在 Normal 模式下使用,如果你不知道现在在什么样的模式,你就狂按几次 ESC 键。
命令模式中最常用的一些命令:
| 命令 | 作用 |
|---|---|
i | 在光标所在位置插入文本,即输入模式。按 ESC 键回到 Normal 模式 |
x | 删除当前光标所在的一个字符。 |
dd | 删除(剪切)光标所在整行,并把删除的行存到剪贴板里 |
p | 将之前删除(dd)或复制(yy)过的数据粘贴到光标后面 |
5dd | 删除(剪切)从光标处开始的 5 行 |
yy | 复制光标所在整行 |
5yy | 复制从光标处开始的 5 行 |
n | 显示搜索命令定位到的下一个字符串 |
N | 显示搜索命令定位到的上一个字符串 |
u | 撤销上一步的操作 |
hjkl | 光标左下上右移动 (也可以使用光标键 ←↓↑→) |
:help <command> | 查看某个命令的帮助文档,例如::help dd,:help yy,:help p(退出帮助需要输入 :q) |
各种插入模式
| 命令 | 作用 |
|---|---|
i | 在光标所在位置插入文本,即输入模式。按 ESC 键回到 Normal 模式 |
o | 在当前行后插入一个新行 |
O | 在当前行前插入一个新行 |
a | 在光标后插入 |
cw | 替换从光标所在位置后到一个单词结尾的字符 |
移动光标
| 命令 | 作用 |
|---|---|
hjkl | 光标左下上右移动 (也可以使用光标键 ←↓↑→) |
0 | 数字零,到行头 |
^ | 到本行第一个不是 blank 字符的位置(所谓 blank 字符就是空格,tab,换行,回车等) |
$ | 到本行行尾 |
g_ | 到本行最后一个不是 blank 字符的位置 |
/pattern | 搜索 pattern 的字符串(如果搜索出多个匹配,可按 n 键到下一个) |
NG | 到第 N 行(例如 10G 到第 10 行) |
gg | 到文档头部 |
G | 到文档尾部 |
w | 光标跳到下一个单词的开头 (词是由 blank 字符分隔符,那么你需要使用大写的 W) |
e | 光标跳到下一个单词的结尾 (词是由 blank 字符分隔符,那么你需要使用大写的 E) |
% | 匹配括号移动,包括 (,{,[ (你需要把光标先移到括号上) |
* | 匹配光标当前所在的单词,并高亮显示其他相同单词,可按 n 键到下一个 |
# | 匹配光标当前所在的单词,并高亮显示其他相同单词,可按 N 键到上一个 |
fx | 查找光标后第一个为 x 的字符,并把光标移动到该位置 |
tx | 查找光标后第一个为 x 的字符,并把光标移动到该位置的前一个字符 |
Nfx | 查找光标后第 N 个为 x 的字符,并把光标移动到该位置 |
Fx | 查找光标前第一个为 x 的字符,并把光标移动到该位置 |
Tx | 查找光标前第一个为 x 的字符,并把光标移动到该位置的后一个字符 |
删除
| 命令 | 作用 |
|---|---|
x | 删除当前光标所在的一个字符 |
dd | 删除(剪切)光标所在整行,并把删除的行存到剪贴板里 |
5dd | 删除(剪切)从光标处开始的 5 行 |
dw | 删除一个单词(不包括空格) |
d$ | 删除光标后至行尾的内容 |
d^ | 删除光标前至行首的内容 |
dG | 删除光标所在行至文档末尾的内容 |
d1G | 删除光标所在行至文档开头的内容 |
d/pattern | 删除从光标所在行开始到匹配 pattern 为止的内容 |
拷贝粘贴
| 命令 | 作用 |
|---|---|
p | 在当前位置之后粘贴 |
P | 在当前位置之前粘贴 |
yy | 拷贝当前行,相当于 ddP |
撤销恢复
| 命令 | 作用 |
|---|---|
u | 撤销上一步的操作,undo |
Ctrl + r | 恢复上一步的操作,redo |
末行模式中的命令
末行模式主要用于保存或退出文件,以及设置 VIM 编辑器的工作环境,还可以让用户执行外部的 Linux 命令或跳转到所编写文档的特定行数。要想切换到末行模式,在命令模式中输入一个冒号就可以了。
末行模式中最常用的一些命令:
| 命令 | 作用 |
|---|---|
:e <文件名> | 打开一个文件 |
:w | 保存 (:w 后可以跟文件名) |
:q | 退出 |
:q! (ZQ) | 强制退出(放弃对文档的修改内容) |
:wq 或 :x (ZZ) | 保存并退出 |
:wq! | 强制保存退出 |
:saveas <文件名> | 另存为 |
:set nu | 显示行号 |
:set nonu | 不显示行号 |
:命令 | 执行该命令 |
:整数 | 跳转到该行 |
:s/one/two | 将当前光标所在行的第一个 one 替换成 two |
:s/one/two/g | 将当前光标所在行的所有 one 替换成 two |
:%s/one/two/g | 将全文中的所有 one 替换成 two |
?字符串 | 在文本中从下至上搜索该字符串 |
/字符串 | 在文本中从上至下搜索该字符串 |
:bn | 下一个文件 (同时打开很多文件) |
:bp | 上一个文件 (同时打开很多文件) |
注意
- 以
:开始的命令你需要输入<enter>回车,例如:q也就是说你要输入:q<enter>.
:x Vs :wq
:x是另一个与:wq几乎相同的命令。根据:h:x,它是“类似于:wq,但只在做出更改时写入”。- 这里的区别在于,无论你是否对其进行了更改,
:wq将保存文件。如果你没有做任何更改,:x将不会保存文件。这里重要的是文件的修改时间,因为:wq会更新修改时间,而:x不会。
ZZ & ZQ
- 在
Normal Mode下,你也可以按ZZ或ZQ来退出 VIM。其中中ZZ与:x相同,ZQ与:q!相同。 ZZ和ZQ被认为是Normal Mode正常/命令模式 的命令,而:x和:q!是 Ex 末行/命令行模式 的命令。
如果 :wq 失败了怎么办
这是可能的,因为当文件是只读的或者文件名丢失时,:wq 可能会失败。
请注意,当一个文件是只读的,VIM 不会阻止你打开和编辑该文件。你可能也会发现 :wq! 在那个时候也不能工作。你可能最终会放弃所有用 :q! 进行的修改,然后打开同一文件,以 sudo 为前缀,再做一次同样的修改。
解决方案 1:
- 把这个文件保存在另一个你有写权限的目录下,比如
~或者甚至是/tmp,然后把它移回你没有写入权限的目录。 - 为了实现这一点,你可以运行
:w ~/my-backup-file,这将把该文件保存在~下 - 接下来,你可以使用
mv命令移动这个文件。还要注意,当 VIM 抱怨文件名丢失时,你需要这样做。。
- 把这个文件保存在另一个你有写权限的目录下,比如
解决方案 2:
使用命令:
:w !sudo tee %。这意味着我们从 shell 环境中使用sudo命令,从 VIM 复制当前文件(注意:修改过的版本)的内容,并将修改过的内容重定向到文件(通过使用文件名引用)。。!sudo表示在 shell 环境中运行 sudo 命令。例如,:ls将列出 VIM 中的所有缓冲区,但是是:!ls将从 shell 运行ls命令并显示结果。tee从标准输入(又名stdin)复制到标准输出(又名stdout)。%为当前文件名。
上面命令会引发下图的警告。发生警告是因为在 shell 环境中更新了文件内容而没有引起 VIM 的注意。所以 VIM 认为这是一个外部变化,并让你知道发生了什么。此时只需按
Enter,因为你是有意进行外部更改的。
你可能还会注意到,修改后的文件内容也显示在警告消息的上方。这是意料之中的,因为它来自标准输出
stdout。如果你不想看到它,你可以执行:w !sudo tee% >/dev/null,这将丢弃来自tee的stdout。
需要强制退出 VIM
如果我们尝试按
Ctrl + c退出,VIM 会显示下图信息。但你仍然可以通过按按Ctrl + Alt + Delete来解决这个问题。
下一次,当你试图再次打开同一个文件时,你应该看到这个(这里我用一个名为
foo.txt的文件作为例子)。
此时 VIM 正试图帮助你恢复你可能丢失的宝贵修改。通过检查该目录,你会发现一个扩展名为
.swp的文件。这是一个swap文件(文档::h swap-file)。如果我们按
R键恢复,我们将看到以下情况:
按
Enter键后,现在你会发现你之前所做的修改又回来了。在你完成恢复过程后,你可以简单地删除.swp文件,这样你就不会再看到上面的错误。
编写简单文档

步骤详细说明
打开 practice.txt 文档后,默认进入的是 Vim 编辑器的命令模式。此时只能执行该模式下的命令,而不能随意输入文本内容,我们需要切换到输入模式才可以编写文档。
可以分别使用
a、i、o三个键从命令模式切换到输入模式。a键是在光标后面一位切换到输入模式i键是在光标当前位置切换到输入模式o键则是在光标的下面再创建一个空行
进入输入模式后,可以随意输入文本内容,Vim 编辑器不会把您输入的文本内容当作命令而执行。

步骤详细说明
- 在编写完之后,要想保存并退出,必须先敲击键盘的
Esc键从输入模式返回命令模式。 - 在末行模式中输入
:wq!命令时,就意味着强制保存并退出文档。然后便可以用cat命令查看保存后的文档内容了。


步骤详细说明
- 在原有 practice.txt 文档的下面追加内容,所以在命令模式中敲击
o键进入输入模式更会高效。 - 在编写完之后,想不保存直接退出,必须先敲击键盘的
Esc键从输入模式返回命令模式。 - 在末行模式中输入
:q!命令时,就意味着不保存直接退出文档。然后便可以用cat命令查看保存后的文档内容了。

$ vim practice.txt
$ cat practice.txt
You can write in it.
$ vim practice.txt
$ cat -n practice.txt
1 You can write in it.
$配置主机名称
- 第 1 步:使用 VIM 编辑器修改
/etc/hostname主机名称文件。 - 第 2 步:把原始主机名称删除后追加
linuxprobe.com。注意,使用 VIM 编辑器修改主机名称文件后,要在末行模式下执行:wq!命令才能保存并退出文档。 - 第 3 步:保存并退出文档,然后使用
hostname命令检查是否修改成功。
INFO
hostname 命令用于查看当前的主机名称,但有时主机名称的改变不会立即同步到系统中,所以如果发现修改完成后还显示原来的主机名称,可重启虚拟机后再行查看。
[linuxprobe@linuxprobe ~]$ cat /etc/hostname
linuxprobe.com
[linuxprobe@linuxprobe ~]$ hostname
linuxprobe.com
[linuxprobe@linuxprobe ~]$配置网卡信息
- 第 1 步:首先切换到
/etc/sysconfig/network-scripts目录中(存放着网卡的配置文件)。 - 第 2 步:使用 VIM 编辑器修改网卡文件
ifcfg-ens160,逐项写入下面的配置参数并保存退出。由于每台设备的硬件及架构是不一样的,因此请读者使用ifconfig命令自行确认各自网卡的默认名称。- 设备类型:
TYPE=Ethernet - 地址分配模式:
BOOTPROTO=static - 网卡名称:
NAME=ens160 - 是否启动:
ONBOOT=yes - IP 地址:
IPADDR=192.168.10.10 - 子网掩码:
NETMASK=255.255.255.0 - 网关地址:
GATEWAY=192.168.10.1 - DNS 地址:
DNS1=192.168.10.1
- 设备类型:
- 第 3 步:重启网络服务并测试网络是否连通。
INFO
由于在 Linux 系统中 ping 命令不会自动终止,因此需要手动按下 Ctrl + C 组合键来强行结束进程。
实验代码
[linuxprobe@linuxprobe ~]$ su - root
Password:
[root@linuxprobe ~]# cd /etc/sysconfig/network-scripts/
[root@linuxprobe network-scripts]# vim ifcfg-ens160
[root@linuxprobe network-scripts]# cat -n ifcfg-ens160
1 TYPE=Ethernet
2 PROXY_METHOD=none
3 BROWSER_ONLY=no
4 BOOTPROTO=static
5 DEFROUTE=yes
6 IPV4_FAILURE_FATAL=no
7 IPV6INIT=no
8 IPV6_AUTOCONF=yes
9 IPV6_DEFROUTE=yes
10 IPV6_FAILURE_FATAL=no
11 IPV6_ADDR_GEN_MODE=stable-privacy
12 NAME=ens160
13 UUID=2690b476-f0fe-4106-b694-1905067dc9f5
14 DEVICE=ens160
15 ONBOOT=yes
16 HWADDR=00:0C:29:99:F4:B2
17 IPADDR=192.168.0.131
18 NERMASK=255.255.255.0
19 GATEWAY=192.168.0.1
20 DNS1=223.5.5.5
21 DNS2=223.6.6.6
22 PREFIX=24
23 PEERROUTES=no
[root@linuxprobe network-scripts]# nmcli connection reload ens160 # 重启网卡设备
[root@linuxprobe network-scripts]# ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=2.19 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=2.10 ms
64 bytes from 192.168.0.1: icmp_seq=3 ttl=64 time=1.49 ms
64 bytes from 192.168.0.1: icmp_seq=4 ttl=64 time=5.13 ms
64 bytes from 192.168.0.1: icmp_seq=5 ttl=64 time=2.60 ms
^C
--- 192.168.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 11ms
rtt min/avg/max/mdev = 1.485/2.699/5.125/1.265 ms配置软件仓库
- 第 1 步:进入
/etc/yum.repos.d/目录中(因为该目录存放着软件仓库的配置文件)。 - 第 2 步:使用 VIM 编辑器创建一个名为
rhel8.repo的新配置文件(文件名称可随意,但后缀必须为.repo),逐项写入下面的配置参数并保存退出。- 仓库名称:具有唯一性的标识名称,不应与其他软件仓库发生冲突。
- 描述信息(name):可以是一些介绍性的词,易于识别软件仓库的用处。
- 仓库位置(baseurl):软件包的获取方式,可以使用 FTP 或 HTTP 下载,也可以是本地的文件(需要在后面添加
file参数)。 - 是否启用(enabled):设置此源是否可用;
1为可用,0为禁用。 - 是否校验(gpgcheck):设置此源是否校验文件;
1为校验,0为不校验。 - 公钥位置(gpgkey):若上面的参数开启了校验功能,则此处为公钥文件位置。若没有开启,则省略不写。
- 第 3 步:按配置参数中所填写的仓库位置挂载光盘,并把光盘挂载信息写入
/etc/fstab文件中。 - 第 4 步:使用
dnf install httpd -y命令检查软件仓库是否已经可用。
实验代码
[root@linuxprobe network-scripts]# cd ~
[root@linuxprobe ~]# cd /etc/yum.repos.d/
[root@linuxprobe yum.repos.d]# ls
redhat.repo
[root@linuxprobe yum.repos.d]# vim rhel8.repo
[root@linuxprobe yum.repos.d]# cat -n rhel8.repo
1 [BaseOS]
2 name=BaseOS
3 baseurl=file:///media/cdrom/BaseOS
4 enabled=1
5 gpgcheck=0
6 [AppStream]
7 name=AppStream
8 baseurl=file:///media/cdrom/AppStream
9 enabled=1
10 gpgcheck=0
[root@linuxprobe yum.repos.d]# mkdir -p /media/cdrom
[root@linuxprobe yum.repos.d]# mount /dev/cdrom /media/cdrom
mount: /media/cdrom: WARNING: device write-protected, mounted read-only.
[root@linuxprobe yum.repos.d]# vim /etc/fstab
[root@linuxprobe yum.repos.d]# cat -n /etc/fstab
1
2 #
3 # /etc/fstab
4 # Created by anaconda on Sun Jun 4 03:05:37 2023
5 #
6 # Accessible filesystems, by reference, are maintained under '/dev/disk/'.
7 # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
8 #
9 # After editing this file, run 'systemctl daemon-reload' to update systemd
10 # units generated from this file.
11 #
12 /dev/mapper/rhel-root / xfs defaults 0 0
13 UUID=73159c7d-b179-4ef9-a83f-3f6f6ce390ed /boot xfs defaults 0 0
14 /dev/mapper/rhel-swap swap swap defaults 0 0
15 /dev/cdrom /media/cdrom iso9660 defaults 0 0
[root@linuxprobe yum.repos.d]# dnf install httpd -y
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
Last metadata expiration check: 0:02:20 ago on Tue 06 Jun 2023 04:31:02 PM CST.
Dependencies resolved.
======================================================================================================
Package Arch Version Repository Size
======================================================================================================
Installing:
httpd x86_64 2.4.37-21.module+el8.2.0+5008+cca404a3 AppStream 1.4 M
Installing dependencies:
apr x86_64 1.6.3-9.el8 AppStream 125 k
apr-util x86_64 1.6.1-6.el8 AppStream 105 k
httpd-filesystem noarch 2.4.37-21.module+el8.2.0+5008+cca404a3 AppStream 36 k
httpd-tools x86_64 2.4.37-21.module+el8.2.0+5008+cca404a3 AppStream 103 k
mod_http2 x86_64 1.11.3-3.module+el8.2.0+4377+dc421495 AppStream 158 k
redhat-logos-httpd noarch 81.1-1.el8 BaseOS 26 k
Installing weak dependencies:
apr-util-bdb x86_64 1.6.1-6.el8 AppStream 25 k
apr-util-openssl x86_64 1.6.1-6.el8 AppStream 27 k
Transaction Summary
======================================================================================================
Install 9 Packages
Total size: 2.0 M
Installed size: 5.5 M
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : apr-1.6.3-9.el8.x86_64 1/9
Running scriptlet: apr-1.6.3-9.el8.x86_64 1/9
Installing : apr-util-bdb-1.6.1-6.el8.x86_64 2/9
Installing : apr-util-openssl-1.6.1-6.el8.x86_64 3/9
Installing : apr-util-1.6.1-6.el8.x86_64 4/9
Running scriptlet: apr-util-1.6.1-6.el8.x86_64 4/9
Installing : httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64 5/9
Running scriptlet: httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch 6/9
Installing : httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch 6/9
Installing : redhat-logos-httpd-81.1-1.el8.noarch 7/9
Installing : mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64 8/9
Installing : httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64 9/9
Running scriptlet: httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64 9/9
Verifying : redhat-logos-httpd-81.1-1.el8.noarch 1/9
Verifying : apr-1.6.3-9.el8.x86_64 2/9
Verifying : apr-util-1.6.1-6.el8.x86_64 3/9
Verifying : apr-util-bdb-1.6.1-6.el8.x86_64 4/9
Verifying : apr-util-openssl-1.6.1-6.el8.x86_64 5/9
Verifying : httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64 6/9
Verifying : httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch 7/9
Verifying : httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64 8/9
Verifying : mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64 9/9
Installed products updated.
Installed:
apr-1.6.3-9.el8.x86_64
apr-util-1.6.1-6.el8.x86_64
apr-util-bdb-1.6.1-6.el8.x86_64
apr-util-openssl-1.6.1-6.el8.x86_64
httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64
httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch
httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64
mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64
redhat-logos-httpd-81.1-1.el8.noarch
Complete!
[root@linuxprobe yum.repos.d]#编写 Shell 脚本
可以将 Shell 终端解释器当作人与计算机硬件之间的“翻译官”,它作为用户与 Linux 系统内部的通信媒介,除了能够支持各种变量与参数外,还提供了诸如循环、分支等高级编程语言才有的控制结构特性。
Shell 脚本命令的工作方式有下面两种:
- 交互式(Interactive):用户每输入一条命令就立即执行。
- 批处理(Batch):由用户事先编写好一个完整的 Shell 脚本,Shell 会一次性执行脚本中诸多的命令。
编写简单的脚本
INFO
Shell 脚本文件的名称可以任意,但为了避免被误以为是普通文件,建议将.sh 后缀加上,以表示是一个脚本文件。
$ vim example.sh
$ cat -n example.sh
1 #!/bin/bash
2 #For Example BY linuxprobe.com
3 pwd
4 ls -al在上面的这个 example.sh 脚本中实际上出现了 3 种不同的元素:
- 第一行的脚本声明(
#!)用来告诉系统使用哪种 Shell 解释器来执行该脚本; - 第二行的注释信息(
#)是对脚本功能和某些命令的介绍信息,使得自己或他人在日后看到这个脚本内容时,可以快速知道该脚本的作用或一些警告信息; - 第三、四行的可执行语句也就是我们平时执行的 Linux 命令了。
实验代码
[root@linuxprobe ~]# logout
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2 #For Example BY linuxprobe.com
3 pwd
4 ls -al
[linuxprobe@linuxprobe ~]$ bash example.sh
/home/linuxprobe
total 44
drwx------. 15 linuxprobe linuxprobe 4096 Jun 6 16:36 .
drwxr-xr-x. 3 root root 24 Jun 4 03:15 ..
-rw-------. 1 linuxprobe linuxprobe 389 Jun 5 04:40 .bash_history
-rw-r--r--. 1 linuxprobe linuxprobe 18 Aug 30 2019 .bash_logout
-rw-r--r--. 1 linuxprobe linuxprobe 141 Aug 30 2019 .bash_profile
-rw-r--r--. 1 linuxprobe linuxprobe 312 Aug 30 2019 .bashrc
drwx------. 10 linuxprobe linuxprobe 232 Jun 4 03:27 .cache
drwx------. 12 linuxprobe linuxprobe 229 Jun 4 14:29 .config
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Desktop
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Documents
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Downloads
-rw-------. 1 linuxprobe linuxprobe 16 Jun 4 03:26 .esd_auth
-rw-rw-r--. 1 linuxprobe linuxprobe 57 Jun 6 16:36 example.sh
-rw-------. 1 linuxprobe linuxprobe 930 Jun 4 04:26 .ICEauthority
drwx------. 3 linuxprobe linuxprobe 19 Jun 4 03:26 .local
drwxr-xr-x. 4 linuxprobe linuxprobe 39 Jun 4 03:06 .mozilla
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Music
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Pictures
drwxrw----. 3 linuxprobe linuxprobe 19 Jun 4 03:26 .pki
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Public
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Templates
drwxr-xr-x. 2 linuxprobe linuxprobe 6 Jun 4 03:26 Videos
-rw-------. 1 linuxprobe linuxprobe 9540 Jun 6 16:36 .viminfo接收用户的参数

Linux 系统中的 Shell 脚本语言已经内设了用于接收参数的变量,变量之间使用空格间隔。
$0对应的是当前 Shell 脚本程序的名称$#对应的是总共有几个参数$*对应的是所有位置的参数值$?对应的是显示上一次命令的执行返回值$1、$2、$3……则分别对应着第 N 个位置的参数值
判断用户的参数
Shell 脚本中的条件测试语法可以判断表达式是否成立,若条件成立则返回数字 0,否则便返回非零值。
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2 echo "当前脚本名称为 $0"
3 echo "总共有 $# 个参数,分别是 $*。"
4 echo "第 1 个参数为 $1,第 5 个为 $5。"
[linuxprobe@linuxprobe ~]$ bash example.sh one two three four five six
当前脚本名称为 example.sh
总共有 6 个参数,分别是 one two three four five six。
第 1 个参数为 one,第 5 个为 five。切记
条件表达式两边均应有一个空格。
按照测试对象来划分,条件测试语句可以分为 4 种:
- 文件测试语句;
- 逻辑测试语句;
- 整数值比较语句;
- 字符串比较语句。
文件测试语句
文件测试所用的参数:
| 操作符 | 作用 |
|---|---|
-d | 测试文件是否为目录类型 |
-e | 测试文件是否存在 |
-f | 判断是否为一般文件 |
-r | 测试当前用户是否有权限读取 |
-w | 测试当前用户是否有权限写入 |
-x | 测试当前用户是否有权限执行 |
实验代码
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/usr/bin/env bash
2
3 # 判断文件是否存在
4 if [ -e "/etc/passwd" ]
5 then
6 echo "'/etc/passwd' file exists"
7 else
8 echo "'/etc/passwd' file not exists"
9 fi
10
11 # 判断文件是否为目录
12 if [ -d "/home/linuxprobe/Desktop" ]
13 then
14 echo "'/home/linuxprobe/Desktop' is a directory"
15 else
16 echo "'/home/linuxprobe/Desktop' is not a directory"
17 fi
18
19 # 判断文件是否为空
20 touch /tmp/test
21 if [ -s "/tmp/test" ]
22 then
23 echo "'/tmp/test' is not empty"
24 else
25 echo "'/tmp/test' is empty"
26 fi
27
28 # 判断文件是否可读
29 if [ -r "/etc/passwd" ]
30 then
31 echo "'/etc/passwd' is readable"
32 else
33 echo "'/etc/passwd' is not readable"
34 fi
35
36 # 判断文件是否为一般文件
37 if [ -f "/dev/sda" ]
38 then
39 echo "'/dev/sda' is a normal file"
40 else
41 echo "'/dev/sda' is not a normal file"
42 fi
43
44 # 判断文件是否可写
45 if [ -w "/etc/passwd" ]
46 then
47 echo "'/etc/passwd' is writable"
48 else
49 echo "'/etc/passwd' is not writable"
50 fi
51
52 # 判断文件是否可执行
53 if [ -x "/etc/passwd" ]
54 then
55 echo "'/etc/passwd' is executable"
56 else
57 echo "'/etc/passwd' is not executable"
58 fi
[linuxprobe@linuxprobe ~]$ bash example.sh
'/etc/passwd' file exists
'/home/linuxprobe/Desktop' is a directory
'/tmp/test' is empty
'/etc/passwd' is readable
'/dev/sda' is not a normal file
'/etc/passwd' is not writable
'/etc/passwd' is not executable
[linuxprobe@linuxprobe ~]$逻辑测试语句
&&是逻辑与,只有当前面的语句执行成功的时候才会执行后面的语句。||是逻辑或,只有当前面的语句执行失败的时候才会执行后面的语句。!是逻辑非,代表对逻辑测试结果取反值;之前若为正确则变成错误,若为错误则变成正确。
实验代码
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2 # 判断文件是否存在,如果存在则输出文件名,否则输出不存在
3 FILE="example.txt"
4 touch $FILE
5 if [ -e $FILE ] || [ -e "example2.txt" ]
6 then
7 echo "$FILE or example2.txt exists"
8 else
9 echo "$FILE and example2.txt does not exist"
10 fi
11
[linuxprobe@linuxprobe ~]$ bash example.sh
example.txt or example2.txt exists
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ ls
Desktop Documents Downloads example.sh example.txt Music Pictures Public Templates Videos
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2 # 判断文件是否存在,如果存在则输出文件名,否则输出不存在
3 FILE="example.txt"
4 touch $FILE
5 if [ -e $FILE ] && [ -e "example2.txt" ]; then
6 echo "$FILE and example2.txt exist"
7 else
8 echo "$FILE or example2.txt does not exist"
9 fi
10
[linuxprobe@linuxprobe ~]$ bash example.sh
example.txt or example2.txt does not exist
[linuxprobe@linuxprobe ~]$ touch example2.txt
[linuxprobe@linuxprobe ~]$ bash example.sh
example.txt and example2.txt exist
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2 # 判断文件是否不存在,如果不存在则输出不存在,否则输出文件名
3 FILE="example.txt"
4 if ! [ -e $FILE ]; then
5 echo "$FILE does not exist"
6 else
7 echo "$FILE exists"
8 fi
9
[linuxprobe@linuxprobe ~]$ rm example2.txt
[linuxprobe@linuxprobe ~]$ ls
Desktop Documents Downloads example.sh example.txt Music Pictures Public Templates Videos
[linuxprobe@linuxprobe ~]$ bash example.sh
example.txt exists
[linuxprobe@linuxprobe ~]$ rm example.txt
[linuxprobe@linuxprobe ~]$ bash example.sh
example.txt does not exist
[linuxprobe@linuxprobe ~]$整数值比较语句
可用的整数比较运算符:
| 操作符 | 作用 |
|---|---|
-eq | 是否等于 |
-ne | 是否不等于 |
-gt | 是否大于 |
-lt | 是否小于 |
-le | 是否等于或小于 |
-ge | 是否大于或等于 |
-eq:等于(equal to)-ne:不等于(not equal to)-gt:大于(greater than)-lt:小于(less than)-le:小于等于(less than or equal to)-ge:大于等于(greater than or equal to)
[linuxprobe@linuxprobe ~]$ free -m
total used free shared buff/cache available
Mem: 1960 1436 135 20 388 344
Swap: 2047 146 1901
[linuxprobe@linuxprobe ~]$ FreeMem=`free -m | grep Mem: | awk '{print $4}'`
[linuxprobe@linuxprobe ~]$ [ $FreeMem -lt 1024 ] && echo "Insufficient Memory"
Insufficient Memory
[linuxprobe@linuxprobe ~]$实验代码
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2
3 # 定义两个整数变量
4 a=10
5 b=20
6
7 # 使用 -eq 比较语句判断 a 是否等于 b
8 if [ $a -eq $b ]
9 then
10 echo "a 等于 b"
11 else
12 echo "a 不等于 b"
13 fi
14
15 # 使用 -ne 比较语句判断 a 是否不等于 b
16 if [ $a -ne $b ]
17 then
18 echo "a 不等于 b"
19 else
20 echo "a 等于 b"
21 fi
22
23 # 使用 -gt 比较语句判断 a 是否大于 b
24 if [ $a -gt $b ]
25 then
26 echo "a 大于 b"
27 else
28 echo "a 不大于 b"
29 fi
30
31 # 使用 -lt 比较语句判断 a 是否小于b
32 if [ $a -lt $b ]
33 then
34 echo "a 小于 b"
35 else
36 echo "a 不小于 b"
37 fi
38
39 # 使用 -le 比较语句判断 a 是否小于等于 b
40 if [ $a -le $b ]
41 then
42 echo "a 小于等于 b"
43 else
44 echo "a 大于 b"
45 fi
46
47 # 使用 -ge 比较语句判断 a 是否大于等于 b
48 if [ $a -ge $b ]
49 then
50 echo "a 大于等于 b"
51 else
52 echo "a 小于 b"
53 fi
54
[linuxprobe@linuxprobe ~]$ bash example.sh
a 不等于 b
a 不等于 b
a 不大于 b
a 小于 b
a 小于等于 b
a 小于 b
[linuxprobe@linuxprobe ~]$字符串比较语句
常见的字符串比较运算符
| 操作符 | 作用 |
|---|---|
= | 比较字符串内容是否相同 |
!= | 比较字符串内容是否不同 |
-z | 判断字符串内容是否为空 |
[linuxprobe@linuxprobe ~]$ echo $LANG
en_US.UTF-8
[linuxprobe@linuxprobe ~]$ [ ! $LANG = "en.US" ] && echo "Not en.US"
Not en.US
[linuxprobe@linuxprobe ~]$实验代码
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2 str1="hello"
3 str2="world"
4 str=""
5
6 if [ $str1 = $str2 ]; then
7 echo "$str1 = $str2"
8 else
9 echo "$str1 != $str2"
10 fi
11
12 if [ $str1 != $str2 ]; then
13 echo "$str1 != $str2"
14 else
15 echo "$str1 = $str2"
16 fi
17
18 if [ -z "$str" ]; then
19 echo "$str 字符串为空"
20 else
21 echo "$str 字符串不为空"
22 fi
23
[linuxprobe@linuxprobe ~]$ bash example.sh
hello != world
hello != world
字符串为空
[linuxprobe@linuxprobe ~]$流程控制语句
- 尽管此时可以通过使用 Linux 命令、管道符、重定向以及条件测试语句来编写最基本的 Shell 脚本,但是这种脚本并不适用于生产环境。
- 原因是它不能根据真实的工作需求来调整具体的执行命令,也不能根据某些条件实现自动循环执行。通俗来讲,就是不能根据实际情况做出调整。
- 通常脚本都是从上到下一股脑儿地执行,效率是很高,但一旦某条命令执行失败了,则后面的功能全都会受到影响。
if 条件测试语句
if 条件测试语句可以让脚本根据实际情况自动执行相应的命令。从技术角度来讲,if 语句分为单分支结构、双分支结构、多分支结构;其复杂度随着灵活度一起逐级上升。
单分支的 if 条件语句
if 条件语句的单分支结构由 if、then、fi 关键词组成,而且只在条件成立后才执行预设的命令,相当于口语的 如果……那么……。
[linuxprobe@linuxprobe ~]$ vim mkshell.sh
[linuxprobe@linuxprobe ~]$ cat -n mkshell.sh
1 #!/bin/bash
2 DIR="/home/linuxprobe/shell"
3 if [ ! -d $DIR ]; then
4 mkdir -p $DIR
5 fi
6
7 ls -ld $DIR
8
[linuxprobe@linuxprobe ~]$ bash mkshell.sh
drwxrwxr-x. 2 linuxprobe linuxprobe 6 Jun 11 14:27 /home/linuxprobe/shell
[linuxprobe@linuxprobe ~]$双分支的 if 条件语句
if 条件语句的双分支结构由 if、then、else、fi 关键词组成,它进行一次条件匹配判断,如果与条件匹配,则去执行相应的预设命令;反之则去执行不匹配时的预设命令,相当于口语的 如果……那么……或者……那么……。
[linuxprobe@linuxprobe ~]$ vim chkhost.sh
[linuxprobe@linuxprobe ~]$ cat -n chkhost.sh
1 #!/bin/bash
2 ping -c 3 -i 0.2 -W 3 $1 &>/dev/null
3 if [ $? -eq 0 ]; then
4 echo "Host $1 is On-line."
5 else
6 echo "Host $1 is Off-line."
7 fi
8
[linuxprobe@linuxprobe ~]$ bash chkhost.sh 192.168.0.1
Host 192.168.0.1 is On-line.
[linuxprobe@linuxprobe ~]$ bash chkhost.sh 192.168.0.100
Host 192.168.0.100 is Off-line.
[linuxprobe@linuxprobe ~]$多分支的 if 条件语句
if 条件语句的多分支结构由 if、then、else、elif、fi 关键词组成,它进行多次条件匹配判断,这多次判断中的任何一项在匹配成功后都会执行相应的预设命令,相当于口语的 如果……那么……如果……那么……。

[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2
3 read -r -p "请输入一个数字: " num
4
5 if [ "$num" -gt 0 ]; then
6 echo "输入的数字是正数"
7 fi
8
9 num=10
10
11 if [ "$num" -gt 10 ]; then
12 echo "$num 大于10"
13 else
14 echo "$num 小于或等于10"
15 fi
16
17 num=1
18
19 if [ $num -gt 10 ]; then
20 echo "$num 大于10"
21 elif [ $num -eq 10 ]; then
22 echo "$num 等于10"
23 else
24 echo "$num 小于10"
25 fi
26
[linuxprobe@linuxprobe ~]$ bash example.sh
请输入一个数字: 100
输入的数字是正数
10 小于或等于10
1 小于10
[linuxprobe@linuxprobe ~]$for 条件循环语句
for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行操作处理。- 当要处理的数据有范围时,使用
for循环语句就再适合不过了。
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2
3 # 定义一个数组
4 arr=("apple" "banana" "orange" "grape")
5
6 # 使用 for 循环遍历数组中的元素
7 for fruit in "${arr[@]}"; do
8 echo "I love ${fruit}s"
9 done
10
11 echo ""
12
13 for i in {1..5}; do
14 echo "num is $i"
15 done
16
[linuxprobe@linuxprobe ~]$ bash example.sh
I love apples
I love bananas
I love oranges
I love grapes
num is 1
num is 2
num is 3
num is 4
num is 5
[linuxprobe@linuxprobe ~]$[linuxprobe@linuxprobe ~]$ su - root
Password:
[root@linuxprobe ~]# cd /home/linuxprobe/
[root@linuxprobe linuxprobe]# cat -n addusers.sh
1 #!/bin/bash
2 read -r -p "Enter The Users Password : " PASSWD
3 arr=("andy" "barry" "carl" "duke" "eric" "linuxprobe")
4 for UNAME in "${arr[@]}"; do
5 # id "$UNAME" &> /dev/null
6 # if [ $? -eq 0 ]
7 if ! id "$UNAME" &>/dev/null; then
8 echo "$UNAME , Already exists"
9 else
10 useradd "$UNAME"
11 echo "$PASSWD" | passwd --stdin "$UNAME" &>/dev/null
12 echo "$UNAME , Create success"
13 fi
14 done
15
[root@linuxprobe linuxprobe]# bash addusers.sh
Enter The Users Password : linuxprobe
andy , Create success
barry , Create success
carl , Create success
duke , Create success
eric , Create success
useradd: user 'linuxprobe' already exists
[root@linuxprobe linuxprobe]# tail -6 /etc/passwd
linuxprobe:x:1000:1000:linuxprobe:/home/linuxprobe:/bin/bash
andy:x:1001:1001::/home/andy:/bin/bash
barry:x:1002:1002::/home/barry:/bin/bash
carl:x:1003:1003::/home/carl:/bin/bash
duke:x:1004:1004::/home/duke:/bin/bash
eric:x:1005:1005::/home/eric:/bin/bashwhile 条件循环语句
while条件循环语句是一种让脚本根据某些条件来重复执行命令的语句,它的循环结构往往在执行前并不确定最终执行的次数,完全不同于for循环语句中有目标、有范围的使用场景。while循环语句通过判断条件测试的真假来决定是否继续执行命令,若条件为真就继续执行,为假就结束循环。
[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2
3 # 使用 while 循环输出 0 到 5
4 count=0
5 while [ $count -lt 5 ]; do
6 echo "count is $count"
7 count=$((count + 1))
8 done
9
10 # 使用 while 循环计算 1 到 100 的和
11 i=1
12 sum=0
13 while [ $i -le 100 ]; do
14 sum=$((sum + i))
15 i=$((i + 1))
16 done
17
18 echo "The sum of 1 to 100 is: $sum"
19
[linuxprobe@linuxprobe ~]$ bash example.sh
count is 0
count is 1
count is 2
count is 3
count is 4
The sum of 1 to 100 is: 5050
[linuxprobe@linuxprobe ~]$case 条件测试语句
case条件测试语句和switch语句的功能非常相似!case语句是在多个范围内匹配数据,若匹配成功则执行相关命令并结束整个条件测试。- 如果数据不在所列出的范围内,则会去执行星号(
*)中所定义的默认命令。

[linuxprobe@linuxprobe ~]$ vim example.sh
[linuxprobe@linuxprobe ~]$ cat -n example.sh
1 #!/bin/bash
2
3 echo "请输入1-3之间的数字:"
4 read -r num
5
6 case $num in
7 1)
8 echo "你输入的是1"
9 ;;
10 2)
11 echo "你输入的是2"
12 ;;
13 3)
14 echo "你输入的是3"
15 ;;
16 *)
17 echo "输入错误"
18 ;;
19 esac
20
[linuxprobe@linuxprobe ~]$ bash example.sh
请输入1-3之间的数字:
3
你输入的是3
[linuxprobe@linuxprobe ~]$ bash example.sh
请输入1-3之间的数字:
6
输入错误
[linuxprobe@linuxprobe ~]$[linuxprobe@linuxprobe ~]$ vim Checkkeys.sh
[linuxprobe@linuxprobe ~]$ cat -n Checkkeys.sh
1 #!/bin/bash
2 read -r -p "请输入一个字符,并按Enter键确认:" KEY
3 case "$KEY" in
4 [a-z] | [A-Z])
5 echo "您输入的是 字母。"
6 ;;
7 [0-9])
8 echo "您输入的是 数字。"
9 ;;
10 *)
11 echo "您输入的是 空格、功能键或其他控制字符。"
12 ;;
13 esac
14
[linuxprobe@linuxprobe ~]$ bash Checkkeys.sh
请输入一个字符,并按Enter键确认:y
您输入的是 字母。
[linuxprobe@linuxprobe ~]$ bash Checkkeys.sh
请输入一个字符,并按Enter键确认:[
您输入的是 空格、功能键或其他控制字符。
[linuxprobe@linuxprobe ~]$ bash Checkkeys.sh
请输入一个字符,并按Enter键确认:
您输入的是 空格、功能键或其他控制字符。
[linuxprobe@linuxprobe ~]$ bash Checkkeys.sh
请输入一个字符,并按Enter键确认:9
您输入的是 数字。
[linuxprobe@linuxprobe ~]$计划任务服务程序
计划任务分为一次性计划任务与长期性计划任务。
- 一次性计划任务:今晚 23:30 重启网站服务。
- 长期性计划任务:每周一的凌晨 3:25 把
/home/wwwroot目录打包备份为backup.tar.gz。
一次性计划任务
- 一次性计划任务只执行一次,一般用于临时的工作需求。可以用
at命令实现这种功能,只需要写成at 时间的形式就行。 - 如果想要查看已设置好但还未执行的一次性计划任务,可以使用
at -l命令。 - 要想将其删除,可以使用
atrm 任务序号。
[linuxprobe@linuxprobe ~]$ at 23:30
warning: commands will be executed using /bin/sh
at> systemctl restart httpd
at> <EOT> # Ctrl + d 键来结束编写计划任务
job 1 at Sun Jun 11 23:30:00 2023
[linuxprobe@linuxprobe ~]$ at -l
1 Sun Jun 11 23:30:00 2023 a linuxprobe
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ echo "systemctl restart httpd" | at 23:30
warning: commands will be executed using /bin/sh
job 2 at Sun Jun 11 23:30:00 2023
[linuxprobe@linuxprobe ~]$ at -l
1 Sun Jun 11 23:30:00 2023 a linuxprobe
2 Sun Jun 11 23:30:00 2023 a linuxprobe
[linuxprobe@linuxprobe ~]$ atrm 2 # 使用 atrm 命令轻松删除计划任务
[linuxprobe@linuxprobe ~]$ at -l
1 Sun Jun 11 23:30:00 2023 a linuxprobe
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ echo "systemctl restart httpd" | at now +2 MINUTE # 表示 2 分钟(MINUTE)后执行这个任务,也可以将其替代成小时(HOUR)、日(DAY)、月(MONTH)等
warning: commands will be executed using /bin/sh
job 3 at Sun Jun 11 14:49:00 2023
[linuxprobe@linuxprobe ~]$ at -l
1 Sun Jun 11 23:30:00 2023 a linuxprobe
3 Sun Jun 11 14:49:00 2023 a linuxprobeat 命令的参数及其作用
| 参数 | 作用 |
|---|---|
-f | 指定包含命令的任务文件 |
-q | 指定新任务名称 |
-l | 显示待执行任务列表 |
-d | 删除指定待执行任务 |
-m | 任务执行后给用户发邮件 |
长期性计划任务
还有些时候,我们希望 Linux 系统能够周期性地、有规律地执行某些具体的任务,那么 Linux 系统中默认启用的 crond 服务简直再适合不过了。
- 创建、编辑计划任务的命令为
crontab -e - 查看当前计划任务的命令为
crontab -l - 删除某条计划任务的命令为
crontab -r - 如果您是以管理员的身份登录的系统,还可以在
crontab命令中加上-u参数来编辑他人的计划任务。
[linuxprobe@linuxprobe ~]$ crontab -e # 使用 rontab -e 命令来创建计划任务
no crontab for linuxprobe - using an empty one
crontab: installing new crontab
[linuxprobe@linuxprobe ~]$ crontab -l
25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ crontab -e
crontab: installing new crontab
[linuxprobe@linuxprobe ~]$ crontab -l
25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
0 1 * * 1-5 /usr/bin/rm -rf /tmp/*
[linuxprobe@linuxprobe ~]$ crontab -r # 使用 crontab -r 命令删除计划任务
[linuxprobe@linuxprobe ~]$ crontab -l
no crontab for linuxprobe
[linuxprobe@linuxprobe ~]$crontab 命令的参数及其作用
| 参数 | 作用 |
|---|---|
-e | 编辑计划任务 |
-u | 指定用户名称 |
-l | 列出任务列表 |
-r | 删除计划任务 |
使用 crond 设置任务的参数格式

使用 crond 设置任务的参数字段说明
| 字段 | 说明 |
|---|---|
| 分钟 | 取值为 0 ~ 59 的整数 |
| 小时 | 取值为 0 ~ 23 的任意整数 |
| 日期 | 取值为 1 ~ 31 的任意整数 |
| 月份 | 取值为 1 ~ 12 的任意整数 |
| 星期 | 取值为 0 ~ 7 的任意整数,其中 0 与 7 均为星期日 |
| 命令 | 要执行的命令或程序脚本 |
使用计划服务的注意事项
- 在
crond服务的配置参数中,一般会像 Shell 脚本那样以#号开头写上注释信息,这样在日后回顾这段命令代码时可以快速了解其功能、需求以及编写人员等重要信息。 - 计划任务中的
分字段必须有数值,绝对不能为空或是*号,而日和星期字段不能同时使用,否则就会发生冲突。
删除 crond 计划任务
- 直接使用
crontab -e命令进入编辑界面,删除里面的文本信息即可。 - 使用
crontab -r命令直接进行删除。
总结
VIM 编辑器的 3 种模式分别是什么?
命令模式、末行模式与输入模式(也叫编辑模式或插入模式)。
怎么从输入模式切换到末行模式?
需要先敲击
Esc键退回到命令模式,然后敲击冒号(:)键后进入末行模式。一个完整的 Shell 脚本应该包含哪些内容?
应该包括脚本声明、注释信息和可执行语句(即命令)。
分别解释 Shell 脚本中
$0与$3变量的作用。在 Shell 脚本中,
$0代表脚本文件的名称,$3则代表该脚本在执行时接收的第 3 个参数。if条件测试语句有几种结构,最灵活且最复杂的是哪种结构?if条件测试语句包括单分支、双分支与多分支等 3 种结构,其中多分支结构是最灵活且最复杂的结构,其结构形式为if…then…elif…then…else…fi。for条件循环语句的循环结构是什么样子的?for条件循环语句的结构为for 变量名 in 取值列表 do 命令序列 done。若在
while条件循环语句中使用true作为循环条件,那么会发生什么事情?由于条件测试值永久为
true,因此脚本中的循环部分会无限地重复执行下去,直到碰到exit命令才会结束。如果需要依据用户的输入参数执行不同的操作,最方便的条件测试语句是什么?
case条件语句。Linux 系统的长期计划任务所使用的服务是什么,其参数格式是什么?
长期计划任务需要使用
crond服务程序,参数格式是分、时、日、月、星期 命令。