Shell编程 | 青训营笔记

125 阅读3分钟

Shell编程 | 青训营笔记

课程介绍

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

课程准备

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

课程内容

  1. Shell 基础概念
  2. 命令和语法
  3. 执行过程和原理
  4. 调试和前端集成

Shell 基础概念

概念

  • 终端
    • 获取用户输入,展示运算结果的硬件设备
  • tty
    • teletypeWriter的简称,和终端等价,早期指电传印机,在linux中是输入\输出环境
  • 终端模拟器
    • Mac Terminal、iTerm2等,关联虚拟tty的输入输出软件
  • Shell
    • command interpreter ,处理来着终端模拟器的输入,解释执行之后输出结果给终端
  • Bash
    • shell的一种具体实现

发展

image.png

构成

Shell 既是一种命令语言,又是一种程序设计语言。

Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

image (1).png

语法和命令

变量

image (2).png

自定义变量

#变量名=变量值(等号左右不能要空格)
page_size=1
page_num=2

#将命令复制给变量
_ls=ls

#将命令结果赋值给变量
file_list=$(ls - a)

#默认字符串,不会进行 + 运算
total=page)size+page_num

#声明变量为整型
let taotal=page_size*page_num

declare -i total=page_size*page_num

#导出环境变量
export total

declare -x total

image (4).png

环境变量

image (3).png

#比如
echo $PS1

echo $PATH

配置加载环境

image (5).png

运算符和引用

image (6).png

管道

管道与管道符 | ,作用是将前一个命令的结果传递给后面的命令

语法: cmd1 | cmd2

要求:管道右侧的命令必须能接受标准输入才行,比如 grep 命令,ls、mv等不能直接使用,可以使用 xargs 预处理

注意:管道命令仅仅处理 stdout,对于 stderr 会予以忽略,可以使用 set -o pipefail 设置 shell 遇到管道报错退出

image (7).png

重定向

image (8).png

image (9).png

image (10).png

判断命令

Shell 中提供了 test、[、[[ 三种判断符号,可用于

  • 整数测试
  • 字符串测试
  • 文件测试

语法

  • test condition
  • [ condition ]
  • [[ condition ]]
#整数测试
test $n1 -eq $n2
test $n1 -lt $n2
test $n1 -gt $n2

#字符串测试
test -z $str_a
test -n $str_a
test $str_a = $str_b

#文件测试
test -e /dmt && echo "exist"
test -f /usr/bin/npm && echo "file exist" 

注意

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

[ $name == "hello" ]

#报错
scipt.sh: line 5: [ : too many arguments #有太多参数
Exited with error status 2

#原因
#[ $name == "hello" ] 被解析为 [ hello world == "hello" ]
#正确为[ "$name" == "hello" ]

分支语法

image (11).png

循环

  • while循环
#while condition ; do 程序段; done
let num=0
while [ $sum -lt 10 ];
do
	echo "current idx: $num"
	((num++))
done
  • until循环
#until condition ; do 程序段; done
let num=0
until [ $num -gt 10 ];
do 
	echo "current idx: $num"
	((num++))
done
  • for循环
#for var in [words...]; do 程序段; done
#对列表进行循环
for foo in a b c
do
	echo $foo
done

#数值方式循环
for((i=0;i<10;i++))
do
	echo $i
done

函数

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

printName(){
	if [ $# -lt 2 ]; then
	  echo "illegal parameter."
	  exit 1
	 fi
	 
	 echo "firstname is :$1"
	 echo "lastname is: $2"
}
printName jacky chen

image (12).png

模块化

模块化的原理是在当前 shell 内执行函数文件,方式:

source [函数库的路径]

image (13).png

常用命令

image (14).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} 解析为 1 2 3
  3. 重定向,将 stdin,stdout,stderr 的文件描述符进行指向变更
  4. 执行命令
    • builtin 执行
    • 非 builtin 使用 $PATH;查找,然后启动子进程执行

shell 展开

  1. 大括号展开(Brace Expansion){...}

    • 一般由三部分组成、前缀、一对大括号、后缀、大括号内可以是逗号分割的字符串序列,也可以是序列表达式 {x..y[..incr]}
    #字符串序列
    a{b,c,d}e => abe ace ade
    
    #表达式序列,{数字可以使用 incr 调整增量,字母不行}
    {1..5} => 1 2 3 4 5
    {1..5..2} => 1 3 5
    {a.e} => a b c d e
    
  2. 波浪号展开(Tilde Expansion){...}

    #当前用户主目录
    ~ => $HOME
    
    ~/foo => $HOME/foo
    
    #指定用户的主目录
    -fred/foo => 用户fred的 $HOME/foo
    
    #当前工作目录
    ~+/foo => $PWD/foo
    
    #上一个工作目录
    ~-/foo => ${SOLDPWD-'-'}/foo
    
  3. 参数展开(Shell Parameter Expansion)

image (15).png

  1. 命令替换(Command Substiution)

    • 在子进程中执行命令,并用得到的结果替换包裹的内容,形式上有两种:$(...) 或 ...
    #! /bin/bash
    
    echo $(wnoimi)
    
    foo(){
    	echi `asdasda`
    }
    a=`foo`
    
  2. 数学计算( Arithmetic Expansion) $((...))

    • 使用 $(()) 包裹数学运算表达式,得到结果并替换
    #! /bin/bash
    
    echo $((1+2)) #3
    
  3. 文件名展开(Filename Expansion) * ?[...]外壳文件名模式匹配

    • 当有单词没有被引号包裹、且其中出现 '*','and','['字符,则shell会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变
    #! /bin/bash
    
    $ echo D*
    
    #输出当前目录下所有以D字母开头的目录,文件
    

调试和前端集成

调试

  1. 普通log,使用 echo、print
  2. 使用 set命令
  3. vscode debug插件

image (16).png

vscode 配置

  1. shellman:代码提示和自动补全
  2. shellcheck:代码语法校验
  3. shell-format:代码格式化
  4. Bash Debug:支持单步调试
    • 安装vscode 插件
    • 编写 launch.json文件
    • 升级 bash到4.x版本以上

前端集成

  1. node中通过 exec、spawn调用 shell命令
  2. shell脚本中调用 node 命令
  3. 借助zx库进行 JavaScript、shell script 的融合
    • 借助 shell 完成系统操作、文件io、内存、磁盘系统状态查询等
    • 借助 node.js 完成应用层能力、网络io、计算等

课程小结

在这次的shell编程中,学习了shell的基础概念,发展,构成,还有shell的语法和命令,shell的执行过程和在前端中如何使用shell