:::

Windows一鍵執行SSH指令:AutoIT、Pietty搭配使用

image

Linux的命令列畫面讓很多人惟恐避之不及,這對有許多指令需要依賴SSH連線、並在命令列輸入才能執行的DSpace來說,無疑是一大門檻。在此我提出一種可以做到「一鍵指令」的方案:利用AutoIt自動執行機器人,透過PieTTY的命令列模式,用ini設定檔來設定連線參數,來執行捷徑所指定的指令的作法。

這種作法對資安來說非常不理想,僅是一個簡便利用的應急方案而已。


一鍵指令的背景與目的

我現在要做的事情是:

  1. 在Windows的環境下
  2. 透過SSH連線到Linux伺服器
  3. 進行登入動作(以及金鑰確認)
  4. 然後執行一個指令。

而這個方案的目的是將使用者的操作簡化到極限,我希望使用者能夠以滑鼠執行一個檔案,就自動做完上述的所有動作。

一鍵指令方案概述

簡單來說,這個方案的作法是:

  1. 利用PieTTY的命令列模式來輸入登入資訊與要執行的指令
  2. 以ini檔案儲存登入資訊
  3. 在Linux伺服器端配置參數與接收命令的sh腳本
  4. 利用AutoIt來處理連線的細節
  5. 利用Windows的捷徑與捷徑後輸入的參數,將參數輸入給AutoIt

Linux環境配置

要做到這些事情,需要Linux伺服器端與Windows使用者端的環境一起配置才行。這邊先敘述Linux的部份,大致上是要做以下三件事情:

  • 建立帳號、密碼
  • 開啟ssh連線
  • 建立ssh-cmd.sh腳本

Linux伺服器建立帳號、密碼、開啟ssh連線等基本操作請參考鳥哥的Linux思房菜。在此最重要的是要配置接收來自客戶端指令的執行腳本「ssh-cmd.sh」。

在本篇的例子中,我以普通使用者「dspace」跟管理者「root」作為帳號、「password」作為該帳號的密碼來說明。

ssh-cmd.sh:執行指令腳本

因為帳號是使用「dspace」,所以我在「/home/dspace/ssh-cmd.sh」(SkyDrive備份)這個位置建立起腳本。腳本的內容如下:

#!/bin/bash
# Program:
#       Excute command and pause at finish.
## History:
## 2009/11/12    Pudding   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export JAVA_HOME=/usr/java/jdk1.6.0_06
export PATH
export LC_ALL=en_US
export JAVA_OPTS="-Xmx128M -Xms64M -Dfile.encoding=UTF-8"

ANT_HOME=/opt/apache-ant-1.7.0
JAVA_HOME=/usr/java/jdk1.6.0_06
CATALINA_HOME=/opt/apache-tomcat-6.0.16
PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$ANT_HOME/bin:$PATH:/opt/apache-maven-2.0.9/bin
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC JAVA_HOME ANT_HOME CATALINA_HOME


if [ "$1" == "/home/dspace/tomcat_restart.sh" ]; then
        at now + 0 minutes < $1
        echo "Tomcat will restart now."
else
        $1
fi

echo ""
echo "====================================="
echo ""
read -p "Please press ENTER to exit. " doExit

這個腳本中設置了相當多參數,請依照你伺服器的實際情況來決定要設置的參數內容。

此外,由於Tomcat的重新啟動無法直接透過這樣的指令來執行,所以我改成以「at」執行一次的方式來執行。必須說明的是,這並不是很理想的作法,有待以後改善。

tomcat_restart.sh:重新啟動Tomcat伺服器腳本

如果你沒有需要重新啟動Tomcat的話,這個步驟是可以省略的。「/home/dspace/tomcat_restart.sh」(SkyDrive備份)是用來重新啟動Tomcat伺服器的腳本,內容如下:

export JAVA_HOME=/usr/java/jdk1.6.0_06
export JAVA_OPTS="-Xmx128M -Xms64M -Dfile.encoding=UTF-8"

/opt/apache-tomcat-6.0.16/bin/shutdown.sh 
sleep 1
/opt/apache-tomcat-6.0.16/bin/startup.sh 

要記得將這些腳本的執行權限開啟,他們才能正常地執行。

Windows使用者端配置

你現在需要在Windows中建立一個資料夾,例如「c:\ssh-cmd\」,然後把以下的檔案放進去:

PieTTY的命令列執行方式

雖然很多人都知道PieTTY是用來作SSH連線的,但是知道PieTTY可以透過命令列與指令檔案來進行連線並執行指令的人就不多了,其實這是基於PieTTY改編自PuTTY原始就有的功能喔。

具體來說,利用命令列來透過PieTTY連線的作法如下:

pietty0327.exe -l [ID] -P [PORT] -pw [PASSWORD] -m [COMMAND] -t [HOST]

裡面的參數中:

  • [ID]是要登入的帳號
  • [PORT]是連接埠
  • [PASSWORD]是密碼
  • [COMMAND]是「存放指令的檔案位置」,注意,不是指令,只是檔案位置喔
  • [HOST]要連線的主機IP
config.ini:連線配置

連線的配置資訊,我將它存放在「config.ini」中。「config.ini」的內容如下:

[ssh-dspace]
login=dspace
pw=password

[ssh-root]
login=root
pw=password

[ssh]
port=22
host=127.0.0.1

在此安排了兩種不同的身分,一種是以普通使用者「dspace」來執行,另一種是以管理者「root」來執行。除了重新啟動伺服器等重大指令之外,一般指令最好是以普通使用者「dspace」的身分來執行會比較安全。

ssh-cmd.exe:執行連線腳本

由於要執行指令必須要以存放在檔案中的形式來執行,所以建立這個檔案、並指引PieTTY來連線的工作,是交給AutoIt的自動腳本ssh-cmd.exe來執行。

ssh-cmd.exe是由ssh-cmd.au3編譯而來的,這是AutoIt的程式語言。內容如下:

Dim $user = "ssh-dspace"
Dim $script = ""
If $CmdLine[0] == 2 Then
	$user = "ssh-" & $CmdLine[1]
	$script = $CmdLine[2]
ElseIf $CmdLine[0] == 1 Then
	$script = $CmdLine[1]
EndIf

Dim $login = IniRead("config.ini",$user, "login", "root")
Dim $pw = IniRead("config.ini",$user, "pw", "password")
Dim $port = IniRead("config.ini","ssh", "port", "22")
Dim $host = IniRead("config.ini","ssh", "host", "127.0.0.1")

If $script == "" Then
	MsgBox(0, "錯誤", "請指定要執行的指令")
	Exit
EndIf

Dim $doExcute = MsgBox(1, "提示","您確定要在伺服器中執行以下命令嗎: " & $script)
If $doExcute == 2 Then
    Exit
EndIf

Dim $sh = "cmd.sh"
Dim $scriptHeader = "~/ssh-cmd.sh "

$file = FileOpen($sh, 2)

; Check if file opened for writing OK
If $file = -1 Then
    MsgBox(0, "錯誤", "無法開啟檔案")
    Exit
EndIf

FileWrite($file, $scriptHeader & $script)
FileClose($file)

Dim $cmd = "pietty0327.exe -l " & $login & " -P " & $port & " -pw " & $pw & " -m " & $sh & " -t " & $host
Run($cmd)
Sleep(1000)
If WinActivate("PieTTY Security Alert") Then
	WinActive("PieTTY Security Alert")
	Send("{ALTDOWN}Y{ALTUP}")
EndIf

這個腳本做了幾件事情:

  1. 接收來自外部的「身分」與「指令」參數(稍後建立Windows捷徑的時候,我會再說明怎麼輸入這邊的參數)
  2. 讀取來自config.ini中的連線資訊,包括「帳號」、「密碼」、「伺服器位置」、「連接埠」
  3. 過濾指令、顯示提示
  4. 將指令寫入「cmd.sh」檔案中
  5. 以命令列執行PieTTY連線
建立Windows捷徑

image

接著要建立到「ssh-cmd.exe」的捷徑,並且在捷徑之後加上「參數」。建立好ssh-cmd.exe並改好名字之後,你可以打開捷徑的「內容」,在「目標」的欄位中設定參數。

舉例來說,我現在要在伺服器上以「dspace」身分執行「/home/dspace/tomcat_restart.sh」的指令,那麼目標裡面的設定如下:

"C:\ssh-cmd\ssh-cmd.exe" dspace /home/dspace/tomcat_restart.sh

目標的值除了指定要執行的程式位置之外,還指定了要執行的身分「dspace」跟要執行的指令「/home/dspace/tomcat_restart.sh」。如此配置之後,就能夠讓使用者直接點選此捷徑,讓他自動執行這些動作了。

你可以利用這個例子舉一反三,建立執行不同身分、不同指令的捷徑,並組成一個操作列表,讓使用者易於選擇。也可以將此捷徑放到「開始」程式集裡面,讓使用者更容易執行各種操作。這些動作我是用InnoSetup在安裝時自動配置而成,不過那又是另一番長篇大論了。


結語

儘管一鍵指令的方案我研究了很久,但是仍有很多不完美之處,希望高手能多多指教。

其實這個是DSpace-DLLL寫書的一部分技術內容。之前寫完書之後就匆忙地投入其他事情中,到最近在使用AutoIt時,又把之前寫的檔案挖出來看。

這時候就會覺得這個Blog對我來說也是很重要的,如果沒有這些記錄,我恐怕很快就會忘記自己之前做過的事情了吧。

總共11 則留言 ( 我要發問 , 隱藏留言 顯示留言 )

  1. 網誌管理員已經移除這則留言。

    回覆刪除
  2. 您好!

    感謝你分享這麼好的資訊。

    不過小弟今天使用的時候發現了一些問題,我想使用MFC想要達到用這方法登入Linux 然後呼叫一個.sh去實行一個程式,不過我卡在[COMMAND]這邊,試了好多方法都會掛掉,沒有帶[COMMAND]參數就OK,可見我對cmd line file的認知不太對。我是直接在程式下面建立一個.sh檔,然後裡面就是一行呼叫Linux root下的一個程式,看您程式是有header+script去combine,不知這樣出來的檔案會是怎樣?

    不知這樣您了解我的問題否,還望指點迷津 感恩 :)

    回覆刪除
  3. 您好,

    請問您的[COMMAND]部分寫了些什麼?
    路徑位置跟檔案位置有正確嗎?請盡量用完整路徑,不要用相對路徑

    你看起來是想用MFC取代我原本用的AutoIT,應該是可行的
    不過語法上你再確認一下比較好

    回覆刪除
  4. 剛剛跟of.hsiao信件討論,他說他的Windows上cmd.sh內容只有

    ~/ssh-cmd.sh
    /root/test.sh

    應該是不會有斷行才是吧?
    cmd.sh的產生你是用AutoIT來做的嗎?還是用MFC來做的?

    回覆刪除
  5. 您好

    之前[COMMAND]有點錯誤,我現在更正了

    可以執行到Linux上的ssh-cmd.sh

    不過我只是想單純的執行上面的某個程式

    但是假設我在ssh-cmd.sh打上 /root/test 呼叫程式,Pietty就整個都掛了...

    回覆刪除
  6. 嗯……太複雜的執行方法我也不確定要如何處理。
    總之這是一個在bash shell中執行的腳本就是了。

    有找到解法的話,歡迎分享一下,感謝感謝

    回覆刪除
  7. 謝謝回答

    其實我的目的只是想在MFC程式上,連接登入Linux,然後執行某個程式而已。

    應該是比大大的還簡單,只是shell bash這東西我不太了解... Orz

    回覆刪除
  8. 不好意思請問版主大大 cmd.sh這個檔案裡面寫的是要寫連線後的操作指令?還是一個空白檔?還是有甚麼其他用途的嗎?

    回覆刪除
    回覆
    1. To 樓上,

      將指令寫入「cmd.sh」檔案中
      cmd.sh是一個暫存用的指令檔,它就是被建立用來保存要執行的指令,然後再來執行這個cmd.sh

      刪除
    2. 我知道了,我會再試試看,謝謝版主大大

      刪除