Messing with environment variables for one command - php

I'm currently planning to use Symfony's ProcessBuilder, which allows to set some environment variable which will be passed onto a proc_open call.
I need for a certain command to change the TMPDIR, and to restore it afterwards, so I was wondering if, when the modified env (and thus modified value for the $TMPDIR env variable) would be restored after the call, or do I need to restore it myself ? And will this value be indeed changed if need be for a particular command (which is ghostscript in my case) ?
Thanks

After some tests, it seems that the $env parameter in the proc_open function is really to modify the environment only for the duration of the run process. So it basically covers my question. :}

Related

Export environment variable from PHP CLI

I'm looking for a way to export an environment variable from a PHP script running with PHP CLI. The putenv function only permit to set variable that will be existing during script execution, not after.
My use case is a PHP script used as bash autocompleter function. In this type of function, we have to set COMPREPLY variable that must contain the list of available options (as a bash array). Currently, I'm setting this variable by this way :
COMPREPLY=( $(php myscript.php) )
I would like to have possibility to set COMPREPLY variable and some others (especially for action on default behavior on empty options list).
Thank you in advance

Passing variables from PHP to python

I have a python script. When I run the script from the command line as:
python upgrade.py arg1 arg2
The script runs successfully.
Now I am trying to pass the same variables via PHP code using:
passthru("python upgrade_device.py $arg1 $arg2");
The script does not execute.
I am accepting the arguments using:
sys.argv
The arguments are passed correctly
I have tested using print
This is specific command where the execution fails:
child=pexpect.spawn('ssh admin#%s'%ip_addr)
ip_addr is one of the arguments passed from PHP. Right below this command I am ip_addr so as to find what value is passed to the command. and the value is as expected.
I have the ip_addr variable stored correctly.
I have even type casted it to string so that should not be problem.
In general, is there a difference of format in passing variables from the command line and passing from PHP
For my understanding i think passing it through shell and php is the same, i can't be sure for 100% but that what i know from experience.
For your case if you have verified with print that it's the right string to pass (mean take the output and test it in the terminal if it work) if it work, than verify if the python script file is in the same directory as the php script file, because the shell will be opened at the current php script path. And so the shell command should respect that. For example let assume php script file is in the root "/", and python script file is in "/myPythonScripts/imageProccessing/" then when you execute something like "python myPyScript.py 646545645" for example, in this example in php you should execut "python ./myPythonScripts/imageProccessing/myPyScript.py 646545645", as i said the shell is launched on the php script path.
Now if that's not the problem, then try escaping the string first, with escapeshellcmd(). And see what it give. There is characters that are not supported by the shell, or that have a certain signification and parsed by the shell differently. make sure none of them is passed as argument.
In case none of the above is helpful try to use execshell() instead, and see what it give. Too probable that will not make a difference.
Edit: In case nothing helped, try to change just a bit the way of the exchange is done, and use the way it's done in this response using json https://stackoverflow.com/a/14048046/7668448 (it's a kind of more convenient)
Please if any of that solved the problem, precise in a response which one was! I hope it will help. Also if it's not your case it may be useful for other persons in the future. Think also about giving the solution when you do! (i also personally interested too)

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.

How can I access environment variables within a shell script called by PHP?

Here is how I set the variable within my Apaches VirtualHost Container
SetEnv MY_VAR "/opt/"
Now, PHP can perfectly access this vairable:
echo $_SERVER['MY_VAR'];
/opt/
However, if I call a shell script from my PHP code
passthru('/path/to/myscript');
MY_VAR is empty within /path/to/myscript.
If I however modify the call like this, it works:
passthru('export MY_VAR='. $_SERVER['MY_VAR'] .'; /path/to/myscript');
Is there a better way to pass all environment variables to the shell script? Since I need to pass multiple ones.
I also tried system(), exec(), backticks and shell_exec(). They all show the same behavior, as passthru().
If you use putenv("MY_VAR=test"); the environment value is passed on to the invoked shell command. (but it is not put in $_ENV)
So you could simply do something like
foreach ( $_SERVER as $k=>$v ) putenv("$k=$v");
Try proc_open.
proc_open('/path/to/myscript', $descriptorspec, $pipes, null, $_SERVER);
You could pass an array with the environment variables as an option.
If you use phpinfo() in your first page, you will see that your env variable (MY_VAR) is not listed in the "Environment" box, but in the "Apache Environment" (if this is the webserver you use).
So, it seems that "getenv" not only gets its values from the environment, but also from Apache environment, which (it seems) is not inherited when launching something by passthru.
In the script executed by passthru, I only see env. vars listed in the "Environment" box, so it is consistent.
So, for each variable you want to export to the passthru script, you should use:
putenv('MY_VAR ='.apache_getenv('MY_VAR'));
Easy to do with an array and a for loop.
I guess it's because when you call SetEnv you're modifing your current shell environment. When you subsequently when you call passthru, your existing env is destroyed along with any non exported variables, and a "fresh" environment given to /path/to/myscript.
Can you instead pass env variables on the command line, as parameters to the /path/to/myscript -MY_VAR=/opt ?

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