7

我已经阅读了多篇文章和许多文章,详细说明了 cron 作业中的 scipts 需要保留在脚本本身内部运行所需的环境变量,因为在 cron 中打开了 shell。我的情况是独一无二的,因为我的路径变量都是按照讨论的那样设置的,这反过来又会使用 subprocess.call ()成功调用 pysaunter python egg ,但它似乎从那里崩溃了。这会导致整个过程中断一个 cron 作业。

为清楚起见,以下是我参考的步骤:

1) cronjob calls run_test.py -n foo
2) run_test.py sets the environment variables correctly 
(cur_shell_path=sys.path (converted to proper path string, not shown here)
 my_env= os.environ.copy()
 my_env["PATH"] = my_env["PATH"] + cur_shell_path)
3) run_test.py calls subprocess.call("pysaunter -m foo -v", env=my_env, shell=True)

步骤 3 的输出显示它正在找到 egg 并成功开始从 pysaunter 加载必要的模块,但是在尝试查找用于修改 pysaunter 的目录时它会中断。错误显示:

ImportError: no module named helpers

我曾多次尝试将此路径添加到环境中,但似乎从未找到包含 helpers.py 的目录。pysaunter -m foo -v当从交互式 shell 调用时,该命令正常工作。

我在 pysaunter 上找不到太多帮助,所以我认为这里不需要过多的 pysaunter 细节。但是,如果您对 pysaunter 有更多了解,请告诉我您是否需要更多信息。我不确定要分享什么。

我还阅读了许多帖子,讨论了通过编辑 .profile/.bash_profile 来更改 shell 的默认行为的能力。我试图找到一个可以让我的路径变量全局可访问的地方,但我找不到任何东西。我不确定这是如何完成的,它可能会解决我的问题,所以如果您对此有所了解,请告诉我。

最后一点,这是在 Mac 10.7.5 上运行的。

4

2 回答 2

4

经过多次试验和错误,以及很多很多 stackoverflow.com 文章和其他在线教程,在 Perl 脚本的帮助下,我发现做了类似的事情,我能够弄清楚需要做什么才能让它工作.

以下是确保一切设置正确的步骤:

  1. 确保您在 PYTHONPATH 中拥有所需的变量(可在此处此处找到,以及更多信息。请转到此处)内的 .profile 或 .bash_profile 用于您想要测试脚本以确保其正常工作的任何 shell。

  2. 编辑您的 crontab 以包含在 cron 作业中运行脚本所需的目录(可在此处此处找到)。

    a) 确保在 PATH 变量 (.) 中包含根目录,如此处所述。基本上,如果您使用命令运行可执行文件,它需要能够找到根目录或存储可执行文件的目录,还可能是这些:(/sbin:/bin:/usr/sbin:/usr/bin)。

  3. 在您的 crontab 文件中,创建一个 cronjob,它将当前目录更改为您之前成功运行脚本的目录(例如,/Users/user/Documents/foo)。

    a) 这将如下所示:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
  4. 由于我的问题专门针对调用可执行文件,因此有必要注意编写要运行的 Python 脚本有多种方法(尽管在发现过程中我了解到这适用于使用 cron 中的子进程进行的任何调用)。

    第一种方法如下所示:

    ... #some script calls
    my_env = os.environ.copy()
    my_env["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>")
    os.chdir("<path/to/desired/directory>")
    subprocess.Popen(<call_as_string>, env=my_env, shell=True)
    

    第二个看起来像这样:

    ... #some script calls
    os.environ["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>")
    os.chdir("<path/to/desired/directory>")
    subprocess.Popen(<call_as_list_of_arguments)
    

    由于可执行文件需要包含在从中调用它的 shell 中的 helpers 目录的路径,因此有必要将环境变量传递给可执行文件,如此所述。不过,我发现修改环境中的 PATH 变量不适用于 cron 作业,但设置 PYTHONPATH 可以。我在这里读到,shell 使用 PATH 变量仅查找可执行文件,因此对于 cronjob 中的新 shell,您需要向 shell 传递 PYTHONPATH 以查找新的 Python 模块。(这也在Python 文档中进行了解释。)

    问题中引用的子流程文档解释了这两种不同方法之间的差异,但可以在此处找到有关此模块的良好教程。

于 2013-07-16T22:18:06.810 回答
1

你说的没有道理。

你说shell_env = sys.pathsys.path是python查找模块的文件夹列表,而不是环境变量映射!

然后你在subprocess.call. 也许你的意思是写env=my_env

那是下一个问题。首先,PATH应该是一个以 . 分隔的文件夹列表':'。您只需将 shell_path 附加到最后一个文件夹。

最后,pythonPYTHONPATH用作一个列表来定位 python 模块(这似乎是你遇到的问题。)

于 2013-07-11T04:50:10.320 回答