溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

UNIX/Linux 系統(tǒng)管理技術(shù)手冊(cè)閱讀(十一)

發(fā)布時(shí)間:2020-03-19 19:35:46 來(lái)源:網(wǎng)絡(luò) 閱讀:371 作者:cix123 欄目:系統(tǒng)運(yùn)維

2016.11.7

2 Scripting and the Shell

Good system administrators write scripts. Scripts standardize and automate the performance of administrative chores and free up admins’ time for more important and more interesting tasks. In a sense, scripts are also a kind of low-rent documentation in that they act as an authoritative outline of the steps needed to complete a particular task.

  好的系統(tǒng)管理員都要寫(xiě)腳本。腳本以標(biāo)準(zhǔn)和自動(dòng)的方式履行系統(tǒng)管理員的繁雜事務(wù),藉此把管理員的時(shí)間節(jié)省出來(lái),以花在更重要和更有意思的任務(wù)上。從某種意思上講,腳本也是一種低質(zhì)量的文檔,因?yàn)樗鼈兂洚?dāng)了一種權(quán)威提綱,提綱里列出完成特殊任務(wù)所需的步驟。

In terms of complexity, administrative scripts run the gamut from simple ones that encapsulate a few static commands to major software projects that manage host configurations and administrative data for an entire site. In this book we’re primarily interested in the smaller, day-to-day scripting projects that sysadmins normally encounter, so we don’t talk much about the support functions (e.g., bug tracking and design review) that are needed for larger projects.

  從復(fù)雜性來(lái)看,系統(tǒng)管理腳本的范圍很廣,簡(jiǎn)單得只封裝幾條靜態(tài)命令,大到一處重要的軟件項(xiàng)目,為整個(gè)站點(diǎn)管理主機(jī)配置和管理性數(shù)據(jù)。在本書(shū)里,我們所感興趣的主要是系統(tǒng)管理員通常會(huì)碰到的較小的日常腳本項(xiàng)目。因此,對(duì)于大的項(xiàng)目才需要的支持功能(例如,bug追蹤和設(shè)計(jì)評(píng)審),我們不會(huì)講得太多。

Administrative scripts should emphasize programmer efficiency and code clarity rather than computational efficiency. This is not an excuse to be sloppy, but simply a recognition that it rarely matters whether a script runs in half a second or two seconds. Optimization can have an amazingly low return on investment, even for scripts that run regularly out of cron.

  系統(tǒng)管理腳本應(yīng)該注重兩點(diǎn),即編程人員的開(kāi)發(fā)效率和代碼的清晰可讀性。計(jì)算效率不應(yīng)該成為關(guān)注重點(diǎn),但這不應(yīng)該成為草率行事的借口,而是要認(rèn)識(shí)到,很少需要在意一個(gè)腳本是在半秒還是兩秒內(nèi)運(yùn)行完。優(yōu)化腳本獲得的回報(bào)都非常低,甚至對(duì)通過(guò)cron定期運(yùn)行的腳本來(lái)說(shuō)也不例外。

For a long time, the standard language for administrative scripts was the one defined by the shell. Most systems’ default shell is bash (the “Bourne-again” shell),but sh (the original Bourne shell) and ksh (the Korn shell) are used on a few UNIX systems. Shell scripts are typically used for light tasks such as automating a sequence of commands or assembling several filters to process data.

  長(zhǎng)期以來(lái),編寫(xiě)系統(tǒng)管理腳本的標(biāo)準(zhǔn)語(yǔ)言是shell所定義的語(yǔ)言。在大多數(shù)系統(tǒng)上,默認(rèn)的shell都是由bash(即“Bourne agin”shell),但是在幾種不多的UNIX系統(tǒng)上,也用sh(最初的Bourne shell)和ksh(Korn shell)。shell腳本一般用于輕量級(jí)的任務(wù),如自動(dòng)執(zhí)行一系列命令,或者把幾個(gè)過(guò)濾器組合起來(lái)處理數(shù)據(jù)。

The shell is always available, so shell scripts are relatively portable and have few dependencies other than the commands they invoke. Whether or not you choose the shell, the shell may choose you: most environments include a hefty complement of existing sh scripts, and those scripts frequently need to be read, understood, and tweaked by administrators.

  各種操作系統(tǒng)上都有shell,所以shell腳本可移值性相當(dāng)好,除了它們調(diào)用的命令之外,要依賴(lài)的東西也不多。無(wú)論是否選擇shell來(lái)編寫(xiě)腳本,都會(huì)碰到shell;大多數(shù)環(huán)境都包括已有sh腳本的強(qiáng)大補(bǔ)充,系統(tǒng)管理員會(huì)頻頻閱讀、理解和調(diào)整這些腳本。

For more sophisticated scripts, it’s advisable to jump to a real programming language such as Perl or Python, both of which are well suited for administrative work. These languages incorporate a couple of decades’ worth of language design advancements relative to the shell, and their text processing facilities (invaluable to administrators) are so powerful that sh can only weep and cower in shame.

  對(duì)于更為復(fù)雜高端的腳本來(lái)說(shuō),建議轉(zhuǎn)而采用一種真正的編程語(yǔ)言來(lái)寫(xiě),像perl或者python這樣的語(yǔ)言,它們兩者都很適合于系統(tǒng)管理工作。這兩種語(yǔ)言融入的設(shè)計(jì)理念比shell領(lǐng)先20年,它們的字處理功能(對(duì)于系統(tǒng)管理員來(lái)說(shuō),價(jià)值難以估量)如此強(qiáng)大,sh在它們面前黯然失色。

The main drawback to Perl and Python is that their environments can be a bit

fussy to set up, especially when you start to use third-party libraries that have compiled components. The shell skirts this particular issue by having no module structure and no third-party libraries.

  Perl和Python的主要缺點(diǎn)在于,建立它們的環(huán)境要麻煩一點(diǎn),尤其是要用到的第三方庫(kù),而庫(kù)里又包含已經(jīng)編譯好的部件的時(shí)候。shell沒(méi)有模塊結(jié)構(gòu),也沒(méi)有第三方的庫(kù),因此避開(kāi)了這個(gè)特殊的問(wèn)題。

This chapter takes a quick look at bash, Perl, and Python as languages for scripting, along with regular expressions as a general technology.

  本章簡(jiǎn)要介紹了bash、Perl和Python作為腳本編程語(yǔ)言的用法,以及正則表達(dá)式這種通用的技術(shù)。


2.1 SHELL BASICS

Before we take up shell scripting, let’s review some of the basic features and syntax of the shell. The material in this section applies to all major shells in the sh lineage (including bash and ksh, but not csh or tcsh), regardless of the exact platform you are using. Try out the forms you’re not familiar with, and experiment!

2.1 shell的基礎(chǔ)知識(shí)

  在我們開(kāi)始介紹Shell的腳本編輯之前,讓我們先看看shell的一此基本特性和語(yǔ)法。不管讀者正在使用的是何種平臺(tái),本節(jié)都適用于sh大家庭里的所有主流shell(包括bash和ksh,但不包括csh或者tesh)。嘗試一下自己不熟悉的sh形式,做做實(shí)驗(yàn)吧!


2016.11.11 15:10

Command editing

We’ve watched way too many people edit command lines with the arrow keys. You

wouldn’t do that in your text editor, right?

If you like emacs, all the basic emacs commands are available to you when you’re editing history. <Control-E> goes to the end of the line and <Control-A> to the beginning. <Control-P> steps backward through recently executed commands and recalls them for editing. <Control-R> searches incrementally through your history to find old commands.

If you like vi, put your shell’s command-line editing into vi mode like this:

  $ set -o vi

As in vi, editing is modal; however, you start in input mode. Type <Esc> to leave input mode and “i” to reenter it. In edit mode, “w” takes you forward a word, “fX”finds the next X in the line, and so on. You can walk through past command history entries with <Esc> k. Want emacs editing mode back again?

  $ set -o emacs

2.1.1 編輯命令

  我們已經(jīng)注意到一點(diǎn),太多人都用方向鍵來(lái)編輯命令行。但讀者朋友不會(huì)在文字編輯器里這么做,對(duì)嗎?

  如果喜歡emacs,那么在編輯命令歷史的時(shí)候,所有emacs基本命令都用得上,用<Control-E>到行尾,用<Control-A>到命令行的開(kāi)頭,用<Control-P>一條一條回退到最近執(zhí)行過(guò)的命令,重新把它們調(diào)出來(lái)進(jìn)行編輯。用<Control-R>增量搜索命令歷史找出老命令。

  如果喜歡vi,那么用下面的命令就能讓shell的命令行編輯進(jìn)入vi模式:

  $ set -o vi

  和在vi里一樣,編輯操作也是有模式的;不過(guò),一開(kāi)始會(huì)進(jìn)入輸入模式。按ESC鍵開(kāi)始離開(kāi)輸入模式,按“i”鍵重新進(jìn)入輸入模式。在編輯模式下“w”鍵向前進(jìn)一個(gè)單詞,“FX”在本行里找到下一個(gè)X,等等。用<ESC>k可以遍歷過(guò)去輸入的命令。想要再次回到emacs編輯代碼,輸入:

  $ set -o emacs

Pipes and redirection

Every process has at least three communication channels available to it: “standard input” (STDIN), “standard output” (STDOUT), and “standard error” (STDERR). The kernel sets up these channels on the process’s behalf, so the process itself doesn’t necessarily know where they lead. They might connect to a terminal window, a file, a network connection, or a channel belonging to another process, to name a few possibilities.

2.1.2 管理和重定向

  每個(gè)進(jìn)程都至少有3個(gè)信息:“標(biāo)準(zhǔn)輸入”、標(biāo)準(zhǔn)輸出、和“標(biāo)準(zhǔn)出錯(cuò)”。內(nèi)核給每個(gè)進(jìn)程都設(shè)置了3個(gè)信道,所以進(jìn)程本身不必知道這三個(gè)信道通到哪里。舉例來(lái)說(shuō),它們可能連接到一個(gè)終端窗口、一個(gè)網(wǎng)絡(luò)連接,或者屬于另一個(gè)進(jìn)程的信道。

UNIX has a unified I/O model in which each channel is named with a small integer called a file descriptor. The exact number assigned to a channel is not usually significant, but STDIN, STDOUT, and STDERR are guaranteed to correspond to file descriptors 0, 1, and 2, so it’s safe to refer to these channels by number. In the context of an interactive terminal window, STDIN normally reads from the keyboard and both STDOUT and STDERR write their output to the screen.

  UNIX有一個(gè)統(tǒng)一的I/O模型,在這個(gè)模型中,每個(gè)信道都以一個(gè)整數(shù)來(lái)命名,它叫做文件描述符。分配給一個(gè)信道整數(shù)值到底是哪個(gè),通常而主沒(méi)有意義,但要保證STDIN、STDOUT和STDERR對(duì)應(yīng)文件描述符0,1和2,所以保險(xiǎn)的做法是,用數(shù)字來(lái)引用這三個(gè)信道。在交互式的終端窗口里,STDIN一般讀取鍵盤(pán)的輸入,而STDOUT和STDERR把它們的輸出寫(xiě)到屏幕上。

Most commands accept their input from STDIN and write their output to STDOUT. They write error messages to STDERR. This convention lets you string commands together like building blocks to create composite pipelines.

  大多數(shù)命令都接受從STDIN來(lái)輸入,并且把自己的輸出寫(xiě)到STDOUT,而把錯(cuò)信息寫(xiě)到STDERR。有了這樣的約定,用戶(hù)就能把命令像積木一樣串起來(lái),創(chuàng)建出混合管道。

The shell interprets the symbols <, >, and >> as instructions to reroute a command’s input or output to or from a file. A < symbol connects the command’s STDIN to the contents of an existing file. The > and >> symbols redirect STDOUT; > replaces the file’s existing contents, and >> appends to them. For example, the command

  $ echo "This is a test message." > /tmp/mymessage

  shell將<、>和》解釋成指令,用來(lái)把一條命令的輸入或者輸出重新定向到一個(gè)文件。<這個(gè)符號(hào)把這條命令的STDIN和已有的某個(gè)文件的內(nèi)容聯(lián)系起來(lái)。符號(hào)>和》則重定向STDOUT;>會(huì)替換文件的現(xiàn)有內(nèi)容,而》則給文件追加內(nèi)容。例如,下面的命令

  $ echo "This is a test message." > /tmp/mymessage

stores a single line in the file /tmp/mymessage, creating the file if necessary. The command below emails the contents of that file to user johndoe.

  $ mail -s "Mail test" johndoe < /tmp/mymessage

  在/tmp/mymessage這個(gè)文件里存入一行內(nèi)容,如果必要,還會(huì)創(chuàng)建這個(gè)文件。下面的命令把該文件的內(nèi)容用電子郵件發(fā)給用戶(hù)johndoe。

  $ mail -s "Mail test" johndoe < /tmp/mymessage

To redirect both STDOUT and STDERR to the same place, use the >& symbol. To

redirect STDERR only, use 2>.

  為了把STDOUT和STDERR都重定向到同一個(gè)地方,可以用>&這個(gè)符號(hào),僅僅重定向STDERR的話,則用2>。

The find command illustrates why you might want to handle STDOUT and

STDERR separately because it tends to produce output on both channels, especially when run as an unprivileged user. For example, a command such as

  $ find / -name core

  命令find演示了想要分開(kāi)處理STDOUT和STDERR的原因,因?yàn)樗鼤?huì)在兩個(gè)信道提供輸出,特別是以非特權(quán)用戶(hù)身份運(yùn)行的時(shí)候。例如,像下面這條命令

  $ find / -name core

usually results in so many “permission denied” error messages that genuine hits get lost in the clutter. To discard all the error messages, you can use

  $ find / -name core 2> /dev/null

  通常會(huì)導(dǎo)致很多“permission denied”這樣的出錯(cuò)信息,從而把真正的結(jié)果淹沒(méi)在混亂的輸出里了。要消除所有出錯(cuò)消息,可以用這條命令

  $ find / -name core 2> /dev/null

In this version, only real matches (where the user has read permission on the parent directory) come to the terminal window. To save the list of matching paths to a file, try

  $ find / -name core > /tmp/corefiles 2> /dev/null

  在這個(gè)版本的命令里,只有真正匹配的結(jié)果(該用戶(hù)對(duì)父目錄有讀權(quán)的地方)才會(huì)出現(xiàn)在終端窗口中。要把匹配路徑的清單保存在一個(gè)文件里,可以試試下面的命令

  $ find / -name core > /tmp/corefiles 2> /dev/null

This command line sends matching paths to /tmp/corefiles, discards errors, and sends nothing to the terminal window.

  這一行命令把匹配的路徑發(fā)到/tmpcorefile這個(gè)文件,丟棄出錯(cuò)消息,向終端窗口什么都不發(fā)。

To connect the STDOUT of one command to the STDIN of another, use the | symbol, commonly known as a pipe. Some examples:

  $ ps -ef | grep httpd

  $ cut -d: -f7 < /etc/passwd | sort -u

  要把一條命令的STDOUT連接到另一條命令的STDIN上,可以用|這個(gè)符號(hào),它常叫做管道。下面是一些例子

  $ ps -ef | grep httpd

  $ cut -d: -f7 < /etc/passwd | sort -u

The first example runs ps to generate a list of processes and pipes it through the grep command to select lines that contain the word httpd. The output of grep is not redirected, so the matching lines come to the terminal window.

  第一個(gè)例子運(yùn)行ps產(chǎn)生一份進(jìn)程清單,由管道送給grep命令選出包含httpd這個(gè)詞的若干行。grep命令的輸出沒(méi)有重定向,所以匹配的結(jié)果都出現(xiàn)在終端窗口里。

The cut command in the second example picks out the path to each user’s shell

from /etc/passwd. The list of shells is then sent through sort -u to produce a

sorted list of unique values.

  第二個(gè)例子用cut命令從/etc/passwd文件里把每個(gè)用戶(hù)的shell的路徑選出來(lái)。接著,列出的shell的路徑都通過(guò)sort -u進(jìn)行處理,產(chǎn)生的清單中,路徑名不但依次排序,且路徑名只出現(xiàn)一次。

To execute a second command only if its precursor completes successfully, you

can separate the commands with an && symbol. For example,

  $ lpr /tmp/t2 && rm /tmp/t2

  要讓第二條命令只有在第一條命令成功完成之后才執(zhí)行,可以用一個(gè)&&符號(hào)把兩條命令隔開(kāi)。例如

  $ lpr /tmp/t2 && rm /tmp/t2

removes /tmp/t2 if and only if it is successfully queued for printing. Here, the success of the lpr command is defined as its yielding an exit code of zero, so the use of a symbol that suggests “l(fā)ogical AND” for this purpose may be confusing if you’re used to short-circuit evaluation in other programming languages. Don’t think about it too much; just accept it as a shell idiom.

  這條命令當(dāng)且僅當(dāng)/tmp/t2成功送入打印隊(duì)列之后,才會(huì)刪除/tmp/t2。在這里,lpr命令產(chǎn)生的退出碼為0的話,就算它執(zhí)行成功,所以,如果讀者已經(jīng)習(xí)慣了其他編程語(yǔ)言中的“短路”計(jì)算,而這里用一個(gè)表示“邏輯與”的符號(hào),那么就可能造成混亂。不要想得太多;僅僅把它當(dāng)做一個(gè)shell的習(xí)慣用法就行了。

Conversely, the || symbol executes the following command only if the preceding

command fails (produces a nonzero exit status).

In a script, you can use a backslash to break a command onto multiple lines, helping to distinguish the error-handling code from the rest of the command pipeline:

  cp --preserve --recursive /etc/* /spare/backup \

       || echo "Did NOT make backup"

For the converse effect—multiple commands combined onto one line—you can

use a semicolon as a statement separator.

  相反,||這個(gè)符號(hào)表明,只有前一條命令執(zhí)行不成功(產(chǎn)生了一個(gè)非零的退出碼)時(shí),才執(zhí)行后面的腳本。

  在一個(gè)腳本里,可以用反斜線把一條命令分成多行來(lái)寫(xiě),從而把出錯(cuò)處理代碼和命令管道的其他部分區(qū)分開(kāi)來(lái)。

  cp --preserve --recursive /etc/* /spare/backup \

       || echo "Did NOT make backup"

  要實(shí)現(xiàn)相反的效果--將多條命令整合在一行里--可以用分號(hào)作為語(yǔ)句分隔符。


向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI