chặn tin nhắn stderr trong tập lệnh bash


48

Hãy xem xét tên tập lệnh (hơi ngớ ngẩn) sau đây 'test1.sh':

#/bin/bash
#
sleep 10 &
echo sleep pid = $!
pkill sleep

Khi tôi chạy nó, tôi không chỉ nhận được đầu ra của tiếng vang mà còn báo cáo về cái chết của giấc ngủ trên stderr:

$ ./test1.sh
sleep pid = 3551
./test1.sh: line 5:  3551 Terminated              sleep 10

Trong trường hợp này, tôi muốn loại bỏ bản in ra stderr. Tôi biết tôi có thể làm điều đó trên dòng lệnh, như trong:

$ ./test1.sh 2> /dev/null

... nhưng có cách nào để ngăn chặn nó từ trong kịch bản không? (Tôi biết rằng tôi có thể gói nó trong một tập lệnh thứ hai và có trình bao bọc chuyển hướng nó, nhưng phải có một cái gì đó dễ dàng hơn ...)


Bạn đã thử thêm chuyển hướng 2> / dev / null sau khi ngủ pkill chưa?
rahul

@rahul: vâng tôi đã làm - pkill không tạo ra tin nhắn, bash là.
sợ

Tôi đã sử dụng kill thay vì pkill và không nhận được stderr. lạ ..
rahul

@rahul: nó có thể là một thứ được xây dựng so với không được xây dựng không? Bạn đã thử nó với pkill chưa?
sợ hãi_fool

vâng, tôi tin là như vậy Tôi nhận được cùng một lỗi với pkill, nhưng không phải với kill. Trong khi sử dụng kill, tôi đã sử dụng pid thay vì tên Proc.
rahul

Câu trả lời:


72

Bạn đúng; pkill không tạo ra thông điệp, bash là. Bạn đề nghị rằng

$ ./test1.sh 2> /dev/null

là một giải pháp có thể. Như UVV chỉ ra, hành động tương đương từ trong kịch bản là

exec 2> /dev/null

Điều này chuyển hướng stderr cho kịch bản /dev/null từ câu lệnh này cho đến khi nó được thay đổi trở lại. Những cách vụng về để thay đổi nó trở lại bao gồm

exec 2> /dev/tty

mà chuyển hướng stderr đến thiết bị đầu cuối. Đây có lẽ là (nhưng không nhất thiết) nơi nó ban đầu.

Hoặc là

exec 2>&1

mà thiết lập thiết bị lỗi chuẩn giống như thiết bị xuất chuẩn và có khả năng sai.

Một cách đáng tin cậy hơn là

thực hiện 3> & 2
thực hiện 2> / dev / null
(làm những thứ mà bạn không muốn thấy thiết bị lỗi chuẩn.) 
exec 2> & 3

lưu stderr gốc trong mô tả tập tin 3, và sau đó khôi phục nó.

Các cách khác để ngăn chặn thông báo về cái chết của quá trình bao gồm

(sleep 10 & pkill sleep) 2> /dev/null

{ sleep 10 & pkill sleep;} 2> /dev/null

mà thay đổi stderr chỉ cho các lệnh được nhóm.


Đây là một câu trả lời tuyệt vời, chi tiết. Cảm ơn ngài!
Keenan Lawrence

Có bất kỳ nguy hiểm nào liên quan đến việc lưu stdinstderrmô tả tệp mới, gửi các mô tả gốc đến /dev/nullvà sau đó khôi phục chúng không?
Alexej Magura

Chà, tôi cho rằng, nếu bạn chạy một chương trình (không biết đến bạn) đã viết cho tập tin mô tả 3 (hoặc 4), thì hoạt động đó sẽ thất bại trong các trường hợp bình thường. Nhưng chương trình có thể được viết để bỏ qua thất bại và tiếp tục mà không báo cáo nó; sau đó bạn sẽ không bao giờ biết. Nhưng nếu bộ mô tả tệp 1 (hoặc 2) của bạn được đặt trên nền tảng mô tả tệp 3 (hoặc 4), thì chương trình đó sẽ đột nhiên được ghi vào thiết bị xuất chuẩn hoặc thiết bị xuất chuẩn của bạn. Nhưng đó là một ví dụ rất giả tạo, và vẫn còn nguy hiểm tối thiểu. Bạn đã có một cái gì đó trong tâm trí?
Scott

1
FWIW, tôi ủng hộ cách tiếp cận chỉ huy theo nhóm của Scott, tức là{ sleep 10 & pkill sleep;} 2> /dev/null
sợ hãi_fool

9

Theo đó bạn có thể làm một cái gì đó như sau:

#!/bin/bash
exec 2>/dev/null
ls -al test
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.