파일을 분할할 때 awk 오류 "리디렉션에 빈 문자열 값이 있습니다"

파일을 분할할 때 awk 오류 "리디렉션에 빈 문자열 값이 있습니다"

수세 리눅스에서는 느린 쿼리 로그를 매시간 분할하기 위해 다음 스크립트를 사용합니다.
이 오류를 해결하는 방법은 무엇입니까?

#!/bin/bash    
# split mysql slow query log by hour    
usage() {    
cat <<EOF
Usage: $0 [options]    
[REQUIRED]
-l
EOF
exit 1    
}    
while getopts "l:" opt; do
case $opt in
l) slowlog="$OPTARG" ;;
esac
done    
[ -z "$slowlog" ] && usage   
awk '{
if ($0~/^# Time*/) {
split($4, h, ":");
hour=h[1];
minute=h[2];
splitfile="mysql-slow.log-split-"substr($0, 9, 6)"-"hour".txt";
print $0 >> splitfile
} else {
print $0 >> splitfile
}
}' "$slowlog"

그러나 실행 중에 다음 오류가 발생합니다.

mysql@eudc-mysql-lx03:/mysql-work/chandra> sh -x test_slow.sh -l eudc-mysql-lx03-slow.log
+ getopts l: opt
+ case $opt in
+ slowlog=eudc-mysql-lx03-slow.log
+ getopts l: opt
+ '[' -z eudc-mysql-lx03-slow.log ']'
+ awk '{
if ($0~/^# Time*/) {
split($4, h, ":");
hour=h[1];
minute=h[2];
splitfile="mysql-slow.log-split-"substr($0, 9, 6)"-"hour".txt";
print $0 >> splitfile
} else {
print $0 >> splitfile
}
}' eudc-mysql-lx03-slow.log
awk: cmd. line:8: (FILENAME=eudc-mysql-lx03-slow.log FNR=1) fatal: expression for `>>' redirection has null string value

답변1

문제는 else명령문이 실행되기 전에 해당 명령문으로 분기하므로 주석에서 언급한 대로 if변수를 할당하기 전에 변수를 사용하고 있다는 것입니다 . splitline여기서 awk를 사용하는 유일한 이유는 시간이나 날짜가 증가할 때마다 날짜를 추출하고 다른 파일로 리디렉션하기 위한 것 같습니다. 귀하의 코드는 로그의 첫 번째 줄이 항상 타임스탬프임을 보장하는 경우에만 작동하지만, 그렇지 않은 것 같습니다. 처음 발견된 타임스탬프에서 로깅을 시작해야 합니다. 이를 위해 awk코드 조각을 간단히 조정하는 것이 좋습니다.

awk 'BEGIN{ date_found=0 }
     /^# Time/       { date_found=1 }
     date_found == 0 { continue }
     date_found == 1 {
       split($4, h, ":");
       hour=h[1];
       date=$3
       splitfile="mysql-slow.log-split-"date"-"hour".txt";
       date_found=2
     }
     {print $0 >> splitfile}' "$slowlog"

이 접근 방식의 단점: 대용량 로그 파일의 첫 번째 타임스탬프 이전에 로그 콘텐츠를 저장하지 않습니다. 첫 번째 분할 파일의 첫 번째 타임스탬프 이전에 행을 저장하려면 기본 awk 호출을 실행하기 전에 날짜를 추출해야 합니다. 조금 복잡해지지만 다음과 같이 할 수 있습니다.

first_date=$(awk '/^# Time/{print $3" "$4; exit}' "$slowlog")
awk -v init_date="$first_date" '
     BEGIN{ 
       split(init_date, a, " ")
       date=a[1]
       split(a[2], b, ":")
       hour=b[1] 
     }
     /^# Time/ {
       split($4, h, ":");
       hour=h[1];
       date=$3
     }
     {
       splitfile="mysql-slow.log-split-"date"-"hour".txt";
       print $0 >> splitfile
     }' "$slowlog"

두 솔루션 모두 질문에 표현한 요구 사항에 맞아야 합니다. 필요한 경우 코드에 대해 자유롭게 질문하세요.

관련 정보