Nếu bạn bao giờ dùng pipe (ống dẫn) và chuyển hướng (redirections) dưới shell Linux, rất có thể bạn cũng sẽ đôi khi cần dùng tiện ích tee.
Làm Gì Của Tee?
Một lệnh như
ls
sẽ hiển thị nội dung thư mục hiện tại. Nói cách khác, nó hiển thị nội dung này đến stdout (đầu ra chuẩn), thường là màn hình của bạn, hoặc chính xác hơn, hiển thị terminal ảo.
Một lệnh như
ls > file123
sẽ không hiển thị gì trên màn hình. Đó là vì dấu > chuyển hướng tất cả đầu ra đến một tệp thay vì hiển thị ra stdout. file123 bây giờ sẽ được lấp đầy nội dung trước đây hiển thị trên màn hình.
Để hiển thị nội dung thư mục trên màn hình VÀ ghi vào tệp, bạn cần hai lệnh. Với tee bạn có thể làm cả hai cùng lúc.
ls | tee file123
Tại Sao Dùng Tee Nếu Bạn Có Thể Chạy Lệnh Tương Tự Hai Lần?
Trong ví dụ trên, bạn rõ ràng không cần tee nếu bạn có thể thực thi ls bình thường và sau đó thực thi lại và chuyển hướng đầu ra đến tệp. Tuy nhiên, bạn sẽ gặp tình huống đầu ra là duy nhất. Hãy tưởng tượng kịch bản bạn cố gắng chẩn đoán vấn đề. Bạn chạy diagnose | tee error.log. Lỗi bạn nhận được có thể là duy nhất. Bạn muốn chúng hiển thị trên màn hình để thấy chuyện gì xảy ra khi bạn test. Nhưng bạn cũng muốn lưu lỗi đó vào tệp, để xem lại sau hoặc dán đầu ra lên diễn đàn hỏi mọi người.
Một tình huống khác, thường gặp, khi bạn có thể cần tee, là: bạn muốn ghi đầu ra của lệnh đến vị trí chỉ user root mới đọc/ghi được. Điều này sẽ không hoạt động.
/sbin/blkid > /root/somefile
Sau đó, bạn có thể nghĩ, "Tất nhiên, chỉ cần dùng sudo!" Và bạn sẽ ngạc nhiên điều đó cũng không hoạt động:
sudo blkid > /root/somefile
Đó là vì sau khi sudo blkid thực thi, bạn vẫn đăng nhập như user thường, non-root. Và shell (thường là bash), cố ghi vào /root/somefile với thông tin user thường. Để giải quyết, bạn dùng tee:
/sbin/blkid | sudo tee /root/somefile
Ghi Thêm Văn Bản Và Chuyển Hướng Lỗi
tee là lệnh hữu ích nhưng đơn giản; command | tee somefile cơ bản sẽ đủ hầu hết thời gian. Tuy nhiên, có hai kịch bản bạn có thể gặp cần mẹo này.
Thứ nhất, tee mặc định luôn ghi đè tệp. Nếu bạn chạy
ls | tee somefile
rồi
ls /tmp | tee somefile
lệnh thứ hai sẽ ghi đè nội dung somefile, và bạn chỉ thấy nội dung lệnh cuối cùng. Để thay đổi hành vi này, bạn làm cho tee ghi thêm (append) thay vì ghi đè. Để làm vậy, chỉ dùng cờ -a.
ls | tee -a somefile
Thứ hai, không phải đầu ra nào cũng giống nhau. Thông báo lỗi được xử lý khác, và dù chúng xuất hiện trên màn hình, chúng không được coi là stdout, nên chúng không bị bắt bởi tee. (Chúng được coi là stderr.) Đây là ví dụ trên grep.
grep -r L2TP /etc | tee somefile
Nó sẽ hiển thị như hình sau.

Thông báo "Permission denied" được ghi vào stderr. Chỉ có văn bản được highlight mới được ghi vào stdout. Đó là lý do bạn sẽ thấy nội dung "somefile" như hình dưới.

Trong trường hợp này, grep dùng để tìm văn bản, nó hữu ích là thông báo lỗi không bị chuyển hướng đến tệp. Chúng chỉ sẽ lấp đầy tệp bằng rác không cần thiết. Bạn chỉ muốn thấy kết quả tìm thấy. Nhưng khi bạn cần thông báo lỗi, dùng 2>&1, chuyển hướng stderr đến stdout.
grep -r L2TP /etc 2>&1 | tee somefile
Với lệnh này bạn sẽ thấy somefile bây giờ cũng chứa thông báo lỗi.
Kết Luận
Hy vọng hướng dẫn này bao gồm mọi thứ bạn cần để tận dụng tối đa lệnh tee. Nhưng nếu bạn gặp tình huống bị kẹt với tee, hãy để lại bình luận bên dưới, chúng tôi có thể giúp.