文章目录
案列1:批量创建任意数量的用户并设置随机密码
[root@shell_test example_shell]# cat useradd_set_passwd.sh
#!/bin/bash
#auth:sunwei
#以下几种方式都可以从命令行读取参数,进而传入脚本中
#userlist="$@"
#userlist="$*"
#userlist=$@
userlist=$*
userinfo=./user.info
#接收从命令行传入的用户名,进而创建
#for user in $userlist;do
num1=$1
num2=$2
#用户名前缀固定,接收从命令行传入的用户名后缀
for user in $(seq -f 'user%03g' $num1 $num2);do
if ! id $user &>/dev/null;then
pass=$(echo $RANDOM|md5sum |cut -c 1-8)
useradd $user
echo $pass |passwd --stdin $user
echo "$user $pass" >>$userinfo
if id $user &>/dev/null;then
echo "$user user was created successful..."
echo "======================================"
else
echo "$user create failed..."
fi
else
echo "$user user already exists..."
fi
done
案例2:批量主机执行命令(shell)
可以阅读网友博客:https://www.jellythink.com/archives/373
我们可以使用ssh root@192.168.1.4 "df -h"这种方式去远程主机执行密码(前提是做好免密码ssh配置),但是还可以使用expect脚本去实现,更加方便。下面为脚本:
#主机文件(存放用户名密码的文件)
[root@shell_test example_shell]# cat host.info
192.168.1.4 root 22 sunwei@123
#192.168.1.5 root 22 123
192.168.1.6 root 22 sunwei@123
脚本示例:
[root@shell_test example_shell]# cat expect.sh
#!/bin/bash
#auth:sunwei
COMMAND=$*
HOST_INFO=host.info
for IP in $(awk '/^[^#]/{print $1}' $HOST_INFO);do
USER=$(awk -v ip=$IP 'ip==$1{print $2}' $HOST_INFO)
PORT=$(awk -v ip=$IP 'ip==$1{print $3}' $HOST_INFO)
PASS=$(awk -v ip=$IP 'ip==$1{print $4}' $HOST_INFO)
expect -c "
spawn ssh -p $PORT $USER@$IP
expect {
\"(yes/no)\" {send \"yes\r\"; exp_continue}
\"password:\" {send \"$PASS\r\"; exp_continue}
\"$USER@*\" {send \"$COMMAND\r exit\r\"; exp_continue}
}
"
echo "---------------------"
done
[root@shell_test example_shell]# ./expect.sh free -g
案例3:检测网站可用性(使用curl)
脚本核心是采用curl工具探测网站通过状态返回码来判断网站是否可用
#!/bin/bash
#auth:sunwei
URL_LIST="www.baidu.com www.abcd.com"
for URL in $URL_LIST;do
FAIL_COUNT=0
for ((i=1;i<=3;i++ ));do
HTTP_CODE=$(curl -s -o /dev/null --connect-timeout 3 -w "%{http_code}" $URL)
if [ $HTTP_CODE -eq 200 ];then
echo "$URL is ok..."
break
else
echo "$URL retry $i"
let FAIL_COUNT++
fi
done
if [ $FAIL_COUNT -eq 3 ];then
echo "$URL had retry $FAIL_COUNT..failure"
fi
done
案例4:shell处理用户命令行选项
#!/bin/bash
while [ -n "$1" ];do
case $1 in
-a)
echo "Found the -a option";;
-b)
para="$2"
echo "fount the -b option,and the $para"
shift ;;
--)
shift
break;;
esac
shift
done
count=1
for para in "$@";do
echo "para#$count: $para"
count=$[$count+1]
done
[root@shell_test shell]# sh para.sh -a -b test1 -- test2 test3
Found the -a option
fount the -b option,and the test1
para#1: test2
para#2: test3
案例5: vmstat输出小脚本
需求:学习vmstat命令中各项参数的含义。开发一个脚本,定时(一分钟
一次)执行vmstat,连续执行两个小时,将其输出定向到一个文件。两小时后,由脚本将这些值进行处理,处理后重新写入到新的文件中,处理包括以下内容:
- 1.自动求出每个参数在这两个小时里的平均值,最大值和最小值。
- 2.对超过平均值浮动范围10%的数值以红色或粗体标出。
#!/bin/bash
#定义变量
current_time=`date '+%Y-%m-%d %H:%M:%S'`
one_mins_later=`date '+%Y-%m-%d %H:%M:%S' -d +1min`
output_file1=/tmp/vmstat.log
output_file2=/tmp/file_vmstat
>${output_file2}
#定义vmstat输出函数
function vmstat_out(){
vmstat|tail -n 1 >> ${output_file1}
sleep 5
}
#定义统计指标函数
function average_max_min(){
num=$2
field=$1
average=`awk '{sum+=$'$num'} END {print sum/(NR-1)}' ${output_file1}`
max=`awk 'NR!=1{print }' ${output_file1} |awk 'NR==1{max=$'$num';next}{max=max>$'$num'?max:$'$num'}END{print max}'`
min=`awk 'NR!=1{print }' ${output_file1} |awk 'NR==1{min=$'$num';next}{min=min<$'$num'?min:$'$num'}END{print min}'`
#平均值上限:平均值乘以110%
#平均值下限:平均值乘以90%
upper_value=`echo ${average}*1.1|bc`
lower_value=`echo ${average}*0.9|bc`
#echo "$1: $average $max $min ${upper_value} ${lower_value}"
echo -e "$1:\t${average}\t${max}\t${min}" >> ${output_file2}
echo -ne "$field\t"
awk 'NR!=1{if($'$num'<$upper_value||$'$num'>$lower_value){printf $'$num'"\t"}else{printf "\033[31m"$'$num'"\033[0m""\t"}}' ${output_file1}
echo ""
}
#脚本主入口
#屏幕格式化输出
echo -e "当前时间为:【\033[32m${current_time}\033[0m】,【\033[32m${one_mins_later}\033[0m】将统计vmstat命令输出的各项指标..."
#文件中打印首行
vmstat |awk 'NR==2{print}' > ${output_file1}
#当前时间如果等于预设的时间,则退出,进行数据的计算,否则,继续收集数据。
while [ "`date '+%Y-%m-%d %H:%M:%S'`" != "${one_mins_later}" ];do
vmstat_out
done
echo -e "\033[41;36m超出上下限范围分布\033[0m"
for i in `seq 1 17`
do
field=`awk 'NR==1{print $'$i'}' ${output_file1}`
average_max_min $field $i
done
echo -e "\033[41;36m下列数据依次为平均值、最大值、最小值!!!\033[0m"
cat ${output_file2}
后续改进点:格式化输出(屏幕打印时关键数据加上高亮);”平均值“、“最大值”、“最小值”与数据需一一对应
----------------------------------------------------------
实现2:
案例6: shell实现cp -r
需求:用shell编一个文件夹拷贝工具,不使用cp 的-r选项(可以使用cp),并对文
件夹中的每个文件使用进度条(打印’+'号即可)显示传输进度。
比较low:
#!/bin/bash
#假设a中全是文件,b中无任何文件或者目录,进而实现cp -r a b
# .
# ├── a
# │ ├── file1
# │ ├── file2
# │ └── file3
# └── b
#获取命令行参数
src=`basename $1`
dest=`basename $2`
flag=false
#遍历源目录,并进行传输
mkdir "$2/${src}"
for element in `ls $1`;do
src_file_size=`ls -l "$1/${element}"|awk '{print $5}'`
echo "开始传输${element},数据总大小为:${src_file_size} Bytes,目标路径为$2/${src}/${element}"
cp "$1/${element}" "$2/${src}/${element}"
while true;do
if [ `ls -l "$2/${src}/${element}"|awk '{print $5}'` == ${src_file_size} ];then
#dest_file_size=`ls -l "$2/${src}/${element}"|awk '{print $5}'`
#echo "传输进度:`echo ${dest_file_size}/${src_file_size}|bc`"
echo "传输完成..."
break
fi
done
done
后续改进需要考虑的点:
1. b目录不存在,需要进行判断。
2. a中也存在目录,需要递归将a目录里面的文件进行拷贝;a为文件时,需要考虑。
3. 命令行传参的判断,判断命令行参数数目个数。
4. 拷贝时进度条的实现。
案列7:scp
#!/bin/bash
servers=("126" "127" "128" "129")
for v in ${servers[@]}; do
scp $1 192.168.12.$v:/root/
done