標準IO和重定向
程序:指令+數據
讀入數據:Input
輸出數據:Output
打開的文件都有一個fd: file descriptor (文件描述符)
Linux給程序提供三種I/O設備
標準輸入(STDIN)-0 默認接受來自鍵盤的輸入
標準輸出(STDOUT)-1 默認輸出到終端窗口
標準錯誤(STDERR)-2 默認輸出到終端窗口
I/O重定向:改變默認位置
fd示例:
首先用tail -f 持續打開一個文件,這時已經給tail程序分配了一個文件描述符fd
然後在另一個終端上面進入 /etc/proc中找到它的 進程編號,可以用pidof tail來顯示
然後進入到這個進程編號目錄內,找到fd,查看其中的內容
程序tail 用ctrl+c關閉之後 這個進程編號便會消失,同時fd自然也就沒有了(fd是在進程編號裏面的文件夾)
20:16[root@centos7 /data]# tail -f /data/1.t
2awda awdf###n dwa /naaa
另一個終端:
20:37[root@centos7 ~]# cd /proc 20:38[root@centos7 /proc]# ls 1 26 3018 6 6245 7698 8144 8329 cmdline modules 10 27 36 6103 6250 7791 8150 8335 consoles mounts 11 27378 37 6105 6292 7804 8163 8343 cpuinfo mpt 12 27438 38 6107 6586 7810 8164 8352 crypto mtrr 13 27526 39 6110 66 7814 8174 8354 devices net 14 27537 47 6111 667 7816 8182 8359 diskstats pagetypeinfo 14249 27551 4701 6135 6781 7820 8183 8372 dma partitions 14674 27707 4886 6136 6782 7832 8185 8380 driver sched_debug 16 27768 4888 6137 6785 7835 8187 8381 execdomains schedstat 16316 27847 4889 6138 6786 7910 8196 8390 fb scsi 1658 27890 4896 6141 6791 7915 8198 8391 filesystems self 1661 28 4897 6143 6810 8 8201 8405 fs slabinfo 1665 2886 49 6144 6811 8017 8202 8421 interrupts softirqs 1709 2889 4901 6150 6814 8031 8206 8427 iomem stat 1715 2890 4902 6160 682 8036 8208 8432 ioports swaps 1791 2898 4908 6161 687 8039 8221 8547 irq sys 1793 29 4910 6162 693 8066 8224 8566 kallsyms sysrq-trigger 18 2902 4914 6165 699 8085 8226 8572 kcore sysvipc 19 2905 4917 6170 7 8089 8227 8573 keys timer_list 2 2906 4918 6174 7197 8092 8229 8625 key-users timer_stats 20 2907 4919 6177 7209 8094 8232 8636 kmsg tty 21 2908 4920 6178 7229 8106 8236 9 kpagecount uptime 22 2909 4937 6180 7234 8110 8246 99 kpageflags version 23 2910 4941 6181 7248 8116 8248 acpi loadavg vmallocinfo 23591 2911 5 6183 7537 8123 8267 asound locks vmstat 24 2984 50 6185 7605 8124 8311 buddyinfo mdstat zoneinfo 25 3 51 6203 7612 8133 8314 bus meminfo 25713 3005 53 6235 7614 8135 8317 cgroups misc 20:38[root@centos7 /proc]# cd `pidof tail` 20:38[root@centos7 /proc/27526]# ls attr coredump_filter gid_map mountinfo oom_score sched statm autogroup cpuset io mounts oom_score_adj schedstat status auxv cwd limits mountstats pagemap sessionid syscall cgroup environ loginuid net patch_state setgroups task clear_refs exe map_files ns personality smaps timers cmdline fd maps numa_maps projid_map stack uid_map comm fdinfo mem oom_adj root stat wchan 20:38[root@centos7 /proc/27526]# cd fd 20:39[root@centos7 /proc/27526/fd]# ll total 0 lrwx------. 1 root root 64 Mar 11 20:39 0 -> /dev/pts/1 lrwx------. 1 root root 64 Mar 11 20:39 1 -> /dev/pts/1 lrwx------. 1 root root 64 Mar 11 20:39 2 -> /dev/pts/1 lr-x------. 1 root root 64 Mar 11 20:39 3 -> /data/1.t lr-x------. 1 root root 64 Mar 11 20:39 4 -> anon_inode:inotify
標準輸出和標準錯誤重定向到其他文件或終端
- STDOUT和STDERR可以被重定向到文件
命令 操作符號 文件名
支持的操作符號包括:把STDOUT重定向到文件
2>把STDERR重定向到文件
&>把所有輸出重定向到文件
">"文件內容會被覆蓋
set -C 禁止將內容覆蓋已有文件,但可追加
| file 強制覆蓋
set +C 允許覆蓋
">>"原有內容基礎上,追加內容
2> 覆蓋重定向錯誤輸出數據流
2>> 追加重定向錯誤輸出數據流
標準輸出和錯誤輸出各自定向至不同位置
COMMAND > /path/to/file.out 2> /path/to/error.out
&> 覆蓋重定向
&>> 追加重定向
COMMAND > /path/to/file.out 2>&1 (順序很重要)
COMMAND >> /path/to/file.out 2>&1
():合並多個程序的STDOUT,或者合並錯誤和輸出
( cal 2007 ; cal 2008 ) > all.txt
( cal 2007 ; cal 0000 2>&1) > all.txt
- 可以用> 指向 /dev/null 將標準輸出不顯示
- 可以用> 指向文件將文件內容清空 ,但註意有些shell可能不支持,比如csh,它只能用cat /dev/null > file 才可以
- 追加到文件中可以用>> 也可以將兩個命令用小括號括起來再使用
- 同時,正確和錯誤信息同時追加到一個文件也有一個寫發2>&1, 放在括號裏面,註意與後面的那好幾個寫法區分
20:55[root@centos7 /data]# (hostname; uname -r) > 1.t 20:55[root@centos7 /data]# cat 1.t centos7.6test 3.10.0-957.el7.x86_64
21:36[root@centos7 /data]# (ls /eraf /home 2>&1) >1.t
21:38[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang
- \> 或者兩個>> 也可以創建文件,但是因為>會把文件內容覆蓋,(假如存在原始文件) 所以用>>更加安全
21:07[root@centos7 /data]# ls /eraf /home > 1.t 2>&1
21:08[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang
21:08[root@centos7 /data]# ls /eraf /home 2>1.t 1>&2
21:08[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang
21:09[root@centos7 /data]# ls /eraf /home 2>&1 >1.t
ls: cannot access /eraf: No such file or directory
21:09[root@centos7 /data]# cat 1.t
/home:
zhang
21:12[root@centos7 /data]# ls /eraf /home &>1.t
21:12[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang
其中
1 cmd &> file
2 cmd > file 2>&1
3 cmd 2>&1 > file xxx
4 cmd 2>file 1>&2
問題:可以測試一下下面這幾個命令的區別
ls /eraf /home 1>1.t 2>1.t
ls /eraf /home 1>>1.t 2>1.t
ls /eraf /home 2>>1.t 1>1.t
ls /eraf /home 2>1.t 1>1.t
ls /eraf /home 2>1.t 2>&1 1>1.t
ls /eraf /home 2>>1.t 2>&1 1>1.t
ls /eraf /home 2>&1 2>1.t 1>1.t
ls /eraf /home 2>&1 2>>1.t 1>1.t
tr轉換
tr 轉換和刪除字符
tr [OPTION]... SET1 [SET2]
選項:
-c –C --complement:取字符集的補集
-d --delete:刪除所有屬於第一字符集的字符
-s --squeeze-repeats:把連續重復的字符以單獨一個字符表示
-t --truncate-set1:將第一個字符集對應字符轉化為第二字符集對應的字符
tr命令默認會讓你用鍵盤輸入,退出的時候不能按回車(按回車只是換行,增加了一個\n),需要用ctrl+d快捷鍵
[:alnum:]:字母和數字
[:alpha:]:字母
[:cntrl:]:控制(非打印)字符
[:digit:]:數字
[:graph:]:圖形字符
[:lower:]:小寫字母
[:print:]:可打印字符
[:punct:]:標點符號
[:space:]:空白字符
[:upper:]:大寫字母
[:xdigit:]:十六進制字符
註意:tr轉換中的字符串和通配符的區別在於:
tr轉換裏面不需要再加中括號了,直接代表一種字符
而通配符整體僅僅代表一個字符,外層需要再加中括號才可以
ls [:lower:]
ls [[:lower:]]
tr ‘[:lower:][:upper:]‘ ‘12‘
註意:windows中的換行 包括兩個字符,\c 和\n;linux中只有一個\n 它會自動把光標移動到開頭
例如
a
b
c
windows:
00000000 61 0d 0a 62 0d 0a 63
00000007
linux:
0000000 61 0a 62 0a 63 0a
0000006
利用tr計算 1+..100總和
09:45[root@centos7 ~]# echo {1..100} | tr ‘ ‘ ‘+‘ | bc
5050
09:46[root@centos7 ~]# seq -s + 100 |bc
5050
帶有標準輸入的部分程序:bc ,cat ,tr,mail
例如 bc < file1 file1中寫有計算式,則屏幕上輸出結果.
標準輸入
使用 < 來重定向標準輸入
某些命令能夠接受從文件中導入的STDIN
tr ‘a-z’ ‘A-Z’< /etc/issue
該命令會把/etc/issue中的小寫字符都轉換成大寫字符
tr –d abc < /etc/fstab
刪除fstab文件中的所有abc中任意字符
tr -dc "abc" < /etc/fstab
只保留abc字符,其他的全部刪除
cat 也有標準輸入,只輸入cat則會讓你用鍵盤輸入,按回車之後會再次顯示出來,按ctrl+d可以離開
cat可以鍵盤輸入後輸出到文件
cat > file
mage
wangxiaochun
cat也可使用文件來代替鍵盤的輸入,並同時輸出到文件
cat < file1 > file2
但是需要註意下面的兩個結果
cat < file1 > file1 :會把file1清0
cat < file1 >> file1:會一直追加file1中的內容到file1下面,必須停止否則文件會過大
22:02[root@centos7 /data]# tr ‘abc‘ ‘xyzmk‘
abcdefaf
xyzdefxf
22:04[root@centos7 /data]# tr ‘abcde‘ ‘xyz‘
abcderf
xyzzzrf
22:06[root@centos7 /data]# tr -t ‘abcde‘ ‘xyz‘
abcedrf
xyzedrf
單行重定向和多行重定向
使用“<<終止詞”命令從鍵盤把多行重導向給STDIN
直到 終止詞 位置的所有文本都發送給STDIN
有時被稱為就地文本(heretext)
mail -s "Please Call" [email protected] <<END
註意:終止詞最後必須單獨一行且前後不能有任何字符包括空格等
註意:單行重定向(也就是不寫終止詞的默認寫法),每按一次回車,就會把結果重定向一次,而多行重定向只有終止詞輸入並回車之後才會把結果一次性輸出,在此之前沒有對文件做任何修改。
註意: 多行重定向內部可以用``來輸入命令等,可以實現不同的結果
管道
管道(使用符號“|”表示)用來連接命令
命令1 | 命令2 | 命令3 | …
將命令1的STDOUT發送給命令2的STDIN,命令2的STDOUT發送到命令3的STDIN
STDERR默認不能通過管道轉發,可利用2>&1 或 |& 實現
最後一個命令會在當前shell進程的子shell進程中執行
組合多種工具的功能
ls | tr ‘a-z’ ‘A-Z’
註意:管道前面命令必須要標準輸出,管道後面命令必須要標準輸入
管道重定向到多個目標
命令1 | tee [-a ] 文件名 | 命令2
把命令1的STDOUT保存在文件中,同時它也做為命令2的輸入
-a 追加到文件中
使用:
保存不同階段的輸出
復雜管道的故障排除
同時查看和記錄輸出
註意:tee 後面必須跟文件
管道特殊用法-
示例:
將 /home 裏面的文件打包,但打包的數據不是記錄到文件,而是傳送到stdout,經過管道後,將 tar -cvf - /home 傳送給後面的 tar -xvf - , 後面的這個 - 則是取前一個命令的 stdout,因此,就不需要使用臨時file了
tar -cvf - /home | tar -xvf -
本來的用法是:
tar -cvf 文件包名 /home
傳輸....
tar -xvf 文件包名
標準IO和重定向