编写shell
Shell终端解释器当作人与计算机硬件之间的“翻译官”,Shell脚本命令的工作方式有两种:
交互式(Interactive):用户每输入一条命令就立即执行
批处理(Batch):由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中诸多的命令
系统默认使用Bash作为命令行终端解释器:
# echo $SHELL
shell脚本有三部分组成:
脚本声明:(#!)用来告诉系统使用哪种Shell解释器来执行该脚本;
注释信息:(#)是对脚本功能和某些命令的介绍信息;
脚本命令:可执行语句也就是我们平时执行的Linux命令了
#!/bin/bash
# this is example
pwd
ls
在日常中有解释器 来执行脚本;还有直接运行脚本程序的方法来执行,但是可能权限不足无法执行。这时需要增加权限即可
接收用户参数
像 ls -a 与 ls -l 同样的命令,参数不通结果不一样。也就是可以接收用户参数,判断参数。同样的脚本也是。
Linux系统中的Shell脚本已经内设了用于接收参数的变量,变量之间使用空格间隔。例如,
$0对应的是当前Shell脚本程序的名称,
$#对应的是总共有几个参数,
$*对应的是所有位置的参数值,
$?对应的是显示上一次命令的执行返回值,0表示执行成功,非0表示失败
而$1、$2、$3……则分别对应着第N个位置的参数值
判断用户参数
测试语句格式:
条件测试语句可分为4种:文件测试语句;逻辑测试语句;整数值比较语句;字符串比较语句。
文件测试的一些参数:
# [ -d /etc/fstab ]
# echo $?
# [-f /etc/fstab ]
# echo $?
逻辑测试参数:
&&是逻辑“与”,只有当前面的语句执行成功的时候才会执行后面的语句。
||是逻辑“或”,只有当前面的语句执行失败的时候才会执行后面的语句。
!是逻辑“非”,代表对逻辑测试结果取反值;之前若为正确则变成错误,若为错误则变成正确。
# [ -e /etc/fstab ] && echo "exists" || echo "it's no t exits"
# [ -e /dev/fstab ] && echo "exists" || echo "it's no t exits"
!逻辑非 需要与 字符串比较符的 != 不等于注意下,虽然下面的结果都一样,但是表示的不一样。第一个是取反,第二个是字符串的内容进行比较。
[root@linuxprobe ~]# [ ! $USER = root ] && echo "admin" || echo " user"
user
[root@linuxprobe ~]# [ $USER != root ] && echo "admin" || echo " user"
user
[root@linuxprobe ~]#
整数比较运算符
注意:shell中不能用 >,< 作为整数的比较运算符,
字符串比较运算符:
[root@linuxprobe ~]# [ -z $String ]
[root@linuxprobe ~]# echo $?
0
[root@linuxprobe ~]# echo $String
[root@linuxprobe ~]#
#流程控制语句
if条件测试语句
if语句分为单分支结构、双分支结构、多分支结构;
单分支:
双分支:
多分支:
例如:
[root@linuxprobe ~]# cat chkscore.sh
#!/bin/bash
read -p "Enter your score(0-100):" GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then
echo "$GRADE is Excellent"
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then
echo "$GRADE is Pass"
else
echo "$GRADE is Fail"
fi
[root@linuxprobe ~]# bash chkscore.sh
Enter your score(0-100):88
88 is Excellent
[root@linuxprobe ~]# bash chkscore.sh
Enter your score(0-100):80
80 is Pass
再来看下异常:
输入-1 和 2000数字,都是fail。所以要注意下else 的意思是:不满足前面条件的统统的都放到else 中。也就是 说 else 就是一个兜底行为。
但是 a 又有报错呢,实际是 字符与数字 无法进行比较而报的错。
[root@linuxprobe ~]# bash chkscore.sh
Enter your score(0-100):-1
-1 is Fail
[root@linuxprobe ~]# bash chkscore.sh
Enter your score(0-100):2000
2000 is Fail
[root@linuxprobe ~]# bash chkscore.sh
Enter your score(0-100):a
chkscore.sh: line 3: [: a: integer expression expected
chkscore.sh: line 5: [: a: integer expression expected
a is Fail
[root@linuxprobe ~]#
for范围循环语句
如,建立一个用户档案,然后对立面的用户进行批量新建
[root@linuxprobe ~]# vim users.txt
[root@linuxprobe ~]# cat users.txt
zhangsan
lisi
wanger
mazi
[root@linuxprobe ~]#
[root@linuxprobe ~]# id zhangsan
id: ‘zhangsan’: no such user
[root@linuxprobe ~]# id lisi
id: ‘lisi’: no such user
[root@linuxprobe ~]# id wanger
id: ‘wanger’: no such user
[root@linuxprobe ~]# id mazi
id: ‘mazi’: no such user
[root@linuxprobe ~]#
编写脚本:
里面的 /dev/null是一个被称作Linux黑洞的文件,把输出信息重定向到这个文件等同于删除数据(类似于没有回收功能的垃圾箱),可以让用户的屏幕窗口保持简洁。
[root@linuxprobe ~]# vim addusers.sh
[root@linuxprobe ~]# cat addusers.sh
#!/bin/bash
# this is script addusers
read -p "Enter a passwd: " PASSWD
for UNAME in `cat users.txt`
do
id $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "$UNAME is already exists"
else
useradd $UNAME
echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null
fi
done
[root@linuxprobe ~]# bash addusers.sh
Enter a passwd: redhat
[root@linuxprobe ~]#
[root@linuxprobe ~]# id zhangsan
uid=1001(zhangsan) gid=1001(zhangsan) groups=1001(zhangsan)
[root@linuxprobe ~]# id lisi
uid=1002(lisi) gid=1002(lisi) groups=1002(lisi)
[root@linuxprobe ~]# id wanger
uid=1003(wanger) gid=1003(wanger) groups=1003(wanger)
[root@linuxprobe ~]# id mazi
uid=1004(mazi) gid=1004(mazi) groups=1004(mazi)
[root@linuxprobe ~]#