Chinaunix首页 | 论坛 | 博客
  • 博客访问: 94337
  • 博文数量: 21
  • 博客积分: 568
  • 博客等级: 中士
  • 技术积分: 175
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-31 10:29
文章分类
文章存档

2014年(1)

2012年(6)

2011年(14)

我的朋友

分类: LINUX

2011-02-17 15:23:56

與檔案系統及程序的限制關係: ulimit | alias unalias ;history
2008/12/08 11:11

與檔案系統及程序的限制關係: ulimit

想像一個狀況:我的 Linux 主機裡面同時登入了十個人,這十個人不知怎麼搞的, 同時開啟了 100 個檔案,每個檔案的大小約 10MBytes ,請問一下, 我的 Linux 主機的記憶體要有多大才夠? 10*100*10 = 10000 MBytes ~~ 老天爺,這樣,系統不掛點才有鬼哩!為了要預防這個情況的發生,所以, 我們的 bash 是可以『限制使用者的某些系統資源』的,包括可以開啟的檔案數量, 可以使用的 CPU 時間,可以使用的記憶體總量等等。如何設定?用 ulimit 吧!
[root@linux ~]# ulimit [-SHacdflmnpstuv] [配額] 參數: -H :hard limit ,嚴格的設定,必定不能超過設定的值; -S :soft limit ,警告的設定,可以超過這個設定值,但是會有警告訊息, 並且,還是無法超過 hard limit 的喔!也就是說,假設我的 soft limit 為 80 , hard limit 為 100 ,那麼我的某個資源可以用到 90 , 可以超過 80 ,還是無法超過 100 ,而且在 80~90 之間,會有警告訊息的意思。 -a :列出所有的限制額度; -c :可建立的最大核心檔案容量 (core files) -d :程序資料可使用的最大容量 -f :此 shell 可以建立的最大檔案容量 (一般可能設定為 2GB)單位為 Kbytes -l :可用於鎖定 (lock) 的記憶體量 -p :可用以管線處理 (pipe) 的數量 -t :可使用的最大 CPU 時間 (單位為秒) -u :單一使用者可以使用的最大程序(process)數量。 範例: 範例一:列出所有的限制資料 [root@linux ~]# ulimit -a 範例二:限制使用者僅能建立 1MBytes 以下的容量的檔案 [root@linux ~]# ulimit -f 1024
還記得我們在 Linux 磁碟檔案系統 裡面提到過,單一 filesystem 能夠支援的單一檔案大小與 block 的大小有關。例如 block size 為 1024 byte 時,單一檔案可達 16GB 的容量。但是,我們可以用 ulimit 來限制使用者可以建立的檔案大小喔! 利用 ulimit -f 就可以來設定了!例如上面的範例二,要注意單位喔!單位是 Kbytes。 若改天你一直無法建立一個大容量的檔案,記得瞧一瞧 ulimit 的資訊喔!( 不過,要注意的是,一般身份使用者如果以 ulimit 設定了 -f 的檔案大小, 那麼他『只能減小檔案大小,不能增加檔案大小喔!』)

小標題的圖示額外的變數設定功能

剛剛我們提到了兩種變數取用的方法,分別是這樣:
[root@linux ~]# echo $HOME [root@linux ~]# echo ${HOME}
那麼,在那個 ${variable} 的使用方法中,其實,我們還可以將變數進行一些修訂的工作喔! 只要加上一些字符標誌,後面再接著使用比對字串,就能夠修改變數的內容了! 我們取底下的例子來說明:在底下的例子中,假設我的變數名稱為 vbird ,且內容為 /home/vbird/testing/testing.x.sh。
1. 完整呈現 vbird 這個變數的內容; [root@linux ~]# vbird="/home/vbird/testing/testing.x.sh" [root@linux ~]# echo ${vbird} /home/vbird/testing/testing.x.sh 2. 在 vbird 變數中,從最前面開始比對,若開頭為 / ,則刪除兩個 / 之間的所有資料,亦即 /*/ [root@linux ~]# echo ${vbird##/*/} testing.x.sh <==刪除了 /home/vbird/testing/ [root@linux ~]# echo ${vbird#/*/} vbird/testing/testing.x.sh <==僅刪除 /home/ 而已 # 這兩個小例子有趣了~變數名稱後面如果接了兩個 ## ,表示在 ## # 後面的字串取『最長的』那一段;如果僅有一個 # ,表示取『最小的那一段』喔! 3. 承上題,如果是從後面開始,刪除 /* 呢? [root@linux ~]# echo ${vbird%%/*/} /home/vbird/testing/testing.x.sh <==都沒被刪除 [root@linux ~]# echo ${vbird%%/*} <==被刪除光了! [root@linux ~]# echo ${vbird%/*} /home/vbird/testing <==只刪除 /testing.x.sh 部分 # 這個例子當中需要特別注意,那個 % 比對的是『最後面那個字元』的意思, # 所以囉,第一個方式當然不對~因為 vbird 這個變數的內容最後面是 h 而不是 / 啊! # 至於 %%/* 則是刪除『最長的那個 /* 』,當然就是全部喔!而 %/* 則是最短的那個! 4. 將 vbird 變數中的 testing 取代為 TEST [root@linux ~]# echo ${vbird/testing/TEST} /home/vbird/TEST/testing.x.sh [root@linux ~]# echo ${vbird//testing/TEST} /home/vbird/TEST/TEST.x.sh # 如果變數後面接的是 / 時,那麼表示後面是進行『取代』的工作~而且僅取代『第一個』 # 但如果是 // ,則表示全部的字串都取代啊!
這裡您稍微留意一下就好了~反正就是變數後面可以接 #, ##, %, %%, /, // , 而他們存在的意義並不相同的啦~

另外,幾個不同的變數內容還可以進行判斷呢! 舉例來說,目前我需要用到兩個變數,分別是 var 與 str , 那我想要針對 str 這個變數內容是否有設定成一個字串,亦即 "expr" 來決定 var 的內容。 那我可以使用什麼方法來進行判斷呢?如果您會寫 shell script 的話, 直接用 shell script 就好了,如果不會寫,那麼我們就透過簡單的變數判斷吧!
Tips:
底下的例子當中,那個 var 與 str 為變數,我們想要針對 str 是否有設定來決定 var 的值喔! 一般來說, str: 代表『str 沒設定或為空的字串時』;至於 str 則僅為『沒有該變數』。
變數設定方式 str 沒有設定 str 為空字串 str 已設定非為空字串
var=${str-expr} var=expr var= var=$str
var=${str:-expr} var=expr var=expr var=$str
var=${str+expr} var= var=expr var=expr
var=${str:+expr} var= var= var=expr
var=${str=expr} str=expr
var=expr
str 不變
var=
str 不變
var=$str
var=${str:=expr} str=expr
var=expr
str=expr
var=expr
str 不變
var=$str
var=${str?expr} expr 輸出至 stderr var= var=str
var=${str:?expr} expr 輸出至 stderr expr 輸出至 stderr var=str

根據上面這張表,我們來進行幾個範例的練習吧! ^_^
範例一:若 str 這個變數內容存在,則 var 設定為 str ,否則 var 設定為 "newvar" [root@linux ~]# unset str; var=${str-newvar} [root@linux ~]# echo var="$var", str="$str" var=newvar, str= <==因為 str 不存在,所以 var 為 newvar [root@linux ~]# str="oldvar"; var=${str-newvar} [root@linux ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==因為 str 存在,所以 var 等於 str 的內容 範例二:若 str 不存在,則 var 與 str 均設定為 newvar,否則 var 與 str 相同 [root@linux ~]# unset str; var=${str=newvar} [root@linux ~]# echo var="$var", str="$str" var=newvar, str=newvar <==因為 str 不存在,所以 var/str 均為 newvar [root@linux ~]# str="oldvar"; var=${str=newvar} [root@linux ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==因為 str 存在,所以 var 等於 str 的內容 範例三:若 str 這個變數存在,則 var 等於 str ,否則輸出 "novar" [root@linux ~]# unset str; var=${str?novar} -bash: str: novar <==因為 str 不存在,所以輸出錯誤訊息 [root@linux ~]# str="oldvar"; var=${str?novar} [root@linux ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==因為 str 存在,所以 var 等於 str 的內容 # 上面這三個案例都沒有提到當 str 有設定,且為空字串的情況喔! # 您可以自行測試一下哩!

雖然猛一看,覺得變數沒有什麼奇特的地方,但是,如果仔細瞧一瞧,嘿!一堆環境變數與系統資源方面的變數, 可是會影響到我們在 bash 裡頭是否能夠順利作業的呢!例如 PATH 啊、ulimit 之類的~ 所以,您還是得要瞭解變數這個玩意才行喔! ^_^

命令別名與歷史命令:

我們知道在早期的 DOS 年代,清除螢幕上的資訊可以使用 cls 來清除,但是在 Linux 裡面, 我們則是使用 clear 來清除畫面的。那麼可否讓 cls 等於 clear 呢?可以啊!用啥方法? link file 還是什麼的?別急!底下我們介紹不用 link file 的命令別名來達成。那麼什麼又是歷史命令? 曾經做過的舉動我們可以將他記錄下來喔!那就是歷史命令囉~底下分別來談一談這兩個玩意兒。

小標題的圖示命令別名設定: alias, unalias
命令別名是一個很有趣的東西,特別是你的慣用指令特別長的時候!還有, 增設預設的屬性在一些慣用的指令上面,可以預防一些不小心誤殺檔案的情況發生的時候! 舉個例子來說,如果你要查詢隱藏檔,並且需要長的列出與一頁一頁翻看,那麼需要下達『 ls -al | more 』這個指令,我是覺得很煩啦! 要輸入好幾個單字!那可不可以使用 lm 來簡化呢?!當然可以,你可以在命令列下面下達:
[root@linux ~]# alias lm='ls -l | more'
嘿嘿!我立刻多出了一個可以執行的指令喔!這個指令名稱為 lm ,且其實他是執行 ls -al | more 啊!真是方便。不過, 要注意的是:『alias 的定義規則與變數定義規則幾乎相同』, 所以你只要在 alias 後面加上你的 {『別名』='指令 參數' }, 以後你只要輸入 lm 就相當於輸入了 ls -al|more 這一串指令!很方便吧!

另外,命令別名的設定還可以取代既有的指令喔!舉例來說,我們知道 root 可以移除( rm )任何資料!所以當你以 root 的身份在進行工作時,需要特別小心, 但是總有失手的時候,那麼 rm 提供了一個參數來讓我們確認是否要移除該檔案,那就是 -i 這個參數!所以,你可以這樣做:
[root@linux ~]# alias rm='rm -i'
嘿嘿!那麼以後使用 rm 的時候,就不用太擔心會有錯誤刪除的情況了!這也是命令別名的優點囉! 那麼如何知道目前有哪些的命令別名呢?就使用 alias 呀!
[root@linux ~]# alias alias l.='ls -d .* --color=tty' alias ll='ls -l --color=tty' alias lm='ls -al | more' alias ls='ls --color=tty' alias vi='vim' alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
由上面的資料當中,您也會發現一件事情啊,我們在 vi 文書編輯器 裡面提到 vi 與 vim 是不太一樣的, vi 是比較老,而 vim 可以用來取代 vi 喔。我們的 FC4 明明就同時有 vi/vim , 為何我執行 vi 會是進入 vim 呢?呵呵!那就是因為上面的表格當中的『 alias vi='vim' 』這個設定啦! 至於如果要取消命令別名的話,那麼就使用 unalias 吧!例如要將剛剛的 lm 命令別名拿掉,就使用:
[root@linux ~]# unalias lm
那麼命令別名與變數有什麼不同呢?基本上,他們的意義就不太一樣了! alias 這種命令別名,你可以將他想成是建立一個新的指令名稱, 至於變數則僅是將一個數值或者字串存在某個代表意義當中!舉個例子好了,我們知道以前的 DOS 年代,列出目錄與檔案就是 dir ,而清除螢幕就是 cls ,那麼如果我想要在 linux 裡面也使用相同的指令呢?那就以 alias 來進行指令的別名設定:
    alias cls='clear'
    alias dir='ls -l'
      只要加入這兩行,以後你輸入 cls 及 dir 就可以執行了!很方便吧!
    歷史命令:history
    前面我們提過 bash 有提供指令歷史的服務!那麼如何查詢我們曾經下達過的指令呢?就使用 history 囉!當然,如果覺得 histsory 要輸入的字元太多太麻煩,可以使用命令別名來設定呢! 不要跟我說還不會設定呦! ^_^
      alias h='history'
    如此則輸入 h 等於輸入 history 囉!好了,我們來談一談 history 的用法吧!
    [root@linux ~]# history [n] [root@linux ~]# history [-c] [root@linux ~]# history [-raw] histfiles 參數: n :數字,意思是『要列出最近的 n 筆命令列表』的意思! -c :將目前的 shell 中的所有 history 內容全部消除 -a :將目前新增的 history 指令新增入 histfiles 中,若沒有加 histfiles , 則預設寫入 ~/.bash_history -r :將 histfiles 的內容讀到目前這個 shell 的 history 記憶中; -w :將目前的 history 記憶內容寫入 histfiles 中! 範例: 範例一:列出目前記憶體內的所有 history 記憶 [root@linux ~]# history # 前面省略 1017 man bash 1018 ll 1019 history 1020 history # 列出的資訊當中,共分兩欄,第一欄為該指令在這個 shell 當中的代碼, # 另一個則是指令本身的內容喔!至於會秀出幾筆指令記錄,則與 HISTSIZE 有關! 範例二:列出目前最近的 3 筆資料 [root@linux ~]# history 3 1019 history 1020 history 1021 history 3 範例三:立刻將目前的資料寫入 histfile 當中 [root@linux ~]# history -w # 在預設的情況下,會將歷史紀錄寫入 ~/.bash_history 當中! [root@linux ~]# echo $HISTSIZE 1000
    在正常的情況下,當我們以 bash 登入 Linux 主機之後,系統會主動的由家目錄的 ~/.bash_history 讀取以前曾經下過的指令,那麼 ~/.bash_history 會記錄幾筆資料呢?這就與你 bash 的 HISTSIZE 這個變數設定值有關了!在預設的 FC4 底下,是會記錄 1000 筆資料的! 那麼假設我這次登入主機後,共下達過 100 次指令,『等我登出時, 系統就會將 101~1100 這總共 1000 筆歷史命令更新到 ~/.bash_history 當中。』 也就是說,歷史命令在我登出時,會將最近的 HISTSIZE 筆記錄到我的紀錄檔當中啦! 當然,也可以用 history -w 強制立刻寫入的!那為何用『更新』兩個字呢? 因為 ~/.bash_history 記錄的筆數永遠都是 HISTSIZE 那麼多,舊的訊息會被主動的拿掉! 僅保留最新的!

    那麼 history 這個歷史命令只可以讓我查詢命令而已嗎?呵呵!當然不止啊! 我們可以利用相關的功能來幫我們執行命令呢!舉例來說囉:
    [root@linux ~]# !number [root@linux ~]# !command [root@linux ~]# !! 參數: number :執行第幾筆指令的意思; command :由最近的指令向前搜尋『指令串開頭為 command』的那個指令,並執行; !! :就是執行上一個指令(相當於按↑按鍵後,按 Enter) 範例: [root@linux ~]# history 66 man rm 67 alias 68 man history 69 history [root@linux ~]# !66 <==執行第 66 筆指令 [root@linux ~]# !! <==執行上一個指令,本例中亦即 !66 [root@linux ~]# !al <==執行最近以 al 為開頭的指令(上頭列出的第 67 個)
    經過上面的介紹,瞭乎?歷史命令用法可多了!如果我想要執行上一個指令, 除了使用上下鍵之外,我可以直接以『 !! 』 來下達上個指令的內容,此外, 我也可以直接選擇下達第 n 個指令,『 !n 』來執行,也可以使用指令標頭,例如 『 !vi 』來執行最近指令開頭是 vi 的指令列!相當的方便而好用!基本上 history 的用途很大的!但是需要小心安全的問題!尤其是 root 的歷史紀錄檔案,這是 Cracker 的最愛!因為不小心的 root 會將很多的重要資料在執行的過程中會被紀錄在 ~/.bash_history 當中,如果這個檔案被解析的話,後果不堪吶!無論如何,使用 history 配合『 ! 』曾經使用過的指令下達是很有效率的一個指令方法!
阅读(724) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~