歡迎您光臨本站 註冊首頁

bash shell筆記5 顯示數據

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

知識體系:
#回顧重定向
#標準輸入和輸出
#報告錯誤
#丟棄數據
#創建日誌文件
這裡主要講述如何將腳本重定向到linux系統的各個位置.

1、了解輸入和輸出
我們知道顯示腳本輸出的方法有兩種:
*在監視器屏幕上顯示
*將輸出重定向到文件
下面主要講述如何使用標準的linux輸入和輸出體系滿足將腳本輸出定向到特定位置的需求.
1.1、標準文件描述符
linux使用文件描述符來標識每個文件對象,每個進程最多有9個可以打開文件的描述符(且非零),bash shell為特殊需要保留了前三個文件描述符(0、1、2),如下所示:
**************************************
文件描述符 縮寫 描述
0 STDIN 標準輸入
1 STDOUT 標準輸出
2 STDERR 標準錯誤
**************************************
shell使用他們將shell中的默認輸入輸出重定向到相應的位置,默認就是監視器屏幕了.
下面簡單講述下這三個保留的文件描述符:
1》STDIN
STDIN文件描述符引用shell的標準輸入,對於終端介面的標準輸入就是鍵盤了.當然,我們可以使用輸入重定向符號(<)也可以使其讀取文件中的數據,跟鍵盤輸入時一樣的道理.先來看個例子:
[root@wzp ~]# cat
i am twentyfour , who are you ?
i am twentyfour , who are you ?
我直接輸入cat后回車,結果我輸入什麼內容,系統就顯示一樣的內容.
這就是cat命令通過STDIN輸入數據的示例.
[root@wzp ~]# vim testfile


[root@wzp ~]# cat < testfile
aaaaaaaaaaaa
bbbbbbbbbbbb
cccccccccccc
現在cat命令使用包含在testfile文件的中行作為輸入,也是標準輸入.
2》STDOUT
STDOUT文件描述符引用shell的標準輸出,在終端介面的標準輸出就是終端監視器.我們可以使用輸出重定向(>)或者追加(>>)向文件添加數據.對於這個都是很好理解的,看個例子:
[root@wzp ~]# ls > 51cto.test
[root@wzp ~]# cat 51cto.test
51cto.test
anaconda-ks.cfg
Desktop
install.log
install.log.syslog
linux-linkto-mysql
login-mysql
mbox
sendto-mysql
如上把定向到監視器的內容重定向到文件中.
3》STDERR
STDERR文件描述符處理錯誤消息,默認情況下將所有錯誤消息顯示在監視器上,具體應用下來講述.
1.2、重定向錯誤
重定向STDERR數據的時候只要定義好STDERR文件描述符即可,這裡頭分兩種情況的數據重定向.
(1)先來第一種:僅重定向錯誤消息
我們已經知道ETDERR文件描述符值為2,在重定向符號前附加2即可把錯誤消息重定向到具體的位置去,看個例子:
[root@wzp ~]# ll 51cto 2> errfile
[root@wzp ~]# cat errfile
ls: 51cto: 沒有那個文件或目錄
就是說明知道不存在51cto,然後去ll后把錯誤消息重定向到errfile中,而不是默認的顯示在顯示器上.下面的例子也如此:
[root@wzp ~]# ll 51cto.test 51cto 2>> errfile
-rw-r--r-- 1 root root 115 02-14 17:02 51cto.test
[root@wzp ~]# cat errfile
ls: 51cto: 沒有那個文件或目錄
ls: 51cto: 沒有那個文件或目錄

從結果都可以看出存在的文件顯示在屏幕上,而不存在的文件的報錯消息被追加到errfile文件中.
(2)還有一種是:重定向錯誤和數據
既然要分開處理錯誤消息和正確的數據顯示,我們就可以通過1>符號進行標準輸出重定向,和2>進行錯誤消息重定向,看個例子就明白了:
[root@wzp ~]# ls -al 51cto.test install.log linux rhca 1> exist 2> error
[root@wzp ~]# cat exist
-rw-r--r-- 1 root root 115 02-14 17:02 51cto.test
-rw-r--r-- 1 root root 27682 12-12 18:06 install.log
[root@wzp ~]# cat error
ls: linux: 沒有那個文件或目錄
ls: rhca: 沒有那個文件或目錄
存在的文件重定向到exist文件中,不存在的文件把報錯信息重定向到error中,這就是靈活使用1>和2>符號的效果.
當然,假如你想把正確輸出的錯誤輸出都重定向到一個文件的時候可以使用特殊的重定向符號:&> 先來看個例子:
[root@wzp ~]# ls -al 51cto.test install.log linux rhca &> totalfile
[root@wzp ~]# cat totalfile
ls: linux: 沒有那個文件或目錄
ls: rhca: 沒有那個文件或目錄
-rw-r--r-- 1 root root 115 02-14 17:02 51cto.test
-rw-r--r-- 1 root root 27682 12-12 18:06 install.log
我們看到totalfile包含的所有信息,並且是按照順序排列兩類信息.

2、在腳本中重定向輸出
使用腳本重定向輸出的方法有兩種:
*臨時重定向每一行
*在腳本中永久性重定向所有命令
2.1、臨時重定向
我們可以通過在文件描述符前加&符號來把一些輸入重定向到文件描述符中,然後在重定向輸入的時候調用這些文件描述符,也行聽起來覺得怪怪的不好理解,OK,先來看個例子:


[root@wzp ~]# chmod u x 5.2test
[root@wzp ~]# cat 5.2test
#!/bin/bash
echo "this is a error" >&2
echo "this is normal output"
[root@wzp ~]# ./5.2test
this is a error
this is normal output
這個腳本執行后沒什麼不同之處,但"this is a error" >&2已經是把這個"this is a error"消息重定向給STDERR文件描述符了.
[root@wzp ~]# ./5.2test 2> errorfile
this is normal output
[root@wzp ~]# cat errorfile
this is a error
如上就表示把STDERR文件描述符的消息"this is a error"重定向給errorfile文件.所以我們知道,這裡頭的動作有兩個重定向!
2.2、永久重定向
如果在腳本中要重定向許多數據,可以通過exec命令通知shell在腳本執行中重定向特定的文件描述符,先看如下例子:
[root@wzp ~]# cat 5.2test
#!/bin/bash
exec 1>testfile
echo "welcome to CHINA"
date
[root@wzp ~]# ./5.2test
[root@wzp ~]# cat testfile
welcome to CHINA
2011年 02月 14日 星期一 19:15:25 CST
exec命令啟動一個新的shell,並且STDOUT文件描述符重定向到testfile.
當然還可以在腳本中重定向到STDOUT,看如下例子:
[root@wzp ~]# cat 5.2test
#!/bin/bash
exec 2>testfile1
echo "aaaaaaaaa"
exec 1>testfile2
echo "bbbbbbbbb"
echo "ccccccccc" >&2
[root@wzp ~]# ./5.2test
aaaaaaaaa
[root@wzp ~]# cat testfile1
ccccccccc
[root@wzp ~]# cat testfile2
bbbbbbbbb
腳本內容是從上往下執行每個命令的,所以在STDERR后的echo aa的內容勢必顯示在顯示屏上.當定義了STDOUT后,bb的內容就被重定向到testfile2中.但是,雖然cc處於STDOUT之後,但是此行特意制定重定向到STDERR中,所以也就發生兩次重定向處於testfile1中.

3、在腳本中重定向輸入
重定向STDOUT和STDERR的技術也可以用來重定向鍵盤的STDIN,如
exec 0< testfile
該命令告訴shell應該從文件testfile而不是STDIN獲取輸入,如下例:
[root@wzp ~]# chmod u x 5.3test
[root@wzp ~]# cat 5.3test
#!/bin/bash
exec 0< testfile
count=1
while read line
do
echo "Line #$count: $line"
count=$[ $count 1 ]
done
[root@wzp ~]# cat testfile
5555555
1111111
CCCCCCC
TTTTTTT
OOOOOOO
[root@wzp ~]# ./5.3test
Line #1: 5555555
Line #2: 1111111
Line #3: CCCCCCC
Line #4: TTTTTTT
Line #5: OOOOOOO
如上表示把testfile中的每一行重定向到STDIN中,然後通過變數line把STDIN的內容逐行echo出來.

4、創建自己的重定向
一開始我就提及到shell中最多可以有9個打開的文件描述符,其他六個的編號是3~8,對於這6個文件描述符同樣可運用在較本中.
4.1、創建輸出文件描述符
直接來看一個例子,非常好理解:
[root@wzp ~]# chmod u x 5.4test
[root@wzp ~]# cat 5.4test
#!/bin/bash
exec 3> testfile
echo "aaaaaaa"
echo "bbbbbbb" >&3
[root@wzp ~]# ./5.4test
aaaaaaa
[root@wzp ~]# cat testfile
bbbbbbb
對於aa的正常顯示沒啥好說,而bb的內容被重定向給文件描述符3,然後文件描述符3再次重定向給文件testfile,所以可以預知testfile的內容.
4.2、重定向文件描述符
對於重定向文件描述符說起來挺複雜的,先看個例子解釋下:


[root@wzp ~]# cat 5.4test
#!/bin/bash
exec 3>&1
exec 1>testfile
echo "today is so cold"
exec 1>&3
echo "kobe bryant is great" >&3
[root@wzp ~]# ./5.4test
kobe bryant is great
[root@wzp ~]# cat testfile
today is so cold
第一次看如上的腳本,也許會頭暈的.呵呵,把文件描述符3重定向給STDOUT,而STDOUT重定向給文件testfile,接下來的echo標準輸出,所以對應上面的理念存到testfile中,先理解好這點!接下來就是STDOUT重定向給文件描述符3,而下面的echo重定向內容給文件描述符3,回頭看腳本exec 3>&1,很明顯把echo的內容重定向給etdout了,所以就顯示在屏幕上
4.3、創建輸入文件描述符
之所以要講述這個就是說當出現有文件重定向輸入文件描述符的時候,並且出現鍵盤輸入這樣的STDIN普通設置,我們可以通過先把默認的輸入文件描述符重定向給2~9這樣的文件描述符,等文件的內容被重定向結束后回過頭來把先前設置的2~9文件描述符重定向到默認的STDIN,恢復原狀.也許你對這段話看起來覺得費解,可以先理解下面的例子:
[root@wzp ~]# cat testfile
aaaaaaaaaaaa
bbbbbbbbbbbb
cccccccccccc
[root@wzp ~]# cat 5.4test
#!/bin/bash
exec 6<&0
exec 0< testfile
count=1
while read wzp
do
echo "Line #$count : $wzp"
count=$[ $count 1 ]
done
exec 0<&6
read -p "are you sure now ?"
case $REPLY in
Y | y) echo "OK , Goodbye";;
N | n) echo "Why ?";;
esac
[root@wzp ~]# ./5.4test
Line #1 : aaaaaaaaaaaa
Line #2 : bbbbbbbbbbbb


Line #3 : cccccccccccc
are you sure now ?y
OK , Goodbye
[root@wzp ~]# ./5.4test
Line #1 : aaaaaaaaaaaa
Line #2 : bbbbbbbbbbbb
Line #3 : cccccccccccc
are you sure now ?N
Why ?
如上要把testfile的內容重定向輸入,隨著while循環通過read命令讀取testfile每一行.等這個讀取的過程完成以後,把文件描述符6重定向為默認的STDIN,也就是文件描述符0,就可以通過鍵盤輸入了.並且借用read命令的-p選項做交互性問答.
4.4、關閉文件描述符
有時候想在腳本運行過程中關閉一些輸入輸出文件描述符,是的其失去存在意義,這個時候可以借用特殊符號 &-
exec 3>$- 這就表示文件描述符3在腳本中不能使用,先來看個例子:
[root@wzp ~]# cat 5.4test
#!/bin/bash
exec 8> testfile
echo "i will come back to school soon" >&8
exec 8>&-
echo "lalalalala" >&8
[root@wzp ~]# ./5.4test
./5.4test: line 5: 8: 錯誤的文件描述符
[root@wzp ~]# cat testfile
i will come back to school soon
把回校的消息重定向到&8,而&8重定向到testfile中,這點沒什麼質疑的.然後把&8關閉后,再次使用echo重定向給&8就報錯了,當然,testfile的內容肯定是有的,腳本即便報錯也是有運行結束.

5、列出開放文件描述符
可用的文件描述符有9個,所以有時候會出現很難跟蹤哪個文件描述符重定向到哪個位置的情況發生,這個時候就可以借用losf命令理清線索.
lsof輸出有很多參數和選項,常用的有-p,該參數可以指定進程ID;還有-d可以指定要顯示餓文件描述符編號.
為了輕鬆確定進程當前的PID,可以藉助特殊環境變數$$,而-a選擇則是用於連接其他兩個選項的結果,如下:


[root@wzp ~]# lsof -a -p $$ -d 0,1,2
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
bash 19302 root 0u CHR 136,0 2 /dev/pts/0
bash 19302 root 1u CHR 136,0 2 /dev/pts/0
bash 19302 root 2u CHR 136,0 2 /dev/pts/0
把0、1、2文件描述符的相關進程顯示出來.

6、禁止命令輸出
有時候一個腳本在後台運行出現了一些錯誤,shell就會通過mail通知進程的所有者,而這些錯誤卻是無關緊要的.這個時候就可以利用回收站來處理這些錯誤信息.這就是我經常使用的linux系統特有的/dev/null空設置文件,可謂無底洞,給他多少吃多少...
先來看看例子:
[root@wzp ~]# echo aaaaa > /dev/null
[root@wzp ~]# cat /dev/null
查看的時候一直為空,再來看個例子:
[root@wzp ~]# cat testfile
i will come back to school soon
[root@wzp ~]# cat /dev/null > testfile
[root@wzp ~]# cat testfile
利用上面原本存在數據的testfile文件,把空文件重定向到該文件中,結果testfile的內容都被吃光了,O(∩_∩)O哈哈~

7、使用臨時文件
linux系統有一個創建臨時文件的特殊命令mktemp,可以在臨時目錄/tmp創建一個唯一的臨時文件.不過,創建的臨時文件不使用默認的umask值,而是600許可權的文件.

7.1、創建本地臨時文件
mktemp可以在任一目錄創建臨時文件,並且只需指定一個文件模板名即可.模板包括文本文件名和文件名后6的大寫的X.如下:
[root@wzp ~]# mktemp 51cto.XXXXXX


51cto.Z26308
[root@wzp ~]# ll 51cto.Z26308
-rw------- 1 root root 0 02-14 23:05 51cto.Z26308
後面的Z26308是系統隨意創建的,並且具有唯一性
[root@wzp ~]# mktemp 51cto.XXXXXX
51cto.n26366
[root@wzp ~]# mktemp 51cto.XXXXXX
51cto.o26367
[root@wzp ~]# mktemp 51cto.XXXXXX
51cto.G26369
[root@wzp ~]# ll 51cto.*
-rw------- 1 root root 0 02-14 23:07 51cto.G26369
-rw------- 1 root root 0 02-14 23:07 51cto.n26366
-rw------- 1 root root 0 02-14 23:07 51cto.o26367
所以放心,決不出現一樣文件名的臨時文件
7.2、在/tmp中創建臨時文件
-t選項強迫mktemp在系統的/tmp目錄下創建文件,這是一個挺不錯的特性,直接看看例子:
[root@wzp ~]# mktemp -t wzp.XXXXXX
/tmp/wzp.I26701
[root@wzp ~]# ll /tmp/wzp.I26701
-rw------- 1 root root 0 02-14 23:16 /tmp/wzp.I26701
由於mktemp命令返回完整路徑名,因此可以從linux系統引用臨時文件,如下例子:
[root@wzp ~]# chmod u x 7.2test
[root@wzp ~]# cat 7.2test
#!/bin/bash
tempfile=`mktemp -t tmp.XXXXXX`
echo "this is a temp file" >$tempfile
[root@wzp ~]# ll /tmp/tmp.u26849
-rw------- 1 root root 20 02-14 23:21 /tmp/tmp.u26849
[root@wzp ~]# cat /tmp/tmp.u26849
this is a temp file
通過這種方式非常的方便,靈活調用系統目錄文件.
7.3、臨時創建目錄
mktemp不僅可以創建臨時文件,還可以借用-d選項創建臨時目錄,下例:
[root@wzp ~]# chmod u x 7.3test
[root@wzp ~]# ./7.3test
[root@wzp ~]# cat 7.3test
#!/bin/bash
tempdir=`mktemp -d dir.XXXXXX`
cd $tempdir
tempfile1=`mktemp temp.XXXXXX`


tempfile2=`mktemp temp.XXXXXX`
exec 7> $tempfile1
exec 8> $tempfile2
echo "this is 7" >&7
echo "this is 8" >&8
[root@wzp ~]# ll dir.A27050/
總計 16
-rw------- 1 root root 10 02-14 23:27 temp.f27052
-rw------- 1 root root 10 02-14 23:27 temp.p27051
[root@wzp ~]# cat dir.A27050/temp.f27052
this is 8
[root@wzp ~]# cat dir.A27050/temp.p27051
this is 7
通過創建臨時目錄后切換目錄創建臨時文件.

8、記錄消息
有時候需要將輸出同時發送到監視器和日誌文件中,這個時候不需要使用兩次重定向,只要使用特殊的tee命令即可.
比如看下簡單的操作:
[root@wzp ~]# date | tee testfile
2011年 02月 14日 星期一 23:31:05 CST
[root@wzp ~]# cat testfile
2011年 02月 14日 星期一 23:31:05 CST
由於tee重定向來自於STDIN的數據,因此配合管道命令就可以把輸出顯示在監視屏和指定的文件中.
如果希望對如上的testfile文件不斷增加這樣的數據,必須使用-a選項,先看看一個效果:
[root@wzp ~]# cal | tee testfile
二月 2011
日 一 二 三 四 五 六
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28

[root@wzp ~]# cat testfile
二月 2011
日 一 二 三 四 五 六
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28
你會發現date的內容沒了,也就好比是重定向完全覆蓋的概念,所以想追加內容到文件中就必須使用-a選項,例子:


[root@wzp ~]# date | tee -a testfile
2011年 02月 14日 星期一 23:35:10 CST
[root@wzp ~]# cat testfile
二月 2011
日 一 二 三 四 五 六
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28

2011年 02月 14日 星期一 23:35:10 CST
對於這樣的效果就比較好,可以把各個信息都歸檔到一個日誌文件中.


本文出自 「twenty_four」 博客,請務必保留此出處http://twentyfour.blog.51cto.com/945260/521455


[火星人 ] bash shell筆記5 顯示數據已經有640次圍觀

http://coctec.com/docs/linux/show-post-49171.html