Có một công cụ Bash tiêu chuẩn hoạt động như echo nhưng xuất ra stderr chứ không phải stdout?
Tôi biết tôi có thể làm echo foo 1>&2
nhưng điều đó hơi xấu và, tôi nghi ngờ, dễ bị lỗi (ví dụ như nhiều khả năng bị chỉnh sửa sai khi mọi thứ thay đổi).
Có một công cụ Bash tiêu chuẩn hoạt động như echo nhưng xuất ra stderr chứ không phải stdout?
Tôi biết tôi có thể làm echo foo 1>&2
nhưng điều đó hơi xấu và, tôi nghi ngờ, dễ bị lỗi (ví dụ như nhiều khả năng bị chỉnh sửa sai khi mọi thứ thay đổi).
Câu trả lời:
Bạn có thể làm điều này, tạo điều kiện cho việc đọc:
>&2 echo "error"
>&2
sao chép mô tả tệp # 2 sang mô tả tệp # 1. Do đó, sau khi chuyển hướng này được thực hiện, cả hai bộ mô tả tệp sẽ tham chiếu đến cùng một tệp: mô tả một tệp # 2 ban đầu được đề cập đến. Để biết thêm thông tin, xem Hướng dẫn chuyển hướng minh họa Bash Hackers .
alias
tập lệnh shell. Có lẽ sẽ an toàn hơn khi sử dụngerrcho(){ >&2 echo $@; }
errcho(){ >&2 echo $@|pr -To5;}
sẽ không hoạt động. Để làm điều gì đó tương tự, bạn sẽ phải đặt chuyển hướng ở đâu đó sau đường ống cuối cùng như:errcho(){ echo $@|>&2 pr -To5;}
Bạn có thể định nghĩa một hàm:
echoerr() { echo "$@" 1>&2; }
echoerr hello world
Điều này sẽ nhanh hơn một kịch bản và không có phụ thuộc.
Gợi ý cụ thể về bash của Camilo Martin sử dụng "chuỗi ở đây" và sẽ in bất cứ thứ gì bạn chuyển đến nó, bao gồm cả các đối số (-n) mà tiếng vang thường sẽ nuốt:
echoerr() { cat <<< "$@" 1>&2; }
Giải pháp của Glenn Jackman cũng tránh được vấn đề nuốt phải tranh luận:
echoerr() { printf "%s\n" "$*" >&2; }
echoerr -ne xt
sẽ không in "-ne xt". Sử dụng tốt hơn printf
cho điều đó.
echoerr() { cat <<< "$@" 1>&2; }
printf "%s\n" "$*" >&2
$IFS
khoảng trắng được gửi như một lý lẽ riêng, mà trong trường hợp echo
phương tiện concatenating chúng với 0x20
s, nhưng sự nguy hiểm của không trích dẫn xa outweight sự tiện lợi của 2 nhân vật ít hơn để gõ) .
Vì 1
là đầu ra tiêu chuẩn, bạn không cần phải đặt tên rõ ràng trước một chuyển hướng đầu ra như thế >
mà thay vào đó có thể chỉ cần gõ:
echo Thông báo này đi tới stderr> & 2
Vì bạn có vẻ lo lắng rằng 1>&2
bạn sẽ khó có thể gõ một cách đáng tin cậy, nên việc loại bỏ dư thừa 1
có thể là một sự khích lệ nhỏ đối với bạn!
Một lựa chọn khác
echo foo >>/dev/stderr
foo
- có chuyển hướng stderr của riêng nó - ví dụ foo >foo.log 2>&1
- sau đó echo foo >/dev/stderr
sẽ ghi đè tất cả đầu ra trước nó. >>
nên được sử dụng thay thế:echo foo >>/dev/stderr
/dev/fd/2
.
/proc/self/fd/2
. Xem câu trả lời của tôi dưới đây :)
Không, đó là cách tiêu chuẩn để làm điều đó. Nó không gây ra lỗi.
1>&2
. Tất cả chúng ta đều mong muốn điều này sẽ không xảy ra, nhưng tôi chắc chắn rằng tất cả chúng ta đều là những nơi nó xảy ra.
( echo something 1>&2 ; something else ) > log
-> (echo something; cp some junk 1>&2 ; something else) > log
Rất tiếc.
Nếu bạn không nhớ đăng nhập tin nhắn vào syslog, cách not_so_ugly là:
logger -s $msg
Tùy chọn -s có nghĩa là: "Xuất thông báo thành lỗi tiêu chuẩn cũng như nhật ký hệ thống."
Đây là một hàm STDERR đơn giản, giúp chuyển hướng đầu vào đường ống thành STDERR.
#!/bin/bash
# *************************************************************
# This function redirect the pipe input to STDERR.
#
# @param stream
# @return string
#
function STDERR () {
cat - 1>&2
}
# remove the directory /bubu
if rm /bubu 2>/dev/null; then
echo "Bubu is gone."
else
echo "Has anyone seen Bubu?" | STDERR
fi
# run the bubu.sh and redirect you output
tux@earth:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err
echo what | /dev/stderr
...
Lưu ý: Tôi đang trả lời bài đăng - không phải câu hỏi "tiếng vang" mơ hồ / đầu ra cho thiết bị lỗi chuẩn (đã được OP trả lời).
Sử dụng một chức năng để hiển thị ý định và nguồn thực hiện bạn muốn. Ví dụ
#!/bin/bash
[ -x error_handling ] && . error_handling
filename="foobar.txt"
config_error $filename "invalid value!"
output_xml_error "No such account"
debug_output "Skipping cache"
log_error "Timeout downloading archive"
notify_admin "Out of disk space!"
fatal "failed to open logger!"
Và error_handling
được:
ADMIN_EMAIL=root@localhost
config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }
output_xml_error() { echo "<error>$*</error>" 2>&1; }
debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }
log_error() { logger -s "$*"; }
fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }
notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }
Những lý do xử lý mối quan tâm trong OP:
Những lý do khác:
Đề xuất của tôi:
echo "my errz" >> /proc/self/fd/2
hoặc là
echo "my errz" >> /dev/stderr
echo "my errz" > /proc/self/fd/2
sẽ hiệu quả đầu ra stderr
vì /proc/self
là một liên kết đến các quá trình hiện tại, và /proc/self/fd
giữ quá trình mở file descriptor, và sau đó, 0
, 1
, và 2
đại diện cho stdin
, stdout
và stderr
tương ứng.
Các /proc/self
liên kết không hoạt động trên hệ điều hành MacOS, tuy nhiên, /proc/self/fd/*
hiện có sẵn trên Termux trên Android, nhưng không phải /dev/stderr
. Làm thế nào để phát hiện HĐH từ tập lệnh Bash? có thể giúp đỡ nếu bạn cần làm cho tập lệnh của mình dễ di chuyển hơn bằng cách xác định biến thể nào sẽ sử dụng.
/proc/self
liên kết không hoạt động trên hệ điều hành MacOS, vì vậy tôi sẽ gắn bó với các chi tiết thẳng về phía trước /dev/stderr
phương pháp. Ngoài ra, như đã lưu ý trong các câu trả lời / nhận xét khác, có lẽ tốt hơn là sử dụng >>
để chắp thêm.
/proc/self/fd/*
có sẵn trên Termux trên Android, nhưng không /dev/stderr
.
Đừng sử dụng cat
như một số được đề cập ở đây. cat
là một chương trình
trong khi echo
và printf
là các nội trang bash (shell). Khởi chạy một chương trình hoặc một tập lệnh khác (cũng được đề cập ở trên) có nghĩa là tạo ra một quy trình mới với tất cả chi phí. Sử dụng các nội trang, các hàm viết khá rẻ, vì không cần phải tạo (thực thi) một quy trình (môi trường).
Các opner hỏi "có công cụ tiêu chuẩn nào để xuất ( ống ) thành stderr không", câu trả lời schort là: KHÔNG ... tại sao? ... ống dẫn rediredcting là một khái niệm ưu tú trong các hệ thống như unix (Linux ...) và bash (sh) xây dựng trên các khái niệm này.
Tôi đồng ý với người mở rằng chuyển hướng với các ký hiệu như thế này: &2>1
không dễ chịu cho các lập trình viên hiện đại, nhưng đó là bash. Bash không có ý định viết các chương trình lớn và mạnh mẽ, nó nhằm mục đích giúp các quản trị viên đến đó làm việc với ít phím bấm hơn ;-)
Và ít nhất, bạn có thể đặt chuyển hướng bất cứ nơi nào trong dòng:
$ echo This message >&2 goes to stderr
This message goes to stderr
cat
và hướng dẫn ai đó không sử dụng mèo vì nó chậm. Có vô số trường hợp sử dụng trong đó mèo là lựa chọn đúng đắn, vì vậy đó là lý do tại sao tôi phản đối câu trả lời của bạn.
echo
thay thế. Ngay cả khi anh ta sử dụng cat
, anh ta phải sử dụng chuyển hướng bash. dù sao. Vì vậy, hoàn toàn không có ý nghĩa để sử dụng cat
ở đây. BTW Tôi sử dụng cat
100 lần một ngày, nhưng không bao giờ trong bối cảnh người mở yêu cầu ... bạn hiểu chứ?
Một lựa chọn khác mà tôi gần đây vấp phải là:
{
echo "First error line"
echo "Second error line"
echo "Third error line"
} >&2
Điều này chỉ sử dụng các hàm dựng sẵn của Bash trong khi làm cho đầu ra lỗi nhiều dòng ít bị lỗi hơn (vì bạn không phải nhớ thêm &>2
vào mỗi dòng).
cat
hoặc bất kỳ tiện ích nào khác, không có chủ đề cho câu hỏi.
read
là một lệnh dựng sẵn shell in ra stderr và có thể được sử dụng như echo mà không cần thực hiện các thủ thuật chuyển hướng:
read -t 0.1 -p "This will be sent to stderr"
Thời -t 0.1
gian chờ là vô hiệu hóa chức năng chính của đọc, lưu trữ một dòng stdin vào một biến.
Tạo kịch bản
#!/bin/sh
echo $* 1>&2
đó sẽ là công cụ của bạn
Hoặc tạo một chức năng nếu bạn không muốn có một tập lệnh trong tệp riêng biệt.
Mac OS X: Tôi đã thử câu trả lời được chấp nhận và một vài câu trả lời khác và tất cả chúng đều dẫn đến việc viết STDOUT không STDERR trên máy Mac của tôi.
Đây là một cách di động để ghi vào lỗi tiêu chuẩn bằng Perl:
echo WARNING! | perl -ne 'print STDERR'