[附录代码] shell脚本一步完成多层ssh跳转时的文件传输

2020-05-12 10:41:59 浏览数 (2)

transfer_file.sh

代码语言:javascript复制
#!/usr/bin/expect
###############################################
# Author      :   PedroQin
# Date        :   2020-04-26 20:26:20
# Description :
# Version     :   1.0.0
###############################################


set timeout         -1
set script_name     $argv0
# send or recive file
set send_receive    [lindex $argv 0]
set dir_name        [lindex $argv 1]
set file_name       [lindex $argv 2]
set server_offset   [lindex $argv 3]
set server_id       [lindex $argv 4]
set username        [lindex $argv 5]
set host            [lindex $argv 6]
set passwd          [lindex $argv 7]
set hostname        [lindex $argv 8]
set remain_argv     [lrange $argv 9 999]

set basename        [lindex [split "$file_name" "/"] end]
set server_offset   [expr $server_offset   1]

if {$send_receive=="send"} {
    # send file

    if {$remain_argv!=""} {
        send_user "$server_offset. scp to $server_id $host ##**==  ==**## ==> "
        if {$server_offset=="1"} {
            spawn scp -r $file_name $username@$host:$dir_name/
        } else {
            spawn scp -r $dir_name/$basename $username@$host:$dir_name/
        }
        expect {
            "yes/no"                { send "yesn"; exp_continue}
            "password:"             { send "$passwdn" ; exp_continue}
        }

        send_user "$server_offset. ssh to $server_id $host ##**==  ==**## ==> "
        spawn ssh $username@$host
        expect {
            "yes/no"                { send "yesn"; exp_continue}
            "$host's password:"     { send "$passwdn" ; exp_continue}
            "$hostname*#"           { send "$script_name $send_receive $dir_name $file_name $server_offset $remain_argv && wait && sync && exitn" ; exp_continue}
        }
        
    } else {

        send_user "$server_offset. scp to $server_id $host ##**==  ==**## ==> "
        spawn scp -r $dir_name/$basename $username@$host:$dir_name/
        expect {
            "yes/no"                { send "yesn"; exp_continue}
            "password:"             { send "$passwdn" ; exp_continue}
        }

    }
} else {
    # recive file
    spawn mkdir -p $dir_name
    if {$remain_argv!=""} {
    
        send_user "$server_offset. ssh to $server_id $host ##**==  ==**## ==> "
        spawn ssh $username@$host
        expect {
            "yes/no"                { send "yesn"; exp_continue}
            "$host's password:"     { send "$passwdn" ; exp_continue}
            "$hostname*#"           { send "$script_name $send_receive $dir_name $file_name $server_offset $remain_argv && wait && sync && exitn" ; exp_continue}
        }
        
        send_user "$server_offset. scp from $server_id $host ##**==  ==**## ==> "
        spawn scp -r $username@$host:$dir_name/$basename $dir_name/
        expect {
            "yes/no"                { send "yesn"; exp_continue}
            "$host's password:"     { send "$passwdn" ; exp_continue}
        }
    } else {
        send_user "$server_offset. scp from $server_id $host ##**==  ==**## ==> "
        spawn scp -r $username@$host:$file_name $dir_name/
        expect {
            "yes/no"                { send "yesn"; exp_continue}
            "password:"             { send "$passwdn" ; exp_continue}
        }
    }
}
#interact
#expect eof

multi_scp.sh

代码语言:javascript复制
#!/bin/bash
###############################################
# Author      :   PedroQin
# Date        :   2020-04-26 22:43:32
# Description :
# Version     :   1.0.0
###############################################


config_file="/etc/multi_scp_conf.xml"
parameters=""
# the file is not in $dir
not_dir=0
# show message in green
function green_message()
{
    tput bold
    echo -ne "33[32m$@33[0m"
    tput sgr0
    echo
}

# show message in red
function red_message()
{
    tput bold
    echo -ne "33[31m$@33[0m"
    tput sgr0
    echo
}

function isdigit()
{
    local str=
    for str in $@
    do
        str=$1
        while [ -n "$str" ]; do
            echo ${str:0:1} | grep "[-.0-9]" > /dev/null 2>&1
            [ $? -ne 0 ] && return 27
            str=`echo ${str:1}`
        done
        shift
    done
    return 0
}

# $1 - keyword
# $2 - path to xml file
function xml_parse()
{
    local keyword=""
    local line=""
    local col=`sed -n "/<$1>/=" $2`
    local last=`sed -n "/</$1>/=" $2`

    [ -z "$col" ] && echo "err=255" && return 255

    line=`sed -n "$col p" $2`
    line=${line#*$1}

    if [ -z "$last" ]; then
        line=${line%/>*}
        echo ${line} | awk '{for (c=1;c<=NF;c  ) print $c}'
        last=0
    else
        echo ${line%*>}
    fi

    let col =1
    while (( $col < $last )); do
        line=`sed -n "$col p" $2`
        if [ -n "$line" ]; then
            keyword=${line##*/}
            line=${line%<*}
            echo "${keyword/>/=}"${line#*>}""
        fi
        let col =1
    done
    return 0
}

# decode the cmd
function parse_cmd()
{
    # decode the config
    route=`xml_parse "to_server_${server_id}" $config_file`
    if [ -z "$route" ] ;then
        red_message "Can't find route info in $config_file !"
        usage
    fi
    # get script and dir
    eval `xml_parse common $config_file`
    if [ -z "$command" ] || [ -z "$dir" ] ;then
        red_message "common information(command and dir) in $config_file is not complete !"
    fi
    # this 0 using for transfer_file.sh to calculate how many floors now
    parameters="$command $method $dir $file_name 0"
    offset=0
    for i in `echo "$route"|tr '>' ' '`;do
        # skip the local server
        [ $offset -eq 0 ] && let offset =1 && continue

        eval `xml_parse server.$i $config_file`
        if [ -z "$username" ] || [ -z "$IP" ] || [ -z "$passwd" ] ;then
            red_message "server.$i information in $config_file is not complete !"
            exit 254
        fi
        
        parameters="$parameters ID.$i $username $IP $passwd $hostname"
    done
    echo "$parameters"
    $parameters

}

function usage()
{
    cat <<USAGE
    $0 -t <server id in $config_file> -f <file name to send/receive> -m <send or receive> [ -c <config_file> ]
    $0 -h
USAGE
    exit 255
}

while getopts ":t:hc:f:m:" optname ;do
    case "$optname" in
        "m")
        method="$OPTARG"
        method=`echo "$method"|tr 'A-Z' 'a-z'`
        if [ "$method" == "send" -o "$method" == "s" ] ;then
            method="send"
        elif [ "$method" == "receive" -o "$method" == "r" ];then
            method="receive"
        else
            red_message "transfer method must be send/receive !"
            usage
        fi
        ;;

        "t")
        server_id="$OPTARG"
        if ! isdigit "$server_id" ;then
            red_message "server_idi: $server_id is illegal !"
            usage
        fi
        ;;

        "c")
        config_file="$OPTARG"
        ;;

        "f")
        file_name="$OPTARG"
        ;;

        "h")
        usage
        ;;
    esac
done
if [ -z "$method" ] || [ -z "$server_id" ] ||[ -z "$file_name" ] ;then
    usage
fi
if [ ! -f "$config_file" ];then
    red_message "Can't locate config file $config_file"
    exit 253
fi
parse_cmd

multi_scp_conf.xml

代码语言:javascript复制
<route>
    <to_server_2 1 > 2 />
    <to_server_3 1 > 2 > 3 />
    <to_server_4 1 > 2 > 3 > 4 />
    <to_server_5 1 > 2 > 3 > 4 > 5 />
    <to_server_6 1 > 2 > 3 > 4 > 6 />
</route>
<common>
    <command>transfer_file</command>
    <dir>/tmp</dir>
</common>
<server_info>
    <server.1 item="local server">
        <username>root</username>
        <IP>192.168.0.1</IP>
        <passwd>123456</passwd>
        <hostname>local</hostname>
    </server.1>
    <server.2 item="server 1">
        <username>root</username>
        <IP>192.168.1.1</IP>
        <passwd>123456</passwd>
        <hostname>server1</hostname>
    </server.2>
    <server.3 item="server 2">
        <username>root</username>
        <IP>192.168.2.1</IP>
        <passwd>123456</passwd>
        <hostname>server2</hostname>
    </server.3>
    <server.4 item="server 3">
        <username>root</username>
        <IP>192.168.3.1</IP>
        <passwd>123456</passwd>
        <hostname>server3</hostname>
    </server.4>
    <server.5 item="server 4">
        <username>root</username>
        <IP>192.168.4.1</IP>
        <passwd>123456</passwd>
        <hostname>server4</hostname>
    </server.5>
    <server.6 item="server 5">
        <username>root</username>
        <IP>192.168.5.1</IP>
        <passwd>123456</passwd>
        <hostname>server5</hostname>
    </server.6>
</server_info>

install.sh

代码语言:javascript复制
#!/bin/bash
###############################################
# Author      :   PedroQin
# Date        :   2020-04-28 15:40:50
# Description :
# Version     :   1.0.0
###############################################

Lines=66
MD5="e83f8ab79a1f0df0ef695030d6957066"
# show message in green
function green_message()
{
    tput bold
    echo -ne "33[32m$@33[0m"
    tput sgr0
    echo
}

# show message in red
function red_message()
{
    tput bold
    echo -ne "33[31m$@33[0m"
    tput sgr0
    echo
}

# print description and then run it
function print_run()
{
    if [ $# -eq 1 ];then
        green_message "$1"
        eval "$1"
    elif [ $# -eq 2 ];then
        green_message "$1"
        eval "$2"
    else
        return 1
    fi
}

function install_fail()
{
    red_message "install fail"
    exit 255
}

cat $0 |tail -n  $Lines > /tmp/multi_scp.tgz
md5_cur=`md5sum /tmp/multi_scp.tgz | awk '{print $1}'`
if [ "$md5_cur" != "$MD5" ];then
    red_message "Wrong md5sum ..."
    exit 255
else
    green_message "md5sum check pass"
fi
print_run "tar -xf /tmp/multi_scp.tgz -C /tmp"
print_run "cp /tmp/multi_scp/transfer_file.sh /usr/bin/transfer_file"   || install_fail
print_run "(cd /usr/bin; chmod  x transfer_file)"
print_run "cp /tmp/multi_scp/multi_scp.sh /usr/bin/multi_scp"           || install_fail
print_run "(cd /usr/bin; chmod  x multi_scp)"
print_run "cp /tmp/multi_scp/multi_scp_conf.xml /etc"                   || install_fail
print_run "rm -rf /tmp/multi_scp*"
echo Done
exit

0 人点赞