bash(以及通常意義上的shell腳本編程)出現(xiàn)的日子可是不短了,,每天都有新手通過(guò)bash見(jiàn)識(shí)到shell腳本編程和系統(tǒng)自動(dòng)化的威力,。隨著微軟公司在Windows 10中發(fā)布了交互式的bash shell以及Unix子系統(tǒng),現(xiàn)在已是更適合了解shell腳本所能實(shí)現(xiàn)的簡(jiǎn)潔和高效的時(shí)候了,。 從計(jì)算機(jī)出現(xiàn)的早期開(kāi)始,,shell腳本就一直在幫助系統(tǒng)管理員和程序員完成費(fèi)時(shí)費(fèi)力的枯燥工作。那么,,什么是shell腳本,?為什么你要關(guān)心它? 什么是shell腳本shell腳本就是包含一組可運(yùn)行的特定shell命令(在本文中是bash shell)的文本文件,,命令的執(zhí)行順序與其出現(xiàn)在腳本中的順序一致,。shell以命令行的形式提供了可用的操作系統(tǒng)命令庫(kù)的接口。 shell腳本其實(shí)就是為使用shell環(huán)境中的命令所編寫(xiě)的小型程序,,可用于自動(dòng)化那些通常沒(méi)人愿意手動(dòng)完成的任務(wù),例如Web爬取,、磁盤(pán)用量跟蹤,、天氣數(shù)據(jù)下載,、文件更名,等等,。你甚至能夠用shell腳本制作一些初級(jí)的游戲,!腳本中可以加入簡(jiǎn)單的邏輯,例如在其他語(yǔ)言中出現(xiàn)的if語(yǔ)句,。 OS X,、BSD以及Linux操作系統(tǒng)中可用的命令行shell有很多種,包括tcsh,、zsh和廣受歡迎的bash,。本文關(guān)注的是Unix環(huán)境中的主流:bash。 每種shell都有自己的特性和功能,,但是多數(shù)人在Unix中最先熟悉的就是bash,。在OS X中,Terminal(終端)應(yīng)用會(huì)打開(kāi)一個(gè)bash shell窗口(如圖0-1),。在Linux中,,有各種各樣的shell控制臺(tái)程序,其中最常見(jiàn)的是gnome-terminal(GNOME)或konsole(KDE),。這些應(yīng)用可以修改自身的配置來(lái)使用其他類(lèi)型的shell,,不過(guò)默認(rèn)選用的都是bash。實(shí)際上,,不管你用的是哪種類(lèi)Unix操作系統(tǒng),,打開(kāi)Terminal應(yīng)用,得到的都是bash,。 圖0-1 OS X中的Terminal應(yīng)用,,其中顯示了bash的版本號(hào) 注意 2016年8月,微軟發(fā)布了針對(duì)Windows 10周年版(Windows 10 Anniversary)的bash,,所以如果你用的是Windows,,照樣可以使用bash shell。bash的美妙之處就在于它的可移植性,,所以多數(shù)腳本基本上應(yīng)該沒(méi)問(wèn)題,。 使用終端與系統(tǒng)交互可能看起來(lái)是件艱巨的任務(wù)。但隨著時(shí)間的推移,,打開(kāi)終端,,快速對(duì)系統(tǒng)做出更改,會(huì)變得比在一個(gè)又一個(gè)的菜單中移動(dòng)鼠標(biāo),,找到要更改的選項(xiàng)更加自然,。 執(zhí)行命令bash的核心功能是執(zhí)行系統(tǒng)命令。來(lái)看一個(gè)簡(jiǎn)單的“Hello World”的例子,。在bash shell中,,echo命令可以在屏幕上顯示文本,,例如: $ echo 'Hello World' 在命令行中輸入上面的內(nèi)容,你就會(huì)看到Hello World出現(xiàn)在屏幕上,。這行代碼執(zhí)行了bash標(biāo)準(zhǔn)命令echo,。bash用來(lái)搜索標(biāo)準(zhǔn)命令的目錄被保存在環(huán)境變量PATH中。你可以使用echo查看PATH變量的內(nèi)容,,如代碼清單0-1所示,。 代碼清單0-1 輸出當(dāng)前環(huán)境變量PATH
注意 如果代碼清單中既顯示了輸入命令,也顯示了輸出內(nèi)容,,輸入命令會(huì)以粗體顯示并以$作為起始,,以此同輸出內(nèi)容區(qū)分開(kāi)來(lái)。 輸出中的各個(gè)目錄之間以冒號(hào)分隔,。當(dāng)需要運(yùn)行程序或命令時(shí),,bash會(huì)檢查所有這些目錄。如果命令沒(méi)有在其中,,bash就無(wú)法執(zhí)行,。另外要注意的是,bash是以這些目錄在PATH中出現(xiàn)的順序依次檢查的,。順序在這里很重要,,如果有兩個(gè)同名的命令分別位于PATH中兩個(gè)不同的目錄中,可能會(huì)由于目錄出現(xiàn)的先后順序產(chǎn)生不同的結(jié)果,。如果在查找特定命令時(shí)碰到了麻煩,,可以用which命令查看待查找命令在PATH中的位置,如代碼清單0-2所示,。 代碼清單0-2 使用which在PATH中查找命令 $ which ruby 知道了這些信息,,你可以把需要測(cè)試的文件移動(dòng)或復(fù)制到echo $PATH所列出的某個(gè)目錄中(如代碼清單0-1所示),然后就能執(zhí)行命令了,。本文中使用了which來(lái)確定命令的完整路徑,。在調(diào)試有問(wèn)題的PATH環(huán)境變量時(shí),which是一個(gè)有用的工具,。 配置登錄腳本我們會(huì)編寫(xiě)一些隨后用于其他腳本中的腳本,,因此能夠輕松調(diào)用新腳本就顯得很重要了。你可以配置PATH環(huán)境變量,,使得在啟動(dòng)新的命令shell時(shí),,可以像其他命令那樣自動(dòng)調(diào)用定制腳本。新命令shell啟動(dòng)后的第一件事是讀取用戶(hù)主目錄(在OS X和Linux中分別是/Users/<username>和/home/<username>)中的登錄腳本并執(zhí)行其中的定制命令,。根據(jù)你所用的系統(tǒng),,登錄腳本可以是.login、.profile、.bashrc或.bash_profile,。要想知道具體是哪個(gè),,像下面這樣在這些文件中各加入一行:
將最后一個(gè)單詞調(diào)整為對(duì)應(yīng)的文件名,然后登錄,。這行內(nèi)容應(yīng)該會(huì)出現(xiàn)在終端窗口頂端,指明登錄時(shí)運(yùn)行的是哪個(gè)腳本,。如果你打開(kāi)終端,,看到的是this is .profile,那么說(shuō)明你的shell環(huán)境載入的是.profile文件,;如果看到的是this is .bashrc,,則說(shuō)明是.bashrc文件,以此類(lèi)推,。依賴(lài)于你所用的shell,,這種行為也會(huì)有變化。 你可以修改登錄腳本,,讓它幫助在PATH變量中加入其他目錄,。另外也可以在登錄腳本中完成其他bash設(shè)置,例如修改bash提示符外觀(guān),、定制PATH等,。讓我們用cat命令來(lái)看一個(gè)定制好的.bashrc登錄腳本。cat命令接受文件名作為參數(shù),,然后將文件內(nèi)容輸出到控制臺(tái)屏幕,,如代碼清單0-3所示。 代碼清單0-3 定制過(guò)的.bashrc文件,,其中將RVM加入了PATH $ cat ~/.bashrc 該代碼顯示出了.bashrc文件的內(nèi)容,可以看到PATH獲得了一個(gè)新的值,,允許本地RVM (Ruby version manager,,Ruby版本管理器)管理已安裝的各種Ruby版本。因?yàn)?bashrc在每次啟動(dòng)新的命令shell時(shí)都會(huì)設(shè)置PATH,,所以RVM在系統(tǒng)中總是默認(rèn)可用,。 你可以用類(lèi)似的方法讓自己的shell腳本也默認(rèn)可用。首先,,在主目錄中創(chuàng)建一個(gè)開(kāi)發(fā)目錄,,將編寫(xiě)的所有腳本都保存到這個(gè)目錄。然后在登錄腳本中將該目錄添加到PATH變量中,,這樣就可以更方便地引用新寫(xiě)的腳本了,。 命令echo $HOME可以在終端中打印出主目錄的路徑。進(jìn)入主目錄,然后創(chuàng)建開(kāi)發(fā)目錄(建議將其命名為scripts),。接著用文本編輯器打開(kāi)登錄腳本,,在腳本頂端添加以下代碼(把/path/to/scripts/替換成開(kāi)發(fā)目錄的具體路徑),將開(kāi)發(fā)目錄加入PATH,。
在此之后,,你保存到開(kāi)發(fā)目錄中的任何腳本都可以像其他shell命令那樣調(diào)用了。 運(yùn)行shell腳本我們到目前為止已經(jīng)用到了幾個(gè)命令,,例如echo,、which和cat,但是只是單獨(dú)使用,,并沒(méi)有把它們放到shell腳本中,。讓我們來(lái)寫(xiě)一個(gè)可以連續(xù)執(zhí)行這些命令的shell腳本,如代碼清單0-4所示,。這個(gè)腳本先打印出Hello World,,然后輸出shell腳本neqn的路徑,neqn應(yīng)該位于PATH默認(rèn)的目錄中,。接著用該路徑將neqn的內(nèi)容打印到屏幕上,。(neqn的內(nèi)容是什么目前并不重要,這里只是作為一個(gè)例子而已,。)這是利用shell腳本按順序執(zhí)行命令序列的一個(gè)很好的例子,,在這里我們查看了文件的完整系統(tǒng)路徑并快速檢查了文件內(nèi)容。 代碼清單0-4 我們的第一個(gè)shell腳本 echo 'Hello World' 打開(kāi)你自己慣用的文本編輯器(Linux上的Vim或gedit,、OS X上的TextEdit都是很流行的編輯器),,輸入代碼清單0-4中的代碼。然后將shell腳本保存到開(kāi)發(fā)目錄中并命名為intro,。shell腳本對(duì)文件擴(kuò)展名沒(méi)有特別要求,,用不用都行(如果喜歡的話(huà),可以用.sh作為擴(kuò)展名,,但不是必須的),。第一行代碼使用echo命令打印出文本Hello World。第二行代碼稍微復(fù)雜點(diǎn),,使用which命令找出neqn的位置,,然后將其用echo命令在屏幕上打印出來(lái)。為了像這樣將一個(gè)命令作為另外一個(gè)命令的參數(shù)來(lái)運(yùn)行兩個(gè)命令,,bash使用子shell(subshell)來(lái)執(zhí)行第二個(gè)命令并將其輸出作為第一個(gè)命令的參數(shù),。在上面的例子中,子shell執(zhí)行的是which命令,,該命令返回neqn腳本的完整路徑,。這個(gè)路徑再被用作echo的參數(shù),,結(jié)果就是在屏幕上顯示出neqn的路徑。最后,,還是用子shell將neqn的路徑傳給cat命令,,在屏幕上打印出neqn腳本的內(nèi)容。 保存好文件之后,,就可以在終端運(yùn)行腳本了,。代碼清單0-5顯示了執(zhí)行結(jié)果。 代碼清單0-5 運(yùn)行我們的第一個(gè)shell腳本
運(yùn)行這個(gè)腳本的時(shí)候,,使用sh命令并將intro腳本作為參數(shù),。sh命令會(huì)依次執(zhí)行腳本中的每行代碼,就好像這些命令是在終端上敲入的一樣,。你可以看到先是打印出了Hello World?,然后是neqn的路徑?,,最后輸出neqn的文件內(nèi)容?,,也就是shell腳本neqn的源代碼(至少在OS X上是這樣的,Linux版本也許略有不同),。 讓shell腳本用起來(lái)更自然不使用sh命令也可以執(zhí)行腳本,。如果在shell腳本intro中多加一行,然后修改腳本的權(quán)限,,就可以像其他bash命令那樣直接調(diào)用腳本了,。在文本編輯器中更新intro腳本: ? #!/bin/bash 我們?cè)谀_本頂端加上了一行/bin/bash?。這行叫作shebang,。shebang允許你指定用哪個(gè)程序來(lái)解釋腳本,。這里選擇將文件作為bash腳本。你可能還碰到過(guò)其他shebang,,例如針對(duì)Perl(#!/usr/bin/perl)或Ruby(#!/usr/bin/env ruby)的,。 shebang:這個(gè)詞其實(shí)是兩個(gè)字符名稱(chēng)sharp-bang 的簡(jiǎn)寫(xiě)。在Unix 的行話(huà)里,,用sharp 或hash(有時(shí)候是mesh)來(lái)稱(chēng)呼字符“#”,,用bang 來(lái)稱(chēng)呼驚嘆號(hào)“!”,因而shebang 合起來(lái)就代表了這兩個(gè)字符,。詳情請(qǐng)參考:en.wikipedia.org/wiki/ Shebang_(Unix),。 有了這行,還得設(shè)置文件權(quán)限才能像其他程序那樣直接運(yùn)行shell腳本,。在終端中的操作方法如代碼清單0-6所示,。 代碼清單0-6 將腳本intro的權(quán)限修改為可執(zhí)行
我們用到了權(quán)限修改命令chmod?并將+x作為命令參數(shù),該參數(shù)可以將隨后指定的文件設(shè)置為可執(zhí)行權(quán)限,。權(quán)限設(shè)置好之后,,不用調(diào)用bash就可以直接運(yùn)行shell腳本?。這是一種很好的shell腳本編程實(shí)踐,在你以后精進(jìn)技藝的過(guò)程中就會(huì)發(fā)現(xiàn)它的作用了,。 這只是一個(gè)簡(jiǎn)單的例子,,告訴你如何運(yùn)行shell腳本,如何使用shell腳本運(yùn)行其他的shell腳本,。在今后編寫(xiě)shell腳本的時(shí)候,,你也會(huì)看到更多的shebang。 為什么要用shell腳本你也許疑惑為什么偏要選擇bash shell腳本,,而不去用那些漂亮的新語(yǔ)言,,比如Ruby或Go。盡管這些語(yǔ)言都試圖在多種系統(tǒng)上實(shí)現(xiàn)可移植性,,但它們通常并沒(méi)有被默認(rèn)安裝,。原因很簡(jiǎn)單:所有Unix機(jī)器上都已經(jīng)有了一個(gè)基本的shell,而且絕大多數(shù)用的都是bash shell,。 文章開(kāi)頭也提到過(guò),,微軟最近在Windows 10中也加入了多數(shù)Linux發(fā)行版和OS X中采用的bash shell。這意味著你的shell腳本幾乎不需要做什么額外的工作,,就擁有了比以往更好的可移植性,。相較于其他語(yǔ)言,shell腳本能夠更準(zhǔn)確,、更輕松地完成系統(tǒng)維護(hù)及其他任務(wù),。 代碼清單0-7中展示了一個(gè)方便的微型shell腳本(沒(méi)錯(cuò),只有一行),,完全可移植,。該腳本可以統(tǒng)計(jì)出OpenOffice文檔目錄中的文檔共有多少頁(yè),這對(duì)于作者特別有用,。 代碼清單0-7 統(tǒng)計(jì)OpenOffice文檔目錄中文檔頁(yè)面數(shù)量的bash腳本 #!/bin/bash 我們不會(huì)深究這個(gè)腳本的工作細(xì)節(jié),,畢竟才剛上路嘛!不過(guò)概括地講,,腳本從各個(gè)文檔中提取出頁(yè)數(shù)信息,,使用加號(hào)將頁(yè)數(shù)拼接在一起,然后通過(guò)管道將算式傳給命令行計(jì)算器,,計(jì)算出最終的頁(yè)面總數(shù),。所有這一切全在這一行代碼中完成。還有更多像這樣的酷炫腳本,,做過(guò)一些練習(xí)之后,,這個(gè)腳本的含義就一目了然了! 開(kāi)始動(dòng)手吧如果你之前沒(méi)有接觸過(guò)shell腳本編程,,那么現(xiàn)在對(duì)此應(yīng)該有了基本的了解,。創(chuàng)建小型腳本完成特定的任務(wù)是Unix哲學(xué)的核心,。搞清楚如何編寫(xiě)腳本并根據(jù)個(gè)人需要擴(kuò)展Unix系統(tǒng),這樣才能成長(zhǎng)為一名高級(jí)用戶(hù),。本文只是道開(kāi)胃菜,,真正酷炫的shell腳本在這本《shell腳本實(shí)戰(zhàn)(第2版)》里面↓
bash仍舊是類(lèi)Unix服務(wù)器或工作站用戶(hù)的主要工具,,這些用戶(hù)包括Web開(kāi)發(fā)人員(很多人都是在OS X上做開(kāi)發(fā),,然后部署到Linux服務(wù)器)、數(shù)據(jù)分析師,、移動(dòng)應(yīng)用程序開(kāi)發(fā)人員以及軟件工程師,,等等。除此之外,,大量的業(yè)余愛(ài)好者也在自己的開(kāi)源微型計(jì)算機(jī)(例如樹(shù)莓派)上運(yùn)行著Linux,,實(shí)現(xiàn)智能家庭的自動(dòng)化。shell腳本是這類(lèi)用途的不二之選,。 無(wú)論是對(duì)于在bash技藝上追求精益求精的老手,,還是那些偶爾用一下終端或shell腳本的用戶(hù),書(shū)中所展現(xiàn)的腳本都大有裨益,。后一陣營(yíng)中的用戶(hù)可能希望溫習(xí)一些技巧或是學(xué)點(diǎn)bash的高級(jí)概念,給自己再充充電,。 本書(shū)并非教程,!其目標(biāo)是通過(guò)(基本上)簡(jiǎn)短緊湊的腳本教會(huì)你bash腳本編程的實(shí)用技術(shù)以及常見(jiàn)工具的用法,但不會(huì)去逐行解釋腳本,。本書(shū)只講解每個(gè)腳本的核心內(nèi)容,,有經(jīng)驗(yàn)的shell腳本用戶(hù)通過(guò)閱讀代碼就能明白其余的部分。你大可放開(kāi)手腳,,把腳本拆解開(kāi)來(lái),,根據(jù)自己的需要修改,借此達(dá)到融會(huì)貫通的目的,。書(shū)中的腳本旨在解決那些三天兩頭就會(huì)碰上的麻煩事,,比如Web管理或是文件同步,不管用的是什么工具,,每個(gè)技術(shù)專(zhuān)家都得應(yīng)付這類(lèi)問(wèn)題,。 本書(shū)重點(diǎn)關(guān)注編寫(xiě)可移植的自動(dòng)化腳本(例如構(gòu)建軟件或提供業(yè)務(wù)流程)時(shí)經(jīng)常面對(duì)的那些難題,為此我們的做法是先實(shí)現(xiàn)一些常見(jiàn)任務(wù)的自動(dòng)化,。但如果想從本書(shū)中獲得最大收益,,就要將已形成的解決方案推廣應(yīng)用到其他類(lèi)似的問(wèn)題上。 盡管很多系統(tǒng)管理員都能受益于這個(gè)腳本,,但其中真正的價(jià)值在于,,創(chuàng)建包裝器腳本這種一般性的解決方案能夠確??缙脚_(tái)行為的一致性。書(shū)中隨后的章節(jié)將深入研究bash腳本編程中一些酷炫的特性以及Unix系統(tǒng)常見(jiàn)的實(shí)用工具,,為你傳授各種絕招,。 目錄 第 1 章 遺失的代碼庫(kù) 第 2 章 改進(jìn)用戶(hù)命令 第 3 章 創(chuàng)建實(shí)用工具 第 4 章 Unix調(diào)校 第 5 章 系統(tǒng)管理:用戶(hù)管理 第 6 章 系統(tǒng)管理:系統(tǒng)維護(hù) 第 7 章 Web與Internet用戶(hù) 第 8 章 網(wǎng)站管理員絕招 第 9 章 Web與Internet管理 第 10 章 Internet服務(wù)器管理 第 11 章 OS X腳本 第 12 章 shell腳本趣用與游戲 第 13 章 與云共舞 第 14 章 ImageMagick及圖像處理 第 15 章 天數(shù)與日期 附錄 A 在Windows 10中安裝bash 附錄 B 免費(fèi)福利 文末暢聊 一本好工具書(shū),一定會(huì)讓你事半功倍,! 工具好書(shū)太多,,你最先想到了哪本呢? 是 《番茄工作法圖解》 《單核工作法圖解》 還是 《GitHub入門(mén)與實(shí)踐》 《用數(shù)據(jù)講故事》,? 工具書(shū)中還有哪些 你用得特別順手的呢,? ...... |
|