Swoole runs in cli and then resides in memory. The RINT process can only be executed once during the entire lifecycle at startup time, after which all requests are completed within the third step. (This is one of the reasons why swoole is faster.) In this way, if the relevant php script is executed once, it will permanently reside in memory and update the code will not work. It's rough and tedious to restart the swoole service if you want the code to take effect. How can we automatically detect code files? Does the code take effect automatically?
I checked on the Internet that the runkit extension was used, and I found that it didn't work after testing (maybe I configured it incorrectly).
Later, a feasible method was found, which was modified and tested successfully. The specific steps are as follows:
Install inotify extensions
pecl install inotify
Add at the bottom of php.ini
extension=inotify.so
Used for monitoring files
Create PHP files
Create in the swoole/ToolKit directory
AutoReload.php
<?php
namespace Swoole\ToolKit;
class NotFound extends \Exception
{
}
class AutoReload
{
/**
* @var resource
*/
protected $inotify;
protected $pid;
protected $reloadFileTypes = array('.php' => true);
protected $watchFiles = array();
protected $afterNSeconds = 1;
/**
* Is reload ing
*/
protected $reloading = false;
protected $events;
/**
* root directory
* @var array
*/
protected $rootDirs = array();
public function putLog($log)
{
$_log = "[" . date('Y-m-d H:i:s') . "]\t" . $log . "\n";
echo $_log;
}
/**
* @param $serverPid
* @throws NotFound
*/
public function __construct($serverPid)
{
$this->pid = $serverPid;
if (posix_kill($serverPid, 0) === false) {
throw new NotFound("Process#$serverPid not found.");
}
$this->inotify = inotify_init();
$this->events = IN_MODIFY | IN_DELETE | IN_CREATE | IN_MOVE;
swoole_event_add($this->inotify, function ($ifd) {
$events = inotify_read($this->inotify);
if (!$events) {
return;
}
// var_dump($events);
foreach ($events as $ev) {
if ($ev['mask'] == IN_IGNORED) {
continue;
} else if ($ev['mask'] == IN_CREATE or $ev['mask'] == IN_DELETE or $ev['mask'] == IN_MODIFY or $ev['mask'] == IN_MOVED_TO or $ev['mask'] == IN_MOVED_FROM) {
$fileType = strrchr($ev['name'], '.');
//Non-restart type
if (!isset($this->reloadFileTypes[$fileType])) {
continue;
}
}
//reload, no more events, freeze for 1 second
if (!$this->reloading) {
$this->putLog("after 1 seconds reload the server");
//Something happened and we restarted it.
swoole_timer_after($this->afterNSeconds * 1000, array($this, 'reload'));
$this->reloading = true;
}
}
});
}
public function reload()
{
$this->putLog("reloading");
//Send a signal to the main process
posix_kill($this->pid, SIGUSR1);
//Clean up all monitors
$this->clearWatch();
//Re-monitoring
foreach ($this->rootDirs as $root) {
$this->watch($root);
}
//Continue reload ing
$this->reloading = false;
}
/**
* add file type
* @param $type
*/
public function addFileType($type)
{
$type = trim($type, '.');
$this->reloadFileTypes['.' . $type] = true;
}
/**
* Adding Events
* @param $inotifyEvent
*/
public function addEvent($inotifyEvent)
{
$this->events |= $inotifyEvent;
}
/**
* Clean up all inotify listeners
*/
public function clearWatch()
{
foreach ($this->watchFiles as $wd) {
inotify_rm_watch($this->inotify, $wd);
}
$this->watchFiles = array();
}
/**
* @param $dir
* @param bool $root
* @return bool
* @throws NotFound
*/
public function watch($dir, $root = true)
{
//directory does not exist
if (!is_dir($dir)) {
throw new NotFound("[$dir] is not a directory.");
}
//Avoid repetitive monitoring
if (isset($this->watchFiles[$dir])) {
return false;
}
//root directory
if ($root) {
$this->rootDirs[] = $dir;
}
$wd = inotify_add_watch($this->inotify, $dir, $this->events);
$this->watchFiles[$dir] = $wd;
$files = scandir($dir);
foreach ($files as $f) {
if ($f == '.' or $f == '..') {
continue;
}
$path = $dir . '/' . $f;
//Recursive catalogue
if (is_dir($path)) {
$this->watch($path, false);
}
//Detecting file type
$fileType = strrchr($f, '.');
if (isset($this->reloadFileTypes[$fileType])) {
$wd = inotify_add_watch($this->inotify, $path, $this->events);
$this->watchFiles[$path] = $wd;
}
}
return true;
}
public function run()
{
swoole_event_wait();
}
}
Create under the swoole folder
daemon.php
<?php
require __DIR__ . '/ToolKit/AutoReload.php';
//PID for storing SWOOLE services
$file = __DIR__ . '/../../examples/app_server.pid';
if (file_exists($file)) {
$pid = file_get_contents($file);
$kit = new Swoole\ToolKit\AutoReload((int)$pid);
$kit->watch(__DIR__ . '/../../');//Monitoring Directory
$kit->run();
}
Create startup scripts
vim swoole.sh
#!/bin/bash
apppidpath="/var/www/examples/app_server.pid"
pid="/tmp/swoole.pid" #Process Locking
if [ -e $pid ]
then
exit 0
fi
echo $$ > ${pid}
if [ -f ${apppidpath} ]
then
nohup php /var/www/libs/Swoole/daemon.php </dev/null &>/dev/null &
echo "deamon is ok!"
else
echo "swoole is stopped!"
fi
#Delete Locked Files
rm $pid -rf
chmod +x swoole.sh
Start monitoring program
./swoole.sh
At this point, the Linux monitoring file automatically realizes the deployment of the swoole framework hot update. You can modify the code to see if it works.
If there are any problems in the use process, you are welcome to criticize and correct them. If you have any good suggestions, I hope to give you a reply. Thank you again.