iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0

實做訊息重導

訊息重導

在這個小節中,我們使用一些實際上的練習,透過這些練習可以更加瞭解訊息重導的結果與其運作方式。

我們假設使用帳號 student 登入主機,並使用 /etc/passwd 檔案做為練習範本來源。

指令如下:

  1. 建立測試目錄,並進入該目錄。
    student$ mkdir ~/message/; cd ~/message/
    
  2. 複製範本練習檔案。
    student$ cp /etc/passwd ./sample
    

輸入重導

標準輸入(stdin)是一個在許多作業系統中,包括 Linux,用於行程之間通信的重要概念。

stdin 主要負責下列工作:

  • 主要輸入通道:stdin 是行程的主要輸入通道,通常預設來自鍵盤輸入。行程可以從 stdin 讀取數據,就像從一個文件或讀取其他數據流一樣。

  • 資料交換接口:stdin 允許行程讀取其他行程的輸出,或者從文件和讀取其他數據來源。這樣可以讓不同的行程互相通信。

stdin 是作業系統和程式設計中的一個核心概念,它支撐了許多資料處理、自動化和跨行程通信的功能。這也是為什麼理解和掌握 stdin 如何工作是每個 Linux 使用者和開發人員的重要技能之一。

來自不同的輸入

我們使用 grep 程式從 sample 檔案中取出 root 字串,可以從下列方法得到結果:

student$ grep root sample
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

上述的做法,是由 grep 程式本身讀取檔案然後進行過濾。

若要使用 stdin 的方法,可以使用下列指令:

student$ grep root < sample
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

我們可以看到處理結果相同,但實際上 grep 並不是直接開啟檔案進行過濾,而是透過 shell 使用 stdin (<) 將資料提供給 grep

在實務的情況下我們更容易看到如下的指令:

student$ cat sample | grep root
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

上述的做法我們稱之為管線重導,grep 也是從 stdin 讀取資料流,而這個資料是由 cat 的輸出轉過去的,grep 在這個案例中沒有開啟任何檔案。有關管線操作的方法我們會在 管線應用 小節中說明。

輸出重導

在這個小節中,我們透過實作來瞭解程式訊息輸出的重新導向,讀者可以在此觀察到輸出的 stdoutstderr 的差別,並控制他們的流向。

管理 stdout

執行下列指令

student$ ls -lh sample

得到程式輸出如下

-rw-r--r-- 1 d3admin wheel 1.8K Aug 25 16:44 sample

我們現在知道不管哪一種輸出,都會輸出到預設的終端機,若要分辨是否為一般輸出,則可以使用 > 符號把訊息重導到另一檔案:stdout.txt

student$ ls -lh sample > stdout.txt

此時原本會顯示在畫面上的訊息不見了。接著我們再檢視 stdout.txt 內容,如下:

student$ cat stdout.txt
-rw-r--r-- 1 student student 1.8K Aug 25 16:44 sample

由上例所知,透過 ls 列出 sample 物件的結果是一般輸出。

若是我們再多執行幾次,不管如何都會發現 stdout.txt 的內容都只會有一行,原因是 > 會先清空 stdout.txt,若不存在而對目標路徑又有權限的話,則該檔案會被產生。

要把後續的訊息附加到原檔案而不刪除原有內容的話,可以使用 >> 來處理。

然後透過下列指令刪除原有的 stdout.txt,然後連做 3 次輸出重導:

student$ rm sample

student$ ls -lh sample >> stdout.txt
student$ ls -lh sample >> stdout.txt
student$ ls -lh sample >> stdout.txt

接著檢視 stdout.txt 內容

student$ cat stdout.txt
-rw-r--r-- 1 student student 1.8K Aug 25 16:44 sample
-rw-r--r-- 1 student student 1.8K Aug 25 16:44 sample
-rw-r--r-- 1 student student 1.8K Aug 25 16:44 sample

管理 stderr

stdout 一樣,stderr 也是輸出的一種,但它是錯誤的訊息,所以要重導錯誤輸出的話可以透過代號 2 來進行訊息重導。

我們刻意使用 ls 列出一個不存在的檔案為 sample2,會得到下列的內容:

student$ ls sample2
ls: cannot access sample2: No such file or directory

透過下列方法,把上面的輸出轉到 stderr.txt

student$ ls sample2 2> stderr.txt

原本輸出在螢幕上的訊息現在不見了,這些訊息被存到 stderr.txt 裡,使用 cat 來檢視:

student$ cat stderr.txt 
ls: cannot access sample2: No such file or directory

與管理 stdout 一樣,若要附加錯誤內容的話,使用 2>> 就可以完成一樣的目標。

使用下列指令先刪除 stderr.txt 檔案後,再連做 3 次:

student$ rm stderr.txt

student$ ls sample2 2>> stderr.txt
student$ ls sample2 2>> stderr.txt
student$ ls sample2 2>> stderr.txt

然後再使用 cat 檢視:

student$ cat stderr.txt 
ls: cannot access sample2: No such file or directory
ls: cannot access sample2: No such file or directory
ls: cannot access sample2: No such file or directory

透過以上的練習,我們就可以把訊息進行分類。

整合訊息重導

經過上一節的練習,大部份都是單一類別的處理,不過在現實的管理作業中我們會有延伸應用,比如想要合併到同一檔案或是在同一指令進行描述,我們將在此進行練習。

因為程式運作中,可能會是 stdout 與 stderr 同時出現,若我們要在同一指令把這些輸出同時指定也是可以的。

使用 ls 列出檔案,如果檔案存在則轉存到 stdout.txt,若失敗則將訊息存到 stderr.txt,做法如下:

  1. 刪前先前的輸出檔案

    student$ rm stdout.xt stderr.txt
    
  2. 刻意列出不存在的檔案 sample2,並檢視相關檔案

    student$ ls sample2 > stdout.txt 2>stderr.txt
    

    顯示 stdout.txt,檔案內容為空。

    student$ cat stdout.txt
    

    顯示 stderr.txt,出現錯誤訊息。

    student$ cat stderr.txt
    ls: cannot access sample2: No such file or directory
    

若要把所有的訊息,不分類存到 log.txt 檔案中,其作法如下:

student$ ls sample2 > log.txt 2>&1

上述做法能夠把 stderr(2) 轉到 stdout(1),也就是 2>&1 來表示,由於 stdout 指定輸出到 log.txt,也就是 > log.txt 所表示。最後,不管指令中間的輸出什麼錯誤訊息都可以存到 log.txt 中。

結果如下:

student$ cat log.txt 
ls: cannot access sample2: No such file or directory

讓我們把上面的指令修改改為列出 sample 檔案,因為 sample 檔案是在的,所以會經由 > log.txt 輸出,因此內容會是 sample

student$ ls sample > log.txt 2>&1

student$ cat log.txt
sample

現在我們已經能夠把所有訊息在同一指令進行分拆或是整併到同一檔案中。同理在某些情境中我們更想要把這些內容以附加的方式進行儲存而不是清空後再存進去,在這種情境裡一樣可以使用 >> 完成。

我們使用 ls 列出檔案,不若其成功或失敗都以附加方式轉存到 log.txt

  1. 刪除原有的 log.txt

    student$ rm log.txt
    
  2. 轉存訊息到 log.txt

    student$ ls sample >> log.txt 2>&1
    student$ ls sample2 >> log.txt 2>&1
    
  3. 查看檔案

    student$ cat log.txt 
    sample
    ls: cannot access sample2: No such file or directory
    

上一篇
Day 12: 什麼是訊息重導
下一篇
Day 14: 管線應用
系列文
Linux 升華:初學者的探索到專家的洞察30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言