From inside my index.php file, say, I'd like to check if another PHP file executes without error (and include it, if so), and if it does in fact fail and returns a fatal error, I'd obviously like to not include it. Any suggestions? Thanks...
You may use -l parameter of php CLI:
php -l filename.php
and parse the output.
$o = `php -l filename.php`;
if (strpos($o, 'No syntax errors detected') !== false) {
echo 'No errors';
} else {
echo 'There are errors';
}
You probably don't want to run the second file separately. That said, you can do one of two things...
1.) if you really want to use it as an include that executes separately you could call it with something such as CURL and have it output either the expected result or a failure message that would then be read and acted on accordingly.
2.) Include your function/class/etc execution in a try/catch statement to properly handle any errors encountered. http://php.net/manual/en/language.exceptions.php might help you a little more with this method.
This runs the script as a separate process, with no shared variables/functions/state/scope etc...
$cmd = 'php file.php';
exec($cmd, $ar, $exit_status);
$wasFatal = $exit_status == 255;
There's a real good chance it gets run with a php.ini that's different than whatever your webserver php.ini is, so expect differences in config and maybe even php version.
Related
I try to execute a command "wget" to download a file on my server A and then execute a python who will scrypt argument in this file.
My script:
switch ($_POST["parse"]) {
case 'parse1':
shell_exec("wget http://localhost/".$file_path);
shell_exec("python /opt/lampp/htdocs/mysite/api/scripts/script_parse.py ".$file_path." 1");
echo $file_path;
break;
default:
echo "no";
break;
}
However (I'm with local xampp under debian), the file is not downloaded and I have a page that loads into space when I try to execute the script (with or without file) but that does nothing .
So I'm looking since last night but I can not.
Besides, I like to avoid that the page load until the end of script execution.
Instead of shell_exec() and wget to download the file, use "file_get_contents()`. It supports both the HTTP and the HTTPS protocols, among many others, and it'll also give you an informative error message if downloading fails.
You will also need to add some error handling to your code, as stated in the comment by Arek. Since that is the only way you can properly handle the situations where something goes wrong, and they will. Not only for your sake, to make it easier to detect and debug, but also for your users.
Read the PHP manual, find out what values the different functions return in case of errors, and check against these. If any of the functions does return an erroneous value, then show an error message to the user and abort the rest of business logic (the stuff your code is really meant to do).
I'm having trouble executing the lessc compiler from PHP. I'm using Symfony, and have tried using the sfLESSPlugin, but have been unsuccessful. I've put my code in a filter that executes before the page renders, so that every time the page is refreshed, my LESS files are compiled into one CSS file (don't want to have recompile manually every time I make a change, at least while I'm developing). Here are the different variations that I've attempted:
$fs = new sfFilesystem();
$command = '/Users/jordanb/node/node_modules/less/bin/lessc less/bootstrap.less css/bootstrap.css';
try
{
$fs->execute($command, null, array($this, 'throwCompilerError'));
}
catch (RuntimeException $e)
{
return false;
}
This returns an error: "Problem executing command", with an error code of 127. Digging deeper into Symfony's execute(), it calls proc_open() and then proc_close(). Some research online told me that an error code of 127 means that the command was not found.
Running the exact same command on the command line works just fine.
To be extra sure, I executed chmod 777 on /Users/jordanb/node/node_modules/less/bin/lessc, just to make sure it wasn't a permissions issue. Still didn't work.
I also tried just "lessc" instead of the full path, which didn't work. I've added lessc to my classpath, so typing "which lessc" gives me "/Users/jordanb/node/node_modules/less/bin/lessc".
I also tried a simple:
shell_exec('lessc less/bootstrap.less css/bootstrap.css');
which didn't seem to do anything. I printed the output to the PHP error log as well as to a text file, and the output was empty in both cases. I also tried using the full path in this case.
You can make a shell script that compiles things the way you want:
compile_css.sh
/Users/jordanb/node/node_modules/less/bin/lessc less/bootstrap.less css/bootstrap.css
Then
chmod +x compile_css.sh
And finally call it from your script
$command = '/path/to/compile_css.sh';
This will give you more control over what you can execute, but if you still want to do it from php, try this:
$command = '/Users/jordanb/node/node_modules/less/bin/lessc "less/bootstrap.less css/bootstrap.css"';
// note the quotes around the arguments.
How would I go about checking if and include or a require has an error in it. For example, and include would try to be included, if that page has an error the page isn't included and a message is throw?
Cheers.
You can't catch a parse error in PHP in the same language environment (for obvious reasons).
One approach might be to run php -l your_included_file.php using exec and then check the exit code. The -l (lint) argument checks that your code can be parsed correctly.
You can try using file_exist function, it check whether the file exist or not.
$filename = "/path/to/file.php";
if(file_exists($filename)){
include $filename;
}else{
include "errorpage.php";
}
You can't trap parser errors.
However, if the code executes something that causes an exception to be thrown, you could catch it with a try/catch block.
I have a PHP script that creates other PHP files based on user input. Basically, there are files containing language specific constants (define) that can be translated by the user. In order to avoid runtime errors, I want to test newly written files for parse errors (due to "unusual" character sequences). I have read several posts here on SO (like PHP include files with parse errors) and tried a function that uses
$output = exec("php -l $filename");
to determine whether a file parses correctly. This works perfectly on my local machine, but at on the provider's machine, the output of calls to exec("php ...") seems to be always empty. I tried a call to ls and it gives me output, leading me to the assumption that PHP is somehow configured to not react to command line invocations or so. Does anyone know a way around this?
EDIT: I forgot to mention, I had already tried shell_exec and it gives no result, either. In response to sganesh's answer: I had tried that too, sorry I forgot to mention. However, the output (second argument) will always be an empty array, and the return value will always be 127, no matter if the PHP file to test has syntax errors or not.
I had the same problem. The solution that worked for me was found in running-at-from-php-gives-no-output. I needed to add output redirection.
$output = exec("php -l $filename 2>&1");
You can try with exec second and third arguments.
second argument will have the output of the command.
third argument will have the return value.
And exec will return only last line of the command.
$filename = "a.php";
$output = exec("php -l $filename",$op,$ret_val);
print $output."\n";
print $ret_val."\n";
var_dump($op);
By executing shell_exec(), you can see the output as if you executed that file via command line. You can just see if there is an error right here.
<?php
if (strpos(shell_exec('php -l file.php'), 'Syntax Error')) {
die('An error!');
}
There may also be a possibility that shell_exec() or exec() may be disable by your host.
Nice idea to check the file validity :-)!
Now, from the PHP manual for exec():
Note: When safe mode is enabled, you can only execute files within the safe_mode_exec_dir. For practical reasons, it is currently not allowed to have components in the path to the executable.
Can you check if this is not the case for you?
Also, can you check by providing the full path of the PHP interpreter in the exec() instead of only php. Let me know how you fare.
Pinaki
the correct way is to add >2&1 as tested on a windows system using imagemagick!
I worked around my original problem by using a different method. Here is what I do now:
Write a temporary file with contents <?php include "< File to test >"; echo "OK"; ?>
Generate the correct URL for the temporary file
Perform HTTP request with this URL
Check if result equals "OK". If yes, the file to test parses without errors.
Delete temporary file
Maybe this could be done without the temporary file by issuing an HTTP request to the file to test directly. However, if there is a parse error and errors are suppressed, the output will be empty and not discernible from the output in the case of a file that gives no parse errors. This method is risky because the file is actually executed instead of just checked. In my case, there is only a limited number of users who have access to this functionality in the first place. Still, I'm naturally not entirely happy with it.
Why the exec() approach did not work, I still do not know exactly. pinaki might be right by suggesting to provide the full path to the PHP executable, but I cannot find out the full path.
Thank you everyone for answering, I upvoted you all. However, I cannot accept any of your answers as none of your suggestions really solved my problem.
I need to write a script that will give users info on a given Unix account (the same Unix server that the script lives on). Mostly thing kinds of things that are in the passwd file or available via finger.
PHP is in safe-mode, so I can't access the passwd file via something built into php like file_get_contents(). Also, because it's in safe mode, various other command-line functions are disabled.
I thought I could get the info via a socket (no clue yet what that means, but I thought I'd try) but I get a fatal error that socket_create() is an unknown function. I pulled up the php-config file (which I can't change, FYI), and sure enough, sockets are not enabled.
However, while I was in there, I saw the line '--with-exec-dir=' with no actual directory set.
So then I remembered that when I was trying EVERY command line function, that some threw "not allowed in safe-mode" type errors, while others did nothing at all. If I put something like:
echo "[[";
exec("finger user");
echo "]]";
I'd end up with [[]]. So no errors, just no results either.
Bottom line:
Is there something I haven't tried? (in general)
Is there a runtime config option I can set to make exec() work?
quick note: I tried passthru() as well, specifically passthru("pwd") with still no output.
update
based on feedback, I tried both of the following:
$stuff = exec("pwd", $return);
echo "stuff=".$stuff."\n";
echo "return=";
print_r($return);
which results in:
stuff=
return=Array
(
)
and
$stuff = passthru("pwd", $return);
echo "stuff=".$stuff."\n";
echo "return=";
print_r($return);
which results in:
stuff=
return=1
The 1 sounds hopeful, but not what I want yet.
Idea
So this is actually an update of an already existing script that (please don't ask) I don't have access to. It's a perl script that's called via cgi. Is there a way to do php via cgi (so I don't have to deal with perl or rely on the older code)?
I'm afraid you can't do that in safe-mode. You have to remove the safe-mode if you have control of the server configuration.
I think you can't rely on sockets to read local files, sockets are used for network related things.
exec doesn't inherently return any data.
Try something like,
exec("finger user",$output);
echo "[[";
foreach($output as $key => $value){
echo $value;
}
echo "]]";
Exec returns a value, so do:
$var = exec("finger user");
and then parse the output to get what you want. You can get return status by adding in an optional variable thus:
exec("finger user", $var, $return_status);
or just:
echo exec("finger user");
if all you want is to see the output.
Thanks to all that responded, the following is what finally worked:
Create a cgi-bin folder
Add the following to the top of the php script:
#!/usr/local/bin/php-cgi
I don't know if this is something special on my server configuration, but I can run exec() and get what I'm after.