shell知識點小結2
$? 前一命令退出狀態,0表示成功
$$ shell程式ID
PPID 父程式ID
LANG 當前Locale的預設名稱,其他LC_*變數會覆蓋此值
LC_ALL 當前Locale名稱,會覆蓋LANG和其他LC_*
PS1(prompt sign) 當前提示字串
exit 終止整個指令碼的執行
return 退出當前函式並返回數字 return N或者$?
shift
shift 3表示原來的$4現在變成$1,原來的$5現在變成$2等等,原來的$1、$2、$3丟棄,$0不移動。不帶引數的shift命令相當於shift 1
getopts
http://blog.sina.com.cn/s/blog_674b5aae0100o2nz.html
getopts一般格式為:getopts option_string variable
指定變數取值,即在option_string中將一個冒號放在選項後;但當冒號放在第一個選項時,代表其作為一個選項存在;
具體含意為如果某選項設定為取值傳遞但卻未傳值時,返回該選項後的資訊,若未新增此選項則預設系統也會返回一個錯誤資訊,只是錯誤資訊提示並不明確。
如getopts ahfvc: option表明選項a、h、f、v可以不加實際值進行傳遞,而選項c必須取值。使用選項取值時,必須使用變數OPTARG儲存該值。
在使用getopts命令的時候,shell會自動產生兩個變數OPTIND和OPTARG。
OPTIND初始值為1,其含義是下一個待處理的引數的索引。只要存在,getopts命令返回true,所以一般getopts命令使用while迴圈;
OPTARG是當getopts獲取到其期望的引數後存入的位置。
#!/bin/bash
if [ $# -lt 1 ]
then
echo "there is no option";
else
while getopts ":Iti:s:v" opt;
do
case $opt in
I)echo "option is I "
;;
t)echo "option is t "
;;
i)ii=$OPTARG;echo "option is i,the value is $ii";
;;
s)ss=$OPTARG;echo "option is s ,the value is $ss";
;;
v)echo "option is v \n";
;;
:)
echo ">>> Error: '-$OPTARG' requires an argument"
;;
?)paralist=-1;
echo ">>> Error: '-$OPTARG' not supported,please input valid argument [Itisv]"
;;
esac
done
fi
下面給出幾個執行的例子:
(1)sh datediff.sh -i 1 -I -v
option is i,the value is 1
option is I
option is v \n
(2)sh datediff.sh -s -i 1
option is s, the value is -i //取s選項後的值
(3)sh datediff.sh -s //選項中有前置冒號
>>> Error: '-s' requires an argument
sh datediff.sh -s //去除選項中的前置冒號後的輸出
datediff.sh: option requires an argument -- s
>>> Error: '-' not supported,please input valid argument [Itisv]
subshell和程式碼塊
前者由()包圍,後者則是{};
subshell可以在行上任何位置執行,會建立一個新程式,除此之外,呼叫&提交後臺作業/管道,都會建立新程式;
程式碼塊只能位於換行字元、分號或關鍵字之後,與主指令碼共享狀態;
subshell模擬並行運算
#!/bin/bash
for i in $(seq 1 1000)
do
( Generating random numbers here , sorting and outputting to file$i.txt ) &
if (( $i % 10 == 0 )); then wait; fi # Limit to 10 concurrent subshells.
done
wait
tee
tee命令會從標準輸入讀取資料,將其內容輸出到標準輸出裝置,同時又可將內容儲存成檔案。例如有如下的指令碼片段,其作用是獲取本機的ip地址:
ipaddr=`/sbin/ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | cut -d : -f3 | awk '{print $1}'`
#注意=號後面的整句是用反引號(數字1鍵的左邊那個鍵)括起來的。
echo $ipaddr
執行這個指令碼,實際輸出的卻不是本機的ip地址,而是廣播地址,這時我們可以藉助tee命令,輸出某些中間結果,將上述指令碼片段修改為:
ipaddr=`/sbin/ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | tee temp.txt | cut -d : -f3 | awk '{print $1}'`
echo $ipaddr
之後,將這段指令碼再執行一遍,然後檢視temp.txt檔案的內容:
$ cat temp.txt
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0
我們可以發現中間結果的第二列(列之間以:號分隔)才包含了IP地址,而在上面的指令碼中使用cut命令擷取了第三列,
故我們只需將指令碼中的cut -d : -f3改為cut -d : -f2即可得到正確的結果
trap
trap命令用於捕獲指定的訊號並執行預定義的命令。
其基本的語法是:
trap 'command' signal
其中signal是要捕獲的訊號,command是捕獲到指定的訊號之後,所要執行的命令。
可以用kill –l命令看到系統中全部可用的訊號名,捕獲訊號後所執行的命令可以是任何一條或多條合法的shell語句,也可以是一個函式名。
shell指令碼在執行時,會產生三個所謂的“偽訊號”,之所以稱之為“偽訊號”是因為這三個訊號是由shell產生的,而其它的訊號是由作業系統產生的
表 1. shell偽訊號
訊號名 何時產生
EXIT 從一個函式中退出或整個指令碼執行完畢
ERR 當一條命令返回非零狀態時(代表命令執行不成功)
DEBUG 指令碼中每一條命令執行之前
透過捕獲EXIT訊號,我們可以在shell指令碼中止執行或從函式中退出時,輸出某些想要跟蹤的變數的值,並由此來判斷指令碼的執行狀態以及出錯原因,其使用方法是:
trap 'command' EXIT 或 trap 'command' 0
透過捕獲ERR訊號,我們可以方便的追蹤執行不成功的命令或函式,並輸出相關的除錯資訊,
以下是一個捕獲ERR訊號的示例程式,其中的$LINENO是一個shell的內建變數,代表shell指令碼的當前行號。
$ cat -n exp1.sh
1 ERRTRAP()
2 {
3 echo "[LINE:$1] Error: Command or function exited with status $?"
4 }
5 foo()
6 {
7 return 1;
8 }
9 trap 'ERRTRAP $LINENO' ERR
10 abc
11 foo
其輸出結果如下:
$ sh exp1.sh
exp1.sh: line 10: abc: command not found
[LINE:10] Error: Command or function exited with status 127
[LINE:11] Error: Command or function exited with status 1
在除錯過程中,為了跟蹤某些變數的值,我們常常需要在shell指令碼的許多地方插入相同的echo語句來列印相關變數的值,這種做法顯得煩瑣而笨拙。
而透過捕獲DEBUG訊號,我們只需要一條trap語句就可以完成對相關變數的全程跟蹤。
以下是一個透過捕獲DEBUG訊號來跟蹤變數的示例程式:
$ cat –n exp2.sh
1 #!/bin/bash
2 trap 'echo “before execute line:$LINENO, a=$a,b=$b,c=$c”' DEBUG
3 a=1
4 if [ "$a" -eq 1 ]
5 then
6 b=2
7 else
8 b=1
9 fi
10 c=3
11 echo "end"
其輸出結果如下:
$ sh exp2.sh
before execute line:3, a=,b=,c=
before execute line:4, a=1,b=,c=
before execute line:6, a=1,b=,c=
before execute line:10, a=1,b=2,c=
before execute line:11, a=1,b=2,c=3
end
從執行結果中可以清晰的看到每執行一條命令之後,相關變數的值的變化。
eval
http://www.cnblogs.com/friedwm/archive/2012/04/06/2435171.html
eval 相當於一個引數替換器,它會把所有 $開頭的變數 進行求值替換,然後把替換後的結果當作一條命令來執行
#!/bin/bash
PARA="hello world my friend"
function Process()
{
temp=$(eval echo \$$1 | cut -d ' ' -f 2-) #1
eval $1=\$temp #2
}
Process PARA
echo $PARA
[oracle@ ~]$ sh tesh.sh
world my friend
說明:
#1處eval先將它後面所有變數求值,$1==PARA,然後再執行 echo $PARA | cut -d ' ' -f 2-,得到處理後的值,臨時存於temp。
#2處,先進行替換,替換結果為: PARA=$temp,再執行這條命令,結果複製回源引數。
http://doudouclever.blog.163.com/blog/static/175112310201252111104169/
set 11 22 33 44
如果要輸出最近一個引數,即44,可以使用如下命令,
echo $4
但是如果我們不知道有幾個引數的時候,要輸出最後一個引數,大家可能會想到使用$#來輸出最後一個引數,
如果使用命令:
echo "\$$#"
則得到的結果是 $4,而不是我們想要的44。這裡涉及到一個變數間接引用的問題,我們的本意是輸出 $4,預設情況下,命令後忽略變數間接引用的情況。
這時候,就可以使用eval命令。
eval echo "\$$#"
得到的結果為44
source、exec與system
http://www.cnblogs.com/zhaoyl/archive/2012/07/07/2580749.html
bash shell的命令分為兩類:外部命令和內部命令;
外部命令是透過系統呼叫或獨立的程式實現的,如sed、awk等等;
內部命令是由特殊的檔案格式(.def)所實現,如cd、history、exec等等。
有兩種方法執行shell scripts,一種是新產生一個shell,然後執行相應的shell scripts;一種是在當前shell下執行,不再啟用其他shell。
新產生一個shell然後再執行scripts的方法是在scripts檔案開頭加入以下語句
#!/bin/sh
一般的script檔案(.sh)即是這種用法。這種方法先啟用新的sub-shell(新的子程式),然後在其下執行命令。
另外一種方法就是上面說過的source命令,不再產生新的shell,而在當前shell下執行一切命令。
source命令即點(.)命令。
在bash下輸入man source,找到source命令解釋處,可以看到解釋”Read and execute commands from filename in the current shell environment and …”。
從中可以知道,source命令是在當前程式中執行引數檔案中的各個命令,而不是另起子程式(或sub-shell)。
exec:
在bash下輸入man exec,找到exec命令解釋處,可以看到有”No new process is created.”這樣的解釋,這就是說exec命令不產生新的子程式。那麼exec與source的區別是什麼呢?
1. 系統呼叫exec是以新的程式去代替原來的程式,但程式的PID保持不變。因此,可以這樣認為,exec系統呼叫並沒有建立新的程式,只是替換了原來程式上下文的內容。
原程式的程式碼段,資料段,堆疊段被新的程式所代替。
一個程式主要包括以下幾個方面的內容:
(1)一個可以執行的程式
(2) 與程式相關聯的全部資料(包括變數,記憶體,緩衝區)
(3)程式上下文(程式計數器PC,儲存程式執行的位置)
2. exec是一個函式簇,由6個函式組成,分別是以excl和execv打頭的。
執行exec系統呼叫,一般都是這樣,用fork()函式新建立一個程式,然後讓程式去執行exec呼叫。
我們知道,在fork()建立新程式之後,父進各與子程式共享程式碼段,但資料空間是分開的,但父程式會把自己資料空間的內容copy到子程式中去,還有上下文也會copy到子程式中去。
而為了提高效率,採用一種寫時copy的策略,即建立子程式的時候,並不copy父程式的地址空間,父子程式擁有共同的地址空間,
只有當子程式需要寫入資料時(如向緩衝區寫入資料),這時候會複製地址空間,複製緩衝區到子程式中去。從而父子程式擁有獨立的地址空間。
而對於fork()之後執行exec後,這種策略能夠很好的提高效率,如果一開始就copy,那麼exec之後,子程式的資料會被放棄,被新的程式所代替。
3. exec與system的區別
(1) exec是直接用新的程式去代替原來的程式執行,執行完畢之後不回到原先的程式中去。
(2) system是呼叫shell執行你的命令,system=fork+exec+waitpid,執行完畢之後,回到原先的程式中去。繼續執行下面的部分。
總之,如果你用exec呼叫,首先應該fork一個新的程式,然後exec. 而system不需要你fork新程式,已經封裝好了。
exec命令在執行時會把當前的shell process關閉,然後換到後面的命令繼續執行。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25462274/viewspace-2148955/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- shell知識點小結1
- 【JAVA】- 知識點小結Java
- promise知識點小結Promise
- HTTP知識點小結HTTP
- makefile 知識點小結
- node知識點小結(一)
- awk知識點小結1
- 雜湊表知識點小結
- 總結的小知識點(一)
- oracle事務知識點小結Oracle
- shell相關知識點
- 前端知識點小結--node、express、mongodb前端ExpressMongoDB
- RxJava 知識梳理(3) RxJava2 基礎知識小結RxJava
- java小知識點Java
- js小知識點JS
- 小知識點1
- 前端小知識點前端
- mongo 小知識點Go
- javascript小知識點JavaScript
- PHP小知識點PHP
- 2021/06/02知識點小結
- 微信小程式開發知識點總結微信小程式
- 浮點數小知識點
- Flex知識小結Flex
- 小知識總結
- c語言常用小知識點總結1C語言
- Silverlight 常用小知識點總結
- CSS小知識點一CSS
- ElasticSearch知識點小記Elasticsearch
- VEEAM的小知識點
- linux知識知識點總結Linux
- 知識點總結
- oracle小知識點1--varchar2的長度Oracle
- python中shell執行知識點Python
- Vue重要知識小結Vue
- 硬碟知識小總結硬碟
- 儲存知識小結
- 簡單小結密碼學入門知識點密碼學