212 lines
7.1 KiB
JavaScript
212 lines
7.1 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const process = require('child_process');
|
|
const projectsFile = path.join(__dirname, 'project')
|
|
|
|
const getDatetime = (fmt = "YYYY-mm-dd HH:MM", date) => {
|
|
date = date || new Date();
|
|
|
|
let ret;
|
|
const opt = {
|
|
"Y+": date.getFullYear().toString(), // 年
|
|
"m+": (date.getMonth() + 1).toString(), // 月
|
|
"d+": date.getDate().toString(), // 日
|
|
"H+": date.getHours().toString(), // 时
|
|
"M+": date.getMinutes().toString(), // 分
|
|
"S+": date.getSeconds().toString() // 秒
|
|
// 有其他格式化字符需求可以继续添加,必须转化成字符串
|
|
};
|
|
for (let k in opt) {
|
|
ret = new RegExp("(" + k + ")").exec(fmt);
|
|
if (ret) {
|
|
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
|
|
}
|
|
}
|
|
;
|
|
return fmt;
|
|
}
|
|
router.get('/', function (req, res, next) {
|
|
const data = fs.readFileSync(projectsFile + '/index.json');
|
|
res.json(JSON.parse(data.toString()))
|
|
});
|
|
router.get('/history', (req, res, next) => {
|
|
let {id, time} = req.query;
|
|
|
|
const fileName = projectsFile + '/' + id + '/' + time + '.log';
|
|
if (!fs.existsSync(fileName)) {
|
|
res.json({code: 1, message: "日志不存在", fileName});
|
|
return;
|
|
}
|
|
res.sendFile(fileName, {}, function (err) {
|
|
if (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
});
|
|
|
|
// 读取编译记录
|
|
router.get('/:id', function (req, res, next) {
|
|
const id = req.params.id;
|
|
const file = projectsFile + '/' + id + '/index.json';
|
|
|
|
if (!fs.existsSync(file)) {
|
|
res.json({code: 1, message: "项目不存在"});
|
|
return;
|
|
}
|
|
const data = fs.readFileSync(file);
|
|
res.json(JSON.parse(data.toString()))
|
|
});
|
|
router.get('/shell/:id', (req, res) => {
|
|
const path = projectsFile + '/' + req.params.id + '/build.sh';
|
|
if (!fs.existsSync(path)) {
|
|
res.send({code: 1, message: '脚本文件不存在'})
|
|
return;
|
|
}
|
|
const shell = fs.readFileSync(path,{encoding:'utf-8'})
|
|
res.send({code: 0, shell})
|
|
});
|
|
router.post('/shell/:id', (req, res) => {
|
|
const path = projectsFile + '/' + req.params.id + '/build.sh';
|
|
if (!fs.existsSync(path)) {
|
|
res.send({code: 1, message: '脚本文件文件不存在'})
|
|
return;
|
|
}
|
|
const shell = req.body.shell;
|
|
fs.writeFileSync(path, shell,{encoding:"utf-8"})
|
|
res.send({code: 0})
|
|
});
|
|
|
|
const writeExecLog = (id, status, running = false) => {
|
|
const data = JSON.parse(fs.readFileSync(projectsFile + '/index.json'));
|
|
data[id - 1].lastUpdate = getDatetime('YYYY-mm-dd HH:MM:SS');
|
|
data[id - 1].lastStatus = status;
|
|
data[id - 1].running = running;
|
|
|
|
fs.writeFile(projectsFile + '/index.json', JSON.stringify(data), (err1) => {
|
|
if (err1) {
|
|
console.log('writeExecLog:write project file fail')
|
|
}
|
|
})
|
|
}
|
|
|
|
// 执行
|
|
router.all('/hook/:id', function (req, res, next) {
|
|
const id = parseInt(req.params.id);
|
|
const projects = JSON.parse(fs.readFileSync(projectsFile + '/index.json',{encoding:'utf-8'}));
|
|
if (id < 1 || id > projects.length) {
|
|
res.json({code: 1, message: "项目不存在(1)"});
|
|
return;
|
|
}
|
|
if (projects[id - 1].running) {
|
|
res.json({code: 3, message: "当前项目脚本正在运行中"});
|
|
return;
|
|
}
|
|
|
|
const file = projectsFile + '/' + id + '/build.sh';
|
|
if (!fs.existsSync(file)) {
|
|
res.json({code: 1, message: "项目不存在(2)"});
|
|
return;
|
|
}
|
|
res.json({code: 0, message: "开始执行脚本,请稍后查看运行结果"});
|
|
|
|
// 历史记录
|
|
fs.readFile(projectsFile + '/' + id + '/index.json', (err, data) => {
|
|
if (err) {
|
|
console.log('read project {', id, '} history failed', err)
|
|
return;
|
|
}
|
|
const histories = JSON.parse(data.toString());
|
|
const currentTime = getDatetime('YYYY-mm-dd HH:MM:SS'),timeNow = Date.now();
|
|
// 开始执行脚本
|
|
fs.open(projectsFile + '/' + id + '/' + timeNow + '.log', 'a', function (err, fd) {
|
|
if (err) { // 操作日志失败了
|
|
writeExecLog(id, 'fail');
|
|
return;
|
|
}
|
|
writeExecLog(id, null, true); // 运行中
|
|
let isFailed = -1;
|
|
const workerProcess = process.spawn('sh', [file]);
|
|
let startTime = Date.now(); // 记录开始时间
|
|
workerProcess.stdout.on('data', (execData) => {
|
|
let line = execData.toString().trim();
|
|
console.log('out:', line);
|
|
if (line == 'execute success') {
|
|
isFailed = 1;
|
|
} else if (line == 'execute fail') {
|
|
isFailed = 0;
|
|
}
|
|
fs.writeSync(fd, line); // 写入日志
|
|
});
|
|
workerProcess.stderr.on('data', (execData) => {
|
|
console.log('err:', execData.toString())
|
|
fs.writeSync(fd, execData.toString()); // 写入日志
|
|
// isFailed = true;
|
|
});
|
|
workerProcess.on('close', function (code) {
|
|
// 计算使用时间
|
|
const useTime = Date.now() - startTime;
|
|
let status = isFailed == -1 ? '未知' : (isFailed == 1 ? '成功' : '失败');
|
|
histories.push({
|
|
time: currentTime,
|
|
timestamp:timeNow,
|
|
status,
|
|
useTime
|
|
})
|
|
// 写入记录
|
|
fs.writeFileSync(projectsFile + '/' + id + '/index.json', JSON.stringify(histories));
|
|
writeExecLog(id, status)
|
|
fs.close(fd, function (err) {
|
|
if (err) {
|
|
console.log('close file error', err);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
|
|
});
|
|
//创建项目
|
|
router.post('/create', (req, res, next) => {
|
|
const data = JSON.parse(fs.readFileSync(projectsFile + '/index.json'));
|
|
let id = data.length + 1;
|
|
|
|
let {name, shell} = req.body;
|
|
if (!name || !shell) {
|
|
res.json({code: 1, message: "参数不能为空"})
|
|
return;
|
|
}
|
|
fs.mkdirSync(projectsFile + '/' + id); // 创建项目目录
|
|
// 创建记录文件
|
|
fs.writeFile(projectsFile + '/' + id + '/index.json', '[]', function (err) {
|
|
fs.writeFile(projectsFile + '/' + id + '/build.sh', shell, (err1) => {
|
|
if (err1) {
|
|
console.log('create shell success')
|
|
}
|
|
});
|
|
if (err) {
|
|
res.json({code: 2, message: "创建项目失败"})
|
|
}
|
|
data.push({
|
|
id,
|
|
name,
|
|
create: getDatetime(),
|
|
lastUpdate: null,
|
|
lastStatus: "",
|
|
running: false
|
|
})
|
|
fs.writeFile(projectsFile + '/index.json', JSON.stringify(data), (err1) => {
|
|
if (err1) {
|
|
console.log('create project fail')
|
|
}
|
|
})
|
|
res.json(data);
|
|
});
|
|
});
|
|
|
|
|
|
module.exports = router;
|