我编写了一个脚本文件,其中一个函数搜索另一个脚本,如果找到,则执行该脚本。
脚本摘录
#!/bin/bash
...
service_status() {
local my_script=`which my-services-check.sh 2>/dev/null`
[[ -z "$my_script" ]] && { echo -n "functionality not available" ; failure ; echo ; return ; }
source $my_script
}
...
当我which my-services-check.sh 2>/dev/null
从终端执行此操作时,它会返回该文件的正确路径。
当我运行该函数时服务状态()(调用脚本时),它找不到该文件($my_script
为空)。
which
我没有尝试使用type
andcommand
但最终得到了相同的结果。
路径问题
然后我从终端和脚本打印出来$PATH
,果然它们不一样!从我的脚本执行时,被$PATH
设置为安全路径,如以下定义/etc/sudoers
:
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
从航站楼出发
echo $PATH /usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin: ...
所以,
如何从我的脚本中可靠地找到我正在寻找的文件? (不使用,
find
因为我需要的文件必须位于路径中)?从脚本执行时为什么 PATH 设置不同?
答案1
交互式 shell 加载.bashrc
,但脚本不加载。如果你的$PATH
设置为.bashrc
并且你不导出它,该脚本不会继承您对 的修改$PATH
。如果您调用export PATH
,脚本应该会看到它。检查export -p
导出哪些变量($PATH
应该在其中)。还要检查$BASH_ENV
哪些可能会覆盖您的$PATH
.
理想情况下,$PATH
应该在您的 中设置和导出.profile
,以便在您登录时加载和设置它,并且从那时起对您运行的所有内容都可见。
一个好的做法是不仅检查文件名是否存在,而且检查它是否是一个正确的文件,[[ -f "$my_script" ]]
或者(如果您想将其作为脚本调用而不是获取它)开关-x
。
答案2
实际上并没有任何保证包含在PATH
.你会发现/bin
,但其他一切都是可能的或可能的。我的系统上的用户将会有类似的东西$HOME/bin:/usr/local/bin:/bin:/usr/bin
。根用户也在/usr/local/sbin:/sbin:/usr/sbin
那里。
如果您的文件可能位于多个位置之一,您可以在这些可能的位置搜索它。只需删除此搜索中的整个依赖项PATH
,或扩展 PATH 以包含可能找到脚本的最小位置集。
local OPATH="$PATH"
PATH="$PATH:/extra/place:/another/extra/place"
local my_script=$( which my-services-check.sh 2>/dev/null )
PATH="$OPATH" # Restore the original PATH (optional)
if test -z "$my_script"; then ...; fi
. "$my_script"
或者,只需PATH
在脚本顶部设置所需的值。一旦您的初始脚本运行,您就没有理由不能设置PATH
.我倾向于在我的许多脚本中这样做,只是为了让我知道环境是合理的。