简介

Shell是命令解释器,用于解释用户对操作系统的操作
CentOS7默认使用的Shell是bash

编写Shell脚本

入门示例

  1. 1.编写demo.sh文件,示例:
  2. ----------
  3. #!/bin/bash
  4. cd /var/
  5. ls
  6. pwd
  7. ----------
  8. - 各命令之间可以以;或者换行间隔
  9. - 第一行声明 #!/bin/bash,在./demo.sh执行时会告诉系统使用bash解释执行
  10. - 除了第一行外以#开头的一行都为注释, 建议注释单开一行
  11. 2. 授予执行的权限
  12. chmod u+x demo.sh
  13. 3. 执行
  14. 在子进程中执行
  15. bash demo.sh
  16. ./demo.sh
  17. 在当前进程执行
  18. source ./demo.sh
  19. . demo.sh
  20. 内建命令不需要创建子进程
  21. 内建命令对当前Shell生效

管道与重定向

管道是进程通信的方式,在脚本中使用是为了方便命令之间进行通信
管道符是“|”,将前一个命令执行的结果传递给后面的命令
示例:

  1. ls -l | more 组装多条命令, 实现分页显示
  2. ps | cat
  3. echo 123 | ps

重定向可以让程序输出到文件中,也可以将文件作为输入源
一个进程默认会打开标准输入0,标准输出1,错误输出2三个文件描述符
输入重定向符号 <
输出重定向符号>,>>,2>,&>, 共4种
输出时, >表示覆盖, >>表示追加, 2>表示只输出错误, &>表示无论正确与错误都进行输出
示例:

  1. read var2 < a.txt a.txt输入到var2变量中
  2. echo $var2 查看var2变量
  3. echo $var2 > b.txt var2变量输出到b.txt
  4. 输入输出可以组合使用, 一般用来在shell中生成新的文件
  5. -------------------
  6. #!/bin/bash
  7. cat > /root/a.sh <<EOF
  8. echo "hello world"
  9. EOF
  10. -------------------
  11. 执行上面脚本会生成a.sh文件, 文件中为 echo "hello world"

变量

  1. 变量名命名规则
  • 只能包含字母,数字,下划线
  • 不以数字开头
  1. 给变量赋值
  • 变量名=变量值, 如a=123, 注意等号两侧不能出现空格
  • 使用let为变量赋值, 如 let a=10+20
  • 将命令赋值给变量,如l=ls
  • 将命令结果赋值给变量,使用$()或者``, 如let c=$(ls -l /etc)
  • 变量值有空格等特殊字符可以包含在” “或者’’中
  1. 变量的引用
  • ${变量名}称作对变量的引用
  • echo ${变量名}查看变量的值
  • ${变量名}在部分情况下可以省略为 $变量名
  1. 变量的作用范围
  • 默认作用范围是当前shell
  • 变量的导出, 导出后子进程可以拿到父进程的变量

export 变量名

  • 变量的删除

unset 变量名

  1. 环境变量 ```bash 1.查看系统所有的环境变量 env | more

2.查看当前用户 echo $USER echo $UID

3.查看命令搜索路径 echo $PATH 将/root添加到命令搜索路径 PATH=$PATH:/root

4.查看当前提示终端, 常用于增加终端提示信息,比如添加ip,时间等 echo $PS1

  1. 6. 预定义变量
  2. ```bash
  3. 确认上一条命令是否执行成功, 成功返回0,失败返回1
  4. echo $?
  5. 显示当前进程的PID,常用于对脚本状态的监测
  6. echo $$
  7. 显示当前进程的名称
  8. echo $0

image.png

  1. 位置变量, 用于脚本中定义变量, 外界传参

$1 $2…$9 ${10}…

  1. 示例脚本
  2. --------
  3. #!/bin/bash
  4. echo $1
  5. echo ${2-_}
  6. --------
  7. 执行bash 1.sh test输出(${2}为空值时, 采用_)
  8. test
  9. _

环境变量的配置文件

  1. /etc下的是所有用户通用的配置文件, ~存放当前用户特有的配置文件
  2. 1. /etc/profile
  3. 当使用su - root,这个文件第一个被加载
  4. 系统环境环境变量和启动程序的环境变量,用于登陆配置
  5. 终端启动的时候的环境
  6. 不要在/etc/profile里面直接修改,而是创建一个custom.sh在/etc/profile.d里面制作自定义的修改
  7. 2. /etc/profile.d/
  8. 3. ~/.bash_profile
  9. 4. ~/.bashrc
  10. 5. /etc/bashrc
  11. 命令搜索路径增加新的路径, 将下面配置加到上面文件
  12. export PATH=$PATH:/newPath...
  13. 添加后不会立即生效, 方式一是exit离开当前终端, 方式二是source /etc/profile(刚才改的配置文件)

切换root用户, 执行顺序如下: (这里为了测试依次在各个配置文件中加了echo 当前文件夹)
image.png
不加 - 登录时, 配置文件加载如下, 因此不建议使用这种登录方式
image.png

数组

image.png

  1. 定义数组
  2. TEST=(1 2 3)
  3. 显示数组的所有元素
  4. echo ${TEST[@]}
  5. 显示数组元素个数
  6. echo ${#TEST[@]}
  7. 显示数组的第一个元素
  8. echo ${TEST[0]}

转义和引用

  • 特殊字符: 字符不仅有字面意义, 还有元意, 比如#注释 ;分号 \转义符号 “和’引号’
  • 单个字符前的转义符号, 比如 \$, 将$转义成普通的符号
  • “ 表示不完全引用, 变量的引用会被解释
  • ‘ 表示完全引用, 是啥就是啥
  • ` 反引号表示

运算符

  • 赋值运算符, 即 =
  • 基本运算符, + - / * %, 使用expr进行运算, 比如a=expr 4 + 5 (注意只能整数且中间要有空格)

数字常量的使用
let “变量名=变量值”
双圆括号是对let的简化:
(( a=10 ))
(( a++ ))
echo $(( 10+9 ))

特殊字符

引号

‘ ‘ 完全引用, 不会被赋值
“” 不完全引用, 会被赋值
` 执行命令, 等同于$()

括号

image.png

运算符号和逻辑符号

image.png

特殊符号

image.png
image.png

测试与判断

退出程序命令

  • exit
  • exit 10 返回10给Shell, 返回值非0位不正常退出
  • $? 判断当前Shell前一个进程是否正常退出

test测试命令

  1. 注意在Shell脚本中, 0是真值, 非0是假值
  2. 对于Integer, 方括号不支持>, <, 应该使用[[ ]], 示例: [[ 5<4 ]]
  3. 英文字母区分大小写

image.png

if-then语句

语法如下:

  1. if [测试条件] 或命令
  2. then 执行命令
  3. elif [测试条件2]
  4. then 执行命令
  5. else 测试条件不成立, 执行相应命令
  6. fi 结束

image.png
image.png
image.png
image.png

分支

case

  1. case "$变量" in
  2. "情况1" )
  3. 命令...;;
  4. "情况2" )
  5. 命令...;;
  6. * )
  7. 命令...;;
  8. esac

示例: 注意$0是当前脚本名字
image.png

循环

for循环

  1. for 参数 in 列表
  2. do 执行的命令
  3. done 封闭一个循环
  4. - 使用反引号或$()执行命令, 命令的结果当做列表进行处理
  5. - 列表中包含多个变量, 变量用空格分隔
  6. - 对文本处理, 要使用文本查看命令取出文本内容
  7. - 默认逐行处理, 如果文本出现空格会当做多行处理

示例: 将.mp3批量改为.mp4
image.png

C语言风格的for

  1. for((变量初始化;循环判断条件;变量变化))
  2. do
  3. 循环执行的命令
  4. done

image.png

while循环

  1. while test测试是否成立
  2. do
  3. 命令
  4. done

: 为空命令, while: ;为死循环
image.png

until循环

与while循环相反, 循环测试为假时, 执行循环, 为真时循环停止

循环的嵌套以及break, continue

break打破循环,
continue跳出当前循环
image.png

使用循环处理命令行参数

  • 命令行参数可以用$1 $2…${10}…$n来读取
  • $0代表脚本名称
  • $*和$@代表所有位置参数
  • $#代表位置参数的数量

示例: 将参数”help”打印两次
注意while循环中的shift作用是将参数左移, 比如sh test.sh a b c d 左移后参数剩 b c d
image.png

自定义函数

  • 自定义函数, function可省略

function fname(){
命令
}

  • 函数的执行

fname

  • 函数作用范围的变量

local 变量名

  • 函数的参数

$1 $2…$n

  • 函数的取消

unset fname
image.png
image.png

image.png

信号

kill会发送15号信号
ctrl+c会发送2号信号

示例: 使用trap捕获了15号以及2号信号, 因此此时使用kill或是ctrl+c不能使死循环停止
可以用kill -9 停止脚本, kill -9是不可阻塞的
image.png

计划任务

一次性计划任务

at命令

  1. at 18:31
  2. echo hello > /tmp/hello.txt

周期性计划任务

image.png