Skip to content

Instantly share code, notes, and snippets.

@alphp
Created March 5, 2019 20:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alphp/67f99429b9c76c972199c4051b3c57b6 to your computer and use it in GitHub Desktop.
Save alphp/67f99429b9c76c972199c4051b3c57b6 to your computer and use it in GitHub Desktop.
CakePHP 3 service example
<?php
namespace App\Shell;
if (!extension_loaded('win32service')) dl('php_win32service.dll');
use Cake\Core\Configure;
use Cake\Console\Shell;
use Cake\Log\Log;
Log::drop('debug');
Log::drop('error');
Log::config('service', array(
'engine' => 'File',
'levels' => ['notice', 'info', 'debug', 'warning', 'error', 'critical', 'alert', 'emergency'],
'path' => LOGS,
'file' => strftime('cake-service-%Y%m%d'),
'size' => false,
));
class ServiceShell extends Shell {
private $service = [
'run_file' => LOGS . '/service_run.log',
'loop_wait' => 10,
'service' => [
'service' => 'CakePHPServiceShell',
'display' => 'CakePHP ServiceShell',
'description' => 'Test CakePHP Service',
//'user' => '',
//'password' => '',
'path' => '"cake.cmd"',
'params' => 'Service run -q',
//'load_order' => '',
'svc_type' => WIN32_SERVICE_WIN32_OWN_PROCESS,
// WIN32_SERVICE_AUTO_START | WIN32_SERVICE_DEMAND_START | WIN32_SERVICE_DISABLED
//'start_type' => WIN32_SERVICE_AUTO_START,
//'error_control' => WIN32_SERVER_ERROR_IGNORE,
//'delayed_start' => false,
//'base_priority' => '',
],
];
private $status = null;
private $config = null;
private $cmd = null;
private $commands = ['run', 'create', 'delete', 'stop', 'start', 'debug'];
private function write_run ($msg = null) {
file_put_contents($this->service['run_file'], date('Y-m-d H:i:s') . $this->nl() . $msg);
}
public function create () {
if (!isset($this->status['CurrentState']) and $this->status == WIN32_ERROR_SERVICE_DOES_NOT_EXIST) {
$this->log('Creating service', 'warning');
$this->win32_op_service('win32_create_service', $this->service['service'], WIN32_NO_ERROR, 'Service created', 'debug');
}
}
public function delete () {
if (isset($this->status['CurrentState']) and $this->status['CurrentState'] == WIN32_SERVICE_STOPPED) {
$this->log('Deleting service', 'warning');
$this->win32_op_service('win32_delete_service', $this->service['service']['service'], WIN32_NO_ERROR, 'Service deleted', 'debug');
}
}
public function stop () {
if (isset($this->status['CurrentState']) and $this->status['CurrentState'] == WIN32_SERVICE_RUNNING) {
$this->log('Sending stop signal', 'warning');
$this->win32_op_service('win32_stop_service', $this->service['service']['service'], WIN32_NO_ERROR, 'Stop signal sent', 'debug');
}
}
public function start () {
if (isset($this->status['CurrentState']) and $this->status['CurrentState'] == WIN32_SERVICE_STOPPED) {
$this->log('Sending start signal', 'warning');
$this->win32_op_service('win32_start_service', $this->service['service']['service'], WIN32_NO_ERROR, 'Start signal sent', 'debug');
}
}
private function start_service () {
$this->log('Connecting with the service', 'info');
if (!$this->win32_op_service('win32_start_service_ctrl_dispatcher', $this->service['service']['service'])) return false;
return $this->set_service_running();
}
private function set_service_running () {
$this->log('Sending running signal', 'warning');
return $this->win32_op_service('win32_set_service_status', WIN32_SERVICE_RUNNING, true, 'Service started', 'info');
}
private function set_service_stopped () {
$this->log('Sending stopped signal', 'warning');
return $this->win32_op_service('win32_set_service_status', WIN32_SERVICE_STOPPED, true, 'Service stopped', 'info');
}
private function win32_op_service ($win32_op_service, $param, $cond = true, $msg = null, $debug = null) {
$err_code = $win32_op_service($param);
if ($err_code === $cond) {
if (isset($msg)) $this->log($msg, $debug);
return true;
} elseif ($err_code === false) {
$this->log('Problem with the parameters', 'error');
} elseif ($err_code === WIN32_ERROR_ACCESS_DENIED) {
$this->log('Access denied', 'error');
} else {
$this->log('Win32 Error Code ' . $err_code, 'error');
}
return false;
}
private function main_loop ($debug = false) {
$this->write_run();
$this->log('Do something', 'info');
}
public function run () {
if (isset($this->status['CurrentState']) and $this->status['CurrentState'] == WIN32_SERVICE_START_PENDING) {
if ($this->start_service()) {
while (WIN32_SERVICE_CONTROL_STOP != $ctr_msg = win32_get_last_control_message()) {
if ($ctr_msg === WIN32_SERVICE_CONTROL_INTERROGATE) {
win32_set_service_status(WIN32_SERVICE_RUNNING);
//} elseif ($ctr_msg === WIN32_SERVICE_CONTROL_CONTINUE) {
//} elseif ($ctr_msg === WIN32_SERVICE_CONTROL_PAUSE) {
//} elseif ($ctr_msg === WIN32_SERVICE_CONTROL_PRESHUTDOWN) {
//} elseif ($ctr_msg === WIN32_SERVICE_CONTROL_SHUTDOWN) {
//} elseif ($ctr_msg === WIN32_SERVICE_CONTROL_STOP) {
}
$this->main_loop();
$this->write_run('LOOP WAIT');
sleep($this->service['loop_wait']);
}
$this->set_service_stopped();
}
}
}
public function startup () {
$this->log('Querying service status', 'info');
$this->status = win32_query_service_status($this->service['service']['service']);
}
public function getOptionParser () {
$parser = parent::getOptionParser();
$parser->description('Test Servicio CakePHP.');
$subcommands = [];
$subcommands['run']['help'] = ('Ejecuta el bucle del servicio.');
$subcommands['create']['help'] = ('Crea el servicio.');
$subcommands['create']['parser']['description'][] = 'Crea el servicio.';
$subcommands['create']['parser']['description'][] = 'Es necesatiro tener permisos administrativos.';
$subcommands['create']['parser']['epilog'][] = 'Uso:';
$subcommands['create']['parser']['epilog'][] = 'Cake Service create';
$subcommands['delete']['help'] = ('Elimina el servicio.');
$subcommands['delete']['parser']['description'][] = 'Elimina el servicio.';
$subcommands['delete']['parser']['description'][] = 'Es necesatiro tener permisos administrativos.';
$subcommands['delete']['parser']['epilog'][] = 'Uso:';
$subcommands['delete']['parser']['epilog'][] = 'Cake Service delete';
$subcommands['stop']['help'] = ('Detiene el servicio.');
$subcommands['stop']['parser']['description'][] = 'Detiene el servicio.';
$subcommands['stop']['parser']['description'][] = 'Es necesatiro tener permisos administrativos.';
$subcommands['stop']['parser']['epilog'][] = 'Uso:';
$subcommands['stop']['parser']['epilog'][] = 'Cake Service stop';
$subcommands['start']['help'] = ('Inicia el servicio.');
$subcommands['start']['parser']['description'][] = 'Inicia el servicio.';
$subcommands['start']['parser']['description'][] = 'Es necesatiro tener permisos administrativos.';
$subcommands['start']['parser']['epilog'][] = 'Uso:';
$subcommands['start']['parser']['epilog'][] = 'Cake Service start';
$parser->addSubcommands($subcommands);
return $parser;
}
public function welcome () {}
public function main () {
$this->log($this->status, 'info');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment