Chuyển hướng đầu ra tùy thuộc vào grep regex


8

Tôi đang sử dụng gradle runđể bắt đầu một máy chủ REST. Đầu ra của máy chủ REST trông như thế này:

XXX.XXX.XX.XXX - <moreinfo>
randomtext
randomtext
XXX.XXX.XX.XXX - <moreinfo>
XXX.XXX.XX.XXX - <moreinfo>
randomtext
XXX.XXX.XX.XXX - <moreinfo>

XXX.XXX.XX.XXXđây là một địa chỉ IP, Randomtext là các thông báo lỗi. Tất cả đầu ra được hướng đến thiết bị xuất chuẩn, thật đáng buồn.

Làm cách nào tôi có thể hướng tất cả các dòng bắt đầu bằng một địa chỉ IP đến một tệp được gọi err.logvà mọi dòng khác đến all.log?

Thật không may, gradle runchỉ có thể được khởi động một lần và không dừng lại, vì đó là máy chủ REST.

Có thể sử dụng một tee, grepkết hợp?

Câu trả lời:


8

Trong Bash, bạn có thể sử dụng thay thế quá trình bằng tee:

tee >(grep XXX > err.log) | grep -v XXX > all.log

Điều này sẽ đặt tất cả các dòng khớp với XXX vào err.logvà tất cả các dòng vào all.log. >( ... )tạo quá trình trong ngoặc đơn và kết nối đầu ra tiêu chuẩn của nó với một đường ống. Điều này hoạt động trong zsh và vỏ hiện đại khác quá.

Bạn cũng có thể sử dụng peelệnh từ moreutils :

pee "grep XXX > err.log" "grep -v XXX > all.log"

pee chuyển hướng đầu vào tiêu chuẩn cho nhiều lệnh ("tee for pipe").

Một thay thế khác là với awk:

awk '{ if (/^([0-9]{1,3}\.){3}[0-9]{1,3}/) { print > "err.log" } else { print > "all.log" } }'

Điều đó chỉ kiểm tra mọi dòng so với biểu thức và viết toàn bộ vào err.lognếu nó khớp và all.lognếu không.

Biểu thức chính quy awk cũng phù hợp grep -E(mặc dù nó phù hợp với một số địa chỉ xấu - 999.0.0.0v.v. - nhưng đó có lẽ không phải là vấn đề).


Hmm err.logtrống và tất cả đầu ra được chuyển hướng đến all.logsử dụng teelệnh trên.
polym

Kiểm tra xem biểu thức chính quy của bạn có thực sự khớp với các dòng đúng hay không - nếu err.logtồn tại thì lệnh đã chạy nhưng không có gì xuất hiện. grep -Evới biểu thức được sử dụng trong lệnh awk nên khớp, hoặc nó ở đây.
Michael Homer

À, tôi hiểu rồi. Bạn có thể sửa đổi câu hỏi của mình để all.logkhông chứa các dòng trùng khớp trong biểu thức grep không?
polym

Xong - không chắc bạn muốn cái nào, vì vậy tôi có cả hai.
Michael Homer

Oh xin lỗi, nó đã làm việc. Tôi ghi đè all.logerr.logvới một lệnh cũ. Xin lỗi vì sự nhầm lẫn. Cảm ơn, bạn thật tuyệt vời :)) !!
polym

4

Vì vậy, có vẻ như gradle runkhông phù hợp với tee, pee, grepvà io-chuyển hướng. Nó luôn dừng đọc sau 4096 byte.

Để khắc phục vấn đề này, tôi readtừng dòng gradle run. Tôi chưa kiểm tra nó, nhưng tôi đoán rằng đọc một dòng dài hơn 4k ký tự cũng sẽ thất bại.

Dù sao, đây là mã để giải quyết câu hỏi của tôi cụ thể:

#!/bin/bash
STDOUTLOG="/log/stdout.txt"
STDERRLOG="/log/stderr.txt"
while read -r line; do
    [[ $line =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.* ]] && printf '%s\n' "$line" >> "$STDERRLOG" && continue
    printf '%s\n' "$line" >> "$STDOUTLOG"
done < <(gradle run)

1
Bạn nên sử dụng read -r lineprintf '%s\n' "$line"để tránh một số trường hợp cạnh phá vỡ mọi thứ.
nyuszika7h

@ nyuszika7h Cảm ơn bạn! Tôi đã sửa đổi câu trả lời cho phù hợp :).
polym
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.