我需要将来自 shell 脚本的所有输出/错误日志记录到具有标准格式的文件中。
例如文件 script.sh:
echo "I want to be a json message!"
echo "I also want to be a json message!"
执行如下:
./script.sh >> jsonmessages.log
应该给我一个文件内容,如:
{timestamp: '2020-12-31 00:00:00', message: 'I want to be a json message!'}
{timestamp: '2020-12-31 00:00:00', message: 'I also want to be a json message!'}
答案 0 :(得分:4)
将 shell 字符串可靠地转换为有效的 JSON 字符串的最佳选择是使用 JSON 解析器/格式化程序。最受欢迎的是jq
。
这是一个使用 jq
的带时间戳的 JSON 消息记录器的实现:
#!/usr/bin/env bash
json_logger() {
while read -r msg || [ -n "$msg" ]; do
jq \
-nc \
--arg msg "$msg" \
'{ "timestamp": (now | strftime("%Y-%m-%d %H:%M:%S")), "message": $msg }'
done
}
----------
编辑:
正如 KamilCuk 所写:
<块引用>我们可以在没有缓慢的 bash 循环的情况下做得更好 - 这只是 jq --raw-input '{ "timestamp": (now | strftime("%Y-%m-%d %H:%M:%S")), "message": . }'
所以这是一个改进的json_logger
:
json_logger() {
jq \
--raw-input \
--compact-output \
'{ "timestamp": (now | strftime("%Y-%m-%d %H:%M:%S")), "message": . }'
}
附录:
<块引用>例如,我需要在调用 json_logger 的 json 中打印方法名称。如何修改 json_logger 以及如何在 echo 中使用它?
如果作为参数提供给 json_logger
函数,这是一个添加方法名称的实现:
#!/usr/bin/env bash
IFS= read -r -d '' __JQ_LOGGER_SCRIPT <<'JQSCRIPT'
{
"timestamp": now | strftime("%Y-%m-%d %H:%M:%S"),
"message": .
} |
if ($name | length) != 0
then
. + { "method": $name }
else
.
end
JQSCRIPT
json_logger() {
jq \
--raw-input \
--compact-output \
--arg name "$1" \
"$__JQ_LOGGER_SCRIPT"
}
echo "I want to be a json message!" | json_logger
echo "I also want to be a json message!" | json_logger echo
printf %s $'I am a message with "quoted text" and some special characters: \'\t\7\42\\\'; that can only be properly converted to JSON with a JSON formatter and parser.' | json_logger printf
生成此 JSON 输出:
{"timestamp":"2021-01-29 14:02:46","message":"I want to be a json message!"}
{"timestamp":"2021-01-29 14:02:46","message":"I also want to be a json message!","method":"echo"}
{"timestamp":"2021-01-29 14:02:46","message":"I am a message with \"quoted text\" and some special characters: '\t\u0007\"\\'; that can only be properly converted to JSON with a JSON formatter and parser.","method":"printf"}
答案 1 :(得分:1)
./script.sh | awk -v squot="'" '{ print "{\"timestamp\": \""strftime("%Y-%m-%d %H:%M:%S")"\", \"message\": \""$0"\"}" }' mess | jq >> jsonmessages.log
使用 GNU awk,使用 awk 的 strftime 函数以所需格式打印时间戳,以及双引号和所需格式的其他数据。管道通过 jq 以确保有效的 json
答案 2 :(得分:1)
感谢您的解决方案。
我能够使用以下实现将脚本执行的日志写入日志文件:
创建一个 json 记录器
json_logger() {
# Values for json
current_timestamp="$(date +\"%Y-%m-%dT%H:%M:%S\")"
param1="$param1value"
param2="$param2value"
log_level=$1
script_name=$(basename $2 .sh)
# Create json and re-direct to log file
jq --raw-input --compact-output \
'{
"@timestamp": '$current_timestamp',
"parameter1": "'$param1'",
"parameter2": "'$param2'",
"log-level": "'$log_level'",
"logger": "'$script_name'",
"message": .
}' >> /var/log/app.log 2>&1
}
然后执行如下脚本
"script.sh" 2>&1 | json_logger "INFO" {job_name or script_name}