shell脚本基础
1.shell条件测试
1.1命令执行结果判定
&&在命令执行后如果没有任何报错时会执行符号后面的动作
||在命令执行后如果命令有报错会执行符号后的动作
ping -c1 -w1 $* &> /dev/null && { echo -e "$* is up" }||{ echo -e "$* is done" }
对命令执行结果的判定
脚本练习:检查用户是否存在,如果不存在就创建它,并且将密码设置为用户名
id $1 &> /dev/null &&{ echo $1 is exist }||{ echo $1 is not exist useradd $1 echo $1 | passwd --stdin $1 &> /dev/null && echo $1 is created }
1.2条件判定方法
脚本后的字符个数为$#
test = [],扩展的表达式要用[[ ]]括起来
[root@node ~]# [[ $a =~ 1|2 ]] && echo yes || echo no
判断a是不是在0-10之间
[root@node ~]# (($a<10&&$a>0)) && echo yes || echo no
(( ))只适用于整数
1.3文件判断表达式
-a/-e 文件是否存在 -L 软连接 -r 读权限
-b 扩展设备 -d 目录 -w 写权限
-c 字符设备 -f 普通目录 -x执行权限
-s 大s套接字小s文件大小不为零
-u 设置了特殊权限的suid
[root@node ~]# [ -e "/mnt/file" ]&& echo yes || echo no
脚本练习:脚本后写一个文件名称,如果存在输出文件的类型,如果不存在则输出文件不存在
[ -e "$1" ] || { echo $1 is not exist exit } [ -L "$1" ] &&{ echo $1 is link file } [ -f "$1" ] &&{ echo $1 is common file exit } [ -d "$1" ] &&{ echo $1 is dir file }
1.4字符串测试表达式
[root@node ~]# [ -z "$c" ] && echo yes || echo no
[root@node ~]# [ -n "$c" ] && echo yes || echo no
-n 判定是否不为空
-z 判定是否为空
= !=
测试字符串
1.5整数测试表达式
-eq ==或= -ge >=
-ne != -le <=
-gt > -lt <
[root@node ~]# [ "$a" -lt "1" ] && echo yes || echo no
[root@node ~]# [ "$a" -gt "1" ] && echo yes || echo no
[root@node ~]# [ "$a" -ge "1" ] && echo yes || echo no
[root@node ~]# [ "$a" -le "1" ] && echo yes || echo no
[root@node ~]# [ "$a" -eq "1" ] && echo yes || echo no
[root@node ~]# [ "$a" -ne "1" ] && echo yes || echo no
man test(查看帮助)
1.6判定中的逻辑操作符
[root@node ~]# [[ "$a" -gt 0 ]]&&[[ "$a" -lt "10" ]] && echo yes || echo no yes
[root@node ~]# (( "$a">0 && "$a"<10 )) && echo yes || echo no yes
[root@node ~]# [ "$a" -gt 0 -a "$a" -lt "10" ] && echo yes || echo no yes
[root@node ~]# test "$a" -gt 0 -a "$a" -lt "10" && echo yes || echo no yes
[root@node ~]# [ ! "$a" -lt "0" ] && echo yes || echo no yes(条件反选)
2.shell脚本中的运行流程控制
1.1if判定语句
脚本默认的程序执行方式是自上而下的
if单分支结构
if [ "$USER" = "root" ] then echo supper user fi
if双分支结构
if [ "$1" = "root" ] then echo supper user elif [ -z "$1" ] then echo pleas input username else echo unknow error fi
练习:if脚本代码
read -p "please input username: " USERNAME read -p "what do you want [D]elete or [C]create:" ACTION if [[ -z "$USERNAME" ]] then echo error: please input username exit elif [[ ! "$USER" = "root" ]] then echo "error: please run $0 with root" elif [[ "$ACTION" =~ d|D ]] then if id $USERNAME &> /dev/null then userdel -r $USERNAME echo $USERNAME is deleted else echo $USERNAME is not exist fi elif [[ "$ACTION" =~ C|c ]] then if id $USERNAME &> /dev/null then echo $USERNAME is exist else read -p "please input password:" PASS useradd $USERNAME echo $PASS | passwd --stdin $USERNAME &> /dev/null fi else echo "error: please input C|D for action!!" fi
2.2shell脚本中的选择判断(case语句)
用if做判断选择执行效率低,则需要使用case语句
case $1 in linux|Linux|LINUX) 一个“)”是一个按钮 echo zee ;; zee) echo linux ;; *) 其他和*都匹配 echo error esac
case可以解决恰巧在最后,执行效率会比较低的问题
-
case $1 in
-
echo liux
-
case $1 in
-
echo zee
-
'[' linux = linux ']'
-
echo zee
-
'[' zee = linux ']'
-
'[' zee = zee ']'
-
echo linux
2.3脚本中的循环语句
2.3.1无条件for循环
1.罗列变量的写法
for USERNAME in test1 test2 test3 do echo $USERNAME done
2.连续选择的写法
for USERNAME in {1..10} do echo $USERNAME done
3.用命令的执行结果充当变量的值(反引号提取执行的结果)
一次执行一个
for USERNAME in `ls /root` do echo $USERNAME done
4.用seq
for USERNAME in `seq 1 2 10` do echo $USERNAME done
5.用运算的方式
for ((USERNAME=1;USERNAME<=10;USERNAME++)) do echo $USERNAME done
2.3.2有条件的循环while
条件成立
while [ "$1" = "go" ] while [ "1" = "1"](直接执行) while [ "$1" = "start" ] (有动作的执行) do for N in {1..10} do echo $N done done
条件不成立用until
until [ "$1" = "go" ] do for N in {1..10} do echo $N done done
示例
while [ "$1" = "go" ] do clear (清空屏幕) ls -l /root sleep 1 (等1秒) done
练习:1分10秒倒计时
echo -ne (不换行 \生效)
[ -a ]并且
SEC=10 MIN=1 SECS=$[ $MIN*60+$SEC] for ((;SECS>0;SECS--)) do sec=$[$SECS%60] min=$[$SECS/60] echo -ne "after $min:$sec is end" echo -ne "\r" sleep 1 done
2.4循环中的控制器
1.exit
for n in {1..10} do if [ "$n" -eq "4" ] then echo luck exit (退出脚本) fi echo $n done
2.break
for n in {1..10} do if [ "$n" -eq "4" ] then echo luck break(退出循环) fi echo $n done
3.continue
for n in {1..10} do if [ "$n" -eq "4" ] then echo luck continue(下面放弃掉,提前进入下一次循环) fi echo $n done
4.return
FOR() { for n in {1..10} do if [ "$n" -eq "4" ] then echo luck return(退出函数 fi echo $n done } FOR
2.5自动应答
如果我们想要依照问题的内容回答问题需要借助软件expect(一种环境)
[root@node mnt]# dnf install expect -y 下载软件
[root@node mnt]# vim answer.exp
#!/usr/bin/expect spawn /mnt/ask.sh #spawn监控ask.sh expect { "name" { send "zee\r";exp_continue } "old" { send "18\r";exp_continue } "subject" { send "linux\r";exp_continue } "happy" { send "happy\r" } } expect eof #应答完毕后退出 interact #保留当前的绘画环境
[root@node mnt]# expect answer.exp
shell版本
#!/bin/bash /usr/bin/expect <<EOF spawn /mnt/ask.sh 将spawn写入expect执行 expect { "name" { send "zee\r";exp_continue } "old" { send "18\r";exp_continue } "subject" { send "linux\r";exp_continue } "happy" { send "happy\r" } } expect eof EOF
函数的调用
AUTO_ANSWER() { /usr/bin/expect <<EOF spawn /mnt/ask.sh 将spawn写入expect执行 expect { "name" { send "$1\r";exp_continue } "old" { send "$2\r";exp_continue } "subject" { send "$3\r";exp_continue } "happy" { send "$4\r" } } expect eof EOF } AUTO_ANSWER zee 18 linux happy