原文地址:https://rtyan.github.io/%E5%B7%A5%E5%85%B7/2017/09/12/ssh-keys-manager.htmlhtml
我有兩個github帳戶,一個是平時正常使用的,另一個是用來專門作博客用的,
由於以前經常使用的那個作博客名字很差看o(╯□╰)o。git
這就引起了一個問題,我想在博客帳戶中添加ssh keys
的時候,github會提示
我下面的信息github
原來,同一個公鑰只能在github系統中添加一次,重複添加的話會報這個錯誤,就算
是不一樣的帳戶也不能將同一個公鑰添加屢次。shell
這個問題要怎麼解決呢?bash
最簡單的方法,也就是直接生成一套新的公鑰密鑰對,而後添加到個人博客帳戶中,
等下次再用經常使用的帳號時候再從新生成一套,再替換經常使用帳號中的ssh keys
就能夠
了,事實上我第一次就是這麼幹的,沒徹底弄清楚怎麼回事,只能按照流程從新生成
一遍了,並且確實生效了。ssh
但用了幾回以後我發現不用從新生成、只要在本地生成兩份ssh keys
,而後每次講要
使用的ssh keys
命名爲id_rsa
、id_rsa.pub
就能夠了,不用每次替換帳號中的配置了。工具
但用了一段時間,發現仍是很麻煩,是在太難受了,因而就想着寫一個半
自動化的建立、切換ssh keys
的工具。優化
沿着上面的思路,我能夠生成多套ssh keys
,而後將他們管理起來,每次使用的時候
只須要將他們替換到id_rsa
、id_rsa.pub
就能夠了,省略了人工去切換。就像下面
這樣:this
➜ rtyan.github.io git:(master) git push origin master Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. ➜ rtyan.github.io git:(master) sshkeys change rtyan 切換ssh keys對,從[aizuyan]到[rtyan]... 複製/Users/ritoyan/.ssh-keys-pair/rtyan到/Users/ritoyan/.ssh/id_rsa成功 複製/Users/ritoyan/.ssh-keys-pair/rtyan.pub到/Users/ritoyan/.ssh/id_rsa.pub成功 切換到rtyan成功 ➜ rtyan.github.io git:(master) git push origin master Counting objects: 8, done. Delta compression using up to 4 threads. Compressing objects: 100% (8/8), done. Writing objects: 100% (8/8), 77.54 KiB | 0 bytes/s, done. Total 8 (delta 5), reused 0 (delta 0) remote: Resolving deltas: 100% (5/5), completed with 5 local objects. To github.com:rtyan/rtyan.github.io.git a05e55f..50b54a7 master -> master
目前已經開發完成,用shell完成的,最後面會將代碼貼出來。code
工具生成的全部ssh keys pairs
都保存在~/.ssh-keys-pair/
目錄下,就下下面
這樣:
-rw------- 1 ritoyan staff 3243 9 12 21:15 backup -rw-r--r-- 1 ritoyan staff 741 9 12 21:15 backup.pub -rw-r--r-- 1 ritoyan staff 6 9 12 21:16 nowRecord -rw------- 1 ritoyan staff 3243 9 12 21:15 rtyan -rw-r--r-- 1 ritoyan staff 741 9 12 21:15 rtyan.pub
其中backup
、backup.pub
記錄了軟件安裝以前的ssh keys
信息(若是有的話)。
nowRecord
記錄了當前使用的是哪一個ssh keys
,裏面的內容等同於~/.ssh-keys-pair/
目錄下的密鑰名稱。
其餘文件的話就是公鑰密鑰對了,密鑰是 <生成時候的名稱> ,公鑰是 <生成時候的名稱> .pub
列出全部ssh keys
列表的時候就是經過匹配~/.ssh-keys-pair/
文件夾下面的.pub
後綴來的,匹配上了就算是一個公鑰密鑰對。
安裝的話直接把最下面的shell代碼複製到/usr/local/bin/sshkeys
中(或其餘$PATH
目錄中),而後執行chmod +x /usr/local/bin/sshkeys
給腳本加上可執行權限,而後
就能夠看命令使用了。
這個工具一共5個命令,功能分別以下(也能夠直接看代碼):
sshkeys init
初始化環境,備份原來的ssh keys
到backup
,設置當前使用的ssh keys
名稱爲backup
sshkeys list
列出當前全部的ssh keys
名稱,當前使用的前面有星號:
➜ GIT sshkeys list aizuyan backup * rtyan
sshkeys create <name> [<email>]
上面的命令是建立一個名稱爲<name>
的ssh keys
,後面的<email>
是可選項:
➜ GIT sshkeys create aizuyan ritoyan@163.com 開始建立密鑰公鑰對... 執行命令[ssh-keygen -t rsa -b 4096 -f /Users/ritoyan/.ssh-keys-pair/aizuyan -q -N "" -C "ritoyan@163.com"] 建立成功
sshkeys showpub [<name>]
上面的命令是展現公鑰,後面的<name>
是可選的,默認展現當前正在使用的,加了參數顯示
對應<name>
的公鑰:
➜ GIT sshkeys showpub aizuyan ssh-rsa AA.........Vw== ritoyan@163.com
sshkeys change <name>
切換到對應<name>
的ssh keys
➜ GIT sshkeys change aizuyan 切換ssh keys對,從[rtyan]到[aizuyan]... 複製/Users/ritoyan/.ssh-keys-pair/aizuyan到/Users/ritoyan/.ssh/id_rsa成功 複製/Users/ritoyan/.ssh-keys-pair/aizuyan.pub到/Users/ritoyan/.ssh/id_rsa.pub成功 切換到aizuyan成功
代碼又長又臭,能夠忽略過了,想看的看下。
還有不少地方要優化,不過如今我用是夠了,哈哈。
#/bin/bash # 存放數據的根目錄 softBase="${HOME}/.ssh-keys-pair/" sshBase="${HOME}/.ssh/" sshIdRsaPath="${sshBase}id_rsa" sshIdRsaPubPath="${sshBase}id_rsa.pub" nowSshPairRecordPath="${softBase}nowRecord" action=$1 function init() { # 判斷根目錄是否存在,不存在建立 if [ -d $softBase ];then return 1 fi echo "初始化..." #[1] 建立目錄 echo "[1]建立必要的目錄..." mkdir -p -m 700 $softBase if [ $? != 0 ];then echo "[1-1]建立目錄${softBase}失敗" else echo "[1-1]建立目錄${softBase}成功" fi #[2] 備份如今的sshkey echo "[2]備份當前的ssh key pair" if [ -f "${sshIdRsaPath}" ];then cp $sshIdRsaPath "${softBase}backup" if [ $? != 0 ];then echo "[2-1]備份${sshIdRsaPath}到${softBase}backup" else echo "[2-1]備份${sshIdRsaPath}到${softBase}backup" fi else echo "${sshIdRsaPath}文件不存在,不須要備份" fi if [ -f "${sshIdRsaPubPath}" ];then cp $sshIdRsaPubPath "${softBase}backup.pub" if [ $? != 0 ];then echo "[2-2]備份${sshIdRsaPubPath}到${softBase}backup.pub失敗" else echo "[2-2]備份${sshIdRsaPubPath}到${softBase}backup.pub成功" fi else echo "${sshIdRsaPubPath}文件不存在,不須要備份" fi #[3] 設置當前sshkeys echo "[3]設置當前sshkeys記錄" if [ -f "${sshIdRsaPubPath}" ];then echo "backup" > $nowSshPairRecordPath if [ $? != 0 ];then echo "[3-1]設置當前sshkeys記錄爲[backup],寫入${nowSshPairRecordPath}失敗" else echo "[3-1]設置當前sshkeys記錄爲[backup],寫入${nowSshPairRecordPath}成功" fi fi echo "初始化成功\n" return 0 } function nowRecord() { local nowRecord=`cat ${nowSshPairRecordPath}` echo $nowRecord return 0 } # 列出全部的公鑰名稱 function list() { local files=`ls $softBase | grep "\.pub\$"` local file local nowRecord=`nowRecord` for file in ${files} do sshKeysName=${file%%.pub} if [[ $nowRecord == $sshKeysName ]]; then echo "* "$sshKeysName else echo " "$sshKeysName fi done } # 建立一對新的密鑰 # $1 密鑰名稱 必選 # $2 郵件 可選 function create() { keyPairName=$1 maybeEmail=$2 createPath="${softBase}${keyPairName}" cmd="ssh-keygen -t rsa -b 4096 -f ${createPath} -q -N \"\"" if [[ $maybeEmail ]]; then cmd="${cmd} -C \"${maybeEmail}\"" fi echo "開始建立密鑰公鑰對..." echo "執行命令[${cmd}]" eval $cmd if [ $? != 0 ];then echo "建立失敗" else echo "建立成功" fi } # 切換ssh keys function change() { local keyPairName=$1 local rsaPath="${softBase}${keyPairName}" local rsaPubPath="${rsaPath}.pub" local preSshPairRecord=`nowRecord` echo "切換ssh keys對,從[${preSshPairRecord}]到[${keyPairName}]..." cp $rsaPath $sshIdRsaPath if [ $? != 0 ];then echo "複製${rsaPath}到${sshIdRsaPath}失敗" else echo "複製${rsaPath}到${sshIdRsaPath}成功" fi cp $rsaPubPath $sshIdRsaPubPath if [ $? != 0 ];then echo "複製${rsaPubPath}到${sshIdRsaPubPath}失敗" else echo "複製${rsaPubPath}到${sshIdRsaPubPath}成功" fi echo "${keyPairName}" > $nowSshPairRecordPath if [ $? != 0 ];then echo "切換到${keyPairName}失敗" else echo "切換到${keyPairName}成功" fi } function showpub() { local keyPairName=$1 if [ -z "${keyPairName}" ]; then keyPairName=`nowRecord` fi local keyPubPath="${softBase}${keyPairName}.pub" cat $keyPubPath } case "${action}" in "init" ) init ;; "list" ) list ;; "create" ) keyPairName=$2 maybeEmail=$3 create "${keyPairName}" "${maybeEmail}" ;; "change" ) keyPairName=$2 change "${keyPairName}" ;; "showpub" ) keyPairName=$2 showpub "${keyPairName}" ;; * ) echo "this is action none" ;; esac