Created
August 23, 2011 16:01
-
-
Save carcus88/1165610 to your computer and use it in GitHub Desktop.
CakeShell - SOS JobScheduler CakeShell job for executing cakePHP shells
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function spooler_process() { | |
try { | |
var commandline; | |
var parameters; | |
var subprocess = spooler_task.create_subprocess(); | |
if (spooler_task.params.value("shell_command") != null && spooler_task.params.value("shell_command").length > 0) { | |
commandline = spooler_task.params.value("shell_command"); | |
} else { | |
throw "no value for shell command was given for parameter [shell_command]"; | |
} | |
/* these are samples for shell commands: | |
if ( String(java.lang.System.getProperty("os.name")).toLowerCase().substring(0,3) === "win" ) { | |
// Windows: the command to be executed, modify this to an executable script for your platform | |
commandline = "cmd.exe /V:ON /C " + spooler.directory + "samples/shell.webservice.command/webservice_shell.cmd"; | |
} else { | |
// Unix: the command to be executed, modify this to an executable script for your platform | |
commandline = spooler.directory + "samples/shell.webservice.command/webservice_shell.sh"; | |
} | |
*/ | |
// retrieve parameters from order payload (<job order="yes"/>) or from task parameters | |
if ( spooler_job.order_queue != null ) { | |
parameters = spooler_task.order.payload; | |
} else { | |
parameters = spooler_task.params; | |
} | |
if (parameters != null) { | |
var parameter_names = parameters.names().split(";"); | |
// Sort params by name since at this stage they are random order | |
// This is because the shell does not take param key=value pairs, it takes params in order so | |
// send params as param_1 => value param_2 => value etc and they will be kept in order | |
parameter_names.sort(); | |
for(var i=0; i<parameter_names.length; i++) { | |
if (parameter_names[i].toLowerCase() == "shell_command") continue; | |
// .. either append parameter names and values to the comamnd line (this needs more checking for vulnerabilities) | |
// spooler_log.debug3( "parameter " + parameter_names[i] + "=" + parameters.value(parameter_names[i]) ); | |
// commandline += " " + parameter_names[i] + "=\"" + parameters.value(parameter_names[i]) + "\""; | |
// .. or move parameters to environment variables which is more safe | |
subprocess.environment( parameter_names[i] ) = parameters.value( parameter_names[i] ); | |
// .. and for this sample append parameter names to the command line | |
commandline += " \""+parameters.value( parameter_names[i] )+"\""; | |
} | |
} | |
spooler_log.info( ".. executing command line: " + commandline ); | |
subprocess.start( commandline ); | |
// wait until the subprocess terminates, timeout is restricted by <job timeout="..."/> or subprocess.wait_for_termination(60) | |
subprocess.wait_for_termination(); | |
if (subprocess.terminated) { | |
spooler_log.info( "exit code=" + subprocess.exit_code ); | |
spooler_log.info( "termination signal=" + subprocess.termination_signal ); | |
} | |
return !(spooler_job.order_queue == null); | |
} catch (e) { | |
spooler_log.warn( String(e) ); | |
return false; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="iso-8859-1"?> | |
<spooler> | |
<config> | |
<web_services> | |
<web_service debug="no" name="CakeShell" url_path="/CakeShell" | |
request_xslt_stylesheet="config/scheduler_soap_request_modified.xslt" | |
response_xslt_stylesheet="config/scheduler_soap_response.xslt"> | |
</web_service> | |
<jobs> | |
<job name="CakeShell" title="EzCallout CakeShell" tasks="100"> | |
<description> | |
<include file="jobs\JobSchedulerWebServiceShellJob.xml"/> | |
</description> | |
<params> | |
<param name="shell_command" value=""c:\path\to\cake\console\cake.bat" -console .\console -app "c:\your_app\app" "/> | |
</params> | |
<script language="javascript"> | |
<include file="jobs\cake_shell_generic.js"/> | |
</script> | |
</job> | |
<config> | |
<spooler> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* The nusoap client is used to connect to the SOS Job Scheduler SOAP interface | |
* | |
* Note the SOS job scheulder interface uses a modified XSLT transformation (scheduler_soap_request_modified.xslt) | |
* to translate SOAP XML into the Job XML format. | |
* This modification was necessary since real SOAP calls use prefixes and the default XSLT (scheduler_soap_request.xslt) | |
* did not match or support this properly. | |
* | |
* @internal To debug SOAP calls use $client->setGlobalDebugLevel(9); | |
*/ | |
/** | |
* SOAP client | |
*/ | |
App::import('Vendor', 'nusoap', array('file' => 'nusoap/nusoap.php')); | |
/** | |
* Class to communicate with SOS Job Scheduler | |
* | |
*/ | |
class SchedulerRpcComponent extends Object { | |
/** | |
* Contains the controller this component is intitialized in | |
* | |
* @var object | |
*/ | |
public $controller; | |
/** | |
* The host the job scheduler is running on | |
* | |
* @var string | |
*/ | |
public $host = 'localhost'; | |
/** | |
* The port the job scheduler is running on | |
* | |
* @var string | |
*/ | |
public $port = "4444"; | |
/** | |
* The last error message recieved from the server | |
* @var string | |
*/ | |
public $lastErrorMessage = null; | |
/** | |
* Get the last error message | |
* @return string The last error message stored in $this->lastErrorMessage | |
*/ | |
public function getLastErrorMessage() { | |
return $this->lastErrorMessage; | |
} | |
/** | |
* Call any cake shell | |
* | |
* @param string $shell_name The shell name to call | |
* @param string $shell_function The shell function to execute | |
* @param array $params List of parameters to send to the command | |
* @returns mixed Task ID on sucess, false on error | |
* @since 1.0 | |
*/ | |
public function cake_shell($shell_name, $shell_function, $params) { | |
$webservices_uri = "http://" . $this->host . ":" . $this->port . '/CakeShell'; | |
$sendParams = array(); | |
$sendParams = array($shell_name,$shell_function); | |
foreach($params as $i=>$v) { | |
$sendParams[] = $v; | |
} | |
$allParams = array( 'job' => '', | |
'param' => $sendParams); | |
$allParams = '<job>CakeShell</job>'; | |
foreach ($sendParams as $i=>$v) { | |
$allParams .= "\n<param><name>{$i}</name><value>{$v}</value></param>"; | |
} | |
$namespace = 'http://www.sos-berlin.com/scheduler'; | |
$client = new nusoap_client($webservices_uri, false, null, null, null, null, 10, 30); | |
$resp = $client->call('startJob',$allParams,$namespace); | |
$this->lastErrorMessage = $client->getError(); | |
if ( $this->lastErrorMessage ) { | |
return false; | |
} else { | |
$taskID = $client->return; | |
if (is_numeric($taskID)) { | |
return $taskID; | |
} else { | |
return false; | |
} | |
} | |
} | |
/** | |
* Check if a task is complete | |
* | |
* @param integer $taskID Task ID to check | |
* @return boolean True if the task is complete, otherwise false | |
*/ | |
public function isTaskComplete($taskID) { | |
$cmd = "<show_task id=\"{$taskID}\"/>\r\n"; | |
$xml = $this->_sCommand($cmd); | |
if ( ! $xml ) { | |
$this->lastErrorMessage = 'XML command failed. ({$cmd})'; | |
return false; | |
} | |
// Convert the XML to an object and check the results for a valid end_time | |
$data = simplexml_load_string($xml); | |
if ( ! $data | |
|| ! property_exists($data, 'answer') | |
|| ! property_exists($data->answer, 'task')) { | |
return false; | |
} | |
if ( (string) $data->answer->task['end_time']) { | |
return true; | |
} | |
} | |
/** | |
* Execute a socket command on the scheduler | |
* | |
* NOTE: needs to be tested more on commands that return more then 1024 bytes | |
* | |
* @link http://localhost:4444/doc/en/xml_commands.xml | |
* @param string $cmd Command to execute | |
* @return mixed XML return value of the command on success, otherwise false | |
*/ | |
public function _sCommand($cmd) { | |
$s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); | |
socket_connect($s, $this->host, $this->port); | |
$bw = socket_write($s, $cmd); | |
$a = ''; | |
do { | |
$b = ''; | |
$b = socket_read($s, 1024, PHP_BINARY_READ); | |
if($b != "") { | |
$a .= $b; | |
} | |
} while( ! strstr($b, "\x00")); | |
if ( ! $a | |
|| substr($a,0,5) != '<?xml' ) { | |
return false; | |
} | |
socket_close($s); | |
return $a; | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="ISO-8859-1"?> | |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sos="http://www.sos-berlin.com/scheduler" | |
exclude-result-prefixes="soapenv sos" version="1.0"> | |
<xsl:output method="xml" indent="yes"/> | |
<xsl:param name="jobchain"></xsl:param> | |
<xsl:template match="/service_request/content/soapenv:Envelope | /soapenv:Envelope"> | |
<xsl:apply-templates select="soapenv:Body"/> | |
</xsl:template> | |
<xsl:template match="soapenv:Body"> | |
<xsl:apply-templates select="*" mode="soapBody"/> | |
</xsl:template> | |
<xsl:template match="*" mode="soapBody" priority="0.5"> | |
<!-- creat soap error for web service client if the below templates were not matched --> | |
<service_response> | |
<content> | |
<soapenv:Envelope> | |
<soapenv:Body> | |
<soapenv:Fault> | |
<faultcode>SOAP-ENV:Client</faultcode> | |
<faultstring>unknown command: <xsl:value-of select="name(.)"/></faultstring> | |
</soapenv:Fault> | |
</soapenv:Body> | |
</soapenv:Envelope> | |
</content> | |
</service_response> | |
</xsl:template> | |
<xsl:template match="sos:addOrder" mode="soapBody" priority="2"> | |
<add_order> | |
<xsl:attribute name="web_service"> | |
<xsl:value-of select="/service_request/web_service/@name"/> | |
</xsl:attribute> | |
<xsl:if test="id"> | |
<xsl:attribute name="id"> | |
<xsl:value-of select="id"/> | |
</xsl:attribute> | |
</xsl:if> | |
<xsl:attribute name="job_chain"> | |
<xsl:choose> | |
<xsl:when test="string-length(jobchain)"> | |
<xsl:value-of select="jobchain"/> | |
</xsl:when> | |
<xsl:otherwise> | |
<xsl:value-of select="$jobchain"/> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:attribute> | |
<xsl:if test="priority"> | |
<xsl:attribute name="priority"> | |
<xsl:value-of select="priority"/> | |
</xsl:attribute> | |
</xsl:if> | |
<xsl:if test="replace"> | |
<xsl:attribute name="replace"> | |
<xsl:if test="replace='true'">yes</xsl:if> | |
<xsl:if test="not(replace='true')">no</xsl:if> | |
</xsl:attribute> | |
</xsl:if> | |
<xsl:if test="title"> | |
<xsl:attribute name="title"> | |
<xsl:value-of select="title"/> | |
</xsl:attribute> | |
</xsl:if> | |
<xsl:if test="param"> | |
<params> | |
<xsl:apply-templates select="param"/> | |
</params> | |
</xsl:if> | |
<xsl:if test="payload"> | |
<payload> | |
<xsl:copy-of select="payload/*"/> | |
</payload> | |
</xsl:if> | |
<xsl:if test="xml_payload"> | |
<xml_payload> | |
<xsl:copy-of select="xml_payload/*"/> | |
</xml_payload> | |
</xsl:if> | |
</add_order> | |
</xsl:template> | |
<xsl:template match="sos:startJob" mode="soapBody" priority="2"> | |
<start_job> | |
<xsl:attribute name="web_service"> | |
<xsl:value-of select="/service_request/web_service/@name"/> | |
</xsl:attribute> | |
<xsl:if test="name"> | |
<xsl:attribute name="name"> | |
<xsl:value-of select="name"/> | |
</xsl:attribute> | |
</xsl:if> | |
<xsl:attribute name="job"> | |
<xsl:value-of select="job"/> | |
</xsl:attribute> | |
<xsl:if test="param"> | |
<params> | |
<xsl:apply-templates select="param"/> | |
</params> | |
</xsl:if> | |
<xsl:if test="after"> | |
<xsl:attribute name="after"> | |
<xsl:value-of select="after"/> | |
</xsl:attribute> | |
</xsl:if> | |
<xsl:if test="at"> | |
<xsl:attribute name="at"> | |
<xsl:value-of select="at"/> | |
</xsl:attribute> | |
</xsl:if> | |
</start_job> | |
</xsl:template> | |
<xsl:template match="sos:modifyJob" mode="soapBody" priority="2"> | |
<modify_job> | |
<xsl:attribute name="job"> | |
<xsl:value-of select="job"/> | |
</xsl:attribute> | |
<xsl:attribute name="cmd"> | |
<xsl:value-of select="cmd"/> | |
</xsl:attribute> | |
</modify_job> | |
</xsl:template> | |
<xsl:template match="sos:showOrder" mode="soapBody" priority="2"> | |
<show_order> | |
<xsl:attribute name="job_chain"> | |
<xsl:value-of select="jobChain"/> | |
</xsl:attribute> | |
<xsl:attribute name="order"> | |
<xsl:value-of select="order"/> | |
</xsl:attribute> | |
</show_order> | |
</xsl:template> | |
<xsl:template match="param"> | |
<param> | |
<xsl:attribute name="name"> | |
<xsl:value-of select="name"/> | |
</xsl:attribute> | |
<xsl:attribute name="value"> | |
<xsl:value-of select="value"/> | |
</xsl:attribute> | |
</param> | |
</xsl:template> | |
</xsl:stylesheet> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Add this to your Shell and you can call call $this->loadComponent('mycomponent'); | |
// now you can share components between controllers and shells (yippie) | |
/** | |
* Lazy loading of a component | |
* | |
* @var $component string Component to load | |
* @return boolean True on sucess, otherwise false | |
*/ | |
public function loadComponent($component) { | |
if (!property_exists($this,'Controller')) { | |
App::import('Core', 'Controller'); | |
$this->Controller =& new Controller(); | |
$this->Controller->ext = '.thtml'; // Use old style template names | |
} | |
if ( property_exists($this, $component)) { | |
return true; | |
} | |
App::import('Component',$component); | |
$cn = $component.'Component'; | |
$this->$component = new $cn; | |
if(method_exists($this->$component,'startup')){ | |
$this->$component->startup($this->Controller); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment