解决了:
几个月前,我对登录 shell 脚本产生了兴趣。
第一个想法是手动记录功能,如下所示:
add2log() {
printf "$(date)\tINFO\t%s\t%s\n" "$1" "$2" >>"$logPATH"
}
但我想自动化它,例如 STDERR 会自动记录。
已经有一段时间了,我找到了满意的答案,终于花时间分享了。
对于每个 shell 脚本,我现在使用一个“main.sh”来保存日志函数以及配置(设置日志和配置文件)。它看起来是这样的:
#!/bin/bash
###################################################################
# MY HEADERS
###################################################################
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~Global vars
mainScriptNAME=$(basename "$0")
mainScriptNAME="${mainScriptNAME%.*}"
mainScriptDIR=$(dirname "$0")
version="v0.0"
scriptsDIR="$mainScriptDIR/SCRIPTS"
addonsDIR="$mainScriptDIR/ADDONS"
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~LOGGER FUNCS
manualLogger() {
# $1=PRIORITY $2=FUNCNAME $3=message
printf "$(date)\t%s\t%s()\t%s\n" "$1" "$2" "$3" >>"$logFilePATH"
}
stdoutLogger() {
# $1=message
printf "$(date)\tSTDOUT\t%s\n" "$1" >>"$logFilePATH"
}
stderrLogger() {
# $1=message
printf "$(date)\tSTDERR\t%s\n" "$1" >>"$logFilePATH"
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~LOG & CONF
createLog() {
# code to set and touch logFilePATH & confFilePATH
manualLogger "INFO" "${FUNCNAME[0]}" "Log file created."
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~MAIN
#
createLog
#run scripts
{
#
source "$scriptsDIR/file1.sh"
doSomthing1
doSomthing2
#
source "$scriptsDIR/file2.sh"
anotherFunction1
anotherFunction2
...
} 2> >(while read -r line; do stderrLogger "$line"; done) \
1> >(while read -r line; do stdoutLogger "$line"; done)
换句话说:
- 我想要运行的所有脚本/函数都位于 ./SCRIPTS 文件夹中的单独文件中(所以我的 main.sh 几乎总是相同的)
- 我将所有这些脚本放在一个组 { ... } 中以捕获它们的 STDOUT 和 STDERR
- 它们的 STDOUT 和 STDERR 被重定向到各自的记录器函数
日志文件如下所示(一个手动记录器、一个 STDOUT 记录器、一个 STDERR 记录器的示例):
Lun 23 mai 2022 12:20:42 CEST INFO createLog() Log file created.
Lun 23 mai 2022 12:20:42 CEST STDOUT Some standard output
Lun 23 mai 2022 12:20:42 CEST STDERR ls: sadsdasd: No such file or directory
该小组将所有输出收集在日志中。相反,您显然可以根据需要对每个功能使用重定向2> >(while read ...
和。1> >(while read ...
例如doSomthing1
它的 STDOUT 和 STDERR 将记录,但doSomthing2
只有它的 STDERR 重定向。
答案1
从表面上看,您似乎只是添加了调试语句。这里的“重”是什么意思?在 Bash 脚本(或者更确切地说任何与此相关的编程语言)中,如果您需要回显某些内容,则需要有一个语句来告诉解释器echo
您已传递的内容。
如果您希望在脚本(或任何代码段)中的某个点执行操作,则没有什么可以替代编写命令。
您可以使用 IO 重定向来实现各种技巧,但您必须有两个语句 - 一个在开始,一个在结束,才能实现您想要的效果。
如果您想要完整记录脚本,请参阅set -x
。如果您只想记录脚本的某些函数,请set -x
在 suhshell 中使用这些函数。
(set -x; func1)
答案2
我在专用目录中使用标志文件:
foo.bash:
#!/bin/bash
[[ -f $HOME/.local/debug/foo.debug ]] && \
source $HOME/.local/debug/foo.debug
...
我可以在foo.debug
文件中放入任何我喜欢的内容,包括类似debug_foofunction=1
、 以及稍后的内容,foo
我foofunction
可以使用debug_foofunction
(小心 - 它可能未定义)来调用(或不调用)调试代码。
如果我简单地说rm $HOME/.local/debug/foo.debug
,所有调试代码都会被关闭。如果我将其更改为,debug_foofunction=0
我可以关闭foofunction
调试,同时保留其他调试设置(例如debug_foootherfunction=1
)。
阅读man bash
有关“ trap
”内置的内容。
真正的解决方案是不要编写复杂的脚本。使用适合您的问题集的编程语言。
始终将脚本粘贴到https://shellcheck.net
语法检查器中,或shellcheck
在本地安装。让使用成为shellcheck
您开发过程的一部分。