我有一个脚本,它调用同一个类中的两个函数A和B。A创建亚马逊虚拟服务器,B通过亚马逊命令行工具的shell_exec()销毁一个。脚本doActions.php从队列中拉出操作。如果操作是“创建”,它会创建一个实例;当操作是“销毁”时,它会杀死一个。
当我从命令行php script.php执行该脚本时,它可以很好地同时执行A和B。
当我把它放在cron上时,它会运行,但只成功地运行了B函数。它会删除销毁实例,但不会创建它们。
故障点显然是函数B。它在第一个也是最重要的shell_exec中阻塞,没有任何返回和回显。
echo $string = shell_exec('/home/user/public_html/domain.com/private/ec2-api-tools/bin/ec2-run-instances ami-23b6534a -k gsg-keypair -z us-east-1a');除非你对亚马逊的命令行工具的工作方式有所了解,否则请告诉我为什么shell_exec可以在一种情况下工作,而不是在另一种情况下工作。
同一位置的另一个shell_exec的行为与预期一致:
echo $string = shell_exec ('echo overflow');我的猜测是,它必须与权限有关。但是,当我让它运行shell_exec('whoami')时,它会返回"root“,而当我su并运行该命令时,它工作得很好。我很难想出有创意的方法来解决为什么我的PHP脚本在cron中不能工作,而它却在命令行中工作。你能推荐一些吗?
发布于 2010-07-21 09:26:09
当某些东西从命令行运行但拒绝在cron中运行时,通常是环境问题(path或您运行的代码所需的其他环境变量)。
首先,您应该修改脚本以输出当前环境(shell_exec('env')?)查看命令行和cron的输出。
希望有一些明显的东西,比如AMAZON_EC2_VITAL_VAR,但如果没有,您应该将cron环境移到命令行中,一次一个变量,直到它开始工作。
一个快速测试来确定这一点。在命令行中,执行以下操作:
env >/tmp/pax_env.sh然后从一个shell脚本运行PHP脚本,该脚本首先执行:
. /tmp/pax_env.sh因此环境是相同的。
请记住,su本身并不能为您提供与直接以特定用户身份登录时相同的环境(我认为是su -)。您可能希望检查直接以root身份登录时的行为。
请回复您的评论:
是的,我相信你已经做到了。我可能会将你的答案标记为正确,但你需要经历一些关于你聪明的解决方案的附录。首先,执行pax_env.sh脚本的最佳方式是什么?shell_exec()能工作吗?
永远不要说我不是为了钱而工作:-)不。shell_exec几乎肯定会运行子shell,因此变量将在该子shell中设置,但不会影响PHP父进程。
我的建议是,如果您希望设置所有这些变量,可以创建一个包含/tmp/pax_env.sh中的所有命令(可能每个命令都以export为前缀)的shell脚本,后跟当前在cron中运行的命令,内容大致如下:
export PATH=.:/usr/bin
export PS1=Urk:
export PS2=MoreUrk:
/home/user/pax/scriptB.php然后从cron运行该脚本,而不是直接从/home/user/pax/scriptB.php运行。这将确保在调用PHP代码之前设置好环境。
精明的读者可能已经注意到上面的短语“如果你想要设置所有这些变量”。我个人认为将所有命令行变量都转储到cron作业的shell脚本中并不是一个好主意。我更喜欢实际找出哪些是需要的,并且只包括那些。这减少了cron作业必须在其下运行的污染。例如,您的PS1/PS2脚本不太可能需要prompt变量。
如果它可以工作,你可以设置所有的环境变量-我只是喜欢绝对最小值,这样当事情发生变化时我就不必太担心了。
找出所需内容的一种方法是一次注释掉一个export,直到脚本再次中断。那么你就知道需要这个变量了。一旦它处理了最大数量的注释掉的export语句,您就可以完全删除那些注释的导出语句,剩下的语句,无论多么不可能,都必须是好的(向Arthur Conan Doyle爵士道歉)。
https://stackoverflow.com/questions/3295611
复制相似问题