Shell脚本和编程
学习shell的价值
- Linux服务器的基本操作和管理
- 前端Node.js服务的进程管理、问题排查、资源监控等运维操作
- 使用shell编写TCE、SCM、Docker脚本,完成服务编译和部署
Shell基本概念
基本概念
Shell(也称为命令行界面或终端)是一种通过文本输入和输出进行交互的计算机用户界面。它允许用户通过输入命令来执行操作、运行程序和管理系统
- 命令(Command):Shell通过输入命令来执行不同的操作或任务,例如创建文件、复制文件、移动文件、运行程序等。命令通常由命令名和参数组成,命令名指定要执行的操作,参数用于指定命令的具体操作方式或作用对象。
- 提示符(Prompt):Shell在等待用户输入命令时会显示一个提示符,通常是一个特殊的字符或字符串,表示Shell已经准备好接受命令输入。
- 文件系统(File System):Shell可以用于管理计算机上的文件和目录,包括创建、复制、移动、删除、重命名、查看等操作。Shell使用文件系统的路径来定位文件和目录,例如绝对路径(从根目录开始的完整路径)和相对路径(从当前目录开始的相对路径)。
- 管道(Pipeline):Shell允许将多个命令通过管道连接起来,其中一个命令的输出作为另一个命令的输入。这样可以实现多个命令的组合和协作,从而更加灵活地完成复杂的任务。
- 环境变量(Environment Variable):Shell使用环境变量来存储系统级别的配置信息、用户配置和运行时参数。环境变量可以在命令中使用,并且可以通过设置和修改来影响Shell的行为和操作。
- 脚本(Script):Shell允许用户编写一系列命令的脚本文件,以便将一组命令作为一个单独的程序运行。脚本可以包含条件语句、循环、函数等控制结构,从而实现更加复杂的自动化任务。
- 快捷键(Shortcut):Shell提供了许多快捷键和命令行编辑功能,用于提高命令行操作的效率和便捷性。例如,可以使用上下箭头键来浏览历史命令,使用Tab键进行命令和文件名的自动补全,使用Ctrl+C来中断正在执行的命令等。
Bash的历程
shell的构成
Unix shell既是一个命令解释器也是一种编程语言。作为命令解释器,shell为丰富的GNU工具集提供了用户接口
命令和语法
自定义变量
declare选项的含义
系统环境变量
-
$#表示当前脚本或函数的参数个数。在shell脚本中,可以通过$#来获取当前脚本或函数的参数个数,并根据参数个数执行相应的操作。 -
$*表示当前脚本或函数的所有参数列表。在shell脚本中,可以通过$*来获取当前脚本或函数的所有参数,并根据参数列表执行相应的操作。 -
$?表示上一个命令的退出状态码。在shell脚本中,可以通过$?来获取上一个命令的退出状态码,并根据状态码执行相应的操作。 -
$PS1表示shell提示符的格式。在shell中,可以通过修改$PS1来自定义shell提示符的格式,以适应个人习惯或需求。 -
$HOME表示当前用户的主目录。在shell脚本中,可以通过$HOME来获取当前用户的主目录,并根据主目录执行相应的操作。 -
$PATH表示系统的可执行文件路径列表。在shell中,可以通过修改$PATH来添加或删除系统的可执行文件路径,以便更方便地执行系统命令或自定义命令。
配置文件加载
运算符和引用
管道
管道与管道符 | ,作用是将前一个命令的结果传递给后面的命令 语法:cmd1 | cmd2
要求:管道右侧的命令必须能接受标准输入才行,比如grep命令,ls、mv等不能直接使用,可以使用xargs预处理
注意:管道命令仅仅处理stdout,对于stderr会予以忽略,可以使用set -o pipefail设置shell遇到管道错误退出
重定向
判断命令
shell中提供了test、[、[[三种判断符号,可用于:
- 整数测试
- 字符串测试
- 文件测试
语法:
- test condition
- [ condition ]
- [[ condition ]]
三种循环
while循环
while循环用于在条件成立的情况下重复执行一段代码块
unitil循环
until循环与while循环类似,不同之处在于until循环在条件不成立的情况下重复执行一段代码块
for循环
for循环用于遍历一组数据,并对每个数据执行相同的命令或者代码块
函数
在shell中,函数是一段可以重复使用的代码块,可以在脚本中定义并调用
案例演示: 定义了一个名为
hello的函数,函数的代码块中只有一条命令,用于输出“Hello, World!”。在定义完函数后,我们在脚本中通过函数名hello来调用函数,从而输出“Hello, World!”
注意点
-
shell自上而下执行,函数必须在使用前定义
-
函数获取变量和shell script类似,0代表函数名,后续参数通过0代表函数名,后续参数通过0代表函数名,后续参数通过1、$2..获取
-
函数内return仅仅表示函数执行状态,不代表函数执行结果
-
返回结果一般使用echo、printf,在外面使用$()、``获取结果
-
如果没有return,函数状态是上一条命令的执行状态,存储在$?中
模块化
模块化的原理是在当前shell内执行函数文件,方式:
- source[函数库的路径]
模块化命令
执行过程和原理
- shell脚本一般以.sh结尾,也可以没有,这是一个约定;第一行需要指定用什么命令解释器来执行
- 启动shell的三种方式
执行过程
-
字符解析
- 识别换行符、分号(;)做行的分割
- 识别命令连接符(||&&管道)做命令的分割
- 识别空格、tab符,做命令和参数的分割
-
shell展开,例如{1...3}解析为1 2 3
-
重定向,将stdin、stdout、stderr的文件描述符进行指向变更
-
执行命令
- builtin直接执行
- 非builtin使用$PATH查找,然后启动子进程执行
-
收集状态并返回给脚本
shell展开
Shell 展开是指在执行命令之前,Shell 预处理命令行中的各种特殊字符,将它们替换为实际的值或执行相应的操作
-
大括号展开(Brace Expansion):使用大括号
{}将一组字符串包含在命令行中,Shell 将展开大括号内的所有字符串,并将其作为命令行的一部分。例如:echo file{1..3}.txt将展开为file1.txt file2.txt file3.txt。 -
波浪号展开(Tilde Expansion):使用波浪号
~将用户名或路径名包含在命令行中,Shell 将展开波浪号并将其替换为相应的用户名或路径名。例如:cd ~/Documents将进入当前用户的 Documents 目录。 -
参数展开(Parameter Expansion):使用
$将变量名包含在命令行中,并使用一些特殊符号来修改变量的值或进行字符串操作。例如:${var:-default}表示如果变量$var未定义,则使用默认值default。 -
命令替换(Command Substitution):使用反引号或
$()将一个命令包括起来,Shell 将执行该命令并将其输出作为命令行的一部分。例如:echo "The date is $(date)"将输出当前日期和时间。 -
数学计算(Arithmetic Expansion):使用
$(( ))将一个算术表达式包含在命令行中,Shell 将计算该表达式并将其替换为计算结果。例如:echo $((1+2))将输出3。 -
文件名展开(Filename Expansion):使用通配符
*、?、[]等来匹配文件名或路径名。Shell 将展开通配符并将其替换为匹配的文件名或路径名。例如:ls *.txt将列出当前目录下所有扩展名为.txt的文件。
调试和前端集成
调试的方法
- 普通log,使用echo、printf
- 使用set命令
- vscode debug插件
Vscode插件配置
-
shellman:代码提示和自动补全
-
shellcheck:代码语法校验
-
shell-format:代码格式化
-
Bash Debug:支持单步调试
- 安装vscode插件
- 编写launch.json文件
- 升级bash到4.x以上版本
前端集成
- node中通过exec、spawn调用shell命令
2. shell脚本中调用node命令
3. 借助zx等库进行javascript、shell script的融合
- 借助shell完成系统操作,文件io、内存、磁盘系统状态查看
- 借助nodejs完成应用层能力,网络io、计算等