与Bash中的_文件和_行相当
bash中是否有任何变量包含执行的.sh文件的名称?线路号也会很好 我想在错误消息中使用它,例如:与Bash中的_文件和_行相当,bash,error-handling,environment-variables,Bash,Error Handling,Environment Variables,bash中是否有任何变量包含执行的.sh文件的名称?线路号也会很好 我想在错误消息中使用它,例如: echo "ERROR: [$FILE:L$LINE] $somefile not found" 当前行号的$LINENO 当前文件的$0。我使用basename确保只获取文件名,而不获取路径 更新: #!/bin/bash MY_NAME=`basename $0` function ouch { echo "Fail @ [${MY_NAME}:${1}]" exit 1 }
echo "ERROR: [$FILE:L$LINE] $somefile not found"
当前行号的$LINENO
当前文件的$0
。我使用basename
确保只获取文件名,而不获取路径
更新:
#!/bin/bash
MY_NAME=`basename $0`
function ouch {
echo "Fail @ [${MY_NAME}:${1}]"
exit 1
}
ouch $LINENO
如果使用函数方法,则必须将该行作为参数传递,否则将获得函数定义的行。只需
echo $LINENO
echo $(basename $0)
我发现“BASH_SOURCE”和“BASH_LINENO”内置阵列非常有用:
$ cat xx
#!/bin/bash
_ERR_HDR_FMT="%.23s %s[%s]: "
_ERR_MSG_FMT="${_ERR_HDR_FMT}%s\n"
error_msg() {
printf "$_ERR_MSG_FMT" $(date +%F.%T.%N) ${BASH_SOURCE[1]##*/} ${BASH_LINENO[0]} "${@}"
}
error_msg "here"
error_msg "and here"
调用xx产生
2010-06-16.15:33:13.069 xx[11]: here
2010-06-16.15:33:13.073 xx[14]: and here
下面介绍如何在可重用函数中实现这一点。如果以下内容位于名为
script
的文件中:
#!/bin/bash
debug() {
echo "${BASH_SOURCE[1]##*/}:${FUNCNAME[1]}[${BASH_LINENO[0]}]" > /dev/tty
}
debug
这将产生以下输出:
script:main[5]
它指示调用debug
的行
下面将打印文件名、函数、行和可选消息 也可以在
zsh
中工作,以获得额外的好处
# Say the file, line number and optional message for debugging
# Inspired by bash's `caller` builtin
# Thanks to https://unix.stackexchange.com/a/453153/143394
function yelp () {
# shellcheck disable=SC2154 # undeclared zsh variables in bash
if [[ $BASH_VERSION ]]; then
local file=${BASH_SOURCE[1]##*/} func=${FUNCNAME[1]} line=${BASH_LINENO[0]}
else # zsh
emulate -L zsh # because we may be sourced by zsh `emulate bash -c`
# $funcfiletrace has format: file:line
local file=${funcfiletrace[1]%:*} line=${funcfiletrace[1]##*:}
local func=${funcstack[2]}
[[ $func =~ / ]] && func=source # $func may be filename. Use bash behaviour
fi
echo "${file##*/}:$func:$line $*" > /dev/tty
}
basename$0
(不需要echo
)请注意,如果source
脚本,basename$0
将返回父脚本。而且,在加载了脚本的登录shell(~/.bashrc,/etc/profile.d/*)中,这也不起作用。“BASH_SOURCE”和“BASH_LINENO”更好,尽管它们是BASH主义。在任何源代码d脚本中都会失败。basename$0
(不需要echo
),我也更喜欢使用您描述的BASH_*变量。这里有一篇关于如何调试我在过去引用过的bash脚本的好文章:请参阅此处的日志记录和错误处理实现:它涉及使用bash内置的caller
命令以及bash\u SOURCE
和bash\u LINENO
数组来记录执行/转储堆栈跟踪的上下文非常好的解决方案。虽然我认为必须有一种方法使它更紧凑,但我没有发现它,我喜欢在我的许多生产/关键shell脚本中使用set-euo pipefail
,所以我稍微修改了它,使用if[${BASH_VERSION:-}];然后
代替if[[$BASH_VERSION]];然后
否则我会得到yelp:3:BASH\u VERSION:parameter not set
,这是预期的,因为set-u
的严格性,它将在访问未设置的变量时退出
# Say the file, line number and optional message for debugging
# Inspired by bash's `caller` builtin
# Thanks to https://unix.stackexchange.com/a/453153/143394
function yelp () {
# shellcheck disable=SC2154 # undeclared zsh variables in bash
if [[ $BASH_VERSION ]]; then
local file=${BASH_SOURCE[1]##*/} func=${FUNCNAME[1]} line=${BASH_LINENO[0]}
else # zsh
emulate -L zsh # because we may be sourced by zsh `emulate bash -c`
# $funcfiletrace has format: file:line
local file=${funcfiletrace[1]%:*} line=${funcfiletrace[1]##*:}
local func=${funcstack[2]}
[[ $func =~ / ]] && func=source # $func may be filename. Use bash behaviour
fi
echo "${file##*/}:$func:$line $*" > /dev/tty
}