shell脚本编程 ②
目录
- bash shell 配置文件
- 流程控制 if 和 case
- for 循环
- while 循环
- until 循环
- continue
- break
- shift
- while read
- select
- 函数
bash shell 配置文件
按照bash shell的生效范围划分
1 全局配置:针对所有用户有效
- /etc/profile
- /etc/profile.d/*.sh
- /etc/bashrc
2 个人配置:只对特定用户有效
- ~/.bash_profile
- ~/.bashrc
按照shell登录的两种方式分类
交互式登录,通过终端使用账号密码登录或者使用su - username切换的用户
交互式登录下,bash shell文件执行的顺序(命令在配置文件中位置不同,执行的顺序也不同)
# 命令放在放在每个配置文件最前面 /etc/profile /etc/profile.d/*. sh /etc/bashrc ~/ .bash_ profile ~/ .bashrc /etc/bashrc # 命令放在放在每个配置文件最后面 /etc/profile.d/*.sh /etc/bashrc /etc/profile /etc/bashrc #此文件执行两次 ~/.bashrc ~/.bash_profile
非交互式登录,如su username切换用户,图形界面下打开终端,执行脚本,执行顺序如下:
/etc/profile.d/*.sh /etc/bashrc ~/.bashrc
按照bash shell配置文件的功能划分
- profile类 为交互式登录的shell提供配置,功能在于定义环境变量,运行命令或脚本
- bashrc类 为非交互式登录的shell提供配置,功能在于定义命令别名或函数,定义本地变量
bash 退出任务
bash 退出任务脚本是~/. bash_logout,在退出shell的时候,会执行这个脚本。主要功能是创建备份和清除临时文件
流程控制
if 流程控制
if 判断条件1;then 条件为真执行代码 elif 判断条件2;then 条件2为真执行代码 elif 判断条件3;then 条件3为真执行代码 ... else 以上条件都为假执行的分支代码 fi
例子:
#!/bin/bash read -p "请输入你的身高(单位是M):" HIGH echo $HIGH if [[ ! "$HIGH" =~ ^[0-2](\.[0-9]{,2})?$ ]];then echo "输入错误" exit 1 fi read -p "请输入你的体重(单位是kg)" WEIGHT if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then echo "输入错误" exit 1 fi BMI=`echo $WEIGHT/$HIGH^2|bc` if [ $BMI -le 18 ];then echo "太瘦了,多吃点" elif [ $BMI -lt 24 ];then echo "身材很棒" else echo "太胖了,注意节食" fi
case流程控制
case 变量引用 in PAT1) 分支1 ;; PAT2) 分支2 ;; ... *) 默认分支 ;; esac
例子:
#!/bin/bash echo -en "\E[$[RANDOM%7+31];1m" cat << EOF 请选择: 1)备份数据库 2)清理日志 3)软件升级 4)软件回滚 5)删库跑路 EOF echo -en "\E[0m" read -p "请输入上边的数字1-5: " MENU case $MENU in 1) echo "执行备份数据库" ;; 2) echo "清理日志" ;; 3) echo "软件升级" ;; 4) echo "软件回滚" ;; 5) echo "删库跑路" ;; *) echo "输入错误" esac
for循环
# 方式1 for 变量名 in 列表;do 循环体 done # 方式2 for 变量名 in 列表 do 循环体 done # 方式3 for (( for (( exp1; exp2; exp3 )); do COMMANDS; done # 方式4 for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)) do 循环体 done
例子:
for i in {1..10};do useradd user$i PASS=`cat /dev/urandom | tr -dc '[:alnum:]' |head -c12` echo $PASS | passwd --stdin user$i &> /dev/null echo user$i:$PASS >> /data/user.log echo "user$i is created" done
九九乘法表
for i in {1..9};do for j in `seq $i`;do echo -e "\E[1;$[RANDOM%7+31]m${j}x${i}=$[j*i]\E[0m\t\c" done echo done
while循环
while COMMANDS; do COMMANDS; done while CONDITION; do 循环体 done
例1
sum=0 while ((i<=100));do let sum+=$i let i++ done echo $sum
例2
WARNING=50 while true;do USE=`df | sed -rn '/^\/dev\/sd/s#.* ([0-9]+)%.*#\1#p' |sort -nr|head -n1` if [ $USE -gt $WARNING ];then echo disk will be full | mail -s "主机报警" 693007996@qq.com fi sleep 10 done
until循环
until和while相似,不同的是until的进入条件是 until后接的条件结果是fasle
until COMMANDS; do COMMANDS; done until CONDITION; do 循环体 done
循环控制语句continue
跳过本次循环,直接进入到下一次的循环
while CONDITION1; do CMD1 ... if CONDITION2; then continue fi CMDn ... done
循环控制语句break
打断循环
while CONDITION1; do CMD1 ... if CONDITION2; then break fi CMDn ... done
shift
shitf [n] 用于将列表左移,默认左移一次。参量列表list一旦移动,最左端的那个参数就会从列表中删除。
while循环遍历位置参量列表时,经常会用到shift
举例:
#!/bin/bash echo $* shift echo $* shift echo $* shift echo $* #执行脚本传入多个参数,发现每一次shift都会删掉一个参数
if [ $# -eq 0 ];then echo "输入格式错误,必须有参数,参数为用户名" exit fi while [ "$1" ];do if id $1 &> /dev/null;then echo "用户 $1 已存在" else useradd $1 echo "用户 $1 已经创建完成" fi shift done echo "所有用户已成功创建" # 脚本后加要创建的用户名为参数,所有参数在一个列表,每次处理完一个用户shift,下一轮处理下一个参数
while read
while循环的特殊用法,遍历文件或文本的每一行做处理
举例:
while true;do WARNING=1 df | sed -nr '/^\/dev\/sd/s/^([^ ]+) .*([0-9]+)%.*/\1 \2/p' | while read DEVICE USE;do if [ $USE -gt $WARNING ] ; then echo "$DEVICE的容量已经达到$USE" fi done sleep 5; done # 循环处理每一行
select菜单
select循环用于创建菜单,按照数字的顺序把列表内的元素显示在菜单项,并显示PS3提示符,等待用户输入
用户输入列表中的某个数字,执行对应的命令
用户输入被保存在内置变量REPLY中
select是一个无限循环,要用break或者exit 打断循环或退出循环
select经常和case使用
与for循环相似,如果不带 in list,则使用位置变量
select NAME [in WORDS ... ;] do COMMANDS; done select variable in list ;do 循环体命令 done
举例:
#!/bin/bash sum=0 PS3="请点菜(1-6): " select MENU in 北京烤鸭 佛跳墙 小龙虾 羊蝎子 火锅 点菜结束;do case $REPLY in 1) echo $MENU 价格是 100 let sum+=100 ;; 2) echo $MENU 价格是 88 let sum+=88 ;; 3) echo $MENU价格是 66 let sum+=66 ;; 4) echo $MENU 价格是 166 let sum+=166 ;; 5) echo $MENU 价格是 200 let sum+=200 ;; 6) echo "点菜结束,退出" break ;; *) echo "点菜错误,重新选择" ;; esac done echo "总价格是: $sum"
函数
定义函数
# 语法一:
func_name (){
...函数体...
}
# 语法二:
function func_name {
...函数体...
}
# 语法三:
function func_name () {
...函数体...
}
查看函数
declare -F # 查看当前已定义的函数名 declare -f # 查看当前已定义的函数定义 declare -f func_name # 查看指定当前已定义的函数名 declare -F func_name # 查看当前已定义的函数名定义
删除函数
unset func_name
在交互式环境下创建使用函数
[root@centos8 mnt]# get_version () { > sed -nr "s/([a-z,A-Z]+) .* ([0-9]{1}).*/\1 \2/p" /etc/redhat-release > } [root@centos8 mnt]# get_version # 直接函数名调用
在脚本中定义使用函数
#!/bin/bash hello(){ echo "hello there today's date is `date "+%F %H:%M:%S"`" } echo "now going the function hello" hello echo "back from the function"