第三节 Shell 脚本和编程
学习 shell 的价值:
-
Linux 服务器的基本操作和管理
-
前端 Node.js 服务的进程管理、问题排查、资源监控等运维操作
-
使用 shell 编写TCE、SCM、Docker 脚本,完成服务编译和部署
一、Shell 基础概念
概念:
- 终端:获取用户输入、展示运行结果的硬件设备
- tty:teletypeWriter的简称,和终端等价,早期指电传印机. 在linux 中是输入/输出环境
- 终端模拟器:Mac Terminal、 iTerm2等,关联虚拟 tty 的输入输出软件
- Shell:command interpreter ,处理来自终端模拟器的输入,解释执行之后输出结果给终端
- Bash:shell的—种具体实现
发展:
- 1971 为UNIX开发第一个shell ,称V6 shell
- 贝尔实验室为V7 UNIX开发的 Bourne shell 即sh
- 为了取代Bourne shell开发的Bourne-Again shell即 Bash
构成:
- 解释器:bash 内置命令、GNU核心工具集、第三方库
- 编程语音:变量、运算、语句、函数
二、命令和语法
变量:
- 类型:自定义变量 当前 shell 声明方式:=
- 类型:环境变量 当前 shell 及其子 shell 声明方式:export、declare -x
- 类型:系统环境变量 所有 shell 声明方式:启动加载
自定义变量:
declare [+/-] 选项 变量
- 选项:- 含义:给变量设定类型属性
- 选项:+ 含义:取消变量的类型属性
- 选项:-a 含义:将变量声明为数组类型
- 选项:-i 含义:将变量声明为整数型
- 选项:-x 含义:将变量声明为环境变量
- 选项:-r 含义:将变量声明为只读变量
- 选项:-p 含义:显示指定变量的被声明的类型
管道:
管道与管道符|,作用是将前一个命令的结果传递给后面的命令
- 语法:cmd1 | cmd2
- 要求:管道右侧的命令必须能接受标准输人才行,比如l grep命令, ls、mv等不能直接使用,可以使用xargs预处理
- 注意: 管道命令仅仅处理stdout,对于stderr会予以忽略, 可以使用set -o pipefail设置 shell遇到管道错误退出
重定向:
- 输出重定向符号:
- 1)>:覆盖写入文件
- 2)>>:追加写入文件
- 3)2>:错误输出写入文件
- 4)&>:正确和错误输出统一写入到文件中
- 输人重定向符号:
- 1)<
- 2)<<
判断命令:
shell中提供了test、[、[[三种判断符号,可用于:
- 整数测试
- 字符串测试
- 文件测试
语法:
- test condition
- [ condition ]
- [[ condition ]]
注意:
- 中括号前后要有空格符;
- [和l test是命令,只能使用自己支持的标志位,<、>、=只能用来比较字符串
- 中括号内的变量,最好都是用引号括起来
- [[更丰富,在整型比较中支持<、>、=,在字符串比较中支持=~正则
循环:
- while循环 while condition ; do程序段;done
- until循环 until condition ; do程序段;done
- for循环 for var in [words...]; do程序段;done
函数:
语法一: funcName(){ echo "abc"; }
语法二: function funcName() { echo "abc"; }
注意:
- shell自上而下执行,函数必须在使用前定义
- 函数获取变量和 shell script类似,1、$2 ...获取
- 函数内return 仅仅表示函数执行状态,不代表函数执行结果
- 返回结果一般使用echo、printf,在外面使用$()、“获取结果
- 如果没有return ,函数状态是上一条命令的执行状态,存储在$?中
模块化:
模块化的原理是在当前shell内执行函数文件,方式: source [函数库的路径]
三、执行过程和原理
shell脚本一般以.sh结尾,也可以没有,这是一个约定;第一行需要指定用什么命令解释器来执行
#!/bin/bash
#!/usr/bin/env bash
2、启动方式
- #文件名运行
- ./filename.sh
- #解释器运行
- bash ./filename. sh
- #source运行
- source ./filename.sh
执行过程:
- 字符解析
- 识别换行符、分号(:)做行的分割
- 识别命令连接符(&&管道)做命令的分割
- 识别空格、 tab符,做命令和参数的分割
-
shell展开,例如{1..3}解析为123
-
重定向,将stdin、 stdout、 stderr的文件描述符进行指向变更
-
执行命令
- builtin直接执行
- 非 builtin使用$PATH查找,然后启动子进程执行
- 收集状态并返回
shell展开:
- 大括号展开(Brace Expansion) { ...}
- 一般由三部分构成,前缀、一对大括号、后缀,大括号内可以是逗号分割的字符串序列,也可以是序列表达式区{x..y [..incr]}
- 波浪号展开(Tilde Expansion)~
- 参数展开(Shell Parameter Expansion)
- 命令替换(Command Substitution)
- 数学计算(Arithmetic Expansion)$((..))
- 使用$(())包裹数学运算表达式,得到结果并替换
- 文件名展开(Filename Expansion) * ?[..]外壳文件名模式匹配
- 当有单词没有被引号包裹,且其中出现了‘*’, ‘?’, and‘[’字符,则shell 会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变。
四、调试和前端集成
调试:
- 普通log,使用echo、printf
- 使用set命令
- vscode debug插件
VSCode 配置:
- shellman:代码提示和自动补全
- shellcheck:代码语法校验
- shell-format:代码格式化
- Bash Debug:支持单步调试
- 安装vscode插件
- 编写launch.json文件
- 升级bash到4.x 以上版本
前端集成:
- node中通过exec、spawn调用shell命令
- shell脚本中调用node命令
- 借助zx等库进行javascript、 shell script的融合
- 借助shell完成系统操作,文件io、内存、磁盘系统状
- 借助nodejs 完成应用层能力,网络io、计算等