将多行字符串(utmpdump结果)转换为JSON [已关闭]

p5fdfcr1  于 2022-12-05  发布在  其他
关注(0)|答案(1)|浏览(94)

已关闭。此问题需要更多focused。当前不接受答案。
**想要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

18小时前关门了。
Improve this question
所有人,
这是我第一次提交堆栈溢出问题,所以提前感谢您花时间阅读/考虑我的问题。我目前正在使用'utmpdump'实用程序每小时从bash脚本转储linux身份验证日志结果,使用如下所示的语法完成:

dateLastHour=$(date +"%a %b %d %H:" -d '1 hour ago')

dateNow=$(date +"%a %b %d %H:")

utmpdump /var/log/wtmp* | awk "/$dateLastHour/,/$dateNow/"

我现在要完成的工作和这个问题的主题是在将每个身份验证事件转换为它自己的JSON文件以导出到外部syslog收集器进行额外分析和长期存储之前,我如何获取这些结果并为每个身份验证日志使用新行分隔它们?
作为一个例子,这里有一些我一直在使用的测试结果:

[7] [08579] [ts/0] [egecko] [pts/0       ] [10.0.2.6            ] [1.1.1.1       ] [Fri Nov 04 23:40:29 2022 EDT]
[8] [08579] [    ] [        ] [pts/0       ] [                    ] [0.0.0.0        ] [Fri Nov 04 23:55:16 2022 EDT]
[2] [00000] [~~  ] [reboot  ] [~           ] [3.10.0-1160.80.1.el7.x86_64] [0.0.0.0        ] [Sat Dec 03 12:28:05 2022 EST]
[5] [00811] [tty1] [        ] [tty1        ] [                    ] [0.0.0.0        ] [Sat Dec 03 12:28:12 2022 EST]
[6] [00811] [tty1] [LOGIN   ] [tty1        ] [                    ] [0.0.0.0        ] [Sat Dec 03 12:28:12 2022 EST]
[1] [00051] [~~  ] [runlevel] [~           ] [3.10.0-1160.80.1.el7.x86_64] [0.0.0.0        ] [Sat Dec 03 12:28:58 2022 EST]
[7] [02118] [ts/0] [egecko] [pts/0       ] [1.1.1.1            ] [1.1.1.1       ] [Sat Dec 03 12:51:22 2022 EST]

任何帮助或指针在这里是非常感谢!
我已经使用了以下SED命令来删除不必要的空格,并且我知道我可能应该做的是在使用括号作为分隔符之前使用IDF将结果字符串拆分为新的行:

utmpResults=$(echo "$utmpResults" | sed 's/  */ /g')

IFS="\n" read -a array <<< "$utmpResults"

echo $array

但是当我回显$array时,它只返回第一行...?

nue99wik

nue99wik1#

jq(sed代表json)的帮助下,这是一个简单的任务:

#!/bin/bash

jq -R -c '
  select(length > 0) |                           # remove empty lines
  [match("\\[(.*?)\\]"; "g").captures[].string   # find content within square brackets
   | sub("^\\s+";"") | sub("\\s+$";"")]          # trim content
  | {                                            # convert to json object
      "type"                 : .[0],
      "pid"                  : .[1],
      "terminal_name_suffix" : .[2],
      "user"                 : .[3],
      "tty"                  : .[4],
      "remote_hostname"      : .[5],
      "remote_host"          : .[6],
      "datetime"             : .[7],
      "timestamp"            : (.[7] | strptime("%a %b %d %T %Y %Z") | mktime)
    }' input.txt

输出

{"type":"7","pid":"08579","terminal_name_suffix":"ts/0","user":"egecko","tty":"pts/0","remote_hostname":"10.0.2.6","remote_host":"1.1.1.1","datetime":"Fri Nov 04 23:40:29 2022 EDT","timestamp":1667605229}
{"type":"8","pid":"08579","terminal_name_suffix":"","user":"","tty":"pts/0","remote_hostname":"","remote_host":"0.0.0.0","datetime":"Fri Nov 04 23:55:16 2022 EDT","timestamp":1667606116}
{"type":"2","pid":"00000","terminal_name_suffix":"~~","user":"reboot","tty":"~","remote_hostname":"3.10.0-1160.80.1.el7.x86_64","remote_host":"0.0.0.0","datetime":"Sat Dec 03 12:28:05 2022 EST","timestamp":1670070485}
{"type":"5","pid":"00811","terminal_name_suffix":"tty1","user":"","tty":"tty1","remote_hostname":"","remote_host":"0.0.0.0","datetime":"Sat Dec 03 12:28:12 2022 EST","timestamp":1670070492}
{"type":"6","pid":"00811","terminal_name_suffix":"tty1","user":"LOGIN","tty":"tty1","remote_hostname":"","remote_host":"0.0.0.0","datetime":"Sat Dec 03 12:28:12 2022 EST","timestamp":1670070492}
{"type":"1","pid":"00051","terminal_name_suffix":"~~","user":"runlevel","tty":"~","remote_hostname":"3.10.0-1160.80.1.el7.x86_64","remote_host":"0.0.0.0","datetime":"Sat Dec 03 12:28:58 2022 EST","timestamp":1670070538}
{"type":"7","pid":"02118","terminal_name_suffix":"ts/0","user":"egecko","tty":"pts/0","remote_hostname":"1.1.1.1","remote_host":"1.1.1.1","datetime":"Sat Dec 03 12:51:22 2022 EST","timestamp":1670071882}

如果不使用-c选项,则可以创建格式化输出。
要保存文件中的每一行,可以在bash中这样做。我选择了时间戳作为文件名。

INPUT_AS_JSON_LINES=$(
  jq -R -c '
     select(length > 0) |                           # remove empty lines
     [match("\\[(.*?)\\]"; "g").captures[].string   # find content within square brackets
      | sub("^\\s+";"") | sub("\\s+$";"")]          # trim content
     | {                                            # convert to json object
         "type"                 : .[0],
         "pid"                  : .[1],
         "terminal_name_suffix" : .[2],
         "user"                 : .[3],
         "tty"                  : .[4],
         "remote_hostname"      : .[5],
         "remote_host"          : .[6],
         "datetime"             : .[7],
         "timestamp"            : (.[7] | strptime("%a %b %d %T %Y %Z") | mktime)
       }' input.txt
  )

while read line
do
  FILENAME="$(jq '.timestamp' <<< "$line").json"
  CONTENT=$(jq <<< "$line")   # format json
  echo "writing file '$FILENAME'"
  echo "$CONTENT" > "$FILENAME"
done <<< "$INPUT_AS_JSON_LINES"

输出

writing file '1667605229.json'
writing file '1667606116.json'
writing file '1670070485.json'
writing file '1670070492.json'
writing file '1670070492.json'
writing file '1670070538.json'
writing file '1670071882.json'

相关问题