掌握 Shell 脚本 – 从零开始到面试准备!🔥
介绍
大家好,很高兴见到你们回来!对于我们程序员来说,深入 Bash 脚本的世界非常重要。它的核心是创建脚本,这些脚本本质上是一些小程序,用来自动化我们每天面对的那些繁琐重复的操作。我们不用一遍又一遍地手动运行命令,而是使用脚本来简化操作。
它通过自动化日常事务让我们的生活变得更轻松,让我们能够专注于开发中更令人兴奋的方面。
在接下来的几分钟里,我们将通过实际示例探索 Bash 脚本的基础知识。最终,你将对如何简化工作流程和提高生产力有深入的理解。
你兴奋吗?

有什么先决条件吗?
如果您是 Windows 用户,则需要设置 WSL 才能在系统上使用 Linux。您可以在这里了解更多信息。
注意:在本文中,“shell 脚本”和“Bash 脚本”这两个术语可以互换使用。Bash 是最常见的 shell,出于本讨论的目的,它们可以被视为相同的。
涵盖基础知识
Bash 脚本究竟是什么?
可以把它想象成创建一个小程序,用来自动执行你通常手动完成的任务。这些脚本是纯文本文件,包含你通常在命令行中输入的命令。例如,假设你需要将文件夹 A 中的所有 100 个文件复制到文件夹 B,这项任务非常枯燥乏味且重复,因此你可以编写一个 Bash 脚本将所有文件从 A 复制到 B。
我们为什么需要它?它真的那么重要吗?
我们需要 Bash 脚本,因为它能节省我们的时间和精力。你可以把它想象成一个助手,帮你处理所有枯燥重复的任务,这样你就可以专注于真正有趣的事情。是的,它确实有助于组织自动化大型任务。
我们在哪里编写这些脚本?
我们在文本编辑器中编写这些脚本。在本例中,我们将使用 Linux 发行版自带的 VIM 编辑器。
外壳看起来是这样的:
Bash 命令
在这里,我们将了解最常用的 bash 命令。
了解当前所在的路径非常重要,尤其是在处理多个项目时,这很容易造成混淆。为了获取当前目录,我们使用命令pwd
“打印工作目录”。
pwd
现在我们知道了当前目录,让我们创建一个新文件夹(也可以称之为目录)来保存文件。为此,我们使用mkdir
命令“make directory”。
mkdir <specify your folder name>
创建目录后,您可以使用ls
命令查看其中的内容。
ls
或者
您还可以使用ls -ltr
命令,该命令以长格式(-l)列出内容,按修改时间(-t)排序,并首先显示最旧的条目(-r)。
ls -ltr
现在,为了在文件夹/目录内移动,您可以编写代表更改目录的命令cd
,使用 cd 您可以进入文件夹内部,再次输入 ls 将显示该文件夹内的所有文件。
cd <folder_name>
为了退出当前所在的目录,您可以使用命令cd ..
,这可以让您退出目录。
cd ..
为了删除文件或整个目录,我们使用命令rm -r
rm -r <name of file or folder>
我们可以使用命令重命名文件mv
。
mv <your-file-name> <new-file-name>
现在让我们创建一个文件,要创建文件,我们使用touch
命令。
touch <filename>
要打印文件内的内容,我们使用cat
命令。
cat <filename>
该文件最初是空的,因为我们没有在文件中添加任何内容。让我们向文件中添加一些内容。我们将使用 vim 编辑器(文章前面有详细说明)来编辑文件,保存它,然后使用 cat 命令。
该文件现在显示我们写入的内容。
最后,如果我们想在 shell 上打印一些内容,我们使用命令echo
。
好的,太棒了!我们已经学习了在 Shell 中操作的基本命令。现在我们可以继续学习更有趣的内容了。其实并不难,所以不用担心!
Bash 脚本和 VIM 编辑器
如果你以前从未编写过脚本,那么你可能对 vim 以及与之相关的各种梗并不熟悉。vim 是一个用于在终端上编写 Bash 脚本的编辑器,市面上还有许多其他编辑器,例如 neovim、nano,可以帮助你编写脚本,但在本教程中我们将使用 vim。
注意:对于初学者来说,您可能会难以使用 vim,不用担心,这是很正常的。
让我们编写第一个 bash 脚本
"#" symbol is used to show the content is a comment not a part of program.
# Type the below command on the shell.
vim bashscriptfile.sh
耶!!您现在位于 vim 编辑器中。
注意:您现在无法在编辑器中键入或插入任何内容,因为它在
Insert
模式下不会默认打开。
要启用Insert
模式,您需要按下i
键盘上的键,现在您就可以像在普通编辑器上一样书写。
您可以看到编辑器现在处于插入模式。
棘手的部分
现在您已经在 vim 上完成了写作,您需要保存它并退出编辑器,为了保存您的进度,我们首先需要按下esc
键退出插入模式,现在我们输入:w
命令,这将保存我们的进度,为了在保存进度后退出 vim,我们使用:q
命令。
我们可以:wq!
直接使用命令保存并退出编辑器。
或者
您也可以使用命令:x
, 来实现相同的效果。
您可以简单地编写命令 bash 或 sh(我们很快会讨论它们)后跟文件名来运行示例脚本。
现在您可能已经注意到,我已将文件扩展名更改为.sh
,.sh
文件名中的扩展名(如bashscriptfile.sh)表示该文件是一个 shell 脚本,其中包含由 Unix shell 运行的一系列命令。
现在,让我们编写一个更好的 Shell 脚本。上面的文件中我们没有#!/bin/bash
在 vim 编辑器中使用,这是因为它是一个非常普通的脚本,只是打印我们提供的命令。但实际上,我们处理的是包含大量需要编译/解释的代码的复杂脚本。
Shell 脚本开头的shebang 行#!/bin/bash
告诉操作系统应该使用哪个解释器(在本例中为位于 /bin/bash 的 Bash shell)来执行该脚本,以确保无论用户的默认 shell 是什么,该脚本都能正确、一致地运行。
#!
:这两个字符表示该文件是一个脚本,后面跟着的是解释器的路径。/bin/bash
:这是 Bash shell 解释器的路径。
现在,让我们编写一个 shell 脚本来自动执行文件和文件夹的创建过程,该脚本在执行时将创建一个文件夹并在文件夹内创建一个 5 个文件。
vim firstscript.sh
#!/bin/bash
# this is used to ask the name of folder/directory u wanted to create.
read -p "Enter the directory name: " dir_name
# if the folder/directory already exist, show error
if [ -d "$dir_name" ]; then
echo "Error: Directory '$dir_name' already exists."
exit 1
fi
# Creating the directory
mkdir "$dir_name"
# if we are able to create it or not
if [ ! -d "$dir_name" ]; then
echo "Error: Failed to create directory '$dir_name'."
exit 1
fi
# Creating 5 files inside the directory we made.
for i in {1..5}; do
file_name="$dir_name/file_$i.txt"
touch "$file_name"
if [ ! -f "$file_name" ]; then
echo "Error: Failed to create file '$file_name'."
fi
done
echo "Directory '$dir_name' and 5 files created successfully."
exit 0
编写脚本后保存它,返回终端并运行以下命令,让我们看看我们是否真的自动创建文件。
bash firstscript.sh
然后它会要求您输入文件夹名称,我输入了“firstdirectory”。
🎉🎉 哇哦!您已经编写了您的第一个 bash 脚本,如果您喜欢它,请考虑关注我以获取更多此类内容!!
文件权限
在执行 shell 脚本时,当您键入./ <sample.sh>
命令来运行文件时,您将看到权限错误,这是因为您没有执行该文件的权限。
Shell 脚本中的文件权限对于管理类 Unix 系统中的访问控制至关重要。该chmod
命令用于更改这些权限,确定谁可以读取、写入和执行文件。
该chmod
命令使用数字代码设置权限,遵循 4-2-1 规则。每位数字分别代表所有者、组和其他人的权限。4
:代表读取权限。2
:代表写入权限。1
:代表执行权限。
4+2+1 = 7,这意味着给予每个人文件的完全访问权限(不建议)。
chmod 777 demo.txt
或者
chmod +x demo.txt
在上面的命令中,您授予了文件的完全访问权限,任何人都可以读取、写入和执行该文件。
您可以在此处了解有关该chmod
命令的更多信息。
Bash 与 Sh
上面我们讨论了用于执行 Shell 脚本的命令。我们可以使用 sh 和 bash。bashsh
注重可移植性,并遵循 POSIX 标准,以实现与类 Unix 系统的最大兼容性。bashbash
是 Linux 和 macOS 上常见的功能更丰富的 Shell,它提供了命令行编辑和存储命令历史记录的数组等便利功能,但牺牲了一些可移植性。
我们可以说 bash 就是 sh,但具有一些更高级的功能。
Shell 脚本中的网络
Shell 脚本中的网络功能涉及使用 Shell 脚本中的命令行工具与网络交互、传输数据和管理网络配置。它允许自动执行与网络相关的任务,例如检查网络连接、下载文件、配置网络接口、连接到远程实例等。
Shell 脚本能够自动执行任务、管理配置和处理文件操作,这对于系统管理、DevOps 和开发领域的专业人员来说非常有价值。
常用命令curl
:使用网络协议与服务器之间传输数据。
以下命令将 Dev Community 主页的 HTML 代码输出到您的终端。
curl https://dev.to
ping
:检查系统与另一台主机的连接。
ping www.google.com
ssh
:安全地连接到远程主机。该命令用于连接 EC2 等远程实例。
ssh username@ip-address
条件语句和位置参数
它们是和其他语言一样的普通 if/else 语句。区别在于,我们在末尾使用fi
来表示结束。
if [[ condition1 ]]
then
commands1
elif [[ condition2 ]]
then
commands2
else
commands3
fi
让我们创建一个非常简单的脚本。
vim condition.sh
正确保存脚本
位置参数:在 Shell 脚本中,我们有一个位置参数的概念,它存储传递给 Shell 脚本的命令行参数。它们被称为 $1、$2、$3 等等,其中 $1 是第一个参数,$2 是第二个参数,依此类推。$0 保留用于脚本文件名。
您可以在 bash 命令和文件名后输入参数
循环和函数
Shell 脚本中主要有三种循环类型:for、while 和 until。for 循环遍历一系列项,while 循环只要条件为真就会执行,until 循环只要条件为假就会执行。
for i in {INITIAL_VALUE..TERMINATING_VALUE}
do
# Code
done
vim forloop.sh
现在保存文件
函数,正如我们所知,是可以在整个脚本中调用和重用的代码块。
function_name() {
# Commands
}
vim functions.sh
该脚本定义了一个名为 follow 的函数,它接受一个参数并打印语句。
让我们使用函数和循环编写一个脚本。
vim sumScript.sh
注意:如果您忘记了如何在 vim 中输入,请记住按下
i
以启用插入模式。
#!/bin/bash
# Calculate the sum of numbers from 1 to n.
sum_numbers() {
local n=$1
local sum=0
local i=1
while [[ $i -le $n ]]; do
sum=$((sum + i))
i=$((i + 1))
done
echo "Sum of numbers from 1 to $n is: $sum"
}
while true
do
read -p "Enter a positive integer or press q to exit:" input
if [[ "$input" == "q" ]]; then
break
fi
# Check if input is a number
if ! [[ "$input" =~ ^[0-9]+$ ]]; then
echo "Invalid"
continue
fi
sum_numbers "$input"
done
echo "Script completed."
保存脚本
深入探索:一些更有趣的命令🚀
管道 | 和重定向 (>>)
管道符号 | 是 Shell 脚本中一个强大的功能,它允许你将多个命令串联起来。管道符号后面的命令始终依赖于它前面的命令。
echo 'Hello, Bash piping!' | wc -w
该wc -w
命令计算其输入中的单词数,结果输出为“3”,这清楚地表明了它是如何依赖于输入的。
Grep命令
grep 命令是 Linux 中一个强大的工具,用于在文件中搜索文本或模式。为了搜索关键字、进程或任何特定于组织的内容,grep 命令非常方便。
grep "keyword" <filename>
以下是我在上面创建的文件中搜索单词demo 的方法。
现在,让我演示如何使用该grep
命令查找系统上正在运行的进程。Grep 在工业界非常有用,它可以在大型日志文件中识别感兴趣的关键字,就像我们搜索特定进程一样。
ps -ef | grep "postgres"
Sed 命令
该sed
命令也称为“流编辑器”,是类 Unix 操作系统中用于文本操作的命令行实用程序。
您可以对文件或输入流中的文本执行搜索、替换、插入和删除操作,而无需在文本编辑器中打开文件。
让我们运行一个 Bash 脚本来替换文件中的文本。我们创建一个文件,touch sedfile.txt
并在其中写入“这是一个 Bash 脚本教程”,然后:
vim sedsamplefile.sh
它将打开 vim 编辑器,启用插入模式。
现在让我们运行脚本。
注意:我已经用 vim 编辑器把内容写入了 sedfile.txt 中。现在我们来运行脚本。
您可以看到脚本按预期工作并且 bash 被 shell 取代。
sed可用于转换数据格式、清理杂乱数据、自动执行 shell 脚本中的重复文本编辑任务、跨多个文件查找和替换操作以及生成代码片段。
Awk 命令
Shell 脚本中的命令awk
是一个强大的文本处理工具,用于模式扫描和处理。它可以过滤和操作文本数据,使其适用于报告、计算和文本转换。AWK 逐行处理文件,并将每行拆分为多个字段。
vim awk_script.sh
让我们添加一个脚本来仅显示已登录用户的用户名。
保存文件
您可以清楚地看到它打印了今天登录的用户的姓名。
# The $2 indicates the column 2 which was assigned to username and similarly $1 was assigned to date.
awk '{print "User: " $2 " logged in on " $1}'
AWK 通常用于日志处理、数据提取和文本转换。例如,如果我们有一个日志文件,其中包含日期、用户名和执行的操作等列,如上所示,我们可以使用 AWK 仅提取相关信息,例如上面的用户名。
I/O 重定向:重定向允许你更改命令的输入和输出流。默认情况下,命令从键盘接收输入,并将输出发送到终端屏幕。但重定向允许你更改输入的来源和输出的去向。
将输出重定向到文件 (>)
之前我们使用 vim 编辑器来编辑 sedfile.txt,但也可以仅使用终端并使用重定向运算符来完成。
- > 运算符用于将输出发送到文件,覆盖任何现有内容。
echo "Hello, World!" > sample.txt
这将在 sample.txt 文件中插入文本“Hello, world!”。
将输出附加到文件 (>>)
- >> 运算符将输出附加到现有文件而不是覆盖它。
echo "This is an appended line." >> sample.txt
这将在“Hello, world!”文本下方附加一行。
输入重定向(< 命令)
- < 运算符用于从文件而不是键盘获取输入。
cat < output.txt
重定向输出和错误(&> 和 2>)
- 将错误消息重定向到文件。
ls random_file 2> error_log.txt
输出将是 ls: 无法访问‘random_file’:没有这样的文件或目录
重定向输出和错误(&> 命令)
- 将标准输出和标准错误发送到单个文件。
ls valid_file Invalid_file &> output.txt
预期输出:
valid_file
ls: cannot access 'Invalid_file': No such file or directory
之前我们使用 vim 编辑器来编辑 sedfile.txt,但也可以仅使用终端并使用重定向运算符来完成。
I/O 重定向是 Linux 的一个基本概念,它允许用户有效地管理数据。
错误处理和调试
错误处理对于创建可靠的 Shell 脚本至关重要。它涉及管理程序执行过程中的意外情况,并确保脚本的行为可预测。
基本错误处理
# This option causes the script to exit immediately if a command fails.
set -e
让我们编写一个示例脚本。
vim sample.sh
添加一个可以打印文件内容的脚本,但在这里我们将学习如何set -e
在出现错误时派上用场。
在上面的脚本中,我尝试查看一个不存在的文件,并且set -e
将立即执行,脚本中断。
实际用例:假设任何 AWS CLI 命令(例如,aws ec2 run-instances、aws ec2 authorize-security-group-ingress)失败,脚本将立即退出。这可以防止脚本继续在可能已损坏的状态下配置资源。
Trap:Bash 中的 trap 命令是一个内置函数,允许您在脚本接收到特定信号时执行特定操作。
信号:信号是发送给进程以通知其事件的软件中断。
任务调度
相信大家都知道“任务调度”是什么意思。在 Shell 脚本中,可以使用crontab之类的工具来实现。crontab 是类 Unix 操作系统中的一个实用程序,允许你安排作业以特定间隔自动运行。这些计划作业被称为“cron 作业”。
实际用例包括 EC2 实例管理、按计划时间将数据同步到数据库等。
要深入了解任务调度和 Crontab,您可以在此处进行探索。
后台和前台作业
前台作业直接在终端中运行并阻止进一步输入直到完成,后台作业通过在命令后附加“&”来启用,从而释放终端。
这些工作对于提高效率至关重要,尤其是在软件开发中,编译代码、运行测试和部署应用程序可能非常耗时。
通过在后台运行模型训练或数据库备份等耗时较长的任务,同时其他监控任务在前台运行,用户可以继续工作,从而最大限度地提高生产力和资源利用率。
是时候通过脚本来理解这一点了。
vim sample.sh
复制以下脚本
#!/bin/bash
# Foreground task
echo "Starting a foreground task..."
sleep 3 # Wait for 3 seconds
echo "Foreground task completed."
# Background task
echo "Starting a background task..."
sleep 5 & # Run the sleep command in the background
echo "Background task started!"
echo "Doing other things while background task runs..."
sleep 1
echo "Script is still running."
#The other process runs while this message is being displayed.
sleep 2
echo "All done."
该脚本演示了前台和后台作业的使用。
- 你会看到“正在启动前台任务...”,然后必须等待 3 秒钟才会发生其他事情。这表明前台任务会阻塞后续输入,直到完成为止。
- 在后台任务的 sleep 5 命令执行完成之前,你几乎立刻就能看到“正在启动后台任务...”和“后台任务已启动!”。这是因为 & 语句将 sleep 5 命令置于了后台。
- 启动后台任务后,脚本立即继续打印“在后台任务运行时执行其他操作...”,然后暂停另一次睡眠 1。这表明终端可以自由执行其他任务。
- 即使后台任务(sleep 5)可能仍在运行,最终仍会显示“全部完成。”消息。该脚本并未明确等待后台任务完成后再退出。
Shell 脚本最佳实践🌟

-
保持脚本简单:通过确保每个脚本都有单一职责来实现简单性。
-
使用版本控制:将您的脚本存储在版本控制系统(如 Git)中以跟踪更改并与他人协作。
-
检查工作目录:验证脚本是否在正确的目录中执行。
-
日志记录和故障排除:实施日志记录机制来捕获脚本执行细节和错误。
-
文档和帮助选项:使用注释在脚本中包含文档,并提供帮助选项(例如 -h 或 --help)来指导用户如何有效地使用脚本。
-
在函数中使用局部变量:定义函数时,使用局部变量来限制其范围并避免与全局变量发生意外的交互。
Shell 脚本的实际应用
-
基础设施自动化:AWS 依靠 Shell 脚本来自动执行许多基础设施管理任务。例如,Shell 脚本可以自动创建新服务器、配置资源和管理更新,从而确保其庞大基础设施的一致性和可靠性。
-
例行检查:Google 使用 Shell 脚本自动执行常规系统管理任务,例如用户帐户管理、日志文件维护和系统资源监控。这种自动化有助于维护系统的健康和稳定性。
-
配置管理:Shell 脚本确保应用程序的所有设置正确且一致。它们可以设置数据库配置、管理应用程序与其他服务的交互方式以及处理日志管理。
-
部署应用程序:Shell 脚本可用于通过打包应用程序、将其复制到服务器以及将其配置为在所需环境中运行来自动化应用程序部署。
进一步学习资源
结论
是的,终于结束了。我们深入探索了 Shell 脚本的深度和广度,见证了它如何在各种规模的组织(包括 AWS 和 Google 这样的巨头)中,为 DevOps、系统管理、数据处理等领域的关键任务提供支持。通过自动化日常任务、管理配置、监控系统和促进部署,Shell 脚本仍然是不可或缺的工具。
如果您喜欢整个教程,请考虑分享给真正需要的人,并关注我以获取更多类似内容。
付费合作请发送邮件至:harshit77dev@gmail.com
欢迎通过Twitter、LinkedIn、Youtube、Github联系我。
再次感谢!