加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

第十二章 Shell脚本编写及常见面试题(三)

发布时间:2020-12-15 16:58:24 所属栏目:安全 来源:网络整理
导读:本章目录: 650) this.width=650;" src="http://img.jb51.cc/vcimg/static/loading.png" title="QQ图片20170531092359.png" alt="wKiom1kuG2Dij8H6AAAuNhrwFhc739.png" src="https://s2.51cto.com/wyfs02/M02/97/5E/wKiom1kuG2Dij8H6AAAuNhrwFhc739.png"> 12

本章目录:

wKiom1kuG2Dij8H6AAAuNhrwFhc739.png

12.21 FTP下载文件

#!/bin/bash
if[$#-ne1];then
echo"Usage:$0filename"
fi
dir=$(dirname$1)
file=$(basename$1)
ftp-n-v<<EOF#-n自动登录
open192.168.1.10
useradminadminpass
binary#设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误
cd$dir
get"$file"
EOF

12.22 输入五个100数之内的字符,统计和、最小和最大

COUNT=1
SUM=0
MIN=0
MAX=100
while[$COUNT-le5];do
read-p"请输入1-10个整数:"INT
if[[!$INT=~^[0-9]+$]];then
echo"输入必须是整数!"
exit1
elif[[$INT-gt100]];then
echo"输入必须是100以内!"
exit1
fi
SUM=$(($SUM+$INT))
[$MIN-lt$INT]&&MIN=$INT
[$MAX-gt$INT]&&MAX=$INT
letCOUNT++
done
echo"SUM:$SUM"
echo"MIN:$MIN"
echo"MAX:$MAX"

wKioL1kuHZCQQNrOAAAloooYaNM429.png

12.23 将结果分别赋值给变量

方法1:
foriin$(echo"456");do
evala$i=$i
done
echo$a4$a5$a6
方法2:将位置参数192.168.18.1{1,2}拆分为到每个变量
num=0
foriin$(evalecho$*);do#eval将{1,2}分解为12
letnum+=1
evalnode${num}="$i"
done
echo$node1$node2$node3
#basha.sh192.168.18.1{1,2}
192.168.18.11192.168.18.12
方法3:
arr=(456)
INDEX1=$(echo${arr[0]})
INDEX2=$(echo${arr[1]})
INDEX3=$(echo${arr[2]})

12.24 批量修改文件名

#toucharticle_{1..3}.html
#ls
article_1.htmlarticle_2.htmlarticle_3.html
现在想把article改为bbs:
方法1:
forfilein$(ls*html);do
mv$filebbs_${file#*_}
#mv$file$(echo$file|sed-r's/.*(_.*)/bbs1/')
#mv$file$(echo$file|echobbs_$(cut-d_-f2)
done
方法2:
forfilein$(find.-maxdepth1-name"*html");do
mv$filebbs_${file#*_}
done
方法3:
#renamearticlebbs*.html

12.25 统计当前目录中以.html结尾的文件总大小

方法1:
#find.-name"*.html"-maxdepth1-execdu-b{};|awk'{sum+=$1}END{printsum}'
方法2:
forsizein$(ls-l*.html|awk'{print$5}');do
sum=$(($sum+$size))
done
echo$sum
递归统计:
#find.-name"*.html"-execdu-k{};|awk'{sum+=$1}END{printsum}'

12.26 扫描主机端口状态

#!/bin/bash
HOST=$1
PORT="2225808080"
forPORTin$PORT;do
ifecho&>/dev/null>/dev/tcp/$HOST/$PORT;then
echo"$PORTopen"
else
echo"$PORTclose"
fi
done

wKiom1kuIdyj5UkEAAAONQjBJ3c657.png

12.27 Expect实现SSH免交互执行命令

需要先安装expect工具。

expect涉及用法说明:

命令描述

set可以设置超时,也可以设置变量

timeout超时等待时间,默认10s

spawn执行一个命令

expect ""匹配输出的内容

exp_continue继续执行下面匹配

r回车

$argc统计位置参数数量

[lindex $argv 0]位置参数

puts打印字符串,类似于echo

expect{...}输入多行记录

方法1:EOF标准输出作为expect标准输入

#!/bin/bash
USER=root
PASS=123.com
IP=192.168.1.120
expect<<EOF
settimeout30
spawnssh$USER@$IP
expect{
"(yes/no)"{send"yesr";exp_continue}
"password:"{send"$PASSr"}
}
expect"$USER@*"{send"$1r"}
expect"$USER@*"{send"exitr"}
expecteof
EOF

方法2:

#!/bin/bash
USER=root
PASS=123.com
IP=192.168.1.120
expect-c"
spawnssh$USER@$IP
expect{
"(yes/no)"{send"yesr";exp_continue}
"password:"{send"$PASSr";exp_continue}
"$USER@*"{send"df-hrexitr";exp_continue}
}"

方法3:将expect脚本独立出来

login.exp登录文件:

#!/usr/bin/expect
setip[lindex$argv0]
setuser[lindex$argv1]
setpasswd[lindex$argv2]
setcmd[lindex$argv3]
if{$argc!=4}{
puts"Usage:expectlogin.expipuserpasswd"
exit1
}
settimeout30
spawnssh$user@$ip
expect{
"(yes/no)"{send"yesr";exp_continue}
"password:"{send"$passwdr"}
}
expect"$user@*"{send"$cmdr"}
expect"$user@*"{send"exitr"}
expecteof

执行命令脚本:

#!/bin/bash
HOST_INFO=user_info
foripin$(awk'{print$1}'$HOST_INFO)
do
user=$(awk-vI="$ip"'I==$1{print$2}'$HOST_INFO)
pass=$(awk-vI="$ip"'I==$1{print$3}'$HOST_INFO)
expectlogin.exp$ip$user$pass$1
done

SSH连接信息文件:

# cat user_info

192.168.1.120 root 123456

12.28 批量修改服务器用户密码

旧密码SSH主机信息old_info文件:

# ip user passwd port

#--------------------------------------

192.168.18.217 root 123456 22

192.168.18.218 root 123456 22

修改密码脚本:

#!/bin/bash
OLD_INFO=old_info
NEW_INFO=new_info
forIPin$(awk'/^[^#]/{print$1}'$OLD_INFO);do
USER=$(awk-vI=$IP'I==$1{print$2}'$OLD_INFO)
PASS=$(awk-vI=$IP'I==$1{print$3}'$OLD_INFO)
PORT=$(awk-vI=$IP'I==$1{print$4}'$OLD_INFO)
NEW_PASS=$(mkpasswd-l8)
echo"$IP$USER$NEW_PASS$PORT">>$NEW_INFO
expect-c"
spawnssh-p$PORT$USER@$IP
settimeout2
expect{
"(yes/no)"{send"yesr";exp_continue}
"password:"{send"$PASSr";exp_continue}
"$USER@*"{send"echo'$NEW_PASS'|passwd--stdin$USERrexitr";exp_continue}
}"
done

生成新密码new_info文件:

192.168.18.217 root n8wX3mU% 22

192.168.18.218 root c87;ZnnL 22

12.29 打印乘法口诀

方法1:
#awk'BEGIN{for(n=0;n++<9;){for(i=0;i++<n;)printfi"x"n"="i*n"";print""}}'
方法2:
for((i=1;i<=9;i++));do
for((j=1;j<=i;j++));do
result=$(($i*$j))
echo-n"$j*$i=$result"
done
echo
done

wKioL1kuHgrQ_XPxAABhsSZCEJg877.png-wh_50

12.30 getopts工具完善脚本命令行参数

getopts是一个解析脚本选项参数的工具。

命令格式:getopts optstring name [arg]

初次使用你要注意这几点:

1)脚本位置参数会与optstring中的单个字母逐个匹配,如果匹配到就赋值给name,否则赋值name为问号;

2)optstring中单个字母是一个选项,如果字母后面加冒号,表示该选项后面带参数,参数值并会赋值给OPTARG变量;

3)optstring中第一个是冒号,表示屏蔽系统错误(test.sh: illegal option -- h);

4)允许把选项放一起,例如-ab

下面写一个打印文件指定行的简单例子,用于引导你思路,扩展你的脚本选项功能:

#!/bin/bash
whilegetopts:f:n:option;do
case$optionin
f)
FILE=$OPTARG
	[!-f$FILE]&&echo"$FILEFilenotexist!"&&exit
;;
n)
sed-n"${OPTARG}p"$FILE
;;
?)
echo"Usage:$0-f<file_path>-n<line_number>"
echo"-f,--filespecifiedfile"
echo"-n,--line-numberprintspecifiedline"
exit1
;;
esac
done

wKioL1kuID3zfLJWAAAeiazGKzY694.png

思路扩展:限定脚本参数,将参数保存变量,下面调用变量继续操作。


本章写的Shell脚本例子都比较实用,在面试题中也经常出现,希望大家多动手练习,不要复制粘贴就拿来跑,这样是学不会的!有问题请加群交流:323779636(Shell/Python运维开发群)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读