我有一个 bash 脚本,它获取一个文件,该文件获取另一个文件:
script.sh:
cd /script/dir
source funcs.sh
funcs.sh:
...
source mode.sh
现在,当我从 /script/dir 中的命令行运行该脚本时,该脚本运行正常。但是当我从 crontab 运行它时,funcs.sh 文件找不到 mode.sh。可能是因为某种原因cd /script/dir
没有传递给它?我可以在脚本中做任何事情,或者我需要在 cron 中执行 cd 或类似的操作吗?
答案1
可能出现的问题:
没有舍邦里面
script.sh
。如果告诉 cron 运行,script.sh
那么它会像这样运行/bin/sh -c script.sh
(除非SHELL
你的 crontab 内部指向 以外的东西/bin/sh
,我们不知道这一点)。由于没有 shebang,因此适用:哪个 shell 解释器运行不带 shebang 的脚本?答案取决于您的 cron 使用什么 shell,我们不确定这一点。最终sh
可能会选择其他东西作为脚本的解释器。即使选择了,它也可能由或其他东西sh
提供(默认情况下在 Ubuntu 中,但我们不知道是否真的如此)dash
bash
dash
在你的情况下)。关键是
script.sh
当脚本从 cron 启动时,我们并不真正知道解释器是什么。我想在某些情况下脚本可能根本无法从 cron 启动。OTOH 当您从交互式 shell 运行脚本时,可能会选择不同的解释器然后它就可以工作。
cd /script/dir
可能会因某种原因失败(例子)。source
是 的别名.
,但并非在所有 shell 中。由于我们不认识解释器,所以我们不知道它是否理解source
。即使解释器将其理解
source
为 as.
,参数仍是funcs.sh
且不包含/
。在这种情况下, POSIX 的行为.
是funcs.sh
在$PATH
.现在:即使您
$PATH
包含.
(即当前工作目录),cron 中的相同变量也可能不包含它。仅当搜索
$PATH
失败时,一些shell 尝试当前工作目录。
要修复,请执行以下操作:
在里面使用 shebang
script.sh
,这样你就可以控制script.sh
执行时使用哪个 shell 来解释。(根据您选择的 shell,修复程序 (3) 和 (4) 可能是必要的,也可能不是必要的;它们不会造成损害,因此如果有任何疑问,请无论如何应用它们。)
如果失败则中止
cd
。如果脚本在cd
失败后继续,则脚本可能会尝试funcs.sh
从错误的目录获取源。使用
.
而不是source
.前者是便携式的,后者则不是。/
使用包含(在本例中./funcs.sh
而不是)的显式路径funcs.sh
,因此无需搜索,$PATH
并且清楚您的意思是什么文件。
固定的script.sh
将是这样的:
#!/bin/sh
cd /script/dir || exit 1
. ./funcs.sh
funcs.sh
不需要在 shebang内部,因为该文件是由 shell 解释获取的script.sh
,但修复 (3) 和 (4) 可能仍然是必要的(取决于所选的 shell)。
答案2
每个进程都有一个$PWD
(工作目录)cron 不在您的$HOME
.您可以使用这个来代替cd
脚本中的 ing
#!/bin/bash
dir="$(dirname "$(readlink -f "$0")")"
echo $dir
$dir
是脚本的位置目录。例如
$ cd /
$ bash /home/junaga/script.sh
输出/home/junaga
,因为那是脚本位置