Path is not available in PHP exec or shell_exec - php

I've been trying and searching about a small issue I have in our php application. We use a which to find the full path of a program, however it returns with
which: no bla in ((null))
on Centos, on our own debian boxes it works just fine. I've figured out since then that (obviously) the PATH is not available in the shell from PHP. But what I can't find out is why that is the case. I've replaced the command with all sorts of commands to find out what the environment is in which I run in.
If I run an echo $PATH I actually see the directories I've set in the .bash_profile. If I run echo $SHELL I know I am using bash, if I run whoami I found out I am not the apache user but a different user, whom I changed the .bash_profile for. As I've read there's a difference between shells, so I thought it might not load the .bash_profile so I've also added the export PATH to the .bashrc.
I can get it to work with a change in the code, I could replace the which, but I am just genuinely interested in why this is not working on this centos configuration. I've now added an export PATH in the exec function before the which and it works, and should also work on other systems, but still I think it shouldn't be necessary.
Anyone know what could cause this behaviour?

Related

Can't get PHP Command Line Script to execute without prepending 'php' despite shebang added and path to symlinked executable added to PATH

I'm trying to create something similar to the laravel installer, it's a PHP Script that utilises Symfony's Console Component. It all works fine except I can't seem to get the damn thing to execute globally on my command line.
I've currently got the script(boiler) stored as /dir/dir/vendor/author/packagename/boiler.
Via Composer I also have a symlink that points to the script from /dir/dir/vendor/bin/. Automatically done via bin in composer.json.
I've updated my $PATH, which now shows /folder/folder/vendor/bin/ to point to the symlink;
My script starts:
#!/usr/bin/env php
Permissions are:
-rwxr-xr-x
I'm running Zshell on Mac OSX.
It will run if I go into the directory and type php boiler but boilerreturns command not found and if I'm in a different directory boiler also returns command not found. php boiler returns "Could not open input file: boiler"
The laravel installer runs exactly as I want mine to, using just laravel whilst anywhere on the command line.
At a complete loss. Google isn't turning up any similar issues, and neither is Stack (My searching ability may be lacking though, it's 4am.)
For those with similar issues:
Use which commandName to see if it's correctly added to your $PATH
Check the symlink is correct if it's via one
Check permissions on symlink and executable script
Post to stackoverflow so that it'll just.. fix itself.
So... which boiler returned the correct path so I tried boiler again from my home dir and it worked.
I genuinely haven't changed a single thing and been stuck for an hour. I don't understand...
Thanks all for help.

Apache/PHP unable to execute convert even when called with an absolute path

I have run into a truly strange issue for which i have no explanation whatsoever.
After setting up OS X Yosemite and my local dev environment using XAMPP, i installed ImageMagick through MacPorts. All is well, it runs perfectly fine on the commandline.
However, when executed through Apache and called through PHP, i get no output from it whatsoever.
I have done extensive research and found a variety of approaches:
Setting the path environment variable in Apache (which i tried)
Using an absolute path to the executable (which i do)
Checking if exec() is listed as a disabled function (which it is not)
Checking if convert is even callable, as in executable (which it is)
I even went as far as copying the convert executable to the local project root directory and trying to exec('./convert'); but to no avail. I always receive absolutely no output from that call. Not even an error message. Needless to say, when i run the same thing through the Terminal, it works fine.
I also tried:
Calling exec('ls'); to see if anything comes up at all (yes it does, that works fine)
Calling exec('which convert');, where i get no result at all - the call returns nothing
Calling exec('which ls'); to double-check if the problem was with which - but which ls works fine and gives me /bin/ls as a response.
Providing chmod 0777 to the executable - to no avail
Regardless from what i try or do, convert remains entirely untouchable to PHP/Apache.
Can anyone tell me why that is and how to remedy it?
Checking the Apache error logs, i found the following message:
dyld: Library not loaded: /opt/local/lib/libfreetype.6.dylib
Referenced from: /opt/local/bin/convert
Reason: Incompatible library version: convert requires version 18.0.0 or later, but libfreetype.6.dylib provides version 15.0.0
Research showed that there is a common approach changing some environment path variable that applies to Apache and its subsidiary processes while running. However, since i did not want to fiddle around like that, i went for a somewhat more raw approach:
I opened a terminal and went to the very root directory of my system. There i ran:
find . -name "libfreetype.6.dylib"
This gave me all the libfreetype.6.dylib files that were available on my system. One of them was in the XAMPP lib directory, another one was in /usr/local/lib.
I backup up the file in the XAMPP directory and then copied the one from /usr/local/lib there.
I then tested convert again through Apache and was given another, quite similar error message relating to libexpat.1.dylib. For that i repeated the copying process as above. Afterwards, convert was executable through Apache and the problem was solved.
When you run scripts and programs via your web server, they are being run by a different user. In Macs this is usually _www. The convert application can't be found because the path to its executable file (probably /usr/local/bin) isn't included in the $PATH environment setting for this user.
The simplest solution is just to prefix the command with the path to convert, i.e., exec('/usr/local/bin/convert ... ');

Cron Job uses old non-existent php file

I'm working with Yii and have to implement a script for cron.
I've got a script file, which just calls Yii and starts my php-script file.
Until this point everything is fine. If I'm updating the php-script, Cron just continues executing the old one.
Restart of cron-service, reboot of the server etc didn't help.
I also uninstalled cron and installed it again, but nothing changed. He still executes the old version of this php-script.
Anyone an idea what's wrong or what I could do to solve this? I'm using Ubuntu 12.04.
EDIT:
The cronjob script is running:
#!/bin/bash
cd ../www/protected/ ./yiic Cron ProcessPayments
The php-script
class CronCommand extends CConsoleCommand {
public function actionProcessPayments() {
...
}}
This works, but any change I make on this script is ignored by Cron.
And now I'm on this point: he executes both. My old version and the new version. I've never been this confused by something.
Assuming you have sudo on the machine it's located on...
First check to see if it's located in the usual cron directories /etc/cron.*
sudo find /etc/cron* -mount -iname yiic
If nothing shows up there then search the entire filesystem because otherwise you'll start having to search a lot of other places manually and it takes more time than running a find
sudo find / -mount -iname yiic
In both find commands if the filename is or has ever been anything other than yiic do yiic* so that it searchs for anything that starts with yiic
Once you have found the copies, if there are any others, remove every single one except the newest one, or even that one and then reinstall the script on the machine from version control.
Edit:
Probably more than you really care about, but the find command breaks down like this:
sudo - elevated priviledges so you can search everywhere as opposed to where you're user can read
find - command to look for thigs
/ - the starting point for the search, can be anywhere
-mount - this tells find not to search other filesystems
-iname - case insensitive name to search for
yiic - the search term
Locate all your copies of the script using the find command and delete those copies not needed. Restart cron after you have chosen the copy of the script you want to execute. My guess is a copy of the script might be hanging around in a directory (e.g. config.daily or something similar).
HTH
I had a similar problem. A script in /etc/cron.d was still executed in the old fashion after modifying it. I solved the problem by sending a SIGHUP to cron:
sudo pkill -SIGHUP /usr/sbin/cron

Append to the Apache Environment Path

I have a web accessible PHP script that is using a shell command to drop PDFs to text. I installed Poppler, and am using pdftotext, via MacPorts. I am able to run the command successfully from the CL, and when supplying the full path within the PHP script to '/opt/local/bin/pdftotext'. So, I know that my $PATH is correct and the permissions are sufficient, yet I am still getting an exit status of 127: Command Not Found, when attempting to do simply 'pdftotext' in the exec().
I have tried the answers from How do I add paths to the Apache PATH variable? and http://lists.apple.com/archives/macos-x-server/2008/Sep/msg00433.html. I modified both the /etc/paths and /etc/profile, and added /etc/paths.d/macports all pointing to '/opt/local/bin'. setenv, apache_setenv, etc all had no effect also.
I am using a MAMP (1.9 I think) install for my local development, OSX 10.6, PHP 5.3.5, all a little behind I know :-) ... my $PATH is modified to point to the MAMP bin/php
/etc/paths.d/macports will influence on PATH variable for macports, not for the Apache. You probably need to add /etc/parhs.d/apache (or else) to do what you need.
Edit: also check this and this threads for solutions. It is somewhat outdated but still can help.

How to make a PATH variable availailable to Apache? (OSX Lion)

I have a Python script that is using MySQLdb on OSX Lion. To get MySQLdb to work, I had to add
export DYLD_LIBRARY_PATH=/usr/local/mysql/lib:$DYLD_LIBRARY_PATH
to my ~/.bash_profile. The python script, when executed from the command line, works just fine.
When I try executing the same python script from a PHP script using the exec() function, the python script is unable to locate the library path. Here's the err msg from the Apache log:
ImportError: dlopen(/Library/Python/2.7/site-packages/_mysql.so, 2): Library not loaded: libmysqlclient.18.dylib
Referenced from: /Library/Python/2.7/site-packages/_mysql.so
Reason: image not found
I'm assuming this is a user issue though I'm unclear on how to fix it.
Where should I put this path so that it will be globally available to all scripts and users on my machine? (well at least, to Apache and Root)
Solution: creating a soft link did the trick:
sudo ln -s /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/lib/libmysqlclient.18.dylib
This solution was taken from comments on this post. Perhaps this solution will help another struggling with MySQLdb on OSX.
Though I'm still not clear on why it worked on one user and not another - or, rather, to which file the above mentioned export should have been saved in order to make it available to all. Any explanation on this would be appreciated.
It looks like you need to modify sys.path array. It initialized from the environment variable PYTHONPATH: http://docs.python.org/library/sys.html#sys.path
For Apache you can add PYTHONPATH entry to the EnvironmentVariables section in /System/Library/LaunchDaemons/org.apache.httpd.plist that will make it available to anything Apache runs. See man launchd.plist for details.
For root you can add an export PYTHONPATH to /etc/profile which will make it available to all sh and bash login shells. See man bash for details.

Categories