背景
在windows中,有诸如XShell,SecureCRT等ssh连接神器,但在Mac中,可选择的工具并不多,ITerm2被一众程序员吹上了天,但自己实际用下来并不好用,对终端的执念让我基本上尝试了所有在Mac上能找得到的终端工具,最终选择了termius,该工具界面有点极客风,设计简洁,连接速度快,可惜的是如果用户退出所有记录将被清除,在被清除两次后终于无奈的放弃了Mac下唯一上手的终端工具,放弃termius后却很难再找一个满意的终端,mac自带的终端其实还行,就是不大好用,理想中的终端应该满足以下功能
- 能够发送心跳包,不至于因为断网或者闲置时间过长连接断开需要重连
- 能够有一定的管理功能,记住密码,不用每次输入地址和账号,这个也是最重要的需求
- 支持tab页,支持分屏
- 能够上传下载文件
- 颜值要高
- 可以选择复制,因为在终端经常需要复制,大部分终端都可以选择即可复制,无需手动ctrl+c
如果mac自带终端能够满足以上需求,就完全可以用于日常开发,那么接下来我们就一步步改造终端
心跳检测
用过ssh终端的都知道,如果网络断开或者长时间不操作,会导致终端掉线,表现为键盘无响应,需要重新连接,有时候我们在服务器工作目录下,重新登录又要切换到当前目录,非常到不方便,因此一般终端都可以配置一个心跳检测,终端会定时发送心跳包保持连接,Mac终端也提供了该配置,编辑文件/etc/ssh/ssh_config
增加以下配置
$ sudo vi /etc/ssh/ssh_config
ServerAliveInterval 60
ServerAliveCountMax 999
- ServerAliveInterval:发送心跳包间隔,单位秒
- ServerAliveCountMax:最多发送多少次失败就断开连接
另外/etc/ssh/ssh_config
文件中有SendEnv LANG LC_*
配置,将服务器语言环境设置为和本地一样的环境,一般我们本机是中文环境,但不一定所有Linux服务器都支持中文环境,有时候可能出现乱码,因此这里建议注释掉该配置。
颜值
颜值真的就仁者见仁,mac终端提供了自定义主题的功能,在菜单终端->偏好设置
中
另外可以编辑文件/etc/motd
文件,自定义终端欢迎页
你可以也可以安装第三方shell,比如Oh My Zsh
管理功能
这个需求是硬需求,不可能每次连接都重新输入地址和账号信息,得有个方案记录用户名和密码,并且能够通过脚本得方式进行自动连接,ssh工具本身处于安全考虑不提供在命令行中指定密码功能,也就是你不能通过类似ssh {password} {user}@{host}
方式进行连接,必须手动输入密码,所以第一步就是解决自动登录问题。
自动登录
sshpass就是解决ssh手动输入密码的问题,你可以通过brew安装sshpass
brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Formula/sshpass.rb
如果没有安装brew,你可以下载源码自行编译安装
安装sshpass后,可以通过以下命令登录服务器
# 登录ssh
sshpass -p "password" ssh user@host
# 登录sftp
sshpass -p "password" sftp user@host
管理
解决了自动登录问题,那么就必须有地方管理连接,其实就是把其他终端工具的界面操作搬到控制台实现,我们假设有一个工具叫PowerTerminal
简称pw,pw提供以下功能
# 创建新连接
pw create $连接名称 $ip $用户名 $密码
# 列出所有连接
pw
# 根据关键字搜索连接
pw $关键字
# 在显示所有连接后可以根据编号选择连接某个连接
# sftp
pw sftp
界面效果
创建连接
$ pw create
➜ 分组 : huaweiyun
➜ ip : 192.168.10.100
➜ 名称 : oam
➜ 登录名: oam
➜ 密码 : oam
添加主机 192.168.10.100 成功
服务器列表
$ pw
服务器列表
1. aliyun ➡ 192.168.1.100(hr)
2. aliyun ➡ 192.168.1.101(bpm)
3. huaweiyun ➡ 192.168.10.100(oam)
4. huaweiyun ➡ 192.168.10.101(soa)
➜ 输入编号 :
关键字搜索
$ pw huawei
服务器列表
1. huaweiyun ➡ 192.168.10.100(oam)
2. huaweiyun ➡ 192.168.10.101(soa)
➜ 输入编号 :
输入前面的数字编号后便可自动连接,我希望是打开新的tab页而不是在当前页面打开,只要在脚本执行以下命令便可在终端打开新的tab页并且在新tab页执行命令
osascript -e 'tell application "Terminal" to activate' -e 'tell application "System Events" to tell process "Terminal" to keystroke "t" using command down' -e 'tell application "Terminal" to do script "'"$v_script"'" in selected tab of the front window'
$v_script
就是要执行的命令,这里借助了Mac自带的脚本功能,因此无法跨平台,如果是在当前tab页打开连接就可以直接执行sshpass命令。这里也要打开脚本辅助功能权限,在系统偏好设置中找到安全与隐私,在辅助功能中将脚本编辑器和终端加进去
完整脚本pw.sh
#!/bin/bash
v_pw_home=~/.pw
v_pw_data=$v_pw_data/data
function help(){
echo "usage : pw [create|sftp|{searchKey}]"
echo " create 根据命令行提示创建连接"
echo " sftp 进入sftp模式"
echo " searchKey 根据关键字进行模糊搜索链接支持按照分组名称,连接名称,ip进行搜索"
echo " help 帮助信息"
}
function init(){
if [ "$PW_HOME" != "" ]; then
v_pw_home=$PW_HOME
fi
v_pw_data=$v_pw_home/data
mkdir -p $v_pw_data
}
function login(){
v_login_host=$1
v_login_name=$2
v_login_pwd=$3
v_action=$4
printf "\e[0mlogin to ➡ %s with user %s ....\n" $v_login_host $v_login_name
if [ "$v_login_pwd" != "nil" ]; then
v_script="sshpass -p '$v_login_pwd' $v_action ${v_login_name}@${v_login_host}"
else
v_script="sshpass $v_action ${v_login_name}@${v_login_host}"
fi
osascript -e 'tell application "Terminal" to activate' -e 'tell application "System Events" to tell process "Terminal" to keystroke "t" using command down' -e 'tell application "Terminal" to do script "'"$v_script"'" in selected tab of the front window'
}
init
cmd=$1
if [ "${cmd}" = "help" ]; then
help
exit 0
fi
v_action=ssh
v_spec_number="-1"
if [ "${cmd}" == "create" ]; then
read -p "➜ 分组 : " v_group
read -p "➜ ip : " v_host
read -p "➜ 名称 : " v_name
read -p "➜ 登录名: " v_username
read -p "➜ 密码 : " v_password
if [ "$v_host" == "" ]; then
echo "ip地址不能为空"
exit 1
fi
if [ "$v_name" == "" ]; then
echo "名称不能为空"
exit 1
fi
if [ "$v_group" == "" ]; then
v_group="default"
fi
if [ "$v_password" == "" ]; then
v_password="nil"
fi
echo ${v_host},${v_username},${v_password} >$v_pw_data/${v_group}#$v_host#${v_name}.kimy
echo "添加主机 "${v_host}" 成功"
exit 0
fi
if [ "${cmd}" == "sftp" ]; then
v_action=sftp
cmd=$2
fi
if [ "${cmd}" == "delete" ]; then
v_action=delete
cmd=$2
fi
v_search_key="*.kimy"
v_machine_id=-1
if [ "$cmd" != "" ]; then
if [ -n "$cmd" ] && [ "$cmd" -eq "$cmd" ] 2>/dev/null; then
v_machine_id=$cmd
else
v_search_key="*${cmd}*.kimy"
fi
fi
if [ "$v_machine_id" == "-1" ]; then
v_sequence=1
printf "服务器列表\n"
for f in $(find $v_pw_data -name ${v_search_key}|sort)
do
v_file_name=$(basename ${f})
v_names=(${v_file_name//#/ })
v_group=''
v_host=''
v_nick=''
v_index=1
for i in ${v_names[@]}
do
if [ "$v_index" == "1" ]; then
v_group=$i
fi
if [ "$v_index" == "2" ]; then
v_host=$i
fi
if [ "$v_index" == "3" ]; then
v_nick=(${i//.kimy/})
fi
v_index=`expr $v_index + 1`
done
printf "\e[0m%-4s" $v_sequence"."
printf "\e[32m%-12s" $v_group
printf "\e[0m ➡ \e[35m%s(%s)\n\e[0m" $v_host $v_nick
v_sequence=`expr $v_sequence + 1`
done
if [ "$v_sequence" != "2" ]; then
printf "\n"
read -p "➜ 输入编号 : " v_machine_id
else
v_machine_id="1"
fi
fi
v_sequence=1
for f in $(find $v_pw_data -name $v_search_key|sort)
do
if [ "$v_machine_id" == "$v_sequence" ]; then
v_content=`cat ${f}`
v_sps=(${v_content//,/ })
v_host=''
v_name=''
v_password=''
v_index=1
for i in ${v_sps[@]}
do
if [ "$v_index" == "1" ]; then
v_host=$i
fi
if [ "$v_index" == "2" ]; then
v_name=$i
fi
if [ "$v_index" == "3" ]; then
v_password=$i
fi
v_index=`expr $v_index + 1`
done
if [ "$v_action" == "delete" ];then
printf "delete file %s\n" $f
rm -rf "$f"
else
login $v_host $v_name $v_password $v_action
fi
fi
v_sequence=`expr $v_sequence + 1`
done
脚本安装
将脚本保存到本地,比如/you/path/pwoerterminal/pw.sh
,在~/.bash_profile
加入以下内容
alias pw='/you/path/pwoerterminal/pw.sh'
alias pwf='/you/path/pwoerterminal/pw.sh sftp'
PW_HOME=/you/path/pwoerterminal/data
export PW_HOME
- pw定义pw命令方便调用,这样你就可以在任何地方执行pw进入脚本
- pwf定义sftp命令方便调用,这样你就可以输入pwf进入sftp模式
- PW_HOME:保存数据的地方
修改后执行~/.bash_profile
令其生效
效果
其他问题
- 选择复制功能目前是无法实现,貌似需要借助插件,这里就不折腾了
- 这里密码是明文保存,有一定的安全性问题
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。