当前位置:网站首页 > Linux运维 > 正文

30个Linux Shell脚本经典案例(下)

作者:jinxijing发布时间:2019-07-19分类:Linux运维浏览:297


导读: 30个LinuxShell脚本经典案例(下)21,从FTP服务器下载文件#!/bin/bashif[$#-ne1];then  e...

 30个Linux Shell脚本经典案例(下)


21,从FTP服务器下载文件

#!/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

22,连续输入5个100以内的数字,统计和,最小和最大

#!/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"


23,将结果分别赋值给变量

应用场景:希望将执行结果或者位置参数赋值给变量,以便后续使用。

方法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]})

24,批量修改文件名

示例:

# touch article_{1..3}.html
# ls
article_1.html  article_2.html  article_3.html

目的:把物品改为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

25,统计当前目录中以的.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

26,扫描主机端口状态

#!/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



27,预计实现SSH免交互执行命令

期待是一个自动交互式应用程序的工具,如TELNET,FTP,passwd文件等。

需先安装期待软件包。

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

#!/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:将期望脚本独立出来

登录脚本:

# 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

28,批量修改服务器用户密码

Linux的主机SSH连接信息:旧密码

# cat old_pass.txt 
192.168.18.217  root    123456     22
192.168.18.218  root    123456     22

内容格式:IP用户密码端口

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

29,打印乘法口诀

方法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


30,getopts的工具完善脚本命令行参数

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

命令格式:getopts optstring name [arg]

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

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

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

  • optstring中第一个是冒号,表示屏蔽系统错误(test.sh:非法选项 - 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 <file_path> -n <line_number>"
           echo "-f, --file           specified file"
           echo "-n, --line-number    print specified line"
           exit 1
       ;;
   esac
done




111.png

 


标签:LinuxShellLinux ShellLinux运维云计算