18

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.

ChrisR
  • 14,370
  • 16
  • 70
  • 107
  • possible duplicate of [In php, how to detect the execution is from CLI mode or through browser?](http://stackoverflow.com/questions/1991346/in-php-how-to-detect-the-execution-is-from-cli-mode-or-through-browser) – Marc B Oct 21 '11 at 15:40
  • 3
    Don't think this is a duplicate of that question. That one was concerned with telling whether a script was being run by a web server or from a commandline. This one is more about getting environment vars when running from the commandline. – GordonM Oct 21 '11 at 15:43
  • Indeed, i've elaborated a little further in my question – ChrisR Oct 21 '11 at 15:56
  • you can use this library: https://github.com/arcanisgk/WEB-CLI-Detector –  Aug 01 '22 at 18:01

10 Answers10

13

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.

Mark
  • 999
  • 9
  • 19
  • 1
    Seems like the most stable method as of now. One should take extra care not to change the hostname after this though. – Halil Özgür May 24 '12 at 08:59
  • 2
    how about a multi vhost scenario. I wish I could take the ENV based on the current dir and the vhost config. – Nikola May 22 '14 at 10:19
  • you can use this library: https://github.com/arcanisgk/WEB-CLI-Detector –  Aug 01 '22 at 18:01
12

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.

bhavinb
  • 3,278
  • 2
  • 28
  • 26
1

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.

yoshz
  • 11
  • 1
1

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').

DaveRandom
  • 87,921
  • 11
  • 154
  • 174
  • i'm looking for neither of both since both my staging and production server run the same OS and i don't need to detect wether or not it's CLI i'm running. Check the OP, i've elaborated a little further. – ChrisR Oct 21 '11 at 15:59
  • @ChrisR ...and how do you do it under Apache? `$_ENV` or in some other way? i.e. where do the Apache environment variables get the values from? – DaveRandom Oct 21 '11 at 16:01
  • SetEnv in my vhost config en getenv() in PHP, simple as pie :) – ChrisR Oct 21 '11 at 19:48
1

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

smassey
  • 5,875
  • 24
  • 37
1

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.

0

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
Chris Adams
  • 651
  • 6
  • 8
0

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.

wbrco01
  • 1
  • 1
0
$cli = false;
if (isset($argc)) $cli = true;

See: $argc

John Watson
  • 2,554
  • 1
  • 17
  • 13
  • I'm not looking for CLI detection, i need environment detection, detecting what server the script is running on, i've elaborated a little further in my question – ChrisR Oct 21 '11 at 15:58
  • Probably the most reliable way to detect what server the script is on is to put a special file on each server and make that file part of your deployment process. Put a server.dev file on the dev server, server.prod on the production server, etc. A lot of applications go one further and put the configs themselves in server specific files (e.g. config.dev, config.prod, config.stage). Then your config loader just tests for the existence of each of those files, optionally loads them if they contain configuration data, and you know what server you're on and have a server-specific configuration. – John Watson Oct 21 '11 at 22:39
-1

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.

GordonM
  • 31,179
  • 15
  • 87
  • 129
  • 5
    Yes, but PHP CLI doesn't know of the SetEnv variables set in the apache config. That's what i'm trying to solve. – ChrisR Oct 21 '11 at 15:56