bash 如何模拟cron执行脚本的环境?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2135478/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to simulate the environment cron executes a script with?
提问by Jorge Vargas
I normally have several problems with how cron executes scripts as they normally don't have my environment setup. Is there a way to invoke bash(?) in the same way cron does so I could test scripts before installing them?
我通常对 cron 如何执行脚本有几个问题,因为它们通常没有我的环境设置。有没有办法以与 cron 相同的方式调用 bash(?) 以便我可以在安装脚本之前测试它们?
回答by mmccoo
Add this to your crontab (temporarily):
将此添加到您的 crontab(临时):
* * * * * env > ~/cronenv
After it runs, do this:
运行后,执行以下操作:
env - `cat ~/cronenv` /bin/sh
This assumes that your cron runs /bin/sh, which is the default regardless of the user's default shell.
这假设您的 cron 运行 /bin/sh,无论用户的默认 shell 是什么,它都是默认值。
回答by gregseth
Cron provides only this environment by default :
Cron 默认只提供这个环境:
HOME
user's home directoryLOGNAME
user's loginPATH=/usr/bin:/usr/sbin
SHELL=/usr/bin/sh
HOME
用户的主目录LOGNAME
用户登录PATH=/usr/bin:/usr/sbin
SHELL=/usr/bin/sh
If you need more you can source a script where you define your environment before the scheduling table in the crontab.
如果您需要更多,您可以在 crontab 中的调度表之前定义您的环境的脚本。
回答by Cookie
Couple of approaches:
几种方法:
Export cron env and source it:
Add
* * * * * env > ~/cronenv
to your crontab, let it run once, turn it back off, then run
env - `cat ~/cronenv` /bin/sh
And you are now inside a
sh
session which has cron's environmentBring your environment to cron
You could skip above exercise and just do a
. ~/.profile
in front of your cron job, e.g.* * * * * . ~/.profile; your_command
Use screen
Above two solutions still fail in that they provide an environment connected to a running X session, with access to
dbus
etc. For example, on Ubuntu,nmcli
(Network Manager) will work in above two approaches, but still fail in cron.* * * * * /usr/bin/screen -dm
Add above line to cron, let it run once, turn it back off. Connect to your screen session (screen -r). If you are checking the screen session has been created (with
ps
) be aware that they are sometimes in capitals (e.g.ps | grep SCREEN
)Now even
nmcli
and similar will fail.
导出 cron env 并获取它:
添加
* * * * * env > ~/cronenv
到您的 crontab,让它运行一次,将其关闭,然后运行
env - `cat ~/cronenv` /bin/sh
你现在在一个
sh
具有 cron 环境的会话中将您的环境带到 cron
你可以跳过上面的练习,只是
. ~/.profile
在你的 cron 工作前做一个,例如* * * * * . ~/.profile; your_command
使用屏幕
以上两种解决方案仍然失败,因为它们提供了一个连接到正在运行的 X 会话的环境,可以访问
dbus
等。例如,在 Ubuntu 上,nmcli
(网络管理器)将在上述两种方法中工作,但在 cron 中仍然失败。* * * * * /usr/bin/screen -dm
将以上行添加到 cron,让它运行一次,然后将其关闭。连接到您的屏幕会话 (screen -r)。如果您正在检查屏幕会话是否已创建(使用
ps
),请注意它们有时是大写的(例如ps | grep SCREEN
)现在甚至
nmcli
和类似的都会失败。
回答by dimba
You can run:
你可以运行:
env - your_command arguments
This will run your_command with empty environment.
这将在空环境下运行 your_command。
回答by tcurdt
Depending on the shell of the account
取决于帐户的外壳
sudo su
env -i /bin/sh
or
或者
sudo su
env -i /bin/bash --noprofile --norc
From http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html
来自http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html
回答by Mark Stosberg
Answering six years later: the environment mismatch problem is one of the problems solved by systemd
"timers" as a cron replacement. Whether you run the systemd "service" from the CLI or via cron, it receives exactly the same environment, avoiding the environment mismatch problem.
六年后回答:环境不匹配问题是systemd
“定时器”作为cron替代解决的问题之一。无论您是从 CLI 还是通过 cron 运行 systemd“服务”,它都会接收完全相同的环境,避免环境不匹配问题。
The most common issue to cause cron jobs to fail when they pass manually is the restrictive default $PATH
set by cron, which is this on Ubuntu 16.04:
导致 cron 作业在手动传递时失败的最常见问题是 cron$PATH
设置的限制性默认值,这在 Ubuntu 16.04 上是这样的:
"/usr/bin:/bin"
By contrast, the default $PATH
set by systemd
on Ubuntu 16.04 is:
相比之下,Ubuntu 16.04 上的默认$PATH
设置systemd
是:
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
So there's already a better chance that a systemd timer is going to find a binary without further hassle.
因此,systemd 计时器更有可能轻松找到二进制文件。
The downside with systemd timers, is there's a slightly more time to set them up. You first create a "service" file to define what you want to run and a "timer" file to define the schedule to run it on and finally "enable" the timer to activate it.
systemd 计时器的缺点是设置它们的时间稍微多一点。您首先创建一个“服务”文件来定义要运行的内容,并创建一个“计时器”文件来定义运行它的时间表,最后“启用”计时器以激活它。
回答by Jens Carlberg
Create a cron job that runs env and redirects stdout to a file. Use the file alongside "env -" to create the same environment as a cron job.
创建一个运行 env 并将标准输出重定向到文件的 cron 作业。将文件与“env -”一起使用以创建与 cron 作业相同的环境。
回答by Randy Proctor
Don't forget that since cron's parent is init, it runs programs without a controlling terminal. You can simulate that with a tool like this:
不要忘记,因为 cron 的父级是 init,它在没有控制终端的情况下运行程序。您可以使用这样的工具来模拟:
回答by Paused until further notice.
By default, cron
executes its jobs using whatever your system's idea of sh
is. This could be the actual Bourne shell or dash
, ash
, ksh
or bash
(or another one) symlinked to sh
(and as a result running in POSIX mode).
默认情况下,cron
使用系统的任何想法来执行其作业sh
。这可能是实际的 Bourne shell 或dash
, ash
,ksh
或bash
(或另一个)符号链接到sh
(并因此在 POSIX 模式下运行)。
The best thing to do is make sure your scripts have what they need and to assume nothing is provided for them. Therefore, you should use full directory specifications and set environment variables such as $PATH
yourself.
最好的办法是确保你的脚本有它们需要的东西,并假设没有为它们提供任何东西。因此,您应该使用完整的目录规范并设置环境变量,例如您$PATH
自己。
回答by four43
Another simple way I've found (but may be error prone, I'm still testing) is to source your user's profile files before your command.
我发现的另一种简单方法(但可能容易出错,我仍在测试中)是在执行命令之前获取用户的配置文件。
Editing a /etc/cron.d/ script:
编辑 /etc/cron.d/ 脚本:
* * * * * user1 comand-that-needs-env-vars
Would turn into:
会变成:
* * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars
Dirty, but it got the job done for me. Is there a way to simulate a login? Just a command you could run? bash --login
didn't work. It sounds like that would be the better way to go though.
脏,但它为我完成了工作。有没有办法模拟登录?只是一个你可以运行的命令?bash --login
没有用。听起来这将是更好的方法。
EDIT: This seems to be a solid solution: http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/
编辑:这似乎是一个可靠的解决方案: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