文件描述符
#文件描述符來標(biāo)識(shí)每個(gè)文件對(duì)象蚓再,唯一的標(biāo)識(shí)會(huì)話中打開的文件
#0 stdin 1 stdout 2 stderr
#使用<時(shí),Linux會(huì)用重定向指定的文件替換標(biāo)準(zhǔn)輸入文件描述符
#命令行中只輸入cat命令靶庙,它會(huì)接受stdin 的輸入
#也可以使用重定向符號(hào)接受非stdin的輸入
cat < testfile
#輸出重定向來改變輸出,將顯示到顯示器的輸出定向到指定的重定向文件
ls -l > test2
#追加數(shù)據(jù)
who >> test2
#shell處理錯(cuò)誤消息和處理普通輸出是分開的
#默認(rèn)情況下娃属,stdout,stderr文件描述符指向同樣的地方,顯示器
#重定向錯(cuò)誤
#只重定向錯(cuò)誤,2>是緊連在一起的
ls -al badfile 2> test4
#重定向錯(cuò)誤和數(shù)據(jù)
#在重定向的每個(gè)數(shù)據(jù)前添加對(duì)應(yīng)的文件描述符掏击,將它們指向?qū)?yīng)的保存數(shù)據(jù)的輸出文件
ls -al test test2 test3 badtest 2> test6 1> test7
#同樣也可以將stderr和stdout輸出重定向到同一個(gè)輸出文件
ls -al test test2 test3 badtest &> test7
#bash shell會(huì)自動(dòng)給錯(cuò)誤消息分配較標(biāo)準(zhǔn)輸出來說更高的優(yōu)先級(jí)
#這樣就可以在一處地方查看錯(cuò)誤消息了```
###腳本中重定向輸出
用stdout和stderr文件描述符來在多個(gè)位置生成輸出秩铆,重定向相應(yīng)的文件描述符
臨時(shí)重定向
在腳本中生成錯(cuò)誤消息,將某一行輸出重定向到stderr
echo "this is an error message" >&2
所以如果腳本重定向了stderr捅膘,就會(huì)將上條消息輸出到重定向的文件
./test8 2> test9```
永久重定向
#exec命令使shell在腳本執(zhí)行期間重定向某個(gè)特定文件描述符
#重定向每個(gè)echo語句
exec 1>testout
echo "this is a test"
#exec命令會(huì)啟動(dòng)一個(gè)新shell并且將stdout文件描述符重定向到文件
#腳本中發(fā)給stdout的所有輸出都會(huì)被重定向到文件
exec 2>testerror
echo "this is the start of the script"
exec 1>testout
echo "i love you"
echo "but this should go to the testerror file" >&2
#因此這里testout會(huì)包含正常信息滚粟,testerror則包含錯(cuò)誤信息
#在定義1>testout之前的echo還是會(huì)輸出到屏幕上的```
###在腳本中重定向輸入
exec命令將stdin重定向到linux系統(tǒng)上的文件中
!/bin/bash
exec 0< testfile
count=1
while read line;do
echo "line #$count: $line"
count=$[ $count + 1 ]
done
讀取日志文件的最簡(jiǎn)單辦法```
創(chuàng)建輸出文件描述符
#shell中最多可以有9個(gè)打開的文件描述符坦刀,另外6個(gè)是3-8
exec 3>test13out
echo "this should display on the monitor"
echo "and this should be stored in the file" >&3
echo "then this should be back on the monitor"
#可以使用exec命令來輸出追加到現(xiàn)有文件
exec 3>>test13out```
###重定向文件描述符
將文件描述符3重定向到文件描述符1的位置,也就是顯示器
類似于引用沐寺,顯示器的引用盖奈,重定向文件的引用
exec 3>&1
將文件描述符1重定向到文件,但是3仍然指向顯示器
exec 1>test14out
echo "this should store in the output file"
echo "along with this line"
將1重定向3的位置钢坦,也就是顯示器
exec 1>&3
echo "now things should be back to normal"```
創(chuàng)建輸入文件描述符
#先將stdin文件描述符保存到另外一個(gè)文件描述符爹凹,讀取完重定向文件后再恢復(fù)
exec 6<&0
exec 0< testfile
count=1
while read line;do
echo "Line #$count: $line"
count=$[ $count + 1 ]
done
exec 0<&6
read -p "are you done now?" answer
case $answer in
y|Y) echo "goodbye";;
N|n) echo "sorry, this is the end";;
esac```
###創(chuàng)建讀寫文件描述符
使用同一個(gè)文件描述符來從文件中讀寫數(shù)據(jù)
exec 3<> testfile
read line <&3
echo "Read: $line"
echo "this is a test line" >&3
因?yàn)閟hell中會(huì)維護(hù)一個(gè)讀寫文件的位置指針
因此讀取之后,指針的位置將作為下一次讀寫的位置
如果寫入的話微酬,就會(huì)從這個(gè)位置開始覆蓋原有的數(shù)據(jù)```
關(guān)閉文件描述符
#shell會(huì)在腳本退出時(shí)自動(dòng)關(guān)閉它們
#手動(dòng)關(guān)閉文件描述符
exec 3>&-
#下面是一個(gè)例子,最后會(huì)出現(xiàn)錯(cuò)誤陷遮,一旦關(guān)閉了垦江,就不能再使用了
exec 3> test17file
echo "this is a test line of data" >&3
exec 3>&-
echo "this won't work" >&3```
###列出打開的文件描述符
lsof -a -p $$ -d 0,1,2
-a選項(xiàng)是對(duì)后面兩個(gè)選項(xiàng)的結(jié)果執(zhí)行布爾and運(yùn)算
-p指定進(jìn)程PID,$$表示當(dāng)前進(jìn)程的PID
-d表示允許指定要顯示的文件描述符的個(gè)數(shù)
FD那一列中绽族,數(shù)字表示文件描述符梗逮,u表示讀寫,w表示寫慷彤,r表示讀```
阻止命令輸出
ls -al > /dev/null
#阻止任何錯(cuò)誤消息但是不保存
ls -al badfile test16 2> /dev/null
#也可以在輸入重定向?qū)?dev/null作為輸入文件
#從而快速移除現(xiàn)有的文件中的數(shù)據(jù)而不用先刪除文件再創(chuàng)建底哗,bingo
cat /dev/null > testfile```
###創(chuàng)建本地臨時(shí)文件
mktemp會(huì)在本地目錄中創(chuàng)建一個(gè)臨時(shí)文件
指定文件名模板,
mktemp testing.XXXXXX
mktemp會(huì)用6個(gè)字符碼替換這6個(gè)X跋选,保證文件名在目錄中是唯一的前标,返回文件名
將文件名保存到變量中,就可以在后面腳本中引用了
tempfile=mktemp test19.XXXXXX
exec 3>$tempfile
echo "this script writes to temp file $tempfile"
echo "this is the first line" >&3
echo "this is the second line" >&3
exec 3>&-
echo "done creating temp file, the contents are:"
cat $tempfile
rm -f $tempfile 2> /dev/null```
在/tmp目錄創(chuàng)建臨時(shí)文件
#-t選項(xiàng)會(huì)在系統(tǒng)的臨時(shí)目錄創(chuàng)建文件炼列,返回全路徑
mktemp -t test.XXXXXX
#比如返回/tmp/test.XG3374
tempfile=`mktemp -t tmp.XXXXXX`
echo "this is a test file" > $tempfile
echo "this is the second line" >> $tempfile
echo "the temp file is located at: $tempfile"
cat $tempfile
rm -f $tempfile```
###創(chuàng)建臨時(shí)目錄
-d選項(xiàng)使其創(chuàng)建一個(gè)臨時(shí)目錄
tempdir=mktemp -d dir.XXXXXX
cd $tempdir
tempfile1=mktemp temp.XXXXXX
tempfile2=mktemp temp.XXXXXX
exec 7> $tempfile1
exec 8> $tempfile2
echo "sending data to directory $tempdir"
echo "this is a test line of data for $tempfile1" >&7
echo "this is a test line of data for $tempfile2" >&8```
tee命令
#將stdin過來的數(shù)據(jù)重定向
date | tee testfile
#默認(rèn)情況下俭尖,tee命令會(huì)在每次使用時(shí)覆蓋輸出文件內(nèi)容
#使用-a來將數(shù)據(jù)追加過去
date | tee -a testfile```