Is there a way to check in a php script if exec() is enabled or disabled on a server?
This will check if the function actually works (permissions, rights, etc):
if(#exec('echo EXEC') == 'EXEC'){
echo 'exec works';
}
if(function_exists('exec')) {
echo "exec is enabled";
}
ini_get('disable_functions')
What you actually want to do is use ini_get('disable_functions') to find out if it is available to you:
<?php
function exec_enabled() {
$disabled = explode(',', ini_get('disable_functions'));
return !in_array('exec', $disabled);
}
?>
Answered on stackoverflow here: Check if "exec" is disabled, Which actually seems to come from the PHP Man page: http://php.net/manual/en/function.exec.php#97187
Path
If the above returns true (you can use exec()), but PHP can still not trigger the script there is a good chance that you have a path issue for that script, test this by doing:
print exec('which bash');
and then try
print exec('which ogr2ogr');
This will check that exec is available and enabled BEFORE trying to run it. If you run exec() and the function does not exist or is disabled a warning will be generated. Depending on the server settings that may render to the browser and will almost-always write a line to a log file = performance hit.
// Exec function exists.
// Exec is not disabled.
// Safe Mode is not on.
$exec_enabled =
function_exists('exec') &&
!in_array('exec', array_map('trim', explode(', ', ini_get('disable_functions')))) &&
strtolower(ini_get('safe_mode')) != 1
;
if($exec_enabled) { exec('blah'); }
It's a bit tricky to find exec function available until unless checking all possibilities
1.function_exist('exec')
2.Scanning through ini_get('disabled_functions)
3.Checking safe_mode enabled
function is_shell_exec_available() {
if (in_array(strtolower(ini_get('safe_mode')), array('on', '1'), true) || (!function_exists('exec'))) {
return false;
}
$disabled_functions = explode(',', ini_get('disable_functions'));
$exec_enabled = !in_array('exec', $disabled_functions);
return ($exec_enabled) ? true : false;
}
This function never throws warnings unless ini_get function not disabled.
I am assuming that you are running this on a linux server.
You could test the exec function by running the following php script:
exec("whoami", $ret);
echo $ret[0];
This will return the command whoami.
If it errors out, it is because the exec function could not run.
Example:
if(strpos(ini_get('disable_functions'),'ini_set')===false)
#ini_set('display_errors',0);
This is some ugly code I made to detect if a function is enabled or not.
function is_enabled($f)
{
if($f=='ini_get')return#ini_get('a')===false;
return(($l=#ini_get('disable_functions'))===null||!is_callable($f)||!function_exists($f)||!in_array($f,array_map('trim',explode(',',$l)));
}
//Usage example:
print_r(is_enabled('str_split'));//true or null if ini_get() is disabled
(Based on other responses)
To check if exec exists and services are running:
function isRunning($serviceName)
{
return exec('pgrep '.$serviceName);
}
if (#exec('echo EXEC') == 'EXEC') {
$services = [
'mysql',
'nginx',
'redis',
'supervisord',
];
foreach ($services as $service) {
if (isRunning($service)) {
echo $service.' service is running.<br>';
} else {
echo $service.' service is down.<br>';
}
}
}
// mysql service is running.
// nginx service is running.
// redis service is running.
// supervisord service is down.
I would use this:
if (in_array('exec', preg_split('/\s*,\s*/', ini_get('disable_functions')) {
echo "exec is disabled";
}
Related
I've created a PHP function that checks if a PHP code-block has syntax error or not. This is how the function looks like:
function isValidPHP($str) {
$uploads_dir = trailingslashit(wp_upload_dir()['basedir']) . 'folder';
$filename = tempnam($uploads_dir, '_');
file_put_contents($filename, $str);
exec("php -l {$filename}", $output, $return);
$output = trim(implode(PHP_EOL, $output));
if ($return == 0) {
return true;
} else {
return false;
}
}
In another function I'm using the function above the check if a specific php code block is valid:
if (isValidPHP($main_file) == true) {
return "Valid";
} else {
return "Not Valid PHP";
}
The strange part: For one of our users the isValidPHP function returns false, even if there are syntax errors. We tried it with the same php string. On my server environment the syntax error are detected, on his environment not.
What could be a logical reason for this? Could the PHP version causes the error?
Or do I need to adjust the condition operator from == to the type based ===?
Can you think of a possible reason why there are different results for the same string?
By the way: this functions are implemented on a WordPress installation as plugin.
PHP's built in web server allows "router scripts" to be used, allowing for rewriting URLs internally.
The problem with such a router script is the fact that whenever it actually handles a file instead of letting PHP handle it, this causes the request log output for that request to be suppressed. For example, consider the following script:
<?php
if (preg_match('/^\/(js|css)/', $_SERVER['REQUEST_URI']) === 1) {
return false;
}
else {
echo 'hello world!'
}
This causes requests for /js/* and /css/* to be logged on the console; whereas requests for any other URLs simply skip logging the request.
How can I enable logging of all requests to the console?
router.php :
if (preg_match('/^\/(js|css)/', $_SERVER['REQUEST_URI']) === 1) {
return false;
}
else {
$stdErr = fopen("php://stderr",'w+');
fwrite($stdErr, 'LogRequest:'.$_SERVER['REQUEST_URI']."\n");
echo 'hello world!1';
}
Server start: php -S localhost:8000 router.php 2>&1
To log response headers:
if (preg_match('/^\/(js|css)/', $_SERVER['REQUEST_URI']) === 1) {
return false;
}
else {
ob_start()
$stdErr = fopen("php://stderr",'w+');
fwrite($stdErr, 'Request:'.json_encode($_SERVER)."\n");
try {
echo 'hello world!1';
} catch (\Exception $e) {
http_response_code(500);
}
$response = ob_get_clean();
fwrite($stdErr, 'Response:'.json_encode([ http_response_code(),headers_list() ])."\n");
echo $response;
}
In your log you can see errors from php build-in server, so you can do like #cske, but i think you should stick another approach.You can use own logger and write explicitly info to this log. The best logger right now it is monolog, so you don't have to reveal the wheel. Here my example:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// Create a log channel.
$log = new Logger('general');
$log->pushHandler(new StreamHandler('/var/log/php/general.log', Logger::INFO));
if (preg_match('/^\/(js|css)/', $_SERVER['REQUEST_URI']) === 1) {
$log->error('Invalid request.');
return false;
} else {
$log->info('Success.');
echo 'hello world!';
}
I hope you agree that it looks much clear and simple.
Also when you will move from php build-in server to for example nginx your code will work correctly. You need just run in another window into terminal tail -f /var/log/php/general.log and you will observe behavior of your script like in window with php build-in server.
PS: I hope you don't use php build-in server in production
<?php
error_reporting(0);
session_start();
function code($no_of_char)
{
$code='';
$possible_char="0123456789";
while($no_of_char>0)
{
$code.=substr($possible_char, rand(0, strlen($possible_char)-1), 1);
$no_of_char--;
}
return $code;
}
function sendSms($msg, $to)
{
$to=trim($to);
$m.=urlencode($msg);
$smsurl="http://bhashsms.com/api/sendmsg.php?user=*****&pass=*****&sender=******&phone=$to&text=$m&priority=ndnd&stype=normal";
$return = exec($smsurl);
return $return;
}
?>
print_r($smsurl) is showing absolutely right command which i want but doesn't executing exec($smsurl)
i m not familiar with exec() function.
Thanks in advance.
exec is used for executing an external program but accessing some webpage/api from a web url is not a valid use case for exec. Try this if you want to get data from an Url.
how to call url of any other website in php
I wanted to implement a simple locking mechanism for few cron jobs and decided to do it in unusual way. It looks like PHP is a bit buggy when it comes to socket create/bind/listen.
A code that is working:
<?php
echo 'EXECUTING: '. __METHOD__ . \PHP_EOL;
if(false === ($socket = \socket_create(\AF_INET, \SOCK_STREAM, \SOL_TCP))) {
die('create');
}
if(false === ($bind = \socket_bind($socket, '127.0.0.1', 4444))) {
die('bind');
}
if(false === ($listen = \socket_listen($socket))) {
die('listen');
}
var_dump($socket, $bind, $listen);
This will create a socket, bind it to the interface wait for incoming connections.
You can check it by invoking:
netstat -anp | grep LIST | grep tcp
If you take the same PHP code and put it into a simple class it won't bind/listen. Here is the code I'm talking about:
<?php
class Test
{
public function lock()
{
echo 'EXECUTING: '. __METHOD__ . \PHP_EOL;
if(false === ($socket = \socket_create(\AF_INET, \SOCK_STREAM, \SOL_TCP))) {
die('create');
}
if(false === ($bind = \socket_bind($socket, '127.0.0.1', 4444))) {
die('bind');
}
if(false === ($listen = \socket_listen($socket))) {
die('listen');
}
var_dump($socket, $bind, $listen);
}
}
$t = new Test();
$t->lock();
echo 'Working...'. \PHP_EOL;
sleep(60);
echo 'Done.';
Execute this code and you will see that var_dump will say that:
$socket is a resource (which is what we want)
$bind = true
$listen = true
but the code actually is not binding/listening.
What I am doing wrong?
EDIT:
Tested on:
PHP 5.4.4 (Linux)
PHP 5.3.3 (Linux)
The answer is simple: your $socket variable is a local variable and it has no references rather that in method scope. That means, once method was executed, PHP will destroy all local variables - so $socket as well. I. e. you're creating socket successfully and then PHP unset it in same moment (because method ends it's execution). Note, that unsetting local variables does not mean freeing memory immideately. Garbage collecting cycles is expensive, so PHP will do it only when memory limit will be reached.
To see difference, place sleep() call inside method after socket's creation. PHP has garbage collection since version 5.3, so versions you've tried are affected. To see it in live, you can check this snippet:
class Foo
{
public function __destruct()
{
echo('destroyed'.PHP_EOL);
}
}
class Bar
{
public function test()
{
echo('starting method'.PHP_EOL);
$obj = new Foo();
echo('ending method'.PHP_EOL);
}
}
echo('start script'.PHP_EOL);
$obj = new Bar;
$obj->test();
echo('end script'.PHP_EOL);
with result
start script
starting method
ending method
destroyed
end script
-as you can see, class destructor was called immideately after exiting method call, because local $obj variable has no references anywhere else.
Is there any way to determine whether FirePHP is installed on the server (via PEAR)? I'd like to make possible logging in FirePHP but also not to crash the code for everyone without that tool.
The example, how I imagine it should work:
$message = "hello";
function log($message) {
if (library_exists('FirePHPCore/fb.php')) {
require_once('FirePHPCore/fb.php');
ob_start();
\FB::log($message);
} else {
SomeBoringLogger::log($message);
}
}
I haven't found anything like my library_exists method. Is there anything like that in PHP?
#include_once('FirePHPCore/fb.php'); // Ignore any errors here, as we check for existance
if (class_exists('FirePHP')) { // Do something after this
http://php.net/manual/en/function.class-exists.php
FirePHP uses FirePHP as its class name, so if it is available, that class should be defined
For PHP 5.3.2 or later, use zerkms's suggestion:
(!stream_resolve_include_path('FirePHPCore/fb.php')===FALSE)
Use include_once, so it doesn't kill the request. As #Brad suggests, use class_exists afterwards.
$message = "hello";
safe_include_once('FirePHPCore/fb.php');
if (class_exists('FB')) {
function log($message) {
//using FirePHP
}
} else {
function log($message) {
SomeBoringLogger::log($message);
}
}
function safe_include_once($path) {
if ($path = stream_resolve_include_path($path)) {
include_once($path);
}
}
[Edit] Using stream_resolve_include_path in safe_include_path.
[Edit2] Faster runtime logging.
file_exists() can be used for your case.