扬仔的杂货铺

分享微不足道的经验,记录稀奇古怪的玩意

0%

学习Shell脚本

介绍

什么是shell脚本(需要解释器解释)

  1. 系统命令的堆积
  2. 特定的语法+系统的命令=文件
  3. 不会手动搭建或者执行某些程序,那么一定学不会shell

shell脚本能做什么

基于标准化之上的 -> 工具化

作用:简化操作步骤,提高工作效率,减少人为干扰,减少故障

  1. 自动化的完成基础配置

    (系统初始化操作、系统更新、内核调整、网络、时区、SSH优化)

  2. 自动化安装程序

    (自动化安装LNMP、LAMP、MySQL、Nginx、Redis)

  3. 自动化调整配置文件
    (Nginx Conf、MySQL Conf)

  4. 自动化部署业务

    部署php、java、秒级回退

  5. 自动化定期备份恢复程序

    (MySQL全备 + 增量 + binlog + crond + shell脚本)

  6. 自动化信息的采集(Zabbix + shell)

    硬件、系统、服务、网络信息等等

  7. 自动化日志收集(ELK)

    收集 -> 存储 -> 展示 -> 分析
    日志分析(取值 -> 排序 -> 去重 ->统计 -> 分析)

  8. 自动化扩容/缩容(Zabbix + shell)

    监控服务器,如果发现cpu持续80% + 触发动作(脚本)
    脚本:调用api开通云主机 -> 初始化环境 -> 加入集群 -> 对外提供

    当前cpu使用率20% -> 判断有多少web节点 -> 判断是否超过预设 -> 缩减到对应的预设状态 -> 变更负载的配置

  9. shell什么都能做,但要符合实际情况以及实际业务需求

shell技能

  • 变量

    • 自定义变量
    • 系统环境变量
    • 预先定义变量
    • 位置参数变量
  • 条件判断

    if、else

  • 循环语句

    for、while

  • 流程控制

    case

  • 函数

    function

  • 数组

    array

  • 正则表达式

shell脚本概述

脚本的基本格式

1
2
3
4
5
#!/bin/bash
#上面是这里指定使用的解释器,必须写在第一行

#下面编写相应的脚本
echo "Hello world"

运行脚本:

  1. 赋予文件权限

  2. 直接执行脚本

脚本的执行方式

  1. 使用对应的解释器执行

    bash 文件

    如果脚本文件名为test,那么执行的方式为

    bash test
    sh test

    抑或是使用其他的脚本解析器

  2. 直接执行文件

    如果想要直接执行脚本文件,需要先添加执行权限,并且需要在脚本的开头添加#!解释器路径(例如:#!/bin/bash)来声明对应的解释器,否则默认使用bash来执行脚本。

    如果脚本文件名为test,那么执行的方式为./test

shell脚本的特性

bash shell特性

  1. 命令补全和文件路径补全,如果写错无法补全 -> tab

  2. 命令历史记忆功能,查看执行的历史 -> history

  3. 别名功能,查看当前shell的别名 -> aliasunalias

  4. 常用快捷键

    命令 作用
    ctrl + u 剪切光标到行首的所有字符
    ctrl + k 剪切光标到行尾的所有字符
    ctrl + y 粘贴ctrl + uctrl + k剪切的字符
    ctrl + a 光标回到行首
    ctrl + e 光标回到行尾
    ctrl + l 清除屏幕所有的内容,并开启新的一行
    ctrl + c 中断正在执行的任务并开启新的一行
    ctrl + z 将前台进程挂在后台
    ctrl + d 推出当前shell命令行,如果是切换过来的用户,则执行这个命令回退原用户
    ctrl + r 搜索命令行使用过的历史命令记录
    ctrl + g ctrl + r搜索历史命令行的模式中退出
    ctrl + s 锁定终端
    ctrl + q 解除锁定终端
    ctrl + z 暂停在终端运行的任务,使用fg命令可以使暂停恢复
    !! 执行上一条命令
    !pw 这是一个例子,是执行以pw开头的命令,这里的pw可以换成任何已经执行过的字符
    !pw:p 这是一个例子,是仅打印以pw开头的命令,:p是固定字符
    !num 执行历史命令列表的第num条命令,num代指任何数字(前提是历史命令里必须存在)
    !$ 代指上一条命令的最后一个参数,该命令常用与shell脚本中
    esc + . 获取上一条命令的(以空格为分隔符)最后的部分
    esc + b 移动到当前单词的开头
    esc + f 移动到当前单词的结尾
  5. 前后台作业控制bg,fg,jobs,screen

  6. 输入输出重定向

    命令 作用
    command >filecommand 1>file 覆盖的方式,把command的输出的正确结果输出到file中
    command >>filecommand 1>>file 追加的方式,把command的输出的正确结果输出到file中
    command 2>file 覆盖的方式,把command的输出的错误结果输出到file中
    command 2>>file 追加的方式,把command的输出的错误结果输出到file中
    command >file 2>&1 覆盖的方式,把command的输出的所有结果输出到file中
    command >>file 2>&1 追加的方式,把command的输出的所有结果输出到file中
  7. 管道

    命令 作用
    | 将前者命令的标准输出交给后者命令的输入
    tee 把当前管道的内容保存下来
    1
    2
    #例如
    cat /etc/hosts | grep local | tee (-a) test.txt
  8. 命令排序

    命令 作用
    ; 命令没有逻辑关系,无论分号前面的命令执行是否成功都执行后者命令
    && 只有前面的命令执行成功,才会执行后面的命令
    || 如果前面的命令执行成功,就不执行后面的命令
  9. shell通配符

    命令 作用
    * 匹配任意多个字符
    ? 匹配任意一个字符
    [] 匹配括号中任意一个字符(a-z,0-9,A-Z,a-Z)
    () 在子shell中执行,不影响当前shell
    {} 集合,(例如touch file{1..9}
    \ 转义符
  10. echo输出颜色、printf格式化输出文本

shell脚本变量

简单的理解变量:用一个固定的字符串去表示不固定的内容

变量常见类型

自定义变量

  1. 定义变量

    变量名=变量值

    不允许数字命名,不能使用横杠命名

  2. 引用变量

    $变量名${变量名}

  3. 查看变量

    echo $变量名

    set显示所有变量,包括自定义变量和环境变量

  4. 取消变量

    unset 变量名

  5. 作用范围

    仅在当前shell中有效

环境变量

  1. 定义环境变量

    export 变量名=变量值或者先定义自定义变量,然后使用export 自定义变量名将其转换成环境变量

    1
    2
    export ip=1.1.1.1
    echo $ip #得到结果 1.1.1.1
  2. 引用环境变量

    $变量名${变量名}

  3. 查看环境变量

    env 可以查看所有的环境变量

    set显示所有变量,包括自定义变量和环境变量

  4. 取消变量

    unset 变量名

  5. 作用范围

    在当前shell和子shell有效

位置参数变量

脚本参数传参:$1$2$3$4$5$6$7$8$9${10}

根据脚本后面的参数来确定对应数字变量的值

预先定义变量

命令 作用
$0 脚本名
$* 所有的参数(用一对引号,例如:”1 2 3”)
$@ 所有的参数(分别使用引号,例如:”1” “2” “3”)
$# 参数的个数
$$ 当前进程的PID
$! 上一个后台进程的PID
$? 上一个命令的返回值(0表示成功)

变量赋值方式

显式赋值(变量名=变量值)

1
2
3
4
ip=192.168.1.1
name="Yangself"
today1=`date +%F`
today2=$(date +%F)

read从键盘读入变量值

1
2
read -p "输入的提示:" param
echo $param

注意事项

  1. 定义或引用变量时注意引号的问题:""弱引用、''强引用

    变量的解析使用双引号
    如果想要输出特殊字符,可以使用单引号

    1
    2
    3
    4
    echo "hello $hello"
    hello world
    echo 'hello $hello'
    hello $hello
  2. ``命令替换等价于${},反引号中的shell命令会被先执行

变量数值运算

整数运算

  1. expr

    expr 数值 运算符号 数值

    1
    2
    3
    4
    5
    6
    7
    expr 1 + 1
    2

    ➜ a=1
    ➜ b=2
    expr $a + $b
    3
  2. $(())

    $((运算式))

    1
    2
    3
    4
    5
    echo $((2+4)) 
    6
    # ** 代表乘方 ^
    echo $((2**4))
    16
  3. $[]

    $[运算式]

    1
    2
    3
    4
    5
    echo $[2+4]
    6
    # ** 代表乘方 ^
    echo $[2**4]
    16
  4. let

    let 变量名=运算式

    1
    2
    3
    let result=2+3
    echo $result
    5

小数运算bc

1
2
echo "scale=2;6/4" | bc
echo "print 5.0/2" | python

变量替代

${变量名-新的变量值}或者${变量名:-新的变量值}

变量没有被赋值:会使用“新的变量值”替代

变量有被赋值(包括空值):不会被替代

1
2
3
4
5
6
7
8
9
10
➜ hello=world
echo $hello
world
echo $hello-test
world-test
echo ${hello-test}
world
unset hello
echo ${hello-test}
test

变量自增

let i++

1
2
3
4
5
6
➜ i=1
echo $i
1
let i++
echo $i
2

shell条件测试

文件测试

test -d /backup

1
2
3
4
5
test -d /backup
echo $?
1
test -d /backup || mkdir -p /backup
# 这样就可以通过检测有没有此文件夹来判断是否创建文件夹

数值比较

字符串比较