refactor: 优化检查机制
This commit is contained in:
parent
4fe35676f3
commit
54aa32d0e4
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "Miao-Yunzai",
|
||||
"script": "./index.js",
|
||||
"max_memory_restart": "512M",
|
||||
"restart_delay": 60000
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import '../src/init/modules.js'
|
||||
import '../src/init/logger.js'
|
||||
import '../src/init/config.js'
|
||||
import '../src/init/logger.js'
|
||||
import '../src/init/redis.js'
|
||||
import './tailwindcss.js'
|
||||
import Koa from 'koa'
|
||||
|
|
|
@ -5,8 +5,24 @@ module.exports = {
|
|||
name: 'Miao-Yunzai',
|
||||
script: './index.js',
|
||||
args: argv,
|
||||
max_memory_restart: '512M',
|
||||
restart_delay: 60000
|
||||
// 超时时间内进程仍未终止,则 PM2 将强制终止该进程
|
||||
kill_timeout: 5000,
|
||||
// 发送意外重启
|
||||
autorestart: true,
|
||||
// 进程到达指定内存时重启
|
||||
max_memory_restart: '2G',
|
||||
// 进程重启之间的延迟时间
|
||||
restart_delay: 5000,
|
||||
// 进程重启之间的最大延迟时间
|
||||
restart_delay_max: 10000,
|
||||
// 将 PM2 进程列表自动保存到文件中
|
||||
autodump: true,
|
||||
// 不监听文件变化
|
||||
watch: false,
|
||||
env: {
|
||||
NODE_ENV: 'production'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
console.log('module.exports', module.exports)
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import { execAsync, readJSON } from "./utils.js"
|
||||
|
||||
/**
|
||||
* 校验运行
|
||||
* @returns
|
||||
*/
|
||||
export async function checkRun() {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if (process.argv[1].includes('pm2')) return
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if (process.argv[1].includes('test')) return
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const cfg = readJSON('./config/pm2/pm2.json')
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if (!cfg) return
|
||||
/**
|
||||
*
|
||||
*/
|
||||
execAsync(`pm2 show ${cfg.apps[0].name}`).then((status) => {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if (status.stdout.includes('online')) {
|
||||
logger.mark('检测到后台正在运行')
|
||||
logger.mark('已停止后台进程,防止重复运行')
|
||||
execAsync(`pm2 stop ${cfg.apps[0].name}`).catch(logger.error)
|
||||
}
|
||||
}).catch(() => { })
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
import log4js from 'log4js'
|
||||
import chalk from 'chalk'
|
||||
import cfg from './config.js'
|
||||
import { mkdirSync } from 'node:fs'
|
||||
|
||||
/**
|
||||
* 创建日志
|
||||
* @returns
|
||||
*/
|
||||
function createLog() {
|
||||
// log4js.levels.levels[5].level = Number.MAX_VALUE
|
||||
// log4js.levels.levels.sort((a, b) => a.level - b.level)
|
||||
log4js.configure({
|
||||
appenders: {
|
||||
console: {
|
||||
type: 'console',
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '%[[MYZ-V4][%d{hh:mm:ss.SSS}][%4.4p]%] %m'
|
||||
}
|
||||
},
|
||||
command: {
|
||||
type: 'dateFile', // 可以是console,dateFile,file,Logstash等
|
||||
filename: 'logs/command', // 将会按照filename和pattern拼接文件名
|
||||
pattern: 'yyyy-MM-dd.log',
|
||||
numBackups: 15,
|
||||
alwaysIncludePattern: true,
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m'
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: 'file',
|
||||
filename: 'logs/error.log',
|
||||
alwaysIncludePattern: true,
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m'
|
||||
}
|
||||
}
|
||||
},
|
||||
categories: {
|
||||
default: { appenders: ['console'], level: cfg.bot.log_level },
|
||||
command: { appenders: ['console', 'command'], level: 'warn' },
|
||||
error: { appenders: ['console', 'command', 'error'], level: 'error' }
|
||||
}
|
||||
})
|
||||
|
||||
const defaultLogger = log4js.getLogger('message')
|
||||
const commandLogger = log4js.getLogger('command')
|
||||
const errorLogger = log4js.getLogger('error')
|
||||
|
||||
|
||||
/**
|
||||
* 调整error日志等级
|
||||
*/
|
||||
const logger = {
|
||||
trace() {
|
||||
defaultLogger.trace.call(defaultLogger, ...arguments)
|
||||
},
|
||||
debug() {
|
||||
defaultLogger.debug.call(defaultLogger, ...arguments)
|
||||
},
|
||||
info() {
|
||||
defaultLogger.info.call(defaultLogger, ...arguments)
|
||||
},
|
||||
// warn及以上的日志采用error策略
|
||||
warn() {
|
||||
commandLogger.warn.call(defaultLogger, ...arguments)
|
||||
},
|
||||
error() {
|
||||
errorLogger.error.call(errorLogger, ...arguments)
|
||||
},
|
||||
fatal() {
|
||||
errorLogger.fatal.call(errorLogger, ...arguments)
|
||||
},
|
||||
mark() {
|
||||
errorLogger.mark.call(commandLogger, ...arguments)
|
||||
}
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置日志样式
|
||||
*/
|
||||
export function loggerInit() {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
mkdirSync('./logs', {
|
||||
'recursive': true
|
||||
})
|
||||
|
||||
/**
|
||||
* 全局变量 logger
|
||||
*/
|
||||
global.logger = createLog() as any
|
||||
logger.chalk = chalk
|
||||
logger.red = chalk.red
|
||||
logger.green = chalk.green
|
||||
logger.yellow = chalk.yellow
|
||||
logger.blue = chalk.blue
|
||||
logger.magenta = chalk.magenta
|
||||
logger.cyan = chalk.cyan
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
import cfg from "./config.js"
|
||||
import { execAsync, sleep } from "./utils.js"
|
||||
import { createClient } from "redis"
|
||||
|
||||
/**
|
||||
* 初始化全局redis客户端
|
||||
* @returns
|
||||
*/
|
||||
export async function redisInit() {
|
||||
const rc = cfg.redis
|
||||
const redisUn = rc.username || ""
|
||||
let redisPw = rc.password ? `:${rc.password}` : ""
|
||||
if (rc.username || rc.password) {
|
||||
redisPw += "@"
|
||||
}
|
||||
const redisUrl = `redis://${redisUn}${redisPw}${rc.host}:${rc.port}/${rc.db}`
|
||||
let client = createClient({ url: redisUrl })
|
||||
|
||||
try {
|
||||
logger.info(`正在连接 ${logger.blue(redisUrl)}`)
|
||||
await client.connect()
|
||||
} catch (err) {
|
||||
logger.error(`Redis 错误:${logger.red(err)}`)
|
||||
|
||||
const cmd = "redis-server --save 900 1 --save 300 10 --daemonize yes" + await aarch64()
|
||||
logger.info("正在启动 Redis...")
|
||||
|
||||
await execAsync(cmd)
|
||||
|
||||
await sleep(1000)
|
||||
|
||||
try {
|
||||
client = createClient({ url: redisUrl })
|
||||
await client.connect()
|
||||
} catch (err) {
|
||||
logger.error(`Redis 错误:${logger.red(err)}`)
|
||||
logger.error(`请先启动 Redis:${logger.blue(cmd)}`)
|
||||
process.exit()
|
||||
}
|
||||
}
|
||||
|
||||
client.on("error", async err => {
|
||||
logger.error(`Redis 错误:${logger.red(err)}`)
|
||||
const cmd = "redis-server --save 900 1 --save 300 10 --daemonize yes" + await aarch64()
|
||||
logger.error(`请先启动 Redis:${cmd}`)
|
||||
process.exit()
|
||||
})
|
||||
|
||||
/** 全局变量 redis */
|
||||
global.redis = client as any
|
||||
|
||||
logger.info("Redis 连接成功")
|
||||
return client
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async function aarch64() {
|
||||
if (process.platform == "win32") return ""
|
||||
return await execAsync("uname -m").then(async arch => {
|
||||
if (arch.stdout && arch.stdout.includes("aarch64")) {
|
||||
/** 判断redis版本 */
|
||||
let v = await execAsync("redis-server -v")
|
||||
if (v.stdout) {
|
||||
const data = v.stdout.match(/v=(\d)./)
|
||||
/** 忽略arm警告 */
|
||||
if (data && Number(data[1]) >= 6) {
|
||||
return " --ignore-warnings ARM64-COW-BUG"
|
||||
}
|
||||
}
|
||||
}
|
||||
return ''
|
||||
})
|
||||
}
|
|
@ -1,42 +1,7 @@
|
|||
import fs from 'node:fs'
|
||||
import { exec } from 'child_process'
|
||||
import { join } from 'path'
|
||||
|
||||
/**
|
||||
* 休眠函数
|
||||
* @param ms 毫秒
|
||||
*/
|
||||
export function sleep(ms: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param cmd
|
||||
* @returns
|
||||
*/
|
||||
export function execAsync(cmd: string): Promise<{
|
||||
stdout: string
|
||||
stderr: string
|
||||
}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(cmd, (error, stdout, stderr) => {
|
||||
if (error) reject(error)
|
||||
resolve({ stdout, stderr })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dir
|
||||
* @returns
|
||||
*/
|
||||
export function readJSON(dir: string) {
|
||||
try {
|
||||
const cfg = fs.readFileSync(join(process.cwd(), dir), 'utf-8')
|
||||
return JSON.parse(cfg)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
103
src/init.ts
103
src/init.ts
|
@ -1,104 +1,5 @@
|
|||
import './init/modules.js'
|
||||
import './init/config.js'
|
||||
import './init/logger.js'
|
||||
import './init/redis.js'
|
||||
import { promises } from 'node:fs'
|
||||
import yaml from 'yaml'
|
||||
import { BOT_NAME } from './config'
|
||||
import { CONFIG_INIT_PATH } from './config/system.js'
|
||||
import { checkRun } from './config/check.js'
|
||||
/**
|
||||
*
|
||||
*/
|
||||
logger.mark(`${BOT_NAME} 启动中...`)
|
||||
/**
|
||||
* 设置标题
|
||||
*/
|
||||
process.title = BOT_NAME
|
||||
/**
|
||||
* 设置时区
|
||||
*/
|
||||
process.env.TZ = 'Asia/Shanghai'
|
||||
/**
|
||||
*
|
||||
*/
|
||||
process.on('SIGHUP', () => process.exit())
|
||||
/**
|
||||
* 捕获未处理的错误
|
||||
*/
|
||||
process.on('uncaughtException', error => {
|
||||
if (typeof logger == 'undefined') console.log(error)
|
||||
else logger.error(error)
|
||||
})
|
||||
/**
|
||||
* 捕获未处理的Promise错误
|
||||
*/
|
||||
process.on('unhandledRejection', error => {
|
||||
if (typeof logger == 'undefined') console.log(error)
|
||||
else logger.error(error)
|
||||
})
|
||||
/**
|
||||
* 退出事件
|
||||
*/
|
||||
process.on('exit', async () => {
|
||||
if (typeof redis != 'undefined') {
|
||||
await redis.save()
|
||||
}
|
||||
if (typeof logger == 'undefined') {
|
||||
console.log(`${BOT_NAME} 已停止运行`)
|
||||
} else {
|
||||
logger.mark(logger.magenta(`${BOT_NAME} 已停止运行`))
|
||||
}
|
||||
})
|
||||
/**
|
||||
* 添加一些多余的标题内容
|
||||
*/
|
||||
let title = BOT_NAME
|
||||
//
|
||||
const qq = await promises
|
||||
.readFile(`./${CONFIG_INIT_PATH}qq.yaml`, 'utf-8')
|
||||
.then(yaml.parse)
|
||||
.catch(() => null)
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if (qq) {
|
||||
title += `@${qq.qq || ''}`
|
||||
switch (qq.platform) {
|
||||
case 1: {
|
||||
title += ' 安卓手机'
|
||||
break
|
||||
}
|
||||
case 2: {
|
||||
title += ' aPad'
|
||||
break
|
||||
}
|
||||
case 3: {
|
||||
title += ' 安卓手表'
|
||||
break
|
||||
}
|
||||
case 4: {
|
||||
title += ' MacOS'
|
||||
break
|
||||
}
|
||||
case 5: {
|
||||
title += ' iPad'
|
||||
break
|
||||
}
|
||||
case 6: {
|
||||
title += ' Tim'
|
||||
break
|
||||
}
|
||||
default: {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 设置标题
|
||||
*/
|
||||
process.title = title
|
||||
/**
|
||||
* 检查程序
|
||||
*/
|
||||
await checkRun()
|
||||
import './init/process.js'
|
||||
import './init/run.js'
|
||||
|
|
|
@ -1,2 +1,101 @@
|
|||
import { loggerInit } from '../config/log'
|
||||
loggerInit()
|
||||
import log4js from 'log4js'
|
||||
import chalk from 'chalk'
|
||||
import cfg from '../config/config.js'
|
||||
import { mkdirSync } from 'node:fs'
|
||||
|
||||
/**
|
||||
* 创建日志
|
||||
* @returns
|
||||
*/
|
||||
function createLog() {
|
||||
// log4js.levels.levels[5].level = Number.MAX_VALUE
|
||||
// log4js.levels.levels.sort((a, b) => a.level - b.level)
|
||||
log4js.configure({
|
||||
appenders: {
|
||||
console: {
|
||||
type: 'console',
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '%[[MYZ-V4][%d{hh:mm:ss.SSS}][%4.4p]%] %m'
|
||||
}
|
||||
},
|
||||
command: {
|
||||
type: 'dateFile', // 可以是console,dateFile,file,Logstash等
|
||||
filename: 'logs/command', // 将会按照filename和pattern拼接文件名
|
||||
pattern: 'yyyy-MM-dd.log',
|
||||
numBackups: 15,
|
||||
alwaysIncludePattern: true,
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m'
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: 'file',
|
||||
filename: 'logs/error.log',
|
||||
alwaysIncludePattern: true,
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m'
|
||||
}
|
||||
}
|
||||
},
|
||||
categories: {
|
||||
default: { appenders: ['console'], level: cfg.bot.log_level },
|
||||
command: { appenders: ['console', 'command'], level: 'warn' },
|
||||
error: { appenders: ['console', 'command', 'error'], level: 'error' }
|
||||
}
|
||||
})
|
||||
|
||||
const defaultLogger = log4js.getLogger('message')
|
||||
const commandLogger = log4js.getLogger('command')
|
||||
const errorLogger = log4js.getLogger('error')
|
||||
|
||||
/**
|
||||
* 调整error日志等级
|
||||
*/
|
||||
const logger = {
|
||||
trace() {
|
||||
defaultLogger.trace.call(defaultLogger, ...arguments)
|
||||
},
|
||||
debug() {
|
||||
defaultLogger.debug.call(defaultLogger, ...arguments)
|
||||
},
|
||||
info() {
|
||||
defaultLogger.info.call(defaultLogger, ...arguments)
|
||||
},
|
||||
// warn及以上的日志采用error策略
|
||||
warn() {
|
||||
commandLogger.warn.call(defaultLogger, ...arguments)
|
||||
},
|
||||
error() {
|
||||
errorLogger.error.call(errorLogger, ...arguments)
|
||||
},
|
||||
fatal() {
|
||||
errorLogger.fatal.call(errorLogger, ...arguments)
|
||||
},
|
||||
mark() {
|
||||
errorLogger.mark.call(commandLogger, ...arguments)
|
||||
}
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
mkdirSync('./logs', {
|
||||
recursive: true
|
||||
})
|
||||
|
||||
/**
|
||||
* 全局变量 logger
|
||||
*/
|
||||
global.logger = createLog() as any
|
||||
logger.chalk = chalk
|
||||
logger.red = chalk.red
|
||||
logger.green = chalk.green
|
||||
logger.yellow = chalk.yellow
|
||||
logger.blue = chalk.blue
|
||||
logger.magenta = chalk.magenta
|
||||
logger.cyan = chalk.cyan
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import { existsSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
const node_modules = join(process.cwd(), './node_modules')
|
||||
/**
|
||||
* 检查node_modules
|
||||
*/
|
||||
if (!existsSync(node_modules)) {
|
||||
console.log('未安装依赖。。。。')
|
||||
console.log('请先运行命令:pnpm install -P 安装依赖')
|
||||
process.exit()
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
import { promises } from 'node:fs'
|
||||
import yaml from 'yaml'
|
||||
import { BOT_NAME, CONFIG_INIT_PATH } from '../config/system.js'
|
||||
/**
|
||||
*
|
||||
*/
|
||||
logger.mark(`${BOT_NAME} 启动中...`)
|
||||
/**
|
||||
* 设置标题
|
||||
*/
|
||||
process.title = BOT_NAME
|
||||
/**
|
||||
* 设置时区
|
||||
*/
|
||||
process.env.TZ = 'Asia/Shanghai'
|
||||
/**
|
||||
*
|
||||
*/
|
||||
process.on('SIGHUP', () => process.exit())
|
||||
/**
|
||||
* 捕获未处理的错误
|
||||
*/
|
||||
process.on('uncaughtException', error => {
|
||||
if (typeof logger == 'undefined') console.log(error)
|
||||
else logger.error(error)
|
||||
})
|
||||
/**
|
||||
* 捕获未处理的Promise错误
|
||||
*/
|
||||
process.on('unhandledRejection', error => {
|
||||
if (typeof logger == 'undefined') console.log(error)
|
||||
else logger.error(error)
|
||||
})
|
||||
/**
|
||||
* 退出事件
|
||||
*/
|
||||
process.on('exit', async () => {
|
||||
if (typeof redis != 'undefined') {
|
||||
await redis.save()
|
||||
}
|
||||
if (typeof logger == 'undefined') {
|
||||
console.log(`${BOT_NAME} 已停止运行`)
|
||||
} else {
|
||||
logger.mark(logger.magenta(`${BOT_NAME} 已停止运行`))
|
||||
}
|
||||
})
|
||||
/**
|
||||
* 添加一些多余的标题内容
|
||||
*/
|
||||
let title = BOT_NAME
|
||||
//
|
||||
const qq = await promises
|
||||
.readFile(`./${CONFIG_INIT_PATH}qq.yaml`, 'utf-8')
|
||||
.then(yaml.parse)
|
||||
.catch(() => null)
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if (qq) {
|
||||
title += `@${qq.qq || ''}`
|
||||
switch (qq.platform) {
|
||||
case 1: {
|
||||
title += ' 安卓手机'
|
||||
break
|
||||
}
|
||||
case 2: {
|
||||
title += ' aPad'
|
||||
break
|
||||
}
|
||||
case 3: {
|
||||
title += ' 安卓手表'
|
||||
break
|
||||
}
|
||||
case 4: {
|
||||
title += ' MacOS'
|
||||
break
|
||||
}
|
||||
case 5: {
|
||||
title += ' iPad'
|
||||
break
|
||||
}
|
||||
case 6: {
|
||||
title += ' Tim'
|
||||
break
|
||||
}
|
||||
default: {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 设置标题
|
||||
*/
|
||||
process.title = title
|
|
@ -1,2 +1,71 @@
|
|||
import { redisInit } from '../config/redis'
|
||||
import cfg from '../config/config.js'
|
||||
import { execAsync, sleep } from '../utils/common.js'
|
||||
import { createClient } from 'redis'
|
||||
/**
|
||||
* 初始化全局redis客户端
|
||||
* @returns
|
||||
*/
|
||||
async function redisInit() {
|
||||
const rc = cfg.redis
|
||||
const redisUn = rc.username || ''
|
||||
let redisPw = rc.password ? `:${rc.password}` : ''
|
||||
if (rc.username || rc.password) {
|
||||
redisPw += '@'
|
||||
}
|
||||
const redisUrl = `redis://${redisUn}${redisPw}${rc.host}:${rc.port}/${rc.db}`
|
||||
let client = createClient({ url: redisUrl })
|
||||
try {
|
||||
logger.info(`正在连接 ${logger.blue(redisUrl)}`)
|
||||
await client.connect()
|
||||
} catch (err) {
|
||||
logger.error(`Redis 错误:${logger.red(err)}`)
|
||||
const cmd =
|
||||
'redis-server --save 900 1 --save 300 10 --daemonize yes' +
|
||||
(await aarch64())
|
||||
logger.info('正在启动 Redis...')
|
||||
await execAsync(cmd)
|
||||
await sleep(1000)
|
||||
try {
|
||||
client = createClient({ url: redisUrl })
|
||||
await client.connect()
|
||||
} catch (err) {
|
||||
logger.error(`Redis 错误:${logger.red(err)}`)
|
||||
logger.error(`请先启动 Redis:${logger.blue(cmd)}`)
|
||||
process.exit()
|
||||
}
|
||||
}
|
||||
client.on('error', async err => {
|
||||
logger.error(`Redis 错误:${logger.red(err)}`)
|
||||
const cmd =
|
||||
'redis-server --save 900 1 --save 300 10 --daemonize yes' +
|
||||
(await aarch64())
|
||||
logger.error(`请先启动 Redis:${cmd}`)
|
||||
process.exit()
|
||||
})
|
||||
/** 全局变量 redis */
|
||||
global.redis = client as any
|
||||
logger.info('Redis 连接成功')
|
||||
return client
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async function aarch64() {
|
||||
if (process.platform == 'win32') return ''
|
||||
return await execAsync('uname -m').then(async arch => {
|
||||
if (arch.stdout && arch.stdout.includes('aarch64')) {
|
||||
/** 判断redis版本 */
|
||||
let v = await execAsync('redis-server -v')
|
||||
if (v.stdout) {
|
||||
const data = v.stdout.match(/v=(\d)./)
|
||||
/** 忽略arm警告 */
|
||||
if (data && Number(data[1]) >= 6) {
|
||||
return ' --ignore-warnings ARM64-COW-BUG'
|
||||
}
|
||||
}
|
||||
}
|
||||
return ''
|
||||
})
|
||||
}
|
||||
await redisInit()
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { join } from 'path'
|
||||
import { createRequire } from 'module'
|
||||
import { existsSync } from 'fs'
|
||||
import pm2 from 'pm2'
|
||||
const require = createRequire(import.meta.url)
|
||||
/**
|
||||
* 校验运行
|
||||
* @returns
|
||||
*/
|
||||
export function checkRun() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (process.argv[1].includes('pm2')) {
|
||||
resolve(true)
|
||||
}
|
||||
if (process.argv[1].includes('test')) {
|
||||
resolve(true)
|
||||
}
|
||||
// 不是生产运行
|
||||
if (process.env.NODE_ENV != 'production') {
|
||||
const dir = join(process.cwd(), 'pm2.config.cjs')
|
||||
if (!existsSync(dir)) {
|
||||
reject(false)
|
||||
}
|
||||
const cfg = require('../../pm2.config.cjs')
|
||||
pm2.connect(err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
//
|
||||
pm2.list((err, processList) => {
|
||||
if (err) {
|
||||
pm2.disconnect()
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
const app = processList.find(p => p.name === cfg.apps[0].name)
|
||||
if (app && app.pm2_env.status === 'online') {
|
||||
console.log('检测到后台正在运行')
|
||||
// 关闭
|
||||
pm2.stop(cfg.apps[0].name, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
console.log('已停止后台进程,防止重复运行')
|
||||
}
|
||||
pm2.disconnect()
|
||||
resolve(true)
|
||||
})
|
||||
} else {
|
||||
// 断开连接
|
||||
pm2.disconnect()
|
||||
resolve(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
resolve(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
await checkRun().catch(err => {
|
||||
// 打印错误
|
||||
console.error(err)
|
||||
// 关闭进程
|
||||
process.exit(2)
|
||||
})
|
109
trss.js
109
trss.js
|
@ -1,109 +0,0 @@
|
|||
console.log("正迁移到 TRSS-Yunzai")
|
||||
|
||||
import fs from "node:fs"
|
||||
import { execSync } from "child_process"
|
||||
import YAML from "yaml"
|
||||
|
||||
function exec(cmd) { try {
|
||||
console.log(`执行命令 [${cmd}]`)
|
||||
console.log(execSync(cmd).toString())
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error("执行", cmd, "失败", err)
|
||||
return false
|
||||
}}
|
||||
|
||||
function rm(file) { try {
|
||||
if (!fs.existsSync(file)) return true
|
||||
return process.platform == "win32" ?
|
||||
exec(`rd /s /q "${file.replace(/\//g, "\\")}"`) :
|
||||
exec(`rm -rf "${file}"`)
|
||||
} catch (err) {
|
||||
console.error("删除", file, "错误", err)
|
||||
return false
|
||||
}}
|
||||
|
||||
function mv(file, target) { try {
|
||||
if (!fs.existsSync(file)) return false
|
||||
if (fs.existsSync(target)) rm(target)
|
||||
return fs.renameSync(file, target)
|
||||
} catch (err) {
|
||||
console.error("移动", file, target, "错误", err)
|
||||
return false
|
||||
}}
|
||||
|
||||
function readYaml(file) { try {
|
||||
if (!fs.existsSync(file)) return {}
|
||||
return YAML.parse(fs.readFileSync(file, "utf-8"))
|
||||
} catch (err) {
|
||||
console.error("读取", file, "错误", err)
|
||||
return {}
|
||||
}}
|
||||
|
||||
function writeYaml(file, data) { try {
|
||||
return fs.writeFileSync(file, YAML.stringify(data), "utf-8")
|
||||
} catch (err) {
|
||||
console.error("写入", file, "错误", err)
|
||||
return false
|
||||
}}
|
||||
|
||||
const bot = readYaml("config/config/bot.yaml")
|
||||
const qq = readYaml("config/config/qq.yaml")
|
||||
|
||||
exec("git remote add trss https://gitee.com/TimeRainStarSky/Yunzai")
|
||||
exec("git fetch trss main")
|
||||
exec("git clean -df")
|
||||
mv("config/config", "config/config_miao")
|
||||
exec("git reset --hard")
|
||||
exec("git checkout --track trss/main")
|
||||
rm("plugins/ICQQ-Plugin")
|
||||
exec("git clone --depth 1 --single-branch https://gitee.com/TimeRainStarSky/Yunzai-ICQQ-Plugin plugins/ICQQ-Plugin")
|
||||
if (qq.qq) writeYaml("config/ICQQ.yaml", { bot, token: [`${qq.qq}:${qq.pwd}:${qq.platform}`] })
|
||||
rm("plugins/genshin")
|
||||
exec("git clone --depth 1 --single-branch https://gitee.com/TimeRainStarSky/Yunzai-genshin plugins/genshin")
|
||||
exec("pnpm install --force")
|
||||
|
||||
console.log("迁移完成,请查看教程 启动协议端\nhttps://gitee.com/TimeRainStarSky/Yunzai\n输入 node miao 回 Miao-Yunzai")
|
||||
fs.writeFileSync("miao.js", `console.log("正迁移到 Miao-Yunzai")
|
||||
|
||||
import fs from "node:fs"
|
||||
import { execSync } from "child_process"
|
||||
|
||||
function exec(cmd) { try {
|
||||
console.log(\`执行命令 [\${cmd}]\`)
|
||||
console.log(execSync(cmd).toString())
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error("执行", cmd, "失败", err)
|
||||
return false
|
||||
}}
|
||||
|
||||
function rm(file) { try {
|
||||
if (!fs.existsSync(file)) return true
|
||||
return process.platform == "win32" ?
|
||||
exec(\`rd /s /q "\${file.replace(/\\//g, "\\\\")}"\`) :
|
||||
exec(\`rm -rf "\${file}"\`)
|
||||
} catch (err) {
|
||||
console.error("删除", file, "错误", err)
|
||||
return false
|
||||
}}
|
||||
|
||||
function mv(file, target) { try {
|
||||
if (!fs.existsSync(file)) return false
|
||||
if (fs.existsSync(target)) rm(target)
|
||||
return fs.renameSync(file, target)
|
||||
} catch (err) {
|
||||
console.error("移动", file, target, "错误", err)
|
||||
return false
|
||||
}}
|
||||
|
||||
mv("config/config_miao", "config/config")
|
||||
exec("git reset --hard")
|
||||
exec("git clean -df")
|
||||
rm("plugins/ICQQ-Plugin")
|
||||
rm("plugins/genshin")
|
||||
exec("git checkout master")
|
||||
exec("git branch -D main")
|
||||
exec("pnpm install --force")
|
||||
|
||||
console.log("迁移完成")`, "utf-8")
|
Loading…
Reference in New Issue