代码之家  ›  专栏  ›  技术社区  ›  Jorge Vargas

如何模拟cron执行脚本的环境?

  •  226
  • Jorge Vargas  · 技术社区  · 16 年前

    我通常对cron如何执行脚本有几个问题,因为它们通常没有我的环境设置。有没有方法调用bash(?)和cron一样,我可以在安装之前测试脚本吗?

    12 回复  |  直到 8 年前
        1
  •  351
  •   Walf    9 年前

    将此添加到您的cron中:

    30 08 * * * env > ~/cronenv
    

    运行后,请执行以下操作:

    env - `cat ~/cronenv` /bin/sh
    

    这假定cron运行/bin/sh,这是默认值,而不管用户的默认shell是什么。

        2
  •  60
  •   Braiam nahurmf    8 年前

    cron默认情况下只提供此环境:

    • HOME 用户的主目录
    • LOGNAME 用户登录
    • PATH=/usr/bin:/usr/sbin
    • SHELL=/usr/bin/sh

    如果需要更多,可以在crontab中的调度表之前定义环境的脚本。

        3
  •  42
  •   Cookie    8 年前

    几种方法:

    1. 导出cron env并从中获取:

      添加

      * * * * * env > ~/cronenv
      

      对于你的crontab,让它运行一次,关闭它,然后运行

      env - `cat ~/cronenv` /bin/sh
      

      现在你进入了 sh 具有cron环境的会话

    2. 把你的环境带给克罗恩

      你可以跳过上面的练习,只做一个 . ~/.profile 在你的同事面前,例如

      * * * * * . ~/.profile; your_command
      
    3. 使用屏幕

      以上两个解决方案仍然失败,因为它们提供了一个连接到正在运行的X会话的环境,并且可以访问 dbus 例如,在Ubuntu上, nmcli (网络管理器)将在上述两种方法中工作,但在cron中仍然失败。

      * * * * * /usr/bin/screen -dm
      

      将上面的行添加到cron,让它运行一次,然后关闭它。连接到屏幕会话(屏幕-R)。如果您正在检查屏幕会话是否已创建(使用 ps )请注意,它们有时是大写的(例如 ps | grep SCREEN )

      现在甚至 NMCLI 同样的情况也会失败。

        4
  •  21
  •   dimba    16 年前

    你可以运行:

    env - your_command arguments
    

    这将在空环境下运行_命令。

        5
  •  13
  •   tcurdt    15 年前

    取决于账户的外壳

    sudo su
    env -i /bin/sh
    

    sudo su
    env -i /bin/bash --noprofile --norc
    

    http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html

        6
  •  12
  •   J. Bruni    9 年前

    六年后的回答:环境不匹配问题是 systemd “计时器”作为cron替换。无论您是从cli还是通过cron运行systemd“service”,它都会收到完全相同的环境,从而避免了环境不匹配的问题。

    导致cron作业在手动传递时失败的最常见问题是限制性默认值 $PATH 由cron设置,这是Ubuntu 16.04上的:

    "/usr/bin:/bin"
    

    相比之下,默认 $路径 通过设置 系统 在Ubuntu 16.04上是:

    "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    

    因此,有更好的机会,一个SystemD计时器将找到一个二进制文件,而无需进一步的麻烦。

    SystemD计时器的缺点是设置它们的时间稍微长一些。首先创建一个“服务”文件来定义要运行的内容,然后创建一个“计时器”文件来定义运行它的计划,最后“启用”计时器来激活它。

        7
  •  10
  •   Jens Carlberg    16 年前

    创建一个运行env并将stdout重定向到文件的cron作业。 使用“env-”旁边的文件创建与cron作业相同的环境。

        8
  •  3
  •   Randy Proctor    16 年前

    别忘了,因为cron的父级是init,所以它运行的程序没有控制终端。你可以用这样的工具来模拟:

    http://libslack.org/daemon/

        9
  •  2
  •   Dennis Williamson    16 年前

    默认情况下, cron 使用系统的任何想法执行其作业 sh 是。这可能是真正的伯恩贝壳或者 dash ,请 ash , ksh bash (或另一个)符号链接到 (因此在POSIX模式下运行)。

    最好的做法是确保您的脚本具有它们需要的内容,并假定没有为它们提供任何内容。因此,您应该使用完整的目录规范并设置环境变量,例如 $PATH 你自己。

        10
  •  1
  •   four43    12 年前

    我发现的另一个简单方法(但可能很容易出错,我仍在测试)是在您的命令之前获取用户的配置文件。

    编辑a/etc/cron.d/脚本:

    * * * * * user1 comand-that-needs-env-vars
    

    会变成:

    * * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars
    

    很脏,但这让我的工作完成了。有没有模拟登录的方法?只是一个你可以运行的命令? bash --login 不起作用。听起来这是更好的方法。

    编辑:这似乎是一个坚实的解决方案: http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/

    * * * * * root su --session-command="comand-that-needs-env-vars" user1 -l
    
        11
  •  0
  •   Community Mohan Dere    9 年前

    回答 https://stackoverflow.com/a/2546509/5593430 演示如何获取cron环境并将其用于脚本。但是请注意,环境可能因使用的crontab文件而异。我创建了三个不同的cron条目,通过 env > log . 这些是AmazonLinux4.4.35-33.55.amzn1.x86_64上的结果。

    1.具有根用户的全局/etc/crontab

    MAILTO=root
    SHELL=/bin/bash
    USER=root
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    PWD=/
    LANG=en_US.UTF-8
    SHLVL=1
    HOME=/
    LOGNAME=root
    _=/bin/env
    

    2。根目录的用户crontab( crontab -e )

    SHELL=/bin/sh
    USER=root
    PATH=/usr/bin:/bin
    PWD=/root
    LANG=en_US.UTF-8
    SHLVL=1
    HOME=/root
    LOGNAME=root
    _=/usr/bin/env
    

    三。以/etc/cron.hourly格式编写脚本/

    MAILTO=root
    SHELL=/bin/bash
    USER=root
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    _=/bin/env
    PWD=/
    LANG=en_US.UTF-8
    SHLVL=3
    HOME=/
    LOGNAME=root
    

    最重要的是 PATH , PWD HOME 不同。确保在cron脚本中设置这些,以依赖于稳定的环境。

        12
  •  -7
  •   jn80842    16 年前

    我不相信有,我知道测试cron作业的唯一方法就是设置它在未来运行一两分钟,然后等待。