close

http://blog.udn.com/udn2482/25468038

ulimit命令描述

ulimit用於shell啟動進程所占用的資源.

想象一個狀況:我們的Linux主機裏面同時登陸了十個人,這十個人同時打開了100個文件,每個文件的大小為10MB,請問一下我們的Linux主機內存要有多大才夠?10*100*10=10000MB=10GB,這樣,系統不掛掉才怪,為了預防這種情況的發生,所以我們的bash是可以限制用的某些系統資源的,包括可以打開的文件數量、可以使用的CPU時間、可以使用的內存總容量。如何設置?用ulimit吧!

ulimit 用於限制 shell 啟動進程所占用的資源,支持以下各種類型的限制:所創建的內核文件的大小、進程數據塊的大小、Shell 進程創建文件的大小、內存鎖住的大小、常駐內存集的大小、打開文件描述符的數量、分配堆棧的最大大小、CPU 時間、單個用戶的最大線程數、Shell 進程所能使用的最大虛擬內存。同時,它支持硬資源和軟資源的限制。

作為臨時限制,ulimit 可以作用於通過使用其命令登錄的 shell 會話,在會話終止時便結束限制,並不影響於其他 shell 會話。而對於長期的固定限制,ulimit 命令語句又可以被添加到由登錄 shell 讀取的文件中,作用於特定的 shell 用戶。

用戶進程的有效範圍

ulimit 作為對資源使用限制的一種工作,是有其作用範圍的。那麽,它限制的對象是單個用戶,單個進程,還是整個系統呢?事實上,ulimit 限制的是當前 shell 進程以及其派生的子進程。舉例來說,如果用戶同時運行了兩個 shell 終端進程,只在其中一個環境中執行了 ulimit – s 100,則該 shell 進程裏創建文件的大小收到相應的限制,而同時另一個 shell 終端包括其上運行的子程序都不會受其影響:

命令格式

ulimit [options] [limit]

參數

-H:hard limit,嚴格的設置,必定不能超過這個設置的數值

-S:sof limit,警告的設置,可以超過這個設置值,但是若超過則有警告信息。在設置上,通常soft會比hard小,舉例來說,soft可設置為80而hard設置為100,那麽可以使用到90(因為沒有超過100),但介於80~100之間時,系統會有警告信息通知您

-a:後面不接任何參數,可列出所有的限制額度

-c size:設置core文件的最大值.單位:blocks,當某些進程發生錯誤時,系統可能會將該進程在內存中的信息寫成文件(排錯用),這種文件就被稱為內核文件(core file)。次為限制每個內核文件的最大容量。

-f size:此shell可以創建的最大文件容量(一般可能設置為2GB)單位為KB

-d size: 設置數據段(segment)的最大值.單位:kbytes;

-l size: 設置在內存(lock)中鎖定進程的最大值.單位:kbytes;

-t size: 設置CPU使用時間的最大上限.單位:seconds

-n size: 設置內核可以同時打開的文件描述符的最大值.單位:n

-u size:單一用戶可以使用的最大進程(process)數量

-s size: 設置堆棧的最大值.單位:kbytes

-v size:設置虛擬內存的最大值.單位:kbytes

具體的 options 含義以及簡單示例可以參考以下表格。

選項 [options]    含義    例子

-H    設置硬資源限制,一旦設置不能增加。    ulimit – Hs 64;限制硬資源,線程棧大小為 64K。

-S    設置軟資源限制,設置後可以增加,但是不能超過硬資源設置。    ulimit – Sn 32;限制軟資源,32 個文件描述符。

-a    顯示當前所有的 limit 信息。    ulimit – a;顯示當前所有的 limit 信息。

-c    最大的 core 文件的大小, 以 blocks 為單位。    ulimit – c unlimited; 對生成的 core 文件的大小不進行限制。

-d    進程最大的數據段的大小,以 Kbytes 為單位。    ulimit -d unlimited;對進程的數據段大小不進行限制。

-f    進程可以創建文件的最大值,以 blocks 為單位。    ulimit – f 2048;限制進程可以創建的最大文件大小為 2048 blocks。

-l    最大可加鎖內存大小,以 Kbytes 為單位。    ulimit – l 32;限制最大可加鎖內存大小為 32 Kbytes。

-m    最大內存大小,以 Kbytes 為單位。    ulimit – m unlimited;對最大內存不進行限制。

-n    可以打開最大文件描述符的數量。    ulimit – n 128;限制最大可以使用 128 個文件描述符。

-p    管道緩沖區的大小,以 Kbytes 為單位。    ulimit – p 512;限制管道緩沖區的大小為 512 Kbytes。

-s    線程棧大小,以 Kbytes 為單位。    ulimit – s 512;限制線程棧的大小為 512 Kbytes。

-t    最大的 CPU 占用時間,以秒為單位。    ulimit – t unlimited;對最大的 CPU 占用時間不進行限制。

-u    用戶最大可用的進程數。    ulimit – u 64;限制用戶最多可以使用 64 個進程。

-v    進程最大可用的虛擬內存,以 Kbytes 為單位。    ulimit – v 200000;限制最大可用的虛擬內存為 200000 Kbytes。

1、-a參數,下面是root用戶的ulimit默認輸出

[root@awake ~]# ulimit -a

core file size       (blocks, -c)    0 //0為關閉即不生產core文件,linux下默認是不產生core文件的,要用ulimit -c unlimited開啟,並不限制文件大小,設置運行時產生調試信息。

data seg size        (kbytes, -d)    unlimited //啥是數據段?總之這裏開啟了,並且無限制。

scheduling priority  (-e)            0         //啥是調度優先級?

file size            (blocks, -f)    unlimited //可創建的單一文件的大小

pending signals      (-i)            7795      //啥是等待信號?

max locked memory    (kbytes, -l)    64        //最大可加鎖內存大小,以Kbytes為單位,應該是這個用戶也就是root的最大獨享內存?

max memory size      (kbytes, -m)    unlimited //最大內存大小,無限制(系統有多少就用多少嗎?)

open files           (-n)            1024      //同時可打開的文件數量

pipe size            (512 bytes, -p) 8         //管道緩存區大小,不知是幹什麽的

POSIX message queues (bytes, -q)     819200    //POSIX消息隊列

real-time priority   (-r)            0         //實時優先級,不知

stack size           (kbytes, -s)    10240     //線程堆棧大小,10MB

cpu time             (seconds, -t)   unlimited //占用cpu的時間,無限制

max user processes   (-u)            7795      //用戶最大可用的進程數,最多可以使用7795個

virtual memory       (kbytes, -v)    unlimited //虛擬內存

file locks           (-x)            unlimited //文件鎖,

2、block概念

其實本來這幾個概念不是非常難,主要是NND他們的名字都相同,都叫“Block Size”。

a、硬盤上的 block size, 應該是"sector size",linux的扇區大小是512byte

b、有文件系統的分區的block size, 是"block size",大小不一,能用tune2fs工具查看,單一文件系統能夠支持的單一文件大小與block的大小有關,例如block size為1024byte時,單一文件可達16GB,如果block size為4096byte時,單一文件可達2TB。

[root@RHEL6 ~]# tune2fs -l /dev/sda3 | grep "Block size"

Block size:               4096

c、沒有文件系統的分區的block size,也叫“block size”,大小指的是1024 byte

e、Kernel buffer cache 的block size, 就是"block size",大部分PC是1024

f、磁盤分區的"cylinder size",用fdisk 能查看。

3、開啟或關閉core文件的生成

ulimit -c 可以查看是否打開此選項,若為0則為關閉;其他參數值也是如此查看

ulimit -c 0可手動關閉

ulimit -c 1000 為設置core文件大小最大為1000k

ulimit -c unlimited 設置core文件大小為不限制大小

4、實例限制用戶僅能創建10MB以下額容量文件

[root@awake ~]# ulimit -f 10240                          //設置用戶可以創建的文件最大值block=10240k即為10M

[root@RHEL6 ~]# ulimit -a | grep "^file size"            //查看

file size (blocks, -f) 10240

[root@awake ~]# dd if=/dev/zero of=desfile bs=1M count=20 //使用dd在當前目錄下創建一個名為desfile大小為20M的文件。

File size limit exceeded

5、我們可以通過以下幾種方式來使用 ulimit:

在用戶的啟動腳本中

如果用戶使用的是 bash,就可以在用戶的目錄下的 .bashrc 文件中,加入 ulimit – u 64,來限制用戶最多可以使用 64 個進程。此外,可以在與 .bashrc 功能相當的啟動腳本中加入 ulimt。

在應用程序的啟動腳本中

如果用戶要對某個應用程序 myapp 進行限制,可以寫一個簡單的腳本 startmyapp。

ulimit – s 512

myapp

以後只要通過腳本 startmyapp 來啟動應用程序,就可以限制應用程序 myapp 的線程棧大小為 512K。

直接在控制臺輸入

user@tc511-ui:~>ulimit – p 256

限制管道的緩沖區為 256K。

6、用戶進程的有效範圍

ulimit 作為對資源使用限制的一種工作,是有其作用範圍的。那麽,它限制的對象是單個用戶,單個進程,還是整個系統呢?事實上,ulimit 限制的是當前 shell 進程以及其派生的子進程。舉例來說,如果用戶同時運行了兩個 shell 終端進程,只在其中一個環境中執行了 ulimit – s 100,則該 shell 進程裏創建文件的大小收到相應的限制,而同時另一個 shell 終端包括其上運行的子程序都不會受其影響:

Shell 進程 1

ulimit – s 100

cat testFile > newFile

File size limit exceeded

Shell 進程 2

cat testFile > newFile

ls – s newFile

323669 newFile

那麽,是否有針對某個具體用戶的資源加以限制的方法呢?答案是有的,方法是通過修改系統的 /etc/security/limits (RHEL6.4的文件位置是/etc/security/limit.conf)配置文件。該文件不僅能限制指定用戶的資源使用,還能限制指定組的資源使用。該文件的每一行都是對限定的一個描述,格式如下:

domain 表示用戶或者組的名字,還可以使用 * 作為通配符。Type 可以有兩個值,soft 和 hard。Item 則表示需要限定的資源,可以有很多候選值,如 stack,cpu,nofile 等等,分別表示最大的堆棧大小,占用的 cpu 時間,以及打開的文件數。通過添加對應的一行描述,則可以產生相應的限制。例如:

* hard noflle 100

該行配置語句限定了任意用戶所能創建的最大文件數是 100。

現在已經可以對進程和用戶分別做資源限制了,看似已經足夠了,其實不然。很多應用需要對整個系統的資源使用做一個總的限制,這時候我們需要修改 /proc 下的配置文件。/proc 目錄下包含了很多系統當前狀態的參數,例如 /proc/sys/kernel/pid_max,/proc/sys/net/ipv4/ip_local_port_range 等等,從文件的名字大致可以猜出所限制的資源種類。由於該目錄下涉及的文件眾多,在此不一一介紹。有興趣的讀者可打開其中的相關文件查閱說明。

回頁首

7、ulimit 管理系統資源的例子

ulimit 提供了在 shell 進程中限制系統資源的功能。本章列舉了一些使用 ulimit 對用戶進程進行限制的例子,詳述了這些限制行為以及對應的影響,以此來說明 ulimit 如何對系統資源進行限制,從而達到調節系統性能的功能。

7.1使用 ulimit 限制 shell 的內存使用

在這一小節裏向讀者展示如何使用 – d,– m 和 – v 選項來對 shell 所使用的內存進行限制。

首先我們來看一下不設置 ulimit 限制時調用 ls 命令的情況:

未設置 ulimit 時 ls 命令使用情況

大家可以看到此時的 ls 命令運行正常。下面設置 ulimit:

>ulimit -d 1000 -m 1000 -v 1000

這裏再溫習一下前面章節裏介紹過的這三個選項的含義:

-d:設置數據段的最大值。單位:KB。

-m:設置可以使用的常駐內存的最大值。單位:KB。

-v:設置虛擬內存的最大值。單位:KB。

通過上面的 ulimit 設置我們已經把當前 shell 所能使用的最大內存限制在 1000KB 以下。接下來我們看看這時運行 ls 命令會得到什麽樣的結果:

haohe@sles10-hehao:~/code/ulimit> ls test -l

/bin/ls: error while loading shared libraries: libc.so.6: failed to map segment

from shared object: Cannot allocate memory

從上面的結果可以看到,此時 ls 運行失敗。根據系統給出的錯誤信息我們可以看出是由於調用 libc 庫時內存分配失敗而導致的 ls 出錯。那麽我們來看一下這個 libc 庫文件到底有多大:

查看 libc 文件大小

從上面的信息可以看出,這個 libc 庫文件的大小是 1.5MB。而我們用 ulimit 所設置的內存使用上限是 1000KB,小於 1.5MB,這也就充分證明了 ulimit 所起到的限制 shell 內存使用的功能。

7.2使用 ulimit 限制 shell 創建的文件的大小

接下來向讀者展示如何使用 -f 選項來對 shell 所能創建的文件大小進行限制。

首先我們來看一下,沒有設置 ulimit -f 時的情況:

查看文件

現有一個文件 testFile 大小為 323669 bytes,現在使用 cat 命令來創建一個 testFile 的 copy:

未設置 ulimit 時創建復本

從上面的輸出可以看出,我們成功的創建了 testFile 的拷貝 newFile。

下面我們設置 ulimt – f 100:

> ulimit -f 100

-f 選項的含義是:用來設置 shell 可以創建的文件的最大值。單位是 blocks。

現在我們再來執行一次相同的拷貝命令看看會是什麽結果:

設置 ulimit 時創建復本

這次創建 testFile 的拷貝失敗了,系統給出的出錯信息時文件大小超出了限制。在 Linux 系統下一個 block 的默認大小是 512 bytes。所以上面的 ulimit 的含義就是限制 shell 所能創建的文件最大值為 512 x 100 = 51200 bytes,小於 323669 bytes,所以創建文件失敗,符合我們的期望。這個例子說明了如何使用 ulimit 來控制 shell 所能創建的最大文件。

7.3使用 ulimit 限制程序所能創建的 socket 數量

考慮一個現實中的實際需求。對於一個 C/S 模型中的 server 程序來說,它會為多個 client 程序請求創建多個 socket 端口給與響應。如果恰好有大量的 client 同時向 server 發出請求,那麽此時 server 就會需要創建大量的 socket 連接。但在一個系統當中,往往需要限制單個 server 程序所能使用的最大 socket 數,以供其他的 server 程序所使用。那麽我們如何來做到這一點呢?答案是我們可以通過 ulimit 來實現!細心的讀者可能會發現,通過前面章節的介紹似乎沒有限制 socket 使用的 ulimit 選項。是的,ulimit 並沒有哪個選項直接說是用來限制 socket 的數量的。但是,我們有 -n 這個選項,它是用於限制一個進程所能打開的文件描述符的最大值。在 Linux 下一切資源皆文件,普通文件是文件,磁盤打印機是文件,socket 當然也是文件。在 Linux 下創建一個新的 socket 連接,實際上就是創建一個新的文件描述符。如下圖所示(查看某個進程當前打開的文件描述符信息):

查看進程打開文件描述符

因此,我們可以通過使用 ulimit – n 來限制程序所能打開的最大文件描述符數量,從而達到限制 socket 創建的數量。

7.4使用 ulimit 限制 shell 多線程程序堆棧的大小(增加可用線程數量)

在最後一個例子中,向大家介紹如何使用 -s(單位 KB)來對線程的堆棧大小進行限制,從而減少整個多線程程序的內存使用,增加可用線程的數量。這個例子取自於一個真實的案例。我們所遇到的問題是系統對我們的多線程程序有如下的限制:

ulimit -v 200000

根據本文前面的介紹,這意味著我們的程序最多只能使用不到 200MB 的虛擬內存。由於我們的程序是一個多線程程序,程序在運行時會根據需要創建新的線程,這勢必會增加總的內存需求量。一開始我們對堆棧大小的限制是 1024 (本例子中使用 1232 來說明):

# ulimit – s 1232

當我們的程序啟動後,通過 pmap 來查看其內存使用情況,可以看到多個占用 1232KB 的數據段,這些就是程序所創建的線程所使用的堆棧:

程序線程所使用的堆棧

每當一個新的線程被創建時都需要新分配一段大小為 1232KB 的內存空間,而我們總的虛擬內存限制是 200MB,所以如果我們需要創建更多的線程,那麽一個可以改進的方法就是減少每個線程的固定堆棧大小,這可以通過 ulimit – s 來實現:

# ulimit -s 512

我們將堆棧大小設置為 512KB,這時再通過 pmap 查看一下我們的設置是否起作用:

設置 ulimit 後堆棧大小

從上面的信息可以看出,我們已經成功的將線程的堆棧大小改為 512KB 了,這樣在總內存使用限制不變的情況下,我們可以通過本小節介紹的方法來增加可以創建的線程數,從而達到改善程序的多線程性能。

想要復原ulimit的設置最簡單的方法就是註銷再登錄,否則就是要重新以ulimit設置才行,不過要註意的是一般身份用戶如果以ulimit設置了-f的文件大小,那麽他只能繼續減小文件容量,不能增加文件容量。

arrow
arrow
    全站熱搜

    主要步驟 發表在 痞客邦 留言(0) 人氣()