How can we debug a PHP script when display_errors is off and PHP is running in safe mode ?
The best way is to use error_log()
http://php.net/manual/en/function.error-log.php
And you can set specific handler to that method. Either record it to database, file or simply display the error.
If you want to set handler method you can use: set_error_handler
If you're in a development environment you should disable safe_mode and enable error_reporting. On a production environment you should probably not do live debugging (since it's live). If you want to track down errors that seem to be only present on the production environment use error_log, or use the logging mechanism of the framework you are using, and check the logs afterwards. This way you won't break the normal operation of your production environment. Some frameworks like symfony provide a separate interface to access your system in another environment (for example accessing index.php has error reporting disabled but frontend_dev.php has not)
If you don't have a separate production and development environment it is high time to separate the two. You can for example install XAMPP or similar to your development PC, where you can do the development and only deploy to the live servers if you have already debugged / tested / etc. your code.
You can use that:
error_reporting(E_ALL);
ini_set('display_errors','On');
ini_set('error_log','my_file.log');
PHP writes log file to file.
If you can't enable display errors directive, you can using var_dump, debug_backtrace and exceptions for debugging php source code.
When ever error display is off, only way we can debug the code with echo $var; exit; OR var_dump($list); exit;
var_dump($variable);
exit;
OR
echo $variable;
exit;
OR
echo "<pre>";
print_r($variable);
exit;
"Whenever you are tempted to type something into a print statement or
a debugger expression, write it as a test instead"
--Martin Fowler
Related
I have a CodeIgniter PHP app running on a Heroku Cedar instance.
We are running a PHP app and we need to log errors, but NOT print them to the screen. No matter what I do, the errors are printing to the screen, which is not safe for production.
Here is the PHP code which works on my local environment and everywhere else (besides Heroku):
error_reporting(E_ALL); #we care about all errors
ini_set('display_errors',0); #but DONT print to screen
I have seen this document which suggested I try adding a custom CodeIgniter logging class, which did not work.
I also added a phpinfo() to the app to check if somehow my settings were being overridden downstream, but it shows that display_errors is set to "Off".
So why am I STILL seeing errors printed on the screen?
It turns out that CodeIgniter 2.x has some completely asinine error handling in which they use a custom error handler to ignore the developers configurations. Apparently this is fixed in v3.
I was able to fix it by just commenting out the custom error handling, which for me was located in in CodeIgniter.php, line 72...
//set_error_handler('_exception_handler');
Or the best solution of all: don't use CodeIgniter in the first place.
I have a php script that is really simple, but requires some of the wordpress includes. I have used the code from their website for most of it but it is failing whenever I try to call the require_once parts of the scripts. here is the relevant code:
$fn = dirname(__FILE__) . '/wp-admin/includes/media.php';
if(!file_exists($fn))
{
echo 'No File';
}
if(!is_readable($fn))
{
echo 'File is unreadable';
}
require_once $fn;
Interstingly enough, The only echo that I get when the require_once is uncommented is the full path to the document. The file is both existing and readable. However, when I uncomment the require_once code it comes back with a 500 error.
On a slightly related point. What is the easiest way of debugging php. I haven't found anything that is VS easy yet (or even as easy to debug as Django!!)
PHP has various settings in php.ini for how logging works. You can also set them at runtime. It might be logging to a file somewhere rather than displaying the error. Consider trying:
error_reporting(E_ALL)
To debug your application. Don't leave it on when you're done working with it.
You should be developing and debugging the code locally on your workstation, not on a shared hosting server. On your local workstation you have access to the php.ini, Apache error log, and the PHP error log. You can also set project-specific settings for debugging using .htaccess files. For example, you can configure separate PHP error log files for each different project you're working on.
As #Steve Howard pointed out, there are many settings you can alter in the php.ini in order to get more detailed error reporting. In fact, most LAMP packages install a development copy of the php.ini, which is basically a template of a php.ini file that's optimized for detailed error reporting. Detailed error reporting is something you want on your local environment for debugging. It is NOT something want on your production environment where customers and potential hackers will end up seeing more information than they should!
If you don't know how to set up PHP on your workstation, take a look at XAMPP, MAMP, Macports, etc. There are many options. You don't need to be super technical to get a stack set up on your computer. Once you have a good dev environment setup on your computer you can tail the PHP error log and the Apache log.
One thing I like to do is to use the PHP error_log() function. This allows you to output custom messages to the PHP error log. For example, if I'm debugging code and I need to know what the value of $foo is, I can do something like this:
<?php
error_log("Foo is: " . print_r($foo, true));
This is much better than using var_dump() or echo to print debugging data to the screen because it won't interrupt the normal execution of the program or the display of its view layer.
I have recently changed hosts, on my old host if i had an error in my syntax the error would be displayed (showing me where the error was)
On my new host i do not see this, i just see
The website encountered an error while retrieving http://www.XXX.co.uk/delete_product.php?q=66550. It may be down for maintenance or configured incorrectly.
Is there any way i can show the error instead of this?
Turn on error reporting.
Include these lines are the top of your script:
ini_set('display_errors',1);
error_reporting(E_ALL);
If you have access to edit the php.ini file, you can edit it and include the following option:
error_reporting = E_ALL
These settings will help you troubleshoot code faster and makes it easy to identify errors. However, it is not appropriate for a production-level use. You should use the first method and then you can remove the lines once you've fixed the issues. On local development environments, it's okay to edit php.ini file and add the directive as mentioned above.
On production systems, do not use ini_set('display_errors', 1); as it can show information you might want to keep hidden. Use the server's logs instead. By default apache for example logs these errors in error_log.
And, anything that is open to the general internet public is considered "production" in my opinion. Development means it is a server sitting in your own local network.
Turning on error reporting would work, but perhaps it would be better to look into the server logs.
I've seen a few methods for hiding php errors using php.ini or by adding php_flag display_errors off to .htaccess, but I'm wondering if there's a way to make it so only I can see php errors (useful for debugging obviously), but anyone else will be redirected to some boilerplate error page. I have a few scripts on my site that use my forum to authenticate me as an admin and kick everyone else out, so maybe it's possible using the same method?
If this isn't possible, I guess I'll go with the .htaccess method since I don't have access to php.ini. Is adding php_flag display_errors off to .htaccess a good way to go for this?
Thanks!
While displaying errors on screen is great for development (as you see them right away), they should not be enabled for production servers because you may accidentally expose sensitive information (e.g., database passwords) to unauthorized users.
The useful INI options are:
ini_set('error_reporting', E_ALL & ~E_NOTICE);
ini_set('error_log', '/path/to/my/php.log');
ini_set('log_errors', 'On'); // log to file (yes)
ini_set('display_errors', 'Off'); // log to screen (no)
With that, all errors will be logged to the specified file. No errors will be seen on the screen.
Make sure the web server user is able to write to that file. You may have to create it and chmod / chown it accordingly before running your script.
On private development servers, you could disable the log file and display directly to screen. When developing, I would also get in the habit of displaying E_NOTICE errors as well. (Just use E_ALL as the value.) And if your scripts are well written, you can then continue to log them while in production too. An E_NOTICE is good for catching typos in variable names or array indices.
Note that all of those options can also be set in the php.ini or .htaccess files. But if you use .htaccess you cannot use the E_* constants; instead, you must hardcode the integer representation. (i.e., In a .htaccess file, you use whatever the results of <?php echo E_ALL ?> show as the value, or whatever you wish to log.)
In fact, I would recommend setting them in the php.ini if at all possible. Otherwise, if there's a script parsing error (or the ini_set gets skipped for some reason), you may not get the errors logging properly, etc.
On a Linux box you can always do a tail -f /path/to/my/php.log from a shell to monitor the log in realtime.
Although I agree with konforce, this is possible by setting the error reporting at runtime with the error_reporting() function. If you insist on doing that, put it in the same block of code that you mentioned for determining you are the admin, so that you don't have the decision made in different places.
Since your code already knows you are an admin you can use a logic like this:
if($_SESSION['isadmin']==1){
ini_set('display_errors', 1);
ini_set('log_errors', 1);
}
The admins will see errors but the other users will not see the errors.
You can check against the users IP, and if it matches yours, you can show errors.
Something like this:
if($_SERVER['REMOTE_ADDR'] == 'your.ip.address'){
error_reporting(E_ALL);
} else {
error_reporting(0);
}
If you don't know you external IP, just google "what is my ip" or similar.
Base case scenario is obviously having a dev-server.
if you have a users system, set the codes so it recognize you when you log in, and show errors. So, it will only show errors when it's you who is logged in.
I would like to log PHP errors on a CakePHP site that has debug = 0. However, even if I turn on the error log, like this:
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
log_errors = On
it doesn't log errors.
The problem is that even for a parse error that should cause the CakePHP environment to not load completely (I think), it still blocks the error from being logged. If I set debug to 3, it logs to the file without issue.
I am using CakePHP 1.2. I know this is apparently made easier in 1.3, but I'm not ready to upgrade.
Another way to keep track of and log errors would be to use the Referee plugin as it provides a way to arbitrarily log and catch all (including fatal) errors that occur during exection.
define('LOG_ERROR', 2); in core.php
PHP should log errors to its own logfile, regardless of what CakePhp is doing.
Look in /etc/php.ini file (or wherever yours lives) and search for error_log. This will show you where the PHP log resides on your system.
There is a bug in CakePHP 1.2-1.3 where PHP errors/warnings are suppressed in view code when debugging is disabled.
In the file cake/libs/view/view.php on line #664 it reads
#include ($___viewFn);
But the # directive suppresses errors for the entire view handler. Instead it should be:
include ($___viewFn);
Which allows PHP errors/warnings to be generated in view code and subsequently get logged. Once I changed this and had the right logging settings in core.php I was finally able to get complete logs in production.
Sometime the reason could be very different. For example the framework you are using may have its own internal caching module which keeps the value in buffer while you keep on trying. Check whether duplicate copies are getting generated or not. Typically those files would be named as filename.ext.r123 and so on.