前些天在同事進行技術分享時,看到他竟然只輸入了一行命令./test.sh
就成功登陸了開發機,甚是驚異,於是回來搜尋研究了一下,遂成此文。
在編寫ssh自動登陸指令碼之前,先說一下shell指令碼的基礎,此基礎不是一些語法什麼的,網上到處都是,這裡總結了一下shell指令碼的執行機制~
首先要說一下shell的幾種啟動方式,正是踩了指令碼啟動的坑,才使用原來十分鐘就搞定的指令碼,花了兩個小時才搞定。同時也使得我們執行shell,知其所以然。
通過檔名執行
shell指令碼可以直接通過檔名執行,需要注意的是檔案需要執行許可權。通過sudo chmod +x ./file_name.sh
來給檔案新增執行許可權;
指定指令碼直譯器來執行檔案
我們常用的sh file_name.sh
就是指定了指令碼直譯器/bin/sh
來解釋執行指令碼;常見的指令碼直譯器還有:/bin/bash
等,我們可以使用ls -l /bin/*sh
命令來檢視當前可用的指令碼直譯器;
使用. ./file_name或source命令執行指令碼
這種方式不會像前兩種方式一樣fork乙個子程序去執行指令碼,而是使用當前shell環境執行,用於 .bashrc或者.bash_profile被修改的時候,我們不必重啟shell或者重新登入系統,就能使當前的更改生效。
我們寫乙個shell指令碼時,總是習慣在最前面加上一行#!/binbash
,它就是指令碼的shebang
,至於為什麼叫這麼個奇怪的名字,c語言和unix的開發者丹尼斯·里奇稱它為可能是類似於"hash-bang"的英國風描述性文字
;
貼一段wiki上的解釋:
在電腦科學中,shebang是乙個由井號和嘆號構成的字串行,其出現在文字檔案的第一行的前兩個字元。 在檔案中存在shebang的情況下,類unix作業系統的程式載入器會分析shebang後的內容,將這些內容作為直譯器指令,並呼叫該指令,並將載有shebang的檔案路徑作為該直譯器的引數。簡單的說,它指示了此指令碼執行時的直譯器,所以,使用檔名直接執行shell指令碼時,必須帶上shebang; 此外,我們還可以在shebang後面直接附加選項,執行時我們預設使用選項執行;
如test.sh
的shebang
為#!/bin/sh -x
,那我們執行指令碼時:
./test.sh hello
相當於:
bin/sh -x ./test.sh hello
;
而編寫乙個ssh自動登陸指令碼,需要用到的shebang(直譯器)為/usr/bin/expect
;
需要注意的是:在指定指令碼直譯器來執行指令碼時,shebang會被指定的指令碼直譯器覆蓋,即優先使用指定的指令碼直譯器來執行指令碼(習慣性地用sh ./test.sh卻提示command not found)
expect是乙個能實現自動和互動式任務的直譯器,它也能解釋常見的shell語法命令,其特色在以下幾個命令:
spawn command
命令會fork乙個子程序去執行command命令,然後在此子程序中執行後面的命令;
在ssh自動登陸指令碼中,我們使用spawn ssh user_name@ip_str
,fork乙個子程序執行ssh登陸命令;
expect命令是expect直譯器的關鍵命令,它的一般用法為expect "string"
,即期望獲取到string字串,可在在string字串裡使用 * 等萬用字元;
string與命令列返回的資訊匹配後,expect會立刻向下執行指令碼;
set timeout n
命令將expect命令的等待超時時間設定為n秒,在n秒內還沒有獲取到其期待的命令,expect 為false,指令碼會繼續向下執行;
send命令的一般用法為send "string"
,它們會我們平常輸入命令一樣向命令列輸入一條資訊,當然不要忘了在string
後面新增上\r
表示輸入回車;
interact命令很簡單,執行到此命令時,指令碼fork的子程序會將操作權交給使用者,允許使用者與當前shell進行互動;
以下是乙個完成版的指令碼test.sh
:
#!/usr/bin/expect // 指定shebang set timeout 3 // 設定超時時間為3秒 spawn ssh user_name@172.***.***.*** // fork乙個子程序執行ssh命令 expect "*password*" // 期待匹配到 'user_name@ip_string's password:' send "my_password\r" // 向命令列輸入密碼並回車 send "sudo -s\r" send "cd /data/logs\r" // 幫我切換到常用的工作目錄 interact // 允許使用者與命令列互動
執行sudo chmod +x ./test.sh
命令給shell指令碼新增執行許可權;
執行./test.sh
命令,一鍵登陸成功!
簡單的幾個命令,,搭配起來解決了與命令列的互動問題後,很多複雜的功能也不在話下了~
指令碼完成了,可是還是有些小瑕疵:
這裡我們想到了linux的alias命令:
alias命令使用方式為alias alias_name="ori_command"
,將alias_name設定為ori_command的別名,這樣我們輸入執行alias_name,就相當於執行了ori_command;
可是,我們會發現,當你關閉當前shell後,再開啟乙個shell視窗,再使用alias_name,系統提示command not found
;
有沒有能保持命令的方式呢?編輯bash_profile檔案。
我們編輯bash_profile檔案,此檔案會在終端視窗建立的時候首先執行一次,所以可以幫我們再設定一次別名;
執行命令vim ~./bash_profile
,在檔案內部新增:
alias alias_name="/root_dir/../file_name.sh
儲存後,再使用. ~./bash_profile
或source ~./bash_profile
在當前指令碼執行一遍設定別名命令,完成設定;
這樣,我們無論在哪個目錄,只要輸入alias_name
命令,回車,真正的一鍵登陸!
作為乙個程式猿,時刻保持著偷懶
意識(當然此偷懶非彼偷懶。。。),在類unix系統中,不要浪費了shell
這種神奇的工具,讓計算機為我們服務~
乙個多月沒寫部落格了,最近在看apue,unp一套的書,c和unix上入門尚淺,不敢亂寫誤人子弟;平常自己用記事本做的筆記也比較散亂,不成系統;
**:
shell實現SSH自動登陸
公司開發使用docker,每次登陸自己開發機總要輸入ssh user name ip string,然後再確認輸入password,手快了還經常會輸錯。作為乙個懶人,肯定要找乙個取巧的方式,檢視了下ssh命令,由於它要進行一次跟伺服器的加密互動,所以沒有直接附帶密碼登陸的選項,只好作罷。前些天在同事...
shell實現SSH自動登陸
公司開發使用docker,每次登陸自己開發機總要輸入ssh user name ip string,然後再確認輸入password,手快了還經常會輸錯。作為乙個懶人,肯定要找乙個取巧的方式,檢視了下ssh命令,由於它要進行一次跟伺服器的加密互動,所以沒有直接附帶密碼登陸的選項,只好作罷。前些天在同事...
shell實現SSH自動登陸
前些天在同事進行技術分享時,看到他竟然只輸入了一行命令.test.sh就成功登陸了開發機,甚是驚異,於是回來搜尋研究了一下,遂成此文。在編寫ssh自動登陸指令碼之前,先說一下shell指令碼的基礎,此基礎不是一些語法什麼的,網上到處都是,這裡總結了一下shell指令碼的執行機制 首先要說一下shel...