学习shell的价值:
- Linux服务器的基本操作和管理
- 前端Node.js服务的进程管理、问题排查、资源监控等运维操作
- 使用shell编写TCE、SCM、Docker脚本,完成服务编译和部署
课程准备
- 一台安装了 Linux 系统的物理机或者云主机,可运行 shell 脚本
- 本地的 vscode 安装 Bash Debag 插件,并升级 bash 到4.x以上
- Npm 全局安装 zx 依赖
1.Shell基础概念
2.命令和语法
3.执行过程和原理
4.调试和前端集成
-------------------------------------------------分割线-----------------------------------------------------
1.Shell基础概念
概念
tips:
Shell和Bash能够理解为类和实例的关系
构成
Unix shell既是命令解释器,也是程序设计语言。作为一个命令解释器,Shell提供了丰富的GNU实用程序集的用户界面
语法和命令
| 类型 | 作用域 | 声明方式 | 规范 |
|---|---|---|---|
| 自定义变量 | 当前shell | = | 字符串、整形、浮点型、日期型 |
| 环境变量 | 当前shell及子shell | export、declare -x | |
| 系统环境变量 | 所有shell | 启动加载 |
自定义变量
#!/bin/bash
# 变量名=变量值(等号左右不能有空格,有的话shell会当作额外的命令)
page_size=1
page_num=2
#命令复制给变量
_ls=ls
# 将命令结果复制给变量
file_list=$(ls - a)
# 默认字符串 ,不会进行 + 运算
total=page_size+page_num
#声明变量为整型
let total=page_size*page_num
declare -i total=page_size*page_num
#导出环境变量
export total
declare -x total
declare选项的含义
| 选项 | 含义 |
|---|---|
| - | 给变量设定类型属性 |
| + | 取消变量的类型属性 |
| -a | 将变量声明为数组类型 |
| -i | 将变量声明为整数型 |
| -x | 将变量声明为环境变量 |
| -r | 将变量声明为只读变量 |
| -p | 显示指定变量的被声明的类型 |
系统环境变量
| 变量名 | 含义 | 常见操作 |
|---|---|---|
| $0 | 当前shell名称/脚本名称 | 2等可以获取到传入参数 |
| $# | 传入脚本的参数数量 | if[ $# -gt 1 ] |
| $* | 传入脚本的所有参数 | |
| $? | 上条命令执行的状态码 | if [ $? -eq 0 ]; |
| $PS1 | 命令提示符 | export PS1="\u@\h \w>" |
| $HOME | 用户主文件夹(主目录) | cd ~ |
| $PATH | 全局命令的搜索路径 | PATH=$PATH:[新增路径] |
命令和语法
配置加载文件
shell种类
- 1.login shell 首次登陆时需要输入用户名、用户密码;
- 2.non-login shell 细分
交互式与非交互式
运算符和引用
管道
管道与管道符 | ,作用是将前一个命令的结果传递给后面的命令 语法:cmd1 | cmd2
语法:cmd1 | cmd2
要求:管道右侧的命令必须能接受标准输入才行,比如grep命令,ls、mv等不能直接使用,可以使用xargs预处理
注意:管道命令仅仅处理stdout,对于stderr会予以忽略,可以使用set -o pipefail设置shell遇到管道错误退出
#!/bin/bash
cat platform.access.log | grep ERROR
netstat -an | grep ESTABLISHED | wc -l//netstart 查看网络连接状态传递给 grep 筛选结果传递给 wc 来统计
# xargs 会将标准输入转化为参数列表
find . -maxdepth 1 -name "*.sh" | xargs ls -l
重定向
#输出重定向符号
>:覆盖写入文件
>>:追加写入文件
2>:错误输出写入文件
&>:正确和错误输出统一写入到文件中
#输入重定向符号
<
<<
判断命令
shell中提供了test、[、[[三种判断符号,可用于:
- 整数测试
- 字符串测试
- 文件测试
语法:
- test condition
- [ condition ]
- [[ condition ]]
#!/bin/bash
# 整数测试
test $nl -eq $n2 # 测试 $nl 是否等于 $n2
test $nl -lt $n2 # 测试 $nl 是否小于 $n2
test $nl -gt $n2 # 测试 $nl 是否大于 $n2
# 字符串测试
test -z $str_a # 测试 $str_a 是否为空
test -n $str_a # 测试 $str_a 是否非空
test $str_a = $str_b # 测试 $str_a 是否等于 $str_b
# 文件测试
test -e /dmt && echo "exist" # 测试 /dmt 是否存在,并在存在时输出 "exist"
test -f /usr/bin/npm && echo "file exist" # 测试 /usr/bin/npm 是否存在,并在存在时输出 "file exist"
注意:
- 中括号前后要有空格符
- [ 和test是命令,只能使用自己支持的标志位,<、>、=只能用来比较字符串
- 中括号内的变量,最好都是用引号括起来
- [[ 更丰富,在整型比较中支持<、>、=,在字符串比较中支持=~正则
分支语句
在shell中分支语句有
if语句和case语句
#if语句
#语法1:
if condition;then
程序段
elif condition;then
程序段
else
程序段
fi #结束标志
#语法2:
case $变量 in:
"第一个变量内容")
程序段
;;
"第一个变量内容")
程序段
;;
*)
程序段
;;
esac
循环
#while 循环
while condition ;do 程序段; done
#until 循环
until condition ;do 程序段; done
#for 循环
for var in [word...]; do 程序段; done
函数
#语法1:
funcName(){echo"abc";}
#语法2:
function funcName(){echo"abc";}
#内部用$获取参数
模块化
模块化的原理是在当前shell内执行函数文件,方式:
source [函数库的路径]
3.执行过程和原理
执行
1.shell脚本一般以.sh结尾,也可以没有,这是一个约定;第一行需要指定用什么命令解释器来执行
#! /bin/bash
#! /user/bin/env bash
启动方式
#文件名运行(子进程执行)
./filename.sh
#解释器运行(子进程执行)
bash ./filename.sh
# source运行(当前进程中执行)
source ./filename.sh
绿色部分为脚本
内部运行有几个部分:
1.字符解析
识别换行符、分号(;)做行的分割
识别命令连接符(||&&管道)做命令的分割
识别空格、tab符,做命令和参数的分割
2.shell展开,例如{1...3}解析为1 2 3
3.重定向,将stdin、stdout、stderr的文件描述符进行指向变更
4.执行命令
builtin直接执行
非builtin使用$PATH查找,然后启动子进程执行
5.收集状态并返回给脚本
shell展开
-
大括号展开(Brace Expansion) {..}
-
波浪号展开(Tilde Expansion) ~
-
参数展开(Shell Parameter Expansion)
-
命令替换(Command Substitution)
-
数学计算(Arithmetic Expansion) $(())
-
文件名展开(Filename Expansion) *?[.] 外壳文件名模式匹配
4.调试和前端集成
调试的方法
- 普通log,使用echo、printf
- 使用set命令
- vscode debug插件
| set配置 | 作用 | 补充 |
|---|---|---|
| -u | 遇到不存在的变量就会报错,并停止执行。 | -o nounset |
| -x | 运行结果之前,先输出执行的那一行命令。 | -o xtrace |
| -e | 只要发生错误,就终止执行 | -o errexit |
| -o pipefail | 管道符链接的,只要一个子命令失败整个管道命令就失败,脚本就会终止执行。 |
Vscode插件配置
-
shellman:代码提示和自动补全
-
shellcheck:代码语法校验
-
shell-format:代码格式化
-
Bash Debug:支持单步调试
-
安装vscode插件
-
编写launch.json文件
-
升级bash到4.x以上版本
前端集成
1.node中通过exec、spawn调用shell命令
2.shell脚本中调用node命令
3.借助zx等库进行javascript、shell script的融合
- 借助shell完成系统操作,文件io、内存、磁盘系统状态查看
- 借助nodejs完成应用层能力,网络io、计算等
完成对shell的学习,好记心不如烂笔头,不做笔记不实践是永远没有进步的。