Linux基礎總結

Linux操做系統

Linux操做系統博大精深,其中對線程,IO,文件系統等概念的實現都頗有借鑑意義。html

文件系統和VFS

文件系統的inode上面講過了。VFS主要用於屏蔽底層的不一樣文件系統,好比接入網絡中的nfs文件系統,亦或是windows文件系統,正常狀況下難以辦到,而vfs經過使用IO操做的posix規範來規定全部文件讀寫操做,每一個文件系統只須要實現這些操做就能夠接入VFS,不須要從新安裝文件系統。node

進程和線程

> 進程、程序與線程
> 
> 程序
> 
>  程序,簡單的來講就是存在磁盤上的二進制文件,是能夠內核所執行的代碼 
> 
> 進程
> 
>  當一個用戶啓動一個程序,將會在內存中開啓一塊空間,這就創造了一個進程,一個進程包含一個獨一無二的PID,和執行者的權限屬性參數,以及程序所需代碼與相關的資料。
>  進程是系統分配資源的基本單位。
>  一個進程能夠衍生出其餘的子進程,子進程的相關權限將會沿用父進程的相關權限。
> 
> 線程
> 
>  每一個進程包含一個或多個線程,線程是進程內的活動單元,是負責執行代碼和管理進程運行狀態的抽象。
>  線程是獨立運行和調度的基本單位。
複製代碼

子進程和父進程 進程的層次結構(父進程與子進程)在進程執行的過程當中可能會衍生出其餘的進程,稱之爲子進程,子進程擁有一個指明其父進程PID的PPID。子進程能夠繼承父進程的環境變量和權限參數。linux

因而,linux系統中就誕生了進程的層次結構——進程樹。 進程樹的根是第一個進程(init進程)。ios

過程調用的流程: fork & exec一個進程生成子進程的過程是,系統首先複製(fork)一份父進程,生成一個暫存進程,這個暫存進程和父進程的區別是pid不同,並且擁有一個ppid,這時候系統再去執行(exec)這個暫存進程,讓他加載實際要運行的程序,最終成爲一個子進程的存在。正則表達式

服務與進程算法

簡單的說服務(daemon)就是常駐內存的進程,一般服務會在開機時經過init.d中的一段腳本被啓動。shell

進程通訊數據庫

進程通訊的幾種基本方式:管道,信號量,消息隊列,共享內存,快速用戶控件互斥。express

fork方法

一個進程,包括代碼、數據和分配給進程的資源。fork()函數經過系統調用建立一個與原來進程幾乎徹底相同的進程,編程

也就是兩個進程能夠作徹底相同的事,但若是初始參數或者傳入的變量不一樣,兩個進程也能夠作不一樣的事。

一個進程調用fork()函數後,系統先給新的進程分配資源,例如存儲數據和代碼的空間。而後把原來的進程的全部值都
複製代碼

複製到新的新進程中,只有少數值與原來的進程的值不一樣。至關於克隆了一個本身。

fork調用的一個奇妙之處就是它僅僅被調用一次,卻可以返回兩次,它可能有三種不一樣的返回值:
    1)在父進程中,fork返回新建立子進程的進程ID;
    2)在子進程中,fork返回0;
    3)若是出現錯誤,fork返回一個負值;
複製代碼

如何理解pid在父子進程中不一樣?

其實就至關於鏈表,進程造成了鏈表,父進程的pid指向了子進程的pid,由於子進程沒有子進程,因此pid爲0。

寫時複製

傳統的fork機制是,調用fork時,內核會複製全部的內部數據結構,複製進程的頁表項,而後把父進程的地址空間按頁複製給子進程(很是耗時)。

現代的fork機制採用了一種惰性算法的優化策略。

爲了不復制時系統開銷,就儘量的減小「複製」操做,當多個進程須要讀取他們本身那部分資源的副本時,並不複製多個副本出來,而是爲每一個進程設定一個文件指針,讓它們讀取同一個實際文件。

顯然這樣的方式會在寫入時產生衝突(相似併發),因而當某個進程想要修改本身的那個副本時,再去複製該資源,(只有寫入時才複製,因此叫寫時複製)這樣就減小了複製的頻率。
複製代碼

父子進程,殭屍進程,孤兒進程,守護進程

父進程經過fork產生子進程。

孤兒進程:當子進程未結束時父進程異常退出,本來須要由父進程進行處理的子進程變成了孤兒進程,init系統進程會把這些進程領養,避免他們成爲孤兒。

殭屍進程:當子進程結束時,會在內存中保留一部分數據結構等待父親進程顯式結束,若是父進程沒有執行結束操做,則會致使子進程的剩餘結構沒法被釋放,佔用空間形成嚴重後果。

守護進程:守護進程用於監控其餘進程,當發現大量殭屍進程時,會找到他們的父節點並殺死,同時讓init線程認養他們以便釋放這些空間。

殭屍進程是有害的,孤兒進程因爲內核進程的認養不會形成危害。

進程組和會話

會話和進程組進程組每一個進程都屬於某個進程組,進程組就是由一個或者多個爲了實現做業控制而相互關聯的進程組成的。

一個進程組的id是進程組首進程的pid(若是一個進程組只有一個進程,那進程組和進程其實沒啥區別)。

進程組的意義在於,信號能夠發送給進程組中的全部進程。這樣能夠實現對多個進程的同時操做。 會話會話是一個或者多個進程組的集合。

通常來講,會話(session)和shell沒有什麼本質上的區別。 咱們一般使用用戶登陸一個終端進行一系列操做這樣的例子來描述一次會話。

舉例

$cat ship-inventory.txt | grep

booty|sort上面就是在某次會話中的一個shell命令,它會產生一個由3個進程組成的進程組。

守護進程

守護進程(服務)守護進程(daemon)運行在後臺,不與任何控制終端相關聯。一般在系統啓動時經過init腳本被調用而開始運行。

在linux系統中,守護進程和服務沒有什麼區別。 對於一個守護進程,有兩個基本的要求:其一:必須做爲init進程的子進程運行,其二:不與任何控制終端交互。

硬鏈接和軟鏈接

硬連接指的是不一樣的文件名指向同一個inode節點,好比某個目錄下的a和另外一個目錄下的b,創建一個軟鏈接讓a指向b,則a和b共享同一個inode。

軟鏈接是指一個文件的inode節點不存數據,而是存儲着另外一個文件的絕對路徑,訪問文件內容時其實是去訪問對應路徑下的文件inode,這樣的話文件發生改動或者移動都會致使軟鏈接失效。

線程

線程基礎概念線程是進程內的執行單元(比進程更低一層的概念),具體包括 虛擬處理器,堆棧,程序狀態等。 能夠認爲 線程是操做系統調度的最小執行單元。

現代操做系統對用戶空間作兩個基礎抽象:虛擬內存和虛擬處理器。這使得進程內部「感受」本身獨佔機器資源。

虛擬內存系統會爲每一個進程分配獨立的內存空間,這會讓進程覺得本身獨享所有的RAM。

可是同一個進程內的全部線程共享該進程的內存空間。 虛擬處理器這是一個針對線程的概念,它讓每一個線程都「感受」本身獨享CPU。實際上對於進程也是同樣的。

線程模型

線程模型線程的概念同時存在於內核和用戶空間中。下面介紹三種線程模型。

內核級線程模型每一個內核線程直接轉換成用戶空間的線程。即內核線程:用戶空間線程=1:1

用戶級線程模型這種模型下,一個保護了n個線程的用戶進程只會映射到一個內核進程。即n:1。
能夠減小上下文切換的成本,但在linux下沒什麼意義,由於linux下進程間的上下文切換自己就沒什麼消耗,因此不多使用。

混合式線程模型上述兩種模型的混合,即n:m型。
很難實現。
複製代碼

內核線程實現

系統線程實現:PThreads 原始的linux系統調用中,沒有像C++11或者是Java那樣完整的線程庫。

總體看來pthread的api比較冗餘和複雜,可是基本操做也主要是 建立、退出等。

1.建立線程

int pthread_create
  
  (若線程建立成功,則返回0。若線程建立失敗,則返回出錯編號)
  
  注意:線程建立者和新建線程之間沒有fork()調用那樣的父子關係,它們是對等關係。調用pthread_create()建立線程後,線程建立者和新建線程哪一個先運行是不肯定的,特別是在多處理機器上。
複製代碼

   2.終止線程

void pthread_exit(void *value_ptr);
  
     線程調用pthread_exit()結束本身,參數value_ptr做爲線程的返回值被調用pthread_join的線程使用。因爲一個進程中的多個線程是共享數據段的,所以一般在線程退出以後,退出線程所佔用的資源並不會隨着線程的終止而獲得釋放,可是能夠用pthread_join()函數來同步並釋放資源
複製代碼

3.取消線程

int pthread_cancel(pthread_t thread);
  
  注意:如果在整個程序退出時,要終止各個線程,應該在成功發送 CANCEL指令後,使用 pthread_join函數,等待指定的線程已經徹底退出之後,再繼續執行;不然,很容易產生 「段錯誤」。
複製代碼

   4.鏈接線程(阻塞)

int pthread_join(pthread_t thread, void **value_ptr);
  
  等待線程thread結束,並設置*value_ptr爲thread的返回值。pthread_join阻塞調用者,一直到線程thread結束爲止。當函數返回時,被等待線程的資源被收回。若是進程已經結束,那麼該函數會當即返回。而且thread指定的線程必須是joinable的。

須要留意的一點是linux機制下,線程存在一個被稱爲joinable的狀態。下面簡要了解一下:
複製代碼

Join和Detach 這塊的概念,很是相似於以前父子進程那部分,等待子進程退出的內容(一系列的wait函數)。

linux機制下,線程存在兩種不一樣的狀態:joinable和unjoinable。

若是一個線程被標記爲joinable時,即使它的線程函數執行完了,或者使用了pthread_exit()結束了該線程,它所佔用的堆棧資源和進程描述符都不會被釋放(相似殭屍進程),這種狀況應該由線程的建立者調用pthread_join()來等待線程的結束並回收其資源(相似wait系函數)。默認狀況下建立的線程都是這種狀態。

若是一個線程被標記成unjoinable,稱它被分離(detach)了,這時候若是該線程結束,全部它的資源都會被自動回收。省去了給它擦屁股的麻煩。

由於建立的線程默認都是joinable的,因此要麼在父線程調用pthread_detach(thread_id)將其分離,要麼在線程內部,調用pthread_detach(pthread_self())來把本身標記成分離的。
複製代碼

文件系統

文件描述符在linux內核中,文件是用一個整數來表示的,稱爲 文件描述符,通俗的來講,你能夠理解它是文件的id(惟一標識符)

普通文件
普通文件就是字節流組織的數據。
文件並非經過和文件名關聯來實現的,而是經過關聯索引節點來實現的,文件節點擁有文件系統爲普通文件分配的惟一整數值(ino),而且存放着一些文件的相關元數據。

目錄與連接
正常狀況下文件是經過文件名來打開的。
目錄是可讀名稱到索引編號之間的映射,名稱和索引節點之間的配對稱爲連接。
能夠把目錄看作普通文件,只是它包含着文件名稱到索引節點的映射(連接)
複製代碼

文件系統是基於底層存儲創建的一個樹形文件結構。比較經典的是Linux的文件系統,首先在硬盤的超級塊中安裝文件系統,磁盤引導時會加載文件系統的信息。

linux使用inode來標識任意一個文件。inode存儲除了文件名之外的文件信息,包括建立時間,權限,以及一個指向磁盤存儲位置的指針,那裏纔是真正存放數據的地方。

一個目錄也是一個inode節點。

詳細闡述一次文件訪問的過程:

首先用戶ls查看目錄。因爲一個目錄也是一個文件,因此至關因而看目錄文件下有哪些東西。

實際上目錄文件是一個特殊的inode節點,它不須要存儲實際數據,而只是維護一個文件名到inode的映射表。

因而咱們ls到另外一個目錄。同理他也是一個inode。咱們在這個inode下執行vi操做打開某個文件,因而linux經過inode中的映射表找到了咱們請求訪問的文件名對應的inode。

而後尋道到對應的磁盤位置,讀取內容到緩衝區,經過系統調用把內容讀到內存中,最後進行訪問。
複製代碼

IO操做

文件描述符

  對於內核而言,全部打開的文件都經過文件描述符引用。文件描述符是一個非負整數。當打開一個現有文件或建立一個新文件時,內核向進程返回一個文件描述符。當讀或寫一個文件時,使用open或create返回的文件描述符表示該文件,將其做爲參數傳給read或write函數。

write函數

  write函數定義以下:

#include  ssize_t write(int filedes, void *buf, size_t nbytes); // 返回:若成功則返回寫入的字節數,若出錯則返回-1 // filedes:文件描述符 // buf:待寫入數據緩存區 // nbytes:要寫入的字節數

  一樣,爲了保證寫入數據的完整性,在《UNIX網絡編程 卷1》中,做者將該函數進行了封裝,具體程序以下:

複製代碼

 1 ssize_t                        /* Write "n" bytes to a descriptor. */
 2 writen(int fd, const void *vptr, size_t n)
 3 {
 4     size_t nleft;
 5     ssize_t nwritten;
 6     const char *ptr;
 7 
 8     ptr = vptr; 9     nleft = n; 10     while (nleft > 0) { 11         if ( (nwritten = write(fd, ptr, nleft)) <= 0) { 12             if (nwritten < 0 && errno == EINTR) 13                 nwritten = 0;        /* and call write() again */
14             else
15                 return(-1);            /* error */
16 } 17 
18         nleft -= nwritten; 19         ptr   += nwritten; 20 } 21     return(n); 22 } 23 /* end writen */
24 
25 void
26 Writen(int fd, void *ptr, size_t nbytes) 27 { 28     if (writen(fd, ptr, nbytes) != nbytes) 29         err_sys("writen error"); 30 }

複製代碼

read函數

  read函數定義以下:

#include  ssize_t read(int filedes, void *buf, size_t nbytes); // 返回:若成功則返回讀到的字節數,若已到文件末尾則返回0,若出錯則返回-1 // filedes:文件描述符 // buf:讀取數據緩存區 // nbytes:要讀取的字節數

  有幾種狀況可以使實際讀到的字節數少於要求讀的字節數:

  1)讀普通文件時,在讀到要求字節數以前就已經達到了文件末端。例如,若在到達文件末端以前還有30個字節,而要求讀100個字節,則read返回30,下一次再調用read時,它將返回0(文件末端)。

  2)當從終端設備讀時,一般一次最多讀一行。

  3)當從網絡讀時,網絡中的緩存機構可能形成返回值小於所要求讀的字結束。

  4)當從管道或FIFO讀時,如若管道包含的字節少於所需的數量,那麼read將只返回實際可用的字節數。

  5)當從某些面向記錄的設備(例如磁帶)讀時,一次最多返回一個記錄。

  6)當某一個信號形成中斷,而已經讀取了部分數據。

  在《UNIX網絡編程 卷1》中,做者將該函數進行了封裝,以確保數據讀取的完整,具體程序以下:

複製代碼

 1 ssize_t                        /* Read "n" bytes from a descriptor. */
 2 readn(int fd, void *vptr, size_t n)
 3 {
 4     size_t nleft;
 5     ssize_t nread;
 6     char *ptr;
 7 
 8     ptr = vptr; 9     nleft = n; 10     while (nleft > 0) { 11         if ( (nread = read(fd, ptr, nleft)) < 0) { 12             if (errno == EINTR) 13                 nread = 0;        /* and call read() again */
14             else
15                 return(-1); 16         } else if (nread == 0) 17             break;                /* EOF */
18 
19         nleft -= nread; 20         ptr   += nread; 21 } 22     return(n - nleft);        /* return >= 0 */
23 } 24 /* end readn */
25 
26 ssize_t 27 Readn(int fd, void *ptr, size_t nbytes) 28 { 29 ssize_t        n; 30 
31     if ( (n = readn(fd, ptr, nbytes)) < 0) 32         err_sys("readn error"); 33     return(n); 34 }

複製代碼

本文下半部分摘自博文淺談TCP/IP網絡編程中socket的行爲

read/write的語義:爲何會阻塞?

  先從write提及:

#include  ssize_t write(int fd, const void *buf, size_t count);

  首先,write成功返回,**只是buf中的數據被複制到了kernel中的TCP發送緩衝區。**至於數據何時被髮往網絡,何時被對方主機接收,何時被對方進程讀取,系統調用層面不會給予任何保證和通知。

  write在什麼狀況下會阻塞?當kernel的該socket的發送緩衝區已滿時。對於每一個socket,擁有本身的send buffer和receive buffer。從Linux 2.6開始,兩個緩衝區大小都由系統來自動調節(autotuning),但通常在default和max之間浮動。

# 獲取socket的發送/接受緩衝區的大小:(後面的值是在Linux 2.6.38 x86_64上測試的結果)
sysctl net.core.wmem_default       #126976
sysctl net.core.wmem_max        #131071

  已經發送到網絡的數據依然須要暫存在send buffer中,只有收到對方的ack後,kernel才從buffer中清除這一部分數據,爲後續發送數據騰出空間。接收端將收到的數據暫存在receive buffer中,自動進行確認。但若是socket所在的進程不及時將數據從receive buffer中取出,最終致使receive buffer填滿,因爲TCP的滑動窗口和擁塞控制,接收端會阻止發送端向其發送數據。這些控制皆發生在TCP/IP棧中,對應用程序是透明的,應用程序繼續發送數據,最終致使send buffer填滿,write調用阻塞。

  通常來講,因爲接收端進程從socket讀數據的速度跟不上發送端進程向socket寫數據的速度,最終致使發送端write調用阻塞。

  而read調用的行爲相對容易理解,從socket的receive buffer中拷貝數據到應用程序的buffer中。read調用阻塞,一般是發送端的數據沒有到達。

Linux經常使用命令和基礎知識

查看進程

1. ps
查看某個時間點的進程信息

示例一:查看本身的進程

# ps -l
示例二:查看系統全部進程

# ps aux
示例三:查看特定的進程

# ps aux | grep threadx

2. top
實時顯示進程信息

示例:兩秒鐘刷新一次

# top -d 2
3. pstree
查看進程樹

示例:查看全部進程樹

# pstree -A
4. netstat
查看佔用端口的進程

示例:查看特定端口的進程

# netstat -anp | grep port
複製代碼

文件操做

ls -a ,all列出所有文件包括隱藏

ls -l,list顯示文件的所有屬性

ls -d,僅列出目錄自己

cd mkdir rmdir 經常使用不解釋 rm -rf永久刪除 cp複製 mv移動或更名

touch,更新文件時間或者創建新文件。

權限操做

chmod rwx 分別對應 421

 chmod 754 .bashrc 將權限改成rwxr-xr--

對應權限分配是對於 擁有者,所屬羣組,以及其餘人。
複製代碼

文件默認權限

文件默認權限:文件默認沒有可執行權限,所以爲 666,也就是 -rw-rw-rw- 。

目錄默認權限:目錄必需要可以進入,也就是必須擁有可執行權限,所以爲 777 ,也就是 drwxrwxrwx。

目錄的權限

ps:擁有目錄權限才能修改文件名,擁有文件權限是沒用的

文件名不是存儲在一個文件的內容中,而是存儲在一個文件所在的目錄中。所以,擁有文件的 w 權限並不能對文件名進行修改。
複製代碼

目錄存儲文件列表,一個目錄的權限也就是對其文件列表的權限。所以,目錄的 r 權限表示能夠讀取文件列表;w 權限表示能夠修改文件列表,具體來講,就是添加刪除文件,對文件名進行修改;x 權限可讓該目錄成爲工做目錄,x 權限是 r 和 w 權限的基礎,若是不能使一個目錄成爲工做目錄,也就沒辦法讀取文件列表以及對文件列表進行修改了。

鏈接操做

硬連接:

使用ln創建了一個硬鏈接,經過ll -i得到他們的inode節點。發現他們的inode節點是相同的。符合硬鏈接規定。


# ln /etc/crontab .
# ll -i /etc/crontab crontab

34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 crontab
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
複製代碼

軟鏈接:

符號連接文件保存着源文件所在的絕對路徑,在讀取時會定位到源文件上,能夠理解爲 Windows 的快捷方式。

當源文件被刪除了或者被移動到其餘位置了,連接文件就打不開了。

能夠爲目錄創建連接。

# ll -i /etc/crontab /root/crontab2

34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
53745909 lrwxrwxrwx. 1 root root 12 Jun 23 22:31 /root/crontab2 -> /etc/crontab
複製代碼

獲取內容

cat 讀取內容 加上-n 按行打印

tac是cat的反向操做

more容許翻頁查看,而不像cat一次顯示所有內容

less能夠先前翻頁和向後翻頁,more只能向前翻頁

head 和tail 負責取得文件的前幾行和後幾行

搜索和定位

1 which負責指令搜索,並顯示第一條 好比which pwd,會找到pwd對應的程序。加-a 打印所有。

2 whereis負責搜索文件, 後面接上dirname/filename

文件搜索。速度比較快,由於它只搜索幾個特定的目錄。
好比 whereis /bin hello.c

3 locate
文件搜索。能夠用關鍵字或者正則表達式進行搜索。

locate 使用 /var/lib/mlocate/ 這個數據庫來進行搜索,它存儲在內存中,而且天天更新一次,因此沒法用 locate 搜索新建的文件。可使用 updatedb 來當即更新數據庫。

# locate [-ir] keyword
-r:正則表達式

locate hello 
locate he*
vi heeee
updatedb
locate he?

4. find
文件搜索。可使用文件的屬性和權限進行搜索。

# find [basedir] [option]
example: find . -name "shadow*"

find -name "hike"
find +屬性後綴 "屬性"

(一)與時間有關的選項

-mtime  n :列出在 n 天前的那一天修改過內容的文件

(二)與文件擁有者和所屬羣組有關的選項

-uid n
-gid n
-user name

(三)與文件權限和名稱有關的選項

-name filename
-size [+-]SIZE:搜尋比 SIZE 還要大 (+) 或小 (-) 的文件。這個 SIZE 的規格有:c: 表明 byte,k: 表明 1024bytes。因此,要找比 50KB 還要大的文件,就是 -size +50k
-type TYPE
複製代碼

壓縮

gzip壓縮和解壓,還有bzip,xz等壓縮

而tar能夠用打包,打包的時候也能夠執行壓縮

壓縮指令只能對一個文件進行壓縮,而打包可以將多個文件打包成一個大文件。tar 不只能夠用於打包,也可使用 gip、bzip二、xz 將打包文件進行壓縮。

$ tar [-z|-j|-J] [cv] [-f 新建的 tar 文件] filename...  ==打包壓縮
$ tar [-z|-j|-J] [tv] [-f 已有的 tar 文件]              ==查看
$ tar [-z|-j|-J] [xv] [-f 已有的 tar 文件] [-C 目錄]    ==解壓縮
複製代碼

管道指令

1 |

2 cut切分數據,分紅多列,last顯示登錄者信息

正則

grep

g/re/p(globally search a regular expression and print),使用正則表示式進行全局查找並打印。

$ grep [-acinv] [--color=auto] 搜尋字符串 filename
-c : 計算找到個數
-i : 忽略大小寫
-n : 輸出行號
-v : 反向選擇,亦即顯示出沒有 搜尋字符串 內容的那一行
--color=auto :找到的關鍵字加顏色顯示
複製代碼

awk

$ awk '條件類型 1 {動做 1} 條件類型 2 {動做 2} ...' filename
示例 2:/etc/passwd 文件第三個字段爲 UID,對 UID 小於 10 的數據進行處理。

$ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}'
root 0
bin 1
daemon 2
sed

示例 3:輸出正在處理的行號,並顯示每一行有多少字段

$ last -n 5 | awk '{print $1 "\t lines: " NR "\t columns: " NF}'
dmtsai lines: 1 columns: 10
dmtsai lines: 2 columns: 10
dmtsai lines: 3 columns: 10
dmtsai lines: 4 columns: 10
dmtsai lines: 5 columns: 9
複製代碼

sed:

awk用於匹配每一行中的內容並打印
而sed負責把文件內容重定向到輸出,因此sed讀取完文件並重定向到輸出而且經過awk匹配這些內容並打印。

他們倆常常搭配使用。
複製代碼

linux指令實踐和常見場景

查看進程狀態

Linux進程狀態(ps stat)之R、S、D、T、Z、X

D    不可中斷     Uninterruptible sleep (usually IO)
R    正在運行,或在隊列中的進程
S    處於休眠狀態
T    中止或被追蹤
Z    殭屍進程
W    進入內存交換(從內核2.6開始無效)
X    死掉的進程


<    高優先級
N    低優先級
L    有些頁被鎖進內存
s    包含子進程
+    位於後臺的進程組;
l    多線程,克隆線程  multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
複製代碼

ps aux

strace

strace用於跟蹤程序執行過程當中的系統調用,如跟蹤test進程,只須要:

strace -p [test_pid] 或直接strace ./test

好比,跟蹤pid爲12345的進程中全部線程的read和write系統調用,輸出字符串的長度限制爲1024:

strace -s 1024 -f -e trace=read,write -p 12345

tcpdump

tcpdump是Linux上的抓包工具,如抓取eth0網卡上的包,使用:

sudo tcpdump -i eth0

好比,抓取80端口的HTTP報文,以文本形式展現:

sudo tcpdump -i any port 80 -A 這樣你就能夠清楚看到GET、POST請求的內容了。

nc

nc能夠在Linux上開啓TCP Server、TCP Client、UDP Server、UDP Client。

如在端口號12345上開啓TCP Server和Client模擬TCP通訊:

Server: nc -l 127.0.0.1 12345 Client: nc 127.0.0.1 12345 在端口號12345上開啓UDP Server和Client模擬TCP通訊:

Server: nc -ul 127.0.0.1 12345 Client: nc -u 127.0.0.1 12345 Unix Socket通訊示例:

Server: nc -Ul /tmp/1.sock Client: nc -U /tmp/1.sock

curl

curl用於模擬HTTP請求,在終端模擬請求時經常使用,如最基本的用法:

curl http://www.baidu.com

lsof

lsof命令主要用法包括:

sudo lsof -i :[port] 查看端口占用進程信息,常常用於端口綁定失敗時確認端口被哪一個進程佔用

sudo lsof -p [pid] 查看進程打開了哪些文件或套接字

ss

Linux上的ss命令能夠用於替換netstat,ss直接讀取解析/proc/net下的統計信息,相比netstat遍歷/proc下的每一個PID目錄,速度快不少。

awk/sed

awk和sed在文本處理方面十分強大,其中,awk按列進行處理,sed按行進行處理。

如採用冒號分隔數據,輸出第一列數據($0表明行所有列數據,$1表明第一列,$2表明第二列...)

awk -F ":" '{print $1}' 在awk的結果基礎上,結合sort、uniq和head等命令能夠輕鬆完成頻率統計等功能

查看文件的第100行到第200行: sed -n '100,200p' log.txt 替換字符串中的特定子串 echo "int charset=gb2312 float"|sed "s/charset=gb2312/charset=UTF-8/g" 替換test文件每行匹配ab的部分爲cd sed -i 's/ab/cd/g' test

vim

打開文件並跳到第10行

$ vim +10 filename.txt 打開文件跳到第一個匹配的行

$ vim +/search-term filename.txt 以只讀模式打開文件

$ vim -R /etc/passwd

crontab

查看某個用戶的crontab入口

$ crontab -u john -l 設置一個每十分鐘執行一次的計劃任務

*/10 * * * * /home/ramesh/check-disk-space 更多示例:Linux Crontab: 15 Awesome Cron Job Examples

service

service命令用於運行System V init腳本,這些腳本通常位於/etc/init.d文件下,這個命令能夠直接運行這個文件夾裏面的腳本,而不用加上路徑

查看服務狀態

$ service ssh status 查看全部服務狀態

$ service --status-all 重啓服務

$ service ssh restart

free

這個命令用於顯示系統當前內存的使用狀況,包括已用內存、可用內存和交換內存的狀況

默認狀況下free會以字節爲單位輸出內存的使用量

$ free
             total       used       free     shared    buffers     cached
Mem:       3566408    1580220    1986188          0     203988     902960
-/+ buffers/cache:     473272    3093136
Swap:      4000176          0    4000176
複製代碼

若是你想以其餘單位輸出內存的使用量,須要加一個選項,-g爲GB,-m爲MB,-k爲KB,-b爲字節

$ free -g
             total       used       free     shared    buffers     cached
Mem:             3          1          1          0          0          0
-/+ buffers/cache:          0          2
Swap:            3          0          3
複製代碼

若是你想查看全部內存的彙總,請使用-t選項,使用這個選項會在輸出中加一個彙總行

ramesh@ramesh-laptop:~$ free -t
             total       used       free     shared    buffers     cached
Mem:       3566408    1592148    1974260          0     204260     912556
-/+ buffers/cache:     475332    3091076
Swap:      4000176          0    4000176
Total:     7566584    1592148    5974436
複製代碼

top

top命令會顯示當前系統中佔用資源最多的一些進程(默認以CPU佔用率排序)若是你想改變排序方式,能夠在結果列表中點擊O(大寫字母O)會顯示全部可用於排序的列,這個時候你就能夠選擇你想排序的列

Current Sort Field:  P  for window 1:Def
Select sort field via field letter, type any other key to return

  a: PID        = Process Id              v: nDRT       = Dirty Pages count
  d: UID        = User Id                 y: WCHAN      = Sleeping in Function
  e: USER       = User Name               z: Flags      = Task Flags
  ........
複製代碼

若是隻想顯示某個特定用戶的進程,可使用-u選項

$ top -u oracle

df

顯示文件系統的磁盤使用狀況,默認狀況下df -k 將以字節爲單位輸出磁盤的使用量

$ df -k

Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             29530400   3233104  24797232  12% /
/dev/sda2            120367992  50171596  64082060  44% /home
複製代碼

使用-h選項能夠以更符合閱讀習慣的方式顯示磁盤使用量

$ df -h

Filesystem                  Size   Used  Avail Capacity  iused      ifree %iused  Mounted on
/dev/disk0s2               232Gi   84Gi  148Gi    37% 21998562   38864868   36%   /
devfs                      187Ki  187Ki    0Bi   100%      648          0  100%   /dev
map -hosts                   0Bi    0Bi    0Bi   100%        0          0  100%   /net
map auto_home                0Bi    0Bi    0Bi   100%        0          0  100%   /home
/dev/disk0s4               466Gi   45Gi  421Gi    10%   112774  440997174    0%   /Volumes/BOOTCAMP
//app@izenesoft.cn/public  2.7Ti  1.3Ti  1.4Ti    48% 
複製代碼

kill

kill用於終止一個進程。通常咱們會先用ps -ef查找某個進程獲得它的進程號,而後再使用kill -9 進程號終止該進程。你還可使用killall、pkill、xkill來終止進程

$ ps -ef | grep vim ramesh 7243 7222 9 22:43 pts/2 00:00:00 vim

$ kill -9 7243

mount

若是要掛載一個文件系統,須要先建立一個目錄,而後將這個文件系統掛載到這個目錄上

mkdir /u01 mount /dev/sdb1 /u01 也能夠把它添加到fstab中進行自動掛載,這樣任什麼時候候系統重啓的時候,文件系統都會被加載

/dev/sdb1 /u01 ext2 defaults 0 2

chmod

chmod用於改變文件和目錄的權限

給指定文件的屬主和屬組全部權限(包括讀、寫、執行)

$ chmod ug+rwx file.txt 刪除指定文件的屬組的全部權限

$ chmod g-rwx file.txt 修改目錄的權限,以及遞歸修改目錄下面全部文件和子目錄的權限

$ chmod -R ug+rwx file.txt 更多示例:7 Chmod Command Examples for Beginners

chown

chown用於改變文件屬主和屬組

同時將某個文件的屬主改成oracle,屬組改成db

$ chown oracle:dba dbora.sh 使用-R選項對目錄和目錄下的文件進行遞歸修改

$ chown -R oracle:dba /home/oracle

ifconfig

ifconfig用於查看和配置Linux系統的網絡接口

uname

uname能夠顯示一些重要的系統信息,例如內核名稱、主機名、內核版本號、處理器類型之類的信息

實際場景問題

1 cpu佔用率

top能夠看
ps看不了
可是ps -aux能夠看到各個線程的cpu和內存佔用

2 進程狀態:

ps -ef看不了
ps aux能夠看進程狀態S R之類

3 IO
iostat查看io狀態

4網絡
netstat查看tcp鏈接狀態和socket狀況,

ipconfig查看網絡設備

lsof能夠查看端口使用狀況

5內存
free複製代碼
相關文章
相關標籤/搜索