Mengarahkan output tergantung pada grep regex

8

Saya menggunakan gradle rununtuk memulai server REST. Output dari server REST terlihat seperti ini:

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.XXXdi sini adalah alamat IP, randomtext adalah pesan kesalahan. Sayangnya, semua output diarahkan ke stdout.

Bagaimana saya bisa mengarahkan semua baris yang dimulai dengan alamat IP ke file yang dipanggil err.logdan setiap baris lainnya all.log?

Sayangnya, gradle runhanya dapat dimulai sekali dan tidak berhenti, karena ini adalah server REST.

Mungkin menggunakan tee, grepkombinasi?

polym
sumber

Jawaban:

8

Di Bash, Anda dapat menggunakan subtitusi proses dengan tee:

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

Ini akan menempatkan semua baris yang cocok dengan XXX err.log, dan semua baris all.log. >( ... )menciptakan proses di dalam tanda kurung dan menghubungkan output standarnya ke sebuah pipa. Ini bekerja di zsh dan kerang modern lainnya juga.

Anda juga dapat menggunakan peeperintah dari moreutils :

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

pee mengalihkan input standar ke beberapa perintah ("tee for pipes").

Alternatif selanjutnya adalah dengan awk:

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

Itu hanya menguji setiap baris terhadap ekspresi dan menulis semuanya err.logjika cocok dan all.logjika tidak.

Ekspresi awk reguler juga cocok grep -E(meskipun cocok dengan beberapa alamat yang buruk - 999.0.0.0dan sebagainya - tapi itu mungkin bukan masalah).

Michael Homer
sumber
Hmm err.logkosong dan semua output diarahkan untuk all.logmenggunakan teeperintah di atas.
polym
Periksa bahwa ekspresi reguler Anda benar-benar cocok dengan garis yang benar - jika err.logada sama sekali maka perintah dijalankan tetapi tidak ada yang keluar. grep -Edengan ekspresi yang digunakan dalam perintah awk harus cocok, atau tidak di sini.
Michael Homer
Ah ok saya mengerti. Bisakah Anda memodifikasi pertanyaan Anda sehingga all.logtidak mengandung baris yang cocok dalam ekspresi grep?
polym
Selesai - tidak yakin yang mana yang Anda inginkan, jadi saya memiliki keduanya.
Michael Homer
Oh, maaf, itu berhasil. Saya menimpa all.logdan err.logdengan perintah lama. Maaf bila membingungkan. Terima kasih, Anda luar biasa :)) !!
Polym
4

Jadi, sepertinya gradle runtidak sesuai dengan tee, pee, grepdan io-redirection. Selalu berhenti membaca setelah 4096 byte.

Untuk menghindari masalah ini, saya readsetiap baris gradle run. Saya belum mengujinya, tapi saya rasa membaca baris yang lebih dari 4k karakter juga akan gagal.

Bagaimanapun, ini adalah kode untuk menyelesaikan pertanyaan saya secara khusus:

#!/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)
polym
sumber
1
Anda harus menggunakan read -r linedan printf '%s\n' "$line"untuk menghindari beberapa kasus tepi yang merusak barang.
nyuszika7h
@ nyuszika7h Terima kasih! Saya memodifikasi jawaban sesuai :).
polym