AWS Elastic Beanstalk: Running Cron.d script, missing Environment Variables - php

I'm trying to run a PHP script that is triggered by a cron script (in cron.d). The script is triggered properly but it is missing the Elastic Beanstalk "Environment Variables" that are stored in the $_SERVER superglobal. The script is being run as the user "root" for now, but it's not in the same environment that has the environment variables. The variables are set correctly, if I run the script from a full shell it runs just fine.
Where are the "exports" for these variables? Where do they get set? I found the SetEnvs for Apache in /etc/apache/conf.d/aws_env.conf. I can't find anything in the user's .bashrc, .bash_profile, etc. Is there a workaround? A better way to do this?
Thanks.

While searching for solutions to the same problem I ran into this blog post: http://sebgoo.blogspot.nl/2013/10/elastic-beanstalk-cron-command-and-rds.html. To summarize, you can load the Elastic Beanstalk environment variables using the opt/elasticbeanstalk/support/envvars file:
0 3 * * * . /opt/elasticbeanstalk/support/envvars; some_command
Hope this helps!

I just found this, using
grep -r "export MY_VAR" /
EDIT: Amazon seems to move the file location from time to time. Current location is:
/opt/elasticbeanstalk/support/envvars
So I think I'll just include (source [file path]) that in my script before calling my php script. Still seems like a funky way to do things. I'm still in for better solutions.
I was running PHP via bash script triggered by cron. So to setup the environment, I would do something like this:
#!/bin/bash
source /opt/elasticbeanstalk/support/envvars
php -f my-script.php
See #userid53's answer below for PHP solution.

I spent several hours trying to figure out how to pass Environment Variables to PHP CLI. I tried:
setting in ebextensions config: $ source /opt/elasticbeanstalk/support/envvars.d/sysenv
setting all my Environment variables to config file.
No matter what I tried, env variables won't pass to PHP CLI.
When I log to my EC2 instance as ec2-user and do this: $ echo $ENVIRONMENT I get prod. If I do it as $ sudo su and then $ echo $ENVIRONMENT I get prod.
If I manually run the PHP CLI file (used in cronjob) my script works. When it runs automatically (via cronjob) Environment Variables are not passed to my script.
Here's what I did. Put this in your cronjob entry script:
$variables = '/opt/elasticbeanstalk/support/envvars.d/sysenv';
if (file_exists($variables) && is_file($variables)) {
$contents = file_get_contents($variables);
foreach(explode("\n", $contents) as $line) {
if (empty($line)) continue;
$new_line = str_replace('export ', '', $line);
$first_part = strpos($new_line, '=');
$last_part = substr($new_line, $first_part, strlen($new_line));
$variable_value = str_replace(array('=', '"'), array('',''), $last_part);
$variable_name = substr($new_line, 0, $first_part);
putenv($variable_name."=".$variable_value);
}
}
It extracts each line from /opt/elasticbeanstalk/support/envvars.d/sysenv file, removes the export part, gets the variable name & value, and sets it via putenv() function.

It's works for me with a Laravel Project
* * * * * root . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/www/html/artisan schedule:run 1>> /dev/null 2>&1
For a non Laravel Project you can test that:
* * * * * root . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /path/to/your/script.php 1>> /dev/null 2>&1
Hope this helps!

in version 3.0.3 it has changed again, use this to export your envars in command line
file="/opt/elasticbeanstalk/deployment/env"
while IFS=: read -r f1
do
export $f1
done <"$file"

I know this is an old thread but I recently needed to do something similar in a Node.js environment deployed on Elastic Beanstalk; for what I could tell, the file /opt/elasticbeanstalk/support/envvars is not present on Node.js environments. I ended up writing a Python script that loaded the environment variables from /opt/elasticbeanstalk/bin/get-config, and then executing my Node.js script from there.
The code I ended up using was:
#!/usr/bin/env python
import os
import subprocess
from subprocess import Popen, PIPE, call
import simplejson as json
envData = json.loads(Popen(['/opt/elasticbeanstalk/bin/get-config', 'environment'], stdout = PIPE).communicate()[0])
for k, v in envData.iteritems():
os.environ[k] = v
call(["babel-node", "/var/app/current/<script_name>.js"])
Hope this helps anyone needing to do the same.
For the complete configuration I deployed, you can refer to my original post How to set environment variables in Amazon Elastic Beanstalk when running a cron job (Node.js)

I added the following line to my shell script:
source /opt/elasticbeanstalk/support/envvars .bash_profile
So my script, which is executed by the crontab, looks like this:
#!/bin/sh
source /opt/elasticbeanstalk/support/envvars .bash_profile
# do some php stuff

In case you need something similar for CodeIgniter:
* * * * * root . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/www/html/index.php controller method
Example:
* * * * * root . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/www/html/index.php tasks pushNotification
A more descriptive alternative:
* * * * * root source /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/www/html/index.php tasks pushNotification

AWS and EBS are changing the location of the env vars from time to time. At the current time, I was able to retrieve the env vars from the following path (I've python EBS)
/opt/python/current/env

Related

cron commands do not run, getting output /bin/sh: 1: php: not found

I have the following inside my crontab -e
0,30 * * * * cd /usr/local/bin && php /var/www/artisan my_command > /var/www/storage/logs/cron.log 2>&1
But I get the following inside /var/www/storage/logs/cron.log.
/bin/sh: 1: php: not found
I tried running the following for reference:
# which php
/usr/local/bin/php
# whoami
root
I am running cron from inside a docker image (OS: Ubuntu) in a Laravel project.
I tried changing the path in different ways, but it still gave the same error.
There were a lot of similar questions, but I didn't manage to find my answer...
The current directory isn't in the PATH (and it shouldn't be).
Simply skip the useless cd command and run /usr/local/bin/php instead:
0,30 * * * * /usr/local/bin/php /var/www/artisan my_command > /var/www/storage/logs/cron.log 2>&1
Thanks to #Some programmer dude.
I would like to add some details, since I was not originally able to understand what he meant.
Basically when I was calling php cron would look for the file in every folder inside the PATH, but NOT the current directory (unless it is inside the PATH).
Sure, simply removing the cd is the best solution.
But to better explain the issue another perfectly working solution would be this one:
0,30 * * * * cd /usr/local/bin && ./php /var/www/artisan my_command
The only difference here, from the command I was originally using, is that I am specifying to use the current path with the ./.

How dynamically set variables on Cron?

I'm trying to make a cron file to be placed in /etc/croon. d. My problem is I don't want keep this file updated, so I'm looking for a way to get the software version dynamically from a file.
I have few other variables, but for now I think the problem is with $ (cat /software/VERSION), it works very well in shell script but not on croon.
#!/bin/bash
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
APPLICATION_ENVIRONMENT=SOME_STRING
VERSION=$(cat /software/VERSION)
HOME=/var/www/scripts/$VERSION/cron
CRON_LOG_DIR=/var/www/scripts/logs
*/2 * * * * root cd $HOME & php -f $HOME/do_something.php $APPLICATION_ENVIRONMENT >> $CRON_LOG/something.log
This is the output on cron log:
(root) CMD (cd $HOME & php -f $HOME/do_something.php $APPLICATION_ENVIRONMENT >> $CRON_LOG/something.log)
(CRON) ERROR chdir failed (/srv/www/tdp/public/$VERSION/backend/cron): No such file or directory
Cron table is not a shell script! You cannot put variables there.
You have to call a script from the cron and do the logic there.
If you really have to set environment variables in cron, you can do it like this
*/2 * * * * root SHELL=/bin/bash VARIABLE=something cd $HOME & php -f $HOME/do_something.php $APPLICATION_ENVIRONMENT >> $CRON_LOG/something.log
But it might not work and you might make a mistake (I am not 100% sure I made the syntax right; it's not easy and it's not necessary).
You should put as little logic to cron as possible.
Also, you should not edit the cron file directly; use crontab -e instead, it will check if you made correct syntax.
So you should do
*/2 * * * * user /home/user/your-script.sh
and set the variables in your script. (You also shouldn't run programs as root if it's possible.)

PHP `exec()` doesn't work if run by Cron

I have a PHP script that is being called every minute by crontab like this:
* * * * * /usr/bin/php /var/www/html/cronjobs/watchdog/watchdogExec.php
The script executes a number of other PHP scripts and passes a variable like so:
$ccmd = "nohup sudo /usr/bin/php watchdog.php " . $var . " &";
exec($ccmd);
When called from a browser, watchdogExec.php runs fine and does its job. However when I added the cronjob, the script is not working and is spamming mails with the following error:
No entry for terminal type "unknown";
using dumb terminal settings.
This error appears the same number of times exec() is called, so I figured that must be the issue. I searched and read about cronjob not running commands in a terminal, and I tried setting the environment in the crontask, but it did not help. Apparently PHP is printing that error, but I haven't found anything in their documentation about it.
* * * * * /usr/bin/env TERM=xterm /usr/bin/php /var/www/html/cronjobs/watchdog/watchdogExec.php
I am running CentOS 7.
Edit:
Searched some more and found out about PHP environment variables. Someone fixed a similar problem by adding the following in their PHP script. However this is not fixing my problem, it only stops the mail spam. The script is still not working.
putenv('SHELL=/bin/bash');
putenv('TERM=xterm');
Have you tried using full paths in your exec statement too? Also try adding the TERM environment variable:
$ccmd = "nohup /usr/bin/sudo /usr/bin/env TERM=xterm /usr/bin/php watchdog.php " . $var . " &";
I do this with a 'shell script wrapper'. I add a file phpcron.sh with
#!/bin/bash
php -f filename.php
and add this to crontab.
* * * * * /var/www/phpcron.sh

cron running php file which uses shell_exec and redis-cli

I have a cronjob that runs the following:
* * * * * php /path/to/phpfile.php >> /cronlog.txt
when I run the php file in bash everything works, but when the cronjob runs it, one command fails:
shell_exec("redis-cli ping"); and returns an error that sh: 1: redis-cli: not found
Does anyone know why the cron user using PHP shell_exec would not be able to use the redis-cli command?
update
git diff /env_term.txt /env_cron.txt
-SHELL=/bin/bash
-TERM=screen
-SSH_CLIENT=*************
-SSH_TTY=/dev/pts/0
-USER=root
-LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.
-TERMCAP= { a bunch of giberish }
-PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
-MAIL=/var/mail/root
-STY=*************
-PWD=*************
-LANG=en_US.UTF-8
-HOME=/root
-SHLVL=2
LANGUAGE=en_US:en
+HOME=/root
LOGNAME=root
-WINDOW=2
-SSH_CONNECTION=*************
-LESSOPEN=| /usr/bin/lesspipe %s
-LESSCLOSE=/usr/bin/lesspipe %s %s
-_=/usr/bin/env
+PATH=/usr/bin:/bin
+LANG=en_US.UTF-8
+SHELL=/bin/sh
+PWD=*************
Did you check if your PATH variable is the same when cron is called.
A quick check is to add a dummy cron job to output the current environment variables passed to cron:
* * * * * env > /tmp/env.out
And then compare this output with when you run the env command from the terminal
try this solution:
cat cronjob
* * * * * php /path/to/phpfile.php >> /path/to/cronlog.txt
Then:
chmod +x cronjob
/etc/init.d/crond start #redhat based servers like centos
/etc/init.d/cron start #debian based servers like ubuntu
crontab cronjob
You can give absolute path of redis-cli to avoid any such issue related to environment variable.

Running a php script from cron not picking the $_SERVER['host'] wheras running from CLI works

As stated, when I run a direct PHP script like so:
# /usr/bin/php path/to/script.php
I am able to use environment variables
But when I have this script running from cron:
* * * * * /usr/bin/php path/to/script.php
The script runs but all my environment variables are null.
How do I simulate the CLI via the cron?
(on centOS / linux)
You can write a script which sets the environment variables you want to be present:
#!/bin/bash
export ENV_VAR_ONE="value one"
export ENV_VAR_TWO="value two"
/usr/bin/php path/to/script.php
and then invoke that script from cron instead.

Categories