shell实现对多台服务器ssh免密登录

管理多台服务器手工执行ssh免密登录有点麻烦,于是写一个shell脚本实现自动化操作,记录以备后续查看。

2021.08.30更新,增加自定义生成密钥位数设置;增加已存在ssh key判断

2019年11月23日更新,支持自定义端口

scripts/shell at master · charnet1019/scripts · GitHub

#!/bin/bash
##########################################################
#
# Copyright (2017-10-21, )
#
# Author: charnet1019@163.com
# Last modified: 2017-10-22 00:02
# Description: 实现ssh免密登录
# 
# Tips: ssh服务端需设置如下参数解决连接慢拷贝失败的问题 
# IgnoreRhosts yes 
# GSSAPIAuthentication no 
# UseDNS no
#
##########################################################

# definition IP dictionary array
declare -A IPListDict

USER_NAME="root"

# 主机IP地址和密码,每行一个主机
IPListDict=(
[192.168.60.5:22]="secret"
[192.168.60.6:22022]="secret"
)

# for ssh
ssh_keygen="/usr/bin/ssh-keygen"
ssh_key_type="rsa"
ssh_key_bit=4096
ssh_pwd=''
ssh_key_base_dir=~/.ssh
ssh_pri_key=$ssh_key_base_dir/id_rsa
ssh_pub_key=$ssh_key_base_dir/id_rsa.pub
ssh_known_hosts=$ssh_key_base_dir/known_hosts
ssh_copy_id="/usr/bin/ssh-copy-id"

DATETIME='date "+%F %T"'

success() {
    printf "\r$(eval $DATETIME) [ \033[00;32mINFO\033[0m ]%s\n" "$1"
}

warn() {
    printf "\r$(eval $DATETIME) [\033[0;33mWARNING\033[0m]%s\n" "$1"
}

fail() {
    printf "\r$(eval $DATETIME) [ \033[0;31mERROR\033[0m ]%s\n" "$1"
}

usage() {
    echo "Usage: ${0##*/} {info|warn|err} MSG"
}

log() {
    if [ $# -lt 2 ]; then
        log err "Not enough arguments [$#] to log."
    fi

    __LOG_PRIO="$1"
    shift
    __LOG_MSG="$*"

    case "${__LOG_PRIO}" in
        crit) __LOG_PRIO="CRIT";;
        err) __LOG_PRIO="ERROR";;
        warn) __LOG_PRIO="WARNING";;
        info) __LOG_PRIO="INFO";;
        debug) __LOG_PRIO="DEBUG";;
    esac

    if [ "${__LOG_PRIO}" = "INFO" ]; then
        success " $__LOG_MSG"
    elif [ "${__LOG_PRIO}" = "WARNING" ]; then
        warn " $__LOG_MSG"
    elif [ "${__LOG_PRIO}" = "ERROR" ]; then
        fail " $__LOG_MSG"
    else
       usage
    fi
}

command_exists() {
	command -v "$@" > /dev/null 2>&1
}

install_expect() {
    yum -y install expect &> /dev/null
}

check_expect() {
    if ! command_exists expect; then
        log warn "No expect command and try to install, please wait..."
        install_expect
        if ! command_exists expect; then
            log err "Installation failed, please install the expect command manually."
            exit 1
        else
            log info "Installation successed."
        fi
    fi
}

get_cipher() {
    local IP=$1
    local PORT=$2

    for key in ${!IPListDict[@]}; do
        if [[ X"$IP:$PORT" == X"$key" ]]; then
            PASSWORD="${IPListDict[$key]}"
        fi
    done
}

is_exist() {
    local IP=$1

    if `grep -q "$IP" ${ssh_known_hosts}`; then
        return 0
    fi

    return 1
}

del_exist_host() {
    local IP=$1

    sed -i "/$IP/d" ${ssh_known_hosts}
}

generate_ssh_key() {
   if [ ! -f ${ssh_pri_key} ]; then
       ${ssh_keygen} -t ${ssh_key_type} -b ${ssh_key_bit} -P "${ssh_pwd}" -f ${ssh_pri_key} &> /dev/null
       if [ $? -eq 0 ]; then
           log info "Generate ssh key successfully."
       else
           log err "Generate ssh key failed."
       fi
   else
       echo "+++++ SSH key is already exists. +++++"
       echo
       echo "Select an option:"
       echo "   1) Regenerate a new ssh key"
       echo "   2) Use an existing ssh key"
       echo "   3) Exit"
       read -p "Option: " option
       until [[ "$option" =~ ^[1-3]$ ]]; do
                echo "$option: invalid selection."
                read -p "Option: " option
       done
       case "$option" in
           1)
               echo "y" | ${ssh_keygen} -t ${ssh_key_type} -b ${ssh_key_bit} -P "${ssh_pwd}" -f ${ssh_pri_key} &> /dev/null
               if [ $? -eq 0 ]; then
                   log info "Re-generate ssh key successfully."
               else
                   log err "Re-generate ssh key failed."
               fi
               ;;
           2)
               :
               log info "Use an existing ssh key."
               ;;
           3)
               exit
               ;;
       esac
   fi
}

copy_pub_key() {
   local IP=$1
   local PORT=$2

   if [ -f ${ssh_known_hosts} ]; then
       is_exist $IP
       if [ $? -eq 0 ]; then
           del_exist_host $IP
       fi
   fi
   
   get_cipher $IP $PORT
   
   expect -c <<- EOF &> /dev/null "
       spawn $ssh_copy_id -i "$ssh_pub_key" -p $PORT $USER_NAME@$IP
       expect {
            \"(yes/no)?\" {
                send \"yes\r\"
                expect {
                    "*assword" {
                        send \"$PASSWORD\r\"
                    }
                }
            }

            "*assword*" {
                send \"$PASSWORD\r\"
            }
            expect eof    
        }
        catch wait retVal
        exit [lindex \$retVal 3]"
EOF
       if [ $? -eq 0 ]; then
           log info "Copy the ssh pub key to $IP successfully."
       else
           log err "Copy the ssh pub key to $IP failed."
       fi
}


# main
check_expect
generate_ssh_key
for element in ${!IPListDict[@]}; do
    IP=`echo "$element" | cut -d':' -f1`
    PORT=`echo "$element" | cut -d':' -f2`

    copy_pub_key $IP $PORT
done


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值