BASH 的基本語法 • 最簡單的例子 —— Hello World! • 關於輸入、輸出和錯誤輸出 • BASH 中對變數的規定(與 C 語言的異同) • BASH 中的基本流程式控制制語法 • 函數的使用 2.1 最簡單的例子 —— Hello World! 幾乎所有的講解編程的書給讀者的第一個例子都是 Hello World 程序,那麼我們今天也就從這個例子出發,來逐步了解 BASH。 用 vi 編輯器編輯一個 hello 文件如下: #!/bin/bash # This is a very simple example echo Hello World 這樣最簡單的一個 BASH 程序就編寫完了。這裡有幾個問題需要說明一下: 一,第一行的 #! 是什麼意思 二,第一行的 /bin/bash 又是什麼意思 三,第二行是註釋嗎 四,echo 語句 五,如何執行該程序 #! 是說明 hello 這個文件的類型的,有點類似於 Windows 系統下用不同文件後綴來表示不同文件類型的意思(但不相同)。Linux 系統根據 "#!" 及該字串後面的信息確定該文件的類型,關於這一問題同學們回去以後可以通過 "man magic"命令 及 /usr/share/magic 文件來了解這方面的更多內容。在 BASH 中 第一行的 "#!" 及後面的 "/bin/bash" 就表明該文件是一個 BASH 程序,需要由 /bin 目錄下的 bash 程序來解釋執行。BASH 這個程序一般是存放在 /bin 目錄下,如果你的 Linux 系統比較特別,bash 也有可能被存放在 /sbin 、/usr/local/bin 、/usr/bin 、/usr/sbin 或 /usr/local/sbin 這樣的目錄下;如果還找不到,你可以用 "locate bash" "find / -name bash 2> /dev/null" 或 "whereis bash" 這三個命令找出 bash 所在的位置;如果仍然找不到,那你可能需要自己動手安裝一個 BASH 軟體包了。 第二行的 "# This is a ..." 就是 BASH 程序的註釋,在 BASH 程序中從「#」號(注意:後面緊接著是「!」號的除外)開始到行尾的多有部分均被看作是程序的註釋。的三行的 echo 語句的功能是把 echo 後面的字元串輸出到標準輸出中去。由於 echo 後跟的是 "Hello World" 這個字元串,因此 "Hello World"這個字串就被顯示在控制台終端的屏幕上了。需要注意的是 BASH 中的絕大多數語句結尾處都沒有分號。 如何執行該程序呢?有兩種方法:一種是顯式制定 BASH 去執行: $ bash hello 或 $ sh hello (這裡 sh 是指向 bash 的一個鏈接,「lrwxrwxrwx 1 root root 4 Aug 20 05:41 /bin/sh -> bash」) 或者可以先將 hello 文件改為可以執行的文件,然後直接運行它,此時由於 hello 文件第一行的 "#! /bin/bash" 的作用,系統會自動用/bin/bash 程序去解釋執行 hello 文件的: $ chmod u+x hello $ ./hello 此處沒有直接 「$ hello」是因為當前目錄不是當前用戶可執行文件的默認目錄,而將當前目錄「.」設為默認目錄是一個不安全的設置。 需要注意的是,BASH 程序被執行后,實際上 Linux 系統是另外開設了一個進程來運行的。 2.2 關於輸入、輸出和錯誤輸出 在字元終端環境中,標準輸入/標準輸出的概念很好理解。輸入即指對一個應用程序 或命令的輸入,無論是從鍵盤輸入還是從別的文件輸入;輸出即指應用程序或命令產生的一些信息;與 Windows 系統下不同的是,Linux 系統下還有一個標準錯誤輸出的概念,這個概念主要是為程序調試和系統維護目的而設置的,錯誤輸出於標準輸出分開可以讓一些高級的錯誤信息不干擾正常的輸出 信息,從而方便一般用戶的使用。 在 Linux 系統中:標準輸入(stdin)默認為鍵盤輸入;標準輸出(stdout)默認為屏幕輸出;標準錯誤輸出(stderr)默認也是輸出到屏幕(上面的 std 表示 standard)。在 BASH 中使用這些概念時一般將標準輸出表示為 1,將標準錯誤輸出表示為 2。下面我們舉例來說明如何使用他們,特別是標準輸出和標準錯誤輸出。 輸入、輸出及標準錯誤輸出主要用於 I/O 的重定向,就是說需要改變他們的默認設置。先看這個例子: $ ls > ls_result $ ls -l >> ls_result 上面這兩個命令分別將 ls 命令的結果輸出重定向到 ls_result 文件中和追加到 ls_result 文件中,而不是輸出到屏幕上。">"就是輸出(標準輸出和標準錯誤輸出)重定向的代表符號,連續兩個 ">" 符號,即 ">>" 則表示不清除原來的而追加輸出。下面再來看一個稍微複雜的例子: $ find /home -name lost* 2> err_result 這個命令在 ">" 符號之前多了一個 "2","2>" 表示將標準錯誤輸出重定向。由於 /home 目錄下有些目錄由於許可權限制不能訪問,因此會產生一些標準錯誤輸出被存放在 err_result 文件中。大家可以設想一下 find /home -name lost* 2>>err_result 命令會產生什麼結果? 如果直接執行 find /home -name lost* > all_result ,其結果是只有標準輸出被存入 all_result 文件中,要想讓標準錯誤輸出和標準輸入一樣都被存入到文件中,那該怎麼辦呢?看下面這個例子: $ find /home -name lost* > all_result 2>& 1 上面這個例子中將首先將標準錯誤輸出也重定向到標準輸出中,再將標準輸出重定向到 all_result 這個文件中。這樣我們就可以將所有的輸出都存儲到文件中了。為實現上述功能,還有一種簡便的寫法如下: $ find /home -name lost* >& all_result 如果那些出錯信息並不重要,下面這個命令可以讓你避開眾多無用出錯信息的干擾: $ find /home -name lost* 2> /dev/null 同學們回去后還可以再試驗一下如下幾種重定向方式,看看會出什麼結果,為什麼? $ find /home -name lost* > all_result 1>& 2 $ find /home -name lost* 2> all_result 1>& 2 $ find /home -name lost* 2>& 1 > all_result 另外一個非常有用的重定向操作符是 "-",請看下面這個例子: $ (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -) 該命令表示把 /source/directory 目錄下的所有文件通過壓縮和解壓,快速的全部移動到 /dest/directory 目錄下去,這個命令在 /source/directory 和 /dest/directory 不處在同一個文件系統下時將顯示出特別的優勢。 下面還幾種不常見的用法: n<&- 表示將 n 號輸入關閉 <&- 表示關閉標準輸入(鍵盤) n>&- 表示將 n 號輸出關閉 >&- 表示將標準輸出關閉 2.3 BASH 中對變數的規定(與 C 語言的異同) 好了下面我們進入正題,先看看 BASH 中的變數是如何定義和使用的。對於熟悉 C 語言的程序員,我們將解釋 BASH 中的定義和用法與 C 語言中有何不同。 2.3.1. BASH 中的變數介紹 我們先來從整體上把握一下 BASH 中變數的用法,然後再去分析 BASH 中變數使用與 C 語言中的不同。BASH 中的變數都是不能含有保留字,不能含有 "-" 等保留字元,也不能含有空格。 2.3.1.1 簡單變數 在 BASH 中變數定義是不需要的,沒有 "int i" 這樣的定義過程。如果想用一個變數,只要他沒有在前面被定義過,就直接可以用,當然你使用該變數的第一條語句應該是對他賦初值了,如果你不賦初值也沒關 系,只不過該變數是空( 注意:是 NULL,不是 0 )。不給變數賦初值雖然語法上不反對,但不是一個好的編程習慣。好了我們看看下面的例子: 首先用 vi 編輯下面這個文件 hello2: #!/bin/bash # give the initialize value to STR STR="Hello World" echo $STR 在上面這個程序中我們需要注意下面幾點: 一,變數賦值時,'='左右兩邊都不能有空格; 二,BASH 中的語句結尾不需要分號(";"); 三,除了在變數賦值和在FOR循環語句頭中,BASH 中的變數使用必須在變數前加"$"符號,同學們可以將上面程序中第三行改為 "echo STR" 再試試,看看會出什麼結果。==>output: STR 四,由於 BASH 程序是在一個新的進程中運行的,所以該程序中的變數定義和賦值不會改變其他進程或原始 Shell 中同名變數的值,也不會影響他們的運行。 更細緻的文檔甚至提到以但引號括起來的變數將不被 BASH 解釋為變數,如 '$STR' ,而被看成為純粹的字元串。而且更為標準的變數引用方式是 ${STR} 這樣的,$STR 自不過是對 ${STR} 的一種簡化。在複雜情況下(即有可能產生歧義的地方)最好用帶 {} 的表示方式。 BASH 中的變數既然不需要定義,也就沒有類型一說,一個變數即可以被定義為一個字元串,也可以被再定義為整數。如果對該變數進行整數運算,他就被解釋為整數;如果對他進行字元串操作,他就被看作為一個字元串。請看下面的例子: #!/bin/bash x=1999 let "x = $x + 1" echo $x x="olympic'"$x echo $x 關於整數變數計算,有如下幾種:" + - * / % ",他們的意思和字面意思相同。整數運算一般通過 let 和 expr 這兩個指令來實現,如對變數 x 加 1 可以寫作:let "x = $x + 1" 或者 x=`expr $x + 1` 在比較操作上,整數變數和字元串變數各不相同,詳見下表: 對應的操作 整數操作 字元串操作 相同 -eq = 不同 -ne != 大於 -gt > 小於 -lt < 大於或等於 -ge 小於或等於 -le 為空 -z 不為空 -n 比如: 比較字元串 a 和 b 是否相等就寫作:if [ $a = $b ] 判斷字元串 a 是否為空就寫作: if [ -z $a ] 判斷整數變數 a 是否大於 b 就寫作:if [ $a -gt $b ] 更細緻的文檔推薦在字元串比較時盡量不要使用 -n ,而用 ! -z 來代替。(其中符號 "!" 表示求反操作) BASH 中的變數除了用於對 整數 和 字元串 進行操作以外,另一個作用是作為文件變數。BASH 是 Linux 操作系統的 Shell,因此系統的文件必然是 BASH 需要操作的重要對象,如 if [ -x /root ] 可以用於判斷 /root 目錄是否可以被當前用戶進入。下表列出了 BASH 中用於判斷文件屬性的操作符: 運算符 含義( 滿足下面要求時返回 TRUE ) -e file 文件 file 已經存在 -f file 文件 file 是普通文件 -s file 文件 file 大小不為零 -d file 文件 file 是一個目錄 -r file 文件 file 對當前用戶可以讀取 -w file 文件 file 對當前用戶可以寫入 -x file 文件 file 對當前用戶可以執行 -g file 文件 file 的 GID 標誌被設置 -u file 文件 file 的 UID 標誌被設置 -O file 文件 file 是屬於當前用戶的 -G file 文件 file 的組 ID 和當前用戶相同 file1 -nt file2 文件 file1 比 file2 更新 file1 -ot file2 文件 file1 比 file2 更老 注意:上表中的 file 及 file1、file2 都是指某個文件或目錄的路徑。 2.3.1.1. 關於局部變數 在 BASH 程序中如果一個變數被使用了,那麼直到該程序的結尾,該變數都一直有效。為了使得某個變數存在於一個局部程序塊中,就引入了局部變數的概念。BASH 中,在變數首次被賦初值時加上 local 關鍵字就可以聲明一個局部變數,如下面這個例子: #!/bin/bash HELLO=Hello function hello { local HELLO=World echo $HELLO } echo $HELLO hello echo $HELLO 該程序的執行結果是: Hello World Hello 這個執行結果表明全局變數 $HELLO 的值在執行函數 hello 時並沒有被改變。也就是說局部變數 $HELLO 的影響只存在於函數那個程序塊中。 2.3.2. BASH 中的變數與 C 語言中變數的區別 這裡我們為原來不熟悉 BASH 編程,但是非常熟悉 C 語言的程序員總結一下在 BASH 環境中使用變數需要注意的問題。 1,BASH 中的變數在引用時都需要在變數前加上 "$" 符號( 第一次賦值及在For循環的頭部不用加 "$"符號 ); 2,BASH 中沒有浮點運算,因此也就沒有浮點類型的變數可用; 3,BASH 中的整形變數的比較符號與 C 語言中完全不同,而且整形變數的算術運算也需要經過 let 或 expr 語句來處理; 2.4 BASH 中的基本流程式控制制語法 BASH 中幾乎含有 C 語言中常用的所有控制結構,如條件分支、循環等,下面逐一介紹。 2.4.1 if...then...else if 語句用於判斷和分支,其語法規則和 C 語言的 if 非常相似。其幾種基本結構為: if [ expression ] then statments fi 或者 if [ expression ] then statments else statments fi 或者 if [ expression ] then statments else if [ expression ] then statments else statments fi 或者 if [ expression ] then statments elif [ expression ] then statments else statments fi 值得說明的是如果你將 if 和 then 簡潔的寫在一行裡面,就必須在 then 前面加上分號,如:if [ expression ]; then ... 。下面這個例子說明了如何使用 if 條件判斷語句: #!/bin/bash if [ $1 -gt 90 ] then echo "Good, $1" elif [ $1 -gt 70 ] then echo "OK, $1" else echo "Bad, $1" fi exit 0 上面例子中的 $1 是指命令行的第一個參數,這個會在後面的「BASH 中的特殊保留字」中講解。 2.4.2 for for 循環結構與 C 語言中有所不同,在 BASH 中 for 循環的基本結構是: for $var in do statments done 其中 $var 是循環控制變數, 是 $var 需要遍歷的一個集合,do/done 對包含了循環體,相當於 C 語言中的一對大括弧。另外如果do 和 for 被寫在同一行,必須在 do 前面加上 ";"。如: for $var in ; do 。下面是一個運用 for 進行循環的例子: #!/bin/bash for day in Sun Mon Tue Wed Thu Fri Sat do echo $day done # 如果列表被包含在一對雙引號中,則被認為是一個元素 for day in "Sun Mon Tue Wed Thu Fri Sat" do echo $day done exit 0 注意上面的例子中,在 for 所在那行的變數 day 是沒有加 "$" 符號的,而在循環體內,echo 所在行變數 $day 是必須加上 "$" 符號的。另外如果寫成 for day 而沒有後面的 in 部分,則 day 將取遍命令行的所有參數。如這個程序: #!/bin/bash for param do echo $param done exit 0 上面這個程序將列出所有命令行參數。for 循環結構的循環體被包含在 do/done 對中,這也是後面的 while、until 循環所具有的特點。 2.4.3 while while 循環的基本結構是: while [ condition ] do statments done 這個結構請大家自己編寫一個例子來驗證。 2.4.4 until until 循環的基本結構是: until [ condition is TRUE ] do statments done 這個結構也請大家自己編寫一個例子來驗證。 2.4.5 case BASH 中的 case 結構與 C 語言中的 switch 語句的功能比較類似,可以用於進行多項分支控制。其基本結構是: case "$var" in condition1 ) statments1;; condition2 ) statments2;; ... * ) default statments;; esac 下面這個程序是運用 case 結構進行分支執行的例子: #!/bin/bash echo "Hit a key, then hit return." read Keypress case "$Keypress" in [a-z] ) echo "Lowercase letter";; [A-Z] ) echo "Uppercase letter";; [0-9] ) echo "Digit";; * ) echo "Punctuation, whitespace, or other";; esac exit 0 上面例子中的第四行 "read Keypress" 一句中的 read 語句表示從鍵盤上讀取輸入。這個命令將在本講義的 BASH 的其他高級問題中講解。 2.4.6 break/continue 熟悉 C 語言編程的都很熟悉 break 語句和 continue 語句。BASH 中同樣有這兩條語句,而且作用和用法也和 C 語言中相同,break 語句可以讓程序流程從當前循環體中完全跳出,而 continue 語句可以跳過當次循環的剩餘部分並直接進入下一次循環。 2.5 函數的使用 BASH 是一個相對簡單的腳本語言,不過為了方便結構化的設計,BASH 中也提供了函數定義的功能。BASH 中的函數定義很簡單,只要向下面這樣寫就可以了: function my_funcname { code block } 或者 my_funcname() { code block } 上面的第二種寫法更接近於 C 語言中的寫法。BASH 中要求函數的定義必須在函數使用之前,這是和 C 語言用頭文件說明函數方法的不同。 更進一步的問題是如何給函數傳遞參數和獲得返回值。BASH 中函數參數的定義並不需要在函數定義處就制定,而只需要在函數被調用時用 BASH 的保留變數 $1 $2 ... 來引用就可以了;BASH 的返回值可以用 return 語句來指定返回一個特定的整數,如果沒有 return 語句顯式的返回一個返回值,則返回值就是該函數最後一條語句執行的結果(一般為 0,如果執行失敗返回錯誤碼)。函數的返回值在調用該函數的程序體中通過 $? 保留字來獲得。下面我們就來看一個用函數來計算整數平方的例子: #!/bin/bash square() { let "res = $1 * $1" return $res } square $1 result=$? echo $result exit 0 BASH 中的特殊保留字 • 保留變數 • 隨機數 • 運算符 • 變數的特殊操作 3.1 保留變數 BASH 中有一些保留變數,下面列出了一些: $IFS 這個變數中保存了用於分割輸入參數的分割字元,默認識空格。 $HOME 這個變數中存儲了當前用戶的根目錄路徑。 $PATH 這個變數中存儲了當前 Shell 的默認路徑字元串。 $PS1 表示第一個系統提示符。 $PS2 表示的二個系統提示符。 $PWD 表示當前工作路徑。 $EDITOR 表示系統的默認編輯器名稱。 $BASH 表示當前 Shell 的路徑字元串。 $0, $1, $2, ... 表示系統傳給腳本程序或腳本程序傳給函數的第0個、第一個、第二個等參數。 $# 表示腳本程序的命令參數個數或函數的參數個數。 $$ 表示該腳本程序的進程號,常用於生成文件名唯一的臨時文件。 $? 表示腳本程序或函數的返回狀態值,正常為 0,否則為非零的錯誤號。 $* 表示所有的腳本參數或函數參數。 $@ 和 $* 涵義相似,但是比 $* 更安全。 $! 表示最近一個在後台運行的進程的進程號。 3.2 隨機數 隨機數是經常要用到的,BASH 中也提供了這個功能,請看下面這個程序: #!/bin/bash # Prints different random integer from 1 to 65536 a=$RANDOM echo $a exit 0 這個程序可以在每次執行的時候隨機的列印出一個大小在 1 到 65536 之間的整數。 3.3 運算符 算術運算符 + - * / % 表示加減乘除和取余運算 += -= *= /= 同 C 語言中的含義 位操作符 << <<= >> >>= 表示位左右移一位操作 & &= | |= 表示按位與、位或操作 ~ ! 表示非操作 ^ ^= 表示異或操作 關係運算符 < > <= >= == != 表示大於、小於、大於等於、小於等於、等於、不等於操作 && || 邏輯與、邏輯或操作 3.4 變數的特殊操作 BASH 中還有一些對變數的簡潔、快速的操作,大家還記得 "${var}" 和 "$var" 同樣是對變數的引用吧,對 ${var} 進行一些變化就可以產生一些新功能: ${var-default} 表示如果變數 $var 還沒有設置,則保持 $var 沒有設置的狀態,並返回後面的默認值 default。 ${var=default} 表示如果變數 $var 還沒有設置,則取後面的默認值 default。 ${var+otherwise} 表示如果變數 $var 已經設置,則返回 otherwise 的值,否則返回空( null )。 ${var?err_msg} 表示如果變數 $var 已經設置,則返回該變數的值,否則將後面的 err_msg 輸出到標準錯誤輸出上。 請同學們自己嘗試下面的例子: #!/bin/bash echo ${var?There is an error} exit 0 還有下面一些用法,這些用法主要用於從文件路徑字元串中提取有用信息: ${var#pattern}, ${var##pattern} 用於從變數 $var 中剝去最短(最長)的和 pattern 相匹配的最左側的串。 ${var%pattern}, ${var%%pattern} 用於從變數 $var 中剝去最短(最長)的和 pattern 相匹配的最右側的串。 另外 BASH 2 中還加入下面一些操作: ${var:pos} 表示去掉變數 $var 中前 pos 個字元。 ${var:pos:len} 表示變數 $var 中去掉前 pos 個字元后的剩餘字元串的前 len 個字元。 ${var/pattern/replacement} 表示將變數 $var 中第一個出現的 pattern 模式替換為 replacement 字元串。 ${var//pattern/replacement} 表示將變數 $var 中出現的所有 pattern 模式全部都替換為 replacment 字元串。 BASH 中的其他高級問題 • BASH 中對返回值的處理 • 用 BASH 設計簡單用戶界面 • 在 BASH 中讀取用戶輸入 • 一些特殊的慣用法 • BASH 程序的調試 • 關於 BASH2 4.1 BASH 中對返回值的處理 無論是在 Shell 中對 BASH 腳本返回值的處理,還是在腳本中對函數返回值的處理,都是通過 "$?" 系統變數來獲得。BASH 要求返回值必須為一個整數,不能用 return 語句返回字元串變數。 4.2 用 BASH 設計簡單用戶界面 BASH 中提供了一個小的語句格式,可以讓程序快速的設計出一個字元界面的用戶交互選擇的菜單,該功能就是由 select 語句來實現的,select 語句的語法為: select var in do statments use $var done 上面的語法結構在執行后,BASH 會將 中的所有項加上數字列在屏幕上等待用戶選擇,在用戶作出選擇后,變數 $var 中就包含了那個被選中的字元串,然後就可以對該變數進行需要的操作了。我們可以從下面的例子中更直觀的來理解這個功能: #!/bin/bash OPTIONS="Hello Quit" select opt in $OPTIONS; do if [ "$opt" = "Quit" ]; then echo done exit elif [ "$opt" = "Hello" ]; then echo Hello World else clear echo bad option fi done exit 0 大家可以試著執行上面的程序,看看是什麼執行結果。 4.3 在 BASH 中讀取用戶輸入 BASH 中通過 read 函數來實現讀取用戶輸入的功能,如下面這段程序: #!/bin/bash echo Please enter your name read NAME echo "Hi! $NAME !" exit 0 上面這個腳本讀取用戶的輸入,並回顯在屏幕上。 另外 BASH 中還提供另外一種稱為 here documents 的結構????,可以將用戶需要通過鍵盤輸入的字元串改為從程序體中直接讀入,如密碼。下面的小程序演示了這個功能: #!/bin/bash passwd="aka@tsinghua" ftp -n localhost < user anonymous $passwd binary bye FTPFTP exit 0 這個程序在用戶需要通過鍵盤敲入一些字元時,通過程序內部的動作來模擬鍵盤輸入。請注意 here documents 的基本結構為: command < statments ... SOMESPECIALSTRING 這裡要求在需要鍵盤輸入的命令后,直接加上 <<符號,然後跟上一個特別的字元串,在該串后按順序輸入本來應該由鍵盤輸入的所有字元,在所有需要輸入的字元都結束后,重複一遍前面 <<符號后的「特別的字元串」即表示該輸入到此結束。 4.4 一些特殊的慣用法 在 BASH 中 () 一對括弧一般被用於求取括弧中表達式的值或命令的執行結果,如:(a=hello; echo $a) ,其作用相當於 `...` 。 : 有兩個含義,一是表示空語句,有點類似於 C 語言中的單個 ";" 。表示該行是一個空命令,如果被用在 while/until 的頭結構中,則表示值 0,會使循環一直進行下去,如下例: while : do operation-1 operation-2 ... operation-n done 另外 : 還可以用於求取後面變數的值,比如: #!/bin/bash : ${HOSTNAME?} {USER?} {MAIL?} echo $HOSTNAME echo $USER echo $MAIL exit 0 在 BASH 中 export 命令用於將系統變數輸出到外層的 Shell 中了。 4.5 BASH 程序的調試 用 bash -x bash-script 命令,可以查看一個出錯的 BASH 腳本到底錯在什麼地方,可以幫助程序員找出腳本中的錯誤。 另外用 trap 語句可以在 BASH 腳本出錯退出時列印出一些變數的值,以供程序員檢查。trap 語句必須作為繼 "#!/bin/bash" 后的第一句非註釋代碼,一般 trap 命令被寫作: trap 'message $checkvar1 $checkvar2' EXIT 。 4.6 關於 BASH2 使用 bash -version 命令可以看出當前你正在使用的 BASH 是什麼版本,一般版本號為1.14或其他版本。而現在機器上一般還安裝了一個版本號為 2.0 的 BASH 。該 BASH 也在 /bin 目錄下。BASH2 提供了一些新功能,有興趣的同敘可以自己去看相關資料,或直接 man bash2 即可。
[火星人
]
Linux Bash Shell快速入門 已經有847 次圍觀
本文地址: http://coctec.com/docs/linux/show-post-143561.html