对于Linux服务器端开发人员,通过ssh访问远程主机是日常的一部分。但频繁地输入ip地址和密码的体验简直太坏了,程序员最不愿做重复的事。下面分享一个ssh连接管理脚本——ipbook。
ipbook是字符界面工具,可实现快速ssh访问。ipbook主要通过读取配置文件展示服务器列表,再根据输入的连接序号ssh到对应的主机上。

ipbook有一个配置文件$HOME/.ipbook.list,里面记录各主机登录信息。这和图形界面ssh工具类似,都是要先把登录信息保存起来。ipbook脚本首次执行时会创建配置文件模版,使用者根据提示修改.ipbook.list模版,加上自己的主机信息即可。

首次执行ipbook
配置文件内容示例:
IP列表 用户名 密码 目录 目录是否启用 主机描述
192.168.5.10 user1 password1 sbin 0 用户描述
192.168.5.11 user2 password2 sbin 0 用户描述
tips1:ipbook脚本ssh交互过程用到了expect解释器,若未安装,需要先dnf install expect。
tips2:把ipbook放到$PATH的某个目录下,直接ipbook执行更简单。
下面贴出ipbook源码(原创首发):
wen@fedora ~]$ cat ipbook
#!/bin/bash
################################################################
#author:zhaoxingwen <explorewen@163.com>
#date:20220212
#note:
#v0.1 快捷登录远程主机,通过ssh协议与远程服务器作命令交互
#使用方法:
# 执行脚本:./ipbook 或 sh ipbook
#
#配置说明:
# ipbook脚本读取$HOME/.ipbook.list文件,.ipbook.list里面配置登录信息;
# 首次执行ipbook脚本时会自动生成配置文件模版,根据提示例加入自已的连接配置;
# 配置文件中以#号开头表示注释.
# 配置示例:
# 192.168.5.10 user1 password1 sbin 0 用户描述
# 192.168.5.11 user2 password2 sbin 0 用户描述
#
################################################################
print_all_line(){
book_address=$1
IFS_old=$IFS
IFS=#39;\n' #强制指定\n为行结束符。默认空格和tab也作为分隔符
i=0
j=0
for line in `cat $book_address`
do
test -z "$line" && continue
firstch=`echo ${line:0:1}`
if [ x"$firstch" = "x#" ];then
let j+=1
if [ $j -eq 1 ];then
echo -e "\t\t\e[1;32mIP Book\e[0m"
echo -e "\e[1;33mNO.\tIP\t\tUSER\tDescription\e[0m"
echo -e "\e[1;33m--------------------------------------------------\e[0m"
fi
continue
else
let i+=1
echo -e "\e[33m$i:\t$line\e[0m" | awk -F ' ' '{ print $NR "\t" $(NR+1) "\t" $(NR+2) "\t" $NF}' #输出前三段,和尾段
fi
done;
IFS=$IFS_old
}
get_line(){
book_address=$1
if read -t 15 -p "Enter your choice:" choice ;then
if [ ! -n "$(echo $choice | sed -n "/^[0-9]\+$/p")" ];then
echo -e "\e[31m$choice is not a number.\e[0m"
exit
fi
else
echo -e "\e[31mtime out.\e[0m"
exit
fi
IFS_old=$IFS
IFS=#39;\n' #强制指定\n为行结束符。默认空格和tab也作为分隔符
declare -i num=0
for line in `cat $book_address`
do
test -z "$line" && continue
firstch=`echo ${line:0:1}`
if [ x"$firstch" = "x#" ];then
continue
else
num+=1
#echo "$num: $line"
if [ $num -eq $choice ];then
echo "$line" | awk '{ \
for(i=1;i<=NF;i++){\
print $i\
}\
}' #匹配到的行逐字段打出作为返回值
break
fi
fi
done;
IFS=$IFS_old
}
ipbook_work(){
book_address=$HOME/.ipbook.list
test ! -f $book_address && (echo "##ip user passwd directory openmode discription" > $book_address \
&& echo "##openmode :1 directory config is used ,0 :ignore directory configeg" >> $book_address \
&& echo "##Remove '#' if they are your records." >> $book_address \
&& echo "#192.168.5.10 user1 password1 sbin 0 用户描述" >> $book_address \
&& echo "#192.168.5.11 user2 password2 sbin 0 用户描述" >> $book_address \
&& echo "A sample configuration file was created at: $book_address ."&& echo "You should edit $book_address first!" ) && exit || print_all_line $book_address
v=$(get_line $book_address)
echo $v #得到匹配行
if [[ $v =~ "is not a number" ]];then #返回值包含子串"is not a number",这是输入非数值情况
echo -e "\e[1;4;33m------------end with input error------------------\e[0m"
exit
elif [[ $v =~ "time out" ]];then #超时返回
echo -e "\e[1;4;33m------------end with time out-------------------\e[0m"
exit
fi
#匹配行到数组
arr=(${v// / })
ip=${arr[0]}
username=${arr[1]}
userpassword=${arr[2]}
userdir=${arr[3]}
openmode=${arr[4]}
dispmsg=${arr[5]}
test -z $ip && echo -e "\e[31minput invalid\e[0m" && exit #输入是数字,但超过合理范围
ipbook_login_sh_address=$HOME/.ipbook_login.sh
$ipbook_login_sh_address ${ip} ${username} ${userpassword}
}
create_ipbook_login(){
ipbook_login_sh_address=$HOME/.ipbook_login.sh
cat > $ipbook_login_sh_address<<!
#!/usr/bin/expect -f
set ipaddr [lindex \$argv 0]
set username [lindex \$argv 1]
set passwdstr [lindex \$argv 2]
set timeout 30
spawn ssh -o "StrictHostKeyChecking no" \$username@\$ipaddr
expect "*password*"
send "\$passwdstr\r"
interact
!
chmod u+rwx $ipbook_login_sh_address
}
#-begin-------------------------
if [ $# -eq 0 ];then
clear
create_ipbook_login
ipbook_work
else
echo "usage:"
echo "./ipbook"
fi
铁锈笔记 2022-02-12