Làm thế nào để đầu ra đường ống từ quá trình này sang quá trình khác nhưng chỉ thực hiện nếu đầu tiên có đầu ra?


23

Làm thế nào tôi có thể viết lại lệnh này để chỉ email nếu có đầu ra từ mailq | grep?

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email

Điều này thậm chí có thể trên một dòng?

Xem Kiểm tra xem đường ống có trống không và chạy lệnh trên dữ liệu nếu không phải là trường hợp chung hơn là gửi email.


Câu trả lời:


19

Tôi nghĩ rằng bạn sẽ phải sử dụng tệp tạm thời cho thao tác này để bạn có thể sử dụng &&toán tử để chỉ chạy lệnh thư nếu grep trả về trạng thái thoát cho biết nó có khớp như sau:

TMPFILE=`mktemp /tmp/mailqgrep.XXXXXX`; mailq | egrep 'rejected|refused' -A5 -B5 > "$TMPFILE" && mail -s 'dd' email@email < "$TMPFILE"; rm "$TMPFILE"

Nếu bạn không bận tâm đến tệp tạm thời ở đâu đó và có thể sử dụng tên tĩnh cho nó, bạn có thể bỏ qua các công cụ đặt tên và xóa đặc biệt:

 mailq | egrep 'rejected|refused' -A5 -B5 > /tmp/mailqgrep && mail -s 'dd' email@email < /tmp/mailqgrep

Chỉnh sửa: Sau khi thấy câu trả lời của glenn, tôi đã chơi thêm một số điều này và rõ ràng việc gán một biến bằng $()cú pháp trả về mã thoát của lệnh, vì vậy bạn có thể bỏ qua bài kiểm tra mà anh ta đã sử dụng cho độ dài chuỗi và thay vào đó sử dụng. Đây là tất cả trong một lệnh:

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5) && mail -s 'dd' email@email <<< "$data"

Chỉnh sửa 2: Sau khi thấy câu trả lời của Simon, tôi đã xem mailchương trình của mình . Nó không hành xử theo cách anh ấy mô tả theo mặc định, nhưng có một tùy chọn cho điều đó. Từ trang người đàn ông:

-ENếu một tin nhắn gửi đi không chứa bất kỳ văn bản nào trong phần tin nhắn đầu tiên hoặc duy nhất của nó, đừng gửi nó mà hãy loại bỏ nó một cách im lặng, thiết lập hiệu quả biến Skipemptybody khi khởi động chương trình. Điều này rất hữu ích để gửi tin nhắn từ các tập lệnh được bắt đầu bởi cron (8).

Làm điều này có thể:

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -E -s 'dd' email@email

1
sức mạnh của sự hợp tác !!
glenn jackman

3
Tôi sẽ đề nghị câu trả lời này có thể được thực hiện tốt hơn bằng cách di chuyển giải pháp tốt nhất lên đầu.
Đánh dấu gian hàng

@Wildcard Việc chỉnh sửa đó là không cần thiết, với các tham số đầu vào mktempsẽ không trả về thứ cần trích dẫn.
Caleb

2
Tôi biết. Bạn là một trong số ít những người phiền muộn hiểu rằng trích dẫn đôi khi cần thiết (và bỏ qua chúng một cách có chủ ý). Tuy nhiên, mặc định nên được trích dẫn trừ khi bạn rõ ràng muốn gọi cho glob(split(var)). Bạn không cần chia từ hoặc mở rộng tập tin toàn cầu ở đây, vì vậy đừng hỏi họ. Ngoài ra, chúng tôi cần thể hiện đúng cách trên trang web này .
tự đại diện

@Wildcard Đủ công bằng. Tôi thường chạy zshvà thực sự không nhận được sự chia tách hoặc tách từ trong các trường hợp như thế này trừ khi tôi yêu cầu họ, nhưng vì câu trả lời ở đây và không biết môi trường mục tiêu trích dẫn ra khỏi nguyên tắc là tốt.
Caleb

11

Chương trình tiện ích ifne tồn tại rõ ràng cho mục đích này: để chạy lệnh nếu đầu vào tiêu chuẩn không trống.

mailq | egrep 'rejected|refused' -A 5 -B 5 | ifne mail -s 'dd' email@email

Lệnh ifne là một phần của gói moreutils , được coi là "một bộ công cụ Unix đang phát triển mà không ai nghĩ sẽ viết từ lâu, khi Unix còn trẻ."


8

Bạn có thể lưu đầu ra trong một biến và sau đó gọi lệnh mail nếu độ dài của chuỗi khác không.

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5)
[[ -n "$data" ]] && mail -s 'dd' email@email <<< "$data"

Đối với một dòng, tham gia hai lệnh với dấu chấm phẩy.


1
Đạo cụ để sử dụng một biến thay vì một tệp tạm thời. Điều này khiến tôi suy nghĩ về việc mã thoát đi từ lệnh mà bạn đã thực hiện gán biến, và rõ ràng nó được truyền vào! Xem câu trả lời cập nhật của tôi .
Caleb

7

Sử dụng mailvới -Etùy chọn. Trên máy Mac của tôi, MAIL (1) nói rằng -Ecờ sẽ không gửi email với một nội dung trống.

-E Đừng gửi tin nhắn với một cơ thể trống rỗng. Điều này rất hữu ích cho các lỗi đường ống từ các tập lệnh cron (8).

Trên máy Mac của tôi, tôi đã chạy thử nghiệm sau. Lưu ý rằng tệp file_does_existkhông tồn tại, nhưng tệp file_does__not_existkhông tồn tại.

Điều này sẽ gửi một email cho tôi:

$ ls file_does_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org

Điều này không có. Lưu ý rằng lệnh ls file_does_not_exist | egrep ...không tạo ra bất kỳ đầu ra.

$ ls file_does_not_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org
ls: file_does_not_exist: No such file or directory

Caleb đánh bại bạn với nó.
Gilles 'SO- ngừng trở nên xấu xa'

1
Anh ta chỉ đánh tôi được 4,75 giờ :). Tôi đã bỏ lỡ chi tiết này trong câu trả lời dài dòng của mình.
Stefan Lasiewski

5

Trong trường hợp cụ thể này, nếu bạn mailhỗ trợ-E tùy chọn , chỉ cần sử dụng nó. Trong trường hợp chung, bạn có thể cố gắng đọc một ký tự; nếu có, bắt đầu lệnh hậu xử lý và cung cấp cho nó ký tự đó từ phần còn lại của tệp.

pipe_if_not_empty () {
  a=$(dd bs=1 count=1 2>/dev/null; echo .)  # read at most one character
  if [ "$a" != "." ]; then                  # if there were two characters,
    { printf %s "${a%.}";                   # then output the first character
      cat; } |                              # and the rest of the input   
    "$@"                                    # into the specified program
  fi
}

mailq | egrep 'rejected|refused' -A 5 -B 5 |
pipe_if_not_empty mail -s 'dd' email@email

Lưu ý việc sử dụng hữu ích của cat . Việc bổ sung echo .làm cho chức năng này hoạt động ngay cả khi ký tự đầu tiên trong đầu vào là một dòng mới (hãy nhớ rằng $(…)cấu trúc dải mới thiết bị đầu cuối dải).

Với hầu hết các shell (bất cứ thứ gì khác ngoài zsh, theo như tôi biết), nếu tệp bắt đầu bằng ký tự null, mã này sẽ tin rằng nó trống. Sửa nó là một bài tập cho người đọc. (Gợi ý: sử dụng odtrong lớp con đầu tiên và printfđể in byte đầu tiên.) (Giải pháp: Cách kiểm tra xem ống có trống không ) Bạn có thể gặp vấn đề tương tự nếu tệp bắt đầu bằng một byte không phải là ký tự hợp lệ trong dòng điện miền địa phương; Điều đó dễ khắc phục hơn bằng cách chạy mã này với LC_ALL=C.


+1 cho sự lố bịch nhưng có thể hữu ích trong một kịch bản khác :) Vì tò mò, tại sao phải tiêm và kiểm tra dấu chấm thay vì kiểm tra chuỗi trống? Điều đó có gây ra vấn đề gì không nếu đầu vào bắt đầu bằng dấu chấm? Có thể sử dụng readgiúp đơn giản hóa điều này?
Caleb

@Caleb: Có, tôi nên đề cập rằng tôi đã trả lời câu hỏi trong tiêu đề và không phải là tình huống cụ thể. Xem chỉnh sửa của tôi để giải thích về dấu chấm. Tôi không nghĩ rằng bạn có thể phân biệt một dòng đầu tiên trống với một tệp trống với readsh di động (có thể có trong bash, ksh hoặc zsh).
Gilles 'SO- ngừng trở nên xấu xa'


1

Gần đây tôi đã biết về tên lệnh ifnelà một phần của moreutilsgói. Nơi bạn có thể sử dụng nó để giải quyết vấn đề cụ thể này.

ifne - Chạy lệnh nếu đầu vào tiêu chuẩn không trống

ví dụ từ trang người đàn ông,

EXAMPLE
       find . -name core | ifne mail -s "Core files found" root

0

Bạn có thể viết lại lệnh của mình bằng cách sử dụng test -s /dev/stdinđể kiểm tra xem có bất kỳ đầu ra nào từ mailq | grepphần đó không.

- mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email
+ mailq | egrep 'rejected|refused' -A 5 -B 5 | (test -s /dev/stdin && cat) | mail -s 'dd' email@email
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.