Ẩn đầu ra của lệnh shell chỉ khi thành công?


12

Ẩn đầu ra của lệnh shell thường liên quan đến việc chuyển hướng stderr và stdout. Có bất kỳ tiện ích hoặc lệnh dựng sẵn nào mà theo mặc định ẩn đầu ra nhưng khi lỗi sẽ bỏ tất cả đầu ra tích lũy? Tôi muốn chạy cái này như một trình bao bọc cho các sshlệnh từ xa . Bây giờ tôi có chúng bằng cách sử dụng chuyển hướng nhưng tôi không hiểu được điều gì đã khiến chúng thất bại, và chúng quá dài dòng.

EDIT: Cuối cùng, tôi đã tạo mẫu sau dựa trên câu trả lời của @Belmin mà tôi đã điều chỉnh một chút để tích lũy tất cả các lệnh trước đó từ tập lệnh, sử dụng mã định danh quy trình hiện tại, tự động xóa nhật ký và thêm lỗi đỏ. tin nhắn khi có sự cố. Trong mẫu này, các trình silentbao bọc ban đầu sẽ thành công, sau đó thất bại lệnh thứ ba vì thư mục đã tồn tại:

#!/bin/sh

set -e

SILENT_LOG=/tmp/silent_log_$$.txt
trap "/bin/rm -f $SILENT_LOG" EXIT

function report_and_exit {
    cat "${SILENT_LOG}";
    echo "\033[91mError running command.\033[39m"
    exit 1;
}

function silent {
    $* 2>>"${SILENT_LOG}" >> "${SILENT_LOG}" || report_and_exit;
}

silent mkdir -v pepe
silent mkdir -v pepe2
silent mkdir -v pepe
silent mkdir -v pepe2

2
Nếu bạn chỉ chuyển hướng thiết bị xuất chuẩn, thiết bị lỗi chuẩn sẽ vẫn hiển thị; Điều này có đủ cho bạn không, hay bạn cũng muốn xem thiết bị xuất chuẩn nếu có lỗi?
Kromey

Tôi muốn nhìn thấy cả hai nhưng chỉ khi có sự cố xảy ra, nếu không tôi không muốn thấy gì cả.
Grzegorz Adam Hankiewicz

2
Những gì tôi làm là in stdout & stderr sang logfile để nó không làm lộn xộn màn hình. Tôi cũng in stderr vào màn hình, vì vậy nếu có và lỗi tôi có thể nhìn thấy nó. Nếu tôi cần chi tiết, tôi có thể kiểm tra logfile, chứa đầu ra chương trình và lỗi chương trình trong ngữ cảnh. Bằng cách này, tôi có thể "nhìn thấy cả hai nhưng chỉ khi có sự cố xảy ra". Không giúp đỡ à? Xem stackoverflow.com/questions/2871233/ từ
Stefan Lasiewski

1
Có an toàn để chuyển hướng stderr và stdout vào cùng một tệp với hai chuyển hướng riêng biệt không? Tôi nghĩ rằng chúng ta nên luôn luôn sử dụng 2>&1, đại loại như:$* >>"${SILENT_LOG}" 2>&1" || report_and_exit
psmith

Câu trả lời:


3

Tôi sẽ thiết lập một hàm bash như thế này:

function suppress { /bin/rm --force /tmp/suppress.out 2> /dev/null; ${1+"$@"} > /tmp/suppress.out 2>&1 || cat /tmp/suppress.out; /bin/rm /tmp/suppress.out; }

Sau đó, bạn có thể chạy lệnh:

suppress foo -a bar

Kẻ tấn công có quyền truy cập không root trên hệ thống của bạn, có thể cố gắng tạo liên kết tượng trưng giữa rm và lệnh gọi, nó sẽ trỏ đến /etc/passswdhoặc một số tệp quan trọng khác và ghi đè nội dung.
Mitar

1
BTW, thứ tự các chuyển hướng ở trên nên là: $* > /tmp/surpress.out 2>&1Điều này thực sự nắm bắt được thiết bị lỗi chuẩn.
Mitar

2
$*không phải là tốt nhất để xử lý đầu vào tùy ý. Đặc biệt là khi nó chứa khoảng trắng hoặc cờ. ${1+"$@"}
Di

Sửa đổi cho cả hai ý kiến. Cảm ơn --- thông tin tốt.
Belmin Fernandez


7

Nó phải đủ dễ dàng để viết một kịch bản cho mục đích này.

Một cái gì đó như kịch bản hoàn toàn chưa được kiểm tra.

OUTPUT=`tempfile`
program_we_want_to_capture &2>1 > $OUTPUT
[ $? -ne 0 ]; then
    cat $OUTPUT
    exit 1
fi
rm $OUTPUT

Mặt khác, đối với các lệnh tôi chạy như một phần của tập lệnh, tôi thường muốn một cái gì đó tốt hơn là chỉ đơn giản là in tất cả đầu ra. Tôi thường giới hạn những gì tôi nhìn thấy đến những điều chưa biết. Đây là một kịch bản tôi đã chuyển thể từ một cái gì đó tôi đọc hơn một thập kỷ trước.

#!/bin/bash

the_command 2>&1 | awk '
BEGIN \
{
  # Initialize our error-detection flag.
  ErrorDetected = 0
}
# Following are regex that will simply skip all lines
# which are good and we never want to see
/ Added UserList source/ || \
/ Added User/ || \
/ init domainlist / || \
/ init iplist / || \
/ init urllist / || \
/ loading dbfile / || \
/^$/ {next} # Uninteresting message.  Skip it.

# Following are lines that we good and we always want to see
/ INFO: ready for requests / \
{
  print "  " $0 # Expected message we want to see.
  next
}

# any remaining lines are unexpected, and probably error messages.  These will be printed out and highlighted.
{
  print "->" $0 # Unexpected message.  Print it
  ErrorDetected=1
}

END \
{
  if (ErrorDetected == 1) {
    print "Unexpected messages (\"->\") detected in execution."
    exit 2
  }
}
'
exit $?

5

Tôi không nghĩ có một cách sạch sẽ để làm điều này, điều duy nhất tôi có thể nghĩ là

  • Nắm bắt đầu ra của lệnh.
  • Kiểm tra giá trị trả về của lệnh và nếu thất bại
    • hiển thị đầu ra bị bắt.

Việc thực hiện điều này có thể là một dự án thú vị nhưng có lẽ vượt ra ngoài Q & A.


Nên được thực hiện với một chức năng. Hừm, để tôi thử xem.
Belmin Fernandez

1

đi ngắn với một cái gì đó như tehcommand &>/tmp/$$ || cat /tmp/$$

phụ thuộc bao nhiêu khả năng sử dụng / gõ bạn muốn / cần. (ví dụ: sử dụng nó như một đường ống hoặc truyền lệnh bằng đối số)

@zoredache kịch bản ngắn về cơ bản là một trình bao bọc trước cho việc này, nó sẽ mang lại sự mạnh mẽ hơn, xử lý đồng thời, v.v.


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.