第11章 認(rèn)識與學(xué)習(xí) bash
標(biāo)簽: 鳥哥的linux私房菜
[toc]
11.1認(rèn)識bash這個shell
什么是shell
只要能夠操作應(yīng)用程序的接口都能夠稱為shell。狹義的shell指的是命令行方面的軟件,包括bash等。廣義的shell則包括 圖形化界面的軟件,因為圖形界面其實也能夠操作各種應(yīng)用程序來調(diào)用內(nèi)核工作。
shell是Linux的任督二脈
各家的distributions使用的bash幾乎都是一樣的;
聯(lián)機(jī)時命令行界面的傳輸速度比較快,而且不容易出現(xiàn)斷線或者信息外流的問題;
可以用通過shell提供的數(shù)據(jù)流重定向以及管道命令 迅速分析日志信息;
etc
bash for Bourne Again SHell,這個Shell是 Bourne Shell的增強(qiáng)版本,也是的基于GNU的架構(gòu)下發(fā)展出來的。
/etc/shells這個文件會記錄系統(tǒng)上合法的shell
bash shell的功能
- 命令記憶能力
- 默認(rèn)記憶1000個
- 命令記錄在主文件夾的.bash_history(內(nèi)存內(nèi))中,~/.bash_history(注銷后)記錄的是前一次登錄所執(zhí)行過的命令。
- 有一個隱憂,被黑客入侵,他只要追蹤曾經(jīng)執(zhí)行過的命令。比如直接輸入MySQL的密碼在命令行里
- 命令與文件補(bǔ)全功能([Tab]鍵的好處)
- 命名別名設(shè)置功能(alias)
- 命令行中輸入
alias就可以知道目前的命令別名有哪些 - 在命令行可以直接執(zhí)行
alias ll='ls -al'來設(shè)置別名
- 命令行中輸入
- 作業(yè)控制、后臺、前臺控制
- 將作業(yè)丟到后臺中執(zhí)行
- 可以在單一登錄的環(huán)境中達(dá)到多任務(wù)的目的
- 不擔(dān)心不小心使用了[Ctrl]+C 中斷了進(jìn)程
-
程序腳本
- 類似DOC下的所謂的“批處理文件”;將需要執(zhí)行的連續(xù)命令寫成一個文件
-
通配符
- 星號“*”
bash shell的內(nèi)置命令 : type
type [-tpa] name
- type: 不加任何參數(shù)時,type會顯示name是外部命令還是bash內(nèi)置命令
- -t:type會將name以下面這些字眼顯示出它的意義:file(外部命令),alias(命令別名所設(shè)置的名稱),builtin(bash內(nèi)置的命令功能)
- -p:如果 后面接的name為外部命令才會顯示完整文件名
- -a:會由PATH變量定義的路徑中,將所有含nam的命令都列出來,包含alias
命令的執(zhí)行
[Enter]具有“開始執(zhí)行”的功能
可以被反斜杠“"轉(zhuǎn)義成換行
11.2shell的變量功能
環(huán)境變量;變量的使用與設(shè)置
Linux是一個多用戶,多任務(wù)的環(huán)境,bash如何得知你的郵件信箱是哪一個問價
什么是變量
用一個簡單的“字眼”來代替另一個比較復(fù)雜或者是比較容易變動的數(shù)據(jù)。這最大的好處就是“方便”。
-
變量的可變性與方便性
- 郵箱(mail)通過MAIL這個變量來進(jìn)行訪問,MAIL這個變量和登錄用戶的登錄名掛鉤
-
影響bash環(huán)境操作的變量
- 環(huán)境變量
-
腳本程序設(shè)計(shell script)的好幫手
- 變量相當(dāng)于配置文件,一改全改
變量的顯示與設(shè)置:echo, unset
- 變量的顯示:echo
echo $PATH
echo ${PATH}
當(dāng)一個變量名稱未被設(shè)置是,默認(rèn)的內(nèi)容是“空”的
- 變量的設(shè)置規(guī)則
1.變量與變量內(nèi)容以一個“=”來連接,如下
myname=Rockhan
2.等號兩邊不能直接接空格符
3.變量名稱只能是英文與數(shù)字,但開頭的字符不能是數(shù)字
4.變量內(nèi)容若有空格符可使用雙引號"或單引號'(英文格式),將變量內(nèi)容結(jié)合起來,需注意
4.1雙引號內(nèi)的特殊字符如$等,可以保持原來的特性
4.2單引號內(nèi)的特殊字符則僅為一般字符
5.可以用轉(zhuǎn)義字符將特殊字符變成一般字符
環(huán)境變量的功能
- 可以利用兩個命令查閱環(huán)境變量:env 與 export
- set可以查看所有變量
- $本身也是個變量,代表的是這個shell的線程代號,即所謂的PID(Process ID)可以用
echo $$命令查看 - ?,上個執(zhí)行命令的回傳碼。成功執(zhí)行為0,不成功非0
- export:自定義變量轉(zhuǎn)成環(huán)境變量(兩者的差別在于是否會被子進(jìn)程所繼續(xù)引用),子進(jìn)程僅會繼承父進(jìn)程的環(huán)境變量,不會繼承父進(jìn)程的自定義變量。
影響顯示結(jié)果的語系變量(locale)
loacale -a查詢Linux支持哪些語系
常見的兩種中文編碼:big5,utf-8
loacale命令顯示所有與語系有關(guān)的變量數(shù)據(jù)。
環(huán)境變量LANG是主語言的環(huán)境
變量的有效范圍
為什么環(huán)境變量的數(shù)據(jù)可以被子進(jìn)程所引用呢?這是因為內(nèi)存配置的關(guān)系。理論上是這樣的:
- 當(dāng)啟動一個shll,操作系統(tǒng)會分配一記憶塊給shell使用,此內(nèi)存內(nèi)的變量可讓子進(jìn)程取用;
- 若父進(jìn)程利用export功能,可以讓自定義變量的內(nèi)容寫到上述的記憶塊當(dāng)中(環(huán)境變量);
- 當(dāng)加載另一個shell時(即啟動子進(jìn)程離開父進(jìn)程),子shell可以將父shell的環(huán)境變量所在的記憶塊導(dǎo)入自己的環(huán)境變量塊當(dāng)中。
- 注意:‘環(huán)境變量’和‘bash的操作環(huán)境’意思不太一樣。PS1并不是環(huán)境變量但會影響到bash的接口(提示符)
變量鍵盤讀取、數(shù)組與聲明:read,array,declare
- read,要想讀取來自鍵盤輸入的變量,就是用read命令。這個命令最常被用在shell script的編寫中,用于與用戶對話
read [-pt] name-p顯示的內(nèi)容,-t 等待的時間 - declare/typeset,聲明變量的類型,不帶參數(shù)
declare [-aixr] name-a數(shù)組,-i 整數(shù),-x 變成環(huán)境變量,同export,-r設(shè)置為readonly,不可更改不可重設(shè)
$sum=100+300+50
$echo $sum
100+300+50
$declare -i sum=100+300+50
$echo $sum
450
- 默認(rèn)變量類型為“字符串”
- bash環(huán)境的中的數(shù)值運算,默認(rèn)最多僅能到達(dá)整數(shù)類型,1/3結(jié)果為0
- 如果不小心把變量設(shè)置為“只讀”,只能注銷再登錄才能復(fù)原該變量的類型
- 數(shù)組變量類型
- 數(shù)組的設(shè)置方式
var[index] = content
- 數(shù)組的設(shè)置方式
與文件系統(tǒng)及程序的限制關(guān)系:ulimit
限制用戶的某些系統(tǒng)資源,包括可以打開的文件數(shù)量,可以使用的CPU時間,可以使用的內(nèi)存總量等
變量內(nèi)容的刪除、替代與替換
除了直接設(shè)置變量內(nèi)容之外,我們可以將變量的內(nèi)容進(jìn)行微調(diào)。
- 變量內(nèi)容的刪除
hanzhou@hanzhou-VirtualBox:~$ echo $path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
hanzhou@hanzhou-VirtualBox:~$ echo ${path#/*:}
/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
hanzhou@hanzhou-VirtualBox:~$ echo ${path##/*:}
/usr/local/games
一個#號刪除從左往右最短的那個,兩個#號從左往右刪除最長的那個
從右往左 用%號
-變量內(nèi)容的替換
hanzhou@hanzhou-VirtualBox:~$ echo $path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
hanzhou@hanzhou-VirtualBox:~$ echo ${path/sbin/SBIN}
/usr/local/SBIN:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
一條斜線只替換第一個字符串,兩條斜線替換所有符合的內(nèi)容
-變量的測試與內(nèi)容替換
hanzhou@hanzhou-VirtualBox:~$ echo $username
hanzhou@hanzhou-VirtualBox:~$ username=${username-root}
hanzhou@hanzhou-VirtualBox:~$ echo $username
root
hanzhou@hanzhou-VirtualBox:~$ user_name=''
hanzhou@hanzhou-VirtualBox:~$ user_name=${user_name-root}
hanzhou@hanzhou-VirtualBox:~$ echo $user_name
echo 出來變量內(nèi)容為空,不一定就沒有這個變量,也許是變量內(nèi)容是空字符串
-(減號):if not none:the former,esle: the later
+(加號):if not none:'',esle thelatr

11.3命令別名與歷史命令
命令別名設(shè)置:alias,unalias
$alias lm='ls -l | more'
alias的定義規(guī)則與變量規(guī)則幾乎相同
root可以rm(刪除)任何數(shù)據(jù),但rm提供了一個參數(shù)讓我們確認(rèn)是否刪除文件,-i,我們可以這樣做:$alias rm='rm -i'
以后使用rm的時候不用太擔(dān)心錯誤刪除的情況
$alias這個命令可以查看目前有哪些命名別名
取消命名別名:
$unalias lm
命名別名與變量的區(qū)別:我們可以直接執(zhí)行命名別名,變量必須要通過類似echo命令才能夠調(diào)用變量的內(nèi)容。
歷史命令: history
history 調(diào)出所有記錄的歷史命令(帶序號,最近的一條數(shù)字最大)
history n 調(diào)出最近n條 歷史記錄
!66執(zhí)行第66條命令
??!執(zhí)行上一條命令,相當(dāng)于↑+enter
!al執(zhí)行最近以al為開頭的命令
echo $HISTSIZE (一般是1000)這個變量決定 ~/.bash_history文件中記錄的歷史命令的最大條數(shù)
- 當(dāng)我們以bash登錄linux主機(jī)后,系統(tǒng)會自動由主文件的
~/.bash_history讀取以前曾經(jīng)下過的命令。 - 默認(rèn)是在用戶注銷時才會將history中的內(nèi)容寫入記錄文件histfiles(一般是
~/.bash_history),所以很多人不會開多個bash接口,而是用單一bash登錄,再用作業(yè)控制(job control)來切換工作,這樣才能將曾經(jīng)執(zhí)行過的命令記錄下來 - 無法記錄時間:歷史命令默認(rèn)不記錄執(zhí)行命令的時間,只有執(zhí)行順序,序號不會變(101~1100),可以通過
~/.bash_logout來進(jìn)行history的記錄,并加上date來增加時間參數(shù)。
11.4 bash shell的操作環(huán)境
路徑與命令查找順序
命令運行的順序可以這樣看:
1.以相對/絕對路徑執(zhí)行命令,例如"/bin/ls" 或 "./ls";
2.由alias找到該命令來執(zhí)行;
3.由bash內(nèi)置的(builtin)命令;
4.通過$PATH這個變量的順序找到的第一個命令來執(zhí)行。
11.5 數(shù)據(jù)流重定向
標(biāo)準(zhǔn)輸入(stdin:standard input):代碼為0,使用<或<<
標(biāo)準(zhǔn)輸出(stdout):代碼為1,使用>或>>
標(biāo)準(zhǔn)錯誤輸出(stderr):代碼為2,使用2>或2>>
輸出
示例:
將正確和錯誤的輸出結(jié)果分別存入不同的文件:
find /home -name .bashrc > list_right 2> list_error將正確和錯誤的輸出結(jié)果存入一個文件:
find /home -name .bashrc > list 2>&1
或
find /home -name .bashrc &> list可以將錯誤信息以“2> /dev/null”丟棄
注意:有錯誤信息但沒有輸出到文件內(nèi)時就會輸出到屏幕上
標(biāo)準(zhǔn)輸入
$cat >catfile
testing
cat file test
(輸入完成要按[ctrl]+d 來離開)
- catfile會被主動創(chuàng)建,并將我們輸入的內(nèi)容內(nèi)容寫入文件。
- 也可以用某個文件的內(nèi)容來代替鍵盤的輸入
$cat >catfile < ~/.bashrc
將~/.bashrc文件的內(nèi)容輸入到catfile中
- 控制字符的用法
$cat >catfile << "eof"
this is a test
ok,now stop
eof ##輸入這個關(guān)鍵詞,立刻就結(jié)束而不需要輸入[ctrl]+d
命令執(zhí)行的判斷依據(jù):;,&&,||
- cmd;cmd(不考慮命令相關(guān)性的連續(xù)命令執(zhí)行)
$sync;sync; - $?(命令回傳碼)與&&或||
cmd1&&cmd2;##若cmd1執(zhí)行正確($?=0)開始執(zhí)行cmd2,否則命令回傳碼不為0,cmd2不執(zhí)行
cmd1||cmd2;##cmd1執(zhí)行正確,cmd2不執(zhí)行,cmd1執(zhí)行不正確,cmd2執(zhí)行
ls/tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe
11.6 管道命令(pipe)
cmd1 | cmd2 | cdm3
選取命令:cut,grep
一般來說,選取信息通常是針對“行”來分析的,并不是通篇信息分析的。
- cut 用于取出我們想要的數(shù)據(jù)
cut -c 12-截取文本每行第十二字符往后的內(nèi)容
cut -d ':' -f 3,5按冒號分隔每行字符,并取出第三個和第五個 字符區(qū)間
hanzhou@hanzhou-VirtualBox:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
hanzhou@hanzhou-VirtualBox:~$ echo $PATH | cut -d ':' -f 3,5
/usr/sbin:/sbin
- grep 用于分析一行信息,若當(dāng)中有我們所需要的信息,就將該行拿出來。
last | grep 'hanzhou':last 命令顯示登錄者信息,用gerp取出含有'hanzhou'的行。
-v反向選擇,顯示沒有查找信息的行
-i 忽略(ignore)大小寫
-n 順便輸出行號
grep 'MANPATH' /etc/man.config顯示/etc/man.config文件中含有'MANPATH'的行
排序命令:sort,wc,uniq
sort [-fbMnrtuk] [file or stdin]
hanzhou@hanzhou-VirtualBox:~$ last | cut -d ' ' -f 1 | sort | uniq -c
1
27 hanzhou
6 reboot
1 wtmp
好奇怪,sort和grep的參數(shù)作用是一樣的,但是用的字母竟然還不一定啊,
sort -f忽略大小寫,-t分隔符 -k以那個區(qū)間(field,字段)排序(可以選擇多個字段排序么?好像可以)
cut -i忽略大小寫,-d (delimter) -f
原因是:sort 的-i,是忽略不可打印內(nèi)容,-d只考慮空白區(qū)域和字母字符
wc:
wc for word count
-l 僅列出行
-w 僅列出多少字(英文)
-m 多少字符 (-c也是一樣)
last | grep [a-zA-Z] | grep -v 'wtmp' | wc -l得到登錄總?cè)舜?br>
第一個greo得到非空白行,第二個去掉wtmp行
雙向重定向:tee
tee會同時將數(shù)據(jù)流送與文件與屏幕
hanzhou@hanzhou-VirtualBox:~/abc$ tee test.txt
this is a test.
this is a test.
check
check
^C
hanzhou@hanzhou-VirtualBox:~/abc$ cat test.txt
this is a test.
check
hanzhou@hanzhou-VirtualBox:~/abc$ tee -a test.txt
another test
another test
over
over
^C
hanzhou@hanzhou-VirtualBox:~/abc$ cat test.txt
this is a test.
check
another test
over
hanzhou@hanzhou-VirtualBox:~/abc$
-a 以append追加模式寫入
第一次cat的時候為什么多一個空白行???
hanzhou@hanzhou-VirtualBox:~/abc$ last | tee newtest |cut -d ' ' -f 1
寫入newtest的結(jié)果沒有經(jīng)過cut處理,但是打印出來的內(nèi)容顯然進(jìn)過cut處理了
tee的用處:可以讓standard output轉(zhuǎn)存一份到文件內(nèi)并將同樣的數(shù)據(jù)繼續(xù)送到屏幕去處理。這樣除了可以讓我們同時分析一份數(shù)據(jù)并記錄下來之外,還可以作為處理一份數(shù)據(jù)的中間暫存盤記錄之用。而且tee是很多認(rèn)證考試中很容易考的。(ORZ)
字符轉(zhuǎn)換命令: tr, col, join, paste, expand
DOS斷行字符與unix斷行字符是不一樣的,可以用dos2UNIX與UNIX2dos來完成轉(zhuǎn)換
- tr
tr可以用來刪除一段信息中的文字,或者是進(jìn)行文字信息的替換
hanzhou@hanzhou-VirtualBox:~/abc$ last | tr '[a-z]' '[A-Z]'
該例把小寫字母全部轉(zhuǎn)為大寫字母
-d 刪除某個字符串
col
一般用col將[tab]按鍵替換為空格鍵,此外還經(jīng)常被用于將man page轉(zhuǎn)存為純文本文件已方便查閱的功能
-x 將tab 換成對等的空格鍵
-b 在文字內(nèi)有反斜杠join
join用于處理兩個文件之間的數(shù)據(jù),
expand
常用于把tab轉(zhuǎn)為空格,可以指定幾個空格切割命令split
文件太大時,按照大小或者行數(shù) split 成為多個小文件
-l按行,-b按照大小
$ split -l 1 test_控制字符 tmp
$ ls
test_控制字符 tmpaa tmpab tmpac tmpad tmpae
- 合并文件 cat