對話 UNIX,第 3 部分: 在命令行中完成所有的工作
研究提供 Internet 訪問的三種基本的 Unix® 命令行實用工具。
UNIX® 命令行是一種WYTIWYG(即所輸即所得)的接口。UNIX 提供了大量的命令,使用這些命令,您可以對內核和用戶空間中各種可用的資源進行操作。您需要對 CPU 的使用情況進行監視嗎?可以嘗試使用 top 或 ps。您需要刪除所有以 .bak 結尾的文件嗎?可以嘗試使用 rm *.bak。您需要獲得關于一個新的命令的幫助嗎?可以運行 man。
但是,當您所需要的資源位于廣域網 (WAN) 和全球 Internet 中的遠程系統時,那又應該如何處理呢?這里引用 The Hitchhiker's Guide to the Galaxy 中的一句話,“您不必驚慌失措。通過 UNIX 命令行可以很容易地下載和上傳文件、連接到遠程計算機并詢問遙遠的服務器和網絡的狀態。請做好準備:讓我們開始一次“太陽系外的奇妙旅行。
在本地進行工作,將信息傳輸到全球
在本系列的第 1 部分和第 2 部分中,您了解了使用 UNIX 命令行可以完成各種各樣的工作。只需要輸入相應的內容,包括管道 (|) 或重定向,您就可以創建即興的數據處理器,從而實現比將其中的這些部分簡單地加在一起更強大的功能。
盡管日常使用的某些資源很可能位于本地,即位于您的工作站中,但是相當數量的、并且越來越多的資產(如文件、電子郵件消息和工具)可能存儲在遠程系統中,即位于連接到您的 WAN 或者 Internet 的計算機中。Web 瀏覽器提供了對這些資源的通用訪問方式,但是有一點需要注意:指向-點擊很快會變得令人厭倦,甚至很麻煩,特別是當您必須對大量的條目進行檢索時。而且,如果您希望使用腳本 來完成重復性的或容易出錯的任務時(從本質上說,是進行捕獲和重放),窗口瀏覽器并不是一種好的工具。
與 ls、cp、mail、uptime、du manage 和 query local resources 一樣,Unix 還提供了一套用于訪問遠程資源的命令行工具。本文將向您介紹其中的一些工具,包括一個有用的技巧,它可以簡化對遠程系統的訪問并保護您的身份驗證憑據。具體來說,您將了解 wget、curl 和安全 Shell (ssh)。wget 和 curl 工具可以用來傳輸文件,而使用 ssh,您可以安全地登錄到遠程系統中,快速地和輕松地傳輸文件。
Telnet(和其他工具)存在的問題
如果您的系統中運行了 rsh(或者其變種——rcp、rexec、rlogin 或 Irdist)或 telnet,那么請立即禁用并刪除這些命令以及相關的守護進程。另外,如果您不允許使用匿名文件傳輸協議 (FTP),請同時禁用 FTP 軟件。
盡管 rsh 和 telnet 在 UNIX 中使用了很長的時間,但是攻擊者可以輕松地利用這兩種實用工具的其中之一來危害您的系統。當發現該軟件正在運行時,您或您的系統管理員應該停止并刪除它,并使用 ssh 來代替這些包。
對于特權 FTP 訪問,可以使用 sftp。將 rdist 替換為更高級的 rsync?;蛘撸绻仨毺峁┠涿?FTP(或通過 HTTP 進行下載),請確保使用防火墻硬件和軟件將所有可以公開訪問的計算機與敏感的內部服務器隔離。
但是首先,讓我們來討論一下密碼所帶來的討厭的問題。
“您不需要討厭的密碼!
通常,對大多數計算機和服務的訪問都受到保護。在有些情況下,進行身份驗證(從而獲得訪問該系統的權限)可能需要復雜的質詢-響應交換、安全套接字層 (SSL) 證書、甚至生物測定掃描。然而在一般情況下,通過密碼就可以獲得訪問權限。與您的個人識別號碼 (PIN) 相同,您的密碼也是保密的,如果您選擇了合適的密碼,那么其他的人將很難猜到它。將您的用戶名和強密碼組合在一起,這樣可以提供足夠的安全性加強。
當然,強密碼可能難以記住,并且當您需要收集和記住另一個 8 字符的密鑰(數字、標點符號及其組合)時,情況變得更復雜。反復地輸入同一個密碼會讓人感到討厭,更糟糕的是,它極大地阻礙了自動化的實現。
正因為認識到這些阻礙的存在,所以許多命令行實用工具都允許您將用戶名和密碼作為命令行參數。例如,您可以使用下面的命令登錄到一個 FTP 站點,而無需進行人工干預:
ftp ftp://joe:[email protected]
然而,使用這種方法可能會將您的憑據泄漏給共享該計算機的其他用戶。(可以嘗試使用 ps -Aeww,例如,查看完整的命令行和系統中每個進程的環境。)
為了提供與命令行相同的簡潔性,而又不會帶來危險,許多程序可以從一個名為 .netrc(讀做 net-r-c)的文件中讀取您的憑據,該文件通常位于 ~/.netrc 目錄中。您的 .netrc 文件必須僅具有所有者讀寫模式(即模式 0600 或者 -rw-------),并且該文件中的每個條目都必須遵守下面這種簡單的語法格式:
Machine ftp.example.com login zaphod passWord I()Trillian!machine www.magazine.com login abner password MmG8y*trdefault login anonymous password [email protected]
前面兩行提供了 machine 關鍵字和該計算機的域名、login 關鍵字和您在該計算機上的登錄名、password 關鍵字以及緊跟其后的登錄密碼。最后一行中的憑據為任何沒有專門指定的系統提供了缺省值。default 行必須是您的 .netrc 文件中的最后一行。(有關 .netrc 文件完整的配置選項,可以輸入 man 5 netrc 以查看 .netrc 的 man 頁面。)
顯然,如果文件中包含任何標識數據,那么請確保它僅具有用戶讀寫模式(模式 600)或用戶只讀模式(模式 400),以防止意外地覆蓋或刪除該文件。您可能還希望使用模式 700 來保護您的 home 目錄。
現在,每當您啟動一個支持 .netrc 的應用程序(包括接下來將要討論的那些應用程序)時,會自動地將登錄名和密碼傳遞給所需的服務,而無需通過鍵盤進行輸入。通常,您可以使用 -n 選項禁用這種自動登錄 特性。
傳遞的過程
除了用于瀏覽 Web 頁面的 HTTP 和基于 SSL 的 HTTP (HTTPS) 外,FTP 是最常用的 Internet 應用程序協議之一。通過 FTP,客戶端可以連接到服務器、獲取目錄和文件的列表、下載文件(即,從服務器請求一個文件)或上傳文件(即,向服務器發送一個文件,以進行持久保存)。ftp://ftp.example.com/path/to/anotherfile.zip 和 ftp://user:[email protected]/path/to/file.zip URL 格式表示,使用 FTP 協議連接到 ftp.example.com 并下載 /path/to/anotherfile.zip 文件。后面的這個 URL 簡單地為登錄添加了相應的憑據。
在大多數桌面計算機中,這兩種 URL 將啟動瀏覽器或缺省的 FTP 應用程序來下載指定的文件。然而,在 wget 命令行實用工具中也可以使用相同的 URL,它是一種用于通過 HTTP、HTTPS 和 FTP 進行文件下載的健壯的實用工具。它支持 .netrc 文件,并且無需進行交互,對于實現自動化來說,使用它非常合適。如果您的系統中沒有 wget,您可以從 GNU Software Foundation 下載其源代碼。它包含幾個簡單的命令,適用于所有的 Unix 變種,您可以將這個實用工具放到您個人的 bin 目錄或者某個中央目錄。
假設已經有了 .netrc 文件,讓我們來研究一些示例,看看 wget 究竟可以完成哪些工作。(在下面的示例中,提供了相應的行號以供參考,您不需要輸入這些數值。)清單 1 顯示了如何在命令行中輕松地使用 wget 來下載文件。
清單 1. 在命令行中使用 wget 下載文件
1 $ wget http://ftp.gnu.org/pub/gnu/wget/wget-1.10.2.tar.gz--16:02:29-- http://ftp.gnu.org/pub/gnu/wget/wget-1.10.2.tar.gz => `wget-1.10.2.tar.gz'Resolving ftp.gnu.org... 199.232.41.7Connecting to ftp.gnu.org[199.232.41.7]:80... connected.HTTP request sent, awaiting response... 200 OKLength: 1,213,056 [application/x-tar]100%[=====================>] 1,213,056531.22K/s16:02:37 (529.57 KB/s) - `wget-1.10.2.tar.gz' saved [1213056/1213056]2 $ wget -q ftp://mirror.Linux.duke.edu/pub/centos/4.3/os /i386/RELEASE-NOTES-en.HTML3 $ cat url_list.txthttp://www.wikipedia.comhttp://valdez.barebones.com/pub/freeware/TextWrangler_2.1.3.dmg4 $ wget -i -nv url_list.txt16:06:00 URL:http://www.wikipedia.org/ [33606] -> "index.html" [1]16:06:41 URL:http://valdez.barebones.com/pub/freeware/ TextWrangler_2.1.3.dmg [9488296/9488296] -> "TextWrangler_2.1.3.dmg" [1]FINISHED --16:06:41--Downloaded: 9,521,902 bytes in 2 files5 $ lsRELEASE-NOTES-en.html index.html wget-1.10.2.tar.gzTextWrangler_2.1.3.dmg url_list.txt
命令 1 通過 HTTP 從該項目的主頁下載最新的 wget 源代碼。在缺省情況下,wget 將向您報告下載的過程。您可以使用 -q(表示 quIEt 模式)選項來禁止所有的消息。命令 2 通過 FTP 獲取 CentOS 的發布說明,同樣也使用了 quiet 模式。
保持 URL 不變
提示:許多 HTTP URL 中包含一些在 Shell 中有特殊含義的字符。例如,許多 URL 中包含問號 (?),它用來將主機名和路徑從參數列表中分隔出來。然而,Shell 卻把問號解釋為通配符。
要阻止 Shell 對其進行解釋,只需要將 URL 放在單引號中即可。要避免奇怪的和長文件名,可以使用 wget -o 對輸出文件進行命名。這里有一個示例:
$ wget -o sharkey'http://www.example.com/download.cgi?proj=scIEnce&file=sharkey'
如果有很長的 URL 列表需要進行下載,您不需要分別將每個 URL 放到命令行中。相反,您可以創建(或生成)需要進行下載的 URL 列表。命令 3 顯示了 url_list.txt 文件,簡單的文本目錄中包含了兩個 URL;命令 4 則對這兩個 URL 進行下載。在提供下載列表時,可以使用 -i 選項。-nv 選項(not verbose 的首字母縮寫)則提供更簡潔的消息。
除非您為下載的文件提供了相應的文件名(使用 -o 選項),否則 wget 將創建一個與遠程文件名稱相同的新的本地文件,而省略前面的 URL 部分。命令 5 顯示了在命令 1 到 3 中下載的 4 個文件。
wget 實用工具有許多選項和特性。它可以訪問 FTP 或 Web 站點,并下載具有層次結構的所有文件。您還可以為自動下載設置相應的配額、提供 cookies、并繼續進行以前被中斷的下載任務。要了解關于使用該工具的技巧,請閱讀 wget 的 man 頁面。
進行上傳
對于自動的下載任務,wget 實用工具非常有價值,但是它卻不能用來上傳文件。它也不能夠與安全 FTP、telnet 和大量其他的(更早的和更少使用的)Internet 協議進行互操作。對于這些類型的傳輸工作,您必須使用“瑞士軍刀般銳利的網絡工具: curl。
curl 命令行實用工具可以獲取和上傳數據,所以它非常適合于將本地文件傳輸到遠程服務器。然而更有價值的是,curl 的基礎是 libcurl 庫,該庫提供了豐富的應用程序編程接口 (API),允許您將各種 curl 特性集成到您自己的應用程序中。C、C++、PHP 和 Perl,這是許多語言中能夠利用 libcurl 的 4 種編程語言。如果您的系統中沒有 curl 和 libcurl,您可以從 libcurl 主頁下載其源代碼。
因為 curl 可以將本地文件復制到遠程服務器,所以它非常適合用于完成少量信息的備份工作。例如,清單 2 介紹了一個 Shell 腳本,出于安全考慮,它可以用來將一個裝滿了數據庫轉儲信息的目錄復制到遠程 FTP 服務器。
清單 2. 使用 curl 以遠程的方式保存數據庫轉儲
foreach db (mydns mysql cms tv radio) /usr/bin/mysqldump --ppassWord --add-drop-table -Q --complete-insert $db > $db.sqlendfind dbs -mtime -1 -type f -name '*.sql' -print | foreach file (`xargs`) curl -n -T $file ftp://ftp1.archive.example.comend
curl -n 命令強制 curl 讀取您的 .netrc 文件。-T 選項告訴 curl 將指定的文件上傳到給定的 URL。如果您省略了目標文件名,那么 curl 將簡單地重用上傳文件的名稱。
正如您可能猜測到的,curl 具有比 wget 更多的選項。您需要閱讀 curl 的 man 頁面,并將其記在心中。curl 項目還維護了一份使用列表,其中包括關于如何使用 HTTP POST 和 PUT 命令、如何提供登錄憑據、如何使用 SSL 證書、以及如何調試 curl 請求的說明。一個簡單的技巧:嘗試使用 curl -v --trace-ascii ... 來生成跟蹤信息。
六處需要說明的地方
現代計算任務的完成在很大程度上依賴于各種型號、規模和服務的計算機之間無數的互連。實際上,即使在一個小型的計算環境中,也可能有一臺計算機專門負責電子郵件,另一臺計算機負責提供 Web 頁面,而其他的計算機則用來執行更專門的任務。在這種環境中(通常使用局域網 (LAN)、WAN 或虛擬專用網 (VPN) 進行連接),每天都需要登錄到不同的計算機。系統管理員需要不停地從一臺計算機轉到另一臺計算機,但是對于開發人員和其他的用戶來說,通常則需要登錄到不同的計算機以實現對關鍵的應用程序的遠程訪問。
X Window System 和現有的桌面軟件使得遠程訪問變得相當透明:窗口僅僅只是窗口,而基礎應用程序可以運行于任何計算機。這里再次說明,即使在這個以鼠標為中心的環境中,命令行也還是有其一席之地的。例如,如何輕松地在多臺計算機上運行相同的命令呢?或者,更簡單地說,如何在遠程系統中啟動一個 xterm 窗口呢?
提供遠程系統訪問正是 ssh 及其派生工具(scp 和 sftp)的任務。ssh 是 rsh 的安全版本,而 scp 和 sftp 則分別是 rcp 和 FTP 的安全替代。它為什么是安全的呢?ssh 及其變種提供了更強的身份驗證機制,并使用您所選擇的幾個密碼對所有的通信內容進行加密。即使有人探查 您的網絡,ssh 通信數據對他們來說也毫無意義。
ssh 最簡單的用法是 ssh hostname。該命令將連接到 hostname,并提示您輸入登錄名和密碼。在提供了正確的憑據之后,您就可以登錄到系統中:
(www.joe.com) $ ssh web.example.comLogin: arthurPassWord: ******( web.example.com) $
如果您只需要在遠程系統中運行一個命令,那么就不需要進行登錄。只需將該命令作為 ssh 的參數即可。例如,清單 3 中所示的命令用于在遠程計算機上運行 hostname -a -v。
清單 3. 使用 ssh 在遠程系統中運行命令
(www.joe.com) $ ssh db.Linux-mag.com hostname -a -vLogin: vogonPassWord: ******dbgethostname()=`db.linux-mag.com'Resolving `db.linux-mag.com' ...Result: h_name=`db.linux-mag.com'Result: h_aliases=`db'Result: h_addr_list=`64.34.170.230'
ssh 建立到 db.linux-mag.com 的連接,然后將 hostname -a -v 參數傳遞到遠程計算機,該參數將運行這個命令并將輸出返回到本地計算機。
ssh 還為將文件和整個目錄從一臺計算機復制到另一臺計算機提供了一種便捷的方法。scp 與 cp 一樣很容易使用。這里有一個示例:
(www.joe.com) $ scp -p -r ~/myproject web.example.com:
這個命令將 ~/myproject 目錄復制到 web.example.com。如果您省略了目標路徑名,那么將把這些文件復制到 home 目錄。-p 選項保持所有文件的日期和時間戳,而 -r 則啟動遞歸 模式,這樣一來,scp 將進入并復制所有的子目錄。
順便提一下,前面的 scp 命令等價于:
(www.joe.com) $ tar czf - ~/myproject | ssh www.example.com tar xvzf -Login: deepthoughtPassword: ******
是的,您可以通過管道將本地命令的輸出傳遞給遠程命令(反之亦然)。
您可能已經厭倦了這些密碼輸入提示。同樣,這些反復出現的提示將降低工作效率并影響自動化的實現。您也可能厭倦了一次又一次地輸入冗長的用戶名。幸運的是,ssh 支持公鑰或私鑰身份驗證和系統別名。
下面,讓我們使用 DSA 加密方案來設置公鑰或私鑰對。要完成這項工作,您必須生成密鑰對,將公鑰復制到遠程系統,并將它添加到已知密鑰列表中,然后對其進行驗證,如清單 4 所示。
清單 4. 創建并安裝公鑰或私鑰
1 $ cd ~2 $ mkdir .ssh3 $ chmod 700 .ssh4 $ cd .ssh5 $ ssh-keygen -t dsaGenerating public/private dsa key pair.Enter file in which to save the key (/home/mstreicher/.ssh/id_dsa): ./id_dsaEnter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in ./id_dsa.Your public key has been saved in ./id_dsa.pub.The key fingerprint is:40:6c:26:e7:53:df:d1:7b:c4:79:c5:a8:cd:6b:fe:8e [email protected] $ lsid_dsa id_dsa.pub7 $ chmod 600 *8 $ scp id_dsa.pub www.example.com:Login: marvinPassWord: ******id_dsa 100% 668 0.7KB/s 00:00 9 $ ssh www.example.comLogin: marvinPassword: ******A $ mkdir .sshB $ chmod 700 .sshC $ cd .sshD $ cat ../id_dsa.pub >> authorized_keysE $ rm ../id_dsa.pubF $ chmod 600 *G $ logout10 $ ssh www.example.coma $ hostnamewww.example.comb $ logout
命令 1 到 3 在您的 home 目錄中創建了一個名為 .ssh 的私有本地目錄。這個目錄的模式必須為 700,否則 ssh 無法使用公鑰或私鑰身份驗證。(您可以看到,步驟 A 到 C 對遠程計算機運行了相同的命令序列。)命令 5 使用 DSA 創建了密鑰對。接下來,保持其中的兩個 Passphrase 為空。(它們提供了額外的安全級別,但卻添加了一項身份驗證步驟。)ssh-keygen 生成兩個文件:id_dsa(私鑰)和 id_dsa.pub(公鑰)。步驟 6 顯示了這些文件,而步驟 7 則對這兩個密鑰進行保護。您的密鑰的模式必須為 0600 或 0400。
相關文章:
