實驗樓 練習 小筆記php
能夠輸出圖形字符的命令banner
html
你能夠先使用以下命令安裝:前端
$ sudo apt-get updatenode
$ sudo apt-get install sysvbannerpython
而後:linux
$ banner shiyanlou
兩個相似的命令toilet
,figlet
git
$ sudo apt-get install toilet正則表達式
Who am ichrome
如今咱們新建一個叫 lilei 的用戶:shell
$ sudo adduser lilei
登陸用戶:
-l$ sulilei
實驗環境:
用戶名:shiyanlou
密碼:X6G4jz6z
用戶及文件權限管理
實驗介紹
一、Linux 中建立、刪除用戶,及用戶組等操做。 二、Linux 中的文件權限設置。
1、Linux 用戶管理
經過第一節課程的學習,你應該已經知道,Linux 是一個能夠實現多用戶登錄的操做系統,好比「李雷」和「韓梅梅」均可以同時登錄同一臺主機,他們共享一些主機的資源,但他們也分別有本身的用戶空間,用於存放各自的文件。但實際上他們的文件都是放在同一個物理磁盤上的甚至同一個邏輯分區或者目錄裏,可是因爲 Linux 的 用戶管理和 權限機制 ,不一樣用戶不能夠輕易地查看、修改彼此的文件。
下面咱們就來學習一下 Linux 下的帳戶管理的基礎知識。
1.查看用戶
請打開終端,輸入命令:
$ who am i
或者
$ who mom likes
輸入的第一列表示打開當前僞終端的用戶的用戶名(要查看當前登陸用戶的用戶名,去掉空格直接使用 whoami 便可),第二列的 pts/0 中 pts 表示僞終端,所謂僞是相對於 /dev/tty 設備而言的,還記得上一節講終端時的那七個使用 [Ctrl]+[Alt]+[F1]~[F7] 進行切換的 /dev/tty 設備麼,這是「真終端」,僞終端就是當你在圖形用戶界面使用 /dev/tty7 時每打開一個終端就會產生一個僞終端, pts/0 後面那個數字就表示打開的僞終端序號,你能夠嘗試再打開一個終端,而後在裏面輸入 who am i ,看第二列是否是就變成 pts/1 了,第三列則表示當前僞終端的啓動時間。
who 命令其它經常使用參數
參數 |
說明 |
-a |
打印能打印的所有 |
-d |
打印死掉的進程 |
-m |
同am i,mom likes |
-q |
打印當前登陸用戶數及用戶名 |
-u |
打印當前登陸用戶登陸信息 |
-r |
打印運行等級 |
2.建立用戶
在 Linux 系統裏, root 帳戶擁有整個系統至高無上的權利,好比 新建/添加 用戶。
root 權限,系統權限的一種,與 SYSTEM 權限能夠理解成一個概念,但高於 Administrator 權限,root 是 Linux 和 UNIX 系統中的超級管理員用戶賬戶,該賬戶擁有整個系統至高無上的權力,全部對象他均可以操做,因此不少黑客在入侵系統的時候,都要把權限提高到 root 權限,用 Windows 的方法理解也就是將本身的非法賬戶添加到 Administrators 用戶組。更好比安卓操做系統中(基於 Linux 內核)得到 root 權限以後就意味着已經得到了手機的最高權限,這時候你能夠對手機中的任何文件(包括系統文件)執行全部增、刪、改、查的操做。
咱們通常登陸系統時都是以普通帳戶的身份登陸的,要建立用戶須要 root 權限,這裏就要用到 sudo 這個命令了。不過使用這個命令有兩個大前提,一是你要知道當前登陸用戶的密碼,二是當前用戶必須在 sudo 用戶組。shiyanlou 用戶也屬於 sudo 用戶組(稍後會介紹如何查看和添加用戶組)。
su,su- 與 sudo
su <user>能夠切換到用戶user,執行時須要輸入目標用戶的密碼,sudo <cmd>能夠以特權級別運行cmd命令,須要當前用戶屬於sudo組,且須要輸入當前用戶密碼。su - <user>命令也是切換用戶,同時環境變量也會跟着改變成目標用戶的環境變量。
如今咱們新建一個叫 lilei 的用戶:
$ sudo adduser lilei
按照提示輸入 shiyanlou 密碼(Linux 下密碼輸入一般都是不可見的),而後是給 lilei 用戶設置密碼,後面的選項的一些內容你能夠選擇直接回車使用默認值:
這個命令不但能夠添加用戶到系統,同時也會默認爲新用戶建立 home 目錄:
$ ls /home
如今你已經建立好一個用戶,而且你能夠使用你建立的用戶登陸了,使用以下命令切換登陸用戶:
$ su -l lilei
退出當前用戶跟退出終端同樣能夠使用 exit 命令或者使用快捷鍵 Ctrl+d。
3.用戶組
在 Linux 裏面每一個用戶都有一個歸屬(用戶組),用戶組簡單地理解就是一組用戶的集合,它們共享一些資源和權限,同時擁有私有資源,就跟家的形式差很少,你的兄弟姐妹(不一樣的用戶)屬於同一個家(用戶組),大家能夠共同擁有這個家(共享資源),爸媽對待大家都同樣(共享權限),你偶爾寫寫日記,其餘人未經容許不能查看(私有資源和權限)。固然一個用戶是能夠屬於多個用戶組的,正如你既屬於家庭,又屬於學校或公司。
在 Linux 裏面如何知道本身屬於哪些用戶組呢?
方法一:使用groups命令
$ groups shiyanlou
其中冒號以前表示用戶,後面表示該用戶所屬的用戶組。這裏能夠看到 shiyanlou 用戶屬於 shiyanlou 用戶組,每次新建用戶若是不指定用戶組的話,默認會自動建立一個與用戶名相同的用戶組(差很少就至關於家長的意思,或者說是老總)。默認狀況下在sudo用戶組裏的能夠使用sudo命令得到root權限。shiyanlou 用戶也能夠使用 sudo 命令,爲何這裏沒有顯示在 sudo 用戶組裏呢?能夠查看下 /etc/sudoers.d/shiyanlou 文件,咱們在 /etc/sudoers.d目錄下建立了這個文件,從而給 shiyanlou 用戶賦予了 sudo 權限:
方法二:查看/etc/group文件
$ cat /etc/group | sort
這裏 cat 命令用於讀取指定文件的內容並打印到終端輸出,後面會詳細講它的使用。| sort 表示將讀取的文本進行一個字典排序再輸出,而後你將看到以下一堆輸出,你能夠在最下面看到 shiyanlou 的用戶組信息:
沒找到,不要緊,你能夠使用命令過濾掉一些你不想看到的結果:
$ cat /etc/group | grep -E "shiyanlou"
etc/group 文件格式說明
/etc/group 的內容包括用戶組(Group)、用戶組口令、GID 及該用戶組所包含的用戶(User),每一個用戶組一條記錄。格式以下:
group_name:password:GID:user_list
你看到上面的 password 字段爲一個 'x' 並非說密碼就是它,只是表示密碼不可見而已。
將其它用戶加入 sudo 用戶組
默認狀況下新建立的用戶是不具備 root 權限的,也不在 sudo 用戶組,可讓其加入sudo用戶組從而獲取 root 權限。
$ su -l lilei
$ sudo ls
會提示 lilei 不在 sudoers 文件中,意思就是 lilei 不在 sudo 用戶組中,至於 sudoers 文件(/etc/sudoers)你如今最好不要動它,操做不慎會致使比較麻煩的後果。
使用 usermod 命令能夠爲用戶添加用戶組,一樣使用該命令你必需有 root 權限,你能夠直接使用 root 用戶爲其它用戶添加用戶組,或者用其它已經在 sudo 用戶組的用戶使用 sudo 命令獲取權限來執行該命令
這裏我用 shiyanlou 用戶執行 sudo 命令將 lilei 添加到 sudo 用戶組,讓它也能夠使用 sudo 命令得到 root 權限
$ su shiyanlou # 此處須要輸入shiyanlou用戶密碼,能夠點擊右側工具欄中的「SSH直連」查看
$ groups lilei
$ sudo usermod -G sudo lilei
$ groups lilei
而後你再切換回 lilei 用戶,如今就能夠使用 sudo 獲取 root 權限了。
4.刪除用戶
刪除用戶是很簡單的事:
$ sudo deluser lilei --remove-home
2、Linux 文件權限
1.查看文件權限
咱們以前已經不少次用到 ls 命令了,如你所見,咱們用它來列出並顯示當前目錄下的文件,固然這是在不帶任何參數的狀況下,它能作的固然不止這麼多,如今咱們就要用它來查看文件權限。
使用較長格式列出文件:
$ ls -l
你可能除了知道最後面那一項是文件名以外,其它項就不太清楚了,那麼究竟是什麼意思呢:
可能你仍是不太明白,好比第一項文件類型和權限那一堆東西具體指什麼,連接又是什麼,何爲最後修改時間,下面一一道來:
關於文件類型,這裏有一點你必需時刻牢記Linux 裏面一切皆文件,正由於這一點纔有了設備文件( /dev 目錄下有各類設備文件,大都跟具體的硬件設備相關)這一說,還有 socket(網絡套接字,具體是什麼,感興趣的用戶能夠本身去了解或期待實驗樓的後續相關課程),和 pipe (管道,這個東西很重要,咱們之後將會討論到,這裏你先知道有它的存在便可)。軟連接文件,連接文件是分爲兩種的,另外一種固然是「硬連接」(硬連接不經常使用,具體內容不做爲本課程討論重點,而軟連接等同於 Windows 上的快捷方式,你記住這一點就夠了)
讀權限,表示你能夠使用 cat <file name> 之類的命令來讀取某個文件的內容;寫權限,表示你能夠編輯和修改某個文件; 執行權限,一般指能夠運行的二進制程序文件或者腳本文件,如同 Windows 上的 'exe' 後綴的文件,不過 Linux 上不是經過文件後綴名來區分文件的類型。你須要注意的一點是,一個目錄要同時具備讀權限和執行權限才能夠打開,而一個目錄要有寫權限才容許在其中建立其它文件,這是由於目錄文件實際保存着該目錄裏面的文件的列表等信息
全部者權限,這一點相信你應該明白了,至於所屬用戶組權限,是指你所在的用戶組中的全部其它用戶對於該文件的權限,好比,你有一個艾派德,那麼這個用戶組權限就決定了你的兄弟姐妹有沒有權限使用它破壞它和佔有它。
連接到該文件所在的 inode 結點的文件名數目(關於這個概念涉及到 Linux 文件系統的相關概念知識,不在本課程的討論範圍,感興趣的用戶能夠本身去了解)。
以 inode 結點大小爲單位來表示的文件大小,你能夠給 ls 加上 -lh 參數來更直觀的查看文件的大小。
明白了文件權限的一些概念,咱們順帶補充一下關於 ls 命令的一些其它經常使用的用法:
$ ls -A
固然,你能夠同時使用 '-A' 和 '-l' 參數:
$ ls -Al
查看某一個目錄的完整屬性,而不是顯示目錄裏面的文件屬性:
$ ls -dl <目錄名>
$ ls -AsSh
其中小 s 爲顯示文件大小,大 S 爲按文件大小排序,若須要知道如何按其它方式排序,請使用「man」命令查詢。
2.變動文件全部者
假設目前是 lilei 用戶登陸,新建一個文件,命名爲 「iphone6」:
$ touch iphone6
可見文件全部者是 lilei :
如今,換回到shiyanlou用戶身份,使用如下命令變動文件全部者爲 shiyanlou :
$ cd /home/lilei
$ ls iphone6
$ sudo chown shiyanlou iphone6
$ cp iphone6 /home/shiyanlou
如今查看,發現 文件全部者成功修改成 shiyanlou :
3.修改文件權限
若是你有一個本身的文件不想被其餘用戶讀、寫、執行,那麼就須要對文件的權限作修改,這裏有兩種方式:
每一個文件的三組權限(擁有者,所屬用戶組,其餘用戶,記住這個順序是必定的)就對應這一個 "rwx",也就是一個 '7' ,因此若是我要將文件「iphone6」的權限改成只有我本身能夠用那麼就這樣:
爲了演示,我先在文件里加點內容:
$ echo "echo \"hello shiyanlou\"" > iphone6
而後修改權限:
$ chmod 700 iphone6
如今,其餘用戶已經不能讀這個「iphone6」文件了:
完成上述相同的效果,你能夠:
$ chmod go-rw iphone
'g''o'還有'u',分別表示group,others,user,'+','-' 就分別表示增長和去掉相應的權限。
3、更多
Linux 還有一些關於隱藏權限和特殊權限的內容,想全面瞭解 Linux 權限管理這部份內容的用戶能夠經過其餘方式學習。
做業
添加一個用戶loutest,使用sudo建立文件/opt/forloutest,設置成用戶loutest能夠讀寫。截圖並把操做過程寫入實驗報告。
實驗環境:
用戶名:shiyanlou
密碼:vRwzLsRH
一、Linux 的文件組織目錄結構。 二、相對路徑和絕對路徑。 三、對文件的移動、複製、重命名、編輯等操做。
在講 Linux 目錄結構以前,你首先要清楚一點東西,那就是 Linux 的目錄與 Windows 的目錄的區別,或許對於通常操做上的感覺來講沒有多大不一樣,但從它們的實現機制來講是徹底不一樣的。
一種不一樣是體如今目錄與存儲介質(磁盤,內存,DVD 等)的關係上,以往的 Windows 一直是以存儲介質爲主的,主要以盤符(C 盤,D 盤...)及分區的來實現文件管理,而後之下才是目錄,目錄就顯得不是那麼重要,除系統文件以外的用戶文件放在任何地方任何目錄也是沒有多大關係。因此一般 Windows 在使用一段時間後,磁盤上面的文件目錄會顯得雜亂無章(少數善於整理的用戶除外吧)。然而 UNIX/Linux 剛好相反,UNIX 是以目錄爲主的,Linux 也繼承了這一優良特性。 Linux 是以樹形目錄結構的形式來構建整個系統的,能夠理解爲一個用戶可操做系統的骨架。雖然本質上不管是目錄結構仍是操做系統內核都是存儲在磁盤上的,但從邏輯上來講 Linux 的磁盤是「掛在」(掛載在)目錄上的,每個目錄不只能使用本地磁盤分區的文件系統,也能夠使用網絡上的文件系統。舉例來講,能夠利用網絡文件系統(Network File System,NFS)服務器載入某特定目錄等。
Linux 的目錄結構說複雜很複雜,說簡單也很簡單。複雜在於,由於系統的正常運行是以目錄結構爲基礎的,對於初學者來講裏面大部分目錄都不知道其做用,重要與否,特別對於哪些曾近的重度 Windows 用戶,他們會糾結很長時間,關於我安裝的軟件在哪裏這類問題。說它簡單是由於,它其中大部分目錄結構是規定好了(FHS 標準),是死的,當你掌握後,你在裏面的一切操做都會變得井井有理。
FHS(英文:Filesystem Hierarchy Standard 中文:文件系統層次結構標準),多數 Linux 版本採用這種文件組織形式,FHS 定義了系統中每一個區域的用途、所須要的最小構成的文件和目錄同時還給出了例外處理與矛盾處理。
FHS 定義了兩層規範,第一層是, / 下面的各個目錄應該要放什麼文件數據,例如 /etc 應該要放置設置文件,/bin 與 /sbin 則應該要放置可執行文件等等。
第二層則是針對 /usr 及 /var 這兩個目錄的子目錄來定義。例如 /var/log 放置系統登陸文件、/usr/share 放置共享數據等等。
若是你以爲看這個不明白,那麼你能夠試試最真實最直觀的方式,執行以下命令:
$ tree /
若是提示"command not found",就先安裝:
# 由於咱們的環境的緣由,每次新啓動實驗會清除系統恢復初始狀態,因此須要手動更新軟件包索引,以便咱們安裝時能找到相應軟件包的源
getsudo apt-update
getsudo apt-install tree
關於上面提到的 FHS,這裏還有個很重要的內容你必定要明白,FHS 是根據以往無數 Linux 用戶和開發者的經驗總結出來的,而且會維持更新,FHS 依據文件系統使用的頻繁與否以及是否容許用戶隨意改動(注意,不是不能,學習過程當中,不要怕這些),將目錄定義爲四種交互做用的形態,以下表所示:
有人可能不明白這路徑是指什麼,有什麼用。顧名思義,路徑就是你要去哪兒的路線嘛。若是你想進入某個具體的目錄或者想得到某個目錄的文件(目錄自己也是文件)那就得用路徑來找到了。
使用 cd
命令能夠切換目錄,在 Linux 裏面使用 .
表示當前目錄,..
表示上一級目錄(**注意,還記得咱們上一節介紹過的,以 .
開頭的文件都是隱藏文件,因此這兩個目錄必然也是隱藏的,你能夠使用 ls -a
命令查看隱藏文件), -
表示上一次所在目錄,~
一般表示當前用戶的"home"目錄。使用 pwd
命令能夠獲取當前所在路徑(絕對路徑)。
進入上一級目錄:
cd$..
進入你的「home」目錄:
cd$~
# 或者 cd /home/<你的用戶名>
使用 pwd
獲取當前路徑:
pwd$
關於絕對路徑,簡單地說就是以根"/"目錄爲起點的完整路徑,以你所要到的目錄爲終點,表現形式如: /usr/local/bin
,表示根目錄下的 usr 目錄中的 local 目錄中的 bin 目錄。
相對路徑,也就是相對於你當前的目錄的路徑,相對路徑是以當前目錄 .
爲起點,以你所要到的目錄爲終點,表現形式如: usr/local/bin
(這裏假設你當前目錄爲根目錄)。你可能注意到,咱們表示相對路徑實際並無加上表示當前目錄的那個 .
,而是直接以目錄名開頭,由於這個 usr
目錄爲 /
目錄下的子目錄,是能夠省略這個 .
的(之後會講到一個相似不能省略的狀況);若是是當前目錄的上一級目錄,則須要使用 ..
,好比你當前目錄爲「home」目錄,根目錄就應該表示爲 ../../
,表示上一級目錄("home"目錄)的上一級目錄("/"目錄)。
下面咱們以你的"home"目錄爲起點,分別以絕對路徑和相對路徑的方式進入 /usr/local/bin
目錄:
# 絕對路徑
cdlocal$/usr//bin
# 相對路徑
cdlocal$../../usr//bin
進入一個目錄,能夠使用絕對路徑也能夠使用相對路徑,那咱們應該在何時選擇正確的方式進入某個目錄呢。就是憑直覺嘛,你以爲怎樣方便就使用哪個,而不用特地只使用某一種。好比假設我當前在 /usr/local/bin
目錄,我想進入上一級的 local 目錄你說是使用 cd ..
方便仍是 cd /usr/local
方便。而若是要進入的是 usr
目錄,那麼 cd /usr
,就比cd ../..
方便一點了。
提示:在進行目錄切換的過程當中請多使用 Tab
鍵自動補全,可避免輸入錯誤,連續按兩次Tab
能夠顯示所有候選結果
使用 touch
命令建立空白文件,關於 touch
命令,其主要是來更改已有文件的時間戳的(好比,最近訪問時間,最近修改時間),但其在不加任何參數的狀況下,只指定一個文件名,則能夠建立一個爲指定文件名的空白文件(不會覆蓋已有同名文件),固然你也能夠同時指定該文件的時間戳,更多關於 touch
命令的用法,會在下一講文件搜索中涉及。
建立名爲 test 的空白文件,由於在其餘目錄沒有權限,因此須要先 cd ~
切換回用戶的/home/shiyanlou
目錄:
cd$~
test$ touch
使用 mkdir
(make directories)命令能夠建立一個空目錄,也可同時指定建立目錄的權限屬性
建立名爲"mydir"的空目錄:
mkdir$mydir
使用 -p
參數,同時建立父目錄(若是不存在該父目錄),以下咱們同時建立一個多級目錄(這在有時候安裝軟件,配置安裝路徑時很是有用):
mkdir$-p father/son/grandson
後面的目錄路徑,以絕對路徑的方式表示也是能夠的。
使用cp
(copy)命令複製一個文件或目錄到指定目錄。將以前建立的"test"文件複製到"/home/shiyanlou/father/son/grandson"目錄中:
test$ cpfather/son/grandson
是否是很方便啊,若是在圖形界面則須要先在源目錄複製文件,再進到目的目錄粘貼文件,命令行操做步驟就一步到位了嘛。
dh這個複製須要在大目錄下進行,將大目錄下的內容複製給子目錄是能夠的,要是交叉,就不行
若是直接使用cp
命令,複製一個目錄的話,會出現以下錯誤:
要成功複製目錄須要加上-r
或者-R
參數,表示遞歸複製,就是說有點「株連九族」的意思:
dh這個的用法見下圖,複製目錄,成爲其子目錄了。
$ cp -r father family
使用rm
(remove files or directories)命令,刪除一個文件或目錄:
test$ rm
有時候你會遇到想要刪除一些爲只讀權限的文件,直接使用rm
刪除會顯示一個提示,以下:
你若是想忽略這提示,直接刪除文件,能夠使用-f
參數強制刪除:
-ftest$ rm
跟複製目錄同樣,要刪除一個目錄,也須要加上-r
或-R
參數:
dh經測試,須要跑到對應的目錄下才能夠刪除,有點小蛋疼
$ rm -r family
使用mv
(move or rename files)命令,移動文件(剪切)。將文件"file1"移動到"Documents"目錄mv
源目錄文件
目的目錄
:
$ mkdir Documents
$ mv file1 Documents
將文件"file1"重命名爲"myfile" mv
舊的文件名
新的文件名
:
dh若是沒有該目錄,就重命名,不然移動到該目錄下面
$ mv file1 myfile
要實現批量重命名,mv 命令就有點力不從心了,咱們能夠使用一個看起來更專業的命令rename
來實現。不過它是要用 perl 正則表達式來做爲參數,關於正則表達式咱們要在後面纔會介紹到,這裏只作演示,你只要記得這個rename
命令能夠批量重命名就行了,之後再從新學習也不會有任何問題,畢竟你已經掌握了一個更經常使用的mv
命令。
# 使用通配符批量建立 5 個文件
15$ touch file{..}.txt
# 批量將這 5 個後綴爲 .txt 的文本文件重命名爲以 .c 爲後綴的文件
's/\.txt/\.c/'$ rename*.txt
# 批量將這 5 個文件,文件名改成大寫
'y/a-z/A-Z/'$ rename*.c
簡單解釋下上面的命令,rename
是先使用第二個參數的通配符匹配全部後綴爲.txt
的文件,而後使用第一個參數提供的正則表達式將匹配的這些文件的.txt
後綴替換爲.c
,這一點在咱們後面學習了sed
命令後,相信你會更好的理解。
dh當年學的正則老不用又給忘記了,如今再用起來,正則仍是很不錯的。
cat
,tac
和nl
命令查看文件這兩個命令都是用來打印文件內容到標準輸出(終端),其中cat
爲正序顯示,tac
倒序顯示。
標準輸入輸出:當咱們執行一個 shell 命令行時一般會自動打開三個標準文件,即標準輸入文件(stdin),默認對應終端的鍵盤;標準輸出文件(stdout)和標準錯誤輸出文件(stderr),這兩個文件都對應被重定向到終端的屏幕,以便咱們能直接看到輸出內容。進程將從標準輸入文件中獲得輸入數據,將正常輸出數據輸出到標準輸出文件,而將錯誤信息送到標準錯誤文件中。
好比咱們要查看以前從"/etc"目錄下拷貝來的passwd
文件:
$ cat passwd
能夠加上-n
參數顯示行號:
$ cat -n passwd
nl
命令,添加行號並打印,這是個比cat -n
更專業的行號打印命令。
這裏簡單列舉它的經常使用的幾個參數:
-b : 指定添加行號的方式,主要有兩種:
-b a:表示不管是否爲空行,一樣列出行號("cat -n"就是這種方式)
-b t:只列出非空行的編號並列出(默認爲這種方式)
-n : 設置行號的樣式,主要有三種:
-n ln:在行號字段最左端顯示
-n rn:在行號字段最右邊顯示,且不加0
-n rz:在行號字段最右邊顯示,且加0
-w : 行號字段佔用的位數(默認爲 6 位)
你會發現使用這幾個命令,默認的終端窗口大小,一屏顯示不完文本的內容,得用鼠標拖動滾動條或者滑動滾輪才能繼續往下翻頁,要是能夠直接使用鍵盤操做翻頁就行了,那麼你就能夠使用下面要介紹的命令。
more
和less
命令分頁查看文件若是說上面的 cat 是用來快速查看一個文件內容的,那麼這個more
和less
就是天生用來"閱讀"一個文件的內容的,好比說"man"手冊內部就是使用的 less 來顯示內容。其中more
命令比較簡單,只能向一個方向滾動,而"less"爲基於"more"和"vi"(一個強大的編輯器,咱們有單獨的課程來讓你學習)開發,功能更強大。less 的使用基本和 more 一致,具體使用請查看 man 手冊,這裏只介紹 more 命令的使用。
使用more
工具打開passwd
文件:
$ more passwd
打開後默認只顯示一屏內容,終端底部顯示當前閱讀的進度(百分比)。能夠使用Enter
鍵向下滾動一行,使用Space
鍵向下滾動一屏,按下h
顯示幫助,q
退出。
head
和tail
命令查看文件這兩個命令那些性子比較急的人應該會比較喜歡,由於它們一個是隻查看的頭幾行(默認爲10行,不足10行則顯示所有)和尾幾行。仍是拿 passwd 文件舉例,好比當咱們想要查看最近新增長的用戶,那麼咱們能夠查看這個/etc/passwd
文件,不過咱們前面也看到了,這個文件裏面一大堆亂糟糟的東西,看起來實在費神啊。這裏想到系統新增長一個用戶,應該會將用戶的信息添加到passwd文件的最後,那麼這時候咱們就能夠使用tail
命令了:
$ tail /etc/passwd
甚至更直接的只看一行, 加上-n
參數,後面緊跟行數:
dh這邊是直接顯示最後幾行
1$ tail -n/etc/passwd
關於tail
命令,不得不提的還有它一個很牛的參數-f
,這個參數能夠實現不停地讀取某個文件的內容並顯示。這可以讓咱們動態查看日誌起到實時監視的做用,不過我不會在這門基礎課程中介紹它的更多細節,感興趣的用戶能夠本身去了解。
前面我提到過,在 Linux 下面文件的類型不是根據文件後綴來判斷的,咱們一般使用file
命令能夠查看文件的類型:
$ file /bin/ls
這表示這是一個可執行文件,運行在 64 位平臺,並使用了動態連接文件(共享庫)。
在 Linux 下面編輯文件一般咱們會直接使用專門的命令行編輯器好比(emacs,vim,nano),因爲涉及 Linux 上的編輯器的內容比較多,且很是重要,故咱們有一門單獨的基礎課專門介紹這其中一個編輯器(vim)。在這裏強烈但願正在學習這門 Linux 基礎課的你先在這裏暫停一下,先去學習vim 編輯器的使用(至少掌握基本的操做)而後再繼續本課程後面的內容,由於後面的內容會假設你已經學會了 vim 編輯器的使用。若是你想更加快速的入門,你能夠直接使用 Linux 內部的 vim 學習教程,輸入以下命令便可開始:
$ vimtutor
dhVim的操做手法以下:
你是否是以爲在咱們的環境中學習感受輕鬆愉快毫無壓力呢,因此偶爾偷偷懶也是沒有問題的。要真是這樣可不太好啊,要學會給本身點壓力,稍微嚴格點要求本身才行。你又或許會想要是有人能監督就行了,這樣你能學得更快。好吧今天就教你怎麼召喚一雙眼睛出來監督你:
$ xeyes
你能夠使用以下命令將它放到後臺運行
$ nohup xeyes &
實驗環境:
用戶名:shiyanlou
密碼:r00Ds8ku
本節實驗介紹環境變量的做用與用法,及幾種搜索文件的方法。學會這些技巧高效地使用 Linux。
要解釋環境變量,得先明白變量是什麼,準確的說應該是 Shell 變量,所謂變量就是計算機中用於記錄一個值(不必定是數值,也能夠是字符或字符串)的符號,而這些符號將用於不一樣的運算處理中。一般變量與值是一對一的關係,能夠經過表達式讀取它的值賦值給其它變量,也能夠直接指定數值賦值給任意變量。爲了便於運算和處理,大部分的編程語言會區分變量的類型,用於分別記錄數值、字符或者字符串等等數據類型。Shell 中的變量也基本如此,有不一樣類型(但不用專門指定類型名),能夠參與運算,有做用域限定。
變量的做用域即變量的有效範圍(好比一個函數中、一個源文件中或者全局範圍),在該範圍內只能有一個同名變量。一旦離開則該變量無效,如同不存在這個變量通常。
在 Shell 中如何建立一個變量,如何給變量賦值和如何讀取變量的值呢?這部份內容會在bash 腳本編程這門課中詳細介紹,這裏我簡單舉例說明一下:
使用declare
命令建立一個變量名爲 tmp 的變量:
declare$tmp
其實也能夠不用 declare 預聲明一個變量,直接即用即建立,這裏只是告訴你 declare 的做用,這在建立其它指定類型的變量(如數組)時會用到。
使用=
號賦值運算符爲變量 tmp 賦值爲 shiyanlou:
$ tmp=shiyanlou
讀取變量的值,使用echo
命令和$
符號($符號用於表示引用一個變量的值,初學者常常會忘記輸入):
echo$tmp$
注意:關於變量名,並非任何形式的變量名都是可用的,變量名只能是英文字母,數字或者下劃線,且不能以數字做爲開頭。
簡單理解了變量的概念,就很好解釋環境變量了,環境變量就是做用域比自定義變量要大,如Shell 的環境變量做用於自身和它的子進程。在全部的 UNIX 和類 UNIX 系統中,每一個進程都有其各自的環境變量設置,且默認狀況下,當一個進程被建立時,處理建立過程當中明確指定的話,它將繼承其父進程的絕大部分環境設置。Shell 程序也做爲一個進程運行在操做系統之上,而咱們在 Shell中運行的大部分命令都將以 Shell 的子進程的方式運行。
一般咱們會涉及到的環境變量有三種:
也有三個與上述三種環境變量相關的命令,set
,env
,export
。這三個命令很類似,均可以用於打印相關環境變量,區別在於涉及的是不一樣範圍的環境變量,詳見下表:
命令 |
說明 |
|
顯示當前 Shell 全部環境變量,包括其內建環境變量(與 Shell 外觀等相關),用戶自定義變量及導出的環境變量 |
|
顯示與當前用戶相關的環境變量,還可讓命令在指定環境中運行 |
|
顯示從 Shell 中導出成環境變量的變量,也能經過它將自定義變量導出爲環境變量 |
你能夠更直觀的使用vimdiff
工具比較一下它們之間的差異:
$ temp=shiyanlou
export$temp_env=shiyanlou
$ env|sort>env.txt
exportexport$|sort>.txt
setset$|sort>.txt
上述操做將命令輸出經過管道|
使用sort
命令排序,再重定向到對象文本文件中。
exportset$ vimdiff env.txt.txt.txt
使用vimdiff
工具比較導出的幾個文件的內容。
關於環境變量,能夠簡單的理解成在當前進程的子進程是否有效,有效則爲環境變量,不然不是(有些人也將全部變量統稱爲環境變量,只是以全局環境變量和局部環境變量進行區分,咱們只要理解它們的實質區別便可)。咱們這裏用export
命令來體會一下,先在 Shell 中設置一個變量temp=shiyanlou
,而後再新建立一個子 Shell 查看temp
變量的值:
注意:爲了與普通變量區分,一般咱們習慣將環境變量名設爲大寫
你可能很早以前就有疑問,咱們在 Shell 中輸入一個命令,Shell 是怎麼知道在哪去找到這個命令而後執行的呢?這是經過環境變量PATH
來進行搜索的,熟悉 Windows 的用戶可能知道 Windows 中的也是有這麼一個 PATH 環境變量。這個PATH
裏面就保存了Shell中執行的命令的搜索路徑。
查看PATH
環境變量的內容:
echo$PATH$
默認狀況下你會看到以下輸出:
/usr//usr//usr//sbin://usr/g/usr//usr/local/sbin:local/bin:sbin:bin:bin:ames:local/games
若是你還記得咱們在 Linux 目錄結構那一節的內容,你就應該知道上面這些目錄下放的是哪一類文件了。一般這一類目錄下放的都是可執行文件,當咱們在 Shell 中執行一個命令時,系統就會按照 PATH 中設定的路徑按照順序依次到目錄中去查找,若是存在同名的命令,則執行先找到的那個。
下面咱們將練習建立一個最簡單的可執行 Shell 腳本和一個使用 C 語言建立的"hello world"程序,若是這兩部份內容你以前沒有學習過,那麼你能夠進行一個入門學習: C 語言入門教程 高級 Bash 腳本編程指南 Linux Shell Scripting Tutorial (LSST) v2.0
建立一個 Shell 腳本文件:
$ vim hello_shell.sh
在腳本中添加以下內容,保存並退出(注意不要省掉第一行,這不是註釋,論壇有用戶反應會有語法錯誤,就是由於沒有了第一行):
#!/bin/zsh
fordo((i=0; i<10; i++));
echo"hello shell"
done
exit0
爲文件添加可執行權限:
chmod755$hello_shell.sh
執行腳本
$ ./hello_shell.sh
建立一個 C 語言"hello world"程序:
$ vim hello_world.c
#include <stdio.h>
int main(void)
{
printf"hello world!\n" ();
return0 ;
}
使用 gcc 生成可執行文件:
$ gcc -o hello_world hello_world.c
gcc 生成二進制文件默認具備可執行權限,不須要修改
在 shiyanlou 家目錄建立一個mybin
目錄,並將上述 hello_shell.sh 和 hello_world 文件移動到其中:
$ mkdir mybin
$ mv hello_shell.sh hello_world mybin/
如今你能夠在mybin
目錄中分別運行你剛剛建立的兩個程序:
$ cd mybin
$ ./hello_shell.sh
$ ./hello_world
回到上一級目錄,也就是shiyanlou
家目錄,當再想運行那兩個程序時,會發現提示命令找不到,除非加上命令的完整路徑,但那樣很不方便,如何作到想使用系統命令同樣執行本身建立的腳本文件或者程序呢?那就要將命令所在路徑添加到PATH
環境變量了。
在前面咱們應該注意到PATH
裏面的路徑是以:
做爲分割符,因此咱們能夠這樣添加自定義路徑:
:/home/shiyanlou/mybin$ PATH=$PATH
注意這裏必定要使用絕對路徑
如今你就能夠在其餘任意目錄執行那兩個命令了(注意須要去掉前面的./
)。你可能會意識到這樣還並無很好的解決問題,由於我給 PATH 環境變量追加了一個路徑,它也只是在當前 Shell 有效,我一旦退出終端,再打開就會發現又失效了。有沒有方法讓添加的環境變量全局有效?或者每次啓動 Shell 時自動執行上面添加自定義路徑到 PATH 的命令?下面咱們就來講說後一種方式——讓它自動執行。
在每一個用戶的 home 目錄中有一個 Shell 每次啓動時會默認執行一個配置腳本,以初始化環境,包括添加一些用戶自定義環境變量等等。zsh 的配置文件是.zshrc
,相應 Bash 的配置文件爲.bashrc
。它們在etc
下還都有一個或多個全局的配置文件,不過咱們通常只修改用戶目錄下的配置文件。
咱們能夠簡單的使用下面命令直接添加內容到.zshrc
中:
"PATH=$PATH:/home/shiyanlou/mybin">> $ echo.zshrc
上述命令中>>
表示將標準輸出以追加的方式重定向到一個文件中,注意前面用到的>
是以覆蓋的方式重定向到一個文件中,使用的時候必定要注意分辨。在指定文件不存在的狀況下都會建立新的文件。
變量的修改有如下幾種方式:
變量設置方式 |
說明 |
|
從頭向後開始匹配,刪除符合匹配字串的最短數據 |
|
從頭向後開始匹配,刪除符合匹配字串的最長數據 |
|
從尾向前開始匹配,刪除符合匹配字串的最短數據 |
|
從尾向前開始匹配,刪除符合匹配字串的最長數據 |
|
將符合舊字串的第一個字串替換爲新的字串 |
|
將符合舊字串的所有字串替換爲新的字串 |
好比要修改咱們前面添加到 PATH 的環境變量。爲了不操做失誤致使命令找不到,咱們先將 PATH 賦值給一個新的自定義變量 path:
$PATH$ path=
echo$path$
${path%/home/shiyanlou/mybin}$ path=
# 或使用通配符,*表示任意多個任意字符
${path%*/mybin}$ path=
能夠使用unset
命令刪除一個環境變量:
unset$temp
在上面咱們在 Shell 中修改了一個配置腳本文件以後(好比 zsh 的配置文件 home 目錄下的.zshrc
),每次都要退出終端從新打開甚至重啓主機以後其才能生效,非常麻煩,咱們能夠使用source
命令來讓其當即生效,如:
source$.zshrc
source
命令還有一個別名就是.
,注意與表示當前路徑的那個點區分開,雖然形式同樣,但做用和使用方式同樣,上面的命令若是替換成.
的方式就該是
$ . ./.zshrc
注意第一個點後面有一個空格,並且後面的文件必須指定完整的絕對或相對路徑名,source 則不須要。
與搜索相關的命令經常使用的有以下幾個whereis
,which
,find
,locate
。
whereis
簡單快速$whereiswho
你會看到它找到了三個路徑,兩個可執行文件路徑和一個 man 在線幫助文件所在路徑,這個搜索很快,由於它並無從硬盤中依次查找,而是直接從數據庫中查詢。whereis
只能搜索二進制文件(-b),man幫助文件(-m)和源代碼文件(-s)。若是想要得到更全面的搜索結果能夠使用locate
命令。
locate
快而全經過"/var/lib/mlocate/mlocate.db"數據庫查找,不過這個數據庫也不是實時更新的,系統會使用定時任務天天自動執行updatedb
命令更新一次,因此有時候你剛添加的文件,它可能會找不到,須要手動執行一次updatedb
命令(在咱們的環境中必須先執行一次該命令)。它能夠用來查找指定目錄下的不一樣文件類型,如查找 /etc 下全部以 sh 開頭的文件:
$ locate /etc/sh
注意,它不僅是在 etc 目錄下查找並會自動遞歸子目錄進行查找
查找 /usr/share/ 下全部 jpg 文件:
/usr/share/$ locate\*.jpg
注意要添加*
號前面的反斜槓轉義,不然會沒法找到
若是想只統計數目能夠加上-c
參數,-i
參數能夠忽略大小寫進行查找,whereis 的-b
,-m
,-s
一樣能夠是使用。
which
小而精which
自己是 Shell 內建的一個命令,咱們一般使用which
來肯定是否安裝了某個指定的軟件,由於它只從PATH
環境變量指定的路徑中去搜索命令:
which$man
find
精而細find
應該是這幾個命令中最強大的了,它不但能夠經過文件類型、文件名進行查找並且能夠根據文件的屬性(如文件的時間戳,文件的權限等)進行搜索。find
命令強大到,要把它將明白至少須要單獨好幾節課程才行,咱們這裏只介紹一些經常使用的內容。
在指定目錄下搜索指定文件名的文件:
/etc/$ find-name interfaces
注意 find 命令的路徑是做爲第一個參數的,基本命令格式爲 find [path] [option] [action]
與時間相關的命令參數:
參數 |
說明 |
|
最後訪問時間 |
|
建立時間 |
|
最後修改時間 |
下面以-mtime
參數舉例:
-mtime n
: n 爲數字,表示爲在n天以前的」一天以內「修改過的文件-mtime +n
: 列出在n天以前(不包含n天自己)被修改過的文件-mtime -n
: 列出在n天以內(包含n天自己)被修改過的文件newer file
: file爲一個已存在的文件,列出比file還要新的文件名
列出 home 目錄中,當天(24 小時以內)有改動的文件:
0$ find ~ -mtime
列出用戶家目錄下比Code文件夾新的文件:
$ find ~ -newer /home/shiyanlou/Code
《黑客帝國》電影裏滿屏幕代碼的「數字雨」,在 Linux 裏面你也能夠輕鬆實現這樣的效果,你只須要一個命令cmatrix
。
須要先安裝,由於 Ubuntu 沒有預裝:
updateinstall$ sudo apt-get;sudo apt-getcmatrix
裝好以後先不要急着執行,爲了看到更好的效果,咱們須要先修改終端的主題配色,修改成黑底綠字,修改方法見下圖:
而後按下F11
能夠全屏顯示。
文件打包與壓縮
實驗介紹
Linux 上經常使用的 壓縮/解壓 工具,介紹了 zip,rar,tar 的使用。
1、文件打包和解壓縮
在講 Linux 上的解壓縮工具以前,有必要先了解如下常見經常使用的壓縮包文件格式。在 Windows 上咱們最多見的不外乎這三種*.zip,*.rar,*.7z後綴的壓縮文件,而在 Linux 上面常見經常使用的除了以上這三種外,還有*.gz,*.xz,*.bz2,*.tar,*.tar.gz,*.tar.xz,*tar.bz2,簡單介紹以下:
文件後綴名 |
說明 |
*.zip |
zip程序打包壓縮的文件 |
*.rar |
rar程序壓縮的文件 |
*.7z |
7zip程序壓縮的文件 |
*.tar |
tar程序打包,未壓縮的文件 |
*.gz |
gzip程序(GNU zip)壓縮的文件 |
*.xz |
xz程序壓縮的文件 |
*.bz2 |
bzip2程序壓縮的文件 |
*.tar.gz |
tar打包,gzip程序壓縮的文件 |
*.tar.xz |
tar打包,xz程序壓縮的文件 |
*tar.bz2 |
tar打包,bzip2程序壓縮的文件 |
*.tar.7z |
tar打包,7z程序壓縮的文件 |
講了這麼多種壓縮文件,這麼多個命令,不過咱們通常只須要掌握幾個命令便可,包括zip,rar,tar。下面會依次介紹這幾個命令及對應的解壓命令。
1.zip壓縮打包程序
$ zip -r -q -o shiyanlou.zip /home/shiyanlou
$ du -h shiyanlou.zip
$ file shiyanlou.zip
上面命令將 shiyanlou 的 home 目錄打包成一個文件,並查看了打包後文件的大小和類型。第一行命令中,-r參數表示遞歸打包包含子目錄的所有內容,-q參數表示爲安靜模式,即不向屏幕輸出信息,-o,表示輸出文件,需在其後緊跟打包輸出文件名。後面使用du命令查看打包後文件的大小(後面會具體說明該命令)。
$ zip -r -9 -q -o shiyanlou_9.zip /home/shiyanlou -x ~/*.zip
$ zip -r -1 -q -o shiyanlou_1.zip /home/shiyanlou -x ~/*.zip
這裏添加了一個參數用於設置壓縮級別-[1-9],1表示最快壓縮但體積大,9表示體積最小但耗時最久。最後那個-x是爲了排除咱們上一次建立的 zip 文件,不然又會被打包進這一次的壓縮文件中,注意:這裏只能使用絕對路徑,不然不起做用。
咱們再用du命令分別查看默認壓縮級別、最低、最高壓縮級別及未壓縮的文件的大小:
$ du -h -d 0 *.zip ~ | sort
經過man 手冊可知:
這樣一目瞭然,你能夠看到默認壓縮級別應該是最高的,效果很明顯,不過你在環境中操做以後看到的大小可能跟圖上的有些不一樣,由於在你使用過程當中,會隨時還生成一些緩存文件在當前用戶的家目錄中,這對於咱們學習命令使用來講,是可有可無的,能夠忽略這些不一樣。
使用-e參數能夠建立加密壓縮包:
$ zip -r -e -o shiyanlou_encryption.zip /home/shiyanlou
注意: 關於zip命令,由於 Windows 系統與 Linux/Unix 在文本文件格式上的一些兼容問題,好比換行符(爲不可見字符),在 Windows 爲 CR+LF(Carriage-Return+Line-Feed:回車加換行),而在 Linux/Unix 上爲 LF(換行),因此若是在不加處理的狀況下,在 Linux 上編輯的文本,在 Windows 系統上打開可能看起來是沒有換行的。若是你想讓你在 Linux 建立的 zip 壓縮文件在 Windows 上解壓後沒有任何問題,那麼你還須要對命令作一些修改:
$ zip -r -l -o shiyanlou.zip /home/shiyanlou
須要加上-l參數將LF轉換爲CR+LF來達到以上目的。
2.使用unzip命令解壓縮zip文件
將shiyanlou.zip解壓到當前目錄:
$ unzip shiyanlou.zip
使用安靜模式,將文件解壓到指定目錄:
$ unzip -q shiyanlou.zip -d ziptest
上述指定目錄不存在,將會自動建立。若是你不想解壓只想查看壓縮包的內容你能夠使用-l參數:
$ unzip -l shiyanlou.zip
注意: 使用unzip解壓文件時咱們一樣應該注意兼容問題,不過這裏咱們關心的再也不是上面的問題,而是中文編碼的問題,一般 Windows 系統上面建立的壓縮文件,若是有有包含中文的文檔或以中文做爲文件名的文件時默認會採用 GBK 或其它編碼,而 Linux 上面默認使用的是 UTF-8 編碼,若是不加任何處理,直接解壓的話可能會出現中文亂碼的問題(有時候它會自動幫你處理),爲了解決這個問題,咱們能夠在解壓時指定編碼類型。
使用-O(英文字母,大寫o)參數指定編碼類型:
unzip -O GBK 中文壓縮文件.zip
3.rar打包壓縮命令
rar也是 Windows 上經常使用的一種壓縮文件格式,在 Linux 上能夠使用rar和unrar工具分別建立和解壓 rar 壓縮包。
$ sudo apt-get update
$ sudo apt-get install rar unrar
$ rm *.zip
$ rar a shiyanlou.rar .
上面的命令使用a參數添加一個目錄~到一個歸檔文件中,若是該文件不存在就會自動建立。
注意:rar 的命令參數沒有-,若是加上會報錯。
$ rar d shiyanlou.rar .zshrc
$ rar l shiyanlou.rar
全路徑解壓:
$ unrar x shiyanlou.rar
去掉路徑解壓:
$ mkdir tmp
$ unrar e shiyanlou.rar tmp/
rar命令參數很是多,上面只涉及了一些基本操做
4.tar打包工具
在 Linux 上面更經常使用的是tar工具,tar 本來只是一個打包工具,只是同時仍是實現了對 7z,gzip,xz,bzip2 等工具的支持,這些壓縮工具自己只能實現對文件或目錄(單獨壓縮目錄中的文件)的壓縮,沒有實現對文件的打包壓縮,因此咱們也無需再單獨去學習其餘幾個工具,tar 的解壓和壓縮都是同一個命令,只需參數不一樣,使用比較方便。
下面先掌握tar命令一些基本的使用方式,即不進行壓縮只是進行打包(建立歸檔文件)和解包的操做。
$ tar -cf shiyanlou.tar ~
上面命令中,-c表示建立一個 tar 包文件,-f用於指定建立的文件名,注意文件名必須緊跟在-f參數以後,好比不能寫成tar -fc shiyanlou.tar,能夠寫成tar -f shiyanlou.tar -c ~。你還能夠加上-v參數以可視的的方式輸出打包的文件。上面會自動去掉表示絕對路徑的/,你也能夠使用-P保留絕對路徑符。
$ mkdir tardir
$ tar -xf shiyanlou.tar -C tardir
$ tar -tf shiyanlou.tar
$ tar -cphf etc.tar /etc
對於建立不一樣的壓縮格式的文件,對於tar來講是至關簡單的,須要的只是換一個參數,這裏咱們就以使用gzip工具建立*.tar.gz文件爲例來講明。
$ tar -czf shiyanlou.tar.gz ~
$ tar -xzf shiyanlou.tar.gz
如今咱們要使用其餘的壓縮工具建立或解壓相應文件只須要更改一個參數便可:
壓縮文件格式 |
參數 |
*.tar.gz |
-z |
*.tar.xz |
-J |
*tar.bz2 |
-j |
tar 命令的參數不少,不過經常使用的就是上述這些,須要瞭解更多你能夠查看 man 手冊獲取更多幫助。
做業
天冷的時候,要是有個火爐就行了。這裏有個有趣的程序:
$ sudo apt-get install libaa-bin
# 提示command not found,請自行解決
$ aafire
本節實驗的文件系統操做的內容十分簡單,只會包含幾個命令的幾個參數的講解,但掌握這些也將對你在學習 Linux 和實驗樓後續其餘課程的過程當中有極大幫助。
由於本課程的定位爲入門基礎,儘快上手,故沒有打算涉及太多理論內容,前面省略了關於 Linux 文件系統的一些基本知識,也由於咱們是在線實驗環境,因此也避開了不多一部分但又十分重要的關於硬件的內容,咱們只能期待用戶可以抱着提升自學能力的心態本身去補充相關的知識。
$ df
在實驗樓的環境中你將看到以下的輸出內容:
但在實際的物理主機上會更像這樣:
通常使用狀況下,咱們更多隻是關心第一行的內容也就是環境中的rootfs
或者物理主機上的/dev/sda2
"rootfs" : (Root File System)它是 Ramfs(Ramfs 是一個很是簡單的 Linux 文件系統用於實現磁盤緩存機制做爲動態可調整大小的基於 ram 的文件系統)或者 tmpfs 的一個特殊實例,它做爲系統啓動時內核載入內存以後,在掛載真正的的磁盤以前的一個臨時文件系統。一般的主機會在系統啓動後用磁盤上的文件系統替換,只是在一些嵌入式系統中會只存在一個 rootfs ,或者像咱們目前遇到的狀況運行在虛擬環境中共享主機資源的系統也可能會採用這種方式。
物理主機上的 /dev/sda2 是對應着主機硬盤的分區,後面的數字表示分區號,數字前面的字母 a 表示第幾塊硬盤(也多是可移動磁盤),你若是主機上有多塊硬盤則可能還會出現 /dev/sdb,/dev/sdc 這些磁盤設備都會在 /dev 目錄下以文件的存在形式。
接着你還會看到"1k-blocks"這個陌生的東西,它表示以磁盤塊大小的方式顯示容量,後面爲相應的以塊大小表示的已用和可用容量,在你瞭解 Linux 的文件系統以前這個就先無論吧,咱們以一種你應該看得懂的方式展現:
$ df -h
如今你就能夠使用命令查看你主機磁盤的使用狀況了。至於掛載點若是你還記得前面第 4 節介紹 Linux 目錄樹結構的內容,那麼你就應該能很好的理解掛載的概念,這裏就再也不贅述。
這個命令前面其實已經用了不少次了:
# 默認一樣以 blocks 的大小展現
$ du
# 加上`-h`參數,以更易讀的方式展現
$ du -h
-d
參數指定查看目錄的深度
# 只查看1級目錄的信息
-d$ du -h0 ~
# 查看2級
-d$ du -h1 ~
du
(estimate file space usage)命令與df
(report file system disk space usage)只用一字只差,首先就但願注意不要弄混淆了,以能夠像我這樣從man手冊中獲取命令的完整描述,記全稱就不會搞混了。
一般狀況下,這一小節應該直接將如何掛載卸載磁盤,如何格式化磁盤,如何分區,但如你所見,咱們的環境中沒東西給你掛,也沒東西給你格和分,因此首先咱們會先建立一個虛擬磁盤來進行後續的練習操做
dd
命令用於轉換和複製文件,不過它的複製不一樣於cp
。以前提到過關於 Linux 的很重要的一點,一切即文件,在 Linux 上,硬件的設備驅動(如硬盤)和特殊設備文件(如/dev/zero
和/dev/random
)都像普通文件同樣,只要在各自的驅動程序中實現了對應的功能,dd 也能夠讀取自和/或寫入到這些文件。這樣,dd
也能夠用在備份硬件的引導扇區、獲取必定數量的隨機數據或者空數據等任務中。dd
程序也能夠在複製時處理數據,例如轉換字節序、或在 ASCII 與 EBCDIC 編碼間互換。
dd
的命令行語句與其餘的 Linux 程序不一樣,由於它的命令行選項格式爲選項
=
值
,而不是更標準的--
選項
值
或-
選項
=
值
。dd
默認從標準輸入中讀取,並寫入到標準輸出中,但能夠用選項if
(input file,輸入文件)和of
(output file,輸出文件)改變。
咱們先來試試用dd
命令從標準輸入讀入用戶輸入到標準輸出或者一個文件:
# 輸出到文件
101# 或者 dd if=/dev/stdin of=test bs=10 count=1$ dd of=test bs=count=
# 輸出到標準輸出
if/dev/stdin/dev/stdout101$ dd=of=bs=count=
上述命令從標準輸入設備讀入用戶輸入(缺省值,因此可省略)而後輸出到 test 文件,bs
(block size)用於指定塊大小(缺省單位爲 Byte,也可爲其指定如'K','M','G'等單位),count
用於指定塊數量。如上圖所示,我指定只讀取總共 10 個字節的數據,當我輸入了「hello shiyanlou」以後加上空格回車總共 16 個字節(一個英文字符佔一個字節)內容,顯然超過了設定大小。使用和du
和cat
命令看到的寫入完成文件實際內容確實只有 10 個字節(那個黑底百分號表示這裏沒有換行符),而其餘的多餘輸入將被截取並保留在標準輸入。
前面說到dd
在拷貝的同時還能夠實現數據轉換,那下面就舉一個簡單的例子:將輸出的英文字符轉換爲大寫再寫入文件:
if/dev/of101$ dd=stdin=test bs=count=conv=ucase
你能夠在man
文檔中查看其餘全部轉換參數。
經過上面一小節,你應該掌握了dd
的基本使用,下面就來使用dd
命令來完成建立虛擬磁盤的第一步。
從/dev/zero
設備建立一個容量爲 256M 的空文件:
if/dev/zero1256$ dd=of=virtual.img bs=M count=
$ du -h virtual.img
而後咱們要將這個文件格式化(寫入文件系統),這裏咱們要學到一個(準確的說是一組)新的命令來完成這個需求。
你能夠在命令行輸入 sudo mkfs
而後按下Tab
鍵,你能夠看到不少個以 mkfs 爲前綴的命令,這些不一樣的後綴其實就是表示着不一樣的文件系統,能夠用 mkfs 格式化成的文件系統。
咱們能夠簡單的使用下面的命令來將咱們的虛擬磁盤鏡像格式化爲ext4
文件系統:
virtual$ sudo mkfs.ext4.img
能夠看到實際 mkfs.ext4 是使用 mke2fs 來完成格式化工做的。mke2fs 的參數不少,不過咱們也不會常常格式化磁盤來玩,因此就掌握這基本用法吧,等你有特殊需求時,再查看 man 文檔解決。
更多關於文件系統的知識,請查看wiki: 文件系統 ext3,ext4
若是你想一想知道 Linux 支持哪些文件系統你能夠輸入ls -l /lib/modules/$(uname -r)/kernel/fs
(咱們的環境中沒法查看)查看。
用戶在 Linux/UNIX 的機器上打開一個文件之前,包含該文件的文件系統必須先進行掛載的動做,此時用戶要對該文件系統執行 mount 的指令以進行掛載。一般是使用在 USB 或其餘可移除存儲設備上,而根目錄則須要始終保持掛載的狀態。又由於 Linux/UNIX 文件系統能夠對應一個文件而不必定要是硬件設備,因此能夠掛載一個包含文件系統的文件到目錄樹。
Linux/UNIX 命令行的 mount 指令是告訴操做系統,對應的文件系統已經準備好,能夠使用了,而該文件系統會對應到一個特定的點(稱爲掛載點)。掛載好的文件、目錄、設備以及特殊文件便可提供用戶使用。
咱們先來使用mount
來查看下主機已經掛載的文件系統:
$ sudo mount
輸出的結果中每一行表示一個設備或虛擬設備,每一行最前面是設備名,而後是 on 後面是掛載點,type 後面表示文件系統類型,再後面是掛載選項(好比能夠在掛載時設定以只讀方式掛載等等)。
那麼咱們如何掛載真正的磁盤到目錄樹呢,mount
命令的通常格式以下:
mount[options][source][directory]
一些經常使用操做:
mount[-o [操做選項][-t 文件系統類型][-w|--rw|--ro][文件系統源][掛載點]]
咱們如今直接來掛載咱們建立的虛擬磁盤鏡像到/mnt
目錄:
loop$ mount -o-t ext4 virtual.img /mnt
# 也能夠省略掛載類型,不少時候 mount 會自動識別
# 以只讀方式掛載
loop$ mount -o--ro virtual.img /mnt
# 或者mount -o loop,ro virtual.img /mnt
# 命令格式 sudo umount 已掛載設備名或者掛載點,如:
$ sudo umount /mnt
不過遺憾的是,因爲咱們環境的問題(環境中使用的 Linux 內核在編譯時沒有添加對 Loop device的支持),因此你將沒法掛載成功:
另外關於 loop 設備,你可能會有諸多疑問,那麼請看下面來自維基百科/dev/loop的說明:
在類 UNIX 系統中,/dev/loop(或稱vnd (vnode disk)、lofi(循環文件接口))是一種僞設備,這種設備使得文件能夠如同塊設備通常被訪問。
在使用以前,循環設備必須與現存文件系統上的文件相關聯。這種關聯將提供給用戶一個應用程序接口,接口將容許文件視爲塊特殊文件(參見設備文件系統)使用。所以,若是文件中包含一個完整的文件系統,那麼這個文件就能如同磁盤設備通常被掛載。
這種設備文件常常被用於光盤或是磁盤鏡像。經過循環掛載來掛載包含文件系統的文件,便使處在這個文件系統中的文件得以被訪問。這些文件將出如今掛載點目錄。若是掛載目錄中自己有文件,這些文件在掛載後將被禁止使用。
一樣由於環境緣由中沒有物理磁盤,也沒法建立虛擬磁盤的緣由咱們就沒法實驗練習使用該命令了,下面我將以個人物理主機爲例講解如何爲磁盤分區。
# 查看硬盤分區表信息
-l$ sudo fdisk
輸出結果中開頭顯示了我主機上的磁盤的一些信息,包括容量扇區數,扇區大小,I/O 大小等信息。
咱們重點開一下中間的分區信息,/dev/sda1,/dev/sda2 爲主分區分別安裝了 Windows 和 Linux 操做系統,/dev/sda3 爲交換分區(能夠理解爲虛擬內存),/dev/sda4 爲擴展分區其中包含 /dev/sda5,/dev/sda6,/dev/sda7,/dev/sda8 四個邏輯分區,由於主機上有幾個分區之間有空隙,沒有對齊邊界扇區,因此分區之間的不是徹底連續的。
# 進入磁盤分區模式
virtual$ sudo fdisk.img
在進行操做前咱們首先應先規劃好咱們的分區方案,這裏我將在使用 128M(可用 127M 左右)的虛擬磁盤鏡像建立一個 30M 的主分區剩餘部分爲擴展分區包含 2 個大約 45M 的邏輯分區。
操做完成後輸入p
查看結果以下:
最後不要忘記輸入w
寫入分區表。
0$ sudo losetup /dev/loopvirtual.img
# 若是提示設備忙你也能夠使用其它的迴環設備,"ls /dev/loop*"參看全部迴環設備
# 解除設備關聯
0$ sudo losetup -d /dev/loop
而後再使用mkfs
格式化各分區(前面咱們是格式化整個虛擬磁盤鏡像文件或磁盤),不過格式化以前,咱們還要爲各分區創建虛擬設備的映射,用到kpartx
工具,須要先安裝:
$ sudo apt-get install kpartx
0$ sudo kpart kpartx -av /dev/loop
# 取消映射
0$ sudo kpart kpartx -dv /dev/loop
接着再是格式化,咱們將其所有格式化爲 ext4:
$ sudo mkfs.ext4 -q /dev/mapper/loop0p1
$ sudo mkfs.ext4 -q /dev/mapper/loop0p5
$ sudo mkfs.ext4 -q /dev/mapper/loop0p6
格式化完成後在/media
目錄下新建四個空目錄用於掛載虛擬磁盤:
mkdir_13$-p /media/virtualdisk{..}
# 掛載磁盤分區
$ sudo mount /dev/mapper/loop0p1 /media/virtualdisk_1
$ sudo mount /dev/mapper/loop0p5 /media/virtualdisk_2
$ sudo mount /dev/mapper/loop0p6 /media/virtualdisk_3
# 卸載磁盤分區
$ sudo umount /dev/mapper/loop0p1
$ sudo umount /dev/mapper/loop0p5
$ sudo umount /dev/mapper/loop0p6
而後:
$ df -h
cowsay
命令,可讓你在終端裏以一種動物說話的形式打印出一段話。
# 安裝
$ sudo apt-get install cowsay
# 默認是一隻牛
$ cowsay hello shiyanlou
# 加上'-l'參數打印全部支持的動物(其實不僅是動物)種類
$ cowsay -l
# 使用'-f'參數選擇動物種類
$ cowsay -f elephant hello shiyanlou
# 此外它還能夠結合咱們以前的做業講過的 fortune 命令一塊兒使用
| cowsay -f daemon$ fortune
Linux下的幫助命令
實驗介紹
咱們時常使用 Linux 的命令,一些經常使用的命令即便不背咱們也能記住,而一些較長的命令或是一些不經常使用的參數甚至是不經常使用的命令到用時怎麼也想不出來。本課程將帶你好好利用 Linux 系統所自帶的幫助工具與文檔了。
實驗涉及的知識點
1、內建命令與外部命令
什麼是內建命令,什麼是外部命令呢?這和幫助命令又有什麼關係呢?
由於有一些查看幫助的工具在內建命令與外建命令上是有區別對待的。
內建命令其實是 shell 程序的一部分,其中包含的是一些比較簡單的 Linux 系統命令,這些命令是寫在bash源碼的builtins裏面的,並由 shell 程序識別並在 shell 程序內部完成運行,一般在 Linux 系統加載運行時 shell 就被加載並駐留在系統內存中。並且解析內部命令 shell 不須要建立子進程,所以其執行速度比外部命令快。好比:history、cd、exit 等等。
外部命令是 Linux 系統中的實用程序部分,由於實用程序的功能一般都比較強大,因此其包含的程序量也會很大,在系統加載時並不隨系統一塊兒被加載到內存中,而是在須要時纔將其調用內存。雖然其不包含在 shell 中,可是其命令執行過程是由 shell 程序控制的。外部命令是在 Bash 以外額外安裝的,一般放在/bin,/usr/bin,/sbin,/usr/sbin等等。好比:ls、vi等。
簡單來講就是一個是天生自帶的天賦技能,一個是後天得來附加技能。咱們能夠使用 type 命令來區分命令是內建的仍是外部的。例如這兩個得出的結果是不一樣的
type exit
type service
獲得的是兩種結果,如果對ls你還能獲得第三種結果
#獲得這樣的結果說明是內建命令,正如上文所說內建命令都是在 bash 源碼中的 builtins 的.def中
xxx is a shell builtin
#獲得這樣的結果說明是外部命令,正如上文所說,外部命令在/usr/bin or /usr/sbin等等中
xxx is /usr/sbin/xxx
#如果獲得alias的結果,說明該指令爲命令別名所設定的名稱;
xxx is an alias for xx --xxx
2、幫助命令的使用
1. help 命令
本實驗環境是 zsh,而 zsh 中內置並無 help 命令,咱們能夠進入 bash 中,在 bash 中內置有該命令
bash
作好了以上的準備,咱們就能夠愉快的使用 help 命令了,咱們能夠嘗試下這個命令:
help ls
獲得的結果如圖所示,爲何是這樣的結果?
由於 help 命令是用於顯示 shell 內建命令的簡要幫助信息。幫助信息中顯示有該命令的簡要說明以及一些參數的使用以及說明,必定記住 help 命令只能用於顯示內建命令的幫助信息,否則就會獲得你剛剛獲得的結果。如圖中 exit,cd 即是內建命令
那若是是外部命令怎麼辦,不能就這麼拋棄它呀。其實外部命令的話基本上都有一個參數--help,這樣就能夠獲得相應的的幫助,看到你想要的東西了。試試下面這個命令是否是能看到你想要的東西了。
ls --help
2. man 命令
你能夠嘗試下這個命令
man ls
獲得的內容比用 help 更多更詳細,並且 man 沒有內建與外部命令的區分,由於 man 工具是顯示系統手冊頁中的內容,也就是一本電子版的字典,這些內容大多數都是對命令的解釋信息,還有一些相關的描述。經過查看系統文檔中的 man 也能夠獲得程序的更多相關信息和 Linux 的更多特性。
是否是好用許多,固然也不表明 help 就沒有存在的必要,當你很是緊急只是忘記改用那個參數什麼的時候,help 這種顯示簡單扼要的信息就特別使用,如果不太緊急的時候就能夠用 man 這種詳細描述的查詢方式
在嘗試上面這個命令是咱們會發現最左上角顯示「 LS (1)」,在這裏,「 LS 」表示手冊名稱,而「(1)」表示該手冊位於第一章節。這個章節又是什麼?在 man 手冊中一共有這麼幾個章節
章節數 |
說明 |
1 |
Standard commands (標準命令) |
2 |
System calls (系統調用) |
3 |
Library functions (庫函數) |
4 |
Special devices (設備說明) |
5 |
File formats (文件格式) |
6 |
Games and toys (遊戲和娛樂) |
7 |
Miscellaneous (雜項) |
8 |
Administrative Commands (管理員命令) |
9 |
其餘(Linux特定的), 用來存放內核例行程序的文檔。 |
打開手冊以後咱們能夠經過 pgup 與 pgdn 或者上下鍵來上下翻看,能夠按 q 退出當前頁面
3. info 命令
要是你以爲man顯示的信息都還不夠,知足不了你的需求,那試試這個命令
#該命令在本環境中沒有,通常的 bash 會自帶的有。
info ls
獲得的信息是否是比 man 還要多了,info 來自自由軟件基金會的 GNU 項目,是 GNU 的超文本幫助系統,可以更完整的顯示出 GNU 信息。因此獲得的信息固然更多
man 和 info 就像兩個集合,它們有一個交集部分,但與 man 相比,info 工具可顯示更完整的 GNU 工具信息。若 man 頁包含的某個工具的概要信息在 info 中也有介紹,那麼 man 頁中會有「請參考 info 頁更詳細內容」的字樣。
3、實驗總結
本節咱們講解了內建與外部命令的差異,以及相關的幫助命令的使用。這樣經過官方的文檔幫助咱們最快最有效率的解決當前所遇到的窘境。靈活的使用三個幫助命令,可以很大的提升咱們的工做效率
咱們時常會有一些按期定時的任務,如週期性的清理一下/tmp,週期性的去備份一次數據庫,週期性的分析日誌等等。並且有時候由於某些因素的限制,執行該任務的時間會很尷尬。本課程將帶你很好的利用 Linx 系統的計劃工具
crontab 命令常見於 Unix 和類 Unix 的操做系統之中(Linux 就屬於類 Unix 操做系統),用於設置週期性被執行的指令。該命令從輸入設備讀取指令,並將其存放於 crontab 文件中,以供以後讀取和執行。一般,crontab 儲存的指令被守護進程激活,crond 爲其守護進程,crond 經常在後臺運行,每一分鐘會檢查一次是否有預約的做業須要執行。
經過 crontab 命令,咱們能夠在固定的間隔時間執行指定的系統指令或 shell script 腳本。時間間隔的單位能夠是分鐘、小時、日、月、周的任意組合。
crontab 在本實驗環境中須要作一些特殊的準備,首先咱們會啓動 rsyslog,以便咱們能夠經過日誌中的信息來了解咱們的任務是否真正的被執行了(在本實驗環境中須要手動啓動,而在本身本地中 Ubuntu 會默認自行啓動不須要手動啓動)
sudoservice rsyslog start
在本實驗環境中 crontab 也是不被默認啓動的,同時不能在後臺由 upstart 來管理,因此須要咱們來啓動它(一樣在本實驗環境中須要手動啓動,本身的本地 Ubuntu 的環境中也不須要手動啓動)
sudocron-f &
下面將開始 crontab 的使用了,咱們經過下面一個命令來添加一個計劃任務
-ecrontab
第一次啓動會出現這樣一個畫面,這是讓咱們選擇編輯的工具,選擇第一個基本的 vim 就能夠了
而選擇後咱們會進入這樣一個畫面,這就是添加計劃的地方了,與通常的配置文檔相同,以#號開頭的都是註釋,經過文檔的最後一排咱們能夠猜猜 crontab 的格式是什麼樣的呢?
咱們經過這樣一張圖來了解 crontab 的文檔編輯的格式與參數
在瞭解命令格式以後,咱們經過這樣的一個例子來完成一個任務的添加,在文檔的最後一排加上這樣一排命令,該任務是每分鐘咱們會在/home/shiyanlou目錄下建立一個以當前的年月日時分秒爲名字的空白文件
/1 * * * * touch /home/shiyanlou/*$(date +\%Y\%m\%d\%H\%M\%S)
注意 「 % 」 在 crontab 文件中,有結束命令行、換行、重定向的做用,前面加 」 \ 」 符號轉意,不然,「 % 」 符號將執行其結束命令行或者換行的做用,而且其後的內容會被作爲標準輸入發送給前面的命令。
添加成功後咱們會獲得最後一排 installing new crontab 的一個提示
固然咱們也能夠經過這樣的一個指令來查看咱們添加了哪些任務
-lcrontab
經過圖中的顯示,咱們也能夠看出,咱們正確的保存而且添加成功了該任務的
雖然咱們添加了任務,可是若是 cron 的守護進程並無啓動,它根本都不會監測到有任務,固然也就不會幫咱們執行,咱們能夠經過一下2種方式來肯定咱們的 cron 是否成功的在後臺啓動,默默的幫咱們作事,如果沒有就得執行上文準備中的第二步了
grepps aux |cron
or
pgrep cron
經過這個截圖咱們能夠看到任務在建立以後便建立了一個當時時間的文件(也就是10點18分04秒的時候),後續在每分鐘的01秒時執行一次咱們的任務
咱們經過這樣一個命令能夠查看到執行任務命令以後在日誌中的信息反饋
-flogsudo tail/var//syslog
從圖中咱們能夠看到分別在10點1八、1九、20、2一、2二、23分的01秒爲咱們在 shiyanlou 用戶的家目錄下建立了文件
當咱們並不須要這個任務的時候咱們能夠使用這麼一個命令去刪除任務
crontab-r
經過圖中咱們能夠看出咱們刪除以後再查看任務列表,系統已經顯示該用戶並無任務哦
這個 crontab -e 是針對使用者的 cron 來設計的,也就是每一個用戶在添加任務,就會在 /var/spool/cron/crontabs 中添加一個該用戶本身的任務文檔,這樣能夠作到隔離,獨立,不會混亂。
若是是系統的例行性任務時,該怎麼辦呢?是否仍是須要以 crontab -e 來管理你的例行性工做排程呢?固然不須要,你只要編輯 /etc/crontab 這個檔案就能夠啦!有一點須要特別注意喔!那就是 crontab -e 這個 crontab 實際上是 /usr/bin/crontab 這個執行的,只是你能夠 root 的身份編輯一下這個文檔!
基本上, cron 這個服務的最低偵測限制是分鐘,因此 cron 會每分鐘去讀取一次 /etc/crontab 與 /var/spool/cron/crontabs 裏面的資料內容 』,所以,只要你編輯完 /etc/crontab 這個文檔,而且將他存儲以後,那麼 cron 的設定就自動的執行了!
在/etc目錄下,咱們能夠觀察到關於 cron 的文件有一下幾個,他們的做用又是什麼
固然,以上的時間均是系統默認時間,能夠根據本身的需求進行修改。
更多的相關知識咱們能夠用上節所學到的man命令來查看,
固然若想進一步的學習該知識或者相關只是可查看鳥哥私房菜
本節咱們講解了 crontab 的一些簡單的應用和一些簡單的概念。crontab 是 Linux 系統中添加計劃任務,定時執行一些必要的腳本所必不可少的工具。
順序執行、選擇執行、管道、cut 命令、grep 命令、wc 命令、sort 命令等,高效率使用 Linux 的技巧。
一般狀況下,咱們每次只能在終端輸入一條命令,按下回車執行,執行完成後,咱們再輸入第二條命令,而後再按回車執行…… 你可能會遇到以下使用場景:我須要使用apt-get
安裝一個軟件,而後安裝完成後當即運行安裝的軟件(或命令工具),又恰巧你的主機才更換的軟件源尚未更新軟件列表(好比以前咱們的環境中,每次從新開始實驗就得sudo apt-get update,如今已經沒有這個問題了),那麼你可能會有以下一系列操做:
$ sudo apt-get update
# 等待——————————而後輸入下面的命令
$ sudo apt-get install some-tool
# 等待——————————而後輸入下面的命令
$ some-tool
這時你可能就會想要是我能夠一次性輸入完,讓它本身去一次執行各命令就行了,這就是咱們這一小節要解決的問題。
簡單的順序執行你能夠使用;
來完成,好比上述操做你能夠:
getget$ sudo apt-update;sudo apt-install some-tool;some-tool
# 讓它本身運行
關於上面的操做,不知你有沒有思考過一個問題,若是咱們在讓它自動順序執行命令時,前面的命令執行不成功,然後面的命令又依賴與上一條命令的結果,那麼就會形成花了時間,最終卻獲得一個錯誤的結果,並且有時候直觀的看你還沒法判斷結果是否正確。那麼咱們須要可以有選擇性的來執行命令,好比上一條命令執行成功才繼續下一條,或者不成功又該作出其它什麼處理,好比咱們使用which
來查找是否安裝某個命令,若是找到就執行該命令,不然什麼也不作(雖然這個操做沒有什麼實際意義,但可幫你更好的理解一些概念):
/dev/nullin$ which cowsay>&& cowsay -f head-ohch~
你若是沒有安裝cowsay
,你能夠先執行一次上述命令,你會發現什麼也沒發生,你再安裝好以後你再執行一次上述命令,你也會發現一些驚喜。
上面的&&
就是用來實現選擇性執行的,它表示若是前面的命令執行結果(不是表示終端輸出的內容,而是表示命令執行狀態的結果)返回0則執行後面的,不然不執行,你能夠從$?
環境變量獲取上一次命令的返回結果:
學習過 C 語言的用戶應該知道在 C 語言裏面&&
表是邏輯與,並且還有一個||
表示邏輯或,一樣 Shell 也有一個||
,它們的區別就在於,shell中的這兩個符號除了也可用於表示邏輯與和或以外,就是能夠實現這裏的命令執行順序的簡單控制。||
在這裏就是與&&
相反的控制效果,當上一條命令執行結果爲≠0($?≠0)時則執行它後面的命令:
/dev/null||"cowsay has not been install, please run 'sudo apt-get install cowsay' to install"$ which cowsay>echo
除了上述基本的使用以外,咱們還能夠結合這&&
和||
來實現一些操做,好比:
whichecho"exist"echo"not exist"$cowsay>/dev/null &&||
我畫個流程圖來解釋一下上面的流程:
上面咱們講到將&&
和||
結合起來使用,那麼是否以任意順序都行?好比上面咱們是&&
在前||
在後,反過來能夠麼?會不會有問題?
管道是什麼,管道是一種通訊機制,一般用於進程間的通訊(也可經過socket進行網絡通訊),它表現出來的形式就是將前面每個進程的輸出(stdout)直接做爲下一個進程的輸入(stdin)。
管道又分爲匿名管道和具名管道(這裏將不會討論在源程序中使用系統調用建立並使用管道的狀況,它與命令行的管道在內核中實際都是採用相同的機制)。咱們在使用一些過濾程序時常常會用到的就是匿名管道,在命令行中由|
分隔符表示,|
在前面的內容中咱們已經屢次使用到了。具名管道簡單的說就是有名字的管道,一般只會在源程序中用到具名管道。下面咱們就將經過一些經常使用的能夠使用管道的"過濾程序"來幫助你熟練管道的使用。
先試用一下管道,好比查看/etc
目錄下有哪些文件和目錄,使用ls
命令來查看:
$ ls -al /etc
有太多內容,屏幕不能徹底顯示,這時候能夠使用滾動條或快捷鍵滾動窗口來查看。不過這時候能夠使用管道:
| less$ ls -al /etc
經過管道將前一個命令(ls
)的輸出做爲下一個命令(less
)的輸入,而後就能夠一行一行地看。
打印/etc/passwd
文件中以:
爲分隔符的第1個字段和第6個字段分別表示用戶名和其家目錄:
-d':'-f$ cut /etc/passwd1,6
打印/etc/passwd
文件中每一行的前N個字符:
# 前五個(包含第五個)
5$ cut /etc/passwd -c -
# 前五個以後的(包含第五個)
5$ cut /etc/passwd -c-
# 第五個
5$ cut /etc/passwd -c
# 2到5之間的(包含第五個)
25$ cut /etc/passwd -c-
grep
命令是很強大的,也是至關經常使用的一個命令,它結合正則表達式能夠實現很複雜卻很高效的匹配和查找,不過在學習正則表達式以前,這裏介紹它簡單的使用,而關於正則表達式後面將會有單獨一小節介紹到時會再繼續學習grep
命令和其餘一些命令。
grep
命令的通常形式爲:
grep[命令選項][文件]...用於匹配的表達式...
仍是先體驗一下,咱們搜索/home/shiyanlou
目錄下全部包含"shiyanlou"的全部文本文件,並顯示出如今文本中的行號:
grep"shiyanlou"$-rnI~
-r
參數表示遞歸搜索子目錄中的文件,-n
表示打印匹配項行號,-I
表示忽略二進制文件。這個操做實際沒有多大意義,但能夠感覺到grep
命令的強大與實用。
固然也能夠在匹配字段中使用正則表達式,下面簡單的演示:
# 查看環境變量中以"yanlou"結尾的字符串
export".*yanlou$"$| grep
其中$
就表示一行的末尾。
wc 命令用於統計並輸出一個文件中行、單詞和字節的數目,好比輸出/etc/passwd
文件的統計信息:
$ wc /etc/passwd
分別只輸出行數、單詞數、字節數、字符數和輸入文本中最長一行的字節數:
# 行數
$ wc -l /etc/passwd
# 單詞數
$ wc -w /etc/passwd
# 字節數
$ wc -c /etc/passwd
# 字符數
$ wc -m /etc/passwd
# 最長行字節數
$ wc -L /etc/passwd
注意:對於西文字符來講,一個字符就是一個字節,但對於中文字符一個漢字是大於2個字節的,具體數目是由字符編碼決定的
再來結合管道來操做一下,下面統計 /etc 下面全部目錄數:
-l$ ls -dl /etc/*/ | wc
這個命令前面咱們也是用過屢次,功能很簡單就是將輸入按照必定方式排序,而後再輸出,它支持的排序有按字典排序,數字排序,按月份排序,隨機排序,反轉排序,指定特定字段進行排序等等。
默認爲字典排序:
sort$ cat /etc/passswd |
反轉排序:
sort$ cat /etc/passwd |-r
按特定字段排序:
sort':'3$ cat /etc/passwd |-t-k
上面的-t
參數用於指定字段的分隔符,這裏是以":"做爲分隔符;-k
字段號
用於指定對哪個字段進行排序。這裏/etc/passwd
文件的第三個字段爲數字,默認狀況下是一字典序排序的,若是要按照數字排序就要加上-n
參數:
sort':'3$ cat /etc/passwd |-t-k-n
uniq
命令能夠用於過濾或者輸出重複行。
咱們能夠使用history
命令查看最近執行過的命令(實際爲讀取${SHELL}_history文件,如咱們環境中的~/.zsh_history文件),不過你可能只想查看使用了那個命令而不須要知道具體幹了什麼,那麼你可能就會要想去掉命令後面的參數而後去掉重複的命令:
history-d' '-f$| cut -c 8- | cut1 | uniq
而後通過層層過濾,你會發現確是只輸出了執行的命令那一列,不過去重效果好像不明顯,仔細看你會發現它趨勢去重了,只是不那麼明顯,之因此不明顯是由於uniq
命令只能去連續重複的行,不是全文去重,因此要達到預期效果,咱們先排序:
history-d' '-f$| cut -c 8- | cut1 | sort | uniq
# 或者$ history | cut -c 8- | cut -d ' ' -f 1 | sort -u
這就是 Linux/UNIX 哲學吸引人的地方,大繁至簡,一個命令只幹一件事卻能幹到最好。
# 輸出重複過的行(重複的只輸出一個)及重複次數
history-d' '-f$| cut -c 8- | cut1 | sort | uniq -dc
# 輸出全部重複的行
history-d' '-f$| cut -c 8- | cut1 | sort | uniq -D
文本處理命令還有不少,下一節將繼續介紹一些經常使用的文本處理的命令。
使用之前介紹過的方法,安裝aview
和imagemagick
,而後用asciiview
命令顯示圖片,使用方法能夠用 man 命令查看。
dh能夠的,這個實驗先用實驗樓的環境打開那個網址,把它保存在Desktop上面,而後再用asciiview命令打開就好,臥槽,看論壇網友的做業完成的,真有一種在上課學習的感受,我愛實驗樓!
Linus大神的照片地址http://labfile.oss.aliyuncs.com/courses/1/Linus.png
這一節咱們將介紹這幾個命令tr
(注意不是tar),col
,join
,paste
。實際這一節是上一節關於能實現管道操做的命令的延續,因此咱們依然將結合管道來熟悉這些命令的使用。
tr 命令能夠用來刪除一段文本信息中的某些文字。或者將其進行轉換。
tr[option].SET1[SET2]..
選項 |
說明 |
|
刪除和set1匹配的字符,注意不是全詞匹配也不是按字符順序匹配 |
|
去除set1指定的在輸入文本中連續並重復的字符 |
# 刪除 "hello shiyanlou" 中全部的'o','l','h'
echo'hello shiyanlou'-d'olh'$| tr
# 將"hello" 中的ll,去重爲一個l
echo'hello'-s'l'$| tr
# 將輸入文本,所有轉換爲大寫或小寫輸出
'[:lower:]''[:upper:]'$ cat /etc/passwd | tr
# 上面的'[:lower:]' '[:upper:]'你也能夠簡單的寫做'[a-z]' '[A-Z]',固然反過來將大寫變小寫也是能夠的
更多 tr 的使用,你能夠使用--help
或者man tr
得到。
col 命令能夠將Tab
換成對等數量的空格建,或反轉這個操做。
col [option]
選項 |
說明 |
|
將 |
|
將空格轉換爲 |
# 查看 /etc/protocols 中的不可見字符,能夠看到不少 ^I ,這其實就是 Tab 轉義成可見字符的符號
$ cat -A /etc/protocols
# 使用 col -x 將 /etc/protocols 中的 Tab 轉換爲空格,而後再使用 cat 查看,你發現 ^I 不見了
| col -x |$ cat /etc/protocolscat -A
學過數據庫的用戶對這個應該不會陌生,這個命令就是用於將兩個文件中包含相同內容的那一行合併在一塊兒。
join[option]... file1 file2
選項 |
說明 |
|
指定分隔符,默認爲空格 |
|
忽略大小寫的差別 |
|
指明第一個文件要用哪一個字段來對比,,默認對比第一個字段 |
|
指明第二個文件要用哪一個字段來對比,,默認對比第一個字段 |
# 建立兩個文件
'1 hello'$ echo> file1
'1 shiyanlou'$ echo> file2
$ join file1 file2
# 將/etc/passwd與/etc/shadow兩個文件合併,指定以':'做爲分隔符
':'$ sudo join -t/etc/passwd /etc/shadow
# 將/etc/passwd與/etc/group兩個文件合併,指定以':'做爲分隔符, 分別比對第4和第3個字段
':'1423$ sudo join -t-/etc/passwd -/etc/group
paste
這個命令與join
命令相似,它是在不對比數據的狀況下,簡單地將多個文件合併一塊兒,以Tab
隔開。
paste[option]file...
選項 |
說明 |
|
指定合併的分隔符,默認爲Tab |
|
不合併到一行,每一個文件爲一行 |
echo$hello > file1
echo$shiyanlou > file2
echo$www.shiyanlou.com > file3
-d':'$ pastefile1 file2 file3
-s$ pastefile1 file2 file3
上面這些命令不是全部你都會常常用到,不過它們確是很實用的,熟練掌握以後,能夠減輕不少工做量,好比不停的用鼠標操做在 gedit 裏面複製粘貼賦值粘貼,將兩個文件的內容合併爲一個文件,這本來只須要一個命令就能完成。
一、在《文件打包與解壓縮》一節實驗中提到 Windows/dos 與 Linux/UNIX 文本文件一些特殊字符不一致,如斷行符 Windows 爲 CR+LF(\r\n
),Linux/UNIX 爲 LF(\n
)。使用cat -A
文本
能夠看到文本中包含的不可見特殊字符。Linux 的\n
表現出來就是一個$
,而 Windows/dos 的表現爲^M$
,能夠直接使用dos2unix
和unix2dos
工具在兩種格式之間進行轉換,使用file
命令能夠查看文件的具體類型。不過如今但願你在不使用上述兩個轉換工具的狀況下,使用前面學過的命令手動完成 dos 文本格式到 UNIX 文本格式的轉換。
二、還記得小時候在小霸王上面玩的小蜜蜂遊戲麼?它的正統名字應該是Space Invaders:太空侵略者。
使用下面這個命令能夠安裝,之因此叫 ninvaders 是由於這款遊戲是基於 ncurses 命令行圖形庫作的:
getsudo apt-install ninvaders
你可能對重定向這個概念感到些許陌生,但你應該在前面的課程中屢次見過>
或>>
操做了,並知道他們分別是將標準輸出導向一個文件或追加到一個文件中。這其實就是重定向,將本來輸出到標準輸出的數據重定向到一個文件中,由於標準輸出(/dev/stdout
)自己也是一個文件,咱們將命令輸出導向另外一個文件天然也是沒有任何問題的。
下面咱們簡單的回顧一下咱們前面常常用到的兩個重定向操做:
'hello shiyanlou'$ echo> redirect
'www.shiyanlou.com'>> $ echoredirect
$ cat redirect
固然前面沒有用到的<
和<<
操做也是沒有問題的,如你理解的同樣,它們的區別在於重定向的方向不一致而已,>
表示是從左到右,<
右到左。
在更多瞭解 Linux 的重定向以前,咱們須要先知道一些基本的東西,前面咱們已經提到過 Linux 默認提供了三個特殊設備,用於終端的顯示和輸出,分別爲stdin
(標準輸入,對應於你在終端的輸入),stdout
(標準輸出,對應於終端的輸出),stderr
(標準錯誤輸出,對應於終端的輸出)。
文件描述符 |
設備文件 |
說明 |
|
|
標準輸入 |
|
|
標準輸出 |
|
|
標準錯誤 |
文件描述符:文件描述符在形式上是一個非負整數。實際上,它是一個索引值,指向內核爲每個進程所維護的該進程打開文件的記錄表。當程序打開一個現有文件或者建立一個新文件時,內核向進程返回一個文件描述符。在程序設計中,一些涉及底層的程序編寫每每會圍繞着文件描述符展開。可是文件描述符這一律念每每只適用於 UNIX、Linux 這樣的操做系統。
另外還有一個符號-
,它能夠同時做爲前一個命令的。
咱們能夠這樣使用這些文件描述符:
默認使用終端的標準輸入做爲命令的輸入和標準輸出做爲命令的輸出
$ cat
(按Ctrl+C退出)
將cat的連續輸出(heredoc方式)重定向到一個文件
$ mkdir Documents
$ cat > Documents/test.c <<EOF
#include <stdio.h>
int main()
{
printf"hello world\n" ();
return0 ;
}
EOF
將一個文件做爲命令的輸入,標準輸出做爲命令的輸出
$ cat Documents/test.c
將echo命令經過管道傳過來的數據做爲cat命令的輸入,將標準輸出做爲命令的輸出
echo'hi'$| cat
將echo命令的輸出從默認的標準輸出重定向到一個普通文件
'hello shiyanlou'$ echo> redirect
$ cat redirect
初學者這裏要注意不要將管道和重定向混淆,管道默認是鏈接前一個命令的輸出到下一個命令的輸入,而重定向一般是須要一個文件來創建兩個命令的鏈接,你能夠仔細體會一下上述第三個操做和最後兩個操做的異同點。
重定向標準輸出到文件,這是一個很實用的操做,另外一個很實用的操做是將標準錯誤重定向,標準輸出和標準錯誤都被指向僞終端的屏幕顯示,因此咱們常常看到的一個命令的輸出一般是同時包含了標準輸出和標準錯誤的結果的。好比下面的操做:
# 使用cat 命令同時讀取兩個文件,其中一個存在,另外一個不存在
$ cat Documents/test.c hello.c
# 你能夠看到除了正確輸出了前一個文件的內容,還在末尾出現了一條錯誤信息
# 下面咱們將輸出重定向到一個文件,根據咱們前面的經驗,這裏將在看不到任何輸出了
$ cat Documents/test.c hello.c > somefile
遺憾的是,這裏依然出現了那條錯誤信息,這正是由於如我上面說的那樣,標準輸出和標準錯誤雖然都指向終端屏幕,實際它們並不同。那有的時候咱們就是要能夠隱藏某些錯誤或者警告,那又該怎麼作呢。這就須要用到咱們前面講的文件描述符了:
# 將標準錯誤重定向到標準輸出,再將標準輸出重定向到文件,注意要將重定向到文件寫到前面
21$ cat Documents/test.c hello.c >somefile >&
# 或者只用bash提供的特殊的重定向符號"&"將標準錯誤和標準輸出同時重定向到文件
$ cat Documents/test.c hello.c &>somefilehell
注意你應該在輸出重定向文件描述符前加上&
,不然shell會當作重定向到一個文件名爲1的文件中
tee
命令同時重定向到多個文件常常你可能還有這樣的需求,除了將須要將輸出重定向到文件以外也須要將信息打印在終端,那麼你能夠使用tee
命令來實現:
echo'hello shiyanlou'$| tee hello
你應該能夠看出咱們前面的重定向操做都只是臨時性的,即只對當前命令有效,那如何作到「永久」有效呢,好比在一個腳本中,你須要某一部分的命令的輸出所有進行重定向,難道要讓你在每一個命令上面加上臨時重定向的操做嘛,固然不須要,咱們能夠使用exec
命令實現「永久」重定向。exec
命令的做用是使用指定的命令替換當前的 Shell,及使用一個進程替換當前進程,或者指定新的重定向:
# 先開啓一個子 Shell
$ zsh
# 使用exec替換當前進程的重定向,將標準輸出重定向到一個文件
1$ exec>somefile
# 後面你執行的命令的輸出都將被重定向到文件中,直到你退出當前子shell,或取消exec的重定向(後面將告訴你怎麼作)
$ ls
$ exit
$ cat somefile
默認在 Shell 中能夠有9個打開的文件描述符,上面咱們使用了也是它默認提供的0
,1
,2
號文件描述符,另外咱們還能夠使用3-8的文件描述符,只是它們默認沒有打開而已,你能夠使用下面命令查看當前 Shell 進程中打開的文件描述符:
cd$/dev/fd/;ls -Al
一樣使用exec
命令能夠建立新的文件描述符:
$ zsh
3$ exec>somefile
# 先進入目錄,再查看,不然你可能不能獲得正確的結果,而後再回到上一次的目錄
$ cd /dev/fd/;ls -Al;cd -
# 注意下面的命令>與&之間不該該有空格,若是有空格則會出錯
"this is test"3$ echo>&
$ cat somefile
$ exit
如上面咱們打開的3號文件描述符,能夠使用以下操做將它關閉:
exec$3>&-
cdcd$/dev/fd;ls -Al;-
在 Linux 中有一個被成爲「黑洞」的設備文件,因此導入它的數據都將被「吞噬」。
在類 UNIX 系統中,/dev/null,或稱空設備,是一個特殊的設備文件,它一般被用於丟棄不須要的輸出流,或做爲用於輸入流的空文件,這些操做一般由重定向完成。讀取它則會當即獲得一個EOF。
咱們能夠利用設個/dev/null
屏蔽命令的輸出:
1/dev/null21$ cat Documents/test.c nefile>>&
向上面這樣的操做將使你得不到任何輸出結果。
xargs 是一條 UNIX 和類 UNIX 操做系統的經常使用命令。它的做用是將參數列表轉換成小塊分段傳遞給其餘命令,以免參數列表過長的問題。
這個命令在有些時候十分有用,特別是當用來處理產生大量輸出結果的命令如 find,locate 和 grep 的結果,詳細用法請參看 man 文檔。
-d-fecho$ cut:1 < /etc/passwd | sort | xargs
上面這個命令用於將/etc/passwd
文件按:
分割取第一個字段排序後,使用echo
命令生成一個列表。
一、理解下面這段代碼的的做用,實際這段代碼不會正常工做,請結合這一小節的知識分析這段代碼沒有正確工做的緣由,並設法解決這個問題。
若是你尚未 Shell 腳本編程的基礎,你能夠選擇跳過或者到這裏高級 Bash 編程指南學習
whilereaddofilename;
$filename rm -iv
done<<(ls)
二、以前介紹過一個在命令行將圖片轉換爲 ascii 字符查看的工具 aview/asciiview,不過它是黑白的。如今,這裏是個彩色的:
$ sudo apt-get install caca-utils
$ cacaview <pic_file>
$ cacademo
$ cacafire
雖然咱們這一節的標題是正則表達式,但實際這一節實驗只是介紹grep
,sed
,awk
這三個命令,而正則表達式做爲這三個命令的一種使用方式(命令輸出中能夠包含正則表達式)。正則表達式自己的內容不少,要把它說明清楚須要單獨一門課程來實現,不過咱們這一節中涉及到的相關內容一般也可以知足不少狀況下的需求了。
想要更深刻地學習使用正則表達式,在這裏 正則表達式基礎。
什麼是正則表達式呢?
正則表達式,又稱正規表示式、正規表示法、正規表達式、規則表達式、常規表示法(英語:Regular Expression,在代碼中常簡寫爲 regex、regexp 或 RE),計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在不少文本編輯器裏,正則表達式一般被用來檢索、替換那些符合某個模式的文本。
許多程序設計語言都支持利用正則表達式進行字符串操做。例如,在 Perl 中就內建了一個功能強大的正則表達式引擎。正則表達式這個概念最初是由 UNIX 中的工具軟件(例如sed
和grep
)普及開的。正則表達式一般縮寫成「regex」,單數有 regexp、regex,複數有 regexps、regexes、regexen。
簡單的說形式和功能上正則表達式和咱們前面講的通配符很像,不過它們之間又有很大差異,特別在於一些特殊的匹配字符的含義上,但願初學者注意不要將二者弄混淆。
假設咱們有這樣一個文本文件,包含"shiyanlou",和"shilouyan"這兩個字符串,一樣一個表達式:
shi*
若是這做爲一個正則表達式,它將只能匹配 shi,而若是不是做爲正則表達式*
做爲一個通配符,則將同時匹配這兩個字符串。這是爲何呢?由於在正則表達式中*
表示匹配前面的子表達式(這裏就是它前面一個字符)零次或屢次,好比它能夠匹配"sh","shii","shish","shiishi"等等,而做爲通配符表示匹配通配符後面任意多個任意字符,因此它能夠匹配"shiyanlou",和"shilouyan"兩個字符。
體驗完了,下面就來開始正式學習正則表達式吧。
一個正則表達式一般被稱爲一個模式(pattern),爲用來描述或者匹配一系列符合某個句法規則的字符串。
|
豎直分隔符表示選擇,例如"boy|girl"能夠匹配"boy"或者"girl"
數量限定除了咱們舉例用的*
,還有+
加號,?
問號,.
點號,若是在一個模式中不加數量限定符則表示出現一次且僅出現一次:
+
表示前面的字符必須出現至少一次(1次或屢次),例如,"goo+gle",能夠匹配"gooogle","goooogle"等;?
表示前面的字符最多出現一次(0次或1次),例如,"colou?r",能夠匹配"color"或者"colour";*
星號表明前面的字符能夠不出現,也能夠出現一次或者屢次(0次、或1次、或屢次),例如,「0*42」能夠匹配4二、04二、004二、00042等。()
圓括號能夠用來定義模式字符串的範圍和優先級,這能夠簡單的理解爲是否將括號內的模式串做爲一個總體。例如,"gr(a|e)y"等價於"gray|grey",(這裏體現了優先級,豎直分隔符用於選擇a或者e而不是gra和ey),"(grand)?father"匹配father和grandfather(這裏體驗了範圍,?
將圓括號內容做爲一個總體匹配)。
正則表達式有多種不一樣的風格,下面列舉一些經常使用的做爲 PCRE 子集的適用於perl
和python
編程語言及grep
或egrep
的正則表達式匹配規則:(因爲markdown表格解析的問題,下面的豎直分隔符用全角字符代替,實際使用時請換回半角字符)
PCRE(Perl Compatible Regular Expressions中文含義:perl語言兼容正則表達式)是一個用 C 語言編寫的正則表達式函數庫,由菲利普.海澤(Philip Hazel)編寫。PCRE是一個輕量級的函數庫,比Boost 之類的正則表達式庫小得多。PCRE 十分易用,同時功能也很強大,性能超過了 POSIX 正則表達式庫和一些經典的正則表達式庫。
字符 |
描述 |
\ |
將下一個字符標記爲一個特殊字符、或一個原義字符。例如,「n」匹配字符「n」。「\n」匹配一個換行符。序列「\\」匹配「\」而「\(」則匹配「(」。 |
^ |
匹配輸入字符串的開始位置。 |
$ |
匹配輸入字符串的結束位置。 |
{n} |
n是一個非負整數。匹配肯定的n次。例如,「o{2}」不能匹配「Bob」中的「o」,可是能匹配「food」中的兩個o。 |
{n,} |
n是一個非負整數。至少匹配n次。例如,「o{2,}」不能匹配「Bob」中的「o」,但能匹配「foooood」中的全部o。「o{1,}」等價於「o+」。「o{0,}」則等價於「o*」。 |
{n,m} |
m和n均爲非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,「o{1,3}」將匹配「fooooood」中的前三個o。「o{0,1}」等價於「o?」。請注意在逗號和兩個數之間不能有空格。 |
* |
匹配前面的子表達式零次或屢次。例如,zo*能匹配「z」、「zo」以及「zoo」。*等價於{0,}。 |
+ |
匹配前面的子表達式一次或屢次。例如,「zo+」能匹配「zo」以及「zoo」,但不能匹配「z」。+等價於{1,}。 |
? |
匹配前面的子表達式零次或一次。例如,「do(es)?」能夠匹配「do」或「does」中的「do」。?等價於{0,1}。 |
? |
當該字符緊跟在任何一個其餘限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的。非貪婪模式儘量少的匹配所搜索的字符串,而默認的貪婪模式則儘量多的匹配所搜索的字符串。例如,對於字符串「oooo」,「o+?」將匹配單個「o」,而「o+」將匹配全部「o」。 |
. |
匹配除「\n」以外的任何單個字符。要匹配包括「\n」在內的任何字符,請使用像「(.|\n)」的模式。 |
(pattern) |
匹配pattern並獲取這一匹配的子字符串。該子字符串用於向後引用。要匹配圓括號字符,請使用「\(」或「\)」。 |
x|y |
匹配x或y。例如,「z|food」能匹配「z」或「food」。「(z|f)ood」則匹配「zood」或「food」。 |
[xyz] |
字符集合(character class)。匹配所包含的任意一個字符。例如,「[abc]」能夠匹配「plain」中的「a」。其中特殊字符僅有反斜線\保持特殊含義,用於轉義字符。其它特殊字符如星號、加號、各類括號等均做爲普通字符。脫字符^若是出如今首位則表示負值字符集合;若是出如今字符串中間就僅做爲普通字符。連字符 |
[^xyz] |
排除型(negate)字符集合。匹配未列出的任意字符。例如,「[^abc]」能夠匹配「plain」中的「plin」。 |
[a-z] |
字符範圍。匹配指定範圍內的任意字符。例如,「[a-z]」能夠匹配「a」到「z」範圍內的任意小寫字母字符。 |
[^a-z] |
排除型的字符範圍。匹配任何不在指定範圍內的任意字符。例如,「[^a-z]」能夠匹配任何不在「a」到「z」範圍內的任意字符。 |
優先級爲從上到下從左到右,依次下降:
運算符 |
說明 |
\ |
轉義符 |
(), (?:), (?=), [] |
括號和中括號 |
*、+、?、{n}、{n,}、{n,m} |
限定符 |
^、$、\任何元字符 |
定位點和序列 |
| |
選擇 |
更多正則表達式的內容能夠參考如下連接:
regex的思導圖:
上面空談了那麼多正則表達式的內容也並無說起具體該如何使用它,實在枯燥,若是說正則表達式是一門武功話,那它也只能算得上一些口訣招式罷了,要把它真正練起來還得須要一些兵器在手才行,這裏咱們要介紹的grep
命令以及後面要講的sed
,awk
這些就該算做是這樣的兵器了。
grep
命令用於打印輸出文本中匹配的模式串,它使用正則表達式做爲模式匹配的條件。grep
支持三種正則表達式引擎,分別用三個參數指定:
參數 |
說明 |
|
POSIX擴展正則表達式,ERE |
|
POSIX基本正則表達式,BRE |
|
Perl正則表達式,PCRE |
不過在你沒學過perl語言的大多數狀況下你將只會使用到ERE
和BRE
,因此咱們接下來的內容都不會討論到PCRE中特有的一些正則表達式語法(它們之間大部份內容是存在交集的,因此你不用擔憂會遺漏多少重要內容)
在經過grep
命令使用正則表達式以前,先介紹一下它的經常使用參數:
參數 |
說明 |
|
將二進制文件做爲文原本進行匹配 |
|
統計以模式匹配的數目 |
|
忽略大小寫 |
|
顯示匹配文本所在行的行號 |
|
反選,輸出不匹配行的內容 |
|
遞歸匹配查找 |
|
n爲正整數,表示after的意思,除了列出匹配行以外,還列出後面的n行 |
|
n爲正整數,表示before的意思,除了列出匹配行以外,還列出前面的n行 |
|
將輸出中的匹配項設置爲自動顏色顯示 |
注:在大多數發行版中是默認設置了grep的顏色的,你能夠經過參數指定或修改GREP_COLOR
環境變量。
查找/etc/group
文件中以"shiyanlou"爲開頭的行
'shiyanlou'group$ grep/etc/
'^shiyanlou'group$ grep/etc/
# 將匹配以'z'開頭以'o'結尾的全部字符串
echo'zero\nzo\nzoo''z.*o'$| grep
# 將匹配以'z'開頭以'o'結尾,中間包含一個任意字符的字符串
echo'zero\nzo\nzoo''z.o'$| grep
# 將匹配以'z'開頭,以任意多個'o'結尾的字符串
echo'zero\nzo\nzoo''zo*'$| grep
注意:其中\n
爲換行符
# grep默認是區分大小寫的,這裏將匹配全部的小寫字母
echo'1234\nabcd''[a-z]'$| grep
# 將匹配全部的數字
echo'1234\nabcd''[0-9]'$| grep
# 將匹配全部的數字
echo'1234\nabcd''[[:digit:]]'$| grep
# 將匹配全部的小寫字母
echo'1234\nabcd''[[:lower:]]'$| grep
# 將匹配全部的大寫字母
echo'1234\nabcd''[[:upper:]]'$| grep
# 將匹配全部的字母和數字,包括0-9,a-z,A-Z
echo'1234\nabcd''[[:alnum:]]'$| grep
# 將匹配全部的字母
echo'1234\nabcd''[[:alpha:]]'$| grep
下面包含完整的特殊符號及說明:
特殊符號 |
說明 |
|
表明英文大小寫字節及數字,亦即 0-9, A-Z, a-z |
|
表明任何英文大小寫字節,亦即 A-Z, a-z |
|
表明空白鍵與 [Tab] 按鍵二者 |
|
表明鍵盤上面的控制按鍵,亦即包括 CR, LF, Tab, Del.. 等等 |
|
表明數字而已,亦即 0-9 |
|
除了空白字節 (空白鍵與 [Tab] 按鍵) 外的其餘全部按鍵 |
|
表明小寫字節,亦即 a-z |
|
表明任何能夠被列印出來的字節 |
|
表明標點符號 (punctuation symbol),亦即:" ' ? ! ; : # $... |
|
表明大寫字節,亦即 A-Z |
|
任何會產生空白的字節,包括空白鍵, [Tab], CR 等等 |
|
表明 16 進位的數字類型,所以包括: 0-9, A-F, a-f 的數字與字節 |
注意:之因此要使用特殊符號,是由於上面的[a-z]不是在全部狀況下都管用,這還與主機當前的語系有關,即設置在LANG
環境變量的值,zh_CN.UTF-8的話[a-z],即爲全部小寫字母,其它語系多是大小寫交替的如,"a A b B...z Z",[a-z]中就可能包含大寫字母。因此在使用[a-z]時請確保當前語系的影響,使用[:lower:]則不會有這個問題。
# 排除字符
echo'geek|good''[^o]'$| grep
注意:當^
放到中括號內爲排除字符,不然表示行首。
要經過grep
使用擴展正則表達式須要加上-E
參數,或使用egrep
。
# 只匹配"zo"
echo'zero\nzo\nzoo''zo{1}'$| grep -E
# 匹配以"zo"開頭的全部單詞
echo'zero\nzo\nzoo''zo{1,}'$| grep -E
注意:推薦掌握{n,m}
便可,+
,?
,*
,這幾個不太直觀,且容易弄混淆。
# 匹配"www.shiyanlou.com"和"www.google.com"
echo'www.shiyanlou.com\nwww.baidu.com\nwww.google.com''www\.(shiyanlou|google)\.com'$| grep -E
# 或者匹配不包含"baidu"的內容
echo'www.shiyanlou.com\nwww.baidu.com\nwww.google.com''www\.baidu\.com'$| grep -Ev
注意:由於.
號有特殊含義,因此須要轉義。
關於正則表達式和grep
命令的內容就介紹這麼多,下面會介紹兩個更強大的工具sed
和awk
,但一樣也正是由於這兩個工具的強大,咱們的內容沒法包含它們的所有,這裏將只對基本內容做介紹。
sed
工具在 man 手冊裏面的全名爲"sed - stream editor for filtering and transforming text ",意即,用於過濾和轉換文本的流編輯器。
在 Linux/UNIX 的世界裏敢稱爲編輯器的工具,大都非等閒之輩,好比前面的"vi/vim(編輯器之神)","emacs(神的編輯器)","gedit"這些個編輯器。sed
與上述的最大不一樣之處大於它是一個非交互式的編輯器,下面咱們就開始介紹sed
這個編輯器。
sed 命令基本格式:
sed [參數]... [執行命令] [輸入文件]...
# 形如:
'1s/sad/happy/'test# 表示將test文件中第一行的"sad"替換爲"happy"$ sed -i
參數 |
說明 |
|
安靜模式,只打印受影響的行,默認打印輸入數據的所有內容 |
|
用於在腳本中添加多個執行命令一次執行,在命令行中執行多個命令一般不須要加該參數 |
|
指定執行filename文件中的命令 |
|
使用擴展正則表達式,默認爲標準正則表達式 |
|
將直接修改輸入文件內容,而不是打印到標準輸出設備 |
sed執行命令格式:
n1,n2[][]command
n1~step[][]command
# 其中一些命令能夠在後面加上做用範圍,形如:
$ sed -i 's/sad/happy/g' test # g表示全局範圍
$ sed -i 's/sad/happy/4' test # 4表示指定行中的第四個匹配字符串
其中n1,n2表示輸入內容的行號,它們之間爲,
逗號則表示從n1到n2行,若是爲~
波浪號則表示從n1開始以step爲步進的全部行;command爲執行動做,下面爲一些經常使用動做指令:
命令 |
說明 |
|
行內替換 |
|
整行替換 |
|
插入到指定行的後面 |
|
插入到指定行的前面 |
|
打印指定行,一般與 |
|
刪除指定行 |
咱們先找一個用於練習的文本文件:
$ cp /etc/passwd ~
# 打印2-5行
'2,5p'$ nl passwd | sed -n
# 打印奇數行
'1~2p'$ nl passwd | sed -n
# 將輸入文本中"shiyanlou" 全局替換爲"hehe",並只打印替換的那一行,注意這裏不能省略最後的"p"命令
's/shiyanlou/hehe/gp'$ sed -npasswd
注意: 行內替換能夠結合正則表達式使用。
grep"shiyanlou"$ nl passwd |
# 刪除第21行
'21c\www.shiyanlou.com'$ sed -npasswd
關於sed命令就介紹這麼多,你若是但願瞭解更多sed的高級用法,你能夠參看以下連接:
看到上面的標題,你可能會感到驚異,難道咱們這裏要學習的是一門「語言」麼,確切的說,咱們是要在這裏學習awk
文本處理語言,只是咱們並不會在這裏學習到比較完整的關於awk
的內容,仍是由於前面的緣由,它太強大了,它的應用無處不在,咱們沒法在這裏以簡短的文字描述面面俱到,若是你有目標成爲一個linux系統管理員,確實想學好awk
,你一不用擔憂,實驗樓會在以後陸續上線linux系統管理員的學習路徑,裏面會有單獨的關於正則表達式
,awk
,sed
等相關課程,敬請期待吧。下面的內容,咱們就做爲一個關於awk
的入門體驗章節吧,其中會介紹一些awk
的經常使用操做。
AWK
是一種優良的文本處理工具,Linux及Unix環境中現有的功能最強大的數據處理引擎之一.其名稱得自於它的創始人Alfred Aho(阿爾佛雷德·艾侯)、Peter Jay Weinberger(彼得·溫伯格)和Brian Wilson Kernighan(布萊恩·柯林漢)姓氏的首個字母.AWK程序設計語言,三位建立者已將它正式定義爲「樣式掃描和處理語言」。它容許您建立簡短的程序,這些程序讀取輸入文件、爲數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其餘的功能。最簡單地說,AWK是一種用於處理文本的編程語言工具。
在大多數linux發行版上面,實際咱們使用的是gawk(GNU awk,awk的GNU版本),在咱們的環境中ubuntu上,默認提供的是mawk,不過咱們一般能夠直接使用awk命令(awk語言的解釋器),由於系統已經爲咱們建立好了awk指向mawk的符號連接。
$ ll /usr/bin/awk
nawk: 在 20 世紀 80 年代中期,對 awk語言進行了更新,並不一樣程度地使用一種稱爲 nawk(new awk) 的加強版本對其進行了替換。許多系統中仍然存在着舊的awk 解釋器,但一般將其安裝爲 oawk (old awk) 命令,而 nawk 解釋器則安裝爲主要的 awk 命令,也能夠使用 nawk 命令。Dr. Kernighan 仍然在對 nawk 進行維護,與 gawk 同樣,它也是開放源代碼的,而且能夠免費得到; gawk: 是 GNU Project 的awk解釋器的開放源代碼實現。儘管早期的 GAWK 發行版是舊的 AWK 的替代程序,但不斷地對其進行了更新,以包含 NAWK 的特性; mawk 也是awk編程語言的一種解釋器,mawk遵循 POSIX 1003.2 (草案 11.3)定義的 AWK 語言,包含了一些沒有在AWK 手冊中提到的特點,同時 mawk 提供一小部分擴展,另外聽說mawk是實現最快的awk
awk全部的操做都是基於pattern(模式)—action(動做)對來完成的,以下面的形式:
$ pattern {action}
你能夠看到就如同不少編程語言同樣,它將全部的動做操做用一對{}
花括號包圍起來。其中pattern一般是是表示用於匹配輸入的文本的「關係式」或「正則表達式」,action則是表示匹配後將執行的動做。在一個完整awk操做中,這二者能夠只有其中一個,若是沒有pattern則默認匹配輸入的所有文本,若是沒有action則默認爲打印匹配內容到屏幕。
awk
處理文本的方式,是將文本分割成一些「字段」,而後再對這些字段進行處理,默認狀況下,awk以空格做爲一個字段的分割符,不過這不是固定了,你能夠任意指定分隔符,下面將告訴你如何作到這一點。
awk[-F fs][-v var=value][-f prog-file | 'program text'][file...]
其中-F
參數用於預先指定前面提到的字段分隔符(還有其餘指定字段的方式) ,-v
用於預先爲awk
程序指定變量,-f
參數用於指定awk
命令要執行的程序文件,或者在不加-f
參數的狀況下直接將程序語句放在這裏,最後爲awk
須要處理的文本輸入,且能夠同時輸入多個文本文件。如今咱們仍是直接來具體體驗一下吧。
先用vim新建一個文本文檔
test$ vim
包含以下內容:
Ilikelinux
www.shiyanlou.com
# "quote>" 不用輸入
'{$ awk
> }'test
# 或者寫到一行
'{print}'test$ awk
說明:在這個操做中我是省略了patter
,因此awk
會默認匹配輸入文本的所有內容,而後在"{}"花括號中執行動做,即print
打印全部匹配項,這裏是所有文本內容
'{$ awk
> if(NR==1){
> print $1 "\n" $2 "\n" $3
> } else {
> print}
> }'test
# 或者
'{$ awk
> if(NR==1){
> OFS="\n"
> print $1, $2, $3
> } else {
> print}
> }'test
說明:你首先應該注意的是,這裏我使用了awk
語言的分支選擇語句if
,它的使用和不少高級語言如C/C++
語言基本一致,若是你有這些語言的基礎,這裏將很好理解。另外一個你須要注意的是NR
與OFS
,這兩個是awk
內建的變量,NR
表示當前讀入的記錄數,你能夠簡單的理解爲當前處理的行數,OFS
表示輸出時的字段分隔符,默認爲" "空格,如上圖所見,咱們將字段分隔符設置爲\n
換行符,因此第一行本來以空格爲字段分隔的內容就分別輸出到單獨一行了。而後是$N
其中N爲相應的字段號,這也是awk
的內建變量,它表示引用相應的字段,由於咱們這裏第一行只有三個字段,因此只引用到了$3
。除此以外另外一個這裏沒有出現的$0
,它表示引用當前記錄(當前行)的所有內容。
'.''{$ awk -F
> if(NR==2){
> print $1 "\t" $2 "\t" $3
> }}'test
# 或者
'$ awk
> BEGIN{
> FS="."
> OFS="\t" # 若是寫爲一行,兩個動做語句之間應該以";"號分開
> }{
> if(NR==2){
> print $1, $2, $3
> }}'test
說明:這裏的-F
參數,前面已經介紹過,它是用來預先指定待處理記錄的字段分隔符。咱們須要注意的是除了指定OFS
咱們還能夠在print
語句中直接打印特殊符號如這裏的\t
,print打印的非變量內容都須要用""一對引號包圍起來。上面另外一個版本,展現了實現預先指定變量分隔符的另外一種方式,即便用BEGIN
,就這個表達式指示了,其後的動做將在全部動做以前執行,這裏是FS
賦值了新的"."點號代替默認的" "空格
注意:首先說明一點,咱們在學習和使用awk的時候應該儘量將其做爲一門程序語言來理解,這樣將會使你學習起來更容易,因此初學階段在練習awk
時應該儘可能按照我那樣的方式分多行按照通常程序語言的換行和縮進來輸入,而不是所有寫到一行(固然這在你熟練了以後是沒有任何問題的)。
變量名 |
說明 |
|
當前輸入文件名,如有多個文件,則只表示第一個。若是輸入是來自標準輸入,則爲空字符串 |
|
當前記錄的內容 |
|
N表示字段號,最大值爲 |
|
字段分隔符,由正則表達式表示,默認爲" "空格 |
|
輸入記錄分隔符,默認爲"\n",即一行爲一個記錄 |
|
當前記錄字段數 |
|
已經讀入的記錄數 |
|
當前輸入文件的記錄數,請注意它與NR的區別 |
|
輸出字段分隔符,默認爲" "空格 |
|
輸出記錄分隔符,默認爲"\n" |
關於awk
的內容本課程將只會包含這些內容,若是你想了解更多,請期待後續課程,或者參看一下連接內容:
一、練習其餘幾個命令動做的使用。
二、一個在線遊戲,固然咱們主要目的是學習,這個遊戲也是有寓教於樂的性質,讓你快速學會vim的基礎操做:
介紹 Ubuntu 下軟件安裝的幾種方式,及 apt,dpkg 工具的使用。
一般 Linux 上的軟件安裝主要有三種方式:
這幾種安裝方式各有優劣,而大多數軟件包會採用多種方式發佈軟件,因此咱們經常須要所有掌握這幾種軟件安裝方式,以便適應各類環境。下面將介紹前三種安裝方式,從源碼編譯安裝你將在 Linux 程序設計中學習到。
試想一下,平時咱們在使用 Windows 的時候,想要安裝一個軟件,咱們須要在網上去下載對應軟件的安裝包,接着安裝的時候就是不斷的去點擊下一步,這些流程想必你們已經經歷的無數回了,可是在 Linux 下,一個命令加回車,等待一下,軟件就安裝好了,這就是方便的在線安裝軟件的方式。在學習這種安裝方式以前有一點須要說明的是,在不一樣的linux發行版上面在線安裝方式會有一些差別包括使用的命令及它們的包管理工具,由於咱們的開發環境是基於ubuntu的,因此這裏咱們涉及的在線安裝方式將只適用於ubuntu發行版,或其它基於ubuntu的發行版如國內的ubuntukylin(優麒麟),ubuntu又是基於debian的發行版,它使用的是debian的包管理工具dpkg,因此一些操做也適用與debian。而在其它一些採用其它包管理工具的發行版如redhat,centos,fedora等將不適用(redhat和centos使用rpm)。
好比咱們想安裝一個軟件,名字叫作 w3m
(w3m是一個命令行的簡易網頁瀏覽器),那麼輸入以下命令:
get$ sudo apt-install w3m
這樣的操做你應該在前面的章節中看到過不少次了,它就表示將會安裝一個軟件包名爲w3m
的軟件
咱們來看看命令執行後的效果:
$ w3m www.shiyanlou.com/faq
注意:若是你在安裝一個軟件以後,沒法當即使用Tab
鍵補全這可命令,你能夠嘗試先執行source ~/.zshrc
,而後你就能夠使用補全操做。
APT是Advance Packaging Tool(高級包裝工具)的縮寫,是Debian及其派生髮行版的軟件包管理器,APT能夠自動下載,配置,安裝二進制或者源代碼格式的軟件包,所以簡化了Unix系統上管理軟件的過程。APT最先被設計成dpkg的前端,用來處理deb格式的軟件包。如今通過APT-RPM組織修改,APT已經能夠安裝在支持RPM的系統管理RPM包。這個包管理器包含以 apt-
開頭的的多個工具,如 apt-get
apt-cache
apt-cdrom
等,在Debian系列的發行版中使用。
當你在執行安裝操做時,首先apt-get
工具會在本地的一個數據庫中搜索關於 w3m
軟件的相關信息,並根據這些信息在相關的服務器上下載軟件安裝,這裏你們可能會一個疑問:既然是在線安裝軟件,爲啥會在本地的數據庫中搜索?要解釋這個問題就得提到幾個名詞了:
咱們須要按期從服務器上下載一個軟件包列表,使用 sudo apt-get update
命令來保持本地的軟件包列表是最新的(有時你也須要手動執行這個操做,好比更換了軟件源),而這個表裏會有軟件依賴信息的記錄,對於軟件依賴,我舉個例子:咱們安裝 w3m
軟件的時候,而這個軟件須要 libgc1c2
這個軟件包才能正常工做,這個時候 apt-get
在安裝軟件的時候會一併替咱們安裝了,以保證 w3m
能正常的工做。
apt-get
使用各用於處理apt
包的公用程序集,咱們能夠用它來在線安裝、卸載和升級軟件包等,下面列出一些apt-get
包含的經常使用的一些工具:
工具 |
說明 |
|
其後加上軟件包名,用於安裝一個軟件包 |
|
從軟件源鏡像服務器上下載/更新用於更新本地軟件源的軟件包列表 |
|
升級本地可更新的所有軟件包,但存在依賴問題時將不會升級,一般會在更新以前執行一次 |
|
解決依賴關係並升級(存在必定危險性) |
|
移除已安裝的軟件包,包括與被移除軟件包有依賴關係的軟件包,但不包含軟件包的配置文件 |
|
移除以前被其餘軟件包依賴,但如今再也不被使用的軟件包 |
|
與remove相同,但會徹底移除軟件包,包含其配置文件 |
|
移除下載到本地的已經安裝的軟件包,默認保存在/var/cache/apt/archives/ |
|
移除已安裝的軟件的舊版本軟件包 |
下面是一些apt-get
經常使用的參數:
參數 |
說明 |
|
自動迴應是否安裝軟件包的選項,在一些自動化安裝腳本中使用這個參數將十分有用 |
|
模擬安裝 |
|
靜默安裝方式,指定多個 |
|
修復損壞的依賴關係 |
|
只下載不安裝 |
|
從新安裝已經安裝但可能存在問題的軟件包 |
|
同時安裝APT給出的建議安裝的軟件包 |
關於安裝,如前面演示的同樣你只須要執行apt-get install <
軟件包名
>
便可,除了這一點,你還應該掌握的是如何從新安裝軟件包。 不少時候咱們須要從新安裝一個軟件包,好比你的系統被破壞,或者一些錯誤的配置致使軟件沒法正常工做。
你能夠使用以下方式從新安裝:
get$ sudo apt---reinstall install w3m
另外一個你須要掌握的是,如何在不知道軟件包完整名的時候進行安裝。一般咱們是使用Tab
鍵補全軟件包名,後面會介紹更好的方法來搜索軟件包。有時候你須要同時安裝多個軟件包,你還能夠使用正則表達式匹配軟件包名進行批量安裝。
# 更新軟件源
get$ sudo apt-update
# 升級沒有依賴問題的軟件包
get$ sudo apt-upgrade
# 升級並解決依賴關係
get$ sudo apt-dist-upgrade
若是你如今以爲 w3m
這個軟件不合本身的胃口,或者是找到了更好的,你須要卸載它,那麼簡單!一樣是一個命令加回車 sudo apt-get remove w3m
,系統會有一個確認的操做,以後這個軟件便「滾蛋了」。
或者,你能夠執行
# 不保留配置文件的移除
get$ sudo apt-purge w3m
# 或者 sudo apt-get --purge remove
# 移除再也不須要的被依賴的軟件包
get$ sudo apt-autoremove
當本身剛知道了一個軟件,想下載使用,須要確認軟件倉庫裏面有沒有,就須要用到搜索功能了,命令以下:
cachesearchsudo apt-softname1 softname2 softname3……
apt-cache
命令則是針對本地數據進行相關操做的工具,search
顧名思義在本地的數據庫中尋找有關 softname1
softname2
…… 相關軟件的信息。如今咱們試試搜索一下以前咱們安裝的軟件 w3m
,如圖:
結果顯示了4個 w3m
相關的軟件,而且有相關軟件的簡介。
關於在線安裝的的內容咱們就介紹這麼多,想了解更多關於APT的內容,你能夠參考:
dpkg 是 Debian 軟件包管理器的基礎,它被伊恩·默多克建立於 1993 年。dpkg 與 RPM 十分類似,一樣被用於安裝、卸載和供給和 .deb 軟件包相關的信息。
dpkg 自己是一個底層的工具。上層的工具,像是 APT,被用於從遠程獲取軟件包以及處理複雜的軟件包關係。"dpkg"是"Debian Package"的簡寫。
咱們常常能夠在網絡上簡單以deb
形式打包的軟件包,就須要使用dpkg
命令來安裝。
dpkg
經常使用參數介紹:
參數 |
說明 |
|
安裝指定deb包 |
|
後面加上目錄名,用於安裝該目錄下的全部deb安裝包 |
|
remove,移除某個已安裝的軟件包 |
|
顯示 |
|
顯示已安裝軟件的信息 |
|
搜索已安裝的軟件包 |
|
顯示已安裝軟件包的目錄信息 |
咱們先使用apt-get
加上-d
參數只下載不安裝,下載emacs編輯器的deb包,下載完成後,咱們能夠查看/var/cache/apt/archives/目錄下的內容,以下圖:
而後咱們將第一個deb
拷貝到home目錄下,並使用dpkg
安裝
314$ cp /var/cache/apt/archives/emacs24_24.+-ubuntu1_amd64.deb ~
# 安裝以前參看deb包的信息
314$ sudo dpkg -I emacs24_24.+-ubuntu1_amd64.deb
如你所見,這個包還額外依賴了一些軟件包,這意味着,若是主機目前沒有這些被依賴的軟件包,直接使用dpkg安裝可能會存在一些問題,由於dpkg
並不能爲你解決依賴關係。
# 使用dpkg安裝
314$ sudo dpkg -i emacs24_24.+-ubuntu1_amd64.deb
跟前面預料的同樣,這裏你可能出現了一些錯誤:
咱們將如何解決這個錯誤了,這就要用到apt-get
了,使用它的-f
參數了,修復依賴關係的安裝
-f$ sudo apt-getinstall
沒有任何錯誤,這樣咱們就安裝成功了,而後你能夠運行emacs程序
若是你依然在糾結到底linux將軟件安裝到了什麼地方,那麼很幸運你將能夠經過dpkg
找到答案
使用dpkg -L
查看deb
包目錄信息
$ sudo dpkg -L emacs
dpkg
還有一些其餘的參數,這裏將做爲練習題由你本身來學習
二進制包的安裝比較簡單,咱們須要作的只是將從網絡上下載的二進制包解壓後放到合適的目錄,而後將包含可執行的主程序文件的目錄添加進PATH
環境變量便可,若是你不知道該放到什麼位置,請從新複習第四節關於 Linux 目錄結構的內容。
這一節是本課程的最後一節,因此這裏咱們給你們介紹一個頗有趣的命令。
安裝:
get$ sudo apt-install bb
Linux中也不免遇到某個程序無響應的狀況,咱們經過一些命令來幫助咱們讓系統可以更流暢的運行,而在此以前咱們須要對進程的基礎知識有必定的瞭解,才能更好更有效率的使用Linux提供的工具
首先程序與進程是什麼?程序與進程又有什麼區別?
程序(procedure)不太精確地說,程序就是執行一系列有邏輯,有順序結構的指令,爲咱們提供所須要的服務。就如咱們去餐館,給服務員說我要牛肉蓋澆飯,她執行了作牛肉蓋澆飯這麼一個程序,最後咱們獲得了這麼一盤牛肉蓋澆飯。它須要去執行,否則它就像一本武功祕籍,放在那裏。
進程(process)進程是程序在一個數據集合上的一次執行過程,在早期的UNIX,Linux 2.4及更早的版本中,它是系統進行資源分配和調度的獨立基本單位。同上一個例子,就如咱們去了餐館,給服務員說我要牛肉蓋澆飯,她執行了作牛肉蓋澆飯這麼一個程序,而裏面作飯的是一個進程,超牛肉湯汁的是一個進程,把牛肉湯汁與飯混合在一塊兒的是一個進程,把飯端上桌的是一個進程。它就像是咱們在看武功祕籍這麼一個過程,而後一個篇章一個篇章的去練
簡單來講,程序是爲了完成某種任務而設計的軟件,好比vim是程序。什麼是進程呢?進程就是運行中的程序。
程序只是一些列指令的集合,是一個靜止的實體,而進程不一樣,進程有一下的特性
併發在一個時間段內,宏觀來看有多個程序都在活動,有條不紊的執行
並行在每個瞬間,都有多個程序都在同時執行,這個必須有多個 CPU 才行
引入進程是由於傳統意義上的程序已經不足以描述 OS 中各類活動之間的動態性、併發行、獨立性還有相互制約性。就好比程序就像一個公司,只是一些證書,文件的堆積(靜態實體)。而當公司運做起來就有各個部門的區分,財務部,技術部,銷售部等等,就像各個進程,各個部門之間能夠獨立運作,也能夠有交互(獨立性、併發性)
而隨着程序的發展越作越大,又會繼續細分,從而引入了線程的概念,當代多數操做系統、Linux 2.6及更新的版本中,進程自己不是基本運行單位,而是線程的容器。就像上述所說的,每一個部門又會細分爲各個工做小組(線程),而工做小組須要的資源須要向上級(進程)申請。
線程(thread)是操做系統可以進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運做單位。一條線程指的是進程中一個單一順序的控制流,一個進程中能夠併發多個線程,每條線程並行執行不一樣的任務。由於線程中幾乎不包含系統資源,因此執行更快、更有效率
簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。線程的劃分尺度小於進程,使得多線程程序的併發性高。另外,進程在執行過程當中擁有獨立的內存單元,而多個線程共享內存,從而極大地提升了程序的運行效率。就以下圖所示:
大概明白進程是個什麼樣的存在,進一步對於進程的一個瞭解就是進程分類,咱們能夠從兩個角度來分,第一個角度以進程的功能與服務的對象來分;第二個角度以應用程序的服務類型來分
第一個角度來看,咱們能夠分爲用戶進程與系統進程
第二角度來看,咱們能夠將進程分爲交互進程、批處理進程、守護進程
進程有這麼多的種類,那麼進程之間定是有相關性的,而這些有關聯性的進程又是如何產生的,如何衍生的?
就好比咱們啓動了終端,就是啓動了一個 bash 進程,咱們能夠在 bash 中再輸入 bash 則會再啓動一個 bash 的進程,此時第二個 bash 進程就是由第一個 bash 進程建立出來的,他們直接又是個什麼關係?
咱們通常稱呼第一個 bash 進程是第二 bash 進程的父進程,第二 bash 進程是第一個 bash 進程的子進程,這層關係是如何得來的呢?
關於父進程與子進程便會說起這兩個系統調用 fork()
與 exec()
fork-exec是由 Dennis M. Ritchie 創造的
fork() 是一個系統調用(system call),它的主要做用就是爲當前的進程建立一個新的進程,這個新的進程就是它的子進程,這個子進程除了父進程的返回值和 PID 之外其餘的都如出一轍,如進程的執行代碼段,內存信息,文件描述,寄存器狀態等等
exec() 也是系統調用,做用是切換子進程中的執行程序也就是替換其從父進程複製過來的代碼段與數據段
下圖能夠很形象的表示他們的做用(此圖來源於鳥哥私房菜):
子進程就是父進程經過系統調用 fork()
而產生的複製品,fork()
就是把父進程的 PCB 等進程的數據結構信息直接複製過來,只是修改了 PID,因此如出一轍,指揮在執行 exec()
以後纔會不一樣,而早先的 fork()
比較消耗資源後來進化成 vfork()
,效率高了很多,感興趣的同窗能夠查查爲何?
這就是子進程產生的由來。簡單的邏輯就以下方所示【註釋1】
pid_tp;
p = fork();
ifpid_t-1(p == ())
/* ERROR */
elseif0(p ==)
/* CHILD */
else
/* PARENT */
既然子進程是經過父進程而衍生出來的,那麼子進程的退出與資源的回收定然與父進程有很大的相關性。當一個子進程要正常的終止運行時,或者該進程結束時它的主函數 main()
會執行 exit(n);
或者 return n
,這裏的返回值 n 是一個信號,系統會把這個 SIGCHLD 信號傳給其父進程,固然如果異常終止也每每是由於這個信號。
而這個時候的子進程代碼執行部分其實已經結束執行了,系統的資源也進本歸還給系統了,可是其進程的進程控制塊(PCB)仍駐留在內存中,而它的 PCB 還在,表明這個進程還存在(由於 PCB 就是進程存在的惟一標誌,裏面有 PID 等消息),並無消亡,這樣的進程稱之爲殭屍進程(Zombie)
如圖中第三行第四列標題是 S,此處的 S 是進程的狀態的意思,而在下屬的第三行是 Z,而此處的 Z 即是 Zombie 的意思。( ps 命令將在後續詳解)
正常狀況下,父進程會收到兩個返回值一個是 exit code 也是 SIGCHLD 信號與 reason for termination 以後,父進程會使用 wait(&status)
系統調用以獲取子進程的退出狀態,而後內核就能夠從內存中釋放已結束的子進程的 PCB;而如若父進程沒有這麼作的話,子進程的 PCB 就會一直駐留在內存中,一直留在系統中作爲殭屍進程(Zombie)。
雖然殭屍進程是已經放棄了幾乎全部內存空間,沒有任何可執行代碼,也不能被調度,在進程列表中保留一個位置,記載該進程的退出狀態等信息供其父進程收集,從而釋放它。可是 Linux 系統中能使用的 PID 是有限的,若是系統中存在有大量的殭屍進程,系統將會由於沒有可用的 PID 從而致使不能產生新的進程。
而另外若是父進程結束(非正常的結束),未能即便收回子進程,子進程仍在運行,這樣的子進程稱之爲孤兒進程。在 Linux 系統中,孤兒進程通常會被 init 進程所「收養」,成爲 init 的子進程。由 init 來作善後處理,因此它並不至於像殭屍進程那樣無人問津,無論不顧,大量存在會有危害。
進程 0 是系統引導時建立的一個特殊進程,也稱之爲內核初始化,其最後一個動做就是調用 fork()
建立出一個子進程運行/sbin/init
可執行文件,而該進程就是 PID=1 的進程1,也就是 init 進程,而進程 0 就轉爲交換進程(也被稱爲空閒進程),而進程 1 (init 進程)是第一個普通用戶態的進程,再由它不斷調用 fork() 來建立系統裏其餘的進程,因此它是全部進程的父進程或者祖先進程。同時它是一個守護程序,直到計算機關機纔會中止。
經過一下的命令咱們能夠很明顯的看到這樣的一個結構
pstree
或者今後圖咱們能夠更加形象的看清子父進程的關係
經過以上的顯示結果咱們能夠看的很清楚,init 爲全部進程的父進程或者說是祖先進程
咱們還能夠使用這樣一個命令來看,其中 pid 就是該進程的一個惟一編號,ppid 就是該進程的父進程的 pid,command 就是該進程是執行什麼樣的程序或者腳本而產生的
commandps-fxo user,ppid,pid,pgid,
能夠在圖中看見咱們執行的 ps 就是由 zsh 經過 fork-exec 建立的子進程而執行的
使用這樣的一個命令咱們也能清楚的看見 init 如上文所說是由進程0這個初始化進程來建立而出的子進程,而其餘的進程基本是由 init 建立的子進程,或者是由它的子進程建立出來的子進程。因此 init 是用戶進程的第一個進程也是全部用戶進程的父進程或者祖先進程。(ps 命令將在後續課程詳解)
就像一個樹狀圖,而 init 進程就是這棵樹的根,其餘進程由根不斷的發散,開枝散葉
每個進程都會是一個進程組的成員,並且這個進程組是惟一存在的,他們是依靠 PGID(process group ID)來區別的,而每當一個進程被建立的時候,它便會成爲其父進程所在組中的一員。
通常狀況,進程組的 PGID 等同於進程組的第一個成員的 PID,而且這樣的進程稱爲該進程組的領導者,也就是領導進程,進程通常經過使用 getpgrp()
系統調用來尋找其所在組的 PGID,領導進程能夠先終結,此時進程組依然存在,並持有相同的PGID,直到進程組中最後一個進程終結。
與進程組相似,每當一個進程被建立的時候,它便會成爲其父進程所在 Session 中的一員,每個進程組都會在一個 Session 中,而且這個 Session 是惟一存在的,
Session 主要是針對一個 tty 創建,Session 中的每一個進程都稱爲一個工做(job)。每一個會話能夠鏈接一個終端(control terminal)。當控制終端有輸入輸出時,都傳遞給該會話的前臺進程組。Session 意義在於將多個jobs囊括在一個終端,並取其中的一個 job 做爲前臺,來直接接收該終端的輸入輸出以及終端信號。 其餘jobs在後臺運行。
前臺(foreground)就是在終端中運行,與你能有交互的
後臺(background)就是在終端中運行,可是你並不能與其任何的交互,也不會顯示其執行的過程
bash(Bourne-Again shell)支持工做控制(job control),而sh(Bourne shell)並不支持。
而且每一個終端或者說 bash 只能管理當前終端的中的 job,不能管理其餘終端中的 job。好比我當前存在兩個 bash 分別爲 bash一、bash2,bash1 只能管理其本身裏面的 job 並不能管理 bash2 裏面的 job
咱們都知道當一個進程在前臺運做時咱們能夠用 ctrl + c
來終止它,可是如果在後臺的話就不行了,而且在一個終端 bash 中只能管理當前 bash 裏的 job.
咱們能夠經過 &
這個符號,讓咱們的命令在後臺中運行
ls&
圖中所顯示的 [1] 236
分別是該工做的 job number 與該進程的 PID,而最後一行的 Done 表示該命令已經在後臺執行完畢。
咱們還能夠經過 ctrl + z
使咱們的當前工做中止並丟到後臺中去
被中止並放置在後臺的工做咱們能夠使用這個命令來查看
jobs
其中第一列顯示的爲被放置後臺的工做的編號,而第二列的 + 表示最近被放置後臺的工做,同時也表示預設的工做,也就是如果有什麼針對後臺的工做的操做,首先對預設的工做,- 表示倒數第二被放置後臺的工做,倒數第三個之後都不會有這樣的符號修飾,第三列表示它們的狀態,而最後一列表示該進程執行的命令
咱們能夠經過這樣的一個命令將後臺的工做拿到前臺來
#後面不加參數提取預設工做,加參數提取指定工做的編號
fg [%jobnumber]
以前咱們經過 ctrl + z
使得工做中止放置在後臺,如果咱們想讓其在後臺運做咱們就使用這樣一個命令
#與fg相似,加參則指定,不加參則取預設
bg [%jobnumber]
既然有方法將被放置在後臺的工做提至前臺或者讓它從中止到繼續運行在後臺,固然也有方法刪除一個工做,或者重啓等等
#kill的使用格式以下
kill-signal %jobnumber
#signal從1-64個信號值能夠選擇,能夠這樣查看
#在 bash 中能夠看到更全面的信息,進入的方法就是輸入 bash
kill-l
其中經常使用的有這些信號值
信號值 |
做用 |
-1 |
從新讀取參數運行,相似與restart |
-2 |
如同 ctrl+c 的操做退出 |
-9 |
強制終止該任務 |
-15 |
正常的方式終止該任務 |
注意
如果在使用kill+信號值而後直接加數字的話,這個數字表明的是 pid,你將會對 pid 對應的進程作操做
如果在使用kill+信號值而後%jobnumber,這時所操做的對象纔是 job,這個數字就是就當前 bash 中後臺的運行的 job 的 ID
經過本實驗咱們初步的瞭解進程在系統中存在的概念,以及進程的如何在系統中衍生,發展,以及進程之間存在的相互關係,能夠爲咱們在後續學習進程管理打下基礎,同時瞭解了工做與進程,以及工做管理的一些使用性的操做。
<span id="jump"> 註釋1:此處參考來自於https://www.win.tue.nl/~aeb/linux/lk/lk-10.html </span>
經過本實驗咱們將掌握一些 Linux 所提供的工具來進行進程的查看與控制,掌握這些工具讓咱們能在某些進程出異常的時候咱們能及時的解決與查看
無論在測試的時候仍是在實際的生產環境中或者本身的使用過程當中,不免遇到進程的一些異常,因此 Linux 爲咱們提供了一些工具能夠查看進程的一些狀態信息,咱們能夠經過 top 動態實時的查看進程的狀態的已經系統的一些信息如 CPU、內存信息等等,咱們一樣能夠經過 ps 來靜態查看當前的進程信息,同時咱們還能夠使用 pstree 來查看當前活躍進程的樹形結構
top 工具是咱們經常使用的一個查看工具,他能實時的查看咱們系統的關鍵一些關鍵信息的變化已經進程在進程中的實時變化
top
top 是一個在前臺執行的程序,因此執行知道便在這樣的一個交互界面,咱們能夠經過一些指令來作一些操做,篩選。首先咱們先來了解一些顯示了哪些信息
咱們看到 top 顯示的第一排,
內容 |
解釋 |
top |
表示當前程序的名稱 |
11:05:18 |
表示當前的系統的時間 |
up 8 days,17:12 |
表示該機器已經啓動了多長時間 |
1 user |
表示當前系統中只有一個用戶 |
load average: 0.29,0.20,0.25 |
分別對應一、五、15分鐘內cpu的平均負載 |
load average 在 wikipedia 中的解釋是 the system load is a measure of the amount of work that a computer system is doing 也就是對當前 CPU 工做量的度量,具體來講也就是指運行隊列的平均長度,也就是等待CPU的平均進程數相關的一個計算值。
咱們該如何看待這個load average 數據呢?
假設咱們的系統是單CPU單內核的,把它比喻成是一條單向的橋,把CPU任務比做汽車。
這是單個 CPU 單核的狀況,而實際生活中咱們須要將獲得的這個值除以咱們的核數來看。咱們能夠經過一下的命令來查看 CPU 的個數與核心數
#查看物理CPU的個數
#cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l
#每一個cpu的核心數
grep"physical id"grep"0"cat /proc/cpuinfo |||wc -l
經過上面的指數咱們能夠得知 load 的臨界值爲 1 ,可是在實際生活中,比較有經驗的運維或者系統管理員會將臨界值定爲0.7。這裏的指數都是除以核心數之後的值,不要混淆了
一般咱們都會先看 15 分鐘的值來看這個大致的趨勢,而後再看 5 分鐘的值對比來看是否有降低的趨勢。
查看 busybox 的代碼能夠知道,數據是每 5 秒鐘就檢查一次活躍的進程數,而後計算出該值,而後 load 從/proc/loadavg 中讀取的。而這個 load 的值是如何計算的呢,這是 load 的計算的源碼
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point(定點) */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals,每隔5秒計算一次平均負載值 */
#define CALC_LOAD(load, exp, n) \
load *= exp; \
load += n*(FIXED_1 - exp); \
load >>= FSHIFT;
unsignedlong3avenrun[];
EXPORT_SYMBOL(avenrun);
/*
* calc_load - given tick count, update the avenrun load estimates.
* This is called while holding a write_lock on xtime_lock.
*/
staticinlinevoidunsignedlongcalc_load(ticks)
{
unsignedlong/* fixed-point */ active_tasks;
staticint count = LOAD_FREQ;
count -= ticks;
if0 (count <) {
count += LOAD_FREQ;
active_tasks = count_active_tasks();
CALC_LOAD0 (avenrun[], EXP_1, active_tasks);
CALC_LOAD1 (avenrun[], EXP_5, active_tasks);
CALC_LOAD2 (avenrun[], EXP_15, active_tasks);
}
}
有興趣的朋友能夠研究一下,是如何計算的。代碼中的後面這部分至關於它的計算公式
咱們迴歸正題,來看 top 的第二行數據,基本上第二行是進程的一個狀況統計
內容 |
解釋 |
Tasks: 26 total |
進程總數 |
1 running |
1個正在運行的進程數 |
25 sleeping |
25個睡眠的進程數 |
0 stopped |
沒有中止的進程數 |
0 zombie |
沒有殭屍進程數 |
來看 top 的第三行數據,這一行基本上是 CPU 的一個使用狀況的統計了
內容 |
解釋 |
Cpu(s): 1.0%us |
用戶空間佔用CPU百分比 |
1.0% sy |
內核空間佔用CPU百分比 |
0.0%ni |
用戶進程空間內改變過優先級的進程佔用CPU百分比 |
97.9%id |
空閒CPU百分比 |
0.0%wa |
等待輸入輸出的CPU時間百分比 |
0.1%hi |
硬中斷(Hardware IRQ)佔用CPU的百分比 |
0.0%si |
軟中斷(Software IRQ)佔用CPU的百分比 |
0.0%st |
(Steal time) 是當 hypervisor 服務另外一個虛擬處理器的時候,虛擬 CPU 等待實際 CPU 的時間的百分比 |
CPU 利用率,是對一個時間段內 CPU 使用情況的統計,經過這個指標能夠看出在某一個時間段內 CPU 被佔用的狀況,Load Average 是 CPU 的 Load,它所包含的信息不是 CPU 的使用率情況,而是在一段時間內 CPU 正在處理以及等待 CPU 處理的進程數狀況統計信息,這兩個指標並不同。
來看 top 的第四行數據,這一行基本上是內存的一個使用狀況的統計了
內容 |
解釋 |
8176740 total |
物理內存總量 |
8032104 used |
使用的物理內存總量 |
144636 free |
空閒內存總量 |
313088 buffers |
用做內核緩存的內存量 |
注意
系統的中可用的物理內存最大值並非 free 這個單一的值,而是 free + buffers + swap 中的 cached 的和
來看 top 的第五行數據,這一行基本上是交換區的一個使用狀況的統計了
內容 |
解釋 |
total |
交換區總量 |
used |
使用的交換區總量 |
free |
空閒交換區總量 |
cached |
緩衝的交換區總量,內存中的內容被換出到交換區,然後又被換入到內存,但使用過的交換區還沒有被覆蓋 |
在下面就是進程的一個狀況了
列名 |
解釋 |
PID |
進程id |
USER |
該進程的所屬用戶 |
PR |
該進程執行的優先級priority 值 |
NI |
該進程的 nice 值 |
VIRT |
該進程任務所使用的虛擬內存的總數 |
RES |
該進程所使用的物理內存數,也稱之爲駐留內存數 |
SHR |
該進程共享內存的大小 |
S |
該進程進程的狀態: S=sleep R=running Z=zombie |
%CPU |
該進程CPU的利用率 |
%MEM |
該進程內存的利用率 |
TIME+ |
該進程活躍的總時間 |
COMMAND |
該進程運行的名字 |
注意
NICE 值叫作靜態優先級,是用戶空間的一個優先級值,其取值範圍是-20至19。這個值越小,表示進程」優先級」越高,而值越大「優先級」越低。nice值中的 -20 到 19,中 -20 優先級最高, 0 是默認的值,而 19 優先級最低
PR 值表示 Priority 值叫動態優先級,是進程在內核中實際的優先級值,進程優先級的取值範圍是經過一個宏定義的,這個宏的名稱是MAX_PRIO,它的值爲140。Linux實際上實現了140個優先級範圍,取值範圍是從0-139,這個值越小,優先級越高。而這其中的 0 - 99 是實時的值,而 100 - 139 是給用戶的。
其中 PR 中的 100 to 139 值部分有這麼一個對應 PR = 20 + (-20 to +19),這裏的 -20 to +19 即是nice值,因此說兩個雖然都是優先級,並且有千絲萬縷的關係,可是他們的值,他們的做用範圍並不相同
VIRT 任務所使用的虛擬內存的總數,其中包含全部的代碼,數據,共享庫和被換出 swap空間的頁面等所佔據空間的總數
在上文咱們曾經說過 top 是一個前臺程序,因此是一個能夠交互的
經常使用交互命令 |
解釋 |
q |
退出程序 |
I |
切換顯示平均負載和啓動時間的信息 |
P |
根據CPU使用百分比大小進行排序 |
M |
根據駐留內存大小進行排序 |
i |
忽略閒置和僵死的進程,這是一個開關式命令 |
k |
終止一個進程,系統提示輸入 PID 及發送的信號值。通常終止進程用15信號,不能正常結束則使用9信號。安全模式下該命令被屏蔽。 |
好好的利用 top 可以頗有效的幫助咱們觀察到系統的瓶頸所在,或者是系統的問題所在
ps 也是咱們最經常使用的查看進程的工具之一,咱們經過這樣的一個命令來了解一下,他能給我帶來哪些消息
psaux
psaxjf
咱們來整體瞭解下會出現哪些信息給咱們,這些信息又表明着什麼
內容 |
解釋 |
F |
進程的標誌 為 4 表示此程序的權限為 root,若為 1 則表示此子程序僅進行複製(fork)而沒有實際執行(exec) |
USER |
進程的屬主 |
PID |
進程的ID |
PPID |
其父進程的PID |
SID |
session的ID |
TPGID |
前臺進程組的ID |
%CPU |
進程佔用的CPU百分比 |
%MEM |
佔用內存的百分比 |
NI |
進程的NICE值 |
VSZ |
進程使用虛擬內存大小 |
RSS |
駐留內存中頁的大小 |
TTY |
終端ID |
S or STAT |
進程狀態 |
WCHAN |
正在等待的進程資源 |
START |
啓動進程的時間 |
TIME |
進程消耗CPU的時間 |
COMMAND |
命令的名稱和參數 |
TPGID欄寫着-1的都是沒有控制終端的進程,也就是守護進程
STAT表示進程的狀態,而進程的狀態有不少,以下表所示
狀態 |
解釋 |
R |
Running.運行中 |
S |
Interruptible Sleep.等待調用 |
D |
Uninterruptible Sleep.不可終端睡眠 |
T |
Stoped.暫停或者跟蹤狀態 |
X |
Dead.即將被撤銷 |
Z |
Zombie.殭屍進程 |
W |
Paging.內存交換 |
N |
優先級低的進程 |
< |
優先級高的進程 |
s |
進程的領導者 |
L |
鎖定狀態 |
l |
多線程狀態 |
+ |
前臺進程 |
其中的 D 不可終端睡眠的狀態,處在這種狀態的進程不接受外來的任何signal,因此沒法使用 kill 命令殺掉處於D狀態的進程,不管是 kill,kill -9 仍是 kill -15,通常處於這種狀態多是進程 IO 的時候出問題了。
ps 工具備許多的參數,下面給你們解釋部分經常使用的參數
使用 -l 參數能夠顯示本身此次登錄的 bash 相關的進程信息羅列出來
-lps
相對來講咱們更加經常使用下面這個命令,他將會羅列出全部的進程信息
psaux
如果查找其中的某個進程的話,咱們還能夠配合着 grep 和正則表達式一塊兒使用
psaux | grep zsh
此外咱們還能夠查看時,將連同部分的進程呈樹狀顯示出來
psaxjf
固然若是你以爲使用這樣的此時沒有把你想要的信息放在一塊兒,咱們也能夠是用這樣的命令,來自定義咱們所須要的參數顯示
commandps-afxo user,ppid,pid,pgid,
這是一個簡單而又實用的工具,想要更靈活的使用,想要知道更多的參數咱們能夠使用 man 來獲取更多相關的信息
經過 pstree 能夠很直接的看到相同的進程數量,最主要的仍是咱們能夠看到全部進程的之間的相關性。
pstree
pstree-up
#參數選擇:
#-A :各程序樹之間以 ASCII 字元來連接;
#-p :同時列出每一個 process 的 PID;
#-u :同時列出每一個 process 的所屬帳戶名稱。
上個實驗中咱們講訴了進程之間是如何衍生,之間又有什麼相關性,咱們來回顧一下,當一個進程結束的時候或者要異常結束的時候,會向其父進程返回一個或者接收一個 SIGHUP 信號而作出的結束進程或者其餘的操做,這個 SIGHUP 信號不只能夠由系統發送,咱們能夠使用 kill 來發送這個信號來操做進程的結束或者重啓等等。
上節課程咱們使用 kill 命令來管理咱們的一些 job,這節課咱們將嘗試用 kill 來操做下一些不屬於 job 範疇的進程,直接對 pid 下手
#首先咱們使用圖形界面打開了 gedit、gvim,用 ps 能夠查看到
ps aux
#使用9這個信號強制結束 gedit 進程
kill91608-
#咱們在查找這個進程的時候就找不到了
grepps aux |gedit
咱們在是使用 ps 命令的時候咱們能夠看到大部分的進程都是處於休眠的狀態,若是這些進程都被喚醒,那麼該誰最早享受 CPU 的服務,後面的進程又該是一個什麼樣的順序呢?進程調度的隊列又該如何去排列呢?
固然就是靠該進程的優先級值來斷定進程調度的優先級,而優先級的值就是上文所提到的 PR 與 nice 來控制與體現了
而 nice 的值咱們是能夠經過 nice 命令來修改的,而須要注意的是 nice 值能夠調整的範圍是 -20 ~ 19,其中 root 有着至高無上的權力,既能夠調整本身的進程也能夠調整其餘用戶的程序,而且是全部的值均可以用,而普通用戶只能夠調製屬於本身的進程,而且其使用的範圍只能是 0 ~ 19,由於系統爲了不通常用戶搶佔系統資源而設置的一個限制
#這個實驗在環境中沒法作,由於權限不夠,能夠本身在本地嘗試
#打開一個程序放在後臺,或者用圖形界面打開
5nice -n -vim &
#用 ps 查看其優先級
stattimegrepps -afxo user,ppid,pid,,pri,ni,,command |vim
咱們還能夠用 renice 來修改已經存在的進程的優先級,一樣由於權限的緣由在實驗環境中沒法嘗試
renice5-pid
經過本實驗咱們學會了進程的查看命令 ps,pstree,top,以及使用這些命令是所獲得的信息的含義,從而獲取咱們想要,咱們須要的信息,同是咱們學會了進程的管理命令 kill,nice,renice
<span id=jump> 註釋1: 該例子參考於http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages</span>
日誌數據能夠是有價值的信息寶庫,也能夠是毫無價值的數據泥潭。它能夠記錄下系統所產生的全部行爲,並按照某種規範表達出來。咱們能夠使用日誌系統所記錄的信息爲系統進行排錯,優化系統的性能,或者根據這些信息調整系統的行爲。收集你想要的數據,分析出有價值的信息,能夠提升系統、產品的安全性,能夠幫助開發完善代碼,優化產品。日誌會成爲在事故發生後查明「發生了什麼」的一個很好的「取證」信息來源。日誌能夠爲審計進行審計跟蹤。
日誌是一個系統管理員,一個運維人員,甚至是開發人員不可或缺的東西,系統用久了偶爾也會出現一些錯誤,咱們須要日誌來給系統排錯,在一些網絡應用服務不能正常工做的時候,咱們須要用日誌來作問題定位,日誌仍是過往時間的記錄本,咱們能夠經過它知道咱們是否被不明用戶登錄過等等。
在 Linux 中大部分的發行版都內置使用 syslog 系統日誌,那麼經過前期的課程咱們瞭解到常見的日誌通常存放在 /var/log
中,咱們來看看其中有哪些日誌
根據圖中所顯示的日誌,咱們能夠根據服務對象粗略的將日誌分爲兩類
系統日誌主要是存放系統內置程序或系統內核之類的日誌信息如 alternatives.log
、btmp
等等,應用日誌主要是咱們裝的第三方應用所產生的日誌如 tomcat7
、apache2
等等。
接下來咱們來看看常見的系統日誌有哪些,他們都記錄了怎樣的信息
日誌名稱 |
記錄信息 |
alternatives.log |
系統的一些更新替代信息記錄 |
apport.log |
應用程序崩潰信息記錄 |
apt/history.log |
使用apt-get安裝卸載軟件的信息記錄 |
apt/term.log |
使用apt-get時的具體操做,如 package 的下載打開等 |
auth.log |
登陸認證的信息記錄 |
boot.log |
系統啓動時的程序服務的日誌信息 |
btmp |
錯誤登錄的信息記錄 |
Consolekit/history |
控制檯的信息記錄 |
dist-upgrade |
dist-upgrade這種更新方式的信息記錄 |
dmesg |
啓動時,顯示屏幕上內核緩衝信息,與硬件有關的信息 |
dpkg.log |
dpkg命令管理包的日誌。 |
faillog |
用戶登陸失敗詳細信息記錄 |
fontconfig.log |
與字體配置有關的信息記錄 |
kern.log |
內核產生的信息記錄,在本身修改內核時有很大幫助 |
lastlog |
用戶的最近信息記錄 |
wtmp |
登陸信息的記錄。wtmp能夠找出誰正在登錄進入系統,誰使用命令顯示這個文件或信息等 |
syslog |
系統信息記錄 |
而在本實驗環境中沒有 apport.log 是由於 apport 這個應用程序須要讀取一些內核的信息來收集判斷其餘應用程序的信息,從而記錄應用程序的崩潰信息。而在本實驗環境中的咱們沒有這個權限,因此將 apport 從內置應用值剔除,天然而然就沒有它的日誌信息了。
只聞其名,不見其人,咱們並不能真正體會這些日誌記錄的內容。首先咱們來看 alternatives.log
中的信息,在本實驗環境中沒有任何日誌輸出是由於剛剛啓動的系統中並無任何的更新迭代。我能夠看看從其餘地方截取過來的內容
update2016-07-02133616with--install /usr/bin/x-www-browser x-www-browser /usr/bin/google-chrome-stable 200-alternatives::: run
update2016-07-02133616with--install /usr/bin/gnome-www-browser gnome-www-browser /usr/bin/google-chrome-stable 200-alternatives::: run
update2016-07-02133616with--install /usr/bin/google-chrome google-chrome /usr/bin/google-chrome-stable 200-alternatives::: run
咱們能夠從中獲得信息有程序做用,日期,命令,成功與否的返回碼
咱們用這樣的命令來看看 auth.log
中的信息
logless auth.
咱們能夠從中獲得的信息有日期與 ip 地址的來源以及登錄的用戶與工具
在 apt 文件夾中的日誌信息,其中有兩個日誌文件 history.log
與 term.log
,兩個日誌文件的區別在於 history.log
主要記錄了進行了那個操做,相關的依賴有哪些,而 term.log
則是較爲具體的一些操做,主要就是下載包,打開包,安裝包等等的細節操做。
咱們經過這樣的例子就能夠很明顯的看出區別,在本實驗環境中由於是剛啓動的環境,因此兩個日誌中的信息都是空的
loglogless /var//apt/history.
loglogless /var//apt/term.
而後咱們來安裝 git 這個程序,由於本實驗環境中本有預裝 git 因此這裏真正執行的操做是一個更新的操做,但這並不影響
getsudo apt-install git
成功的執行以後咱們再來查看兩個日誌的內容變化
其餘的日誌格式也都相似與以前咱們所查看的日誌,主要即是時間,操做。而這其中有兩個比較特殊的日誌,其查看的方式比較不同凡響,由於這兩個日誌並非 ASCII 文件而是被編碼成了二進制文件,因此咱們並不能直接使用 less、cat、more 這樣的工具來查看,這兩個日誌文件是 wtmp,lastlog
咱們查看的方法是使用 last 與 lastlog 工具來提取其中的信息
關於這兩個工具的更深刻使用咱們能夠使用前面的學習過的 man 來查看
這些日誌是如何產生的,而且經過上面的例子咱們能夠看出大部分的日誌信息彷佛格式都都很相似,而且爲何都會出如今這個文件夾中。
這樣的實現能夠經過兩種方式,一種是由軟件開發商本身來自定義日誌格式而後指定輸出日誌位置,還有一種方式就是 Linux 提供的日誌服務程序,而咱們這裏系統日誌是經過 syslog 來實現,提供日誌管理服務。
syslog 是一個系統日誌記錄程序,在早期的大部分 Linux 發行版都是內置 syslog,讓其做爲系統的默認日誌收集工具,雖然時代的進步與發展,syslog 已經年老體衰跟不上時代的需求,因此他被 rsyslog 所代替了,較新的Ubuntu、Fedora 等等都是默認使用 rsyslog 做爲系統的日誌收集工具
rsyslog的全稱是 rocket-fast system for log,它提供了高性能,高安全功能和模塊化設計。rsyslog可以接受從各類各樣的來源,將其輸入,輸出的結果到不一樣的目的地。rsyslog能夠提供超過每秒一百萬條消息給目標文件,
這樣能實時收集日誌信息的程序都會有其守護進程如 rsyslog 的守護進程即是 rsyslogd
由於一些緣由本實驗環境中默認並無打開這個服務,咱們能夠手動開啓這項服務,而後來查看
sudoservice rsyslog start
ps aux | grep syslog
既然它是一個服務,那麼它即是能夠配置,爲咱們提供一些咱們自定義的服務
首先咱們來看 rsyslog 的配置文件是什麼樣子的,而 rsyslog 的配置文件有兩個,一個是 /etc/rsyslog
一個是 /etc/rsyslog.d/50-default.conf
。第一個主要是配置的環境,也就是 rsyslog 的加載什麼模塊,文件的所屬者等;而第二個主要是配置的 Filter Conditions
vim /etc/rsyslog.conf
50defaultvim /etc/rsyslog.d/-.conf
看了以後並不知道從何如何,也不知道他在寫什麼,咱們仍是來看看 rsyslog 的結構框架,數據流的走向吧。
經過這個簡單的流程圖咱們能夠知道 rsyslog 主要是由 Input、Output、Parser 這樣三個模塊構成的,而且瞭解到數據的簡單走向,首先經過 Input module 來收集消息,而後將獲得的消息傳給 Parser module,經過分析模塊的層層處理,將真正須要的消息傳給 Output module,而後便輸出至日誌文件中
上文提到過 rsyslog 號稱能夠提供超過每秒一百萬條消息給目標文件,怎麼只是這樣簡單的結構。咱們能夠經過下圖來作更深刻的瞭解
圖片來源於http://www.rsyslog.com/doc/queues_analogy.html
Rsyslog 架構如圖中所示,從圖中咱們能夠很清楚的看見,rsyslog 還有一個核心的功能模塊即是 Queue,也正是由於它才能作到如此高的併發。
第一個模塊即是 Input,該模塊的主要功能就是從各類各樣的來源出收集 messages,經過一下這些接口實現
接口名 |
做用 |
im3195 |
RFC3195 Input Module |
imfile |
Text File Input Module |
imgssapi |
GSSAPI Syslog Input Module |
imjournal |
Systemd Journal Input Module |
imklog |
Kernel Log Input Module |
imkmsg |
/dev/kmsg Log Input Module |
impstats |
Generate Periodic Statistics of Internal Counters |
imptcp |
Plain TCP Syslog |
imrelp |
RELP Input Module |
imsolaris |
Solaris Input Module |
imtcp |
TCP Syslog Input Module |
imudp |
UDP Syslog Input Module |
imuxsock |
Unix Socket Input |
而 Output 中也有許多可用的接口,能夠經過 man 或者官方的文檔查看
而這些模塊接口的使用須要經過 $ModLoad 指令來加載,那麼返回上文的圖中,配置生效的頭兩行能夠看懂了,默認加載了 imklog、imuxsock 這兩個模塊
在配置中 rsyslog 支持三種配置語法格式:
sysklogd 是老的簡單格式,一些新的語法特性不支持。而 legacy rsyslog 是以 dollar 符($)開頭的語法,在v6及以上的版本還在支持,就如上文所說的 $ModLoad
還有一些插件和特性可能只在此語法下支持。而以 $
開頭的指令是全局指令,全局指令是 rsyslogd 守護進程的配置指令,每行只能有一個指令。 RainnerScript 是最新的語法。在官網上 rsyslog 大多推薦這個語法格式來配置
老的語法格式(sysklogd & legacy rsyslog)是以行爲單位。新的語法格式(RainnerScript)能夠分割多行。
註釋有兩種語法:
/* .. */
執行順序: 指令在 rsyslog.conf 文件中是從上到下的順序執行的。
模板是 rsyslog 一個重要的屬性,它能夠控制日誌的格式,支持相似 template() 語句的基於 string 或 plugin 的模板,即是經過它來自定義咱們的日誌格式
legacy 格式使用 $template 的語法,不過這個在之後要移除,因此最好使用新格式 template():,以避免將來忽然不工做了也不知道爲何
模板定義的形式有四種,適用於不一樣的輸出模塊,通常簡單的格式,能夠使用 string 的形式,複雜的格式,建議使用 list 的形式,使用 list 的形式,能夠使用一些額外的屬性字段(property statement)
若是不指定輸出模板,rsyslog 會默認使用 RSYSLOG_DEFAULT。若想更深刻的學習能夠查看官方文檔
瞭解了 rsyslog 環境的配置文件以後,咱們看向 /etc/rsyslog.d/50-default.conf
這個配置文件,這個文件中主要是配置的 Filter Conditions,也就咱們在流程圖中所看見的 Parser & Filter Engine
,它的名字叫 Selectors 是過濾 syslog 的傳統方法,他主要由兩部分組成,facility
與 priority
,其配置格式以下
logfacility.priority _location
其中一個 priority 能夠指定多個 facility,多個 facility 之間使用逗號 ,
分割開
rsyslog 經過 Facility 的概念來定義日誌消息的來源,以便對日誌進行分類,Facility 的種類有:
類別 |
解釋 |
kern |
內核消息 |
user |
用戶信息 |
|
郵件系統消息 |
daemon |
系統服務消息 |
auth |
認證系統 |
authpriv |
權限系統 |
syslog |
日誌系統自身消息 |
cron |
計劃安排 |
news |
新聞信息 |
local0~7 |
由自定義程序使用 |
而另一部分 priority 也稱之爲 serverity level,除了日誌的來源之外,對統一源產生日誌消息還須要進行優先級的劃分,而優先級的類別有一下幾種:
類別 |
解釋 |
emergency |
系統已經沒法使用了 |
alert |
必須當即處理的問題 |
critical |
很嚴重了 |
error |
錯誤 |
warning |
警告信息 |
notice |
系統正常,可是比較重要 |
informational |
正常 |
debug |
debug的調試信息 |
panic |
很嚴重可是已淘汰不經常使用 |
none |
沒有優先級,不記錄任何日誌消息 |
咱們來看看系統中的配置
loglogauth,authpriv.* /var//auth.
這裏的意思是 auth 與 authpriv 的全部優先級的信息全都輸出於 /var/log/auth.log
日誌中
而其中有相似於這樣的配置信息意思有細微的差異
loglogkern.* -/var//kern.
-
表明異步寫入,也就是日誌寫入時不須要等待系統緩存的同步,也就是日誌還在內存中緩存也能夠繼續寫入無需等待徹底寫入硬盤後再寫入。一般用於寫入數據比較大時使用。
到此咱們對 rsyslog 的配置就有了必定的瞭解,若想更深刻學習模板,隊列的高級應用,你們可去查看官網的文檔,須要注意的是 rsyslog 每一個版本之間差別化比較大,學習以前先查看本身所使用的版本,再去查看相關的文檔
與日誌相關的還有一個還有經常使用的命令 logger
,logger 是一個 shell 命令接口,能夠經過該接口使用 Syslog 的系統日誌模塊,還能夠從命令行直接向系統日誌文件寫入信息。
#首先將syslog啓動起來
sudo service rsyslog start
#向 syslog 寫入數據
testlocalping 127.0.0.1 | logger -it logger_-p3.notice &
#查看是否有數據寫入
-flogtail/var//syslog
從圖中咱們能夠看到咱們成功的將 ping 的信息寫入了 syslog 中,格式也就是使用的 rsyslog 的默認模板
咱們能夠經過 man 來查看 logger 的更深刻用法,上訴命令中
參數 |
內容 |
-i |
在每行都記錄進程ID |
-t |
添加tag標籤 |
-p |
設置日誌的facility與priority |
在本地的機器中天天都有成百上千條日誌被寫入文件中,更別說是咱們的服務器,天天都會有數十兆甚至更多的日誌信息被寫入文件中,若是是這樣的話,天天看着咱們的日誌文件不斷的膨脹,那豈不是要佔用許多的空間,因此有個叫 logrotate 的東西誕生了。
logrotate 程序是一個日誌文件管理工具。用來把舊的日誌文件刪除,並建立新的日誌文件。咱們能夠根據日誌文件的大小,也能夠根據其天數來切割日誌,來管理日誌。這個過程又叫作「轉儲」
大多數Linux發行版使用 logrotate 或 newsyslog 對日誌進行管理。logrotate 程序不但能夠壓縮日誌文件,減小存儲空間,還能夠將日誌發送到指定 E-mail,方便管理員及時查看日誌。
顯而易見,logrotate 是基於 CRON 來運行的,其腳本是 /etc/cron.daily/logrotate;同時咱們能夠在 /etc/logrotate
中找到其配置文件
cat/etc/logrotate
這其中的具體意思是什麼呢?
# see "man logrotate" for details //能夠查看幫助文檔
# rotate log files weekly
//設置每週轉儲一次(daily、weekly、monthly固然能夠使用這些參數天天、星期,月 )weekly
# keep 4 weeks worth of backlogs
4//最多轉儲4次rotate
# create new (empty) log files after rotating old ones
//當轉儲後文件不存在時建立它create
# uncomment this if you want your log files compressed
//經過gzip壓縮方式轉儲(nocompress能夠不壓縮)compress
# RPM packages drop log rotation information into this directory
include//其餘日誌文件的轉儲方式配置文件,包含在該目錄下/etc/logrotate.d
# no packages own wtmp -- we'll rotate them here
var//設置/var/log/wtmp日誌文件的轉儲參數//log/wtmp {
//每個月轉儲 monthly
0664//轉儲後文件不存在時建立它,文件全部者爲root,所屬組爲utmp,對應的權限爲0664 createroot utmp
1//最多轉儲一次 rotate
}
固然在 /etc/logrotate.d/ 中有各項應用的 logrotate 配置,還有更多的配置參數,你們能夠使用 man 查看,如按文件大小轉儲,按當前時間格式命名等等參數配置。
經過本實驗咱們瞭解系統日誌結構,以及咱們能夠從中獲取什麼樣的信息,給咱們帶來什麼樣的價值。還有日誌工具的配置,以及省心省力的 logrotate