Kali Linux 上的 Bash 脚本基础知识
当我们学习 Linux 和终端时,我们不能离开 Bash 脚本。我们可以自动化有效负载和其他任务。在这篇文章中,我们将学习“ Bash 脚本”以及如何在 Linux 上编写准确的脚本。
Kali Linux 上的 Bash 脚本:GNU Bourne-Again Shell ( Bash ) 是一个强大的工具和脚本引擎。我们可以在命令行上自动执行许多任务。在本教程中,我们正在学习 Bash 脚本并了解一些实际用例。
01
Bash 脚本简介
Bash 脚本是一个纯文本文件,其中包含一系列命令,这些命令的执行就像在终端窗口上键入一样。一般来说,Bash 脚本有一个可选的.sh扩展名用于标识(但它可以在没有扩展名的情况下运行),以#!/bin/bash开头,并且在执行脚本之前必须设置可执行权限。让我们使用任何文本编辑器在新文件上编写一个简单的“Hello World”Bash 脚本,将其命名为hello-world.sh并在其中写入以下内容:
#!/bin/bash
# Hello World on Bash Script
echo “Hello World!”
然后保存并关闭它。在上面的脚本中,我们使用了一些需要解释的组件:
第 1 行:#! 称为 shebang,它会被 Bash 解释器忽略。第二部分/bin/bash是解释器的绝对路径,用于运行脚本。为此我们可以识别出这是一个“Bash 脚本”。有多种类型的 shell 脚本,如“zsh”和“C Shell 脚本”等。
第 2 行:#用于添加注释。解释器将忽略哈希 (#) 测试。这些注释将帮助我们对脚本进行特别注释。
第 3 行:回显“Hello World!” 使用 echo Linux 命令实用程序将给定字符串打印到终端,在本例中为“Hello World!” 。
现在我们需要通过运行以下命令使该脚本可执行:
chmod +x hello-world.sh
在下面的屏幕截图中,我们可以看到上述命令的输出:
现在我们可以使用以下命令运行脚本:
bash hello-world.sh
我们可以看到我们的脚本显示了“Hello World!”的输出。在我们的终端上,如下面的屏幕截图所示:
带有+x标志的chmod命令用于使 bash 脚本可执行,并且bash和scriptname.sh一起我们可以运行它。我们可以通过./scriptname.sh来运行脚本。这是我们的第一个 Bash 脚本。
02
变量
变量用于临时存储数据。我们可以声明一个变量来为其内部赋值,或者读取一个变量,这会将其“扩展”或“解析”为其存储值。
我们可以通过多种方式声明变量值。最简单的方法是使用简单的name=value声明直接设置值。我们应该记住,“=”符号之间或之后没有空格。
在我们的终端上我们可以运行以下命令:
name=Kali
然后我们再次运行另一个命令:
surname=Linux
除非我们可以使用/引用变量,否则变量声明是没有意义的。我们在变量前面添加$字符。每当 Bash 在命令中看到此 ( $ ) 语法时,它就会在执行命令之前将变量名称替换为其值。例如,我们可以使用以下命令回显此变量:
echo $name $surname
在下面的屏幕截图中,我们可以输出显示变量的值:
变量名称可以是大写、小写或两者的混合。Bash 区分大小写,因此我们在声明和扩展变量时必须保持一致。使用描述性变量名称的好习惯是,这使得我们的脚本更容易被其他人理解。
Bash 以特定方式解释某些字符。例如,以下声明演示了不正确的多值变量声明:
hello=Hello World
在下面的屏幕截图中,我们可以看到输出。
不是变量的例子
这不一定是我们所期望的。要修复此类错误,我们可以使用单引号(') 或双引号(") 来括住我们的文本。这里我们需要知道 Bash 对单引号和双引号的处理方式不同。当 Bash 遇到单引号时,Bash 会解释每个字面意义上的封闭字符。当用双引号括起来时,所有字符均按字面意思查看,“ $ ”和“ \ ”除外,这意味着变量将在封闭文本的初始替换过程中进行扩展。
在上述情况下,我们以下内容将有助于澄清:
hello=‘Hello World’
现在我们可以使用echo打印这个变量,如下图所示:
正确使用变量
在上面的示例中,我们使用单引号 (') 来使用变量。但是当我们将 hello 变量与其他变量一起使用时,我们需要使用双引号 ("),我们可以看到以下内容以便更好地理解:
hello2="hi,$hello"
现在我们可以在下面的屏幕截图中看到新的$hello2变量的打印(echo):
使用双引号的变量
我们还可以将变量的值设置为命令或脚本的结果。这也称为命令替换,它允许我们获取命令的输出(通常会打印到屏幕上)并将其保存为变量的值。
为此,请将变量名称放在括号“ () ”中,前面加上“ $ ”字符:
user=$(whoami)
echo$user
这里我们将whoami命令的输出分配给user变量。然后我们通过echo显示它的值。在下面的屏幕截图中,我们可以看到上述命令的输出:
在 bash 中将一个变量作为另一个变量
使用反引号 ( ` )进行命令替换的替代语法,如以下命令所示:
user2=`whoami`
echo $user2
这种反引号方法较旧,通常不鼓励使用,因为两种命令替换方法的行为方式存在差异。同样重要的是要注意,命令替换发生在子 shell 中,并且对子 shell 中的变量进行更改不会更改主进程中的变量。
03
论点
并非所有 Bash 脚本都需要参数。然而,理解 bash 如何解释它们以及如何使用它们是极其重要的。我们已经执行了带参数的 Linux 命令。例如,当我们运行命令ls -l /var/log时,-l和/var/log都是ls命令的参数。
Bash 脚本没有什么不同,我们可以提供命令行参数并在我们的脚本中使用它们。例如,我们可以看到以下屏幕截图:
向 bash 脚本提供参数
在上面的屏幕截图中,我们创建了一个简单的 Bash 脚本,为其设置了可执行权限,然后使用两个参数运行它。$1 和 $2 变量表示传递给脚本的第一个和第二个参数。让我们探讨一些特殊的 Bash 变量:
变量名 | 描述 |
$0 | Bash 脚本的名称 |
$1 - $9 | Bash 脚本的前 9 个参数 |
$# | Bash 脚本的参数数量 |
$@ | 传递给 Bash 脚本的所有参数 |
$? | 最近运行的进程的退出状态 |
$$ | 当前脚本的进程ID |
$user | 运行脚本的用户的用户名 |
$HOSTNME | 机器的主机名 |
$random | 一个随机数 |
$LINENO | 脚本中的当前行号 |
其中一些特殊变量在调试脚本时很有用。例如,我们也许能够获取命令的退出状态来确定它是否成功执行。
04
读取用户输入
命令行参数是用户输入的一种形式,但我们也可以在使用read命令运行脚本期间捕获交互式用户输入。我们将使用 read 来捕获用户输入并将其分配给一个变量,就像我们在下面的屏幕截图中所做的那样:
在 Bash 脚本上读取用户输入
我们可以使用各种命令行选项来改变读取命令的行为。两个最常见的标志包括-p和 -s , -p 允许我们指定提示,-s使用户输入静默/不可见(可能对凭据有帮助)。我们可以在下面的屏幕截图中看到一个示例:
在 bash 上静默读取用户输入
05
If、Else、Elif
If、Else、Elif 被认为是最常见的条件语句,它们允许我们根据不同的条件显示不同的操作。
if 语句非常简单。这会检查条件是否为真,但它需要非常特定的语法。需要小心注意这个语法,尤其是所需空格的使用。
bash 上的 if 语句
在上面的屏幕截图中,如果“某些语句”为真,脚本将“执行某些操作”,这些操作可以是then和fi之间的任何命令。让我们看一个实际的例子。
if 语句显示示例
在上面的示例中,我们使用if语句来检查用户输入的年龄。如果用户的年龄小于 ( -lt ) 12,脚本将输出警告消息。
这里上面if语句中的方括号([ &])最初引用的是 test 命令。这仅仅意味着我们可以使用测试命令允许的所有运算符。一些广泛使用的运算符包括:
-n VAR - 如果 VAR 的长度大于零,则为真。
-z VAR - 如果 VAR 为空则为真。
STRING1 = STRING2 - 如果 STRING1 和 STRING2 相等,则为 True。
STRING1 != STRING2 - 如果 STRING1 和 STRING2 不相等,则为 True。
INTEGER1 -eq INTEGER2 - 如果 INTEGER1 和 INTEGER2 相等,则为 True。
INTEGER1 -gt INTEGER2 - 如果 INTEGER1 大于 INTEGER2,则为 True。
INTEGER1 -lt INTEGER2 - 如果 INTEGER1 小于 INTEGER2,则为 True。
INTEGER1 -ge INTEGER2 - 如果 INTEGER1 等于或大于 INTEGER2,则为 True。
INTEGER1 -le INTEGER2 - 如果 INTEGER1 等于或小于 INTEGER2,则为 True。
-h FILE - 如果文件存在并且是符号链接,则为真。
-r FILE - 如果文件存在并且可读则为真。
-w FILE - 如果文件存在并且可写则为真。
-x FILE - 如果文件存在并且可执行,则为真。
-d FILE - 如果文件存在并且是目录,则为真。
-e FILE - 如果 FILE 存在并且是一个文件,则为 True,无论类型如何(节点、目录、套接字等)。
-f FILE - 如果 FILE 存在并且是常规文件(不是目录或设备),则为 True。
我们已将这些内容应用于上面的if语句示例,并使用测试字符串删除方括号。但我们认为方括号使代码更具可读性。
如果一个陈述为真而其他陈述为假,我们还可以执行一组特定的操作。为此,我们可以使用 else 语句,其语法如下:
bash 中的 else 语句
现在作为示例,我们扩展之前的年龄示例,包括else语句,如以下屏幕截图所示:
在 bash 示例中使用 else 语句
我们很容易注意到,当输入的年龄不小于12时,else语句被执行。
我们可以借助elif语句向语句添加更多参数。示例如下:
bash 上的 elif 语句
让我们在下面的屏幕截图中使用elif语句扩展我们的年龄示例:
在 bash 上使用 elif 语句
在上面的示例中,我们可以看到代码与if和else相比有点复杂。这里当用户输入年龄大于 60 时,将执行elif语句并输出“Salut ...”消息。