bash脚本
1.用户交互
例: echo -n "Enter your name:" ; read name #表示将输入的文本保存在name变量中 ‘;’在bash中使用则顺序执行之后的命令 echo -n 让用户直接在后面输入
read 内部命令被用来从标准输入读取单行数据。这个命令可以用来读取键盘输入,当使用重定向的时候,可以读取文件中的一行数据
语法: read 参数 变量
-p 后面跟提示信息,即在输入前打印提示信息。
-t 后面跟秒数,定义输入字符的等待时间。
例: read -p "Enter your name: " -t 5 name
输出:Enter your name: #等待5秒不输入即会退出,变量name则为空
在写shell脚本中需要用户交互时,用户又没有及时填写可以设置默认值来赋予变量
例:
#!/usr/bin
read -p "Enter your name: " -t 5 name
[ -z $name ] && name='root'
执行脚本,等待5s echo $name 输出为root
bash -n 脚本 检查脚本中的语法错误
bash -x 脚本 调试执行
bash脚本编程:
CONDITION:
bash命令:
用命令的执行状态结果:
成功:true
失败:flase
成功或失败的意义,取决于用到的命令;
单分支:
if CONDITION;then
if-true
fi
双分支:
if CONDITION;then
if-true
else
if-false
fi
多分支:
if CONDITION;then
if-true
elif CONDITION;then
if-true
...
else
all-false
fi
逐条进行判断,第一次遇到为“真”条件时,执行其分支,而后结束
例:用户键入文件路径,判断是何种文件类型
#!/bin/bash
read -p "Enter a file path: " filename
if [ -z $filename ];then
echo "Usage:Enter a file path."
exit 2
fi
if [ ! -e $filename ];then
echo "No such file."
exit 3
fi
if [ -f $filename ];then
echo "A common file."
elif [ -d $filename ];then
echo"A directory"
elif [ -L $filename ];then
echo "A symbolic file."
else
echo "Other type."
fi
注意:if语句可嵌套;
循环:for,while,until
循环体:要执行的代码;可能要执行n遍;
进入条件:
退出条件:
for循环:
for 变量名 in 列表;do
循环体
done
执行机制:
依次将列表中的元素赋值给“变量名”;每次赋值后即执行一次循环体;直到列表中的元素用尽,循环结束;
示例:添加10个用户,user1-user10;密码同用户名;
#!/bin/bash
if [ ! $UID -eq 0 ];then #判断是否是root用户,root的uid为0,不等于则不是
echo "Only root."
exit 1 #不等于则退出脚本
fi
for i in {1..10};do #{1..10} == `seq 1 10`
if id user$i &> /dev/null; then #判断是否有用户存在,真则告知用户存在,假则执行下一步,将输出结果都放入/dev/null中
echo "user$i exists."
else
useradd user$i
if [ $? -eq 0 ]; then #判断上一条命令的成功与否,成功则$?为0
echo "user$i" | passwd --stdin user$i & > /dev/null #为用户创建密码,该方式不用交互,直接输入密码即可
echo "add user$i finished"
fi
fi
done
列表生成方式;
(1)直接给出列表;
(2)整数列表;
(a){start...end}
(b)$(seq [start [step]] end)==`seq [start [step]] end`
(3)返回列表的命令;
$(COMMAND)
示例:判断某路径下的所有文件类型
#!/bin/bash
for i in `ls /var`;do
if [ -L /var/$i ];then
echo "A symbolic file."
elif [ -f /var/$i ];then
echo "A common file."
elif [ -d /var/$i ];then
echo "A directory"
else
echo "Other type."
fi
done
或者
#!/bin/bash
for i in /var/* ;do
if [ -L $i ];then
echo "A symbolic file."
elif [ -f $i ];then
echo "A common file."
elif [ -d $i ];then
echo "A directory"
else
echo "Other type."
fi
done
(4)glob
(b)变量引用:
$@,$*
实例:查看netstatTCP协议中所有的状态信息
#!/bin/bash
declare -i estab=0
declare -i listen=0
declare -i other=0
for i in `netstat -ant | grep '^tcp\>' | awk '{print $NF}'`;do
if [ "$i" == 'ESTABLISHED' ];then
let estab++
elif [ "$i" == 'LISTEN' ];then
let listen++
else
let other++
fi
done
echo 'ESTABLISHED:'$estab
echo 'LISTEN:'$listen
echo 'Other:'$other
备注:declare命令
declare[+/-][选项]变量名
选项
-:给变量设置类型属性
+:取消变量的类型属性
-a:将变量声明为数组型
-i:将变量声明为整数型(integer)
-x:将变量声明为环境变量
-r:将变量声明为只读变量
-p:显示指定变量的被声明的类型
练习1:/etc/rc.d/rc3.d目录下分别由多个以K开头和S开头的文件:
分别读取每个文件,以K开头的文件输出为文件加stop,以S开头的文件输出为文件名加start;
xargs 加-i 参数直接用 {}就能代替管道之前的标准输出的内容;
find /etc/rc.d/rc3.d/ -name K* | xargs -i mv {} {}.stop
find /etc/rc.d/rc3.d/ -name S* | xargs -i mv {} {}.start
练习2:使用ping命令探测192.168.1.1-254之间的主机的在线状态;
#!/bin/bash
uphosts=0
downhosts=0
for i in {1..254};do
ping -c 1 -w 1 192.168.1.$i &> /dev/null
if [ $? -eq 0 ];then
echo "192.168.1.$i is up."
let uphosts++
else
echo "192.168.1.$i is down"
let downhosts++
fi
done
echo "Up hosts: $uphosts."
echo "Down hosts: $downhosts."