cmd art
args
cmd
alias
alias ll='ls -al'
unalias
unalias ll
jobs
工作控制tee
雙向重導向
同時將資料流分送到檔案去與螢幕 (screen);而輸出到螢幕的,其實就是 stdout ,可以讓下個指令繼續處理喔
[root@linux ~]# tee [-a] file
參數:
-a :以累加 (append) 的方式,將資料加入 file 當中!
範例:
[root@linux ~]# last | tee last.list | cut -d " " -f1
# 這個範例可以讓我們將 last 的輸出存一份到 last.list 檔案中;
[root@linux ~]# ls -l /home | tee ~/homefile | more
# 這個範例則是將 ls 的資料存一份到 ~/homefile ,同時螢幕也有輸出訊息!
[root@linux ~]# ls -l / | tee -a ~/homefile | more
# 要注意: tee 後接的檔案會被覆蓋,所以,我們要加上 -a
# 這個參數才能將訊息累加。
man
命令去閱讀文件apropos
去查詢文件help
和help -d
命令獲取幫助資訊>
輸出, 會覆蓋了輸出文件>>
輸出, 檔案末新增<
輸入|
重定向管道||
if cmd1 fail, execute the cmd2cmd1 || cmd2
ls this_file_does_not_exist.txt || echo KO
ls: cannot access this_file_does_not_exist.txt: No such file or directory
KO
-
忽略錯誤-rm not_exist_file.txt
refer Make: how to continue after a command fails?
Try the -i flag (or --ignore-errors). Documentation here. The documentation seems to suggest a more robust way to achieve this, by the way:
To ignore errors in a command line, write a -' at the beginning of the
line's text (after the initial tab).
The-' is discarded before the command is passed to the shell for execution.
For example,
clean: -rm -f *.o
This causes rm to continue even if it is unable to remove a file.
All examples are with rm, but are applicable to any other command you need to ignore errors from (i.e. mkdir)
-
0
Standard input
this is the file handle that your process reads to get information from you. -
1
Standard output
your process writes normal information to this file handle. -
2
Standard error
your process writes error information here. -
1>
:是將正確的資料輸出到指定的地方去 -
2>
:是將錯誤的資料輸出到指定的地方去
好了,那麼上面的例子中,我們如何將資料輸出到不同的地方去呢?可以這麼寫
find /home -name testing > list_right 2> list_error
要正確的資料,錯誤的資訊不要
find /home -name testing > list_right 2> /dev/null
將資料都寫到同一個檔案中
find /home -name testing > list 2>&1
File descriptor 1 is the standard output (stdout). File descriptor 2 is the standard error (stderr)
Note 在 Makefile
使用 shell
請注意
What is the meaning of a double dollar sign in bash/Makefile?
makefile variable
=> use a single dollar signshell variable
=> use two dollar signs
Shell
execute
sh /path/to/script.sh
bash /path/to/script.sh
chmod
命令給予檔案執行權限,使檔案可以執行:
chmod +x /path/to/script.sh
在這個 script 第一行必須指定應該使用哪個程式來執行這個檔案
#!/bin/bash
echo "Hello, world!"
execute
/path/to/script.sh
Exit codes
成功
的命令始終回傳 0失敗
回傳非零值, 誤代碼必須介於 1 到 255 的正整數
撰寫 script 時,我們可以使用另一個方便的 exit 命令。使用這個命令來終止目前的執行,並向 shell 提供一個 exit code。執行一個不帶有任何參數的 exit code,會終止執行目前的 script 並回傳在 exit 之前的最後一個命令的 exit code。
當程式終止時,shell 會把 exit code 指派給環境變數 $?
。$?
變數是我們測試一個 script 是否成功執行。
用同樣的方式,我們可以使用 exit 來停止一個 script,我們能在函式中使用 return 來退出函式並回傳 exit code 給呼叫者,又或者你可以在函式中使用 exit,這會退出函式 並結束程式。
Comment
Script 中可以包含註解。註解是一個特殊的語句,會被 shell 直譯器忽略。它們以一個 #
符號為開頭。
#!/bin/bash
# 這個 script 將會列印你的使用者名稱。
whoami
Variable
- local
區域變數
是只存在於單一 script 的變數,它們是無法讓其他程式或 script 存取的。 一個變數可以使用=
來宣告(根據規則,在變數名稱=變數的值
之間不應有空格的存在),你可以透過$
來取得這個變數的值。例如:
username="denysdovhan" # 宣告變數
echo $username # 顯示變數
unset username # 刪除變數
我們也可以使用 local keyword 在一個 function 中宣告一個區域變數。當 function 結束時,這個區域變數就會消失。
local local_var="I'm a local value"
- enviorment
環境變數
執行在目前 shell session 可以讓任何程式或 script 存取的變數。建立它們與區域變數類似,但使用export
作為前綴
export GLOBAL_VAR="I'm a global variable"
also can unset
unexport ENV_VAR_TEST
可以存入檔案 最後使用 source configurefile
來讀取變成暫時性的 環境變數
$HOME
目前使用者的家目錄$PATH
shell 以這些冒號分隔的目錄清單尋找命令$PWD
目前的工作目錄$RANDOM
0 到 32767 之間的隨機整數$UID
數字類型,使用者的 ID$PS1
主要的提示字串$PS2
次要的提示字串
check it for further Variables
-
arg
命令列引數
是當程式執行時,變數根據執行程式時,程式名稱後所跟隨的參數而得。下面表格列出了當你在程式執行時,命令列引數和其他特殊變數它們所代表的意義。 -
$0
Script 的名稱 -
$1 … $9
從第 1 個到第 9 個參數 -
${10} … ${N}
從第 10 個到第 N 個參數 -
$* 或 $@
除了 $0 以外的所有參數 -
$#
不包含 $0的參數數量 -
$FUNCNAME
function 名稱(只有一個變數在 function 內部)
在下面的範例
./script.sh foo bar
命令列引數
$0
:./script.sh
$1
:foo
$2
:bar
# 如果變數是空值,分配一個預設值。
: ${VAR:='default'}
: ${$1:='first'}
# 或
FOO=${FOO:-'default'}
Shell expansion
括號展開
括號展開讓我們可以產生任意字串。它類似於檔案名稱展開。例如:
echo beg{i,a,u}n # begin began begun
括號展開也可以用在建立一個 loop iterated
的範圍。
echo {0..5} # 0 1 2 3 4 5
echo {00..8..2} # 00 02 04 06 08
命令替代
命令替代允許我們對執行指令,並將指令的回傳值作為參數放進其他命令中,或是將回傳值指派到變數當中,當命令被 \
/`` 或 $() 包住時,命令替代將會執行。例如,我們可以使用它如下所示:
now=`date +%T`
# 或
now=$(date +%T)
echo $now # 19:08:26
算術代入展開
在 bash 裡我們可以很輕鬆的做到任何算術運算。但是表達式必須放在 $(( ))
裡面,算術代入展開的格式為
result=$(( ((10 + 5*3) - 7) / 2 ))
echo $result # 9
在算術代入展開內,變數不需要 $
前綴:
x=4
y=7
echo $(( x + y )) # 11
echo $(( ++x + y++ )) # 12
echo $(( x + y )) # 13
單引號和雙引號
- 雙引號內的變數或是命令替代會被代入展開
- 單引號內則不會
echo "Your home: $HOME" # Your home: /Users/<username>
echo 'Your home: $HOME' # Your home: $HOME
區域變數
和環境變數
包含空格時,它們在引號內的展開要格外小心。隨便舉個例子,使用 echo
來印出一些使用者的輸入:
INPUT="A string with strange whitespace."
echo $INPUT # A string with strange whitespace.
echo "$INPUT" # A string with strange whitespace.
第一個 echo
調用了 5 個獨立的參數 — $INPUT
被拆成獨立的單字,echo
在每個單字之間列印一個空白字元。在第二種情況中,echo
調用了一個參數(整個 $INPUT
,包含空白)。
現在來看看一個更嚴重的例子吧:
FILE="Favorite Things.txt"
cat $FILE # 嘗試印出兩個檔案的內容:`Favorite` 和 `Things.txt`。
cat "$FILE" # 列印一個檔案的內容: `Favorite Things.txt`。
在這個範例的問題可以透過把 FILE
重新命名成 Favorite-Things.txt
來解決,
考慮輸入進來的
- 環境變數
- 位置參數
- 命令的輸出(
find
、cat
等等)
如果輸入可能包含空格,請記得使用引號包起來。
陣列
與大部分的程式語言一樣,在 bash 一個陣列是一個變數,讓你可以指向多個數值。在 Bash 中,陣列是從 0 開始
當處理陣列時,我們應該要知道一個特殊的環境變數 IFS
IFS
或 Input Field Separator
,是陣列中的元素之間的分隔符號
。預設的 IFS
是一個空格 IFS=' '
。
陣列宣告
在 Bash 你可以通過簡單地賦值給陣列變數的索引來建立陣列。
fruits[0]=Apple
fruits[1]=Pear
fruits[2]=Plum
也可以使用複合賦值建立陣列變數,像是:
fruits=(Apple Pear Plum)
陣列展開
個別陣列元素可以像其他變數一樣展開:
echo ${fruits[1]} # Pear
可以把 *
或 @
放在陣列索引值的地方將陣列展開:
echo ${fruits[*]} # Apple Pear Plum
echo ${fruits[@]} # Apple Pear Plum
以上兩行有很重要且微妙的差別,假設陣列的元素值中包含空白:
fruits[0]=Apple
fruits[1]="Desert fig"
fruits[2]=Plum
我們想要將陣列中的元素隔行印出,所以我們試著用看看內建函數 printf
:
printf "+ %s\n" ${fruits[*]}
# + Apple
# + Desert
# + fig
# + Plum
為什麼 Desert
和 fig
被分開了?讓我們嘗試使用雙引號括起來:
printf "+ %s\n" "${fruits[*]}"
# + Apple Desert fig Plum
現在所有元素都被放在同一行了 - 這不是我們想要的!為了解決這個問題,接著試試 ${fruits[@]} 吧:
printf "+ %s\n" "${fruits[@]}"
# + Apple
# + Desert fig
# + Plum
在雙引號中,${fruits[@]}
將陣列每個元素視為成獨立的參數;保留了陣列元素中的空白。
切割陣列
除此之外,我們可以使用 slice
運算符來取出陣列中某個部份:
echo ${fruits[@]:0:2} # Apple Desert fig
在上面的範例,${fruits[@]}
expands 整個陣列的內容,而 :0:2
取出從索引為 0
,長度為 2
的元素。 (譯者註:因此會從陣列位置 0 開始取 2 個元素)
把一個物件加入到陣列中
在一個陣列中新增元素也是相單簡單的。在這種情況下複合賦值特別有用。我們可以像這樣使用︰ (譯者註:複合賦值-例如在 a = a + 1 中,就是將 a 的值帶入運算式中,再將值指派回原本的變數)
fruits=(Orange "${fruits[@]}" Banana Cherry)
echo ${fruits[@]} # Orange Apple Desert fig Plum Banana Cherry
上面的範例中,${fruits[@]}
展開整個陣列的內容,並替換 fruits 然後帶入複合賦值,分配新的值到 fruits 陣列,修改原始的值。
把一個物件從陣列中移除
如果要從一個陣列中刪除一個元素,使用 unset
命令:
unset fruits[0]
echo ${fruits[@]} # Apple Desert fig Plum Banana Cherry
Streams、pipes 和 lists
bash 在處理程式及輸出有非常強大的功能可以用。使用 streams
可以把程式的輸出導向到另一個程式的 input 或是一個檔案中,這讓我們可以方便的寫入任何我們想要的東西,或者是程式的紀錄檔。
Pipes 給我們建立 conveyor 的機會和控制命令的執行。(譯者註:converyor 為輸送的概念)
最重要的是我們瞭解如何使用這個強大和複雜的工具。
Streams
Bash 接收輸入並將輸出作為序列或字元的 streams 。這些 streams 可能會被重導向到檔案或其他 streams。
代碼 | 描述符 | 描述 |
---|---|---|
0 | stdin | 標準輸入 |
1 | stdout | 標準輸出 |
2 | stderr | 錯誤輸出 |
重導讓我們可以控制命令的輸入來自哪裡,和輸出到哪去。在重導向 streams 時會用到以下運算子:
運算子 | 描述 |
---|---|
> | 重新導向輸出 |
&> | 重新導向輸出和錯誤輸出 |
&» | 以附加形式重新導向輸出和錯誤輸出 |
< | 重新導向輸入 |
« | Here 文件語法 |
«< | Here 字串 |
這裡有一些重導向的範例:
# 將 ls 的輸出寫入到 list.txt。
ls -l > list.txt
# 將輸出附加到 list.txt。
ls -a >> list.txt
# 所有錯誤將會被寫入到 error.txt。
grep da * 2> errors.txt
# 從 errors.txt 讀取。
less < errors.txt
Pipes
我們不只可以在檔案可以重導 streams,也可以在其他的程式中。Pipes 也能將輸出作為其他程式的輸入。
在下方的範例,command1 把輸出導向到 command2,然後 command2 再將輸出作為 command3 的輸入:
command1 | command2 | command3
這樣的結構稱為 pipelines。
實際上,這可以用來在多個程式中依序處理資料。例如,ls -l 的輸出傳送到 grep,只列印出附檔名為 .md 的檔案,然後這個輸出最終傳到 less:
ls -l | grep .md$ | less
pipeline 的 exit status 通常是 pipeline 中最後一個命令的 exit status。shell 不會回傳狀態,直到所有在 pipeline 的命令都完成。如果任何在 pipeline 內的命令失敗,你應該設定 pipefail 選項:
set -o pipefail
命令序列
命令序列是由 ;
、&
、&&
或 ||
運算符分隔一個或多個 pipeline
序列。
如果一個命令是以 & 作為結尾
,shell 會在 subshell
中非同步執行命令。換句話說,這個命令會在背景執行。
命令透過 ;
隔開依序執行:一個接著一個指令執行直到所有命令完成。
# command2 會在 command1 執行完後被執行。
command1 ; command2
# 等同於這個方式。
command1
command2
&&
和 ||
分別稱為 AND 和 OR 序列。
AND 序列 看起來像是:
# 只有在 command1 結束成功時(回傳 exit status 為 0 ),command2 才會被執行。
command1 && command2
OR 序列 的形式:
# 只有在 command1 未成功完成時(回傳錯誤代碼 ),command2 才會被執行。
command1 || command2
一個 AND 或 OR 序列回傳的狀態碼,是最後一個執行命令的狀態碼。
Logic Flow
條件陳述式
與大部分的程式語言一樣,Bash 中的條件陳述讓我們決定是否執行某些程式。結果取決於在 [[ ]]
內的運算式。
條件表達式可以包含 &&
和 ||
運算符,就是 AND 和 OR。除此之外,這裡還有許多其他方便的表達式。
有兩種不同條件陳述:if
和 case
。
Primary 和組合表達式
在 [[ ]]
(或 sh 中的 [ ]
)中的表達式稱為 測試命令 或 primaries。這些表達式幫助我們表明條件的結果。在下表中,我們使用 [ ]
,因為它也可以在 sh 執行。這裡有關於在 bash 中,雙引號和單引號的差別
的一些回答。
檢查檔案系統中的檔案或目錄的狀態
Primary | 涵義 |
---|---|
[ -e FILE ] | 如果 FILE 存在(exists),為 Ture |
[ -f FILE ] | 如果 FILE 存在且為一個普通的文件(file),為 True |
[ -d FILE ] | 如果 FILE 存在且為一個目錄(directory),為 True |
[ -s FILE ] | 如果 FILE 存在且不為空(size 大於 0),為 True |
[ -r FILE ] | 如果 FILE 存在且有讀取權限(readable),為 True |
[ -w FILE ] | 如果 FILE 存在且有寫入權限(writable),為 True |
[ -x FILE ] | 如果 FILE 存在且有執行權限(executable),為 True |
[ -L FILE ] | 如果 FILE 存在且為符號連結(link),為 True |
[ FILE1 -nt FILE2 ] | FILE1 比 FILE2 新(newer than) |
[ FILE1 -ot FILE2 ] | FILE1 比 FILE2 舊(older than) |
檢查字串狀態
Primary | 涵義 |
---|---|
[ -z STR ] | STR 為空(長度為 0,zero) |
[ -n STR ] | STR 不為空 (長度不為 0,non-zero) |
[ STR1 == STR2 ] | STR1 和 STR2 相等 |
[ STR1 != STR2 ] | STR1 和 STR2 不相等 |
二進制的算術運算符
Primary | 涵義 |
---|---|
[ ARG1 -eq ARG2 ] | ARG1 和 ARG2 相等(equal) |
[ ARG1 -ne ARG2 ] | ARG1 和 ARG2 不相等(not equal) |
[ ARG1 -lt ARG2 ] | ARG1 小於 ARG2(less than) |
[ ARG1 -le ARG2 ] | ARG1 小於等於 ARG2(less than or equal) |
[ ARG1 -gt ARG2 ] | ARG1 大於 ARG2(greater than) |
[ ARG1 -ge ARG2 ] | ARG1 大於等於 ARG2(greater than or equal) |
組合
條件式也可以 組合 在一起使用:
運算符 | 效果 |
---|---|
[ ! EXPR ] | 如果 EXPR 為 false,則為 True |
[ (EXPR) ] | 回傳 EXPR 的值 |
[ EXPR1 -a EXPR2 ] | AND 邏輯。如果 EXPR1 and EXPR2 為 Ture,則為 True |
[ EXPR1 -o EXPR2 ] | OR 邏輯。如果 EXPR1 or EXPR2 為 Ture,則為 True |
使用 if 陳述
if
使用方式就像其他程式語言一樣。如果表達式括號內為 true
,在 then
和 fi
之間的程式碼會被執行。fi
說明根據條件所執行的程式碼已經結束。
# 單行
if [[ 1 -eq 1 ]]; then echo "true"; fi
# 多行
if [[ 1 -eq 1 ]]; then
echo "true"
fi
同樣的,我們可以使用 if..else
,像是:
# 單行
if [[ 2 -ne 1 ]]; then echo "true"; else echo "false"; fi
# 多行
if [[ 2 -ne 1 ]]; then
echo "true"
else
echo "false"
fi
有時候 if..else
不能滿足我們的需要。在這個情況下,別忘了 if..elif..else
,使用起來也是很方便。
看看下面的例子︰
if [[ `uname` == "Adam" ]]; then
echo "Do not eat an apple!"
elif [[ `uname` == "Eva" ]]; then
echo "Do not take an apple!"
else
echo "Apples are delicious!"
fi
使用一個 case 陳述
如果你面對的是好幾個不同情況,需要採取不同的行動,那麼使用 case 陳述或許會比巢狀化的 if 陳述來的有用。下方是使用 case 來處理更多複雜的條件:
case "$extension" in
"jpg"|"jpeg")
echo "It's image with jpeg extension."
;;
"png")
echo "It's image with png extension."
;;
"gif")
echo "Oh, it's a giphy!"
;;
*)
echo "Woops! It's not image!"
;;
esac
每個 case
都會對應到一個條件。|
符號是被用來分離多個條件,而 )
運算符是條件的結尾。第一個符合的命令會被執行。*
代表不對應以上所給的任一條件。每個命令區塊之間需要透過 ;;
隔開。
for 迴圈
for 非常相似於 C 的 for 迴圈。它看起來像是:
for arg in elem1 elem2 ... elemN
do
# statements
done
在每個迴圈中,arg
會依序被賦予 elem1
到 elemN
的值。值可能是萬用字元或括號展開。
當然,我們也可以將 for
迴圈寫成一行,但在這個情況我們需要在 do
之前放一個分號,像是這樣:
for i in {1..5}; do echo $i; done
順便一提,如果你覺得 for..in..do
看起來很奇怪,你也可以撰寫 C 語言風格的 for 迴圈,像是:
for (( i = 0; i < 10; i++ )); do
echo $i
done
當我們想要將目錄下每個文件做相同的操作時,for 是相當方便的。例如,如果我們需要移動所有的 *.bash
檔到 script
資料夾,並給予它們可執行的權限,我們的 script 可以像是這樣:
#!/bin/bash
for FILE in $HOME/*.bash; do
mv "$FILE" "${HOME}/scripts"
chmod +x "${HOME}/scripts/${FILE}"
done
while 迴圈
只要該條件為 true
,while 迴圈測試一個條件,並遍歷序列的命令。被檢測的條件跟 if.. then
中使用的 primary 並沒有差別。所以 while 迴圈
看起來會像是:
while [[ condition ]]
do
# statements
done
就像 for 迴圈一樣,如果我們想要將 do 和條件寫成一行的話,我們必須在 do 之前加上分號
。
一個處理範例如下所示:
#!/bin/bash
# 0 到 9 每個數字的平方。
x=0
while [[ $x -lt 10 ]]; do # x 小於 10。
echo $(( x * x ))
x=$(( x + 1 )) # x 加 1。
done
until 迴圈
until
迴圈和 while
迴圈完全相反的。它會像 while 一樣檢查條件,迴圈持續到表達式為 False 停止:
until [[ condition ]]; do
#statements
done
select 迴圈
select 迴圈幫助我們組織一個使用者功能表。它和 for 迴圈語法幾乎相同:
select answer in elem1 elem2 ... elemN
do
# statements
done
select 會將 elem1..elemN
跟隨著序號列印出來提示使用者。然後將選單的提示文字設定在 PS3 當中。在上面的例子當中,使用者的輸入會存於 answer 中。如果 answer 是介於 1..N 的數字,那敘述句就會被執行且 select 會因為 do-loop 的關係而循環,因此我們應該使用 break 來避免無窮迴圈。
一個處理範例如下所示:
#!/bin/bash
PS3="Choose the package manager: "
select ITEM in bower npm gem pip
do
echo -n "Enter the package name: " && read PACKAGE
case $ITEM in
bower) bower install $PACKAGE ;;
npm) npm install $PACKAGE ;;
gem) gem install $PACKAGE ;;
pip) pip install $PACKAGE ;;
esac
break # 避免無窮迴圈。
done
在這個範例中,詢問使用者想要使用哪套 package manager 安裝套件,並詢問我們需要安裝什麼套件,最後會執行安裝:
如果我們執行,我們可以得到:
$ ./my_script
1) bower
2) npm
3) gem
4) pip
Choose the package manager: 2
Enter the package name: bash-handbook
<installing bash-handbook>
迴圈控制
在某些情況下,我們需要在正常結束前或跳過某次迭代來結束迴圈。在這個情況下,我們可以使用 shell 內建的 break 和 continue 語句。這兩個語法都可以在前述的每一種迴圈執行。
break 語句被用於在迴圈結束之前,退出目前迴圈。我們之前已經看過了。
continue 語句跳過一個迭代。我們可以像這樣使用它:
for (( i = 0; i < 10; i++ )); do
if [[ $(( i % 2 )) -eq 0 ]]; then continue; fi
echo $i
done
如果我們執行上方的範例,我們可以列印出 0 到 9 間的奇數。
函式
在 script 中,就像任何其他程式語言一樣,我們有能力定義 function 和呼叫 function。在 Bash 中的 function 是一個程式碼區塊,但是有些不同。
在 Bash 中的 function 就是將一堆指令包裝成一個 name,而這個 name 就是 function name,呼叫一個 function 就像在其他程式語言一樣,你只要執行 function 的名稱,function 就會被 調用。
我們可以用這種方式宣告我們的 function:
my_func () {
# statements
}
my_func # 呼叫 my_func。
我們在調用 function 前,必須要先宣告。
Function 可以接受參數並回傳一個結果 — exit code。在 function 內,與非互動模式下的 script 參數處理方式相同 — 使用位置參數。結果代碼可以使用 return 命令來 回傳。
以下的 function 需要一個名稱並回傳 0,表示成功執行。
# 帶參數的 function。
greeting () {
if [[ -n $1 ]]; then
echo "Hello, $1!"
else
echo "Hello, unknown!"
fi
return 0
}
greeting Denys # Hello, Denys!
greeting # Hello, unknown!
我們已經討論過 exit codes。return 命令不帶任何最後一個執行命令 exit code 的回傳參數。上面的範例,return 0 會回傳一個成功的 exit code 0。
Debug
shell 提供了 debug script 的工具。如果我們想要在 debug 模式執行 script,我們在 script 的 shebang 使用一個特別的選項:
#!/bin/bash options
這個選項是改變 shell 行為的設定。下面是一些可能對你有幫助的選項清單:
簡寫 | 名稱 | 描述 |
---|---|---|
-f | noglob | 禁止檔案名 expansion(globbing) |
-i | interactive | Script 執行在互動模式 |
-n | noexec | 讀取命令,但不執行它們(確認語法是否正確) |
pipefail | 如果任何命令失敗使 pipeline 失敗,不只是最後一個命令失敗 | |
-t | — | 在第一個命令完成後退出 |
-v | verbose | 在執行前,列印每個命令到 stderr |
-x | xtrace | 在執行前,列印每個命令和他的參數到 stderr |
例如,我們有個 script 有 -x
選項像是:
#!/bin/bash -x
for (( i = 0; i < 3; i++ )); do
echo $i
done
這將會列印變數的值到 stdout 以及其他有用的資訊:
$ ./my_script
+ (( i = 0 ))
+ (( i < 3 ))
+ echo 0
0
+ (( i++ ))
+ (( i < 3 ))
+ echo 1
1
+ (( i++ ))
+ (( i < 3 ))
+ echo 2
2
+ (( i++ ))
+ (( i < 3 ))
有時候我們需要 debug script 某個部份。在這種情況下使用 set 命令是很方便的,使用 - 啟用選項,+ 停用選項。
#!/bin/bash
echo "xtrace is turned off"
set -x
echo "xtrace is enabled"
set +x
echo "xtrace is turned off again"
interupt
Ctrl-C
sends SIGINT, a signal that causes the process to terminate.Ctrl-Z
sends SIGTSTP, a signal this causes the process to suspend execution. In this case, it is resumable - try executing a command that will take a while and press Ctrl-Z; you’ll see something in the lines ofCtrl-D
鍵盤輸入結束(End Of File, EOF 或 End Of Input)
Mount
refer Linux 磁碟與檔案系統管理
顯示所有 partitions
cat /proc/partitions
refer Linux 下 /proc 中的重要訊息
/proc 並不是一個真正的檔案系統,不佔據任何硬碟空間,但是你可以"好像"使用真正的檔案系統一般,瀏覽該目錄下的檔案內容。
/proc 記錄Linux系統程序(process)執行狀況,真正內容並非存在於硬碟,而是由核心根據系統及process狀況,透過這個虛擬的檔案系統,回應相關的檔案及目錄的存取。
/proc的好處是提供一個簡易且統一的系統資訊擷取管道,管理者及程式設計者都可由此獲得必要且重要的系統即時資訊。
系統相關的運作資訊幾乎都可以透過/proc系的"檔案"得到答案。
cat /proc/meminfo
(記憶體資訊)(可使用 free 來查閱。)cat /proc/kcore
(這個就是記憶體的大小,好大對吧,但是不要讀他。)cat /proc/uptime
(使用 uptime 的時候會出現的資訊。)cat /proc/loadavg
(還記得 top 以及 uptime 吧?上頭的三個平均數值就是記錄在此。)cat /proc/swaps
(顯示 Swap 資訊)(到底系統掛載入的記憶體在哪裡?使用掉的 partition 就記錄在此。)cat /proc/partitions
(顯示所有 partitions)cat /proc/filesystems
(目前系統已經載入的檔案系統。)cat /proc/devices
(這個檔案記錄了系統各個主要裝置的主要裝置代號,與 mknod 有關。)cat /proc/mounts
(系統已經掛載的資料,就是用 mount 這個指令呼叫出來的資料。)cat /proc/modules
(目前我們的 Linux 已經載入的模組列表,也可以想成是驅動程式。)cat /proc/interrupts
(目前系統上面的 IRQ 分配狀態。)cat /proc/ioports
(目前系統上面各個裝置所配置的 I/O 位址。)cat /proc/pci
(PCI 匯流排上面每個裝置的詳細資料)(可使用 lspci 來查閱。)cat /proc/bus
(一些匯流排的裝置,還有 USB 的裝置也記錄在此。)cat /proc/cpuinfo
(顯示 CPU 資訊。)cat /proc/version
(顯示 Linux 版本)(可使用uname -a
來查閱。)cat /proc/cmdline
(載入 kernel 時所下達的相關參數。查閱此檔案,可瞭解系統是如何啟動的。)