SHELL脚本编程基础
编程基础
-
Linus: Talk is cheap,show me the code(光说不练,给我看代码)
-
程序
- 程序:算法+数据结构
- 数据:是程序的核心
- 数据结构:数据在计算机中的类型和组织方式
- 算法:处理数据的方式
-
程序编程风格:
- 对象式:以数据为中心,指令服务于数据
- 过程式:以指令为中心,数据服务与指令
-
shell程序:提供了编程能力,解释执行
-
shell编程:过程式、解释执行
- 编程语言的基本结构:
- 各种系统命令的组合
- 数据存储:变量、数组
- 表达式:a+b
- 语句:if
- 编程语言的基本结构:
shell脚本基础
-
shell脚本:
- 包含一些命令或声明,并符合一定格式的文本文件
-
格式要求:首行shebang机制
- #!/bin/bash
- #!/usr/bin/perl
- #!/usr/bin/pythod
-
shell脚本的用途有:
- 自动化常用命令
- 执行系统管理和故障排除
- 创建简单的应用程序
- 处理文本或文件
-
执行脚本方法:
-
绝对路径|相对路径 文件名 (需要执行权限)
-
bash hello.sh
-
cat hello.sh | bash
-
添加环境变量PATH中,然后直接输入文件名:
-
vim /etc/profile.d/env.sh
PATH=/root/data/script/:$PATH
-
-
脚本调试(-n / -x /-c)
- -n 检测脚本中的语法错误
- bash -n /path/to/some_script
- -x 进入跟踪方式,显示所执行的每一条命令-x 进入跟踪方式,显示所执行的每一条命令
- bash -x /path/to/some_script
- -c 使shell解释器从一个字符串中而不是从一个文件中读取并执行shell命令
- bash -c “string” 从strings中读取命令
变量
- 变量:命名的内存空间
- 变量:变量类型
- 作用:
- 1、数据存储方式
- 2、参与的运算
- 3、表示的数据范围
- 类型:
- 1、字符
- 2、数值:整形,浮点型
- 作用:
- shell中变量命名法则:
- 1、不能使用程序中的保留字:例如if,for
- 2、只能使用数字、字母、下划线,且不能以数字开头
- 3、见名知义
- 统一命名规则:驼峰命名法
- shell中命名建议规则:
- 1、变量名大写
- 2、局部变量小写
- 3、函数名小写
- 4、用英文名字,并体现出实际作用
bash中变量的种类
- 根据变量的生效范围等标准划分下面变量类型
- 局部变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效。
- 环境变量:生效范围为当前shell进程及其子进程
- 本地变量:生效范围为当前shell进程中某代码片段,通常指函数
- 位置变量:$1,$2…来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数
- 特殊变量:$?, 0 , 0, 0,*, @ , @, @,#,$$
局部变量:
-
变量赋值:name=‘value’
-
可以使用引用值
- (1)可以是直接字串:name= ”root“
- (2)变量引用:name=”$USER“
- (3)命令引用:
- name=`COMMAND` (注:这里是反引号esc键下面)
- name=$(COMMAND)
-
变量引用:${name} 或者$name
- " "(双引号)弱引用,其中的变量引用会被替换为变量值
- ’’ (单引号) 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
-
显示已定义的所有变量:set
-
删除变量:unset name
环境变量
- 变量声明、赋值:
- export name=value
- declare -x name=value
- 变量引用:
- $name,${name}
- 显示所有环境变量:
- env
- printenv
- export
- declare -x
- 删除变量:
- unset name
只读和位置变量
- 只读变量:只能声明,但不能修改和删除(重新登录后自动消失)
- 声明只读变量:
- readonly name
- declare -r name
- 查看只读变量:
- readonly -p
- 声明只读变量:
- 位置变量:在脚本代码中调用通过命令行传递给脚本的参数
- $1,$2,… 对应第1、第2个参数,shift[n]换位置。
- $0 命令本身
- $@ 传递给脚本的所有参数,每个参数为独立字符串
- $# 传递给脚本的参数的个数
- 注意:$@ $*只在被双引号包起来的时候才会有差异
- 超过10个参数使用${10}(例${11},${12} 分别代表第11个参数、第十二个参数)
- set – 清空所有位置变量
退出状态
- 进程使用退出状态来报告成功或失败
- 0 代表成功,1 -255 代表失败
- 变量 ? 保存最近的命令退出状态(echo $?)
- 例如:
- ping -c1 -W1 hostdown &> /dev/null (bash提示错误)
- echo $? (打印上条命令的退出状态码)
- bash自定义退出状态码
- exit n:自定义退出状态码n
- 注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
- 注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
- exit 100 返回100状态码
算数运算
- bash中的算数运算:help let
- +,-,*,/,%,**(乘方),乘法符号有些场景中需要转义实现算术运算:
- 1、let var=算数表达式
- 2、var=$[算数表达式]
- 3、var=$((算术表达式))
- 4、var=$(expr arg1 arg2 arg3 …)
- 5、declare -i var=数值
- 6、echo ‘算数表达式’ | bc
- bash有内建的随机数生成器变量(范围0-32767):$RANDOM
- 示例:生成0-49之间随机数
- echo $[$RANDOM%50]
- echo $(($RANDOM%50))
- 示例:生成0-49之间随机数
赋值
- 增强型赋值:
- +=,-=,*=,/=,%=
- let varOPERvalue
- 例如:let count +=3
- 自加3后赋值
- 例如:let count +=3
- 自增,自减:
- let var+=1
- let var++
- let var -=1
- let var–
逻辑运算
- true,false
- 1,0
- 与
- 1 与 1 = 1
- 1 与 0 = 0
- 0 与 1 = 0
- 0 与0 = 0
- 或
- 1 或 1 = 1
- 1 或 0 = 1
- 0 或 1 = 1
- 0 或 0 = 0
- 非: !
- !1 = 0 !true
- !0 = 1 !false
- 短路运算
- 短路与 &&
- 短路或 ||
- 异或:^
- 异或的两个值,相同为假,不同为真
- 特性:
- A ^ B = C
- C ^ A = B
- C ^ B = A
- 利用特性,互换变量
- x=$[x^y]; y = $[x^y]; x=$[x^y]
- 第一个表达式:x是异或后的值
- 第二个表达式:y得到原x值
- 第三个表达式:x得到原y值
条件测试
- 判断某需求是否满足,需要由测试机制来实现专用的测试表达式需要由测试命令辅助完成测试过程
- 评估布尔申明,以便用在条件性执行中
- 若真,则返回0
- 若假,则返回1
- 测试命令:
- test EXPRESSION
- [ EXPRESSION ]
- [[ EXPRESSION ]] :支持正则表达式
- 注意:EXPRESSION前后必须有空白字符
bash的字符串测试
- 字符串测试:
- = :是否等于
- >:ascii码是否大于ascii码
- <:是否小于
- !=:是否不等于
- =~:左侧字符串是否能够被右侧的PATTERN所匹配,注意:此表达式一般用于[[]]中;扩展的正则表达式
- -z “STRING” :字符串是否为空,空为真,非空为假
- -n “STRING” :字符串是否不为空,非空为真,空为假
- 注意:用于字符串比较时的用到的操作数都应该使用引号
Bash的组合测试条件
- 第一种方式:
- EXPRESSIOON1 -a EXPRESSION2 并且
- EXPRESSIOON1 -o EXPRESSION2 或者
- !EXPRESSION
- 必须使用测试命令进行,[[]] 不支持
- 第二种方式:
- COMMAND1 && COMMAND2 并且,短路与,代表条件性的AND THEN
- COMmAND1 || COMMAND2 或者,短路或,代表条件性的OR ELSE
- !COMMAND 非
- 如:[ -f “KaTeX parse error: Expected 'EOF', got '&' at position 9: FILE" ] &̲& [[ "FILE” =~ .*\sh$ ]]
条件性的执行操作符
- 示例:
- grep -q no_shuch_user /etc/passwd || echo ‘No such user’
- No such user
- ping -c1 -W2 station1 &>/dev/null && echo “station1 is up” || (echo ‘station1 is unreachable’; exit 1)
- station1 is up
- grep -q no_shuch_user /etc/passwd || echo ‘No such user’
使用read命令来接受输入
- 使用read来把输入值分配给一个或多个shell变量
- -p :指定要显示的提示
- -s:静默输入,一般用于密码
- -n N:指定输入的字符长度N
- -d ‘字符’:输入结束符
- -t N:TIMEOUT为N秒
- read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量
- read -p “Enter a filename:” File
条件选择if语句
- 选择执行:
- 注意:if语句可嵌套
- 单分支
- if 判断条件;then 条件为真的分支代码;fi
- 双分支
- if判断条件;then 条件为真的分支代码
- else 条件为假的分支代码
- fi (结束符)
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
条件判断case
case: case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
- case支持glob风格的通配符:
- *:任意长度任意字符
- ?:任意单个字符
- []:指定范围内的任意单个字符
- a|b:a或b
#PAT1..:是通配符模式
#变量引用是 $变量名
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
例:
case $NUM in
1|3|5)
cmd1
;;
2|4|6)
cmd2
;;
*)
cmd3
;;
esac
bash如何展开命令行
- 把命令行分成单个命令
- 展开别名
- 展开大括号的声明({})
- 展开波浪符声明(~)
- 命令替换$() ``)
- 再次把命令行分成命令词
- 展开文件通配(*、?、[abc]等等)
- 准备I/O重导向(<,>)
- 运行命令
防止扩展
-
反斜线(\)会使随后的字符按原意解释
-
$ echo your cose:\$5.00 Your cose:$5.00
-
-
加引号来防止扩展
- 单引号(’ ')防止所有扩展
- 双引号(" ")也可防止扩展,但是以下情况例外
- $(美元符号)变量扩展
- ``(反引号)命令替换
- \ (反斜线)禁止单个字符扩展
- !(叹号)历史命令替换
bash的配置文件
- 按生效范围划分,存在两类:全局配置、个人配置
- 全局配置:
- /etc/profile
- /etc/profile.d/*.sh
- /etc/bashrc
- 个人配置:
- ~/.bash_profile
- ~/.bashrc
shell登录两种方式
-
交互式登录:
-
直接通过终端输入账号密码登录
-
使用”su - UserName“ 切换的用户
-
执行顺序:
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
-
-
非交互式登录:
-
su UserName
-
图形界面下打开的终端
-
执行脚本
-
任何其它的bash实例
-
执行顺序:
/etc/profile.d/*.sh --> /etc/bashrc --> ~/.bashrc
-
Profile类和Bashrc类
-
按功能划分,存在两类:
- profile类和bashrc类
-
profile类:为交互式登录的shell提供配置
- 全局:/etc/profile,/etc/profile.d/*.sh
- 个人:~/.bash_profile
- 功用:
- 用于定义环境变量
- 运行命令或脚本
-
bashrc类:为非交互式和交互式登录的shell提供配置
- 全局:/etc/bashrc
- 个人:~/.bashrc
- 功用:
- 定义命令别名和函数
- 定义本地变量
编辑配置文件生效
- 修改profile和bashrc文件后需生效
- 两种方法:
- 重新启动shell进程
- . 或者 source 配置文件
- 例 . ~/.bashrc
- 例 source ~/.bashrc
Bash退出任务
- 保存在~/.bash_logout文件中(用户)
- 在退出登录shell时运行
- 用于
- 创建自动备份
- 清除临时文件
set命令
- $- 变量
- h:hashall,打开这个选项后,Shell会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭,set -h将hash恢复
- i:interactive-comments,包含这个选项说明当前的shell是一个交互式的shell。所谓的交互式shell,在脚本中,i选项是关闭的
- m:monitor,打开监控模式,就可以通过Job Control来控制进程的停止、继续,后台或者前台执行等。
- B:braceexpand,大括号扩展
- H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如”!!“返回上最近的一个历史命令,"!n"返回第n个历史命令
脚本安全
- set 命令
- -u 在扩展一个没有设置的变量时,显示错误信息,等同set -o nounset
- -e 如果一个命令返回一个非0退出状态值(失败)就退出,等同于set -o errexit
配置用户环境