標準的輸入、輸出與管線
標準的資料通道
- Linux有三個標準的資料通道,分別是:
- stdin 編號 0 --預設為鍵盤
- stdout 編號 1 --預設為windows終端機
- stderr 編號 2 --預設為windows終端機
- 簡單的說明
[mtchang@server1 ~]$ ls -l Desktop fakefile # STDERR 輸出 ls: fakefile: No such file or directory # STDOUT 輸出 Desktop: total 12 -rw-r--r-- 1 mtchang mtchang 4803 Jan 7 2007 gnome-terminal.desktop -rw-rw-r-- 1 mtchang mtchang 260 Aug 14 19:54 Thunderbird.desktop
轉移輸出
- Linux的轉移資料字元:
- < 轉向標準輸入
- > 轉向輸出,如果該目標(檔案)已存在會覆蓋。
- 1> stdout轉向輸出,如果該目標(檔案)已存在會覆蓋。
- >> 轉向輸出如果該目標(檔案)已存在會添加在檔案後面。
- 1>> stdout轉向輸出如果該目標(檔案)已存在會添加在檔案後面。
- 2> stderr轉向輸出,如果該目標(檔案)已存在會覆蓋。如不想覆蓋可使用2>>添加在檔案後面。
- 2>> stderr轉向輸出,如果該目標(檔案)已存在會添加在檔案後面。
- &> all(0,1,2)轉向輸出到目標(檔案)
- &1> stdout的輸出轉向到目標(檔案)
- &2> stderr的輸出轉向到目標(檔案)
- &1 代表stdout的輸出
- &2 代表stderr的輸出
- Linux的特殊裝置 /dev/null 黑洞,任何輸入到/dev/null的資料皆會消失不顯示於任何地方。
- < 轉向標準輸入的範例,把ls的內容轉入給mail程式
[lcc09@localhost ~]$ ls > ls [lcc09@localhost ~]$ cat ls Desktop ls public_html [lcc09@localhost ~]$ mail lcc09 < ls [lcc09@localhost ~]$ mail Mail version 8.1 6/6/93. Type ? for help. "/var/spool/mail/lcc09": 1 message 1 new >N 1 lcc09@localhost.loca Fri May 25 20:50 17/659 & 1 Message 1: From lcc09@localhost.localdomain Fri May 25 20:50:09 2007 Date: Fri, 25 May 2007 20:50:09 +0800 From: lcc09To: lcc09@localhost.localdomain Desktop ls public_html & q Saved 1 message in mbox
- 一個帶有 stdout 及 stderr 輸出的指令
[lcc09@localhost ~]$ ls ~/ /rec ls: /rec: 沒有此一檔案或目錄 /home/lcc09/: Desktop public_html
- 將 stderr 轉到 /dev/null 所以看不到錯誤的訊息
[lcc09@localhost ~]$ ls ~/ /rec 2> /dev/null /home/lcc09/: Desktop public_html
- 將 stderr 接到 stdout ,並將 stdout 存到 list
- >list :stdout轉向輸出到 list 檔案
- 2>&1 :stderr轉向輸出到 &1(stdout)
- &參考的檔案描述,為標準輸出編號,&1代表stdout
[lcc09@localhost ~]$ ls ~/ /rec > list 2>&1 [lcc09@localhost ~]$ more list ls: /rec: 沒有此一檔案或目錄 /home/lcc09/: Desktop list mbox public_html
- 使用echo以keyboard為輸入裝置,並在銀幕上輸入文字,最後轉存到檔案。
[lcc09@localhost ~]$ echo "hello tux > > how r u > i okey?? > save " > greetings
- 練習:寫一個 shell script 可以自動產生一個 index.html 檔案,內容為標準的 html 檔案結構,並且在 body 內放入今天的日期。
[student@server1 ~]$ ./html.sh [student@server1 ~]$ nano html.sh #!/bin/bash echo " $(date +%Y%m%d) " > index.html [student@server1 ~]$ ./html.sh [student@server1 ~]$ cat index.html 20091209
補充:mail 指令的使用
- mail:送出和接收email
- 在命令列輸入 mail 即可進入 mail 程式內收發信件
- 若想寫信給他人,則在命令列輸入 mail 收信者帳號 ,即可發送信件給「收信者」
- 若想將既有的文字檔當成信件內容寄給他人,則在命令列輸入
mail 收信者帳號 -s 信件主題 < 文件檔名稱
即可將「文件檔名稱」發送給「收信者」
- 在 mail 程式中
- 輸入 ? 查詢所有指令
- 輸入 h 列出所有信件
- 輸入 t 閱讀信件
- 輸入 n 閱讀下一封信件
- 輸入 d 刪除信件
- 輸入 u 救回刪除信件
- 輸入 R 回覆信件
- 輸入 m 收信者帳號 發送信件給「收信者」
- 輸入 q 離開 mail 程式,並將閱讀過的所有信件存至「mbox」檔案
- 輸入 x 離開 mail 程式
- 寄信
[mtchang@mt test]$ mail mtchang Subject: test test . Cc:
- 看信
[mtchang@mt test]$ mail Mail version 8.1 6/6/93. Type ? for help. "/var/spool/mail/mtchang": 1 message 1 new >N 1 mtchang@localhost.lo Tue Oct 14 17:11 16/644 "test" & 1 Message 1: From mtchang@localhost.localdomain Tue Oct 14 17:11:35 2008 Date: Tue, 14 Oct 2008 17:11:35 +0800 From: mtchangTo: mtchang@localhost.localdomain Subject: test test & q Saved 1 message in mbox
標準輸出到程式(Piping)
- 管線指令 pipe(|)
[lcc09@localhost ~]$ command1 | command2 # 將command1的輸出導入到command2的輸入
- less 把輸出限制在一個頁面上,並且可以做功能性的操作,將ls輸出導入到less的輸入。
ls -l /etc | less
- mail 寄郵件,將內容為「test email」的內容以「test」的主旨寄給 student@localhost 使用者,此功能可以寄出到外界的信箱,但是大部分的主機都會將其列為垃圾信件。
echo "test email" | mail -s "test" student@localhost
- lpr 列印,或指定列印到某台印表機
echo "test print" | lpr echo "test print" | lpr -p printer_name
- 把 man ls 的資訊交由 col -b 過濾控制碼,並將其轉輸出到 ls.txt 檔案
[root@server1 ~]# man ls | col -b > ls.txt
多目標轉移
- tee 指令的搭配,tee指令是一個雙向指令,會將標準輸入輸出到兩個地方(檔案及標準輸出)
- $ command1 | tee filename
- 常見用途:
- pipelines 命令除錯
- 想要看結果也想要作logging
- 簡單範例
[lcc09@localhost ~]$ man tee | col -b > tee.txt # 將man tee的結果導入到col -b的輸入,並將結果輸出到tee.txt [lcc09@localhost ~]$ ls -l | tee output # tee這個指令是一個雙向指令,會將標準輸入輸出到兩個地方(檔案及標準輸出)
- 將man tee的結果導入到col -b的輸入,將col -b 的結果輸出tee程式,由tee分配到ls.txt檔案及STDOUT(螢幕)
[lcc09@localhost ~]$ man ls | col -b | tee ls.txt
tr 轉換字元
- tr 轉換字元
[lcc09@localhost ~]$ tr 'a-z' 'A-Z' < .bash_history # 將 .bash_history的英文字母a-z轉換成大寫的A-Z [lcc09@localhost ~]$ cat .bash_history | tr 'a-z' 'A-Z' # 這命令和上述的命令結果一樣
送出多行文字到STDIN
- STDIN可以在命令列中使用 <
- All text until WORD is sent to STDIN
- Sometimes called a heretext
[lcc09@localhost ~]$ mail -s 'please call' root << END > hello root > good by > END [lcc09@localhost ~]$
- ctrl+D 結束輸入
Scripting:for loop array
- 迴圈的語法與應用
for 的語法文字串方式
- for 的語法文字串方式
for 變數 in 數值1 數值2 數值3 do # 迴圈內容,$變數可以取用迴圈帶入的數值 echo $變數 done
簡單的測試 for 迴圈示範
- 程式碼,檔案 for.sh,請建立如下程式
[student@server1 ~]$ nano for.sh #!/bin/bash for NAME in root student mtchang do echo $NAME done
- 賦予可執行權
[student@server1 ~]$ chmod +x for.sh
- 執行結果,變數把root student mtchang三個文字依序帶入迴圈並顯示
[student@server1 ~]$ ./for.sh root student mtchang
迴圈中使用Name的方式
- 此範例為寄信給root、mtchang及student的使用者
[student@server1 ~]$ vi loop.sh #!/bin/bash # for 迴圈開始,第1次載入 root ,第2次載入 mtchang,第3次載入 student # 底下程式碼請注意空白、單引號及雙引號的不同 for NAME in root mtchang student do # 將收件人$NAME存為變數ADDRESS ADDRESS="$NAME" # 將信件內容寫成變數MESSAGE MESSAGE='Projects are due today!' # mail 指令簡單用法 # echo '內容' | mail -s '標題' 收件人 echo $MESSAGE | mail -s Reminder $ADDRESS done
for 的語法:數值方式
- for 的語法:數值方式
for 變數 in {整數值..整數值} do # 迴圈內容,$變數可以取用迴圈帶入的數值 echo $變數 done
產生一各簡單的for迴圈
- for 迴圈:產生 1 至 20的整數
[lcc09@localhost ~]$ vi num.sh #!/bin/bash for n in {1..20}; do echo $n done
檢測目前網段的機器,簡單寫法
- 「$?」變數代表前一各指令正確執行成功。
- $?=1 則前一各指令執行失敗
- $?=0 則前一各指令執行成功
for n in {1..5}; do h="192.168.3.$n" echo $h # 讓 stdout 不輸出,畫面會比較乾淨 # ping -c1 $h > /dev/null echo "return value = $? " done
檢測目前網段的機器
- 檢測目前網段的機器,存活的機器。
- 「$?」變數代表前一各指令正確執行成功。
- $?=1 則前一各指令執行失敗
- $?=0 則前一各指令執行成功
#!/bin/bash # alive2.sh for n in {1..20}; do host=192.168.1.$n ping -c1 $host &> /dev/null if [ $? = 0 ]; then echo "$host id UP" else echo "$host id DOWN" fi done
變數值使用命令帶入
- 在變數的部份,使用命令或是檔案帶入的情形
- 先測是底下的指令,從 /etc/passwd 檔案找出帶有 bash 的行
[root@localhost ~]# grep bash /etc/passwd root:x:0:0:root:/root:/bin/bash lcc09:x:500:500:lcc09:/home/lcc09:/bin/bash student:x:501:501::/home/student:/bin/bash
- 寫個script將此指令結果帶入迴圈
[root@localhost ~]# vim foruser.sh #!/bin/bash for USER in $(grep bash /etc/passwd) do echo $USER done # 賦予可執行權限 [root@localhost ~]# chmod +x foruser.sh # 執行 [root@localhost ~]# ./foruser.sh root:x:0:0:root:/root:/bin/bash lcc09:x:500:500:lcc09:/home/lcc09:/bin/bash student:x:501:501::/home/student:/bin/bash
變數值使用文字檔案帶入
- 使用指令 cat 觀看一個文字檔案
[root@localhost ~]# cat /etc/issue Welcome ! Red Hat Enterprise Linux Server release 5.1 (Tikanga) Kernel \r on an \m
- 程式 forfile.sh
#!/bin/bash for FILE in $(cat /etc/issue) do echo $FILE done
- 執行結果
[root@localhost ~]# ./forfile.sh Welcome ! Red Hat Enterprise Linux Server release 5.1 (Tikanga) Kernel \r on an \m
Scripting:array
- bash下array的幾種使用方法
#!/bin/bash #一舉將變數設定到陣列中 array=(Redhat Novell MicroSoft Sun IBM HP Dell) #利用for loop將陣列中的變數印出 for i in 0 1 2 3 4 5 6 do echo "array[$i]=${array[$i]}" done #設定間隔符號為: 搭配$*將陣列的值一口氣輸出 IFS=: echo "${array[*]}" #設定間隔符號為換行,搭配$*將陣列的值一口氣輸出 IFS=$'\n' echo "${array[*]}" #將陣列中的值利用$@一口氣輸出與$*不同的是,不會將值合併成單一字串 echo "${array[@]}" #印出陣列中有幾筆資料 echo "${#array[@]}" 執行結果: array[0]=Redhat array[1]=Novell array[2]=MicroSoft array[3]=Sun array[4]=IBM array[5]=HP array[6]=Dell Redhat:Novell:MicroSoft:Sun:IBM:HP:Dell Redhat Novell MicroSoft Sun IBM HP Dell Redhat Novell MicroSoft Sun IBM HP Dell 7
沒有留言:
張貼留言