自写 Shell 脚本快捷登陆服务器

开始的时候把个人的、公司的服务器登陆信息保存在了记事本当中,在每天需要频繁切换的情况下,实在是有些烦躁了,就想用 Shell 来写一个登陆脚本,知道有的 SSH 工具可以自带,写这样一个脚本原因就是个人兴趣。话说前阵子还出了个事情,某知名 SSH 工具带后门。

此脚本包括的 Shell 知识点:数组、自定义函数、if、while、printf、expect、read,等等,有基础知识点遗忘的时候也可以回头看看。

使用过程当中也出现了 Bug,都一一进行了修复,也存在还需要优化的地方,以后有空还会进行完善,目前我个人已经使用了一段时间,还算方便快捷。

脚本内容

#!/bin/bash

# 登陆信息配置
# 每个登陆信息为一个数组
# 第一个登陆信息的变量名称必须是「LOGIN_USER_1」,多条登陆信息时需要是 1 的连续整数 
LOGIN_USER_1=(
    'root' # 用户名
    '192.168.171.128' # 主机
    '8686' # 端口
    '' # 密码
    '/Users/admin/.ssh/id_rsa' # 密钥文件的绝对路径
    'key' # 登陆方式。key:密钥方式;pwd:密码方式
    '公司开发服务器' # 备注信息
)

LOGIN_USER_2=(
    'root'
    '192.168.171.120'
    '22'
    '123456'
    ''
    'pwd'
    '本地虚拟机 公司环境'
)

LOGIN_USER_3=(
    'root'
    '192.168.171.129'
    '22'
    '123456'
    ''
    'pwd'
    '本地虚拟机 个人环境'
)

LOGIN_TAG_START=1

login_user_configure_check() {

local LOCAL_LOGIN_TAG_START=${LOGIN_TAG_START}

# 第一个登陆配置数组不存在
if [ ! $(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}}) ]
then
    echo '错误!登陆数组:LOGIN_USER_'${LOCAL_LOGIN_TAG_START}' 不存在'
    exit 1
fi

while [ $(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}}) ]
do

    # 获得配置数组的元素总数
    local length=$(eval echo "\${#LOGIN_USER_${LOCAL_LOGIN_TAG_START}[*]}")

    if [ 7 -ne ${length} ]
    then
        echo 'LOGIN_USER_'${LOCAL_LOGIN_TAG_START}' 配置项必须是 7 项。脚本停止检查、终止执行、退出!'
        exit 1
    fi

    if [[ 'pwd' != "$(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}[5]})" ]] && [[ 'key' != "$(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}[5]})" ]]
    then
        echo 'LOGIN_USER_'${LOCAL_LOGIN_TAG_START}' 配置登陆方式错误,脚本停止检查、终止执行、退出!'
        exit 1
    fi

    if [[ 'key' == "$(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}[5]})" ]] && [[ ! "$(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}[4]})" ]]
    then
        echo 'LOGIN_USER_'${LOCAL_LOGIN_TAG_START}' 配置为密钥登陆,但是没有配置密钥文件,脚本停止检查、终止执行、退出!'
        exit 1
    fi

    for i in ` seq 0 "$((length-1))" `
    do
        if [ 3 -eq "${i}" ] || [ 4 -eq "${i}" ]
        then
            continue
        fi

        if [ ! "$(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}[${i}]})" ]
        then
            local LOGIN_USER_CONFIGURE_NUM=$((i+1))
            echo 'LOGIN_USER_'${LOCAL_LOGIN_TAG_START}' 第 '${LOGIN_USER_CONFIGURE_NUM}' 项配置不能为空'
            exit 1
        fi

    done

    ((LOCAL_LOGIN_TAG_START++))

done

}

# 调用登陆用户配置数组的检查
login_user_configure_check

screen_echo() {

printf "%-7s | " '序号'
printf "%-30s\n" '说明'

local LOCAL_LOGIN_TAG_START=${LOGIN_TAG_START}

while [ $(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}})  ]
do

    printf "\e[31m %-5s\e[0m| " "${LOCAL_LOGIN_TAG_START}" # 颜色为红色
    printf "%-30s\n" "$(eval echo \${LOGIN_USER_${LOCAL_LOGIN_TAG_START}[6]})"

    # 服务器总数 
    USER_SUM=${LOCAL_LOGIN_TAG_START}

    ((LOCAL_LOGIN_TAG_START++))

done

}

# 调用屏幕输出信息函数
screen_echo

while true
do

    # 让使用者选择所需要登陆服务器的所属序号
    read -p '请输入要登陆的服务器所属序号: ' LOGIN_NUM

    if [[ "${LOGIN_NUM}" =~ [^0-9]+ ]]
    then
        echo '序号是数字'
        continue
    fi

    if [ ! ${LOGIN_NUM} ]
    then
        echo '请输入序号'
        continue
    fi

    if [[ "${LOGIN_NUM}" =~ ^0 ]]
    then
        echo '序号不能以 0 开头'
        continue
    fi

    # 用户选择的序号 > 服务器总数、用户选择的序号 < 服务器总数。则提示错误并且重新循环
    if [ ${LOGIN_NUM} -gt ${USER_SUM} ] || [ ${LOGIN_NUM} -lt ${LOGIN_TAG_START} ]
    then
        echo '请输入存在的序号'
        continue
    fi

    break

done

# 登陆的函数

login_exec () {

# 当登陆方式是密码时
if [ 'pwd' == "$(eval echo \${LOGIN_USER_${LOGIN_NUM}[5]})" ]
then
    local mima=$(eval echo \${LOGIN_USER_${LOGIN_NUM}[3]})

    # 密码长度非 0 时
    if [ -n ${mima} ]
    then

        # 对 } 转义
        local mima=${mima//\}/\\\}}

        # 对 ; 转义
        local mima=${mima//\;/\\;}

    fi
fi

# spawn -noecho 不显示登陆信息
# 当登陆后出现「*yes/no*」是,回应「yes」
# ConnectTimeout 连接时超时时间;ConnectionAttempts 连接失败时的重试次数;StrictHostKeyChecking 不提示认证;ServerAliveInterval 客户端每多少秒向服务器发送请求;ServerAliveCountMax 客户端向服务器发送请求失败时的重试次数
# 「exp_continue」继续执行下面的匹配
# 「interact」留在远程终端上面。如果不写此语句,自动退出服务器
expect -c "
switch $(eval echo \${LOGIN_USER_${LOGIN_NUM}[5]}) {
    "pwd" { 
        spawn -noecho ssh -o ConnectTimeout=15 -o ConnectionAttempts=3 -o StrictHostKeyChecking=no -o ServerAliveInterval=15 -o ServerAliveCountMax=3 $(eval echo \${LOGIN_USER_${LOGIN_NUM}[0]})@$(eval echo \${LOGIN_USER_${LOGIN_NUM}[1]}) -p $(eval echo \${LOGIN_USER_${LOGIN_NUM}[2]})
        expect { 
            *yes/no* {
                send yes\r
                exp_continue
            }
            *denied* {
                exit
            }
            *password* {
                send ${mima}\r
            }
        }
        interact
    }
    "key" { 
        spawn -noecho ssh -o ConnectTimeout=15 -o ConnectionAttempts=3 -o StrictHostKeyChecking=no -o ServerAliveInterval=15 -o ServerAliveCountMax=3 -i $(eval echo \${LOGIN_USER_${LOGIN_NUM}[4]}) $(eval echo \${LOGIN_USER_${LOGIN_NUM}[0]})@$(eval echo \${LOGIN_USER_${LOGIN_NUM}[1]}) -p $(eval echo \${LOGIN_USER_${LOGIN_NUM}[2]})
        interact
    }
    default {
        puts "error"
    }
}
";

return 0;

}

# 调用登陆执行函数
login_exec

脚本不要忘了加上可执行权限

你需要的配置

脚本的开始就说了,第一个登陆信息数组名字必须是 LOGIN_USER_1,后面的服务器信息必须数组只需要 1 连续递增就好了。每个数组中的 7 个元素都不能少。脚本注释写的很清楚了。

GitHub 地址

Shell 登陆服务器脚本 GitHub 地址

知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。
随喜
支付宝随喜
微信随喜

我喜欢在.bash_profile加alias aliyun="ssh abc@xxx.xxx.xxx.xxx", 然后直接输入aliyun就可以了

后三排

我喜欢在.bash_profile加alias aliyun="ssh abc@xxx.xxx.xxx.xxx", 然后直接输入aliyun就可以了

引用

简单粗暴有效。哈哈