Custom php.ini file in when executing 'php' as a shell script - php

I'm running php as a shell script.
(I am not sure if "shell script" is correct. The file starts with #!/usr/bin/php.)
This works great. But the MongoDB class doesn't get loaded as the correct php.ini file (having extension=mongo.so) is not used.
How do I make it use that php.ini file?
I already tried #!/usr/bin/php -c /usr/local/lib/php.ini
But I still get the same error - Fatal error: Class 'Mongo' not found
What can be done?

Try putting php.ini in the same folder as the php binary. It seems to look there first.
I know this because I used a very powerful and useful command-line program called strace to show me what's really going on behind my back
$ strace -o strace.log php --version
$ grep php.ini strace.log
Strace digs out kernel (system) calls that your program makes and dumps the output into the file specified after -o
It's easy to use grep to search for occurrences of php.ini in this log. It's pretty obvious looking at the following typical response to see what is going on.
open("/usr/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/php.ini", O_RDONLY) = 3
lstat("/etc/php.ini", {st_mode=S_IFREG|0644, st_size=69105, ...}) = 0

Edit .bashrc located at your home directory and add this line:
alias php='php -c /path-to-custom/php.ini'

In this particular situation. I would
Check to see if the Mongo module is loaded (using extension_loaded() or class_exists())
If not loaded, try to load the Mongo module using dl()
If loading fails, display an error message so the admin can take care of it (STDERR or trigger_error()
Most distributions already ship different versions of php.ini for Web Servers and CLI. Are there other reasons to add another php.ini configuration for script XYZ (in addition to normal configuration)?

I came across this, because I had the same problem. Problem is there is more than one php.ini file used.
The one used by Apache is located in
/etc/php5/apache2/php.ini
This is the one that is modified to run MongoDB with extension=mongo.so.
However, when running a cron job, or from the terminal, it loads a different ini file. You can find this by using the line
grep php.ini strace.log
It is mentioned by thomas-peter.
The path where it displays '=3' is the php.ini file loaded when running the engine from the terminal, this ini file will need "extension=mongo.so" placed in it as well.

The other option is to use a small sh wrapper, something like this below in a myapp.sh file. Don’t forget to chmod +x on the script to run it.
#!/usr/bin/env sh
SOMEVAR='Yea Baby!'
export SOMEVAR
php -c /path/to/my/custom/php.ini /path/to/my/old_script.php
With the added bonus of being able to set or override environment variables pre-run.

This is a bit of a gotcha with PHP.
php -c /path/to/my/custom/php.ini works from the command line.
But try it in a script like this #!/usr/local/bin/php -c /path/to/my/custom/php.ini and your custom php won't load.
The Solution
Get rid of the space between -c and your path:
#!/usr/local/bin/php -c/path/to/my/custom/php.ini

Related

Cannot run a go binary under apache via PHP shell_exec

I am having an issue and I don't understand what is going on. I am basically using this PHP script to try and run a go binary :
<?php
shell_exec('/go/bin/x -arg -arg etc');
If I run this PHP file via command line it works. If I run it directly in browser (it's under www) it does not work. No errors whatsoever.
cli runs as root and apache as www-data. I have set the permissions to 0777 for /go/bin/x and I have also changed the owner / group to www-data. Still nothing.
What can cause this behavior ?
Also note that shell_exec works, but so far I have only ran other php files.
I do not know how I did not think about this before... The issue was that 1 of the input args contained a location to a text file and apache did not have the rights to read the file. The error was in /var/log/apache2/error.log
To Whom It May Concern.
I have same issue that I cannot run shell_exec/exec via website even they were run well in terminal.
See log:
[13-Jul-2020 19:57:23 UTC] PHP Warning: shell_exec() has been disabled for security reasons in /...test_script.php on line 3
Case 1: Check all php.ini where disable_function does not contain "shell_exec" or "exec"
$ sudo find / -name "php.ini"
$ sudo cat <path_to_php.ini> | grep disable_functions
// disable_functions = <<= This is OK
// disable_functions = "shell_exec, exec, system...." <<= They are disabled
Remove function that you want to use. Don't forget restart server.
Case 2: If disable_functions are all empty for all php.ini. Check your PHP-FPM on your hosting via Cpanel. Go to "MultiPHP Manager" from your Cpanel and check PHP-FPM status on your domain. Turn it off and you will be able to run shell_exec();

How Can I use drush.ini file instead of global php.ini file - Drush

I install And run drush as explained in this article:
My server is cloudlinux and cagefs.drupal7
Drush Use global php.ini File instead of drish.ini file and this issue makes some errors for open_basedir and disable_finctions functions.
when I run drush status command.give me following:
> The following restricted PHP modes have non-empty values:
> [error] open_basedir and disable_functions. This configuration is
> incompatible with drush. Please check your configuration settings in
> /opt/cpanel/ea-php56/root/etc/php.ini or in your drush.ini file; see
> examples/example.drush.ini for details. is_dir(): open_basedir
> restriction in effect. [warning]
> File(/usr/share/drush/commands) is not within the allowed path(s):
> (/home/:/usr/lib/php:/usr/local/lib/php:/usr/local/bin:/usr/share/drush:/usr/share/drush/commands:/etc:/tmp)
> preflight.inc:518 PHP configuration :
> /opt/cpanel/ea-php56/root/etc/php.ini
> /home/username/.drush/drush.ini PHP OS : Linux Drush script : /usr/local/bin/drush Drush
> version : 8.1.9 Drush temp directory : /tmp Drush
> configuration : Drush alias files :
So drush for me uses /opt/cpanel/ea-php56/root/etc/php.ini instead of /home/username/.drush/drush.ini
How Can I use drush.ini file instead of server php.ini file ?
I dont want edit global php.ini file for security reasone.
Have you tried adding EXPORT PHP_INI="/home/username/.drush/drush.ini" to your .bashrc file?
This is quite an old question, but I suspect that it is one that many people still puzzle over. Here is a solution that works for me (I'm using Ubuntu linux 18.04, but this should work for any unix system.)
Create a directory, e.g. /home/username/.drushrc
In this directory, create a file named 'php.ini', containing the php settings that you want to override. For example:
disable_functions=
open_basedir=
In your Drupal docroot directory, create a shell script, e.g. named 'mydrush', containing:
#!/bin/sh
PHP_INI_SCAN_DIR=:/home/username/.drushrc ./drush $*
The PHP_INI_SCAN_DIR environment variable specifies additional directories that php will look in to find .ini files when it starts up. The colon at the start of the assignment means that the directory you specify will be appended to the existing list of directories that php scans.
Make your shell script executable:
$ chmod +x mydrush
You can now call drush from your docroot directory using the command ./mydrush, for example:
$ ./mydrush status
Alternatively, you could set the environment variable PHP_INI_SCAN_DIR in your ~/.bashrc file. This would avoid the need for the 'mydrush' file, but it would change the php initialisation settings for every command-line invocation of php - not just when you're running Drush - and that may not be what you want. If you do change ~/.bashrc, then you need to open a new window for the changes to take effect.

php exec crontab not working

I trying on my local CentOS 5.3 server, when I try to execute below line in my php code from apache webserver
exec("crontab -l", $output, $arg);
The $arg reply 127 (command not found code)
Then I changed below code
exec("/usr/bin/crontab -l", $output, $arg);
The $arg reply 126 (Permission problem code)
Here is my current permission of
/usr/bin/crontab -rwsr-sr-x 1 root root 311288 Mar 15 2007 /usr/bin/crontab.
And there is no /etc/cron.allow and /etc/cron.deny file.
I already turned off Safe_mode in php. Any suggestion to solve this problem?
////////////////////////////////////////////////////////////////////////////////
I note that my problem is related to selinux.
It is working, when I disable selinux
echo 0 > /selinux/enforce
But I don't want to disable selinux, is there any option in selinux to allow crontab from apache?
Add /usr/bin to your shell env path
Add crontab to the same group like of the webserver
Try in php exec("echo $PATH") to see the path variable. You can also look for unsetenv and temporarly disable it
You can look in the php error log for a detailed description of the error but as you said you are familiar with Linux I can't teach you about user right management. A note to the env variable and the path variable it's not always sure the env variable get exported when you run a program. This is maybe the case with your problem. It means either the os is broken or you have to attach the env variable manually to your program. A workaround can be to look where the shell is looking for programs and symlink the program. In your error log it seems that crontab is in the folder /usr/bin. Also this seems not to be a programming question. Ask at server.stackexchange why crontab isn't found. For example my env looks like this:
LC_PAPER=de_DE
LC_ADDRESS=de_DE
LC_MONETARY=de_DE
AF_PIDDIR=/tmp/af-piddir
UPNP_ROOT=upnpav://
SHELL=/bin/sh
TERM=xterm
DISABLE_GATEWAY=1
GTK2_RC_FILES=/etc/hildon/theme/gtk-2.0/gtkrc
TMPDIR=/var/tmp
MMC_SWAP_LOCATION=/media/mmc1
LC_NUMERIC=de_DE
MMC_MOUNTPOINT=/media/mmc1
OLDPWD=/root
HILDON_FM_OBEX_ROOT=obex://
LAUNCHWRAPPER_NICE_KILL=/etc/osso-af-init/nice-kill-launch-wrapper.sh
INTERNAL_MMC_MOUNTPOINT=/home/user/MyDocs
OSSO_VERSION=RX-51_2009SE_20.2010.36-2_PR_MR0
USER=root
LS_COLORS=no=00:fi=00:di=00;36:ln=00;35:pi=40;33:so=01;35:bd=40;32;00:cd=40;32;00:or=01;05;37;41:mi=01;05;37;41:ex=00;33:.cmd=00;32:.exe=00;32:.com=00;32:.btm=00;32:.bat=00;32:.sh=00;32:.csh=00;32:.tar=00;31:.tgz=00;31:.arj=00;31:.taz=00;31:.lzh=00;31:.zip=00;31:.z=00;31:.Z=00;31:.gz=00;31:.bz2=00;31:.bz=00;31:.tz=00;31:.rpm=00;31:.cpio=00;31:.jpg=00;35:.gif=00;35:.bmp=00;35:.xbm=00;35:.xpm=00;35:.png=00;35:.tif=00;35:
LC_TELEPHONE=de_DE
SESSION_BUS_PID_FILE=/tmp/dbus_session_bus.pid.user
OSSO_PRODUCT_HARDWARE=RX-51
STATESAVEDIR=/tmp/osso-appl-states
LAUNCHWRAPPER_NICE_TRYRESTART=/etc/osso-af-init/nice-launch-wrapper-tryrestart.sh
OSSO_PRODUCT_FULL_NAME=Nokia N900
OSSO_PRODUCT_RELEASE_FULL_NAME=Maemo 5
OSSO_PRODUCT_RELEASE_NAME=Maemo 5
MYDOCSDIR=/home/user/MyDocs
PATH=/usr/bin/gnu:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin
LC_MESSAGES=de_DE
OSSO_PRODUCT_SHORT_NAME=Nokia N900
SESSION_BUS_ADDRESS_FILE=/tmp/session_bus_address.user
LC_IDENTIFICATION=de_DE
PWD=/home/user/MyDocs
EDITOR=/usr/bin/nano -w -c
LANG=de_DE
ERR=0
LC_MEASUREMENT=de_DE
PS1=[\033[1;36m][[\033[0;36m]\u\h[\033[0;37m]:\w[\033[1;36m]][\033[m]$ [\033[0;37;00m]
ILLEGAL_FAT_CHARS=/:*?<>|
OSSO_PRODUCT_KEYBOARD=German
AF_DEFINES_SOURCED=1
SHLVL=1
HOME=/root
SDL_AUDIODRIVER=pulse
OSSO_SWAP=/home/user/MyDocs
OSSO_PRODUCT_RELEASE_VERSION=20.2010.36-2
LS_OPTIONS=--color
LAUNCHWRAPPER_TRYRESTART=/etc/osso-af-init/launch-wrapper-tryrestart.sh
OSSO_PRODUCT_NAME=N900
AF_INIT_DIR=/etc/osso-af-init
MMC_DEVICE_FILE=/dev/mmcblk0p1
LOGNAME=root
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-eCbOI2qrVP,guid=cd1dea104334a338a9007b9700000014
LAUNCHWRAPPER=/etc/osso-af-init/launch-wrapper.sh
OSSO_PRODUCT_WLAN_CHANNEL=fcc/us
MAX_FILENAME_LENGTH=255
DISPLAY=:0.0
LAUNCHWRAPPER_NICE=/etc/osso-af-init/nice-launch-wrapper.sh
LC_TIME=de_DE
INTERNAL_MMC_SWAP_LOCATION=/home/user/MyDocs
LC_NAME=de_DE
OSSO_PRODUCT_REGION=Germany
_=/usr/bin/gnu/env
Just type env in the prompt.

open_basedir restriction when running script from command line

I'm learning how to use the command line by requirement for a recent project. I have a script that will be run during a cronjob, and am testing it by hitting it from the command line using Putty.
My script runs fine from the browser, but from the command line I get permission errors trying to include files or even check if they exist.
This only happens from the command line. This is what is in the console (I'm sure the correct script is executing, and all it does for now is check if a required file exists):
Here is the line in the terminal that executes the command:
secure:~/www/private/cron$ php -f ./update.php
Here is the output:
Warning: file_exists(): open_basedir restriction in effect.
File(/usr/local/apache/htdocs/example.com/private/modules/real_estate/config/condos.php)
is not within the allowed path(s):
(.:/tmp/:/var/tmp/:/usr/local/apache/htdocs/example.com/images/:/home/example/www/images/)
in /usr/local/apache/htdocs/example.com/private/cron/update.php
on line 43
I do not get this error running the script in a browser, which is confusing to me - but as I mentioned I am new to using the command line. I've tried every way I can think of to reference the file from update.php, and tried changing the include path, but nothing seems to work. Either I get the permission error or it can't find the file.
Does anyone know why there is a difference between executing the script in a browser VS the command line, and what I can do to resolve this error? I'm happy to provide more information as requested.
More information:
This is my CLI output from php --ini:
Configuration File (php.ini) Path: /usr/local/lib
Loaded Configuration File: /usr/local/Zend/etc/php.ini
Scan for additional .ini files in: (none)
Additional .ini files parsed: (none)
This is the Loaded Configuration File entry in phpinfo(), from the browser:
/usr/local/Zend/etc/php.ini
So Loaded Configuration File appears to be the same in both environments.
You may want to run two different php.ini files for CLI vs Apache instances.
One way to do that is to copy your current php.ini file to another directory - say into "/usr/local/Zend/etc/php_cli/php.ini" or a more convenient directory. Then, change settings in "/usr/local/Zend/etc/php_cli/php.ini" to better suit a command line environment (expand open_basedir a bit, log file paths, and other CLI-specific settings). Then, when executing CLI scripts, include the -c "/usr/local/Zend/etc/php_cli" switch to have CLI reference that ini file.
There is often a difference between the php.ini for your server and the php.ini for the command line. This means that whatever you're seeing in the browser is almost certainly not what you'll see when you enter php -r 'phpinfo();' on the command line (I mean, the formatting is different and it is less colorful)
You'll want to look for the other php.ini, and then you'll want to commend out open_basedir = <something>

Custom php.ini when using #!/usr/bin/php

I have a script in which I am trying to load a custom php.ini file. The script is run on *nix systems via a #!/usr/bin/php -qc /path/to/php.ini header. When doing this, however, PHP reports that the loaded php.ini file does not exist, i.e. none is loaded.
If I execute php -qc /path/to/php.ini /path/to/script in the command line directly, it picks up the php.ini -- is it possible to override the php.ini file using the #! notation?
PHP does not like parsing arguments from the shebang. It only allows one to be present. You can however trick it by omitting the space for the first argument parameter:
#!/usr/bin/php -qc/etc/php5/my.ini
(Obviously this method only works for one such parameter with concatenated argument.)
You can workaround this shebang portability specification fail by wrapping your PHP script in a Shell script:
#!/bin/sh
SCRIPT_PATH="$(dirname $0)"
/usr/bin/env php -qc /path/to/php.ini -f $SCRIPT_PATH/my_original_script.php

Categories