I'm using Ubuntu Natty with PHP 5.3.5 and PECL Gearman 0.8.0. Here's the version info:
PHP 5.3.5-1ubuntu7.3 with Suhosin-Patch (cli) (built: Oct 13 2011 22:20:48)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
with the ionCube PHP Loader v4.0.10, Copyright (c) 2002-2011, by ionCube Ltd., and
with Zend Guard Loader v3.3, Copyright (c) 1998-2010, by Zend Technologies
with Suhosin v0.9.32.1, Copyright (c) 2007-2010, by SektionEins GmbH
I'm getting a segmentation fault when trying to run a Gearman Client via the command line (I already have my worker running).
Here's what I get on the command line:
root#Local:~/sandbox# php php_gearman_client.php
Sending job
Segmentation fault
Here is my worker code:
<?php
echo "Starting\n";
# Create our worker object.
$gmworker= new GearmanWorker();
# Add default server (localhost).
$gmworker->addServer();
# Register function "reverse" with the server. Change the worker function to
# "reverse_fn_fast" for a faster worker with no output.
$gmworker->addFunction("reverse", "reverse_fn");
print "Waiting for job...\n";
while($gmworker->work())
{
if ($gmworker->returnCode() != GEARMAN_SUCCESS)
{
echo "return_code: " . $gmworker->returnCode() . "\n";
break;
}
}
function reverse_fn($job)
{
echo "Received job: " . $job->handle() . "\n";
$workload = $job->workload();
$workload_size = $job->workloadSize();
echo "Workload: $workload ($workload_size)\n";
# This status loop is not needed, just showing how it works
for ($x= 0; $x < $workload_size; $x++)
{
echo "Sending status: " . ($x + 1) . "/$workload_size complete\n";
$job->sendStatus($x, $workload_size);
sleep(1);
}
$result= strrev($workload);
echo "Result: $result\n";
# Return what we want to send back to the client.
return $result;
}
# A much simpler and less verbose version of the above function would be:
function reverse_fn_fast($job)
{
return strrev($job->workload());
}
?>
And here is my client code:
<?php
# Create our client object.
$gmclient= new GearmanClient();
# Add default server (localhost).
$gmclient->addServer();
echo "Sending job\n";
# Send reverse job
do
{
$result = $gmclient->do("reverse", "Hello!");
# Check for various return packets and errors.
switch($gmclient->returnCode())
{
case GEARMAN_WORK_DATA:
echo "Data: $result\n";
break;
case GEARMAN_WORK_STATUS:
list($numerator, $denominator)= $gmclient->doStatus();
echo "Status: $numerator/$denominator complete\n";
break;
case GEARMAN_WORK_FAIL:
echo "Failed\n";
exit;
case GEARMAN_SUCCESS:
break;
default:
echo "RET: " . $gmclient->returnCode() . "\n";
exit;
}
}
while($gmclient->returnCode() != GEARMAN_SUCCESS);
?>
EDIT
It appears the segmentation fault was being caused by Imagick. So I did the following to deal with the issue.
Remove imagick dpkg --purge --force-all php5-imagick. I had installed this when I was setting up PHP
Restart PHP (This could vary depending on how you installed php)
Restart Gearman Job Server /etc/init.d/gearman-job-server stop && /etc/init.d/gearman-job-server
Everything seems to be working ok now.
since it is segmentation fault that means something is wrong with your installation. Run dmesg to see more details there may be problem with some php extension that could be disabled.
I just also had this problem.
This is the soution I took (to fully resolving it), and steps to observing the error.
Step 1.
Running the Gearman Worker resulted in a:
Segmentation fault
Step 2.
Run dmesg from shell, I observed that this was showing up.
[2423402.716386] php[21232]: segfault at 30 ip b66d0321 sp bfc704c0
error 6 in libuuid.so.1.3.0[b66cf000+3000]
Step 3.
Googled for libuuid.so and it became apparent that Imagick uses uuid_create() for Image UUIDs.
http://usrportage.de/archives/922-PHP-segfaulting-with-pecluuid-and-peclimagick.html
Step 4. (The solution)
I ensured that Imagick extension gets initialized last out of all of my PHP extensions.
So previously I had in the first line of my
/etc/php5/conf.d/extensions.ini file imagick.so
What I did instead was created a file called imagick.ini and the contents of that were
imagick.so
Because the extensions are loaded in alphabetical order (and if you are running your Worker through command line), loading imagick last ensures that all the dependant extensions are loaded first. In this case libuuid.
Related
After an update from PHP7.0 to PHP7.2 some code stopped working and I don't understand why:
$res = rename($tmpfile, $output_file);
if ($res !== true) {
throw new Exception("Unable to rename temporary file");
}
In php7.2 the exception is triggered, although the rename was successfully done, the file is perfectly readable and nothing has gone wrong. Still I get the exception, because the return value is NULL. I inserted some debugging code:
$res = rename($tmpfile, $output_file);
log('Debug: $res ' . $res);
log('Debug: $res true? ' . $res === true);
log('Debug: $res type ' . gettype($res));
if ($res !== true) {
throw new Exception("Unable to rename temporary file");
}
This gives the following output:
2018-08-03 10:37:39 Debug: $res
2018-08-03 10:37:39
2018-08-03 10:37:39 Debug: $res type NULL
2018-08-03 10:37:39 CURL_DOWNLOAD Exception: Unable to rename temporary file
#0 /var/www/formr.org/application/Library/Functions.php(1470): CURL::DownloadUrl('http://docs.goo...', '/var/www/formr....', NULL, 'GET', Array, Array)
As you can see, there is no output, and the type is NULL. That is an undocumented behavior. According to the php documentation the return value must be nothing but true or false.
I couldn't find any documentation that the behavior of this function was changed. Does someone understand this?
Thanks for help!
Edit: var_dump output
$res = rename($tmpfile, $output_file);
ob_start();
var_dump($res);
$contents = ob_get_contents();
ob_end_clean();
log('Debug $res: ' . $contents);
Gives:
2018-08-03 12:37:40 Debug $res: NULL
Testing rename()-function in terminal:
user$ sudo su www-data -s /bin/bash
www-data$ php -a
Interactive mode enabled
php > $old='/var/www/path/changed/filename.xlsx';
php > $new='/var/www/path/changed/newfilename.xlsx';
php > $res = rename($old, $new);
php > var_dump($res);
bool(true)
(I changed the filenname and path for privacy reasons, but I tested it on the original file.)
PHP version:
$ php --version
PHP 7.2.7-0ubuntu0.18.04.2 (cli) (built: Jul 4 2018 16:55:24) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.7-0ubuntu0.18.04.2, Copyright (c) 1999-2018, by Zend Technologies
The PHP version installed is the one that comes shipped with Ubuntu 18.04. I didn't recompile it myself.
The program has its own rename functions, at two times, as I just noticed. But they are not about renaming files, they rename something in the database.
They both have just one parameter. PHP does not support overloading or differentiation by number of arguments, so might there be some interference? So far this hasn't been an issue. And as the file is actually renamed, I don't believe that the wrong function is called.
Solved by last comment of Apokryfos: Properly calling the rename-function with namespace \rename($old,$new) gives me bool(true) as return value.
I use Net_SSH (phpseclib) to execute SSH commands on an external server. I simply cannot figure out how to have real-time output from the command. I know how to make it run in the background so it's not dependant on the Apache process, but it's unclear how I'd go about showing the external output in real-time instead of having to wait for the command to finish.
My current code is as simple as $ssh->exec('command').
The PHP version used is:
[admin# ~]$ php -v
PHP 7.1.9 (cli) (built: Sep 10 2017 11:31:06) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
I managed to get it working with libssh2 and output buffering, see example below:
$session = ssh2_connect("server.local", 22, array('hostkey'=> 'ssh-rsa' )) or die("Couldn't connect to the SSH Server.");
ssh2_auth_pubkey_file($session, "root", "/path/to/public/key.pub", "/path/to/private/key") or die("couldn't authenticate to server"); // Authenticating to the server with a ssh-key for security purposes
while (ob_end_flush()); // end all output buffers if any
$proc = ssh2_exec($session, "ping -c 40 google.nl");
echo '<pre class="scroll">';
echo "[root#server ~]# ping -c 5 google.nl\n"; // Command you will execute
while (!feof($proc))
{
echo fread($proc, 4096); // Read the output from the command
# flush(); // Flushes the whole php buffer so we can output new data
}
echo "\nDone";
echo '</pre>';
Don't forget that you need php 5.6 or lower for ssh2, you can replace the command in the variable $proc by $ssh->exec('command') as you use it.
I was able to get it working using this:
$ssh->exec('ping 127.0.0.1', function($output) {
echo $output;
});
To eliminate the variability in how your system is configured versus mine I'll use Vagrant to establish a common configuration. To that end, here's my Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
end
My full phpseclib code (using 1.0.7):
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('127.0.0.1', 2222);
$ssh->login('vagrant', 'vagrant');
$ssh->exec('ping 127.0.0.1', function($output) {
echo $output;
});
A youtube video of the output:
https://youtu.be/j9-q3024eEk
If it's not working then several possibilities exist.
Maybe the "command" you're running simply doesn't dump output real time. Or maybe it requires a PTY or something. It's hard to comment since you haven't said what the command you're trying to run is. As my post demonstrates there are commands that my solution does work with.
Maybe it works with Vagrant but not with your system. Maybe your system has been configured in some funky way or something. In this scenario I guess what'd help is if you provided the SSH logs. You can get them by doing define('NET_SSH2_LOGGING', 2); and then echo $ssh->getLog();. Post the results in pastebin.com and then post the link.
edit: if you're running this in a webserver vs in the CLI you may encounter issues with how the webserver is setup - issues that go past phpseclib. For example, does this output real time or does it lock up?:
while (true) {
echo "test\n";
sleep(1);
}
flush() / ob_flush() might help but ultimately this would depend on the webserver you're using (Apache, nginx, etc), the SAPI you're using (CGI, Apache module, etc), etc.
I would consider this to be a "funky configuration".
I have a problem with finally blocks and autoload. I am using PHP 5.5.9. Here is a minimal example:
<?php
function loadMyClass($class){
include_once $class . '.php';
}
spl_autoload_register("loadMyClass");
try {
try {
// Test::printIt("before "); <--- (1) Commented for now
throw new Exception();
}
finally {
echo "finally1 "
Test::printIt("finally2 ");
}
}
catch (Exception $e) {
Test::printIt("catch ");
}
Test.php:
<?php
class Test {
public static function printIt($i) { echo $i; }
}
As you see, we thrown an exception, and want a finally and a catch block to run. Test::printIt is a simple method that calls echo on its parameter. The class Test is loaded via a the registered autoload function. Running this program prints finally1 catch instead of finally1 finally2 catch, so the call to Test::printIt(1); seems to abort the finally block. The problem seems to be the autoload in the finally block. If we uncomment the line (1), then Test is already loaded in the finally block. In this case before finally1 finally2 catch is echoed correctly.
What is the problem here? Is this a bug in PHP? If yes, in which version is it fixed? Or is it my fault because autoloading is supposed to fail in finally blocks?
This is my exact PHP version as output by php -v:
PHP 5.5.9-1ubuntu4 (cli) (built: Apr 9 2014 17:11:57)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
This appears to be a bug in PHP, according to this bug report from April 2014 and this bug report (with links to the fix) from January 2014.
A comment from the person assigned:
As we talked, this is a knew issue, which should be fixed in 5.6+, but due to ABI break, we can not bring the fix to 5.5...
I'm trying to set up a pre-commit git hook that will run and validate our unit tests. We are using PHPUnit in the Symfony 2 platform.
For some reason it seems that when I run the unit tests via the git hook that it is using a different version of PHP.
When I check my php version I get:
php -v
PHP 5.4.14 (cli) (built: May 8 2013 10:23:18)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans
Here is my git hook:
#!/usr/bin/php
<?php
// Hook configuration
$project = 'My Project';
// Tell the commiter what the hook is doing
echo PHP_EOL;
echo '>> Starting unit tests'.PHP_EOL;
// Execute project unit tests
exec('bin/phpunit -c app/', $output, $returnCode);
// if the build failed, output a summary and fail
if ($returnCode !== 0)
{
// find the line with the summary; this might not be the last
while (($minimalTestSummary = array_pop($output)) !== null)
{
if (strpos($minimalTestSummary, 'Tests:') !== false)
{
break;
}
}
// output the status and abort the commit
echo '>> Test suite for '.$project.' failed:'.PHP_EOL;
echo $minimalTestSummary;
echo chr(27).'[0m'.PHP_EOL; // disable colors and add a line break
echo PHP_EOL;
exit(1);
}
echo '>> All tests for '.$project.' passed.'.PHP_EOL;
echo PHP_EOL;
exit(0);
When I run the unit tests manually ("bin/phpunit -c app/" from my project directory) the tests execute with out error. When I run the tests via the git hook I get a PHP Parse Error. I've determined that the parse error stems from the use of array bracket notation (['key'=>'value']) that was added in PHP 5.4
When I echo php -v in the git hook I get the following output
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies
Since the Zend Engine is different (2.4.0 when run manually and 2.3.0 when run via the git hook) I'm assuming that there is a PHP version mismatch happening.
Does anyone have any clues as to why this is happening?
Thanks!
the git/phpunit executable most likely sees a different PATH environment variable than your shell (bash/zsh/...) executable.
If a program looks for i.e. php - the first match from your PATH variable will be used.
Probably you're adding a folder containing a different PHP executable to the PATH variable in one of your shell startup files.
Possible files include:
/etc/profile
/etc/zshenv
/etc/bashrc
~/.profile
~/.bashrc
~/.zshrc
...
I want to execute less and similar programs from the command-line in PHP.
I have tried the usual suspects (exec, shell_exec, passthru, etc), and while many of them can dump the file to the screen, the process is terminated before I can make use of it. If I wanted cat, I'd use it.
How do I execute a program in this fashion?
You could use proc_open to feed input to and get output back from a process via pipes. However, it doesn't seem like less allows for user interaction via pipes as it basically degrades to a cat command. Here's my first (failed) approach:
<?php
$dspec = array(
0 = array('pipe', 'r'), // pipe to child process's stdin
1 = array('pipe', 'w'), // pipe from child process's stdout
2 = array('file', 'error_log', 'a'), // stderr dumped to file
);
// run the external command
$proc = proc_open('less name_of_file_here', $dspec, $pipes, null, null);
if (is_resource($proc)) {
while (($cmd = readline('')) != 'q') {
// if the external command expects input, it will get it from us here
fwrite($pipes[0], $cmd);
fflush($pipes[0]);
// we can get the response from the external command here
echo fread($pipes[1], 1024);
}
fclose($pipes[0]);
fclose($pipes[1]);
echo proc_close($proc);
I guess for some commands this approach might actually work - and there are some examples in the php manpage for proc_open that might be helpful to look over - but for less, you get the whole file back and no possibility for interaction, maybe for reasons mentioned by Viper_Sb's answer.
...But it seems easy enough to simulate less if that's all you need. For example, you could read the output of the command into an array of lines and feed it in bite-sized chunks:
<?php
$pid = popen('cat name_of_file_here', 'r');
$buf = array();
while ($s = fgets($pid, 1024))
$buf[] = $s;
pclose($pid);
for ($i = 0; $i < count($buf)/25 && readline('more') != 'q'; $i++) {
for ($j = 0; $j < 25; $j++) {
echo array_shift($buf);
}
}
I don't believe this is possible. PHP is not a VM/shell environment, the commands it has to access other programs all return control to it, and normally there is no interaction while PHP is running.
One last thing, try with the backtick operators, if that doesn't work then I'm pretty sure you can't do this without writing up something yourself that will sleep and allow user input etc... by default no
`nano file.txt`
Adding exec('stty cbreak'); to the PHP script also fixes the issue.
I put the following in a file defined by the auto_prepend_file setting in php.ini
So, I would do something like edit php.ini to the following:
auto_prepend_file = /path/to/prepend.php
Then in, /path/to/prepend.php, I would add the following line:
if (php_sapi_name() == 'cli') exec('stty cbreak');
I'm not exactly sure of the cause. I've read bug reports for PHP. I'm not sure about versions though. I noticed the problem with the following setup:
$ php -v
PHP 5.3.3 (cli) (built: Jul 12 2013 20:35:47)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
However, the following did not show the issue:
# php -v
PHP 5.3.26 (cli) (built: Oct 21 2013 16:50:03)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies
with the ionCube PHP Loader v4.4.1, Copyright (c) 2002-2013, by ionCube Ltd.
It is worth noting that the version without the issue was using cPanel and the other was using the default CentOS 6 install via yum.