I'm trying to execute a PHP script from the command line. In this script I'm accessing the apache2 environment variables but it won't let me. When I call the script from a browser it works. But I need it to work from the command line, because it should run asynchronously.
I access the environment variables via the getenv() function.
I've set the environment variables in the " /etc/apache2/sites-available/000-default.conf" file.
I need to access an environment variable in my php script. It's running on a remote server. I've added them to /etc/environment but I can't access them as the server needs a reboot.
They can be echoed when I run
source /etc/environment
so it's not a problem with the file.
But the php script isn't running as my user so it doesn't have those variables. Since it's a remote server I don't particularly want to reboot it, as I assume this would then pull in the new environment variables I wrote to /etc/environment.
I've seen I can use /etc/profile but that won't affect the apache user, which I assume is running the php scripts.
I've tried to run
echo exec('source /env/environment && echo $the_var');
but the variable still doesn't return.
Any ideas please?
Thanks in advance
This problem is occuring with Drupal but can be attributed to a general Apache - PHP configuration. In my configuration file I am determing which database to use by a server variable.
if($_SERVER['ENV'] == 'development') {
//Use connection A
} else {
//Use connection B
}
In apache I am setting the env like so:
<VirtualHost *:80>
//Other normal Apache variables set
SetEnv ENV development
</VirtualHost>
In my normal website setting, this works perfectly fine with PHP is accessed through the webserver. But I am trying to run a command using drush, which is on the command line, and it always connects to the wrong database. The problem really is command line php always connects to connection B and I don't think its necessarily drush.
How do I set the ENV to work both on apache on and the command line? The OS is ubuntu.
Drush doesn't use Apache to run commands, rather it loads and runs the PHP files directly. To set the variable globally on the server you can edit /etc/environment and add
ENV=development
You can read more about setting environment variables in Ubuntu, check out this help article.
The --uri switch will inform Drush of what domain to use in the case that HTTP_HOST is unset at runtime.
example: drush --uri=http://uri-to-development cc all
You can add it to the drushrc on each machine so that you don't have to type it every time.
A generic answer,
Apache has its own environment vs the command-line ENV ( run exportto see the difference ).
Apache also include headers/ENV vars that are meaningful only to a web server ( like HTTP_REFERER & DOCUMENT_ROOT ) which are meaningless via command-line ( you don't really have a DOCUMENT_ROOT when using the shell on a regular basis )
The problem in my opinion, starts when you're adding some SetEnv variables in your Apache configuration that you need to also include when you're testing the file via command-line ( such as custom PATH(s) etc .. or a LD_LIBRARY_PATH for Oracle i.e ... )
The bigger problem is that sometimes you can SetEnv variables in your some-local-websiteX.conf and some SetEnv were defined under the global httpd.conf
So I usually do this
1. Print the ENV variables that Apache is using
in my document root I add this small script ( it's in Python but you can adjust it to do the same in PHP )
File: www/env.cgi
#!/usr/bin/python
print "Content-Type: text/html; charset=utf-8\n"
import os
for e in os.environ:
print "export {key}='{value}' <br />".format(key=e, value=os.environ[e])
2. Creating a custom bash env file
I then copy paste the output in the browser to a local file ~/.bash_apache_env
3. Running my website via commandline
Every terminal window will reset the environment to the defaults ( unless you have some settings in your ~/.bashr i.e ofc ), so I'm running the following in each window I need.
source ~/.bash_apache_env
# then I can execute
www/index.cgi
www/admin.cgi
# etc ..
The #1 & #2 are usually just a one-time thing
Hope it helps...
I currently have a script which will run via the browser and separately via the "php" command line tool.
Now the problem is, I am able to access the Apache Environment variables while script being called from the browser, but unable to access it while the script is called via command line.
How can I get the Apache environment available to the command line script as well ?
First, you must declare your environment variable using this command:
export APPLICATION_ENV=development
Then you can get it in your application cli with the function getenv('APPLICATION_ENV');.
I've seen several questions on StackOverflow that handle how to detect the user environment when a script is served via Apache and have such a system in place which works perfectly.
The script depends on the Environment vars set by Apache.
Now I'm creating several tools that need to run in php CLI mode but I don't know how to detect the environment in CLI mode since the apache env vars aren't present there.
I'm thinking about reading the hostname of the server with gethostname() but don't know if that's the best solution and a reliable solution.
What is considered the best way to detect your environment when running in CLI mode with PHP
Clarification:
I'm not looking for a way to detect if i'm running a script from CLI, that base is covered. I'm looking for a way to determine what server my script is running on (DEV, STAGING or PRODUCTION) through CLI means, thus not reading the apache env variables set in my VHOST that are present when running the same script through a browser.
You can use php_uname('n') to get the hostname of your current machine. From there it's up to your implementation to determine whether it's production, staging, or development, either based on patterns in host name, hard-coded values, or some other configuration file.
I'd set the variable in /etc/environment (or its equivalent based on OS flavor) such as
MYAPP_ENV=STAGING.
This will auto-magically get picked up by CLI php runtime and become available in $_SERVER Global variable as such:
_$SERVER['MYAPP_ENV']
If you expect this to work whether the script runs from HTTPD or CLI, you also need to set this variable (assuming apache) in the .htaccess or the vhosts.conf apache file for you app as such:
SetEnv MYAPP_ENV STAGING
From your application code you just need to reference _$SERVER to access this variable regardless of whether the invocation is from CLI or over http.
It sucks that you have to set this variable twice on your machine - one for Apache and once for CLI but at least from the app layer you can be agnostic about the execution runtime when reading the environment variable.
By environment I presume you mean operating system - and there is a fool-proof way to do this from any PHP instance, Apache or no: the constant PHP_OS and the function php_uname().
If you mean "detect whether it's CLI or not", just test isset($GLOBALS['argv']) - it will not be set using a webserver, it will be if it's CLI. Or you can do (PHP_SAPI === 'cli').
I've always used naming matching with server hostnames:
Imagining the hostnames look like this:
- server.production.project.com
- server.development.project.com
You can determine the host using its name and some bash (or php) magic:
$server_env = `hostname | cut -d \. -f 2`; # production or development
# pure php (5.3+) method:
$server_name = gethostname();
$server_name_arr = explode( '.', $server_name );
$server_env = $server_name_arr[1];
The hostnames should most certainly be different ;)
Cheers
you likely need to set the env system wide then not just from apache, then apache scripts can read it AND cli scripts can read it from ENV , you would set them for interactive shells via /etc/profile like
APP_ENV = 'staging'
export APP_ENV
( you do it via 2 lines like that so other things in the script later can refer to APP_ENV also and get the same value, otherwise APP_ENV is not avail to that shell until its re-run )
then just check $_ENV from your programs on the cli or apache , but apache may need a restart, been a while since I've put this into practice but its great for like json encoded settings for DB connections too, but thats for another post.
To not define the environment variables twice, I did the following (in Ubuntu).
Define your variables in /etc/profile.d/env.sh, for example
export APPLICATION_ENV=production
Include that file in /etc/apache2/envvars by adding the following line:
. /etc/profile.d/env.sh
Restart apache2 and your shell to reload the environment.
$cli = false;
if (isset($argc)) $cli = true;
See: $argc
Even though this is an ancient thread you can also set and retrieve variables in php.ini where you can set values in one place and have them available through server or cli:
In php.ini:
[PHP]
MY_ENVIRONMENT = development
;;;;;;;;;;;;;;;;;;;
; About php.ini ;
;;;;;;;;;;;;;;;;;;;
; PHP's initialization file, generally called php.ini, is responsible for...
Then from cli:
php > echo get_cfg_var('MY_ENVIRONMENT');
development
and a web page (note: you have to restart apache for this variable to be available):
<?php
echo "you are in: " . get_cfg_var('MY_ENVIRONMENT');
// you are in: development
I have a number of cli scripts that rely on sh/Bash environment variables, and there's usually more than a handful. To make my life easier I just load all of them in.
The output is an array with the keys equaling the shell environment variable name, and the value being a string of what the variable was set to.
e.g. $env_var['HOME'] => "/home/user"
To use this code, make sure whatever shell you're running in supports the printenv command.
$sh_env_arr = explode(PHP_EOL, shell_exec('printenv'));
foreach($sh_env_arr as $var_lines) {
$vals = explode('=', $var_lines);
/* Some shell vars can have multiple equals signs as part of the value.
We need to make those into a single string */
if (isset($vals[2])){
foreach (range(2, count($vals)-1) as $i) {
$vals[1] = $vals[1].'='.$vals[$i];
}
}
if (!isset($vals[1])) {$vals[1] = "";}
$env_var[$vals[0]] = $vals[1];
}
I've even played games with this using containers since you can pass environment variables in from the host when they are launched. This can be helpful in getting sensitive info (db creds etc.) into the script.
As far as I'm aware you can use $_ENV and getenv() when running in the shell, just like you can while running under a web server, though the actual values available in the env will probably differ.