我有一个简单的bash脚本,允许cron
在virtualenv
中执行一系列Python脚本。该脚本不断引发No such file or directory
错误。
~/nightly.sh
效果很好:
#!/bin/bash
source virt_env/myproject/bin/activate
cd virt_env/myproject/main
python script1.py
python script2.py
我希望将所有内容保留在~/virt_env/myproject/main/
中以简化部署。我以为我可以打电话给bash virt_env/myproject/main/nightly.sh
:
#!/bin/bash
MAINDIR=`dirname $0`
cd $MAINDIR
source ../bin/activate
python script1.py
python script2.py
但我得到了No such file or directory
。如果我手动cd
到~/virt_env/myproject/main/
,那么我可以运行主命令没问题。很明显,我遗漏了dirname
和cd
在这种情况下的工作方式。
如何将bash指向正确的位置?
正如在接受的答案中所提出的,最好避免在脚本中调用cd
并使用显式路径变量。这是virt_env/myproject/main/nightly.sh
的工作版本:
#!/bin/bash
MAINDIR=`dirname $0`
echo "The main directory is" $MAINDIR
# Activate virtual environment
source $MAINDIR/../bin/activate
# Run Python scripts
python $MAINDIR/python1.py
python $MAINDIR/python2.py
因为Python脚本现在是从任意路径调用的,所以我需要更新python脚本以便更加智能地了解路径感知。
此代码失败,因为os.path.basename
省略了路径信息:
# works when called with "python python1.py"
# fails when called with "python $MAINDIR/python1.py"
CONFIG_FILE = os.path.basename(__file__)[:-3] + ".config"
f = open(CONFIG_FILE,"r")
将其更新为使用os.path.abspath
可解决问题:
# works regardless of how it is called
CONFIG_FILE = os.path.abspath(__file__)[:-3] + ".config"
f = open(CONFIG_FILE,"r")
答案 0 :(得分:2)
也许删除'cd'命令会更好。从完整路径规范中调用所有内容。在您的示例中,将$ MAINDIR /添加到可执行文件中。
然后,您的bash脚本可以位于可访问可执行文件的任何目录中。你没有遇到cd失败时会发生什么问题。
示例:
cd yourdir
rm -f yourglob # oops things got removed from where you started if yourdir did not exist.
答案 1 :(得分:0)
两件事:
您确定知道dirname
命令在做什么吗?它将删除顶级目录以及任何您调用它的前导斜杠。我绝对肯定dirname
的输出正是你所想的。
例如,/home/user/
将输出/home
。
您使用的是~
,它引用了您环境中的$HOME
变量。您没有提到列出cron
的位置,但请确保它不是以其他用户身份运行。 Root的~
和您的~
将是两个完全不同的目录。
这就是我所能想到的。我希望有所帮助!
答案 2 :(得分:0)
在
之后添加echo $MAINDIR
MAINDIR=`dirname $0`
cd $MAINDIR
所以你可以看到,如果MAINDIR的内容是正确的。
此外,您可以使用-x
运行sh或将set -x
添加到脚本的开头,以查看会发生什么。