Bash脚本:简单来说就是把许多的指令集和在一起,并提供循环、条件、判断等重要功能,语法简单实用,用以编写程序,大大简化管理员的操作,并可以完成图形工具所无法实现的功能。
1、创建一个bash脚本
我们通常用vim来编辑一个脚本,它通常命名为 *.sh 。
如:vim test.sh
#!/bin/bash
echo "hello"
第一行是指定的命令解释器,常用的有#!/bin/bash 或#!/bin/sh,意思是告诉系统使用什么解释器来执行下面的语句。其他的以#开头的都是一些注释。
2、执行脚本
一般,刚写好的脚本文件的权限是:-rw-r–r–
在运行我们写出来的脚本前,需要给它执行权限chmod +x scripts(脚本名称)
(给所有用户执行权限,或按需要给其他权限)
(1)以绝对路径的方式去执行shell脚本
/mnt/test.sh
在shell脚本所在目录下,直接执行
cd /mnt/
./test.sh
(2)直接使用sh来执行脚本(在这种情况下,可以不必写第一行命令解释器,也可以不用修改权限)
sh test.sh 或 sh /mnt/test.sh
3、脚本调式模式
修改#!/bin/bash -x 或使用sh -x *.sh
4、特殊字符
(1)注释 #
(2)命令分隔符 ; (可以在一行写多个命令)
(3)反引号 ` (在执行一条命令时,会先将反引号内的语句当成命令先执行)
(4)引用和转译
弱引用(双引号““)
强引用 (单引号‘‘)
强引和弱引都是将引号内的字符看作普通字符
但强引用是将其中任何字符都看作普通字符,
弱引用不包括$、`、\
转译(\)一般转译后面的单个字符
例 test1.sh
#!/bin/bash
AA=date
BB=`date`
echo hello!! ; echo happy
#echo this is zhushi
echo abc \#def #ght
echo "$AA ; $BB ; `date` ; \$BB"
echo '$AA ; $BB ; `date` ; \$BB'
运行结果:
5、for循环
for循环的一般格式为
for 变量 in 列表 ;do ;done
例:test2.sh
(循环输出数字1-5)
#!/bin/bash
for NUM in {1..5}
do
echo $NUM
done
运行结果:
6、&& ||
格式:cmd1 && cmd2 || cmd3
若cmd1执行完毕且正确执行,则执行cmd2;若cmd1执行错误,则执行cmd3
例:ping.sh
(ping ip 地址172.25.254.220 - 224,
通了显示:ip is up;不通显示:ip is down)
#!/bin/bash
for NUM in {220..224}
do
ping -c1 -w1 172.25.254.$NUM &> /dev/null && echo 172.25.254.$NUM is up ||echo 172.25.254.$NUM is down
done
运行结果:
7、命令替换
格式:$(command) 或 `command`
如:TODAY=$(date +%Y-%m-%d)——DODAY就表示以年月日为格式的日期
例:将/etc下所有以.conf结尾的备份到 /mnt/etcconfig-(date)
#!/bin/bash
TODAY=etcconfig-`date +%Y-%m-%d-%S`
mkdir -p /mnt/$TODAY
cp /etc/*.conf /mnt/$TODAY
(%Y(年)-%m(月)-%d(日)-%S(秒))
执行几次后,可以在/mnt/目录下看见:
8、shell计算
算术运算符:
运算符 | 意思 |
---|---|
< VARIABLE >++ | 自加 |
< VARIABLE >- - | 自减 |
+ | 加法 |
- | 减法 |
* | 乘法 |
** | 幂运算 |
/ | 除法 |
% | 余数 |
+= | 加等 |
-= | 减等 |
计算命令:
(1)用$[]表示数学运算
(2)用expr表示数学运算
(注意数字与运算符之间要有空格,不能用于乘法,幂运算)
(3)用let表示数学运算
(4)用(())表示数学运算
如:((i=1;i<10;i++)) 从i=1开始,i进行自加,直到不满足i<10结束。
例:一个简单的倒计时
#!/bin/bash
for ((i=5;i>0;i--))
do
echo -n "After ${i}s is end!" #-n,输出不换行
echo -ne "\r \r" # 刷新这一行
sleep 1
done
运行结果:会在同一行显示倒计时“After 5s is end!“,数字由5到1结束。
9、while
while用来作条件判断,也可以用于循环。
语法:while [条件] ;do ;done
(注意条件与[]之间要有空格)
例:判断a是否等于1,是的话输出yes,不是输出no(-eq:等于)
10、参数read -p
read -p可以用来读取屏幕输入
常用方法:read -p “提示语” 变量(可以是多个)
(变量用来接收从shell界面输入的字符串)
例:
#!/bin/bash
read -p "What's your name:" name
read -p "what's your age and sex:" age sex
echo "$name is a $age-years-old $sex!!"
按提示输入相应的信息后,我们可以看到
11、位置参数
位置参数指的就是从命令行中传进来的参数, $0, $1, $2, $3…)(10及以后的位置参数要用${10},${11}…)
如:test.sh a b c
- 脚本文件的名字:$0(test.sh )
- 指定的位置参数总数:$#(即\$1,\$2等有多少个,没有是0)(3)
- 位置参数自身:$1,$2,$3… ( $1:a ,\$2:b …)
- 所有位置参数:$@,$*(a b c…)
例:用$#做判断,脚本后是否跟有参数,没有则提示输入一个ip,$1传递一个ip,判断该ip是否是通的。
#!/bin/bash
while [ "$#" -eq "0" ]
do
echo "Please give me a ip address!"
exit 1
done
ping -c 1 -w 1 $1 >/dev/null && echo "$1 is up" ||echo "$1 is down"
运行结果:
12、退出状态
我们常用“ $? “来判断上一个命令是否正确执行。
正常执行时,它的值为0,不正常时,值不为0
例:ls filename ; echo $? 可以用它来判断一个文件是否存在
#!/bin/bash
ls $1 &>/dev/null
[ "$?" -eq "0" ]&& echo $1 is exist || echo $1 is not exist
运行结果:
13、条件判断test命令
test条件判断可以做各种判断,这里列举一些常用的
(上面的退出状态“ $? “也是一种条件判断)
(1)判断字符串是否为空
判断字符串是否为空:-z
判断字符串是否为非空:-n
(2)字符串比较运算符
字符串 1 = 字符串2——判断字符串1是否和字符串2相等
字符串 1 != 字符串2——判断字符串1是否和字符串2不相等
(3)数字比较运算符
等于:-eq
不等于:-ne
大于:-gt
大于等于:-ge
小于:-lt
小于等于:-le
(4)二进制文件运算符
file1 -ef file2 判断file1和file2是否为硬链接
file1 -nt file2 判断file1的修改时间是否比file2的新
file1 -ot file2 判断file1的修改时间是否比file2的旧
(5)逻辑运算符
逻辑与:-a 判断1和判断2都成立,结果为真
逻辑或:-o 判断1和判断2有一个成立,结果为真
逻辑非:! 使原始的判断式取反
&& ,|| (见6)
(6)文件状态运算符
a、判断文件权限r,w,x
b、判断文件类型
判断文件是否存在:-e
判断文件是否为普通文件:-f
判断文件是否为目录:-d
判断文件是否为连接文件:-L
判断文件是否为块设备文件:-b
判断文件是否为字符设备文件:-c
判断文件是否为套接字文件:-S
例:check_file.sh(判断文件类型)
#!/bin/bash
while [ -z "$*" ]
do
echo "Please give a filename/directory
like: [ /mnt/check_file.sh /mnt/file" ]
exit 1
done
[ -e $1 ]|| (echo $1 is not exist!!!;exit 1)
[ -L $1 ]&& echo "$1 is a link"
[ -d $1 ]&& echo "$1 is a directory"
[ -b $1 ]&& echo "$1 is a block file"
[ -S $1 ]&& echo "$1 is a socket file"
[ -c $1 ]&& echo "$1 is a charactor file"
[ -f "$1" -a ! -L "$1" ]&& echo "$1 is a regular file"
运行结果:
14、if else语句
该语句的格式为:
if [满足的条件]
then
elif []
then
…
else
fi #结束标记
下面是一个简单的例子:(判断一个数是正数,负数,还是0)
#!/bin/bash
if
[ -z "$*" ]
then
echo "Please give a number"
elif
[ "$1" -lt "0" ]
then
echo "$1 is a negative number!"
elif
[ "$1" -gt "0" ]
then
echo "$1 is a positive number!"
else
echo "It is 0!!!"
fi
运行结果:
15、函数
在实现一个功能时,我们可能有很多代码都是重复的,这时,我们可以定义一个函数,让程序的结构更加清楚,代码利用率更高。
函数的定义
fun () { #fun是函数的名称
}
例子:
#!/bin/bash
#函数定义,里面的$1,$2是调用函数时,后面跟的变量
fun () {
echo "$1+$2=$(($1+$2))"
echo "$1-$2=$(($1-$2))"
echo "$1*$2=$(($1*$2))"
echo "$1/$2=$(($1/$2))"
}
#函数调用
fun 2 3
fun 5 1
运行结果:
16、case语句
case语句:它能把变量的值和多个模板进行匹配,在根据成功匹配的模板去判断应该执行哪部分代码。
格式:
case 变量 in
模式1)
command
;;
模式2)
command
;;
*) #表示在上面没有匹配的,用*表示
command
;;
esac
例子:
#!/bin/bash
case "$1" in
create)
touch $2
;;
delete)
rm -f $2
;;
*)
echo "use: /mnt/case.sh <create|delete> filename"
esac
运行结果:
17、expect
expect可以实现自动交互。在使用它之前,我们需要先安装它:
yum install -y expect
下面来实现ssh的自动连接,不需要输入密码
#!/usr/bin/expect表示使用expect的shell交互模式
set 定义变量
spawn在expect下执行shell脚本,命令等
expect对通过spawn执行的shell脚本的返回进行判断,是否包含“”中的字段
send:如果expect监测到了包含的字符串,将输入send中的内容,\n相当于回车
interact:退出expect返回终端,可以继续输入,否则将一直在expect不能退出到终端
#!/usr/bin/expect
set ip [ lindex $argv 0 ]
spawn ssh root@$ip
expect {
"yes/no" {send "yes\r";exp_continue}
"password" {send "123456\r"}
}
interact
运行结果: