bash脚本编程:
编程语言:
数据结构
顺序执行
选择执行
条件测试
运行命令或[[expression ]]
执行状态返回值
if
case
循环执行
将某代码重复运行多次
重复运行多少次?
循环次数事先已知
循环次数事先未知
必须有进入条件和退出条件
for、while、until
函数:结构化编程及代码重用
function
for循环语法:
forname in list; do
循环体
done
列表生成方式:
(1) 整数列表
{start..end}
$(seq start [[ step ]end])
(2) glob
/etc/rc.d/rc3.d/K*
(3) 命令
通过ping命令探测172.16.250.1-254范围内的所有主机的在线状态
#!/bin/bash
net="172.16.250"
uphosts=0
downhosts=0
for i in {1..20}; do
ping -c 1 -w 1 ${net}.${i} &> /dev/null
if [ $? -eq 0 ]; then
echo "${net}.${i} is up "
let uphosts++
else
echo "${net}.${i} is down "
let downhosts++
fi
done
echo "up hosts: ${uphosts}"
echo "down hosts: ${downhosts}"
练习:打印九九乘法表(for和while)
#!/bin/bash
for j in {1..9}; do
for i in $(seq 1 ${j}); do
echo -n "${i}*$[j]=$[${i}*${j} ] "
done
echo
done
#!/bin/bash
for ((j=1;j<=9;j++)); do
for((i=1;i<=j;i++)); do
echo -e -n "${i}*${j}=$[${i}*${j}]\t"
done
echo
done
练习:利用random生成10个数字,并显示其中的最大者和最小者
#!/bin/bash
declare -i max=0
declare -i min=0
declare -i i=1
max=$RANDOM
min=$max
while [ $i -le 10 ]; do
rand=$RANDOM
if [ $rand -gt $max ]; then
max=$rand
fi
if [ $rand -lt $min ]; then
min=$rand
fi
let i++
done
echo "max:$max "
echo "min:$min"
bash编程:
whilecondition; do
循环体
done
进入条件:condition为true
退出条件:false
untilcondition; do
循环体
done
进入条件:false
退出条件:true
示例:求100以内所有正整数之和
#!/bin/bash
declare -i sum=0
declare -i i=1
while [ $i -le 100 ]; do
let sum=sum+$i;
let i=i+1;
done
echo "sum:$sum."
循环控制语句:
continue:
while condition; do
cmd1
…
ifcondition2; do
continue
fi
cmd2
…
break
break [N]:提前结束循环
while condition; do
cmd1
…
ifcondition2; do
break
fi
cmd2
…
break
示例1:求100以内所有偶数之和,要求循环遍历100以内的所有正整数
#!/bin/bash
declare -i i=1
declare -i sum=0
until [ $i -gt 100 ]; do
let i++
if [ $[$i%2] -eq 1 ]; then
continue
fi
let sum=$sum+$i
done
echo "even sum:$sum"
创建死循环
示例2:
每隔3秒钟到系统上获取已经登录的用户的信息,如果doctker登录了,则记录在日志中,并退出
#!/bin/absh
read -p "enter a user name" username
while true; do
if who | grep "^$username" &> /dev/null; then
break
fi
sleep 3
done
echo "$usernmae logined" >> /tmp/userlogin.log
第二种,until
#!/bin/absh
read -p "enter a user name" username
until false; do
if ! who | grep "^$username" &> /dev/null; then
continue
fi
sleep 3
done
echo "$usernmae logined" >> /tmp/userlogin.log
while循环的特殊语法(遍历文件的每一行)
while read line; do
done < /path/from/somefile
一次读取/path/from/somefile文件中的每一行,且将行赋值给变量line
示例:找出id号为偶数的所有用户,显示其用户名和id号
#!/bin/bash
while read line; do
if [ $[`echo $line | cut -d: -f3` % 2] -eq 0 ] ; then
echo -e -n "username:`echo $line | cut -d: -f1`\t"
echo "uid:`echo $line | cut -d: -f3`"
fi
done < /etc/passwd
for循环的特殊格式:
for((控制变量初始化;条件判断表达式;控制变量的修正表达式)); do
循环体
done
示例:求100以内所有正整数之和
#!/bin/bash
declare -i sum=0
for((i=1;i<=100;i++)); do
sum=$sum+$i
done
echo "sum:$sum"
示例:
打印九九乘法表:
#!/bin/bash
for ((j=1;j<=9;j++)); do
for((i=1;i<=j;i++)); do
echo -e -n "${i}*${j}=$[${i}*${j}]\t"
done
echo
done
练习:
写一个脚本,完成如下任务
(1) 显示一个如下的菜单:
a) cpu)show cpu information
b) mem)show memory information
c) disk)show disk information
(2) 提示用户选择选项
(3) 显示用户选择的内容
进一步地:
用户选择,并显示完成后不退出脚本,而是提示用户继续选择其他内容,直到使用quit方式退出
#!/bin/bash
cat << EOF
cpu) show cpu information
mem) show memory information
disk) show disk information
quit) quit
--------------------------------------------
EOF
read -p "enter a option:" option
while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
read -p "wrong option,enter again:" option
done
if [ "$option" == 'cpu' ]; then
lscpu
elif [ "$option" == 'mem' ]; then
cat /proc/meminfo
elif [ "$option" == 'disk' ]; then
fdisk -lh
else
echo "quit"
exit 0
fi
条件判断:case语句
case 变量引用 in
pat1)
分支1
;;
part2)
分支2
;;
*)
默认分支
;;
esac
case写法:#!/bin/bash
cat << EOF
cpu) show cpu information
mem) show memory information
disk) show disk information
quit) quit
--------------------------------------------
EOF
read -p "enter a option:" option
while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
read -p "wrong option,enter again:" option
done
case "$option" in
cpu)
lscpu
;;
mem)
cat /proc/meminfo
;;
disk)
fdisk -l
;;
*)
echo "quit.."
exit 0
;;
esac
练习:写一个脚本,完成如下要求
(1) 脚本可接受参数:start,stop,restart,status
(2) 若果参数非此四者之一,提示格式后报错退出
(3) 如果是start,则创建/var/lock/syssubsys/script_name并显示启动成功
如果事先已经启动过一次,该如何处理
(4) 如果是stop,则删除/var/lock/syssubsys/script_name,并显示“停止完成”
考虑如果事先已停止过,该如何处理
(5) 如果是restart,则先stop,再start
考虑如果本来没有restart,如何处理
(6) 如果是status,则
如果/var/lock/syssubsys/script_name文件存在,则显示“script_name isrunning…”
如果/var/lock/syssubsys/script_name文件不存在,则显示“script_name isstopped…”
其中,script_name为当前脚本名:
#!/bin/bash
#chkconfig: - 88 12
description:test service script
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog
start(){
if [ -e $lockfile ]; then
echo "$prog is aleady running"
return 0
else
touch $lockfile
[ $? -eq 0 ] && echo "starting $prog finished."
fi
}
stop(){
if [ -e $lockfile ]; then
rm -f $lockfile && echo "stop $prog ok."
else
echo "$prog is stopped yet."
fi
}
status(){
if [ -e $lockfile ]; then
echo "$prog is running."\
else
echo "$prog is stopped."
fi
}
usage(){
echo "usage:$prog {start|stop|restart|status}"
}
if [ $# -lt 1 ]; then
usage
exit 1
fi
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
usage
;;
esac
case支持glob分割的通配符:
*:任意长度任意字符
?:任意单个字符
[]:任意范围内的单个字符
a|b:a或b
function:函数
过程式编程:代码重用
模块化编程
结构化编程
语法一:
functionf_name {
函数体
}
语法二:
f_name(){
函数体
}
调用:函数只有调用才会执行
调用:给定函数名
函数出现的地方,会被自动替换为函数代码
函数的生命周期,被调用时创建,返回时终止
return命令返回自定义状态结果
0:成功
1-255:失败
#!/bin/bash
username='myuser'
function adduser {
if id $username &> /dev/null; then
echo "$username has exists"
return 1
else
useradd $username
[ $? -eq 0 ] && echo "$username had created." && return 0
fi
}
adduser