1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Hhxsv5\LaravelS\Illuminate; |
4
|
|
|
|
5
|
|
|
use Illuminate\Console\Command; |
6
|
|
|
use Illuminate\Filesystem\Filesystem; |
7
|
|
|
|
8
|
|
|
class LaravelSCommandBAK extends Command |
9
|
|
|
{ |
10
|
|
|
protected $signature = 'laravels'; |
11
|
|
|
|
12
|
|
|
protected $description = 'LaravelS console tool'; |
13
|
|
|
|
14
|
|
|
protected $actions; |
15
|
|
|
|
16
|
|
|
protected $isLumen = false; |
17
|
|
|
|
18
|
|
|
public function __construct() |
19
|
|
|
{ |
20
|
|
|
$this->actions = ['start', 'stop', 'restart', 'reload', 'publish']; |
21
|
|
|
$actions = implode('|', $this->actions); |
22
|
|
|
$this->signature .= sprintf( |
23
|
|
|
' {action : %s} {--d|daemonize : Whether run as a daemon for start & restart} {--i|ignore : Whether ignore checking process pid for start & restart}', |
24
|
|
|
$actions |
25
|
|
|
); |
26
|
|
|
$this->description .= ': ' . $actions; |
27
|
|
|
|
28
|
|
|
parent::__construct(); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
public function fire() |
32
|
|
|
{ |
33
|
|
|
$this->handle(); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
public function handle() |
37
|
|
|
{ |
38
|
|
|
$action = (string)$this->argument('action'); |
39
|
|
|
if (!in_array($action, $this->actions, true)) { |
40
|
|
|
$this->warn(sprintf( |
41
|
|
|
'LaravelS: action %s is not available, only support %s', |
42
|
|
|
$action, |
43
|
|
|
implode('|', $this->actions) |
44
|
|
|
) |
45
|
|
|
); |
46
|
|
|
return 127; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
$this->isLumen = stripos($this->getApplication()->getVersion(), 'Lumen') !== false; |
50
|
|
|
$this->loadConfigManually(); |
51
|
|
|
return $this->{$action}(); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
protected function loadConfigManually() |
55
|
|
|
{ |
56
|
|
|
// Load configuration laravel.php manually for Lumen |
57
|
|
|
$basePath = config('laravels.laravel_base_path') ?: base_path(); |
58
|
|
|
if ($this->isLumen && file_exists($basePath . '/config/laravels.php')) { |
59
|
|
|
$this->getLaravel()->configure('laravels'); |
|
|
|
|
60
|
|
|
} |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
protected function outputInfo() |
64
|
|
|
{ |
65
|
|
|
static $logo = <<<EOS |
66
|
|
|
_ _ _____ |
67
|
|
|
| | | |/ ____| |
68
|
|
|
| | __ _ _ __ __ ___ _____| | (___ |
69
|
|
|
| | / _` | '__/ _` \ \ / / _ \ |\___ \ |
70
|
|
|
| |___| (_| | | | (_| |\ V / __/ |____) | |
71
|
|
|
|______\__,_|_| \__,_| \_/ \___|_|_____/ |
72
|
|
|
|
73
|
|
|
EOS; |
74
|
|
|
$this->info($logo); |
75
|
|
|
$this->info('Speed up your Laravel/Lumen'); |
76
|
|
|
$this->table(['Component', 'Version'], [ |
77
|
|
|
['Component' => 'PHP', 'Version' => phpversion()], |
78
|
|
|
['Component' => 'Swoole', 'Version' => \swoole_version()], |
79
|
|
|
['Component' => $this->getApplication()->getName(), 'Version' => $this->getApplication()->getVersion()], |
80
|
|
|
]); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
protected function preSet(array &$svrConf) |
84
|
|
|
{ |
85
|
|
|
if (!isset($svrConf['enable_gzip'])) { |
86
|
|
|
$svrConf['enable_gzip'] = false; |
87
|
|
|
} |
88
|
|
|
if (empty($svrConf['laravel_base_path'])) { |
89
|
|
|
$svrConf['laravel_base_path'] = base_path(); |
90
|
|
|
} |
91
|
|
|
if (empty($svrConf['process_prefix'])) { |
92
|
|
|
$svrConf['process_prefix'] = $svrConf['laravel_base_path']; |
93
|
|
|
} |
94
|
|
|
if (empty($svrConf['swoole']['document_root'])) { |
95
|
|
|
$svrConf['swoole']['document_root'] = $svrConf['laravel_base_path'] . '/public'; |
96
|
|
|
} |
97
|
|
|
if ($this->option('daemonize')) { |
98
|
|
|
$svrConf['swoole']['daemonize'] = true; |
99
|
|
|
} |
100
|
|
|
if (empty($svrConf['swoole']['pid_file'])) { |
101
|
|
|
$svrConf['swoole']['pid_file'] = storage_path('laravels.pid'); |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
protected function preCheck(array $svrConf) |
106
|
|
|
{ |
107
|
|
|
if (!empty($svrConf['enable_gzip']) && version_compare(\swoole_version(), '4.1.0', '>=')) { |
108
|
|
|
$this->error('LaravelS: enable_gzip is DEPRECATED since Swoole 4.1.0, set http_compression of Swoole instead, http_compression is disabled by default.'); |
109
|
|
|
$this->info('LaravelS: if there is a proxy server like Nginx, suggest that enable gzip in Nginx and disable gzip in Swoole, to avoid the repeated gzip compression for response.'); |
110
|
|
|
return 1; |
111
|
|
|
} |
112
|
|
|
if (!empty($svrConf['events'])) { |
113
|
|
|
if (empty($svrConf['swoole']['task_worker_num']) || $svrConf['swoole']['task_worker_num'] <= 0) { |
114
|
|
|
$this->error('LaravelS: Asynchronous event listening needs to set task_worker_num > 0'); |
115
|
|
|
return 1; |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
return 0; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
protected function start() |
122
|
|
|
{ |
123
|
|
|
$this->outputInfo(); |
124
|
|
|
|
125
|
|
|
$svrConf = config('laravels'); |
126
|
|
|
|
127
|
|
|
$this->preSet($svrConf); |
128
|
|
|
|
129
|
|
|
$ret = $this->preCheck($svrConf); |
130
|
|
|
if ($ret !== 0) { |
131
|
|
|
return $ret; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
$laravelConf = [ |
135
|
|
|
'root_path' => $svrConf['laravel_base_path'], |
136
|
|
|
'static_path' => $svrConf['swoole']['document_root'], |
137
|
|
|
'register_providers' => array_unique((array)array_get($svrConf, 'register_providers', [])), |
138
|
|
|
'is_lumen' => $this->isLumen, |
139
|
|
|
'_SERVER' => $_SERVER, |
140
|
|
|
'_ENV' => $_ENV, |
141
|
|
|
]; |
142
|
|
|
|
143
|
|
|
if (isset($svrConf['socket_type']) |
144
|
|
|
&& in_array($svrConf['socket_type'], [\SWOOLE_SOCK_UNIX_DGRAM, \SWOOLE_SOCK_UNIX_STREAM]) |
145
|
|
|
) { |
146
|
|
|
$listenAt = $svrConf['listen_ip']; |
147
|
|
|
} else { |
148
|
|
|
$listenAt = sprintf('%s:%s', $svrConf['listen_ip'], $svrConf['listen_port']); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
if (!$this->option('ignore') && file_exists($svrConf['swoole']['pid_file'])) { |
152
|
|
|
$pid = (int)file_get_contents($svrConf['swoole']['pid_file']); |
153
|
|
|
if ($pid > 0 && $this->killProcess($pid, 0)) { |
154
|
|
|
$this->warn(sprintf('LaravelS: PID[%s] is already running at %s.', $pid, $listenAt)); |
155
|
|
|
return 1; |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
if (!$svrConf['swoole']['daemonize']) { |
160
|
|
|
$this->info(sprintf('LaravelS: Swoole is listening at %s, press Ctrl+C to quit.', $listenAt)); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
// Implements gracefully reload, avoid including laravel's files before worker start |
164
|
|
|
$cmd = sprintf('%s -c "%s" %s/../GoLaravelS.php', PHP_BINARY, php_ini_loaded_file(), __DIR__); |
165
|
|
|
$params = json_encode(compact('svrConf', 'laravelConf')); |
166
|
|
|
$ret = $this->popen($cmd, $params); |
167
|
|
|
if ($ret === false) { |
168
|
|
|
$this->error('LaravelS: popen ' . $cmd . ' failed'); |
169
|
|
|
return 1; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
$pidFile = $svrConf['swoole']['pid_file']; |
173
|
|
|
|
174
|
|
|
// Make sure that master process started |
175
|
|
|
$time = 0; |
176
|
|
|
while (!file_exists($pidFile) && $time <= 20) { |
177
|
|
|
usleep(100000); |
178
|
|
|
$time++; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
if (file_exists($pidFile)) { |
182
|
|
|
$this->info(sprintf('LaravelS: PID[%s] is listening at %s.', file_get_contents($pidFile), $listenAt)); |
183
|
|
|
return 0; |
184
|
|
|
} else { |
185
|
|
|
$this->error(sprintf('LaravelS: PID file[%s] does not exist.', $pidFile)); |
186
|
|
|
return 1; |
187
|
|
|
} |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
protected function popen($cmd, $input = null) |
191
|
|
|
{ |
192
|
|
|
$fp = popen($cmd, 'w'); |
193
|
|
|
if ($fp === false) { |
194
|
|
|
return false; |
195
|
|
|
} |
196
|
|
|
if ($input !== null) { |
197
|
|
|
fwrite($fp, $input); |
198
|
|
|
} |
199
|
|
|
pclose($fp); |
200
|
|
|
return true; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
protected function stop() |
204
|
|
|
{ |
205
|
|
|
$pidFile = config('laravels.swoole.pid_file') ?: storage_path('laravels.pid'); |
206
|
|
|
if (!file_exists($pidFile)) { |
207
|
|
|
$this->info('LaravelS: already stopped.'); |
208
|
|
|
return 0; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
$pid = (int)file_get_contents($pidFile); |
212
|
|
|
if ($this->killProcess($pid, 0)) { |
213
|
|
|
if ($this->killProcess($pid, SIGTERM)) { |
214
|
|
|
// Make sure that master process quit |
215
|
|
|
$time = 1; |
216
|
|
|
$waitTime = config('laravels.swoole.max_wait_time', 60); |
217
|
|
|
while ($this->killProcess($pid, 0)) { |
218
|
|
|
if ($time > $waitTime) { |
219
|
|
|
$this->error("LaravelS: PID[{$pid}] cannot be stopped gracefully in {$waitTime}s, will be stopped forced right now."); |
220
|
|
|
return 1; |
221
|
|
|
} |
222
|
|
|
$this->warn("LaravelS: Waiting PID[{$pid}] to stop. [{$time}]"); |
223
|
|
|
sleep(1); |
224
|
|
|
$time++; |
225
|
|
|
} |
226
|
|
|
if (file_exists($pidFile)) { |
227
|
|
|
unlink($pidFile); |
228
|
|
|
} |
229
|
|
|
$this->info("LaravelS: PID[{$pid}] is stopped."); |
230
|
|
|
return 0; |
231
|
|
|
} else { |
232
|
|
|
$this->error("LaravelS: PID[{$pid}] is stopped failed."); |
233
|
|
|
return 1; |
234
|
|
|
} |
235
|
|
|
} else { |
236
|
|
|
$this->warn("LaravelS: PID[{$pid}] does not exist, or permission denied."); |
237
|
|
|
if (file_exists($pidFile)) { |
238
|
|
|
unlink($pidFile); |
239
|
|
|
} |
240
|
|
|
return $this->option('ignore') ? 0 : 1; |
241
|
|
|
} |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
protected function restart() |
245
|
|
|
{ |
246
|
|
|
$exitCode = $this->stop(); |
247
|
|
|
if ($exitCode !== 0) { |
248
|
|
|
return $exitCode; |
249
|
|
|
} |
250
|
|
|
return $this->start(); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
protected function reload() |
254
|
|
|
{ |
255
|
|
|
$pidFile = config('laravels.swoole.pid_file') ?: storage_path('laravels.pid'); |
256
|
|
|
if (!file_exists($pidFile)) { |
257
|
|
|
$this->error('LaravelS: it seems that LaravelS is not running.'); |
258
|
|
|
return 1; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
$pid = (int)file_get_contents($pidFile); |
262
|
|
|
if (!$this->killProcess($pid, 0)) { |
263
|
|
|
$this->error("LaravelS: PID[{$pid}] does not exist, or permission denied."); |
264
|
|
|
return 1; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
if ($this->killProcess($pid, SIGUSR1)) { |
268
|
|
|
$now = date('Y-m-d H:i:s'); |
269
|
|
|
$this->info("LaravelS: PID[{$pid}] is reloaded at {$now}."); |
270
|
|
|
return 0; |
271
|
|
|
} else { |
272
|
|
|
$this->error("LaravelS: PID[{$pid}] is reloaded failed."); |
273
|
|
|
return 1; |
274
|
|
|
} |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
protected function publish() |
278
|
|
|
{ |
279
|
|
|
$basePath = config('laravels.laravel_base_path') ?: base_path(); |
280
|
|
|
$to = $basePath . '/config/laravels.php'; |
281
|
|
|
if (file_exists($to)) { |
282
|
|
|
$choice = $this->anticipate($to . ' already exists, do you want to override it ? Y/N', ['Y', 'N'], 'N'); |
283
|
|
|
if (!$choice || strtoupper($choice) !== 'Y') { |
284
|
|
|
$this->info('Publishing skipped.'); |
285
|
|
|
return 0; |
286
|
|
|
} |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
try { |
290
|
|
|
return $this->call('vendor:publish', ['--provider' => LaravelSServiceProvider::class, '--force' => true]); |
291
|
|
|
} catch (\InvalidArgumentException $e) { |
292
|
|
|
// do nothing. |
293
|
|
|
} catch (\Exception $e) { |
294
|
|
|
throw $e; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
$from = __DIR__ . '/../../config/laravels.php'; |
298
|
|
|
$toDir = dirname($to); |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* @var Filesystem $files |
302
|
|
|
*/ |
303
|
|
|
$files = app(Filesystem::class); |
304
|
|
|
|
305
|
|
|
if (!$files->isDirectory($toDir)) { |
306
|
|
|
$files->makeDirectory($toDir, 0755, true); |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
$files->copy($from, $to); |
310
|
|
|
|
311
|
|
|
$from = str_replace($basePath, '', realpath($from)); |
312
|
|
|
|
313
|
|
|
$to = str_replace($basePath, '', realpath($to)); |
314
|
|
|
|
315
|
|
|
$this->line('<info>Copied File</info> <comment>[' . $from . ']</comment> <info>To</info> <comment>[' . $to . ']</comment>'); |
316
|
|
|
return 0; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
protected function killProcess($pid, $sig) |
320
|
|
|
{ |
321
|
|
|
try { |
322
|
|
|
return \swoole_process::kill($pid, $sig); |
323
|
|
|
} catch (\Exception $e) { |
324
|
|
|
return false; |
325
|
|
|
} |
326
|
|
|
} |
327
|
|
|
} |
328
|
|
|
|
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.