Shell脚本和编程

155 阅读3分钟

Shell学习的价值

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

shell基础概念

概念

  1. 终端 获取用户输出,显示运算结果的硬件设备
  2. tty(teletypeWrite) 和终端等价,在linux中是输入输出环境。是linux的一个终端,每个终端模拟器关联一个虚拟tty,和内核打交道
  3. 终端模拟器 关联虚拟tty的输入输出软件
  4. shell 处理来自终端模拟器的输入,解释执行之后输出结果给终端。
  5. Bash shell的一种具体的实现 (类比类和实例的体现)。0

发展历程

Pasted image 20230417203642.png

构成

  1. 解释器

    • bash内置命令 . echo let 等
    • GNU核心工具 ls mv mkdir cat
    • 第三方库 node python 封装的模块
  2. 编程语言

    • 变量
    • 运算
    • 语句
    • 函数

shell还集成了软件开发中通用的设计模式及(管道和过滤器),具备控制流程,循环,变量,命令查找等机制,它可以采用丰富的GNU工具集,第三方或者内置的来作为命令的解释器。

语法和命令

变量

  1. 自定义类型:作用在当前shell
  2. 环境变量:作用在当前shell 和 子类 shell
  3. 系统环境变量: 作用在所有shell
  4. 父子shell的关系

Pasted image 20230417205712.png

自定义变量

  1. page_size=1 //等号的左右不能有空格
  2. _ls=ls //命令赋值给变量名
  3. let total=page_size*page_num //默认字符串,不会进行+运算
  4. export total //导出环境变量
  5. declare
    • - 给变量设定类型属性
    • + 取消变量的类型属性
    • -a 将变量声明为数组类型
    • -i 将变量声明为整数类型
    • -x 将变量声明为环境变量
    • -r 将变量声明为只读
    • -p 显示指定变量的被声明的类型

系统环境变量

Pasted image 20230417210814.png

配置文件加载

  1. Login shell
    1. 交互式
    2. 非交互式
  2. non-Login

运算符和引用

Pasted image 20230417211434.png

管道

  1. 管道与管道符|,作用是将前一个命令的结果传递给后面的命令
  2. 语法:cmd1|cmd2
  3. 要求:管道右侧的命令必须能接受标准输入才行,比如 grep,ls,mv 等不能直接使用,但可以使用 xargs 预处理来传递结果
  4. 管道在发生错误的时候不会退出,可以使用 set -o pipefail 设置shell 遇到错误退出

重定向

  1. 输出重定向
    • > :覆盖写入文件
    • >> :追加写入文件
    • 2> :错误输出写入文件
    • &> :正确和错误输出统一写入到文件中
  2. 输入重定向
    • <
    • <<

判断命令

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

  • 整数测试:test condition
  • 字符串测试 : [condition]
  • 文件测试 : `[[condition]]

注意

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

分支语句

Pasted image 20230417214521.png

循环

    1. while

while condition ; do 程序段; done

  • 2.until

until condition ; do 程序段; done

  • 3.for

for var in [word...]; do 程序段;done

函数

  1. funcName(){echo"abc";}
  2. function funcName() {echo "abc";}

注意:

  • shell自上而下执行,所以变量的声明必须在使用前定义
  • 0代表函数名,后续用0 代表函数名,后续用 `1,$2` 来获取
  • 函数内 return 仅仅表示函数的执行状态,不代表函数的执行结果
  • 返回结果一般使用 echo,printf , 在外面使用 $(),'' 来获取结果
  • 如果内有 return ,函数状态则是上一条命令的执行状态, 存储在 $?
  • 在函数内声明时,最好用 local 来声明局部变量,不污染全局,或者在结尾采用 unset 在函数结尾释放该变量

模块化

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

常用命令

Pasted image 20230417220649.png

执行过程和原理

执行

  1. shell 脚本一般以 .sh 来结尾,也可以没有,这是一个约定。 #! /bin/bash
  2. 启动方式
    1. 文件名运行 ./filename.sh
    2. 解释器运行 bash ./filename.sh
    3. source 运行 source ./filename.sh

执行过程

  1. 字符解析
  2. shell展开,{1..3} 解析为 1 2 3
  3. 重定向,将stdin,stdout,stderr 的文件描述符进行指定变更
  4. 执行命令
  5. 收集状态并返回

shell展开

    1. 大括号展开
    • 字符串序列
      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

    1. 波浪号展开
    • 当前用户主目录 ~ => $HOME
    • 指定用户主目录 ~fred/foo => 用户fred 的 $HOME/foo
    • 当前工作目录 ~+/foo => $PWD/foo
    • 上一个工作目录 ~-/foo => ${$OLDPWD- '~-'}/foo
    1. 参数展开
    • Pasted image 20230417223848.png
    1. 命令替换
    • 得到的结果替换包裹中的内容 $(...) 或 '...'
    1. 数学计算
    • echo $((1+2)) #3
    1. 文件名展开
    • 当单词未被引号包裹,且其中出现了 * ? [ 字符,则shell会去按照正则去查找文件名并进行替换,若未找到则保持不变