第二十五章 : 編寫第一個 Shell 腳本

編寫第一個 Shell 腳本


In the preceding chapters, we have assembled an arsenal of command line tools. Whilethese tools can solve many kinds of computing problems, we are still limited to manuallyusing them one by one on the command line. Wouldn’t it be great if we could get theshell to do more of the work? We can. By joining our tools together into programs ofour own design, the shell can carry out complex sequences of tasks all by itself. We canenable it to do this by writing shell scripts.html

在前面的章節中,咱們已經裝備了一個命令行工具的武器庫。雖然這些工具可以解決許多種計算問題,可是咱們仍然侷限於在命令行中手動地一個一個使用它們。若是咱們可以讓 shell 來完成更多的工做, 豈不是更好?咱們能夠的。經過把咱們的工具一塊兒放置到咱們本身設計的程序中, shell 就會本身來執行這些複雜的任務序列。經過編寫 shell 腳本,咱們可讓 shell 來作這些事情。linux

什麼是 Shell 腳本?

In the simplest terms, a shell script is a file containing a series of commands. The shellreads this file and carries out the commands as though they have been entered directly onthe command line.shell

最簡單的解釋,一個 shell 腳本就是一個包含一系列命令的文件。shell 讀取這個文件,而後執行文件中的全部命令,就好像這些命令已經直接被輸入到了命令行中同樣。express

The shell is somewhat unique, in that it is both a powerful command line interface to thesystem and a scripting language interpreter. As we will see, most of the things that can bedone on the command line can be done in scripts, and most of the things that can be donein scripts can be done on the command line.編程

Shell 有些獨特,由於它不只是一個功能強大的命令行接口,也是一個腳本語言解釋器。咱們將會看到,大多數可以在命令行中完成的任務也可以用腳原本實現,一樣地,大多數能用腳本實現的操做也可以在命令行中完成。vim

We have covered many shell features, but we have focused on those features most oftenused directly on the command line. The shell also provides a set of features usually (butnot always) used when writing programs.bash

雖然咱們已經介紹了許多 shell 功能,但只是集中於那些常常直接在命令行中使用的功能。Shell 也提供了一些一般(但不老是)在編寫程序時才使用的功能。session

怎樣編寫一個 Shell 腳本

To successfully create and run a shell script, we need to do three things:app

爲了成功地建立和運行一個 shell 腳本,咱們須要作三件事情:dom

  1. Write a script. Shell scripts are ordinary text files. So we need a text editor towrite them. The best text editors will provide syntax highlighting, allowing us tosee a color-coded view of the elements of the script. Syntax highlighting will helpus spot certain kinds of common errors. vim, gedit, kate, and many othereditors are good candidates for writing scripts.

  2. Make the script executable. The system is rather fussy about not letting any oldtext file be treated as a program, and for good reason! We need to set the scriptfile’s permissions to allow execution.

  3. Put the script somewhere the shell can find it. The shell automatically searchescertain directories for executable files when no explicit pathname is specified.For maximum convenience, we will place our scripts in these directories.

  1. 編寫一個腳本。 Shell 腳本就是普通的文本文件。因此咱們須要一個文本編輯器來書寫它們。最好的文本編輯器都會支持語法高亮,這樣咱們就可以看到一個腳本關鍵字的彩色編碼視圖。語法高亮會幫助咱們查看某種常見錯誤。爲了編寫腳本文件,vim,gedit,kate,和許多其它編輯器都是不錯的候選者。

  2. 使腳本文件可執行。 系統會至關挑剔不容許任何舊的文本文件被看做是一個程序,而且有充分的理由!因此咱們須要設置腳本文件的權限來容許其可執行。

  3. 把腳本放置到 shell 可以找到的地方。 當沒有指定可執行文件明確的路徑名時,shell 會自動地搜索某些目錄,來查找此可執行文件。爲了最大程度的方便,咱們會把腳本放到這些目錄當中。

腳本文件格式

In keeping with programming tradition, we’ll create a 「hello world」 program todemonstrate an extremely simple script. So let’s fire up our text editors and enter thefollowing script:

爲了保持編程傳統,咱們將建立一個 「hello world」 程序來講明一個極端簡單的腳本。因此讓咱們啓動咱們的文本編輯器,而後輸入如下腳本:

#!/bin/bash
# This is our first script.
echo 'Hello World!'

The last line of our script is pretty familiar, just an echo command with a stringargument. The second line is also familiar. It looks like a comment that we have seenused in many of the configuration files we have examined and edited. One thing aboutcomments in shell scripts is that they may also appear at the end of lines, like so:

對於腳本中的最後一行,咱們應該是至關的熟悉,僅僅是一個帶有一個字符串參數的 echo 命令。對於第二行也很熟悉。它看起來像一個註釋,咱們已經在許多咱們檢查和編輯過的配置文件中看到過。關於 shell 腳本中的註釋,它們也能夠出如今文本行的末尾,像這樣:

echo 'Hello World!' # This is a comment too

Everything from the # symbol onward on the line is ignored.

文本行中,# 符號以後的全部字符都會被忽略。

Like many things, this works on the command line, too:

相似於許多命令,這也在命令行中起做用:

[me@linuxbox ~]$ echo 'Hello World!' # This is a comment too
Hello World!

Though comments are of little use on the command line, they will work.

雖然不多在命令行中使用註釋,但它們也能起做用。

The first line of our script is a little mysterious. It looks like it should be a comment,since it starts with #, but it looks too purposeful to be just that. The #! charactersequence is, in fact, a special construct called a shebang. The shebang is used to tell thesystem the name of the interpreter that should be used to execute the script that follows.Every shell script should include this as its first line.

咱們腳本中的第一行文本有點兒神祕。它看起來它應該是一條註釋,由於它起始於一個#符號,可是它看起來太有意義,以致於不只僅是註釋。事實上,這個#!字符序列是一種特殊的結構叫作 shebang。這個 shebang 被用來告訴操做系統將執行此腳本所用的解釋器的名字。每一個 shell 腳本都應該把這一文本行做爲它的第一行。

Let’s save our script file as hello_world.

讓咱們把此腳本文件保存爲 hello_world。

可執行權限

The next thing we have to do is make our script executable. This is easily done usingchmod:

下一步咱們要作的事情是讓咱們的腳本可執行。使用 chmod 命令,這很容易作到:

[me@linuxbox ~]$ ls -l hello_world
-rw-r--r-- 1  me    me      63  2009-03-07 10:10 hello_world
[me@linuxbox ~]$ chmod 755 hello_world
[me@linuxbox ~]$ ls -l hello_world
-rwxr-xr-x 1  me    me      63  2009-03-07 10:10 hello_world

There are two common permission settings for scripts; 755 for scripts that everyone canexecute, and 700 for scripts that only the owner can execute. Note that scripts must bereadable in order to be executed.

對於腳本文件,有兩個常見的權限設置;權限爲755的腳本,則每一個人都能執行,和權限爲700的腳本,只有文件全部者可以執行。注意爲了可以執行腳本,腳本必須是可讀的。

腳本文件位置

With the permissions set, we can now execute our script:

當設置了腳本權限以後,咱們就能執行咱們的腳本了:

[me@linuxbox ~]$ ./hello_world
Hello World!

In order for the script to run, we must precede the script name with an explicit path. Ifwe don’t, we get this:

爲了可以運行此腳本,咱們必須指定腳本文件明確的路徑。若是咱們沒有那樣作,咱們會獲得這樣的提示:

[me@linuxbox ~]$ hello_world
bash: hello_world: command not found

Why is this? What makes our script different from other programs? As it turns out,nothing. Our script is fine. Its location is the problem. Back in Chapter 12, we discussedthe PATH environment variable and its effect on how the system searches for executableprograms. To recap, the system searches a list of directories each time it needs to find anexecutable program, if no explicit path is specified. This is how the system knows toexecute /bin/ls when we type ls at the command line. The /bin directory is one ofthe directories that the system automatically searches. The list of directories is heldwithin an environment variable named PATH. The PATH variable contains a colon-separated list of directories to be searched. We can view the contents of PATH:

爲何會這樣呢?什麼使咱們的腳本不一樣於其它的程序?結果證實,什麼也沒有。咱們的腳本沒有問題。是腳本存儲位置的問題。回到第12章,咱們討論了 PATH 環境變量及其在系統查找可執行程序方面的做用。回顧一下,若是沒有給出可執行程序的明確路徑名,那麼系統每次都會搜索一系列的目錄,來查找此可執行程序。這個/bin 目錄就是其中一個系統會自動搜索的目錄。這個目錄列表被存儲在一個名爲 PATH 的環境變量中。這個 PATH 變量包含一個由冒號分隔開的目錄列表。咱們能夠查看 PATH 的內容:

[me@linuxbox ~]$ echo $PATH
/home/me/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:
/bin:/usr/games

Here we see our list of directories. If our script were located in any of the directories inthe list, our problem would be solved. Notice the first directory in the list,/home/me/bin. Most Linux distributions configure the PATH variable to contain abin directory in the user’s home directory, to allow users to execute their own programs.So if we create the bin directory and place our script within it, it should start to worklike other programs:

這裏咱們看到了咱們的目錄列表。若是咱們的腳本位於此列表中任意目錄下,那麼咱們的問題將會被解決。注意列表中的第一個目錄/home/me/bin。大多數的 Linux 發行版會配置 PATH 變量,讓其包含一個位於用戶家目錄下的 bin 目錄,從而容許用戶可以執行他們本身的程序。因此若是咱們建立了一個 bin 目錄,並把咱們的腳本放在這個目錄下,那麼這個腳本就應該像其它程序同樣開始工做了:

[me@linuxbox ~]$ mkdir bin
[me@linuxbox ~]$ mv hello_world bin
[me@linuxbox ~]$ hello_world
Hello World!

And so it does.

它的確工做了。

If the PATH variable does not contain the directory, we can easily add it by including thisline in our .bashrc file:

若是這個 PATH 變量不包含這個目錄,咱們可以輕鬆地添加它,經過在咱們的.bashrc 文件中包含下面這一行文本:

export PATH=~/bin:"$PATH"

After this change is made, it will take effect in each new terminal session. To apply thechange to the current terminal session, we must have the shell re-read the .bashrc file.This can be done by 「sourcing」 it:

當作了這個修改以後,它會在每一個新的終端會話中生效。爲了把這個修改應用到當前的終端會話中,咱們必須讓 shell 從新讀取這個 .bashrc 文件。這能夠經過 「sourcing」.bashrc 文件來完成:

[me@linuxbox ~]$ . .bashrc

The dot (.) command is a synonym for the source command, a shell builtin whichreads a specified file of shell commands and treats it like input from the keyboard.

這個點(.)命令是 source 命令的同義詞,一個 shell 內建命令,用來讀取一個指定的 shell 命令文件,並把它看做是從鍵盤中輸入的同樣。


Note: Ubuntu automatically adds the ~/bin directory to the PATH variable if the~/bin directory exists when the user’s .bashrc file is executed. So, on Ubuntusystems, if we create the ~/bin directory and then log out and log in again,everything works.

注意:在 Ubuntu 系統中,若是存在 ~/bin 目錄,當執行用戶的 .bashrc 文件時,Ubuntu 會自動地添加這個 ~/bin 目錄到 PATH 變量中。因此在 Ubuntu 系統中,若是咱們建立了這個 ~/bin 目錄,隨後退出,而後再登陸,一切會正常運行。


腳本文件的好去處

The ~/bin directory is a good place to put scripts intended for personal use. If we writea script that everyone on a system is allowed to use, the traditional location is/usr/local/bin. Scripts intended for use by the system administrator are oftenlocated in /usr/local/sbin. In most cases, locally supplied software, whetherscripts or compiled programs, should be placed in the /usr/local hierarchy and not in/bin or /usr/bin. These directories are specified by the Linux Filesystem HierarchyStandard to contain only files supplied and maintained by the Linux distributor.

這個 ~/bin 目錄是存放爲我的所用腳本的好地方。若是咱們編寫了一個腳本,系統中的每一個用戶均可以使用它,那麼這個腳本的傳統位置是 /usr/local/bin。系統管理員使用的腳本常常放到 /usr/local/sbin 目錄下。大多數狀況下,本地支持的軟件,不論是腳本仍是編譯過的程序,都應該放到 /usr/local 目錄下,而不是在 /bin 或 /usr/bin 目錄下。這些目錄都是由 Linux 文件系統層次結構標準指定,只包含由 Linux 發行商所提供和維護的文件。

更多的格式技巧

One of the key goals of serious script writing is ease of maintenance; that is, the easewith which a script may be modified by its author or others to adapt it to changing needs.Making a script easy to read and understand is one way to facilitate easy maintenance.

嚴肅認真的腳本書寫的關鍵目標之一是爲了易於維護;也就是說,一個腳本能夠輕鬆地被做者或其它用戶修改,使它適應變化的需求。使腳本容易閱讀和理解是一種方便維護的方法。

長選項名稱

Many of the commands we have studied feature both short and long option names. Forinstance, the ls command has many options that can be expressed in either short or longform. For example:

咱們學過的許多命令都以長短兩種選項名稱爲特徵。例如,這個 ls 命令有許多選項既能夠用短形式也能夠用長形式來表示。例如:

[me@linuxbox ~]$ ls -ad

and:

和:

[me@linuxbox ~]$ ls --all --directory

are equivalent commands. In the interests of reduced typing, short options are preferredwhen entering options on the command line, but when writing scripts, long options canprovide improved readability.

是等價的命令。爲了減小輸入,當在命令行中輸入選項的時候,短選項更受歡迎,可是當書寫腳本的時候,長選項能提供可讀性。

縮進和行繼續符

When employing long commands, readability can be enhanced by spreading thecommand over several lines. In Chapter 18, we looked at a particularly long example ofthe find command:

當使用長命令的時候,經過把命令在幾個文本行中展開,能夠提升命令的可讀性。在第十八章中,咱們看到了一個特別長的 find 命令實例:

[me@linuxbox ~]$ find playground \( -type f -not -perm 0600 -exec
chmod 0600 ‘{}’ ‘;’ \) -or \( -type d -not -perm 0711 -exec chmod
0711 ‘{}’ ‘;’ \)

Obviously, this command is a little hard to figure out at first glance. In a script, thiscommand might be easier to understand if written this way:

顯然,這個命令有點兒難理解,當第一眼看到它的時候。在腳本中,這個命令可能會比較容易理解,若是這樣書寫它:

find playground \
    \( \
        -type f \
        -not -perm 0600 \
        -exec chmod 0600 ‘{}’ ‘;’ \
    \) \
    -or \
    \( \
        -type d \
        -not -perm 0711 \
        -exec chmod 0711 ‘{}’ ‘;’ \
    \)

By using line continuations (backslash-linefeed sequences) and indentation, the logic ofthis complex command is more clearly described to the reader. This technique works onthe command line, too, though it is seldom used, as it is very awkward to type and edit.One difference between a script and the command line is that the script may employ tabcharacters to achieve indentation, whereas the command line cannot, since tabs are usedto activate completion.

經過使用行繼續符(反斜槓-回車符序列)和縮進,這個複雜命令的邏輯會被更清楚地描述給讀者。這個技巧在命令行中一樣有效,雖然不多使用它,由於輸入和編輯這個命令很是麻煩。腳本和命令行的一個區別是,腳本可能使用 tab 字符來實現縮進,然而命令行卻不能,由於 tab 字符被用來激活自動補全功能。

Configuring vim For Script Writing

爲書寫腳本配置 vim

The vim text editor has many, many configuration settings. There are severalcommon options that can facilitate script writing:

這個 vim 文本編輯器有許多許多的配置設置。有幾個常見的選項可以有助於腳本書寫:

:syntax on

turns on syntax highlighting. With this setting, different elements of shell syntaxwill be displayed in different colors when viewing a script. This is helpful foridentifying certain kinds of programming errors. It looks cool, too. Note that forthis feature to work, you must have a complete version of vim installed, and thefile you are editing must have a shebang indicating the file is a shell script. If youhave difficulty with the command above, try :set syntax=sh instead.

打開語法高亮。經過這個設置,當查看腳本的時候,不一樣的 shell 語法元素會以不一樣的顏色顯示。這對於識別某些編程錯誤頗有幫助。而且它看起來也很酷。注意爲了這個功能起做用,你必須安裝了一個完整的 vim 版本,而且你編輯的文件必須有一個 shebang,來講明這個文件是一個 shell 腳本。若是對於上面的命令,你遇到了困難,試試 :set syntax=sh

:set hlsearch

turns on the option to highlight search results. Say we search for the word「echo.」 With this option on, each instance of the word will be highlighted.

打開這個選項是爲了高亮查找結果。好比說咱們查找單詞「echo」。經過設置這個選項,這個單詞的每一個實例會高亮顯示。

:set tabstop=4

sets the number of columns occupied by a tab character. The default is eightcolumns. Setting the value to four (which is a common practice) allows longlines to fit more easily on the screen.

設置一個 tab 字符所佔據的列數。默認是8列。把這個值設置爲4(一種常見作法),從而讓長文本行更容易適應屏幕。

:set autoindent

turns on the 「auto indent」 feature. This causes vim to indent a new line the sameamount as the line just typed. This speeds up typing on many kinds ofprogramming constructs. To stop indentation, type Ctrl-d.

打開 「auto indent」 功能。這致使 vim 能對新的文本行縮進與剛輸入的文本行相同的列數。對於許多編程結構來講,這就加速了輸入。中止縮進,輸入 Ctrl-d。

These changes can be made permanent by adding these commands (without theleading colon characters) to your ~/.vimrc file.

經過把這些命令(沒有開頭的冒號字符)添加到你的 ~/.vimrc 文件中,這些改動會永久生效。

總結概括

In this first chapter of scripting, we have looked at how scripts are written and made toeasily execute on our system. We also saw how we may use various formattingtechniques to improve the readability (and thus, the maintainability) of our scripts. Infuture chapters, ease of maintenance will come up again and again as a central principlein good script writing.

在這腳本編寫的第一章中,咱們已經看過怎樣編寫腳本,怎樣讓它們在咱們的系統中輕鬆地執行。咱們也知道了怎樣使用各類格式技巧來提升腳本的可讀性(可維護性)。在之後的各章中,輕鬆維護會做爲編寫好腳本的中心法則一次又一次地出現。

拓展閱讀

========================================Talk is cheap, show me the code=======================================
相關文章
相關標籤/搜索