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

简介:

本章目录:

wKiom1kuG2Dij8H6AAAuNhrwFhc739.png

12.21 FTP下载文件

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/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
user admin adminpass
binary    # 设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误
cd  $ dir
get  "$file"
EOF

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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"

wKioL1kuHZCQQNrOAAAloooYaNM429.png

12.23 将结果分别赋值给变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
方法1:
for  in  $( echo  "4 5 6" );  do
    eval  a$i=$i
done
echo  $a4 $a5 $a6
方法2:将位置参数192.168.18.1{1,2}拆分为到每个变量
num=0
for  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.18.1{1,2}
192.168.18.11 192.168.18.12
方法3:
arr=(4 5 6)
INDEX1=$( echo  ${arr[0]})
INDEX2=$( echo  ${arr[1]})
INDEX3=$( echo  ${arr[2]})

12.24 批量修改文件名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 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

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

1
2
3
4
5
6
7
8
9
方法1:
# find . -name "*.html" -maxdepth 1 -exec du -b {} \; |awk '{sum+=$1}END{print sum}'
方法2:
for  size  in  $( ls  -l *.html | awk  '{print $5}' );  do
     sum =$(($ sum +$size))
done
echo  $ sum
递归统计:
# find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}'

12.26 扫描主机端口状态

1
2
3
4
5
6
7
8
9
10
#!/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

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标准输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/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:

1
2
3
4
5
6
7
8
9
10
11
#!/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脚本独立出来

login.exp登录文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/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

执行命令脚本:

1
2
3
4
5
6
7
8
#!/bin/bash
HOST_INFO=user_info
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

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

修改密码脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
OLD_INFO=old_info
NEW_INFO=new_info
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

生成新密码new_info文件:

192.168.18.217  root    n8wX3mU%        22

192.168.18.218  root    c87;ZnnL        22

12.29 打印乘法口诀

1
2
3
4
5
6
7
8
9
10
方法1:
# awk 'BEGIN{for(n=0;n++<9;){for(i=0;i++<n;)printf i"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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/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 <file_path> -n <line_number>"
             echo  "-f, --file           specified file"
             echo  "-n, --line-number    print specified line"
             exit  1
         ;;
     esac
done

wKioL1kuID3zfLJWAAAeiazGKzY694.png

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



本文转自 李振良OK 51CTO博客,原文链接:http://blog.51cto.com/lizhenliang/1930804,如需转载请自行联系原作者

相关文章
|
2天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
22 3
|
5天前
|
运维 监控 Shell
利用Shell脚本编写局域网监控软件:实时监测主机连接情况
本文介绍了如何使用Shell脚本创建一个局域网监控工具,以实时检查主机连接状态。脚本包括扫描IP地址范围检测主机可达性及使用`netstat`监控ESTABLISHED连接。此外,还展示了如何每60秒将连接数数据自动提交到指定网站API,以便实时跟踪网络活动。这个自动化监控系统有助于提升网络安全性和故障排查效率。
23 0
|
6天前
|
Shell
Shell脚本之流程控制语句
Shell脚本之流程控制语句
|
7天前
|
JSON 运维 监控
训练shell常用脚本练习(三)
【4月更文挑战第14天】shell代码训练(三)
23 1
|
11天前
|
存储 弹性计算 Shell
ecs服务器shell常用脚本练习(十)
【4月更文挑战第11天】shell代码训练(十)
140 0
|
11天前
|
弹性计算 Shell Go
ecs服务器shell常用脚本练习(九)
【4月更文挑战第10天】shell代码训练(八)
133 0
|
15天前
|
弹性计算 Shell Linux
ecs服务器shell常用脚本练习(六)
【4月更文挑战第4天】shell代码训练(六)
108 0
|
20天前
|
弹性计算 Shell 应用服务中间件
ecs服务器shell常用脚本练习(四)
【4月更文挑战第4天】shell代码训练(四)
96 0
|
21天前
|
Shell
【shell】实时查看网卡流量脚本
【shell】实时查看网卡流量脚本
|
22天前
|
Shell Linux
Linux的shell入门教程shell脚本入门教程
Linux的shell入门教程shell脚本入门教程
15 0