Linux下Shell脚本基础知识

主要参考视频:

这可能是B站讲的最好的Linux Shell脚本教程,3h打通Linux-shell全套教程,从入门到精通完整版_哔哩哔哩_bilibili

主要参考文档:

Shell 教程 | 菜鸟教程 (runoob.com)

Bash Shell教程 (yiibai.com)

先用视频入门,然后参考手册学习,之后实践总结。 

认识Shell和Bash

计算机里,我们基本都会使用操作系统,对于开发人员来说,我们肯定需要控制操作系统做一些事情,但是有个问题,那就是出于安全性考虑我们用户层没法直接访问操纵系统的内核,这种情况下,就有人提出解决方案,那就是在内核操作上套一层“壳”,也就是Shell,然后提供给用户一些指令,用户层再通过指令去完成要干的活,这样,就避免了直接操作内核,保证了内核的安全性以及系统的稳定性。

Shell命令就是由此而来,Shell命令按照一定格式组成的文本就是Shell脚本。

那Bash是怎么回事呢?

有Shell命令,那肯定要有命令的解释器,也就是将输入的命令转换成实际操作系统内核要干的活,其中,Bash就是Shell命令的解释器。

有了一种解释器,肯定就有它的优点和缺点,必然就会出现其他种类的解释器,各有各的特点,各有各的适用场景,于是,市场上就出现了多种Bash。

事实上,不同的Bash对应的Shell也有些不同。

Linux中默认使用Bash,我们操作Linux就需要学习各种Bash Shell。

Linux操作系统中有不同类型的Shell。其中一些如下:

  • Bourne Shell
  • C shell
  • Korn Shell
  • GNU Bourne Shell

要想知道操作系统支持哪种Shell类型,可在终端中输入以下命令:

cat /etc/shells

要想知道bash在操作系统中的位置,可键入以下命令,将获得一个特定的位置:

which bash

如下:

显示的都是绝对路径。 

Bash是Linux附带的标准Shell。它是当今最流行的开源Shell,并且具有在下一主题中阅读的各种生产功能。它也可用于Linux发行版,MacOS,Solaris 11和Windows 10。它通过许多改进为用户提供最佳体验。

Bash脚本

创建和执行

在计算机编程中,脚本是用于适当的运行时环境的一组命令,这些命令用于自动执行任务。

Bash Shell脚本是一个纯文本文件,其中包含一组通常在命令行中键入的各种命令。它用于在Linux文件系统上自动执行重复性任务。它可能包含一组命令或一个命令,或者可能包含命令式编程的标志,例如循环,函数,条件构造等。实际上,Bash脚本是用Bash编程语言编写的计算机程序。

如何创建和运行Bash脚本?

  1. 首先,使用cd命令进入保存脚本的目录;
  2. (如果已有脚本则跳过,否则)使用touch命令创建零字节大小的脚本,脚本以.sh作为扩展名(经验证,不以.sh结尾也可以,事实上,linux中没有扩展名的概念,之所以常常写扩展名,是为了方便人为查看);
    touch file_name
    
  3. 打开文本,并输入bash脚本的shell命令;
  4. 使用chmod赋予该脚本以可执行的权限(这一步别忘了,要不文件没有可执行权限);
  5. ./file_name来执行bash脚本(不在当前目录下就需要输入绝对路径或者相对路径);

比如,创建一个脚本,并输入如下内容:

#! /bin/bash
echo Hello World!

然后执行。

就会在终端打印出Hello World!

注意,shell中的命令没有什么静默输出的概念,比如echo xxx,就只会输出xxx,不像makefile中,还能通过@或者-s来控制是否把指令以及指令的结果一起输出,别搞混了。总之,shell就是linux命令的集合,linux中执行是什么样,shell中执行的结果就是什么样。

shell脚本的几种执行方式

Shell脚本在Linux系统中的执行方式主要有以下几种:

  1. 使用bash命令:通过bash命令执行脚本,例如bash script-name。这种方式不需要脚本文件具有可执行权限,也不会创建子Shell。

  2. 使用sh命令:与bash类似,可以使用sh命令来执行脚本,如sh script-name。这同样不需要脚本具备可执行权限,但可能会依赖于系统默认的解释器。

  3. 赋予可执行权限后直接执行:将脚本文件的权限设置为可执行(chmod a+x script-name),然后直接运行脚本,如./script-name或指定绝对路径执行。这种方式会在当前目录下创建一个子Shell来执行脚本中的命令。

  4. 使用source命令:通过source命令执行脚本,如source script-name或者简写为. script-name。这种方式不会创建新的子Shell,而是在当前Shell环境中读取并执行脚本内容。这意味着脚本中定义的变量和函数会影响当前Shell环境,并且可以访问当前Shell中的变量。

总的来说,这些执行方式各有特点和适用场景,可以根据实际需求选择合适的方法来执行Shell脚本。

开头

每个基于Bash的Linux脚本都以以下行开头:

#!/bin/bash

这里#!称为shebang,该行的其余部分是解释器的路径,用于指定bash shell在操作系统中的位置。

shebang的格式很重要,格式不正确会导致命令工作不正常。因此,在创建脚本时,要始终记住SheBang格式的这两点:

  • 它应该始终在脚本的第一行。
  • #!和解释器的路径之间,#之前不应有任何空格。

经测试,貌似有空格也可以,不过,还是应当遵循标准规范。

注意,单独的#是注释。

注意,linux中路径是以撇/来分隔的,在windows下是以捺\作为分隔的。

echo

echo是bash中常用的linux命令

echo是Bash中的内置命令,用于通过传递参数来显示标准输出。它是用于将文本/字符串行打印到屏幕上的最广泛使用的命令。

echo命令 – 输出字符串或提取后的变量值 – Linux命令大全(手册) (linuxcool.com)

单独的echo可以打印出空行。

比如:

显示结果定向至某个文件,也就是将显示结果写到某个文件里,其中>是重定向符号。

echo "It is a test" > myfile

echo会自动回车换行。

Linux Shell中的echo命令详解 - 知乎 (zhihu.com)

Linux echo命令(在终端输出文本)_echo输出命令结果-优快云博客

关于引号

关于有无引号?

如果字符串是个整体,其实可以不用引号,shell也能识别为一个字符串。

但是,当字符串中有空格时,就有问题了,这是因为Bash使用空格来确定单独的项目。 这种情况下,引号就可以用于处理带有空格字符的文本和文件名。

关于单引号和双引号?

使用简单的文本和字符串时,我们使用单引号或双引号都不会有任何区别

但是,当涉及到变量引用时,就有区别了。

shell变量扩展仅适用于双引号。如果在单引号中定义变量,则不会将其视为变量。

下面通过一个例子来理解这一点:

变量

变量部分内容可参考:

Shell 变量 | 菜鸟教程 (runoob.com)

之所以不能有空格,是因为bash是通过空格作为分隔的。

对于Bash,不必在变量声明时定义变量的数据类型。Bash变量是无类型的,只需通过分配其值来键入变量名称,它会自动判断数据类型。

如果将数字值分配给变量,它将自动转为整数工作,如果将字符值分配给该变量,则它将转为字符串类型。

year=2012  
comp_name=yiibai

使用echo命令,通过在名称之前加上美元($)号来读取它们,例如:

echo $year
echo $name

Shell或UNIX系统中都有两种类型的变量。

  • 系统定义的变量
  • 用户定义的变量

系统定义的变量

是由LINUX操作系统本身创建和维护的预定义变量。它们的标准约定是通常以大写字母进行定义。因此,每当看到以大写字母定义的变量时,很可能它们就是系统定义的变量。要了解系统中这些变量的列表,请在命令行终端上键入命令env或者printenv

用户定义的变量

这些变量由用户创建和维护。通常,这些类型的变量以小写形式定义。但是不强制的,也可以将变量名称写成大写。如下简单示例:

变量的操作

通常对Bash中的变量执行两个操作,如下所示:

  • 为变量设置值。
  • 读取变量的值。

设置变量值有几种方式,其中最常见的方法是直接设置值。

参考:Shell 变量 | 菜鸟教程 (runoob.com)

使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

推荐给所有变量加上花括号,这是个好的编程习惯。

Bash检查识别每个变量后,它将用分配的值替换每个变量名。它解释/运行每一行代码,并针对脚本的每个编码行继续执行此过程。

注:Bash中的两种变量都可以在终端以及Bash脚本上使用

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

删除变量

使用 unset 命令可以删除变量。语法:

获取字符串长度

注意,Makefile中引用变量也是使用美元符号$,不过Makefile中引用变量时可以不加括号,可以加花括号${},也可以加圆括号$(),但是shell里,也就是linux命令中,不支持圆括号来引用变量,比如:

数组

参考:Shell 变量 | 菜鸟教程 (runoob.com) 

Shell 数组 | 菜鸟教程 (runoob.com)

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。

类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。

定义数组

在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:

数组名=(值1 值2 ... 值n)

例如:

array_name=(value0 value1 value2 value3)

注意,数组不需要指定大小。

传递参数

参考:Shell 传递参数 | 菜鸟教程 (runoob.com)

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为 $n,n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。 

例如可以使用 $1、$2 等来引用传递给脚本的参数,其中 $1 表示第一个参数,$2 表示第二个参数,依此类推。

另外,还有几个特殊字符用来处理参数:

在Shell脚本中,${@:n} 是一种参数扩展语法,用于访问传递给脚本或函数的所有位置参数(即命令行参数),但是选取时从第n个参数开始。

我们以${@:2} 为例讲解

具体来说:

  • ${@} 表示所有的位置参数。
  • ${@:2} 表示从第二个参数开始的所有参数。

举个例子,假设你有一个名为 example.sh 的脚本,内容如下:

#!/bin/bash
echo "All parameters: ${@}"
echo "Parameters from the second one onwards: ${@:2}"

如果你运行这个脚本并传递一些参数:

./example.sh arg1 arg2 arg3 arg4

输出将会是:

All parameters: arg1 arg2 arg3 arg4
Parameters from the second one onwards: arg2 arg3 arg4

详细解释

  • ${@} 会将所有传递给脚本的参数展开为一个字符串,每个参数之间用空格分隔。在这个例子中,${@} 的值是 arg1 arg2 arg3 arg4

  • ${@:2} 则从第二个参数开始,将剩余的参数展开为一个字符串。在这个例子中,${@:2} 的值是 arg2 arg3 arg4

这种用法在处理命令行参数时非常有用,尤其是在需要跳过第一个参数而只处理后续参数的情况下。

命令替换

其实就是获取命令执行的结果作为最终的内容。

替换的经典形式是使用反引号,如下所示:

也可以通过将命令放在圆括号(以美元符号($)开头)中来进行命令替换。如下:

示例:

从这里也能看出来为什么引用变量时不能使用圆括号$(),因为圆括号有别的用处,那就是用来执行linux命令,这就是为什么这个图里的报错是“命令未找到”

读取用户输入

读取Bash用户输入,需要使用内置的Bash命令read。它用于从用户处获取输入并分配给变量。它仅从Bash shell中读取一行。以下是read命令的语法。

read <variable_name>

以下是从Bash脚本读取用户输入的示例:

运算符

Shell 和其他编程语言一样,支持多种运算符,包括:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):

反引号,其实就是将expr命令执行的结果作为最终的结果值。

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,而是在 Esc 键下边的反引号。

更多直接参考

Shell 基本运算符 | 菜鸟教程 (runoob.com)

注意:注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。注意,这里面有四个空格,从方括号开始后面就有空格了。

比较新奇的一个字符串运算符

不同的运算符还得用不同的括号,三种括号,[]、[[]]、(()),还有个反引号``,还蛮复杂的。

算数运算符时,用expr加反引号``

乘号需要加转义,乘号(*)前边必须加反斜杠(\)才能实现乘法运算;

比较数字的大小关系时,可以用==、!==

或者这些符号

建议使用第二种方式比较数字大小

逻辑符号&&和||在使用时,必须使用双方括号[[ && ]],否则不识别。

shell(13): Shell脚本,if语句使用方双括号_shell if 双括号-优快云博客

字符串运算符

暂时掌握这些基本用法。

增强型的括号形式,后面再陆续补充吧。

条件语句-if

注意:在 sh/bash 里,如果 else 分支没有语句执行,就不要写这个 else分支。

Shell 流程控制 | 菜鸟教程 (runoob.com)

以if开头,以fi结尾。

有if就要搭配then,最后分支的else可以不用。

条件放在方括号[……]里。我看两个参考文档里,有的说条件后要加分号,有的又没有加,比较混乱。参考下这篇:shell中的if语句 - 开始认识 - 博客园 (cnblogs.com)

再参考这篇:

Shell if else语句(详解版) (biancheng.net)

可知:

当then和if处于同一行时,分号;才是必须的。

双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
注意:(( )) 只能进行整数运算,不能对小数(浮点数)或者字符串进行运算

shell中if后面可以不加方括号吗?

在Shell脚本中,if 语句后面通常需要使用方括号 [ ] 来包围条件表达式。这是因为方括号实际上是一个命令,它用于测试条件是否为真。

例如:

if [ "$a" -eq "$b" ]; then
    echo "a is equal to b"
fi

在这个例子中,[ "$a" -eq "$b" ] 是一个条件测试,它会返回一个退出状态码(0表示真,非0表示假)。

然而,在某些情况下,你可以省略方括号,但这样做有一些限制和注意事项:

1、使用 [[ ]] 进行条件测试

[[ ]] 是 Bash 的扩展语法,提供了更强大的功能和更好的错误处理。它可以替代 [ ],并且不需要转义某些特殊字符。

if [[ "$a" -eq "$b" ]]; then
    echo "a is equal to b"
fi

2、使用 test 命令

你也可以使用 test 命令,它与 [ ] 等价。

if test "$a" -eq "$b"; then
    echo "a is equal to b"
fi

3、使用 (( )) 进行算术比较

对于算术比较,可以使用 (( ))

if (( a == b )); then
    echo "a is equal to b"
fi

4、使用命令的退出状态码

你可以直接使用命令的退出状态码来判断条件。

if grep -q "pattern" file; then
    echo "pattern found in file"
fi

在这个例子中,grep -q "pattern" file 的退出状态码直接用于判断条件。

这种情况下,加方括号[ ]反而会出错?

总结

虽然可以省略方括号 [ ],但为了代码的可读性和兼容性,建议尽量使用 [ ][[ ]]test 命令来进行条件测试。这样可以避免一些潜在的问题,并确保脚本在各种Shell环境中都能正确运行。

在Shell脚本中,退出状态码(exit status)用于表示命令的执行结果。具体来说:

  • 0 表示真(true),即命令成功执行且没有遇到错误。

  • 非零值 表示假(false),即命令执行失败或遇到了某种错误。

示例

以下是一些常见的命令及其返回码:

$ ls /home/user
# 如果目录存在且有权限访问,则返回码为 0

$ echo "Hello, World!"
# 输出字符串并成功执行,返回码为 0

$ cp source.txt destination.txt
# 如果文件复制成功,返回码为 0

检查返回码

你可以使用特殊变量 $? 来检查上一个命令的返回码。例如:

$ ls /home/user
$ echo $?
# 输出 0 表示命令成功执行

条件判断

在Shell脚本中,可以使用条件判断来处理不同的返回码。例如:

#!/bin/bash

if ls /home/user; then
    echo "Command succeeded"
else
    echo "Command failed with return code $?"
fi

在这个例子中,如果 ls /home/user 命令成功执行,脚本会输出 "Command succeeded";否则,它会输出 "Command failed with return code" 以及实际的返回码。

shell中的这个判断逻辑,和C语言等,以及常规思维有所差别,所以要万分注意!

其实这就是因为linux中,命令执行成功时会返回0,所以,shell中判断0为真,其实就是判断命令执行成功了。

Shell中,会将前一条指令执行完,再执行下一条指令。

比如,前一条指令执行了10分钟,那么下一条指令就需要等10分钟后才会执行。

从上面的if例子就能看出来。

选择语句-case

case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。

可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。

case ... esac 语法格式如下:

更多参考:

Shell 流程控制 | 菜鸟教程 (runoob.com)

示例1:基本用法

#!/bin/bash

echo "请输入一个数字(1-3):"
read num

case $num in
    1)
        echo "你选择了数字 1"
        ;;
    2)
        echo "你选择了数字 2"
        ;;
    3)
        echo "你选择了数字 3"
        ;;
    *)
        echo "无效的数字"
        ;;
esac

示例2:处理多个模式

#!/bin/bash

echo "请输入一个字符:"
read char

case $char in
    [a-z])
        echo "你输入的是一个小写字母"
        ;;
    [A-Z])
        echo "你输入的是一个大写字母"
        ;;
    [0-9])
        echo "你输入的是一个数字"
        ;;
    *)
        echo "你输入的不是一个字母或数字"
        ;;
esac

这个示例中,用户被提示输入一个字符,然后通过case语句判断该字符是小写字母、大写字母还是数字,或者都不是。

循环语句

Shell 流程控制 | 菜鸟教程 (runoob.com)

for循环 while循环 until循环

for循环

shell三种 for循环方式_shell 循环100次-优快云博客

参考:

Bash for循环 - Bash Shell教程 (yiibai.com)

注意,for-in中列表是以空格来分开每一项。

更多直接参考:

Shell 流程控制 | 菜鸟教程 (runoob.com)

函数

直接参考即可:

Bash函数 - Bash Shell教程 (yiibai.com)

函数里再使用$n,其实表示的是传递进入的参数了。不再是命令行传递进入的那个。

变量的作用域

全局变量定义为可以在脚本内的任意位置访问的变量,而不管它的范围如何。默认情况下,所有变量都定义为全局变量,即使它们在函数内部声明也是如此。还可以将变量创建为局部变量。可以使用local关键字在函数体内声明局部变量。首次分配关键字时。它们只能在该函数内部访问。可以在不同的函数中创建具有相同名称的局部变量。要添加局部变量,使用以下语法:

local var_name=var_value

为了更好地理解变量作用域如何在Bash脚本中工作,请查看以下示例:

在上面输出中,如果在函数体内设置与全局变量同名的局部变量,则它将优先于全局变量(即,局部变量覆盖全局变量)。可以在函数内修改全局变量。

文件包含

和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。

Shell 文件包含的语法格式如下:

在shell编程中,source命令用于在当前shell环境中执行指定的脚本文件。这意味着脚本文件中的所有变量和函数都将在当前shell会话中可用。

Linux下source命令详解

Linux下source命令详解 - 水车 - 博客园 (cnblogs.com)

source命令其实算不上是什么导入,就是在当前shell环境中执行一个指定的shell脚本,只不过最终效果和导入是一样的。

在C语言中,#include用于将指定的头文件包含到源文件中,以便在编译时插入头文件的内容,提供函数声明、宏定义、类型定义等。而在Shell脚本中,没有直接的“包含”其他文件内容作为脚本一部分的预处理指令。不过,Shell脚本可以通过source命令或.操作符来引入另一个脚本文件的内容,但这与C语言中的#include有本质区别。例如:

  • C语言:#include "stdio.h" 是将标准输入输出库的头文件包含进来。

  • Shell脚本:source another_script.sh 是将 another_script.sh 脚本中的命令在当前Shell环境中执行,相当于把该脚本的内容复制到当前脚本中依次执行。

shell格式规范建议

在Shell脚本或命令行中编写指令时,有一些基本的格式要求和最佳实践,以确保脚本的可读性和可维护性。以下是一些常见的格式要求:

使用空格分隔参数

每个命令、选项和参数之间应该用空格分隔。例如:

ls -l /home/user

使用引号包围包含空格的字符串

如果参数中包含空格,需要使用单引号 (') 或双引号 (") 将其包围。例如:

echo "Hello, World!"

使用变量时加上花括号

在引用变量时,最好使用花括号 {} 来避免歧义。例如:

echo "Home directory is ${HOME}"

使用反斜杠转义特殊字符

如果需要在字符串中使用特殊字符(如 $, \, "),可以使用反斜杠 \ 进行转义。例如:

echo "This is a backslash: \\"

使用注释解释代码

注释可以帮助理解代码的意图,使用 开头的行作为注释。例如:

# This script lists all files in the current directory
ls -l

保持缩进一致

虽然shell脚本对命令的缩进没什么要求,不像makefile里一样要求规则中的命令以Tab开头,注意别搞混了。

不过,对于多行命令或复杂的脚本,还是建议保持缩进一致可以提高可读性。例如:

if [ -f "/etc/passwd" ]; then
    echo "File exists"
else
    echo "File does not exist"
fi

使用适当的退出状态码

确保脚本在错误情况下返回非零退出状态码,以便调用者能够检测到错误。例如:

if [ ! -f "/etc/passwd" ]; then
    echo "File does not exist"
    exit 1
fi

使用绝对路径

尽量使用绝对路径而不是相对路径,以避免路径解析问题。例如:

/usr/bin/python3 script.py

避免硬编码路径和值

将路径和常量值提取为变量,以提高脚本的灵活性和可维护性。例如:

LOG_DIR="/var/log/myapp"
LOG_FILE="${LOG_DIR}/app.log"

使用函数封装重复代码

将重复使用的代码段封装成函数,提高代码的复用性和可读性。例如:

function log_message {
    echo "$(date): $1""${LOG_FILE}"
}
log_message "Starting script"

遵循这些格式要求和最佳实践,可以编写出更清晰、更易维护的Shell脚本。

补充

当Shell脚本运行时,它会先查找系统环境变量ENV,该变量指定了环境文件(加载顺序通常是/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc等),在加载了上述环境变量文件后,Shell就开始执行Shell脚本中的内容。

Shell脚本是从上至下、从左至右依次执行每一行的命令及语句的,即执行完了一个命令后再执行下一个,如果在Shell脚本中遇到子脚本(即脚本嵌套)时,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内后续的命令及语句。

通常情况下,在执行Shell脚本时,会向系统内核请求启动一个新的进程,以便在该进程中执行脚本的命令及子Shell脚本。

exit 命令退出shell,判断上一个命令是否执行成功,可用 echo $? ,为0,表示执行成功,不为0表示失败。失败时,可以使用exit命令退出整个shell脚本的进程。

Shell中函数不调用就不会被执行。 

shift,输入参数左移命令

Linux shell脚本中shift的用法说明_shell shift-优快云博客

shift命令用于对参数的移动(左移),通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理(常见于Linux中各种程序的启动脚本) 。

每执行一次shift,参数就左移一位。

Bash Shell - shell 编程 | shift 命令用法笔记 - 《技术私房菜》 - 极客文档 (geekdaxue.co)

Linux—shell中$(( ))、$( )、``与${ }的区别 - chengd - 博客园 (cnblogs.com)

dirname,获取路径的命令

Linux dirname命令教程:如何从给定的路径或文件名中提取目录(附实例用法详解和注意事项)-Linux入门自学网 (bashcommandnotfound.cn)

dirname命令是一个用于从给定的路径或文件名中提取目录部分的有用工具。

不过,该命令获取的是相对路径。

realpath,用于获取指定目录或文件的绝对路径。 

Linux 命令:realpath 命令-优快云博客

readlink命令

readlink命令 – 找出符号链接所指向的位置 – Linux命令大全(手册) (linuxcool.com)

readlink命令来自英文词组“read link”的拼写,中文译为“读取链接”,其功能是用于找出符号链接所指向的位置。

trap命令用于指定在接收到信号后将要采取的动作,常见的用途是在脚本程序被中断时完成清理工作。

trap命令 – 指定采取的动作 – Linux命令大全(手册) (linuxcool.com)

shell里没有命令要tab开头的语法要求,是makefile里有。 

Shell里的变量默认都是全局的。

shell中局部变量及local命令_shell local-优快云博客

函数里的全局变量是指从调用函数并执行时开始生效。

Shell脚本,或者脚本语言,是解释性的,不是提前编译的,所以,如果有什么语法错误,只有执行到对应行的时候才能知道。没法提前知道。 

shell脚本其实就是一系列linux命令的集合,然后加了一些shell语法,以此来实现自动化执行这些命令。 

shell命令和shell脚本有哪些区别?

shell命令和shell脚本存在显著区别,主要体现在以下几个方面:

定义与形式

Shell命令:是用户在命令行提示符下输入的、由shell解释执行的单个指令,如“ls”命令用于列出目录内容,“cd”命令用于切换工作目录等。

Shell脚本:是将一系列shell命令集中写在文件中,并添加了控制语句和流程控制的结构,如if条件判断、for循环等,形成一个可执行的脚本文件,通常以“.sh”作为扩展名。

执行方式

Shell命令:用户在终端中逐行输入命令,按下回车键后,shell立即对命令进行解析和执行,并返回结果。例如,在终端输入“pwd”命令,shell会立即返回当前工作目录的路径。

Shell脚本:需要先通过shell解释器来执行整个脚本文件。用户可以在终端中使用“sh 脚本文件名”“bash 脚本文件名”或“./脚本文件名”(前提是脚本文件具有可执行权限)等方式来运行脚本。

功能与用途

Shell命令:主要用于完成一些简单的、一次性的操作任务,如文件和目录的管理、系统信息的查看、软件的安装与卸载等。比如使用“mkdir”命令创建新目录,“rm”命令删除文件或目录等。

Shell脚本:更适用于复杂的、需要多次重复执行的任务,以及对多个命令进行批量处理的场景。可以将一系列的操作步骤编写在一个脚本中,实现自动化执行,提高工作效率。例如,编写一个备份脚本,可以定期自动备份指定目录下的文件到另一个存储位置。

可读性与维护性

Shell命令:通常是简洁明了的单个指令,易于理解和记忆,但当需要完成复杂任务时,可能需要组合多个命令,并且命令行参数较多时,可读性和可维护性会降低。

Shell脚本:由于可以添加注释和合理的代码结构,使得脚本的逻辑更加清晰,易于阅读和理解。同时,对于需要修改和维护的部分,也更容易进行定位和调整。

综上所述,shell命令是用户与操作系统交互的基础工具,而shell脚本则是将这些工具组合起来,形成更强大的自动化解决方案。两者相辅相成,在不同的应用场景中发挥着各自的作用。

所谓shell脚本,不过就是若干shell命令加上一些结构化的语法,方便进行自动化批处理。shell脚本中用到的命令其实就是shell命令。

Shell的调试模式

在Linux中,set -x 是一个用于调试Shell脚本的命令。它的作用是打开Shell的调试模式,使得脚本在执行过程中会显示每一行命令及其执行结果。这对于查找和解决脚本中的错误非常有用。

解释

当你在Shell脚本中使用 set -x 时,Shell会在标准错误输出(通常是终端)上打印出每一条被执行的命令,以及这些命令的执行结果。这样,你可以清楚地看到脚本的执行流程,并更容易地定位问题所在。

示例

假设有一个简单的Shell脚本 example.sh

如果你在脚本中添加 set -x,如下所示:

然后运行这个脚本,你会看到类似以下的输出:

关闭调试模式

如果你想关闭调试模式,可以使用 set +x。例如:

在这个例子中,set +x 之后的 echo "This will not be traced" 将不会被跟踪和显示。

总结

  • 作用set -x 用于打开Shell脚本的调试模式,显示每条被执行的命令及其结果。

  • 使用场景:主要用于调试Shell脚本,帮助开发者快速找到和解决问题。

  • 关闭方法:使用 set +x 可以关闭调试模式。

通过合理使用 set -x,你可以更高效地开发和维护Shell脚本,提高脚本的可靠性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值