Bash コマンド find、exec、および grep が正しく動作しません。何が問題ですか?

Bash コマンド find、exec、および grep が正しく動作しません。何が問題ですか?

ALARM / FATALキーワードを使用して、私のログファイルを別のバックアップファイルにフィルタリングしたいと思います。次の2つのファイルがあるとしましょう。

[root@TENCENT64 /tmp/test]# cat test_ccd.log 
ccd0.log:01-28 09:33:18:461 1254 F NORMAL
ccd0.log:01-28 09:33:18:461 1254 F FATAL 
ccd0.log:01-28 09:34:30:827 1254 E ALARM
[root@TENCENT64 /tmp/test]# cat test_mcd.log 
mcd0.log:01-29 09:33:18:461 1254 F NORMAL
mcd0.log:01-29 09:33:18:461 1254 F FATAL 
mcd0.log:01-29 09:34:30:827 1254 E ALARM

次のバックアップファイルを作成したい

[root@TENCENT64 /tmp/test]# cat test_ccd.log.txt
ccd0.log:01-28 09:33:18:461 1254 F FATAL 
ccd0.log:01-28 09:34:30:827 1254 E ALARM
[root@TENCENT64 /tmp/test]# cat test_mcd.log.txt
mcd0.log:01-29 09:33:18:461 1254 F FATAL 
mcd0.log:01-29 09:34:30:827 1254 E ALARM

これを達成するために次のコマンドを試しましたが、そのうちの何も動作しませんでした。誰もが私が間違っている部分を修正するのを助けることができますか?

[root@TENCENT64 /tmp/test]# cat /etc/redhat-release 
CentOS Linux release 7.2 (Final)

# this commands hangs for ever
[root@TENCENT64 /tmp/test]# find . -name "*.log" -type f -exec sh -c 'grep -E "ALARM|FATA:" 1>>"$0.txt"' {} \;

# this commands reports the error and the output was missed up
[root@TENCENT64 /tmp/test]# find . -name "*.log" -type f -exec sh -c 'grep -R -E "ALARM|FATA:" 1>>"$0.txt"' {} \;
grep: input file ‘test_mcd.log.txt’ is also the output
grep: input file ‘test_ccd.log.txt’ is also the output

# the output for each file is not correct
[root@TENCENT64 /tmp/test]# cat test_mcd.log.txt
test_mcd.log:mcd0.log:01-29 09:34:30:827 1254 E ALARM
test_ccd.log:ccd0.log:01-28 09:34:30:827 1254 E ALARM
[root@TENCENT64 /tmp/test]# cat test_ccd.log.txt
test_mcd.log:mcd0.log:01-29 09:34:30:827 1254 E ALARM
test_ccd.log:ccd0.log:01-28 09:34:30:827 1254 E ALARM
test_mcd.log.txt:test_mcd.log:mcd0.log:01-29 09:34:30:827 1254 E ALARM
test_mcd.log.txt:test_ccd.log:ccd0.log:01-28 09:34:30:827 1254 E ALARM

次のコードを使用してバックアップ警告を別の場所に保存しようとすると、状況が複雑になります。バックアップアラートを保存するNFS共有があり、各アラートは共有のフォルダ(IPアドレス名にちなんで名前付け)に個別に保存されます。以下は私のコマンドです

# create the backed folder on the NFS share, like /data/backup/1.1.1.1/alarm_history
ip=`hostname -I|awk '{print $1}'` && mkdir -p /data/backup/${ip}/alarm_history

# iterate through /data/backup/1.1.1.1 to find all the alarms and persist into /data/backup/1.1.1.1/alarm_history, /data/backup is a shared base and 1.1.1.1 is mounted on the current server
ip=`hostname -I|awk '{print $1}'` && find /data/backup/${ip} -name '*.log' -type f -exec sh -c '
    grep -E "ALARM|FATAL" "$1" >> "/data/backup/${ip}/alarm_history/$1.alarm" && sort -o "/data/backup/${ip}/alarm_history/$1.alarm" -u "/data/backup/${ip}/alarm_history/$1.alarm"
' 'find-sh' {} \;

2 つのエラーが発生します。

find-sh: line 1: /data/backup//alarm_history//data/backup/11.62.17.249/manager/manager_mcd0.log.alarm: No such file or directory
find-sh: line 1: /data/backup//alarm_history//data/backup/11.62.17.249/manager/manager_mcd0_stat.log.alarm: No such file or directory

2つの問題があります。 1. "find"コマンドに渡された$ {ip}はgrepによって認識されません。 2. $1.alarm, $1 は grep の絶対パスです。基本名はどのようにわかりますか?

ベストアンサー1

grepパラメータが欠落しており、期待される結果を得るにはパラメータ:が必要です。L

grep -E "ALARM|FATA:" 1>> "$0.txt"

しなければならない

grep -E "ALARM|FATAL" "$0" > "$0.txt"

(または結果を既存のファイルに追加するには、>>または使用)1>>


$0コマンド名と場所パラメータはで始まる必要があるため、名前$1を追加して結果を$1スクリプトに渡すことができます。

find . -name '*.log' -type f -exec sh -c '
    grep -E "ALARM|FATAL" "$1" > "$1.txt"
' 'find-sh' {} \;

shまたは、できるだけ少ない呼び出しを使用して結果を繰り返します{} +

find . -name '*.log' -type f -exec sh -c '
    for file; do
        grep -E "ALARM|FATAL" "$file" > "${file}.txt"
    done
' 'find-sh' {} +

編集する:

最初の引数としてスクリプトに渡されるターゲットディレクトリの変数を追加しました。生成されたログファイルをソートするために一時ファイルを使用します。

ip=$(hostname -I | awk '{ print $1 }')
targetdir="/data/backup/$ip/alarm_history"
mkdir -p "$targetdir"

find "/data/backup/$ip" -name '*.log' -type f -exec sh -c '
    targetdir=$1; shift

    for file; do
            # extract the log filename from the path, append ".alarm", prepend directory
            targetfile=${targetdir}/${file##*/}.alarm

            grep -E "ALARM|FATAL" "$file" >> "$targetfile" \
                && mv "$targetfile" "${targetfile}.tmp" \
                && sort -o "$targetfile" -u "${targetfile}.tmp" \
                && rm "${targetfile}.tmp"
    done
' 'find-sh' "$targetdir" {} +

おすすめ記事