【问题标题】:Why can't bash see my files?为什么 bash 看不到我的文件?
【发布时间】:2013-10-08 23:00:00
【问题描述】:

我有一个简单的 bash 脚本,它允许 cronvirtualenv 中执行一系列 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/,那么我可以运行主要命令没有问题。显然,我错过了 dirnamecd 在这种情况下的工作方式。

如何将 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")

【问题讨论】:

  • crontab 条目是什么?
  • 我还没有加入 crontab,我只是像 crontab 一样从我的主目录启动 bash 脚本。

标签: python linux bash shell virtualenv


【解决方案1】:

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

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

例子:

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

【讨论】:

    【解决方案2】:

    两件事:

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

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

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

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

    【讨论】:

    • 感谢您的回答。
    • (编辑时间用完)是的,dirname 删除了我想要的最后一个参数,因为我正在调用文件。因此/path/to/file.txt 变为/path/to。使用它来构建绝对路径似乎效果更好。 7 14 9 10 * bash virt_env/myproject/main/nightly.sh 的 Chrontab 似乎可以很好地处理新文件。
    【解决方案3】:

    在后面添加echo $MAINDIR

    MAINDIR=`dirname $0`
    cd $MAINDIR
    

    所以你可以看看,如果 MAINDIR 的内容是正确的。

    您也可以使用-x 运行sh 或将set -x 添加到脚本的开头以查看会发生什么。

    【讨论】:

    • echo "MAINDIR is $MAINDIR" 产生MAINDIR is virt_env/myproject/main
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-11-01
    • 1970-01-01
    相关资源
    最近更新 更多