【发布时间】:2018-11-28 16:29:45
【问题描述】:
我遇到了需要用于日志分析的脚本的问题;让我解释一下这个问题:
我有一个像这样的 gzip 文件:
5555_prova.log.gz
文件里面有这样的mali日志行:
2018-06-12 03:34:31 95.245.15.135 GET /hls.playready.vod.mediasetpremium/farmunica/2018/06/218742_163f10da04c7d2/hlsrc/w12/21.ts
我需要一个脚本来读取 gzip 压缩的日志文件,该文件能够在标准输出上输出修改后的日志行,如下所示:
5555 2018-06-12 03:34:31 95.245.15.135 GET /hls.playready.vod.mediasetpremium/farmunica/2018/06/218742_163f10da04c7d2/hlsrc/w12/21.ts
如您所见,日志行现在以从 gzip 文件名中读取的数字开始。 我需要这条新线路来提供 logstash 数据处理链。
我试过这样的脚本:
echo "./5555_prova.log.gz" | xargs -ISTR -t -r sh -c "gunzip -c STR | awk '{$0="5555 "$0}' "
这不是我所需要的(前缀是静态的,不是用文件名中的正则表达式捕获的)但即使使用这个简化版本,我也会收到错误:
sh -c gunzip -c ./5555_prova.log.gz | awk '{-bash=5555 -bash}'
-bash}' : -c: line 0: unexpected EOF while looking for matching `''
-bash}' : -c: line 1: syntax error: unexpected end of file
从上面的输出中可以看出,$0 不再是通过管道传递给 awk 的整行,而是一个奇怪的-bash。
我需要使用 xargs,因为 gzip 压缩文件的列表是从另一个工具(即实例化的 inotifywait 监听通过 ftp 写入文件的目录)提供给命令行的。
我错过了什么?你有什么建议可以为我指明正确的方向吗?
问候, S.
尝试遵循@Charles Duffy 的建议,我编写了这段代码:
#/bin/bash
#
# Usage: sendToLogstash.sh [pattern]
#
# Executes a command whenever files matching the pattern are closed in write
# mode or moved to. "{}" in the command is replaced with the matching filename (via xargs).
# Requires inotifywait from inotify-tools.
#
# For example,
#
# whenever.sh '/usr/local/myfiles/'
#
#
DIR="$1"
PATTERN="\.gz$"
script=$(cat <<'EOF'
awk -v filename="$file" 'BEGIN{split(filename,array,"_")}{$0=array[1] OFS $0} 1' < $(gunzip -dc "$DIR/$file")
EOF
)
inotifywait -q --format '%f' -m -r -e close_write -e moved_to "$DIR" \
| grep --line-buffered $PATTERN | xargs -I{} -r sh -c "file={}; $script"
但我得到了错误:
[root@ms-felogstash ~]# ./test.sh ./poppo
gzip: /1111_test.log.gz: No such file or directory
gzip: /1111_test.log.gz: No such file or directory
sh: $(gunzip -dc "$DIR/$file"): ambiguous redirect
感谢您的帮助,我在编写 bash 脚本时感到很失落。
问候, S.
【问题讨论】:
-
你有嵌套引号,bash 不明白。它认为您的
"gunzip...引用以'{$0="结尾并且因为您有 1 个单引号而感到困惑。 -
您的内部单引号是文字,而不是句法,因此在将内容传递给
awk之前,它们不会阻止$0被 shell 替换。 (当由 bash 而不是 awk 解释时,$0按照惯例/默认是当前脚本的名称;对于交互式解释器,该名称是-bash。