I am trying to get gearman to return a value to php from a function after php makes a request to it using $gmclient->do("somefunction", "somedata"). However, the php client simply times out. The exact code I am using is straight from the php manual. I am using example #1 from http://docs.php.net/manual/en/gearmanclient.do.php
The browser gives me this message:
This webpage is not available.
The webpage at
http://yoursite.com/client.php
might be temporarily down or it may
have moved permanently to a new web
address.
More information on this error. Below
is the original error message
Error 324 (net::ERR_EMPTY_RESPONSE):
Unknown error.
The browser is Chrome if that helps to elaborate the error message.
In case it makes a difference, the worker.php file is being executed in a terminal window using the command "php worker.php". I am running on Ubuntu 9.10 Karmic Koala. I installed gearman using the directions found at http://blog.stuartherbert.com/php/2010/02/26/getting-gearman-up-and-running-on-ubuntu-karmic/
I checked the terminal window and gearman is getting the request and echos the results into the terminal - it just not sent back to the client.
The end goal is to get gearman to return to the client the return value from the function that was executed and display that value to the user.
UPDATE:
As requested, the code is below:
worker.php (the worker)
<?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)
{
return strrev($job->workload());
}
?>
client.php (client code - this is the page I am loading the browser)
<?php
# Client code
echo "Starting\n";
# Create our client object.
$gmclient= new GearmanClient();
# Add default server (localhost).
$gmclient->addServer();
echo "Sending job\n";
$result = $gmclient->do("reverse", "Hello!");
echo "Success: $result\n";
?>
The comments below where it said it was working.. I repeat, it was NOT working. It only appeared to work because I changed $gmclient->do to $gmclient->doBackground which output the job ID, not the actual result from the function.
FINAL UPDATE (WITH SOLUTION)
After some work, I've figured out that it was not a coding error. Gearman was improperly installed. Instead of using apt-get install, I decided to do things manually. I downloaded the gearmand (c) from the gearman site (http://gearman.org/index.php?id=download). I then used the tutorials on the gearman site as well starting with http://gearman.org/index.php?id=getting_started and then http://gearman.org/index.php?id=gearman_php_extension
Change your code and use GearmanClient::addTask. You can use its return value to implement monitoring process. Check on the other functions that you can use on the GearmanTask class.
//Wrong
$gmworker->addServer();
//Correct
$gmworker->addServer("localhost",4730);
Related
I want to complete PHP request even if the Ajax session is closed from user side. I manage to do it on Apache by adding ignore_user_abort(True) to my php file but it is not working on IIS 10 with FASTCGI. tried to google any solution with no luck. I'm using PHP v7.4 and IIS v10 on windows server 2019.
below is just a test code to open a file and print the connection status. it is working perfect on Apache but on IIS, it stops writing ponce session is closed.
<?php
ignore_user_abort ( TRUE );
echo "hello\n";
$x=0;
$log_filename = ".\\test.txt";
while (# ob_end_flush());
while ($x<100)
{
echo($x ."\n");
$status = connection_aborted();
file_put_contents($log_filename, $x ." - " .$status ."\n", FILE_APPEND);
$x++;
# flush();
sleep(1);
}
?>
You could try to use the fastcgi_finish_request() This function flushes all response data to the client and finishes the request. This allows for time-consuming tasks to be performed without leaving the connection to the client open.
https://www.php.net/manual/en/install.fpm.php
I'm building a dashboard that allows me to visualise my crontab as it runs (Think a queue of upcoming tasks, those that are running currently and those that have finished and whether the outcome was successful.) To do this, I need to send messages from the tasks (running or monitored by PHP) on my server, to the client browsers that run the dashboard using javascript. It also has to be secure.
To solve this issue I implemented a Twisted/Autobahn socket server in Python, which worked fine once I had paid for proper security certificates. The problem I have however is getting the PHP running the crontasks to be able to send messages to the webSocket server which passes them on to the client browsers, so far I have hacked this by writing a Python client that accepts the message to send as an argument and run this as an exec from PHP.
Obviously this is not a robust solution (which is also relatively slow to execute) and I'd now like to send logfile entries from the crontasks over websockets to my dashboards so I can see what's happening on my servers as tasks run. I've been looking for a while and tried various approaches (most are too long to post) however they range from tutorials, to segments from the PHP website to libraries such as Thruway (which seems too over-engineered for my use case, specialised and hard to adapt).
The best progress I have so far is Pawl, and using the following code I'm able to successfully send three messages to the Python Socket Server using wss:
<?php
require __DIR__ . '/vendor/autoload.php';
\Ratchet\Client\connect('wss://127.0.0.1:9000')->then(function($conn) {
$conn->on('message', function($msg) use ($conn) {
echo "Received: {$msg}\n";
$conn->close();
});
$conn->send('MSG 1');
$conn->send('MSG 2');
$conn->send('MSG 3');
}, function ($e) {
echo "Could not connect: {$e->getMessage()}\n";
});
?>
(Note that this depends on the libraries found here)
The problem I have is that I would like to be able to open and close the connection and send messages as separate steps, in the code example (which I've had difficulty adapting) it seems that as open, send and close are all wrapped in the then method and anonymous function I cannot call these methods seperately. Ideally I'd like to open the connection at the beginning of my crontask execution, each time a message is logged call the send method and close the connection at the end without wasting time opening and closing a connection to my socket server for each and every message. Please note that listening for replies isn't necessary.
Also, any solutions that work to 127.0.0.1:9000 over WSS and don't need libraries or use a different one I'm happy to consider. Please also note (after seeing other posts) this question specifically refers to a websocket client, not a server.
Many thanks,
James
Leaving this in case anybody else finds this final solution welcome:
In the end I wrapped a module called Textalk by Fredrik Liljegren et al in a small class to make it more accesible and this solved my issue.
Here is the code I used in the end:
require('vendor/autoload.php');
use WebSocket\Client;
class secureSocketClient {
private $OClient;
function __construct($VProtocol, $VLocation, $VPort, $VDir) {
$this->OClient = new Client("$VProtocol://$VLocation:$VPort" . ($VDir != null ? "/$VDir" : ""));
}
function sendMessage($ORequestData) {
$VLocalMessage = json_encode($ORequestData);
$this->OClient->send($VLocalMessage);
}
function __destruct() {
$this->OClient->close();
}
}
Which can be invoked as so:
require_once <class location>
$this->OSecureSocketClient = new secureSocketClient("wss", "127.0.0.1", "9000", null);
$this->OSecureSocketClient->sendMessage($OMSG1);
$this->OSecureSocketClient->sendMessage($OMSG2);
$this->OSecureSocketClient->sendMessage($OMSG3);
To install textTalk (on linux), you can use the following commands in the directory where the class will reside:
curl -sS https://getcomposer.org/installer | php
add the following to composer.json (in the same directory):
{
"require": {
"textalk/websocket": "1.0.*"
}
}
then run the following:
sudo php composer.phar install
Regards,
James
I have written a slack auto-message service on heroku that will auto send a message on some event. However, I have accidentally made an infinity loop and it keeps sending error message to my slack account. (the loop caused by retrying on error and I forgot to add a counter on that)
I have tried restarting the server by typing the command heroku restart (at that directory, so app name can be omitted), as well as git pushing my corrected version which should restart the server. I even turn off the server by settings 0 dymo to it. None of these works and I still keep receiving message on slack.
I am quite sure I have turn off my heroku server, so I think there should be other way to stop the process. The php process will have a bash_exec to trigger phantomjs. Not sure if it is related to the current problem. Do anyone has any suggestions?
P.S. As request, this is my code with important information hidden.
<?php
sendSlackMessageToChannel("Request received. Loading, please wait.");
startPhantomJS();
function startPhantomJS() {
$return_value = bash_exec("path/to/phantomjs myscript.js");
sendSlackMessageToMyself($return_value);
if ($return_value == "error")
startPhantomJS();
else
sendSlackMessageToChannel($return_value);
}
I am trying to setup a PHP web application on a Windows Server 2008 SP1 machine. We have this application running correctly on a Windows Server 2003, but are now unable to get the Windows services built with php_win32service PHP extension starting up correctly.
Here are the relevant sections of the PHP code. Here is the section that does the install and uninstall:
if ($argv[1] == 'install') {
win32_create_service(array(
'service' => $service_name,
'display' => $service_name,
'params' => '"'. __FILE__ . '"' . ' run'));
exit;
}
else if ($argv[1] == 'uninstall') {
win32_delete_service($service_name);
exit;
}
else if ($argv[1] != 'run') {
die("Invalid arguments");
}
win32_start_service_ctrl_dispatcher($service_name);
And here is the main loop:
while (1) {
switch (win32_get_last_control_message()) {
case WIN32_SERVICE_CONTROL_INTERROGATE: win32_set_service_status(WIN32_SERVICE_RUNNING); break; // Respond with status
case WIN32_SERVICE_CONTROL_STOP: win32_set_service_status(WIN32_SERVICE_STOPPED); exit; // Terminate script
}
processQueue();
usleep(500000);
}
The install and uninstall work as long as I run cmd as administrator. If I launch cmd under the account that I use to login to the server then the service is not created win32_create_service. I can also run the script with the run parameter from the command line and it runs correctly, but when I try start the service it just hangs on with the Starting message and never goes into Started state.
I think this issue has something to do with the rights of the LocalSystem account on the machine, but I do not know what rights are needed to get this to work properly. I also do not know how I can debug this and find out what error/issue is occurring with the WIN32_SERVICE_CONTROL_INTERROGATE, especially as I do not have rights on this server to make changes to security settings. Any changes that I need made to security settings I need to communicate to the network administrator so that he can perform the changes. Can anyone offer any help with debugging or resolving this issue?
UPDATE:
This issue only seems to occur in the 64-bit version of PHP. It seems that the 64-bit compile of php_win32service runs into some sort of problem when trying to start the service. I removed the 64-bit versions of PHP and 'php_win32service' and replaced them with the 32-bit versions. The service then started correctly.
Have you tried with NetworkService account? Other way is creating own service account. Do you communicate outside the server? Maybe firewall?
Ps. the network service account has a default password (system known)
Note that this account does not have a password, so any password information that you provide in this call is ignored.
http://msdn.microsoft.com/nl-nl/library/windows/desktop/ms684272(v=vs.85).aspx
Updated Answer:
I am now convinced that this issue arises when you update or downgrade PHP to a different version, but fail to remove and recreate the services using the php_win32service for the newly installed version of PHP. This was mentioned as an aside in my old answer, but after encountering the same thing on another server and resolving it by removing and recreating the service entries, I am convinced that this is the true cause of this issue and that is not a bug in PHP.
Old Answer:
I encountered this issue again when I tried to update PHP on a Windows Server 2008 machine from 5.3 to 5.6. From the testing that I have done I have concluded that php_win32service.dll extension works correctly for PHP 5.3, but not from 5.4 upwards. From 5.4 there seems to be a bug whereby the function win32_get_last_control_message always returns 0 rather than a valid status.
I finally got a clue to what was going on from a post made over here:
http://enlinea.creaelicita.cl/guia/function.win32-set-service-status.html
So, if you have code such as this:
while (1) {
switch (win32_get_last_control_message()) {
case WIN32_SERVICE_CONTROL_INTERROGATE: win32_set_service_status(WIN32_SERVICE_RUNNING); break; // Respond with status
case WIN32_SERVICE_CONTROL_STOP: win32_set_service_status(WIN32_SERVICE_STOPPED); exit; // Terminate script
}
usleep(3000000);
// Main script goes here
processQueue();
}
then
win32_set_service_status(WIN32_SERVICE_RUNNING);
will never get called, because win32_get_last_control_message never gets the value of 4 (WIN32_SERVICE_CONTROL_INTERROGATE).
A workaround which I use is to add a default case to the switch statement that sets the service status. Like this:
switch (win32_get_last_control_message()) {
case WIN32_SERVICE_CONTROL_INTERROGATE: win32_set_service_status(WIN32_SERVICE_RUNNING); break; // Respond with status
case WIN32_SERVICE_CONTROL_STOP: win32_set_service_status(WIN32_SERVICE_STOPPED); exit; // Terminate script
default: win32_set_service_status(WIN32_SERVICE_RUNNING);
}
As an aside, I also found that this issue occurred if I upgraded to PHP 5.4 and did not recreate the service entries before trying to start them. So besides applying the above workaround, remember to first uninstall the windows service in question and reinstall it from your PHP script.
I have a named pipe being read by a python program, installed as a service in Windows 2008 to print data from a database. The code (php) that writes to the pipe is as follows. ($cmd is the command line passed).
$pipeName = "\\\\.\\pipe\\printerpipe";
#trigger_error("");
#$pipe = fopen($pipeName,'rb+');
$a = error_get_last();
if ($a['message'] == '') {
fwrite($pipe,$cmd);
$ans = fread($pipe,256);
} else {
print error message "service not loaded"
}
There is no custom error handler.
This has worked fine on my test machine (Window7) and on the production server - until today. Today it printed three reports, then reported the service not loaded error, and then printed 4 times more! I doubt that the system was busy or overloaded - I have one user, the report is tiny (most reports are one page), and the printing is spooled. Most reports appear on the printer as the reply to the request is being rendered by the browser.
Also the link between my Python code and the metworked printer appers to break every night, so i have to restart the service every morning. Can someone confirm that this is due to the printer being switched off, or suggest how to re-establish the link, other than restarting the printing service?
I need to make the service reliable, and I don't know how to proceed. Ideas and advice gratefully recieved.
It could be this code - I don't understand the error handling, and the code was copied from a post on the internet.