REST 서버를 시작하는 데 사용합니다 gradle run
. REST 서버의 출력은 다음과 같습니다.
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
이것은 IP 주소이고 임의의 텍스트는 오류 메시지입니다. 불행히도 모든 출력은 표준 출력으로 지정됩니다.
IP 주소로 시작하는 모든 줄을 파일 이름 err.log
과 다른 모든 줄로 어떻게 지정할 수 있습니까 all.log
?
아쉽게도 gradle run
REST 서버이기 때문에 한 번만 시작할 수 있고 중지할 수 없습니다.
어쩌면 조합 tee
을 사용할까요 grep
?
답변1
Bash에서는 다음을 사용할 수 있습니다.프로세스 교체티셔츠 포함:
tee >(grep XXX > err.log) | grep -v XXX > all.log
그러면 XXX와 일치하는 모든 줄이 입력 err.log
되고 모든 줄이 all.log
. >( ... )
괄호 안에 프로세스를 만들고 표준 출력을 파이프에 연결합니다. 이는 다음에 적용됩니다.嘚다른 현대 껍질이 있습니다.
pee
다음 명령을 사용할 수도 있습니다.더 많은 유틸리티:
pee "grep XXX > err.log" "grep -v XXX > all.log"
pee
표준 입력을 여러 명령("파이프 티")으로 리디렉션합니다.
또 다른 옵션은 awk를 사용하는 것입니다.
awk '{ if (/^([0-9]{1,3}\.){3}[0-9]{1,3}/) { print > "err.log" } else { print > "all.log" } }'
이는 표현식에 대해 각 행을 테스트하고 일치하는지 여부 err.log
에 관계없이 전체 내용을 작성합니다 all.log
.
awk 정규식도 적합합니다 grep -E
(일부 잘못된 주소와 일치하지만( 999.0.0.0
등등)) 아마도 문제가 되지 않을 것입니다.
답변2
따라서 , io 리디렉션을 gradle run
준수하지 않는 것으로 보입니다 tee
. 4096바이트 이후에는 항상 읽기가 중지됩니다.pee
grep
이 문제를 피하기 위해 read
각 줄을 분리하려고 합니다 gradle run
. 아직 테스트하지는 않았지만 4k 문자보다 긴 줄을 읽는 것도 실패할 것이라고 추측합니다.
어쨌든 내 문제를 구체적으로 해결한 코드는 다음과 같습니다.
#!/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)