美文网首页linux运维相关我是程序员
30个Linux Shell脚本经典案例(下)

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

作者: 六弦极品 | 来源:发表于2019-07-17 16:26 被阅读0次

    1、从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
    

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

    #!/bin/bash
    COUNT=1
    SUM=0
    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
        if [ $COUNT -eq 1 ]; then
            MIN=${INT}
            MAX=${INT}
        fi
        SUM=$(($SUM+$INT))
        [ $INT -lt $MIN  ] && MIN=$INT
        [ $INT -gt $MAX ] && MAX=$INT
        let COUNT++
    done
    echo "SUM: $SUM"
    echo "MIN: $MIN"
    echo "MAX: $MAX"
    
    
    # bash 100_sum_min_max.sh
    请输入1-10个整数:6
    请输入1-10个整数:99
    请输入1-10个整数:77
    请输入1-10个整数:4
    请输入1-10个整数:55
    SUM: 241
    MIN: 4
    MAX: 99
    
    

    3、将结果分别赋值给变量

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

    方法1:
    for i in {4..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]})
    

    4、批量修改文件名

    示例:
    # 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
    

    5、统计当前目录中以.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
    

    6、扫描主机端口状态

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

    7、Expect实现SSH免交互执行命令

    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
    

    8、批量修改服务器用户密码

    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
    

    9、打印乘法口诀

    方法1:
    # awk 'BEGIN{for(n=1;n<=9;n++){for(i=1;i<=n;i++){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
    

    10、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 <file_path> -n <line_number>"
                echo "-f, --file           specified file"
                echo "-n, --line-number    print specified line"
                exit 1
            ;;
        esac
    done
    
    image

    相关文章

      网友评论

        本文标题:30个Linux Shell脚本经典案例(下)

        本文链接:https://www.haomeiwen.com/subject/ircclctx.html