Python 为什么可以';你看不到我的文件吗?

Python 为什么可以';你看不到我的文件吗?,python,linux,bash,shell,virtualenv,Python,Linux,Bash,Shell,Virtualenv,我有一个简单的bash脚本,它允许cron在virtualenv中执行一系列Python脚本。脚本不断引发无此类文件或目录错误 ~/nightly.sh工作正常: #!/bin/bash source virt_env/myproject/bin/activate cd virt_env/myproject/main python script1.py python script2.py 我希望将所有内容都保存在~/virt\u env/myproject/main/中,以简化部署。我想我可以

我有一个简单的bash脚本,它允许
cron
virtualenv
中执行一系列Python脚本。脚本不断引发
无此类文件或目录
错误

~/nightly.sh
工作正常:

#!/bin/bash
source virt_env/myproject/bin/activate
cd virt_env/myproject/main
python script1.py
python script2.py
我希望将所有内容都保存在
~/virt\u 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
但是我得到的
没有这样的文件或目录
。如果我手动
cd
~/virt\u env/myproject/main/
,那么我可以毫无问题地运行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脚本,使其在路径感知方面更加智能

此代码失败,因为忽略了路径信息:

# 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")
将其更新为使用可修复此问题:

# works regardless of how it is called
CONFIG_FILE = os.path.abspath(__file__)[:-3] + ".config"
f = open(CONFIG_FILE,"r")

也许最好是取消“cd”命令。调用完整路径规范中的所有内容。在您的示例中,将$MAINDIR/添加到可执行文件中

然后,bash脚本可以位于可访问可执行文件的任何目录中。您不会遇到cd出现故障时发生的问题

例如:

cd yourdir
rm -f yourglob   # oops things got removed from where you started if yourdir did not exist.
两件事:

  • 您确定知道
    dirname
    命令在做什么吗?它将删除顶级目录以及任何调用它的地方的前导斜杠。我会绝对确保
    dirname
    的输出与您认为的完全一致

    例如,
    /home/user/
    将输出
    /home

  • 您正在使用
    ~
    ,它在您的环境中引用
    $HOME
    变量。您没有提到cron
的列表位置,但请确保它不是以其他用户的身份运行的。Root的
~
和您的
~
将是两个完全不同的目录


这就是我所能想到的。我希望这有帮助

添加
echo$MAINDIR

MAINDIR=`dirname $0`
cd $MAINDIR
您可以看到MAINDIR的内容是否正确


您还可以使用
-x
运行sh,或者将
set-x
添加到脚本的开头,以查看发生了什么情况。

crontab条目是什么?我还没有将crontab加入到混合中,我只是像crontab一样从主目录启动bash脚本。
echo“MAINDIR是$MAINDIR”
yields
MAINDIR是virt\u env/myproject/main
。感谢您的回答。(编辑时间已满)是的,
dirname
删除最后一个参数,因为我正在调用文件。因此,
/path/to/file.txt
变成了
/path/to
。使用此方法构建绝对路径似乎效果更好。
714910*bash virt_env/myproject/main/nightly.sh的Chrontab似乎可以很好地处理新文件。