fix: 修复在windows环境下 pm2执行失败,找不到bun的问题
This commit is contained in:
74
assistant/src/module/get-bun-path.ts
Normal file
74
assistant/src/module/get-bun-path.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { execSync } from 'node:child_process';
|
||||
|
||||
export const getBunPath = (): string => {
|
||||
// 在不同平台上获取 bun 可执行文件的路径
|
||||
const isWindows = process.platform === 'win32';
|
||||
const bunExecutableName = isWindows ? 'bun.exe' : 'bun';
|
||||
|
||||
// 尝试从环境变量中获取 BUN_PATH
|
||||
if (process.env.BUN_PATH) {
|
||||
return process.env.BUN_PATH;
|
||||
}
|
||||
|
||||
// 在 Windows 上,尝试查找通过 npm/nvm 安装的 bun
|
||||
if (isWindows) {
|
||||
try {
|
||||
// 获取全局 node_modules 路径
|
||||
const globalNodeModules = execSync('npm root -g', { encoding: 'utf-8' }).trim();
|
||||
const bunExePath = path.join(globalNodeModules, 'bun', 'bin', 'bun.exe');
|
||||
|
||||
if (fs.existsSync(bunExePath)) {
|
||||
return bunExePath;
|
||||
}
|
||||
} catch (error) {
|
||||
// 忽略错误,继续尝试其他路径
|
||||
}
|
||||
|
||||
// 尝试从 which/where 命令获取 bun 路径
|
||||
try {
|
||||
const bunPath = execSync('where bun', { encoding: 'utf-8' }).trim().split('\n')[0];
|
||||
if (bunPath && bunPath.endsWith('.exe')) {
|
||||
return bunPath;
|
||||
}
|
||||
// 如果 where bun 返回的是 shell 脚本,查找对应的 .exe
|
||||
if (bunPath) {
|
||||
const bunDir = path.dirname(bunPath);
|
||||
const bunExePath = path.join(bunDir, 'node_modules', 'bun', 'bin', 'bun.exe');
|
||||
if (fs.existsSync(bunExePath)) {
|
||||
return bunExePath;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// 忽略错误
|
||||
}
|
||||
} else {
|
||||
// Unix-like 系统
|
||||
try {
|
||||
const bunPath = execSync('which bun', { encoding: 'utf-8' }).trim();
|
||||
if (bunPath && fs.existsSync(bunPath)) {
|
||||
return bunPath;
|
||||
}
|
||||
} catch (error) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
|
||||
// 常见的 bun 安装路径
|
||||
const commonPaths = [
|
||||
'/usr/local/bin/bun',
|
||||
'/usr/bin/bun',
|
||||
'C:\\Program Files\\Bun\\bun.exe',
|
||||
'C:\\Bun\\bun.exe',
|
||||
];
|
||||
|
||||
for (const p of commonPaths) {
|
||||
if (fs.existsSync(p)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找不到,返回默认的 bun 名称,假设在 PATH 中
|
||||
return bunExecutableName;
|
||||
}
|
||||
@@ -4,9 +4,11 @@ import './routes/index.ts';
|
||||
|
||||
import getPort, { portNumbers } from 'get-port';
|
||||
import { program } from 'commander';
|
||||
import { spawnSync } from 'child_process';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import path from 'node:path'
|
||||
import chalk from 'chalk';
|
||||
import { AssistantApp } from './lib.ts';
|
||||
import { getBunPath } from './module/get-bun-path.ts';
|
||||
export const runServer = async (port?: number, listenPath = '127.0.0.1') => {
|
||||
let _port: number | undefined;
|
||||
if (port) {
|
||||
@@ -56,29 +58,76 @@ program
|
||||
.option('-p, --port <port>', '服务端口')
|
||||
.option('-s, --start', '是否启动服务')
|
||||
.option('-e, --interpreter <interpreter>', '指定使用的解释器', 'bun')
|
||||
.option('-i, --home', 'home目录')
|
||||
.action(async (options) => {
|
||||
// console.log('当前执行路径:', execPath, inte);
|
||||
if (options.daemon) {
|
||||
const [_interpreter, execPath] = process.argv;
|
||||
const name = options.name;
|
||||
const port = options.port;
|
||||
let pm2Command = `pm2 start ${execPath} --interpreter ${options.interpreter} --name ${name} -- -s `;
|
||||
const runPath = path.resolve(execPath);
|
||||
|
||||
// Windows 下需要对路径进行转义处理
|
||||
const escapePath = (p: string) => {
|
||||
// 将反斜杠转换为正斜杠,PM2 在 Windows 上更好地支持正斜杠
|
||||
let normalized = p.replace(/\\/g, '/');
|
||||
// 如果路径包含空格,用引号包裹
|
||||
return normalized.includes(' ') ? `"${normalized}"` : normalized;
|
||||
};
|
||||
|
||||
// 获取解释器路径
|
||||
let interpreterPath = options.interpreter;
|
||||
if (options.interpreter === 'bun') {
|
||||
interpreterPath = getBunPath();
|
||||
console.log(chalk.gray('Bun 路径:'), interpreterPath);
|
||||
}
|
||||
|
||||
// 构建 pm2 命令字符串
|
||||
let pm2Command = `pm2 start ${escapePath(runPath)} --interpreter ${escapePath(interpreterPath)} --name ${name} -- -s`;
|
||||
|
||||
if (port) {
|
||||
pm2Command += ` -p ${port}`;
|
||||
}
|
||||
if (options.home) {
|
||||
pm2Command += ` --home`;
|
||||
}
|
||||
const result = spawnSync(pm2Command, {
|
||||
shell: true,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
if (result.error) {
|
||||
console.error('Error starting server:', result.error);
|
||||
|
||||
console.log(chalk.gray('执行命令:'), pm2Command);
|
||||
console.log(chalk.gray('脚本路径:'), runPath);
|
||||
|
||||
try {
|
||||
// 先删除可能存在的同名进程
|
||||
console.log(chalk.yellow('尝试删除旧进程...'));
|
||||
spawnSync(`pm2 delete ${name}`, [], {
|
||||
shell: true,
|
||||
stdio: 'pipe', // 忽略删除时的输出
|
||||
});
|
||||
|
||||
const result = spawnSync(pm2Command, [], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
windowsHide: false,
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
console.error(chalk.red('Error starting server:'), result.error.message);
|
||||
console.log(chalk.yellow('\n提示: 请检查:'));
|
||||
console.log(' 1. pm2 是否已安装: npm install -g pm2');
|
||||
console.log(' 2. bun 是否已安装且在 PATH 中');
|
||||
console.log(' 3. 尝试手动执行:', pm2Command);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (result.status !== 0) {
|
||||
console.error(chalk.red(`PM2 exited with code ${result.status}`));
|
||||
console.log(chalk.yellow('\n查看详细日志:'), `pm2 logs ${name}`);
|
||||
console.log(chalk.yellow('查看进程状态:'), 'pm2 list');
|
||||
process.exit(result.status || 1);
|
||||
}
|
||||
|
||||
console.log(chalk.green('✓ 以守护进程方式运行'));
|
||||
console.log(chalk.gray('查看日志:'), `pm2 logs ${name}`);
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error starting server:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('以守护进程方式运行');
|
||||
process.exit(0);
|
||||
} else if (options.start) {
|
||||
console.log('启动服务', chalk.green(assistantConfig.configDir));
|
||||
const config = assistantConfig.getCacheAssistantConfig();
|
||||
|
||||
5
assistant/src/test/get-bun.ts
Normal file
5
assistant/src/test/get-bun.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { getBunPath } from '../module/get-bun-path.ts';
|
||||
|
||||
const bunPath = getBunPath();
|
||||
|
||||
console.log('Detected Bun Path:', bunPath);
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kevisual/cli",
|
||||
"version": "0.0.69",
|
||||
"version": "0.0.70",
|
||||
"description": "envision 命令行工具",
|
||||
"type": "module",
|
||||
"basename": "/root/cli",
|
||||
|
||||
Reference in New Issue
Block a user