分类: LINUX
2019-08-06 09:50:46
本文档介绍30个关于Shell脚本的经典案例(下) |
21、从FTP服务器下载文件 22、连续输入5个100以内的数字,统计和、最小和最大 23、将结果分别赋值给变量 24、批量修改文件名 25、统计当前目录中以.html结尾的文件总大 26、扫描主机端口状态 27、Expect实现SSH免交互执行命令 28、批量修改服务器用户密码 29、打印乘法口诀 30、getopts工具完善脚本命令行参数
#!/bin/bash if [ $# -ne 1 ]; then echo "Usage: $0 filename" fi dir=$(dirname $1) file=$(basename $1) ftp -n -v << EOF # -n 自动登录 open 192.168.1.10 # ftp服务器 user admin password binary # 设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误 cd $dir get "$file" EOF
#!/bin/bash COUNT=1 SUM=0 MIN=0 MAX=100 while [ $COUNT -le 5 ]; do read -p "请输入1-10个整数:" INT if [[ ! $INT =~ ^[0-9]+$ ]]; then echo "输入必须是整数!" exit 1 elif [[ $INT -gt 100 ]]; then echo "输入必须是100以内!" exit 1 fi SUM=$(($SUM+$INT)) [ $MIN -lt $INT ] && MIN=$INT [ $MAX -gt $INT ] && MAX=$INT let COUNT++ done echo "SUM: $SUM" echo "MIN: $MIN" echo "MAX: $MAX"
应用场景:希望将执行结果或者位置参数赋值给变量,以便后续使用。 方法1: for i in $(echo "4 5 6"); do eval a$i=$i done echo $a4 $a5 $a6 方法2:将位置参数192.168.1.1{1,2}拆分为到每个变量 num=0 for i in $(eval echo $*);do #eval将{1,2}分解为1 2 let num+=1 eval node${num}="$i" done echo $node1 $node2 $node3 # bash a.sh 192.168.1.1{1,2} 192.168.1.11 192.168.1.12 方法3: arr=(4 5 6) INDEX1=$(echo ${arr[0]}) INDEX2=$(echo ${arr[1]}) INDEX3=$(echo ${arr[2]})
示例: # touch article_{1..3}.html # ls article_1.html article_2.html article_3.html 目的:把article改为bbs 方法1: for file in $(ls *html); do mv $file bbs_${file#*_} # mv $file $(echo $file |sed -r 's/.*(_.*)/bbs\1/') # mv $file $(echo $file |echo bbs_$(cut -d_ -f2) done 方法2: for file in $(find . -maxdepth 1 -name "*html"); do mv $file bbs_${file#*_} done 方法3: # rename article bbs *.html
方法1: # find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}' 方法2: for size in $(ls -l *.html |awk '{print $5}'); do sum=$(($sum+$size)) done echo $sum
#!/bin/bash HOST=$1 PORT="22 25 80 8080" for PORT in $PORT; do if echo &>/dev/null > /dev/tcp/$HOST/$PORT; then echo "$PORT open" else echo "$PORT close" fi done
Expect是一个自动交互式应用程序的工具,如telnet,ftp,passwd等。
需先安装expect软件包。
方法1:EOF标准输出作为expect标准输入
#!/bin/bash
USER=root
PASS=123.com
IP=192.168.1.120
expect << EOF
set timeout 30
spawn ssh $USER@$IP
expect {
"(yes/no)" {send "yes\r"; exp_continue}
"password:" {send "$PASS\r"}
}
expect "$USER@*" {send "$1\r"}
expect "$USER@*" {send "exit\r"}
expect eof
EOF
方法2:
#!/bin/bash
USER=root
PASS=123.com
IP=192.168.1.120
expect -c "
spawn ssh $USER@$IP
expect {
\"(yes/no)\" {send \"yes\r\"; exp_continue}
\"password:\" {send \"$PASS\r\"; exp_continue}
\"$USER@*\" {send \"df -h\r exit\r\"; exp_continue}
}"
方法3:将expect脚本独立出来
登录脚本:
# cat login.exp
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set passwd [lindex $argv 2]
set cmd [lindex $argv 3]
if { $argc != 4 } {
puts "Usage: expect login.exp ip user passwd"
exit 1
}
set timeout 30
spawn ssh $user@$ip
expect {
"(yes/no)" {send "yes\r"; exp_continue}
"password:" {send "$passwd\r"}
}
expect "$user@*" {send "$cmd\r"}
expect "$user@*" {send "exit\r"}
expect eof
执行命令脚本:写个循环可以批量操作多台服务器
#!/bin/bash
HOST_INFO=user_info.txt
for ip in $(awk '{print $1}' $HOST_INFO)
do
user=$(awk -v I="$ip" 'I==$1{print $2}' $HOST_INFO)
pass=$(awk -v I="$ip" 'I==$1{print $3}' $HOST_INFO)
expect login.exp $ip $user $pass $1
done Linux主机SSH连接信息:
# cat user_info.txt
192.168.1.120 root 123456
Linux主机SSH连接信息:旧密码 # cat old_pass.txt 192.168.18.217 root 123456 22 192.168.18.218 root 123456 22 内容格式:IP User Password Port SSH远程修改密码脚本:新密码随机生成 #!/bin/bash OLD_INFO=old_pass.txt NEW_INFO=new_pass.txt for IP in $(awk '/^[^#]/{print $1}' $OLD_INFO); do USER=$(awk -v I=$IP 'I==$1{print $2}' $OLD_INFO) PASS=$(awk -v I=$IP 'I==$1{print $3}' $OLD_INFO) PORT=$(awk -v I=$IP 'I==$1{print $4}' $OLD_INFO) NEW_PASS=$(mkpasswd -l 8) # 随机密码 echo "$IP $USER $NEW_PASS $PORT" >> $NEW_INFO expect -c " spawn ssh -p$PORT $USER@$IP set timeout 2 expect { \"(yes/no)\" {send \"yes\r\";exp_continue} \"password:\" {send \"$PASS\r\";exp_continue} \"$USER@*\" {send \"echo \'$NEW_PASS\' |passwd --stdin $USER\r exit\r\";exp_continue} }" done 生成新密码文件: # cat new_pass.txt 192.168.18.217 root n8wX3mU% 22 192.168.18.218 root c87;ZnnL 22
方法1: # awk 'BEGIN{for(n=0;n++<9;){for(i=0;i++30、getopts工具完善脚本命令行参数
getopts是一个解析脚本选项参数的工具。 命令格式:getopts optstring name [arg] 初次使用你要注意这几点: 脚本位置参数会与optstring中的单个字母逐个匹配,如果匹配到就赋值给name,否则赋值name为问号; optstring中单个字母是一个选项,如果字母后面加冒号,表示该选项后面带参数,参数值并会赋值给OPTARG变量; optstring中第一个是冒号,表示屏蔽系统错误(test.sh: illegal option -- h); 允许把选项放一起,例如-ab 下面写一个打印文件指定行的简单例子,引导你思路: #!/bin/bash while getopts :f:n: option; do case $option in f) FILE=$OPTARG [ ! -f $FILE ] && echo "$FILE File not exist!" && exit ;; n) sed -n "${OPTARG}p" $FILE ;; ?) echo "Usage: $0 -f -n " echo "-f, --file specified file" echo "-n, --line-number print specified line" exit 1 ;; esac done
根据工作经验总结的30个Shell脚本案例至此完结,都还是比较实用的,面试笔试题也经常会出。希望朋友们多动手练一练,让你的Shell功底上升一个段位!