Regarding display_startup_errors the PHP manual says that even when display_errors is on, errors that occur during PHP's startup sequence are not displayed. So then what is meant by PHP's startup sequence? What does it involve, and what kind of errors can occur there? Some common examples could help.
The most common types of errors you'll see that would be suppressed by display_startup_errors are going to be related to PHP failing to load modules or modules emitting error messages for various reasons.
For example:
PHP Warning: PHP Startup: Unable to load dynamic library '/path/to/module.so' - /path/to/module.so: cannot open shared object file: No such file or directory in Unknown on line 0
This means PHP is configured to load module.so but it's not found so it cannot be loaded.
A module might also emit a warning due to bad ini configuration values:
PHP Warning: PHP Startup: session.name cannot be a numeric or empty '' in Unknown on line 0
This is one of several warnings the session extension emits, in this case because the configuration value for session.name is numeric or empty.
Most of PHP's startup sequence is going to revolve around configuring itself, loading in dynamic modules, calling each module's GINIT and PHP_MINIT_FUNCTION so they can initialize, then running PHP's startup sequence.
How and when these things happen vary depending on what server API PHP is running under. For Apache, this might be as an Apache module, FPM, CGI/FastCGI.
Some good references that talk about this are:
https://www.slideshare.net/laruence/the-php-life-cycle
http://www.phpinternalsbook.com/php7/extensions_design/php_lifecycle.html
https://wiki.php.net/internals/extensions#extensions_lifetime
Related
My code detects the environment from multiple factors and sets all environment variables and constants based on the autodetected environment.
I have the following line in my code:
ini_set('zend.assertions',environment_among(PRODUCTION) ? -1 : 1);
Don't worry about environment_among(PRODUCTION). The issue is that this line throws this warning: Warning: zend.assertions may be completely enabled or disabled only in php.ini
Since this setting depends on the environment as detected by the code, I can't put this setting in the server's php.ini file. How can I configure this locally? A solution that uses Composer is acceptable.
According to the documentation and the ticket that updated the documentation, your php.ini should be set to 0 in order to dynamically change this at runtime. There are third-party assert libraries but the performance-optimized assert can only be handled by the runtime since it is a compilation step.
I'm using NGINX with PHP-FPM in seperated Docker containers. I want to get errors only to stderr, so that I can collect them on a centralized log-server. Problem is: I'm using WP and seems to have some not well written plugins. They work but cause warnings like this:
2017/06/17 01:16:08 [error] 7#7: *1 FastCGI sent in stderr: "PHP
message: PHP Warning: Parameter 1 to wp_default_scripts() expected to
be a reference, value given in /www/wp-includes/plugin.php on line 601
Example script for testing, which should give me a fatal error in the stderr:
<?php
not_existing_func();
PHP-FPM was configured to log errors to stderr like this:
[global]
log_level = error
error_log = /proc/self/fd/2
I'm wondering that this gave me nothing in the script above. Just after I switched the log_level to at least notice, I got the exception on the console of the docker container:
[17-Jun-2017 01:45:35] WARNING: [pool www] child 8 said into stderr:
"NOTICE: PHP message: PHP Fatal error: Uncaught Error: Call to
undefined function not_existing_func() in /www/x.php:2"
Why the hell is this a notice? For me we've clearly a fatal error here like the message indicates, cause the script can't continue (and we get a 500 error in the browser, of course). It can't be true that I have to set log_level to notice so that I don't miss fatal errors which are delcared as warnings. And simultaneously, my logs get filled with trash warnings from wordpress themes, plugins and so on, that I haven't developed and I don't want to fix for update reasons...
I tried a bit and found out that log_errors in php.ini is essential for PHP-FPM to get any information. But the log level from error_reporting seems wired too. For testing purpose, I used the following configuration:
display_errors = Off
log_errors = On
error_log = /proc/self/fd/2
;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR
error_reporting = 0
Result: I got notices, but NO info about my fatal error...
First of all, I learned that I was wrong: Wordpress is the root cause for this issue, not PHP directly. It's a known fact that WP manipulates the error_reporting when debugging is enabled, so I tried to define WP_DEBUG as false in my config; BUT even having this set, the documentation says
[...]
Except for 'error_reporting', WordPress will set this to 4983 if WP_DEBUG is defined as false.
[...]
So my settings into php.ini were correct and sufficient. I don't even need the php-fpm settings, when errors are redirected to stdout in the php.ini file.
How to prevent WordPress from manipulating the error reporting?
This is not so easy, too. Although the WordPress documentation says, that the wp-config.php is a good place to set global wide settings like the error reporting, they got overwritten later to 4983. I don't know where; maybe it's not even the Core of Wordpress, but rather some poor developed plugin or theme.
We can handle this by adding error_reporting to the disabled functions:
disable_functions = error_reporting
Now it's not possible to overwrite our error_reporting. I think this is the best solution to make sure that we don't get any other error reporting by external influence from plugins or themes. Also in the future, since PHP allows such chaos, we need to reckon with such things.
Basically, we could criticize that this prevent us from getting more logs by setting WP_DEBUG to true, that's right, but as we're on a production system, it seems wrong for me to do troubleshooting in such a way there. We shouldn't do this on an application base, especially without display_errors! Instead, the workflow to find problems should be to look at the error logs.
Fatal errors should always be logged and checked on a regular basis. If that is not enough, error_reporting could be set on a higher level to get information about possible problems like warnings.
Is it just me or is do others have trouble understanding how logging works in PHP?
I come from a Java/Python logging world where you usually have access to an inbuilt utility for logging that allows you to either specify a log level or call a log level function (like logger.info('foo');). The core library would then organise from configuration values how the log appears and in what file it ends up in.
However out of the many documents I've read and google searches done on the subject, I seem to be missing some sort of fundamental understanding of the way PHP logging works.
what I've found so far is that PHP has:
the log_errors=[0|1] ini config directive, which enables logging of errors (if you would believe it),
the error_log=/path/to/file, not to be confused with the error_log() function, which defines the file which errors are logged to
an additional note on the error_log value, I have found that in apache2, when you set this value as an absolute path, Apache will honor the value, however any other relative path will default to the ErrorLog value of the Apache server (usually /var/log/[httpd|apache2|apache]/error.log)
a syslog() and error_log() function which defers messages to either the PHP system logger (/var/log/syslog) or the SAPI logger respectively (see this post and notice on error_log).
I have no control from the method signature what level message I have logged. (I know there are different levels as I can see when I receive an Illegal string offset Warning or Undefined variable notice).
# php internal log examples
[10-Mar-2017 02:45:17 UTC] PHP Warning: Illegal string offset 'username' in /var/www/html/foobar.php on line 123
[10-Mar-2017 02:45:17 UTC] PHP Notice: Undefined variable: col_info in /var/www/html/barfoo.php on line 89
[10-Mar-2017 02:45:17 UTC] my message using error_log() function without any level indication.
Now I realise that I may output the level myself, but am I to believe I cannot integrate with PHP's own level system for the sake of easy config? I choose to believe otherwise.
All my searches thus far have only informed me how to disable or enable these levels and not how to output a message with a given level.
I am hoping to be directed to some fundamental documentation on the reasoning behind logging in PHP... Or I may eat my shoe out of frustration from this simple endeavour.
P.S. I am using Apache2 as my web server.
Update:
I can see that you may log to syslog with syslog($ERRNO, $ERRMSG) and this sets the log_level (LOG_DEBUG, LOG_INFO, etc...). It would be nice to hijack the log_level configuration without using the implicit syslog file. i.e. my_error.log as opposed to syslog. I'm beginning to believe that log levels are internal ideas in the PHP core.
Hello I have simple php script well it is more a html file with few php lines.
Yet it produces tons of errors in log that look like this on every line:
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/local/lib/php/extensions/no-debug-non-zts-20100525/suhosin.so' - /usr/local/lib/php/extensions/no-debug-non-zts-20100525/suhosin.so: cannot open shared object file: No such file or directory in Unknown on line 0
I can not locate in nowhere in code where suhosin might been called...
This error is present on 2 different servers.
EDIT:
In phpinfo there is no suhosin present...
Thanks.
We will likely need more information in order to provide an accurate resolution, such as What version of PHP is installed on your system? however I will give you a general resolution.
Generally this issue is caused by PHP Upgrade, most recent PHP versions does not support suhosin as this only applied to older versions of php that needed additional security.
If you are on a shared hosting server you need to contact to your hosting provider and notify them about this issue, they are likely able to resolve it quickly.
If you are on a Dedicated server, VPS server or a localhost environment you can solve this issue by following the steps below:
Find your php.ini location [You can use phpinfo() to locate php.ini file]
Open the php.ini file and search suhosin.so
When you find suhosin comment this line extension = "suhosin.so" by adding semicolon at the beginning of the line, For example: ;extension = "suhosin.so"
Save this file
Restart Apache service httpd restart
Note: If ClouldLinux installed on your server, you need to force update CageFS by issuing the following command at the command line cagefsctl --force-update
The control operator is used to make all warnings/errors silent, no matter what the consequences are. I would like to use this crazy tool, but I guess I've got some strange server configuration and - even though I add # to a function, it still throws warnings/errors:
$ php -a
Interactive shell
php > $f = #file('juzio');
PHP Warning: file(juzio): failed to open stream: No such file or directory in php shell code on line 1
PHP Stack trace:
PHP 1. {main}() php shell code:0
PHP 2. file() php shell code:1
I've been trying to find a setting that is responsibe for this, but found nothing so far. Anybody knows why # isn't working for me? Just in case, I'm running PHP 5.3.6-13ubuntu3.10 with Suhosin-Patch. I've got also xdebug installed (in case it matters).
edit: please don't write about error_reporting. My question is about # operator. Thanks.
The scream.enabled directive in your php.ini configuration file will disable the effects of error suppression operator (#):
Quoting the manual:
The scream extension gives the possibility to disable the silencing error control operator so all errors are being reported. This feature is controlled by an ini setting.
See the example from the documentation to understand how it affects error reporting.
Disabling scream should fix the issue.
Change the directive in your php.ini, like so:
scream.enabled = 0
If you want to disable it during run-time, then you can use ini_set as stated in the manual:
ini_set('scream.enabled', false);