| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666 |
- <?php
- /**
- * Created by PhpStorm.
- * Author: 芸众商城 www.yunzshop.com
- * Date: 22/02/2017
- * Time: 18:48
- */
- namespace app\backend\modules\supervisord\services;
- use app\common\exceptions\ShopException;
- use PhpXmlRpc\Value;
- use PhpXmlRpc\Request;
- use PhpXmlRpc\Client;
- class Supervisor
- {
- const CHUNK_SIZE = 8192;
- protected $_hostname;
- protected $_port;
- protected $_timeout;
- protected $_username;
- protected $_password;
- protected $_socket;
- protected $_current_hostname;
- protected $_host_num;
- /**
- * Construct a supervisor client instance.
- * These parameters are handed over to fsockopen() so refer to its documentation for further details.
- *
- * @param string $hostname The hostname.
- * @param int $port The port number.
- */
- public function __construct($hostname, $port = -1,$_host_num = 1)
- {
- $this->_hostname = $hostname;
- $this->_port = $port;
- $this->_username = null;
- $this->_password = null;
- $this->_current_hostname = null;
- $this->_host_num = $_host_num;
- $this->setTimeout(null);
- }
- /**
- * Set the username and password.
- *
- * @param string $username The username.
- * @param string $password The password.
- */
- public function setAuth($username, $password) {
- $this->_username = $username;
- $this->_password = $password;
- }
- /**
- * Set the connection timeout.
- *
- * @param float $timeout The connection timeout, in seconds.
- */
- public function setTimeout($timeout) {
- $this->_timeout = is_null($timeout) ? ini_get("default_socket_timeout") : $timeout;
- }
- /**
- * @param null $hostname
- * @author: Merlin
- * @Time: 2020/9/23 18:06
- */
- public function setCurrentHostname($hostname = null){
- $this->_current_hostname = $hostname;
- }
- /**
- * Return the version of the RPC API used by supervisord
- *
- * This API is versioned separately from Supervisor itself. The API version returned by getAPIVersion only changes
- * when the API changes. Its purpose is to help the client identify with which version of the Supervisor API it
- * is communicating.
- *
- * When writing software that communicates with this API, it is highly recommended that you first test the
- * API version for compatibility before making method calls.
- *
- * @return string
- */
- public function getAPIVersion()
- {
- return $this->_rpcCall('supervisor', 'getAPIVersion');
- }
- /**
- * Return the version of the supervisor package in use by supervisord
- *
- * @return string
- */
- public function getSupervisorVersion()
- {
- return $this->_rpcCall('supervisor', 'getSupervisorVersion');
- }
- /**
- * Return identifying string of supervisord
- *
- * This method allows the client to identify with which Supervisor instance it is communicating in the case of
- * environments where multiple Supervisors may be running.
- *
- * The identification is a string that must be set in Supervisor's configuration file. This method simply returns
- * that value back to the client.
- *
- * @return string
- */
- public function getIdentification()
- {
- return $this->_rpcCall('supervisor', 'getIdentification');
- }
- /**
- * Return current state of supervisord as a struct
- *
- * This is an internal value maintained by Supervisor that determines what Supervisor believes to be its current
- * operational state.
- *
- * Some method calls can alter the current state of the Supervisor. For example, calling the method
- * supervisor.shutdown() while the station is in the RUNNING state places the Supervisor in the SHUTDOWN state
- * while it is shutting down.
- *
- * The supervisor.getState() method provides a means for the client to check Supervisor's state, both for
- * informational purposes and to ensure that the methods it intends to call will be permitted.
- *
- * array['statecode'] int State code
- * array['statename'] stirng State name
- *
- * @return array (see above)
- */
- public function getState()
- {
- return $this->_rpcCall('supervisor', 'getState');
- }
- /**
- * Return the PID of supervisord
- *
- * @return int
- */
- public function getPID()
- {
- return $this->_rpcCall('supervisor', 'getPID');
- }
- /**
- * Read length bytes from the main log starting at offset
- *
- * It can either return the entire log, a number of characters from the tail of the log, or a slice of the log
- * specified by the offset and length parameters:
- *
- * @param int $offset Offset to start reading from
- * @param int $length Number of bytes to read from the log
- * @return string
- */
- public function readLog($offset, $length = 0)
- {
- return $this->_rpcCall('supervisor', 'readLog', array(new Value($offset), new Value($length)));
- }
- /**
- * Clear the main log.
- *
- * If the log cannot be cleared because the log file does not exist, the fault NO_FILE will be raised. If the log
- * cannot be cleared for any other reason, the fault FAILED will be raised.
- *
- * @return boolean Result always returns true unless error
- */
- public function clearLog()
- {
- return $this->_rpcCall('supervisor', 'clearLog');
- }
- /**
- * Shut down the supervisor process
- *
- * This method shuts down the Supervisor daemon. If any processes are running, they are automatically killed
- * without warning.
- *
- * Unlike most other methods, if Supervisor is in the FATAL state, this method will still function.
- *
- * @return boolean Result always returns true unless error
- */
- public function shutdown()
- {
- return $this->_rpcCall('supervisor', 'shutdown');
- }
- /**
- * Restart the supervisor process
- *
- * This method soft restarts the Supervisor daemon. If any processes are running, they are automatically killed
- * without warning. Note that the actual UNIX process for Supervisor cannot restart; only Supervisor's main
- * program loop. This has the effect of resetting the internal states of Supervisor.
- *
- * Unlike most other methods, if Supervisor is in the FATAL state, this method will still function.
- *
- * @return boolean Result always returns true unless error
- */
- public function restart()
- {
- return $this->_rpcCall('supervisor', 'restart');
- }
- /**
- * Reload the supervisor configuration
- *
- * @return boolean Result always returns true unless error
- */
- public function reloadConfig()
- {
- return $this->_rpcCall('supervisor', 'reloadConfig');
- }
- /**
- * Get info about all available process configurations.
- *
- * Each struct represents a single process (i.e. groups get flattened).
- *
- * array[process]
- * ['group'] string Name of the process' group
- * ['name'] string Name of the process
- * ['inuse'] bool
- * ['autostart'] bool
- * ['process_prio'] int
- * ['group_prio'] int
- *
- * @return array
- */
- public function getAllConfigInfo()
- {
- return $this->_rpcCall('supervisor', 'getAllConfigInfo');
- }
- /**
- * Get info about a process named name
- *
- * array['name'] string Name of the process
- * array['group'] string Name of the process' group
- * array['strart'] int UNIX timestamp of when the process was started
- * array['stop'] int UNIX timestamp of when the process last ended, or 0 if the process has never been stopped
- * array['now'] int UNIX timestamp of the current time, which can be used to calculate process up-time
- * array['state'] int State code
- * array['statename'] string Description of state
- * array['stdout_logfile'] string Absolute path and filename to the STDOUT logfile
- * array['stderr_logfile'] string Absolute path and filename to the STDOUT logfile
- * array['spawnerr'] string Description of error that occurred during spawn, or empty string if none.
- * array['exitstatus'] int Exit status (errorlevel) of process, or 0 if the process is still running.
- * array['pid'] int UNIX process ID (PID) of the process, or 0 if the process is not running.
- *
- * @param string $processName The name of the process (or 'group:name')
- * @return array (see above)
- */
- public function getProcessInfo($processName)
- {
- return $this->_rpcCall('supervisor', 'getProcessInfo', $processName);
- }
- /**
- * Get info about all processes
- *
- * Each element contains a struct, and this struct contains the exact same elements as the struct returned by
- * getProcessInfo. If the process table is empty, an empty array is returned.
- *
- * array[process] array all processes information
- * [getProcessInfo] array {@Link getProcessInfo}
- *
- * @return array (see above)
- */
- public function getAllProcessInfo()
- {
- return $this->_rpcCall('supervisor', 'getAllProcessInfo');
- }
- /**
- * Start all processes listed in the configuration file
- *
- * @param bool $wait Wait for process to be fully started
- * @return boolean Result always true unless error
- */
- public function startAllProcesses($wait = true)
- {
- return $this->_rpcCall('supervisor', 'startAllProcesses', $wait);
- }
- /**
- * Start a process
- *
- * @param string $processName Process name (or group:name, or group:*)
- * @param bool $wait Wait for process to be fully started
- * @return boolean Result always true unless error
- */
- public function startProcess($processName, $wait = true)
- {
- return $this->_rpcCall('supervisor', 'startProcess', array(new Value($processName)));
- }
- /**
- * Start all processes in the group named 'name'
- *
- * @param string $groupName The group name
- * @param bool $wait Wait for process to be fully started
- * @return boolean Result always true unless error
- */
- public function startProcessGroup($groupName, $wait = true)
- {
- return $this->_rpcCall('supervisor', 'startProcessGroup', array(new Value($groupName())));
- }
- /**
- * @param bool $wait Wait for process to be fully started
- * @return boolean Result always true unless error
- */
- public function stopAllProcesses($wait = true)
- {
- return $this->_rpcCall('supervisor', 'stopAllProcesses', $wait);
- }
- /**
- * @param string $processName Process name (or group:name, or group:*)
- * @param bool $wait Wait for process to be fully started
- * @return boolean Result always true unless error
- */
- public function stopProcess($processName, $wait = true)
- {
- return $this->_rpcCall('supervisor', 'stopProcess', array(new Value($processName)));
- }
- /**
- * Stop all processes in the group named 'name'
- *
- * @param string $groupName The group name
- * @param bool $wait Wait for process to be fully started
- * @return boolean Result always true unless error
- */
- public function stopProcessGroup($groupName, $wait = true)
- {
- return $this->_rpcCall('supervisor', 'stopProcessGroup', array(new Value($groupName)));
- }
- /**
- * Send a string of chars to the stdin of the process name. If non-7-bit data is sent (unicode), it is encoded to
- * utf-8 before being sent to the process' stdin. If chars is not a string or is not unicode, raise
- * INCORRECT_PARAMETERS. If the process is not running, raise NOT_RUNNING. If the process' stdin cannot accept
- * input (e.g. it was closed by the child process), raise NO_FILE.
- *
- * @param string $processName The process name to send to (or 'group:name')
- * @param string $chars The character data to send to the process
- * @return boolean Result always true unless error
- */
- public function sendProcessStdin($processName, $chars)
- {
- return $this->_rpcCall('supervisor', 'sendProcessStdin', array(new Value($processName)));
- }
- /**
- * Send an event that will be received by event listener subprocesses subscribing to the RemoteCommunicationEvent.
- *
- * @param string $eventType String for the 'type' key in the event header
- * @param string $eventData Data for the event body
- * @return boolean Result always true unless error
- */
- public function sendRemoteCommEvent($eventType, $eventData)
- {
- return $this->_rpcCall('supervisor', 'sendRemoteCommEvent', array(new Value($eventType), new Value($eventData)));
- }
- /**
- * Update the config for a running process from config file.
- *
- * @param string $processName Name name of process group to add
- * @return boolean result true if successful
- */
- public function addProcessGroup($processName)
- {
- return $this->_rpcCall('supervisor', 'addProcessGroup', $processName);
- }
- /**
- * Remove a stopped process from the active configuration.
- *
- * @param string $processName Name name of process group to remove
- * @return boolean result Indicates whether the removal was successful
- */
- public function removeProcessGroup($processName)
- {
- return $this->_rpcCall('supervisor', 'removeProcessGroup', $processName);
- }
- /**
- * Read length bytes from name's stdout log starting at offset
- *
- * @param string $processName The name of the process (or 'group:name')
- * @param int $offset Offset to start reading from.
- * @param int $length Number of bytes to read from the log.
- * @return string
- */
- public function readProcessStdoutLog($processName, $offset, $length)
- {
- return $this->_rpcCall('supervisor', 'readProcessStdoutLog', array($processName, $offset, $length));
- }
- /**
- * Read length bytes from name's stderr log starting at offset
- *
- * @param string $processName The name of the process (or 'group:name')
- * @param int $offset Offset to start reading from.
- * @param int $length Number of bytes to read from the log.
- * @return string
- */
- public function readProcessStderrLog($processName, $offset, $length)
- {
- return $this->_rpcCall('supervisor', 'readProcessStderrLog', array(new Value($processName), new Value($offset), new Value($length)));
- }
- /**
- * Provides a more efficient way to tail the (stdout) log than readProcessStdoutLog(). Use readProcessStdoutLog()
- * to read chunks and tailProcessStdoutLog() to tail.
- *
- * Requests (length) bytes from the (name)'s log, starting at (offset). If the total log size is greater than
- * (offset + length), the overflow flag is set and the (offset) is automatically increased to position the buffer
- * at the end of the log. If less than (length) bytes are available, the maximum number of available bytes will be
- * returned. (offset) returned is always the last offset in the log +1.
- *
- * @param string $processName The name of the process (or 'group:name')
- * @param int $offset Offset to start reading from.
- * @param int $length Number of bytes to read from the log.
- * @return string
- */
- public function tailProcessStdoutLog($processName, $offset, $length)
- {
- return $this->_rpcCall('supervisor', 'tailProcessStdoutLog', array(new Value($processName), new Value($offset), new Value($length)));
- }
- /**
- * Provides a more efficient way to tail the (stderr) log than readProcessStderrLog(). Use readProcessStderrLog()
- * to read chunks and tailProcessStderrLog() to tail.
- *
- * Requests (length) bytes from the (name)'s log, starting at (offset). If the total log size is greater than
- * (offset + length), the overflow flag is set and the (offset) is automatically increased to position the buffer
- * at the end of the log. If less than (length) bytes are available, the maximum number of available bytes will
- * be returned. (offset) returned is always the last offset in the log +1.
- *
- * @param string $processName The name of the process (or 'group:name')
- * @param int $offset Offset to start reading from.
- * @param int $length Number of bytes to read from the log.
- * @return string
- */
- public function tailProcessStderrLog($processName, $offset, $length)
- {
- return $this->_rpcCall('supervisor', 'tailProcessStderrLog', array($processName, $offset, $length));
- }
- /**
- * Clear the stdout and stderr logs for the named process and reopen them.
- *
- * @param string $processName The name of the process (or 'group:name')
- * @return boolean Always true unless error
- */
- public function clearProcessLogs($processName)
- {
- return $this->_rpcCall('supervisor', 'clearProcessLogs', new Value($processName));
- }
- public function isRun() {
- $state = $this->getState();
- if ($state->errno == 5) {
- return false;
- }
- return true;
- }
- /**
- * Clear all process log files
- *
- * @return array An array of process status info structs
- */
- public function clearAllProcessLogs()
- {
- return $this->_rpcCall('supervisor', 'clearAllProcessLogs');
- }
- /**
- * Return an array listing the available method names
- *
- * @return array An array of method names available (strings).
- */
- public function listMethods()
- {
- return $this->_rpcCall('system', 'listMethods');
- }
- /**
- * Return a string showing the method's documentation
- *
- * @param string $methodName The name of the method.
- * @return string The documentation for the method name.
- */
- public function methodHelp($methodName)
- {
- return $this->_rpcCall('system', 'methodHelp', $methodName);
- }
- /**
- * Return an array describing the method signature in the form [rtype, ptype, ptype...] where rtype is the return
- * data type of the method, and ptypes are the parameter data types that the method accepts in method argument order.
- *
- * @param string $methodSignature The name of the method.
- * @return array
- */
- public function methodSignature($methodSignature)
- {
- return $this->_rpcCall('system', 'methodSignature', $methodSignature);
- }
- /**
- * Process an array of calls, and return an array of results. Calls should be structs of the form
- * {'methodName': string, 'params': array}. Each result will either be a single-item array containing the result
- * value, or a struct of the form {'faultCode': int, 'faultString': string}. This is useful when you need to make
- * lots of small calls without lots of round trips.
- *
- * @param array $calls An array of call requests
- * @return array
- */
- public function multicall(array $calls)
- {
- return $this->_rpcCall('system', 'multicall', $calls);
- }
- // Methods added by the Twiddler RPC extension from
- // https://github.com/mnaberez/supervisor_twiddler
- /**
- * Checks if the Twiddler extension is installed and configured in supervisord.conf
- *
- * @return bool true if the extension is available, else false
- */
- public function isTwiddlerAvailable()
- {
- $methods = $this->listMethods();
- return in_array('twiddler.getAPIVersion', $methods);
- }
- /**
- * Return the version of the Twiddler API
- *
- * @return string
- */
- public function getTwiddlerAPIVersion()
- {
- return $this->_rpcCall('twiddler', 'getAPIVersion');
- }
- /**
- * Return the group names
- *
- * @return array
- */
- public function getGroupNames()
- {
- return $this->_rpcCall('twiddler', 'getGroupNames');
- }
- /**
- * Add a program to a group
- *
- * @param string $group The name of the group
- * @param string $program The name of the program
- * @param array $options Options
- * @return boolean
- */
- public function addProgramToGroup($group, $program, $options = array())
- {
- return $this->_rpcCall('twiddler', 'addProgramToGroup', array($group, $program, $options));
- }
- /**
- * Remove a process from a group
- *
- * @param string $group The name of the group
- * @param string $processName The name of the process
- * @return boolean
- */
- public function removeProcessFromGroup($group, $processName)
- {
- return $this->_rpcCall('twiddler', 'removeProcessFromGroup', array($group, $processName));
- }
- /**
- * Log a message to the supervisor log
- *
- * @param string $msg The message
- * @param string $level The level (CRIT, ERRO, WARN, INFO, DEBG, TRAC or BLAT)
- * @return boolean
- */
- public function logMessage($msg, $level = "INFO")
- {
- return $this->_rpcCall('twiddler', 'log', array($msg, $level));
- }
- /**
- * @param string $namespace The namespace of the request
- * @param string $method The method in the namespace
- * @param mixed $args Optional arguments
- * @return mixed
- * @throws \Exception
- */
- protected function _rpcCall($namespace, $method, $args = array())
- {
- if (!is_array($args)) {
- $args = array($args);
- }
- // Send the request to the supervisor XML-RPC API.
- return $this->_doRequest($namespace, $method, $args);
- }
- /**
- * Do a request to the supervisor XML-RPC API
- *
- * @param string $namespace The namespace of the request
- * @param string $method The method in the namespace
- * @param mixed $args Optional arguments
- */
- protected function _doRequest($namespace, $method, $args)
- {
- $result = [];
- $hostname = $this->_hostname;
- if ($this->_current_hostname) {
- $hostname = [$this->_current_hostname];
- }
- foreach ($hostname as $_hostname) {
- $client = new Client($_hostname . ":" . $this->_port . "/RPC2");
- $client->return_type = "phpvals";
- $response = $client->send(new Request("$namespace.$method", $args));
- $result[$_hostname] = $response;
- }
- return $result;
- }
- public function getHostname()
- {
- return $this->_hostname;
- }
- public function getHostNum()
- {
- return $this->_host_num;
- }
- /**
- * Close the socket when the class destructs
- */
- public function __destruct()
- {
- if (is_resource($this->_socket)) {
- fclose($this->_socket);
- }
- }
- }
|