前言
首先,我們得知道,linux 系統會將用戶的每個請求對象都當作一個文件,輸入輸出也不例外。那麼,我們就得知道進行輸入與輸出的文件都是什麼?都有那些?
如果每個對象都需要文件,那麼對文件就應該有標識以便區分。因此就需要文件描述符。文件描述符是一個非負整數,可以唯一地標識會話中打開的文件,每個過程一次最多可以有9個文件描述符,出於特殊目的,bash shell 保留了最早的3個文件描述符(0、1、2)。
下圖爲輸入一個命令後系統所進行的一系列操作:
輸入輸出
-
輸入
stdin[標準輸入流]
輸入是指系統外界向系統中傳入的信息,編號爲0 -
輸出
stdout[標準正確輸出流]
在命令順利執行後產生的字符串,編號爲1
stderr[標準錯誤輸出流]
在命令執行失敗後產生的字符串,編號爲2 -
字符設備
指在I/O傳輸過程中以字符爲單位進行傳輸的設備,如鍵盤,打印機等。
字符設備是內存中開啓的虛擬設備並且真實存在
重定向輸出
符號 | 用途 |
---|---|
> | 重定向正確輸出 |
2> | 重定向錯誤輸出 |
&> | 重定向所有輸出 |
輸入輸出示例
[student@workstation Desktop]$ find /etc/ -name passwd //輸入命令,尋找passwd
find: ‘/etc/pki/rsyslog’: Permission denied //結果如下
find: ‘/etc/dhcp’: Permission denied
/etc/pam.d/passwd
/etc/passwd
find: ‘/etc/polkit-1/rules.d’: Permission denied
find: ‘/etc/polkit-1/localauthority’: Permission denied
find: ‘/etc/sssd’: Permission denied
find: ‘/etc/grub.d’: Permission denied
find: ‘/etc/audit’: Permission denied
find: ‘/etc/firewalld’: Permission denied
find: ‘/etc/sudoers.d’: Permission denied
find: ‘/etc/lvm/archive’: Permission denied
find: ‘/etc/lvm/backup’: Permission denied
find: ‘/etc/lvm/cache’: Permission denied
find: ‘/etc/libvirt’: Permission denied
find: ‘/etc/cups/ssl’: Permission denied
可以看出,除了有兩條正確輸出外其他都是錯誤輸出。
我們可以去找一下輸出這些的文件
進程信息
[student@workstation Desktop]$ ps
PID TTY TIME CMD
2684 pts/0 00:00:00 bash
3023 pts/0 00:00:00 ps
進程id爲2684,去proc/2684/fd文件
我們是不能打開這些文件的,但我們可以看到進程中卻是存在這些輸入輸出文件
重定向輸出示例
- ‘>’
如下所示:將結果重定向到test,test中會存在find的正確結果,而將錯誤的結果會輸出到屏幕
[student@workstation Desktop]$ find /etc -name passwd > test
find: ‘/etc/pki/rsyslog’: Permission denied
find: ‘/etc/dhcp’: Permission denied
find: ‘/etc/polkit-1/rules.d’: Permission denied
find: ‘/etc/polkit-1/localauthority’: Permission denied
find: ‘/etc/sssd’: Permission denied
find: ‘/etc/grub.d’: Permission denied
find: ‘/etc/audit’: Permission denied
find: ‘/etc/firewalld’: Permission denied
find: ‘/etc/sudoers.d’: Permission denied
find: ‘/etc/lvm/archive’: Permission denied
find: ‘/etc/lvm/backup’: Permission denied
find: ‘/etc/lvm/cache’: Permission denied
find: ‘/etc/libvirt’: Permission denied
find: ‘/etc/cups/ssl’: Permission denied
- ‘2>’
如下所示:將結果重定向到test,test中會存在find的錯誤結果,而將正確的結果會輸出到屏幕
[student@workstation Desktop]$ find /etc -name passwd 2> test
/etc/pam.d/passwd
/etc/passwd
- ‘&>’
如下所示:將全部結果重定向到test,屏幕上並不會出現任何信息
[student@workstation Desktop]$ find /etc -name passwd &> test
此時讓我們打開test文件查看一下
追加
在重定向操作中,會覆蓋源文件,如果源文件中的內容之後還要用到,我們只是希望將新文件追加到源文件之後,就需要用到追加
符號 | 用途 |
---|---|
>> | 追加正確輸出 |
2>> | 追加錯誤輸出 |
&>> | 追加全部輸出 |
具體操作效果僅與重定向稍許不同,可參見重定向的操作
管道
把輸出變成下一條命令的輸入
(有時候我們需要一些高級的更復雜的操作,比如一條命令得到的結果變成下一條命令的作用對象,這這時候我們就需要管道來幫助我們)
符號 | 用途 |
---|---|
I | 管道符 |
2>&1 | 將編號爲1的輸出轉換爲2 |
tee | 複製輸出到指定位置 |
現在我們來想一個需求,對上面找到的passwd文件進行計數。
我們可以先將找到的結果存儲到一個文件中,在對新產生的文件計算行數,這個行就是文件的個數,在不知道管道的時候,我們需要兩條命令來完成這個操作,但瞭解了管道,一條命令就可以操作。但是,不僅如此,管道帶給我們的好處是能節省我們不少的時間,因爲對磁盤文件裏面的計數與對內存中的計數時間是不一樣的。
-
‘|’ 將正確結果計數
[student@workstation Desktop]$ find /etc -name passwd | wc -l find: ‘/etc/pki/rsyslog’: Permission denied find: ‘/etc/dhcp’: Permission denied find: ‘/etc/polkit-1/rules.d’: Permission denied find: ‘/etc/polkit-1/localauthority’: Permission denied find: ‘/etc/sssd’: Permission denied find: ‘/etc/grub.d’: Permission denied find: ‘/etc/audit’: Permission denied find: ‘/etc/firewalld’: Permission denied find: ‘/etc/sudoers.d’: Permission denied find: ‘/etc/lvm/archive’: Permission denied find: ‘/etc/lvm/backup’: Permission denied find: ‘/etc/lvm/cache’: Permission denied find: ‘/etc/libvirt’: Permission denied find: ‘/etc/cups/ssl’: Permission denied 2
可以看出結果爲2
-
‘2>&1’正誤結果都計數
[student@workstation Desktop]$ find /etc -name passwd 2>&1 | wc -l 16
-
‘tee’記錄消息
tee命令相當於管道的一個T型接頭,它將從輸入過來的數據
同時發給兩個目的地。計數結果
[student@workstation Desktop]$ find /etc -name passwd 2>&1 |tee test |wc -l 16
打開test文件
find: ‘/etc/pki/rsyslog’: Permission denied find: ‘/etc/dhcp’: Permission denied /etc/pam.d/passwd /etc/passwd find: ‘/etc/polkit-1/rules.d’: Permission denied find: ‘/etc/polkit-1/localauthority’: Permission denied find: ‘/etc/sssd’: Permission denied find: ‘/etc/grub.d’: Permission denied find: ‘/etc/audit’: Permission denied find: ‘/etc/firewalld’: Permission denied find: ‘/etc/sudoers.d’: Permission denied find: ‘/etc/lvm/archive’: Permission denied find: ‘/etc/lvm/backup’: Permission denied find: ‘/etc/lvm/cache’: Permission denied find: ‘/etc/libvirt’: Permission denied find: ‘/etc/cups/ssl’: Permission denied
可見既進行的保存文件,又進行了文件的計數
(注意:tee命令會在每次使用時覆蓋輸出文件內容,如果你想將數據追加到文件中,必須使用-a選項。)
輸入重定向
-
‘<’ 輸入重定向
用符號從文件中獲取輸入
例如:我們現在想要將一個文件的大小寫對換。tr命令可以將一個文件的大小寫統一,那麼首先得打開一個文件,再對文件進行tr操作。
原來文件:[root@workstation ~]# cat test Hello world My name is Hai Zhizhuer
利用管道進行更改:
[root@workstation ~]# cat test | tr 'a-z' 'A-Z' HELLO WORLD MY NAME IS HAI ZHIZHUER
然而利用管道在此時就顯得沒那麼高效,使用重定向輸入來看看:
[root@workstation ~]# tr 'A-Z' 'a-z' < test hello world my name is hai zhizhuer
相當於將test文件作爲tr命令的輸入。
-
'<<'多行輸入
例如:如果我們要重置密碼,就得輸入兩邊新的密碼,來確保自己的密碼沒有因爲手誤而輸錯。此時就可使用多行輸入。而這個命令更多的應用於bash腳本,可幫助我們自動化的配置某些文件。paswd << HAI >redhat >redhat >HAI
上述代碼中使用到的HAI這個關鍵字是任意的,可以輸入任何你覺得ok的關鍵字,但注意,若系統監測到與多行輸入後你輸入的關鍵字一樣的關鍵字,即認爲輸入結束。
一般標準情況下,我們使用EOF:
我們打開一個.sh的文件vim test1.sh
並輸入如下文字且保存
date passwd << EOF redhat redhat EOF tr 'a-z' 'A-Z' < test
然後執行這個.sh文件
bash test.sh
結果會逐一執行上述命令。
顯示date信息 對密碼進行重置 將test文件中的小寫全部換成大寫
(注意:重定向輸入與多行輸入並無邏輯上的必然關係。)
總結
輸入輸出操作對於每一個計算機使用者來說都是必不可少的,所以,如何控制輸入輸出爲我們日常需求來工作是運維工程師必須具備的技能。重定向與管道的引入對我們會非常有幫助。