does PUTENV affect the variable in other scripts - php

If I set a variable using putenv, will other scripts be affected by this.
My understanding is that it is script specific, is that correct? if two different scripts are running at the same time on the server, will it affect the other script?

Yes, the env vars are specific to each particular invocation of a program/script. Just like each program can have its own working directory, its own stdin/stdout/stderr, etc... One script's environment cannot affect another's, unless they're in a parent/child relationship.

No, other scripts will not be affected.
The environment variable will only exist for the duration of the current request.
The following sample code can be run using the PHP CLI utility.
<?php
putenv("FOO=bar");
print("PHP says FOO=" . getenv("FOO") . "\n");
?>
Here is the output of the program and the resulting environment.
$ php putenv.php; echo echo says FOO=$FOO
PHP says FOO=bar
echo says FOO=

Related

shell_exec in PHP is not working

shell_exec()
is not working on my localhost. I read a lot of websites to resolve this issue but can't find a solution.
This code:
$output = shell_exec("env");
print "<pre>$output</pre>";
Doesn't give any output.
I checked in php.ini disable_functions but shell_exec is not disabled.
I did error_reporting = E_ALL but again no output (no error). All I get is just a blank screen. Even safe_mode is off.
If I write echo "BULB"; after the above code it is printing "BULB".
What could be the issue?
What info are you expecting to get from env? From your comments, it seems to me as if you're trying to use a Linux command on a Windows system -- that's never going to work.
On Linux systems, the env command on its own like that returns a list of environment variables that have been defined. However env is not a valid command in Windows.
If you're simply looking for the list of environment variables, this can actually be obtained in PHP without having to go to a shell command. PHP has a built-in global variable $_ENV which contains a copy of all the environment variables that were defined when the program stated. Simply print_r($_ENV) to see them.
On the other hand, if you really need to use shell_exec() for some reason, then you need to take into account the operating system that you're using. On Linux you would use env command. The equivalent on Windows is set without any arguments. So your code becomes:
$output = shell_exec("set");
Note that the format of the output may not be identical to what you'd get on Linux, so if you're parsing it, that code will have to change too.
If you need your code to be able to run on multiple platforms then you would need to write additional code before the shell_exec() call to determine the operating system and work out the correct command to use.

Why won't shell_exec execute files but does execute simple commands?

Is there any reason why I can not complied files in PHP's shell_exec/exec/system function?
Example of something that does work in command line and PHP's shell_exec function:
<?php
$data = shell_exec("ls");
echo $data;
?>
Example of something that does not work in PHP's shell_exec function but will work in command line (I can confirm that):
<?php
$data = shell_exec("./c-compiled-file argv1 argv2 argv3");
echo $data;
?>
Is there anything I can do on my server so this will work? I've looked everywhere and no solutions I found fixed the problem. The compiled file is in the same directory as the PHP script as well, it just won't execute it. Also if you're asking, yes I have tried this with SSH2 and it still will not execute.
Also PHP is not in safe mode and NO functions are disabled.
Some common glitches when executing external commands from PHP that work fine from shell:
Command uses relative paths but PHP is launched from an arbitrary location:
Use getcwd() / chdir() to get/set working directory
PHP and shell run with different user credentials. This is often the case when PHP runs through a web server.
PHP and shell run different commands. Many people call stuff like exec("foo $bar") and doesn't even check what "foo $bar" contains.
No error checking is done. The bare minimum is to capture and print standard output, standard error, status code and, of course, all PHP error messages including warnings and notices.
You can redirect stderr to sdtout
You can use a PHP function that allows to capture more information, such as exec()
The web server is disallowed to execute the command at operating system level.
Lookout for SELinux or similar tools.
Just a guess, but the binary you're trying to execute might not have the proper permissions. Prepeding it with ./ in the command line forces it to execute, but PHP probably strips that for security purposes. Try this:
chmod +x c-compiled-file
You want to use system in the second case, and not shell_exec.
system executes an external program and displays the output.
shell_exec executes a command via shell and returns the complete output as a string.
and for good measure:
exec simply executes an external program.
Furthermore you want to make sure your external program is executable and (though you have stated it, I'll restate this) has execute permissions for the user which is running the web server. You also want to make sure the directory your external program is running in has the ability to write to its directory or /tmp or whatever output directory you have set.
Finally you should always use absolute paths for executing things like this in cron or php or whatever... so don't use ./c-compiled-file argv1 argv2 argv3, but instead use /home/username/c-compiled-file argv1 argv2 argv3 or whatever the full path is.

Setting PHP enviromental variable while running command line script

I need to run a PHP script from command line and I need to set some environmental variables. Unfortunately, following does not work:
php -dAPPLICATION_ENV=staging script.php
What I'd like to accomplish is having APPLICATION_ENV variable set.
APPLICATION_ENV=staging php script.php
The variable will be available in the $_SERVER array:
echo $_SERVER['APPLICATION_ENV'];
There is no way to set environment variables from the command line specifically for the execution of a script by passing options to the PHP binary.
You have a few options:
Set the variable globally on the system.
Set the variable on the command line before calling the script. This will persist in the environment after your script has finished executing, which you may not want.
Wrap the PHP script in another script, allowing you to create a temporary variable that exists only for the duration of the script.
Use a command line option instead of an environment variable.
The last two options are probably the cleanest way to do this, in that the variable created only exists for the run time of your script.
The implementation of option 1 is system dependent.
The implementation of option 2 is also system dependent - on Windows you would do set APPLICATION_ENV=staging&& php script.php and on *nix it would be export APPLICATION_ENV='staging' && php script.php.
If you were to go for option 3 you might be tempted to go for a shell script, but this is not portable (you would need a batch file for Windows and a shell script for *nix environments. Instead, I'd suggest you write a simple PHP wrapper script, something like this:
<?php
putenv('APPLICATION_ENV=staging');
include('script.php');
This allows you to leave your target script unchanged and set the environment variable for the script's session only.
A more complex wrapper script could easily be created which would allow you to specify variables on the command line, and even dynamically specify the script which should be executed when these variables are set.
Option 4 can be implemented using the $argv variable:
<?php
$applicationEnv = $argv[1];
// rest of you script
...and call the script like:
php script.php staging
However, it occurs to me that you seem to be indicating to the script which environment is running in (staging, dev, live, etc) - in which case it might be simplest to set a server-wide variable, and rename it as necessary to prevent collision with variables that other applications may be setting. That way you can simply invoke the script and not need to worry about this. This is assuming that you staging environment runs on a different machine to the live (which it should be).
When you execute a PHP script from the command line, it inherits the environment variables defined in your shell. That means you can set an environment variable using the export command like so:
export APPLICATION_ENV='staging'
Here is an example for setting one envirnnomental variable :
ENV_VAR='var' php script.php
Just in case you want to set multiple variables
Try this :
ENV_VAR1=1 ENV_VAR2=2 ENV_VAR3=3 php script.php
You can set a variable in /etc/environment like FOO="bar" which is then accessible with getenv() in both CLI and web requests. You may need to relog for this change to take effect.
Try using putenv and pass the variables through parameters
php script.php APPLICATION_ENV=staging
And in the script.php code:
for($i=1;$i<count($argv);$i++){
putenv($argv[$i]);
}
I have the same situation and i use next code (it works for me):
export APPLICATION_ENV=staging && php script.php
Hope it will helpful for you too.

Cleanest way to read config settings from PHP file and upload entire project code using shell script

I am a newbie with shell scripting so need a few ideas on parsing a PHP file using a shell script.
Ours is a PHP project and I am improving our shell script which is used to upload code to production server.
There is one PHP config file production.settings.php which needs to be read during upload, for a few constants -
BASE_PATH (path to project root on prod server)
db_host, db_name etc. (database settings of prod database - to be used for taking a backup of the database before upload)
Question
How to read the value of the constants?
They are defined like this:
define("BASE_PATH","/path/to/project/root");
How to read the first uncommented value of the constant?
Note - The constant may be defined more than once in the same file (let's assume the possibilty - this may happen by mistake or there may be commented instances of the line)
So far I am only able to get the number of lines containing the string define("BASE_PATH" using grep in my shell script -
cd ..
PROJECT_ROOT=$PWD
result= grep -ic 'define("BASE_PATH",' $PROJECT_ROOT'/config/main.settings.php'
echo "see"$result
Is this method of parsing good enough or a yml file would be better? Is there any shell command/snippet for doing this so that I can get the result by writing lesser amount of code?
Updates
Check my other questions for more details on this:-
Manipulating an array (printed by php-cli) in shell script,
Assigning values printed by PHP CLI to shell variables,
Initiating dynamic variables (variable variables) in bash shell script
just do it using the php, then call your shell script to invoke the php script.
Assuming you have your bunch of defines defined in defs.php:
define('NAME', 'JOHN');
define('HOBBY', 'FISHING');
then create a php script get_defs.php:
require_once 'defs.php';
$const = get_defined_constants(true);
foreach($const['user'] as $k => $v) {
echo "export $k=$v";
}
then in your shell script, run it like so:
`php get_defs.php`
What happen is, get_defs.php will output bunch of export KEY=VALUE, then shell will run those commands outputted by your php get_defs.php.
Why don't you just code with PHP CLI? That's what you understand? Also maybe you could put constants in a ini file and read them?
If youre comforttable with PHP then use PHP to write the shell script. IF you go this route i would move all config settings to a config file... INI, YAML, XML, whetever floats your boat. Then i would modify the bootstrap of the application that defines your constants to also read from this config file. That way you can use it in botht your script and the app without having to change it.

How can I troubleshoot why my PHP script won't work in cron when it does from the command line?

I've got a script that calls two functions, A and B, from the same class. A creates an Amazon virtual server and B destroys one, both via shell_exec()'s of Amazon's command line tools. The script, doActions.php, pulls actions from a queue. If the action is "create" it creates an instance; when the action is "destroy" it kills one.
The script works fine to execute both A and B when I execute it from the command line: php script.php.
When I put it on a cron, it runs but only successfully runs the B function. It deletes destroys instances but won't create them.
The point of failure is clearly function B. It chokes at the first and most important shell_exec, returning and echoing nothing.
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');
Unless you know something specific about the way Amazon's command line tools work, please suggest to me reasons why a shell_exec might work in one case and not the other.
Another shell_exec in the same place behaves as expected:
echo $string = shell_exec ('echo overflow');
My guess is that it has to do something with permissions. But when I have it run shell_exec('whoami') it return "root," and when I su and run the command it works fine. I'm having a hard time thinking of creative ways to troubleshoot why my PHP script won't work in cron when it does from the command line. Can you suggest some?
When something runs from the command line but refuses to do so within cron, it's often an environment issue (path or some other environment variable that's needed by the code you're running).
For a start you should modify the script to output the current environment (shell_exec('env')?) at the very top and examine the output from the command line and cron.
Hopefully, there will be something obvious such as AMAZON_EC2_VITAL_VAR but, if not, you should move the cron environment towards your command line one, one variable at a time, until it starts working.
A quick test to ascertain this. From your command line, do:
env >/tmp/pax_env.sh
Then run your PHP script from a shell script which first executes:
. /tmp/pax_env.sh
so that the environments are identical.
And keep in mind that su on its own doesn't give you the same environment as you'd get from logging in directly as a specific user (su - does, I think). You may want to check the behaviour for when you log in as root directly.
Re your comment:
Yes, I do believe you've got it. I'm likely going to mark your answer as correct but need you to suffer through a few addendums about your clever solution. First of all, what's the best way to execute the pax_env.sh script? Does shell_exec() work?
Never let it be said I didn't work for my money :-) No. The shell_exec will almost certainly be running a sub-shell so the variables would be set in that sub-shell but would not affect the PHP parent process.
My advice, if you wanted all those variables set, would be to create a shell-script consisting of all the commands in /tmp/pax_env.sh (probably prefixing each with export) followed by the command you currently have running in cron, something along the lines of:
export PATH=.:/usr/bin
export PS1=Urk:
export PS2=MoreUrk:
/home/user/pax/scriptB.php
Then run that script from cron rather than /home/user/pax/scriptB.php directly. That will ensure the environment is set up before your PHP code is called.
Astute readers will have noticed the phrase "if you wanted all those variables set" above. I don't personally think it's a good idea to dump all your command line variables into the shell script for the cron job. I'd prefer to actually find out which ones are needed and only include those. That lessens the pollution your cron job has to run under. For example, it's unlikely that the PS1/PS2 prompt variables will be required for your PHP script.
If it works, you can set all the environment variables - I just prefer the absolute minimum so I don't have to worry too much when things change.
A way of finding out what's needed is to comment out one export at a time until your script breaks again. Then you know that variable is needed. Once it works with the maximum amount of export statements commented out, you can just delete those commented export statements altogether and what remains, however improbable, must be okay (with apologies to Sir Arthur Conan Doyle).

Categories