shell脚本基础
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