!165 新增 重启后保持前台运行的方法

Merge pull request !165 from 千奈千祁/master
This commit is contained in:
Kokomi 2024-04-15 17:45:05 +00:00 committed by Gitee
commit 94700862dd
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 134 additions and 23 deletions

View File

@ -7,6 +7,8 @@ ignore_self: true
resend: false
# 发送消息错误时是否通知主人
sendmsg_error: false
# 重启API端口 仅ksr.js生效
restart_port: 27881
# ffmpeg
ffmpeg_path:
ffprobe_path:

59
lib/tools/ksr.js Normal file
View File

@ -0,0 +1,59 @@
import { spawn } from 'child_process';
import log4js from 'log4js';
import http from 'http'
import YAML from 'yaml'
import fs from 'fs'
/* keep ssh run */
log4js.configure({
appenders: { console: { type: 'console' } },
categories: { default: { appenders: ['console'], level: 'debug' } }
});
const logger = log4js.getLogger('app');
let serverProcess;
const startServer = async () => {
logger.info('Starting Bot...');
serverProcess = spawn('node', ['app.js'], { stdio: 'inherit' });
serverProcess.on('close', (code) => {
logger.info(`Bot process exited with code ${code}`);
if (code == null) return
process.exit()
});
};
startServer();
const serverHttpexit = http.createServer(async (req, res) => {
let remoteIP = req.socket.remoteAddress;
if (remoteIP.startsWith('::ffff:')) {
remoteIP = remoteIP.slice(7);
}
if (remoteIP !== `::1` && remoteIP !== `127.0.0.1`) {
console.log(remoteIP)
res.writeHead(403, { 'Content-Type': 'text/plain' });
res.end('Access Forbidden\n');
return
}
if (req.url === `/restart`) {
await serverProcess.kill();
await startServer();
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('OK\n');
} else if (req.url === `/exit`) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('OK\n');
process.exit()
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found\n');
}
})
let restart_port
try {
restart_port = YAML.parse(fs.readFileSync(`./config/config/bot.yaml`, `utf-8`))
restart_port = restart_port.restart_port || 27881
} catch {}
logger.info(`restart_api run on port ${restart_port || 27881}`)
serverHttpexit.listen(restart_port || 27881, () => { });

View File

@ -14,7 +14,8 @@
"start": "pm2 start ./config/pm2/pm2.json",
"stop": "pm2 stop ./config/pm2/pm2.json",
"restart": "pm2 restart ./config/pm2/pm2.json",
"log": "node ./lib/tools/log.js"
"log": "node ./lib/tools/log.js",
"ksr": "node ./lib/tools/ksr.js"
},
"dependencies": {
"art-template": "^4.13.2",

View File

@ -1,9 +1,22 @@
import plugin from '../../lib/plugins/plugin.js'
import { createRequire } from 'module'
import fetch from 'node-fetch'
import net from 'net'
import fs from 'fs'
import YAML from 'yaml'
const require = createRequire(import.meta.url)
const { exec } = require('child_process')
const isPortTaken = async (port) => {
return new Promise((resolve) => {
const tester = net.createServer()
.once('error', () => resolve(true))
.once('listening', () => tester.once('close', () => resolve(false)).close())
.listen(port);
});
};
export class Restart extends plugin {
constructor (e = '') {
super({
@ -51,6 +64,11 @@ export class Restart extends plugin {
}
async restart () {
let restart_port
try {
restart_port = YAML.parse(fs.readFileSync(`./config/config/bot.yaml`, `utf-8`))
restart_port = restart_port.restart_port || 27881
} catch { }
await this.e.reply('开始执行重启,请稍等...')
logger.mark(`${this.e.logFnc} 开始执行重启,请稍等...`)
@ -62,30 +80,44 @@ export class Restart extends plugin {
})
let npm = await this.checkPnpm()
try {
await redis.set(this.key, data, { EX: 120 })
let cm = `${npm} start`
if (process.argv[1].includes('pm2')) {
cm = `${npm} run restart`
}
exec(cm, { windowsHide: true }, (error, stdout, stderr) => {
if (error) {
await redis.set(this.key, data, { EX: 120 })
if(await isPortTaken(restart_port || 27881)) {
try {
let result = await fetch(`http://localhost:${restart_port || 27881}/restart`)
result = await result.text()
if(result !== `OK`) {
redis.del(this.key)
this.e.reply(`操作失败!\n${error.stack}`)
logger.error(`重启失败\n${error.stack}`)
} else if (stdout) {
logger.mark('重启成功,运行已由前台转为后台')
logger.mark(`查看日志请用命令:${npm} run log`)
logger.mark(`停止后台运行命令:${npm} stop`)
process.exit()
this.e.reply(`操作失败!`)
logger.error(`重启失败`)
}
})
} catch (error) {
redis.del(this.key)
let e = error.stack ?? error
this.e.reply(`操作失败!\n${e}`)
} catch(error) {
redis.del(this.key)
this.e.reply(`操作失败!\n${error}`)
}
} else {
try {
let cm = `${npm} start`
if (process.argv[1].includes('pm2')) {
cm = `${npm} run restart`
}
exec(cm, { windowsHide: true }, (error, stdout, stderr) => {
if (error) {
redis.del(this.key)
this.e.reply(`操作失败!\n${error.stack}`)
logger.error(`重启失败\n${error.stack}`)
} else if (stdout) {
logger.mark('重启成功,运行已由前台转为后台')
logger.mark(`查看日志请用命令:${npm} run log`)
logger.mark(`停止后台运行命令:${npm} stop`)
process.exit()
}
})
} catch (error) {
redis.del(this.key)
let e = error.stack ?? error
this.e.reply(`操作失败!\n${e}`)
}
}
return true
@ -107,6 +139,23 @@ export class Restart extends plugin {
}
async stop () {
let restart_port
try {
restart_port = YAML.parse(fs.readFileSync(`./config/config/bot.yaml`, `utf-8`))
restart_port = restart_port.restart_port || 27881
} catch { }
if(await isPortTaken(restart_port || 27881)) {
try {
logger.mark('关机成功,已停止运行')
await this.e.reply(`关机成功,已停止运行`)
await fetch(`http://localhost:${restart_port || 27881}/exit`)
return
} catch(error) {
this.e.reply(`操作失败!\n${error}`)
logger.error(`关机失败\n${error}`)
}
}
if (!process.argv[1].includes('pm2')) {
logger.mark('关机成功,已停止运行')
await this.e.reply('关机成功,已停止运行')