You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
5.5 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
/**
* +----------------------------------------------------------------------
* | CRMEB [ CRMEB赋能开发者助力企业发展 ]
* +----------------------------------------------------------------------
* | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
* +----------------------------------------------------------------------
* | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
* +----------------------------------------------------------------------
* | Author: CRMEB Team <admin@crmeb.com>
* +----------------------------------------------------------------------
*/
namespace crmeb\utils;
use think\Response;
use think\console\Output;
/**
* 执行命令
* Class Terminal
* @author 等风来
* @email 136327134@qq.com
* @date 2023/4/13
* @package crmeb\utils
*/
class Terminal
{
/**
* 命令
* @var \string[][]
*/
protected $command = [
'npm-build' => [
'run_root' => '',
'command' => 'npm run build',
],
'npm-install' => [
'run_root' => '',
'command' => 'npm run install',
],
];
/**
* 执行内容保存地址
* @var string
*/
protected $outputFile;
/**
* 执行状态
* @var integer
*/
protected $procStatus;
/**
* 响应内容
* @var string
*/
protected $outputContent;
/**
* @var
*/
protected $output;
/**
* Terminal constructor.
*/
public function __construct()
{
$this->command['npm-build']['run_root'] = str_replace('DS', DS, config('app.admin_template_path'));
$this->command['npm-install']['run_root'] = str_replace('DS', DS, config('app.admin_template_path'));
$outputDir = root_path() . 'runtime' . DIRECTORY_SEPARATOR . 'terminal';
$this->outputFile = $outputDir . DIRECTORY_SEPARATOR . 'exec.log';
if (!is_dir($outputDir)) {
mkdir($outputDir, 0755, true);
}
file_put_contents($this->outputFile, '');
}
/**
* @param Output $output
* @author 等风来
* @email 136327134@qq.com
* @date 2023/4/13
*/
public function setOutput(Output $output)
{
$this->output = $output;
}
/**
* @return string
* @author 等风来
* @email 136327134@qq.com
* @date 2023/4/13
*/
public function adminTemplatePath()
{
return $this->command['npm-install']['run_root'];
}
/**
* 执行
* @param string $name
* @return string
* @author 等风来
* @email 136327134@qq.com
* @date 2023/4/13
*/
public function run(string $name)
{
if (!function_exists('proc_open')) {
throw new \RuntimeException('缺少proc_open函数无法运行');
}
if (!isset($this->command[$name])) {
throw new \RuntimeException('运行的命令不存在');
}
$command = $this->command[$name];
$descriptorspec = [0 => ['pipe', 'r'], 1 => ['file', $this->outputFile, 'w'], 2 => ['file', $this->outputFile, 'w']];
$process = proc_open($command['command'], $descriptorspec, $pipes, $command['run_root'], null, ['suppress_errors' => true]);
if (is_resource($process)) {
while ($this->getProcStatus($process)) {
$contents = file_get_contents($this->outputFile);
if (strlen($contents) && $this->outputContent != $contents) {
$newOutput = str_replace($this->outputContent, '', $contents);
if (preg_match('/\r\n|\r|\n/', $newOutput)) {
$this->echoOutputFlag($newOutput);
$this->outputContent = $contents;
}
}
usleep(500000);
}
foreach ($pipes as $pipe) {
fclose($pipe);
}
proc_close($process);
}
return $this->output('run success');
}
/**
* 判断状态
* @param $process
* @return bool
* @author 等风来
* @email 136327134@qq.com
* @date 2023/4/13
*/
public function getProcStatus($process): bool
{
$status = proc_get_status($process);
if ($status['running']) {
$this->procStatus = 1;
return true;
} elseif ($this->procStatus === 1) {
$this->procStatus = 0;
$this->output('exit: ' . $status['exitcode']);
if ($status['exitcode'] === 0) {
$this->echoOutputFlag('success');
} else {
$this->echoOutputFlag('error');
}
return true;
} else {
return false;
}
}
/**
* 直接输入响应
* @param string $message
* @author 等风来
* @email 136327134@qq.com
* @date 2023/4/13
*/
public function echoOutputFlag(string $message)
{
if ($this->output && $this->output instanceof Output) {
$this->output->info($message);
} else {
echo $this->output($message);
@ob_flush();
}
}
/**
* 返回响应内容
* @param string $data
* @return string
* @author 等风来
* @email 136327134@qq.com
* @date 2023/4/13
*/
private function output($data)
{
$data = [
'message' => $data,
];
return Response::create($data, 'json')->getContent();
}
}