Shell脚本和编程 | 青训营笔记

155 阅读3分钟

前言

Shell是一种命令行界面,也是一种编程语言, 熟练掌握 Shell 能够大大提升 Unix/Linux环境下的工作效率。本文将从其发展历史、基础语法开始,通过示例逐步深入, 不仅帮助大家学会使用 Shell ,也在一定程度上去理解 Shell 的执行原理和语法设计。

学习Shell的价值

  • 1.Linux服务器的基本操作和管理
  • 2.前端Node.js服务的进程管理、问题排查、资源监控等运维操作哦
  • 3.使用shell编写TCE、SCM、Docker脚本,完成服务编译和部署

学习准备

  • 一台安装了Linux系统的物理机或者云主机,可运行shell脚本
  • 本地的vscode安装 Bash Debug插件,并升级bash到4.x以上
  • Npm全局安装zx依赖
全局安装zx:
$ npm install -g zx

Shell基础概念

概念

终端

  • 获取用户输入、展示运算结果的硬件设备

tty

  • teletypeWriter的简称,和终端等价,早期指电传打印机,在Linux中是输入/输出 环境

终端模拟器

  • Mac Terminal、iTerm2等,关联虚拟tty的输入输出条件

Shell

  • command interpreter,处理来自终端模拟器的输入,解释执行之后输出结果给终端

Bash

  • shell的一种具体表现,可以理解成实例和类的关系

发展

  • Ken Thompson (来自贝尔实验室)在1971年为UNIX开发了第一个shell,称为V6 shell
  • Stephen Bourne在贝尔实验室为V7 UNIX所开发的Bourne shell,即sh
    • sh相比于V6 shell,它的几个优点在于把控制流程,循环,变量引入了脚本,提供了一种更具功能性的语言
    • 主流Linux系统使用的shell,许多都以它为锚点
  • 开源组织GNU为了取代Bourne shell开发的Bourne-Again shell,即Bash
    • Bash是sh的超集,可以直接执行大部分sh脚本
    • Bash在兼容Bourne shell脚本编程的同时,集成了Korn shell和C shell的功能,包括命令历史,命令行编辑,目录堆栈(pushd和popd),一些实用环境变量,命令自动补全等

构成

image.png

命令和语法

变量

image.png

自定义变量

image.png

image.png

系统环境变量

image.png

配置文件加载

image.png

运算符和引用

image.png

管道

  • 管道与管道符|,作用是将前一个命令的结果传递给后面的命令
  • 语法: cmd1 | cmd2
  • 要求:管道右侧的命令必须接受标准输入才行,比如grep命令,ls、mv等不能直接使用,可以使用xargs预处理
  • 注意:管道命令仅仅处理stdout,对于stderr会予以忽略,可以使用set -o pipefail设置shell遇到管道错误退出

image.png

重定向

  • 输出重定向符号
    • >:覆盖写入文件
    • >>:追加写入文件
    • 2>:错误输出写入文件
    • &>:正确和错误输出统一写入到文件中
  • 输入重定向符号
    • <
    • << image.png
  • 如果取得bash需要完整的登录流程,我们称之为login shell,比如ssh远程登录一台主机
  • 不需要登录的bash我们称之为non-login shell,比如在原来的bash中执行bash开启子进程,执行一些外部命令
  • 如果修改了配置文件,不会立即生效,需要我们重启终端或者执行source命令

判断命令

  • shell中提供了test[[[三种判断符号,可用于:
    • 整数测试
    • 字符串测试
    • 文件测试

image.png

  • 语法:

    • test condition
    • [ condition ]
    • [[ condition ]]
  • 注意:

    • 中括号前后要有空格符
    • [test是命令,只能使用自己支持的标志位,<>=只能用来比较字符串
    • 中括号内的变量,最好都是引号括起来
    • [[更丰富,在整型比较中支持<>=,在字符串比较中支持=~正则

image.png

分支语句

语法一:
if condition; then
    程序段
elif condition; then
    程序段
else
    程序段
fi

image.png

语法二:
case $变量 in:
    "第一个变量内容")
    程序段
    ;;
    "第二个变量内容")
    ;;
    * )
    程序段
    ;;
    esac

image.png

循环

  • while循环
    • while condition; do 程序段; done

image.png

  • until循环
    • until conditon; do 程序段; done
    • until当条件成立时会跳出循环

image.png

  • for循环
    • for var in[words...]; do 程序段; done

image.png

函数

  • 语法一:funcName(){echo"abc";}
  • 语法二:function funcName(){echo "abc";}

image.png

  • 注意:
    • shell自上而下执行,函数必须在使用前定义
    • 函数获取变量和shell script类似,0代表函数名,后续通过0代表函数名,后续通过1、$2...获取
    • 函数内return仅仅表示函数执行状态,不代表函数执行结果
    • 返回结果一般使用echo、printf,在外面使用$()、获取结果
    • 如果没有return,函数状态是上一条命令的执行状态存储在$?中

image.png

  • 为了函数内定义的变量不污染全局,我们最好使用local定义,或者在函数退出之前使用unset去处理一下

模块化

  • 模块化的原理是在当前shell内执行函数文件,方式:source[函数库的路径]

image.png

常用命令

image.png

执行过程和原理

执行

  • 1.shell脚本一般以.sh结尾,也可以没有,这是一个约定;第一行需要指定用什么命令解释器来执行
# 第一种方式
#! /bin/bash
# 第二种方式
#! /usr/bin/env bash
  • 2.启动方式
# 文件名运行
./filename.sh
# 解释器运行
bash ./filename.sh
# source运行
source ./filename.sh

执行过程

  • 1.字符解析
    • 识别换行符、分号(;)做行的分割
    • 识别命令连接符(||&&管道)做命令的分割
    • 识别空格、tab符,做命令和参数的分割
  • 2.shell展开
    • 例如解析{1..3}解析为 123
  • 3.重定向
    • 将stdin、stdout、stderr的文件描述符进行指向变更
  • 4.执行命令
    • builtin直接执行
    • 非builtin使用$PATH查找,然后启动子进程执行
  • 5.收集状态并返回

image.png

shell展开

  • 1.大括号展开 (Brace Expansion){...}
    • 一般有三部分构成,前缀、一对大括号、后缀,大括号内可以是逗号分割的字符串序列,也可以是序列表达式{x..y[..incr]}

image.png

  • 2.波浪号展开 (Tilde Expansion) ~

image.png

  • 3.参数展开 (Shell Parameter Expansion)
  1. 间接参数展开${!parameter},其中引用的参数并不是parameter而是parameter的实际的值

image.png

  1. 参数长度${#parameter}

image.png

  1. 空参数处理

    ${!parameter:-word} # 为空替换

    ${!parameter:=word} # 为空替换,并将值赋给parameter变量

    ${!parameter:?word}# 为空报错

    ${!parameter:+word} # 不为空替换

image.png

4.参数切片

5.参数部分删除

image.png

  • 4.命令替换 (Command Expansion)
    • 在子进程中执行命令,并用得到的结果替换包裹的内容,形式上有两种:$(...)``

image.png

  • 5.数学计算 (Arithmetic Expansion) $((..))
    • 使用$((..))包裹数学运算表达式,得到结果并替换

image.png

  • 6.文件名展开 (Filename Expansion) *?[..]外壳文件名模式匹配
    • 当有单词没有被引号包裹,且其中出现了‘*’‘?’,and ‘[’字符,则shell会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变

image.png

调试和前端集成

调试

  • 1.普通log,使用echo、printf

image.png

  • 2.使用set命令

image.png

image.png

  • 3.vscode debug插件

vscode配置

  • 1.shellman:代码提示和自动补全
  • 2.shellcheck:代码语法校验
  • 3.shell-format:代码格式化

91e175ed-2f10-4e27-93f1-b313eff6dbc5.gif

  • 4.Bash Debug:支持单步调试
    • 安装vscode插件
    • 编写launch.json文件
    • 升级bash到4.x以上版本

image.png

前端集成

  • 1.node中通过exec、spawn调用shell命令
    • exec启动一个子进程shell进程执行传入的命令,并且将执行结果保存在缓存区中,并且缓冲区是有大小限制的,执行完毕通过回调函数返回
    • spawn默认不使用shell,而是直接启动子进程执行命令,且会直接返回一个流对象,支持写入或者读取流数据,这个在大数据量交互的场景比较合适

image.png

  • 2.shell脚本中调用node命令

image.png

  • 3.借助zx等库进行javascript、shell script的融合
    • 借助shell完成系统操作,文件io、内存、磁盘系统状态查询等
    • 借助nodejs完成应用层能力,网络io、计算等

image.png

引用

  • 字节内部课:Shell脚本和编程-字节前端初阶训练营