ファイルを分割すると、awkエラー「リ​​ダイレクトに空の文字列値があります」

ファイルを分割すると、awkエラー「リ​​ダイレクトに空の文字列値があります」

Suse Linuxでは、遅いクエリログを毎時間分割するために、次のスクリプトを使用します。
このエラーを解決するには?

#!/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"

どちらのソリューションも、質問に示した要件に合う必要があります。必要に応じてコードについて自由に質問してください。

関連情報