
我正在编写一个包装脚本来包装另一个命令的执行;在本例中为 Chefkitchen
命令。我的脚本也将被调用kitchen
并提前放入,$PATH
以便kitchen
从 bash 运行将运行我的包装器脚本。
问题是:如何调用原始版本kitchen
?当然,最明显的方法就是给出完整路径 - 只需放入/usr/bin/kitchen
脚本中,但其他人可能会将其安装在不同的路径中。当然,这排除了任何其他包装器脚本 - 如果解决方案是可堆叠的,那就太好了。
我想到了两种方法,两种方法都针对同一主题:
- 在脚本中,通过
$PATH
.将每个条目与$(dirname "$0")
使用stat
设备号和索引节点号进行比较,看看是否是同一个目录。如果是这样,请将其从 中删除$PATH
。然后就可以调用kitchen
,因为它不应该重新调用包装器脚本。 - 与 #1 类似,但
$PATH
在脚本中手动查找,并stat
在每个结果上使用与$0
.继续跳过,直到找到自己,然后使用找到的下一个。如果我们从未找到自己,那么只需正常执行它(以处理包装器不在其中$PATH
但通过提供其路径来执行的情况)
有没有更好的办法?或者典型的 Debian 或 Ubuntu Linux 系统上是否已经存在执行此操作的代码?
答案1
我过去曾做过几次类似的事情,我要做的只是command kitchen
在脚本中使用,将其命名为其他名称my-kitchen
,然后创建一个别名:
alias kitchen=/path/to/my-kitchen
但不确定这是否适合您的用例。
答案2
您可以使用反斜杠转义别名,以防止它被 shell 扩展。 command
也有效。
kitchen
我的桌面上没有,所以我将通过别名pwd
来演示uname -r
:
$ alias pwd='uname -r'
$ pwd
5.10.0-8-amd64
$ \pwd
/home/cas
$ command pwd
/home/cas
$ unalias pwd
$ pwd
/home/cas
答案3
听起来您想执行kitchen
中的下一个$PATH
。
#!/bin/bash
me="$0"
foundit=""
for d in $( echo "$PATH" | tr ":" " " ) ; do
if [[ $foundit == "" ]] ; then
if [[ "$me" != "$d/kitchen" ]] ; then
if [[ -x "$d/kitchen" ]] ; then
foundit="$d/kitchen"
fi
fi
fi
done
# the next "kitchen" is in "`$foundit`"
# read `man bash`, about the `eval` and `exec` builtins