我有一个包含一个函数的bash脚本,该函数由许多不同的bash脚本提供。此函数可能会因其输入而失败,我想在函数中创建日志记录以确定导致失败的脚本。
如, source /path/to/function.sh
我最接近的是:
ps --no-heading -ocmd -p $$
如果使用完整文件路径运行父脚本,则返回:
/bin/bash /path/to/parent.sh
但如果从相对路径运行父脚本,则无法提供完整路径,返回:
/bin/bash ./parent.sh
理想情况下,我想要一种可靠地返回两种情况的父脚本文件路径的方法。
我想我可以让每个父脚本将其文件路径传递给该函数(通过$ 0或类似),但这似乎难以强制执行并且不是非常优雅。
任何想法或替代方法?我不应该担心相对路径的情况,只是使用完整/绝对文件路径的一切?
谢谢!
我正在使用Centos 5.9。 Bash版 - GNU bash,版本3.2.25(1)-release(x86_64-redhat-linux-gnu)
答案 0 :(得分:1)
父脚本一开始导出
"`pwd`/$0"
左右,进入一个env变量,比如ORIG_SCRIPT,然后在函数中使用ORIG_SCRIPT。
你需要在脚本启动时立即执行此操作,因为$ 0可能与PWD相关,如果稍后在需要ORIG_SCRIPT的值之前更改PWD,则会出现不必要的复杂。
<强>更新强>
由于您通过$$知道pid,您可能会从/ proc /&lt; PID&gt; / cmdline获得一些内容,但我不知道这个内容究竟是如何工作的。
答案 1 :(得分:1)
您可以使用readlink来跟踪所有符号链接以获得绝对路径。
echo $(readlink -f $0)
答案 2 :(得分:0)
您可以使用${BASH_SOURCE[1]}
来获取调用该函数的脚本,但这并不总是在绝对路径表单上。您可以通过readlink -m
,realpath
或其他shell-script based solutions获取它的绝对路径,但如果您的脚本不时更改目录,则不再将相对路径转换为绝对路径准确,因为这些工具基于当前目录,以获得实际的表格。
然而,有一种解决方法,但这要求您在调用(获取)包含该函数的脚本之前不会更改脚本中的目录。您必须将当前目录保存在该脚本本身中,然后在该目录中构建绝对路径。在包含脚本后,您可以自由更改目录。举个例子:
ORIGINAL_PWD=$PWD
function x {
local CALLING_SCRIPT="${BASH_SOURCE[1]}"
if [[ -n $CALLING_SCRIPT ]]; then
if [[ $CALLING_SCRIPT == /* ]]; then
CALLING_SCRIPT=$(readlink -m "$CALLING_SCRIPT")
else
CALLING_SCRIPT=$(readlink -m "$ORIGINAL_PWD/$CALLING_SCRIPT")
fi
echo "Calling script: $CALLING_SCRIPT"
else
echo "Caller is not a script."
fi
}
或者
ORIGINAL_PWD=$PWD
function getabspath {
local -a T1 T2
local -i I=0
local IFS=/ A
case "$1" in
/*)
read -r -a T1 <<< "$1"
;;
*)
read -r -a T1 <<< "/$PWD/$1"
;;
esac
T2=()
for A in "${T1[@]}"; do
case "$A" in
..)
[[ I -ne 0 ]] && unset T2\[--I\]
continue
;;
.|'')
continue
;;
esac
T2[I++]=$A
done
case "$1" in
*/)
[[ I -ne 0 ]] && __="/${T2[*]}/" || __=/
;;
*)
[[ I -ne 0 ]] && __="/${T2[*]}" || __=/.
;;
esac
}
function x {
local CALLING_SCRIPT="${BASH_SOURCE[1]}"
if [[ -n $CALLING_SCRIPT ]]; then
if [[ $CALLING_SCRIPT == /* ]]; then
getabspath "$CALLING_SCRIPT"
else
getabspath "$ORIGINAL_PWD/$CALLING_SCRIPT"
fi
echo "Calling script: $__"
else
echo "Caller is not a script."
fi
}
您还可以使用FUNCNAME和BASH_LINENO来更具体地处理错误。我不确定他们是否已经在Bash 3.2中得到支持。
如果你实际上有Bash 4.0+,你可以使用关联数组来映射绝对路径,但是如果有两个具有相同名称的脚本或者使用几乎相似的名称调用,则可以覆盖一个值。由于我们无法从BASH_SOURCE中选择我们的密钥,因此无法解决这个问题。
添加注意:您还可以防止脚本多次被不必要地获取,因为它只需要通过Shell Script Loader之类的解决方案。你也可以通过它找到便利。