new_naweigete/crmeb/utils/Terminal.php
2025-03-12 10:47:34 +08:00

209 lines
5.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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();
}
}