linux命令行 基础,Linux命令行基础,关于Bash需要知道的一些常识
介紹
Linux越來越重要,對(duì)于開發(fā)者來說學(xué)習(xí)必要的bash技術(shù)必不可少,對(duì)運(yùn)維來說更是如此。學(xué)習(xí)shell可以參考很多學(xué)習(xí)材料和圖書,比如ChinaUnix論壇網(wǎng)中人大哥總結(jié)的《Shell十三問》的帖子,《ABS 指導(dǎo)》(《Advanced Bash-Scripting Guide》),《linux shell腳本攻略》等大家可以參考。本文蟲蟲給大家一些常用的shell技巧分享給大家,希望可以對(duì)大家有所幫助。
引導(dǎo)順序
首先我們要說下bash腳本的啟動(dòng),Linux中系統(tǒng)初始化都是按照一定順序加載各個(gè)文件初始化腳本(Shell腳本)。腳本所在文件啟動(dòng)順序很重要,下面這個(gè)圖顯示了Linux系統(tǒng)個(gè)初始化腳本和環(huán)境變量的加載順序,包括了bash、sh和zsh等常見的shell。
bash的加載遵循上圖,從上到下順序執(zhí)行加載,尤其要注意non-login、非交互(上面藍(lán)色線)執(zhí)行,它不會(huì)加載很多腳本,比如/etc/profile(總profile),/etc/bash.bashrc(總basrc),和個(gè)人的.profile, .bash_profie,.bash_login和.bashrc等。所以如果你腳本處于這樣環(huán)境下(比如cron腳本),你就要在腳本中自我設(shè)置一些環(huán)境變量。這樣就可以避免由于環(huán)境變量導(dǎo)致的一些莫名其妙的的問題,比如寫的好腳本為什么登陸就可以執(zhí)行,放到cron里面自動(dòng)執(zhí)行就不行。
輸入/輸出和重定向
我們知道Linux下一切皆文件,包括硬件設(shè)備,其中三個(gè)特殊的文件句斌,標(biāo)準(zhǔn)輸入(stdin)、標(biāo)準(zhǔn)輸出(stdout)和標(biāo)準(zhǔn)錯(cuò)誤(stderr),其句柄號(hào)為三個(gè)整數(shù)0,1和2。
< :用于重定向改變標(biāo)準(zhǔn)輸入(stdin)。
0< :0< 和
<< :輸入一段文本,直到讀到<
> :用于重定向改變標(biāo)準(zhǔn)輸出(stdout)。
1> :1> 和>一樣 ,> 默認(rèn)的FD為1。
2> :改變標(biāo)準(zhǔn)錯(cuò)誤(stderr)。
>> :重定向輸出到文件,追加到文件末尾。
set -o noclobber :設(shè)置 > 不能覆蓋已經(jīng)存在的文件。
set +o noclobber :這支 > 可以覆蓋已經(jīng)存在的文件。
>| :設(shè)置set -o noclobber后,使用 >| 可以臨時(shí)覆蓋已經(jīng)存在的文件。
/dev/null 和 /dev/zero
這兩個(gè)文件是兩個(gè)比較特殊設(shè)備。/dev/null,或稱空設(shè)備,它會(huì)丟棄一切寫入它的數(shù)據(jù),但是讀取它則會(huì)拋出錯(cuò)誤。在shell中常用它來表示放棄執(zhí)行的結(jié)果(或者錯(cuò)誤),這樣只關(guān)注于程序執(zhí)行,比如在cron中的任務(wù),輸出和錯(cuò)誤都沒有意義。
command > /dev/null
可以將stdout、stderr都重定向輸出到/dev/null:
command > /dev/null 2>&1 或者
command &> /dev/null
command >& /dev/null
/dev/zero 設(shè)備用于提供無(wú)限制的空null內(nèi)供讀取。當(dāng)讀取該設(shè)備(文件)時(shí)候,它會(huì)提供無(wú)限的空字符 null。我們可以從/dev/zero 讀取任意數(shù)量的 null 字符。和 /dev/null 不同,/dev/zero主要用于作為null數(shù)據(jù)源供讀取,當(dāng)然/dev/zero也支持寫入,可以用做數(shù)據(jù)黑洞,。
/dev/zero主要用途是提供字符流來初始化數(shù)據(jù)存儲(chǔ),也就是使用空字符覆蓋目標(biāo)數(shù)據(jù)。還可以用來一個(gè)特定大小的空白文件。
比如用空白文件覆蓋分區(qū),刪除分區(qū)的數(shù)據(jù)可以用(慎用!):
dd if=/dev/zero of=/dev/
創(chuàng)建一個(gè)一個(gè)1M的文件,可以使用
dd if=/dev/zero of=cc count=1024 bs=1024
``和$()
反引號(hào)(Tab鍵上面的鍵)和$(),兩者基本上類似,在shell中都表示執(zhí)行命令。
echo`ls`
echo $(ls)
最常用的用法是將一些命令結(jié)果輸出傳遞個(gè)其他命令作為參數(shù)。比如要查詢當(dāng)前目錄和子目錄下所有PHP中的包含"eval"函數(shù)(似疑木馬),可以用下面命令:
grep eval `find -type f -name "*.php"`
兩者主要的區(qū)別在于嵌套更簡(jiǎn)單。
對(duì)``來說要實(shí)現(xiàn)嵌套就要增加很多反斜杠來轉(zhuǎn)義,比如:
echo `echo \`echo \\\`echo hello,Chongchong\!\\\`\``
而用$()就簡(jiǎn)介的多了:
echo $(echo $(echo $(echo hello,Chongchong\!)))
這是個(gè)很有意義的操作符,他有點(diǎn)類似于$(),而對(duì)括弧中命令的輸出重用。但是在
比如我們要執(zhí)行下面一些例子
grep keys file1> /tmp/a
grep keys file2> /tmp/b
diff /tmp/a /tmp/b
用
diff
引用
bash引用比較復(fù)雜,我們先從簡(jiǎn)單的開始。
首先,引號(hào)中的變量:
A="123"
echo "$A"
echo "$A"
這個(gè)結(jié)果很簡(jiǎn)單,雙引號(hào)會(huì)解釋變量,輸出為其值123,而單引號(hào)不會(huì)解釋,輸出為$A。
下面三個(gè)echo 都會(huì)打印啥呢?
mkdir -p tmp
cd tmp
touch a
echo *
echo "*"
echo "*"
Bash中還有很多引用方式的快捷操作符,其中一些可以極大的提高我們的工作效率
!$
表示重復(fù)最后一個(gè)命令的最后一個(gè)參數(shù)。如果你正在處理一個(gè)文件,通過該操作符可以在命令后重新引入?yún)?shù),從而節(jié)省大量重復(fù)輸入。
grep xxx /long/path/to/some/file/or/other.txt
vim !$
!:1-$
該操作符,更有意思,它獲取上一個(gè)命令的所有參數(shù)并將它們引入。所以:
grep isthere /long/path/to/some/file/or/other.txt
egrep !:1-$
fgrep !:1-$
!表示"查看上一個(gè)命令",:是一個(gè)分隔符,1表示"取第一個(gè)單詞", -表示范圍"直到",$表示"最后一個(gè)單詞"。
我們可以用!*實(shí)現(xiàn)同樣的目的。但是基于上面規(guī)則,我們就可以隨意定制參數(shù)的范圍了。比如如使用!:2-3。
:h
如果把該操作符放在一個(gè)文件名后面,它會(huì)刪除文件夾以外的文件名稱。比如:
grep XXX /long/path/to/some/file/or/other.txt
cd !$:h
通配符和正則表達(dá)式
通配符合正則表達(dá)式中都會(huì)用*,看起來很相似,但它們差異很大
請(qǐng)解釋下面這個(gè)命令:
rename -n "s/(.*)/HEAD$1/" *
上面兩個(gè)星號(hào)表達(dá)意思完全不同:
第一個(gè)由于用單引號(hào)括住,shell不會(huì)對(duì)其解釋,作為參數(shù)都提交給rename命令。rename會(huì)對(duì)其解釋 ,而s/(.*)/HEAD$1/是一個(gè)正則替換。在正則表達(dá)式中 *表示對(duì)前面字符的0個(gè)或者多個(gè)模式。.表示一個(gè)字符,所以.*表示匹配所有內(nèi)容;()表示對(duì)括住內(nèi)容進(jìn)行引用,在替換后面部分用\1或者$1表示它。
第二個(gè)會(huì)被shell解釋,*在shell中表示通配符,表示當(dāng)前工作文件夾中所有文件的列表替換。
所以整個(gè)命令表示將文件下所有文件名都增加上HEAD 前綴。請(qǐng)嘗試下面兩個(gè)命令:
ls *
ls .*
第二個(gè)看起來更像是一個(gè)正則表達(dá)式,但是實(shí)際是什么樣的呢?請(qǐng)你嘗試對(duì)輸出解釋下。
條件語(yǔ)句,[和[[
請(qǐng)嘗試執(zhí)行一下語(yǔ)句會(huì)輸出什么?
if grep XXX /dev/null
then
echo Chongchong
else
echo lo
fi
grep的返回代碼使得像這樣的代碼更直觀地作為其作為退出狀態(tài)解釋時(shí)候帶來的副作用。
下面兩個(gè)語(yǔ)句的輸出呢?
if [ $(grep XXX /dev/null) = "" ]
then
echo -n Chongchong
else
echo -n lo
fi
if [[ $(grep XXX /dev/null) = "" ]]
then
echo -n Chongchong
else
echo -n lo
fi
[是測(cè)試的原始形式,然后[[引入了更靈活和直觀的方式。在上面的第一個(gè)if塊中,if語(yǔ)句因?yàn)?(grep XXX /dev/null)被評(píng)估為空,導(dǎo)致這種比較:[=""],這會(huì)拋出錯(cuò)誤,針對(duì)這種情況就需要使用[[]]來避免這種異常,還有一個(gè)常用的技巧是使用:
if [x$(grep XXX /dev/null)="x"]
所以,如果命令沒有返回任何內(nèi)容,它仍然可以正常運(yùn)行,而不會(huì)拋出異常,中斷執(zhí)行。
退出狀態(tài)碼
我們知道每次shell執(zhí)行,推出是都會(huì)給shell一個(gè)狀態(tài)碼。
如果命令執(zhí)行正常,則會(huì)返回給shell狀態(tài)碼0。如果不成功,則會(huì)得到一個(gè)非零代碼,用來表具體錯(cuò)誤的種類,其中 1表示"一般錯(cuò)誤",還有其他更多信息,可以在程序中具體定義。狀態(tài)碼,可以通過$?查看。但有些命令會(huì)設(shè)置有特殊設(shè)置比如grep,請(qǐng)嘗試下面的命令:
grep XXX /dev/null
echo $?
grep中使用退出代碼來指示它是否匹配。
set 語(yǔ)句
Bash中也提供了可配置的選項(xiàng),可以即時(shí)設(shè)置環(huán)境變量等。
set -e
如果任何命令返回非零退出狀態(tài),則從腳本退出。
set -X
會(huì)輸出在運(yùn)行時(shí)運(yùn)行的命令。
所以腳本可能會(huì)使用這樣的開頭:
#!/bin/bash
set -e
set -x
grep XXX /dev/null
echo $?
getopts
如果要寫一個(gè)較大的程序,涉及的輸入比較復(fù)雜,則需要使用getopts來簡(jiǎn)化你的工作,用他來幫你做輸入和參數(shù)處理的工作,比如下面一個(gè)例子:
getopts后面跟的是參數(shù)列表字符串,每個(gè)字母表示一個(gè)選項(xiàng),帶:選項(xiàng)表示選項(xiàng)還會(huì)有值,比如上面例子中對(duì)應(yīng)的-j /home/soft/java 和-m /home/soft/maven 。而getopts字符串中沒有跟隨:的字母就是開關(guān)型選項(xiàng),不需要指定值,等同于true/false,只要帶上了這個(gè)參數(shù)就是true。
getopts是shell內(nèi)部命令,可以在shell腳本中直接使用,同時(shí)shell也支持一個(gè)外部命令getopt有很多發(fā)行版本也都自帶。詳細(xì)可以搜索參考具體文檔,本文不在贅述。
總結(jié):
拋磚引玉,本文中列出了shell中一些常見的技巧和容易混淆的知識(shí)點(diǎn),希望能對(duì)大家有所幫助,如果大家有更好的想法技巧也可以一起分享出來,一起參考學(xué)習(xí)。
總結(jié)
以上是生活随笔為你收集整理的linux命令行 基础,Linux命令行基础,关于Bash需要知道的一些常识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php上传同一张图片,两种php实现图片
- 下一篇: linux 其他常用命令