Compare commits

..
28 Commits
Author SHA1 Message Date
whyour fa6d57d809 修复shell发送通知 2022-04-09 11:13:08 +08:00
whyour 1060fc7476 修复并发日志目录 2022-04-06 12:18:16 +08:00
whyour 56bc38e9e7 更新readme 2022-04-05 23:24:27 +08:00
whyour 18be65d6fe 更新发布脚本 2022-04-05 23:17:03 +08:00
whyour 3409085195 更新发布脚本 2022-04-05 23:14:47 +08:00
whyour 17e17ac077 增加发布脚本 2022-04-05 23:11:48 +08:00
whyour c655e1da38 修复日志目录判断 2022-04-05 00:28:14 +08:00
whyour 0ea158724f 修复日志目录获取 2022-04-05 00:21:32 +08:00
whyour fb521498ff 修复task日志打印 2022-04-04 23:32:27 +08:00
whyour 399550ccad 修复日志创建目录 2022-04-04 22:40:02 +08:00
whyour c7c30c86f2 修复目录获取 2022-04-04 18:06:21 +08:00
whyour 5f6c0882d6 修改版本说明 2022-04-04 17:28:15 +08:00
whyour 6e05a4f3a5 更新版本号 v2.12.1 2022-04-04 17:24:42 +08:00
whyour ea8aa6a231 修改获取版本链接 2022-04-04 17:17:34 +08:00
whyour ae2570c677 修复shell日志路径截取 2022-04-03 22:31:11 +08:00
whyour c76d952d41 修改yarn命令 2022-04-03 21:49:20 +08:00
whyour cdf9fb24be 修复定时任务获取日志 2022-04-03 20:00:31 +08:00
whyour 2131e16781 删除console 2022-04-03 19:50:44 +08:00
whyour b0c8425639 修复日志路径拼接规则 2022-04-03 19:32:44 +08:00
whyour f0869567de 七牛云改为http访问 2022-04-01 08:29:16 +08:00
whyour be2a19949b 修复获取日志相对目录 2022-03-30 11:34:36 +08:00
whyour 8627cccb58 修改日志路径合并方式 2022-03-30 11:17:11 +08:00
whyour 4a8eaebf17 修复获取任务日志路径 2022-03-30 10:57:43 +08:00
kan3GitandGitHub e7edd0a5a4 tg发送消息改json (#1269)
发现有带&的消息都会漏掉&后面的内容,改为JSON发送
2022-03-26 17:23:54 +08:00
chen310andGitHub 9ccbea0a04 修复PushDeer推送Python版本错误 (#1270)
* 修复PushDeer推送Python版本错误
2022-03-26 17:20:02 +08:00
whyour ab715ef840 修复系统pushDeer通知 2022-03-26 17:17:13 +08:00
whyour 117822fe7c 修改任务最大内存占用200兆 2022-03-26 16:53:03 +08:00
whyour da922678a1 修复定时任务获取日志目录 2022-03-26 00:29:42 +08:00
20 changed files with 254 additions and 140 deletions
+4 -3
View File
@@ -27,9 +27,10 @@ jobs:
- name: build front and back - name: build front and back
run: | run: |
yarn install npm i -g pnpm
yarn build:front pnpm install
yarn build:back pnpm build:front
pnpm build:back
- name: copy to static repo - name: copy to static repo
env: env:
+5 -3
View File
@@ -22,7 +22,7 @@
[docker-image-size-url]: https://hub.docker.com/r/whyour/qinglong [docker-image-size-url]: https://hub.docker.com/r/whyour/qinglong
</div> </div>
[![](https://z3.ax1x.com/2021/11/18/I7KrTg.jpg)](https://whyour.cn) [![](https://user-images.githubusercontent.com/22700758/161788855-c4e51cb8-d4e9-44fe-bb17-ee1a56c8549b.png)](https://whyour.cn)
简体中文 | [English](./README-en.md) 简体中文 | [English](./README-en.md)
@@ -168,8 +168,10 @@ task <file_path> desi <env_name> <account_number>
$ git clone git@github.com:whyour/qinglong.git $ git clone git@github.com:whyour/qinglong.git
$ cd qinglong $ cd qinglong
$ cp .env.example .env $ cp .env.example .env
$ yarn install # 推荐使用 pnpm https://pnpm.io/zh/installation
$ yarn start $ npm install -g pnpm
$ pnpm install
$ pnpm start
``` ```
打开你的浏览器,访问 http://127.0.0.1:5700 打开你的浏览器,访问 http://127.0.0.1:5700
+1 -1
View File
@@ -4,7 +4,7 @@ import { createRandomString } from './util';
process.env.NODE_ENV = process.env.NODE_ENV || 'development'; process.env.NODE_ENV = process.env.NODE_ENV || 'development';
const lastVersionFile = 'https://qn.whyour.cn/version.ts'; const lastVersionFile = 'http://qn.whyour.cn/version.ts?v=2.12.1';
const envFound = dotenv.config(); const envFound = dotenv.config();
const rootPath = process.cwd(); const rootPath = process.cwd();
+1 -1
View File
@@ -39,7 +39,7 @@ export class PushDeerNotification extends NotificationBaseInfo {
export class BarkNotification extends NotificationBaseInfo { export class BarkNotification extends NotificationBaseInfo {
public barkPush = ''; public barkPush = '';
public barkIcon = 'https://qn.whyour.cn/logo.png'; public barkIcon = 'http://qn.whyour.cn/logo.png';
public barkSound = ''; public barkSound = '';
public barkGroup = 'qinglong'; public barkGroup = 'qinglong';
} }
+51 -18
View File
@@ -9,6 +9,7 @@ import { getFileContentByName, concurrentRun, fileExist } from '../config/util';
import { promises, existsSync } from 'fs'; import { promises, existsSync } from 'fs';
import { promisify } from 'util'; import { promisify } from 'util';
import { Op } from 'sequelize'; import { Op } from 'sequelize';
import path from 'path';
@Service() @Service()
export default class CronService { export default class CronService {
@@ -16,7 +17,7 @@ export default class CronService {
private isSixCron(cron: Crontab) { private isSixCron(cron: Crontab) {
const { schedule } = cron; const { schedule } = cron;
if (schedule.split(/ +/).length === 6) { if (schedule?.split(/ +/).length === 6) {
return true; return true;
} }
return false; return false;
@@ -194,11 +195,12 @@ export default class CronService {
} }
} }
const err = await this.killTask(doc.command); const err = await this.killTask(doc.command);
const logFileExist = await fileExist(doc.log_path); const absolutePath = path.resolve(config.logPath, `${doc.log_path}`);
if (doc.log_path && logFileExist) { const logFileExist = doc.log_path && (await fileExist(absolutePath));
if (logFileExist) {
const str = err ? `\n${err}` : ''; const str = err ? `\n${err}` : '';
fs.appendFileSync( fs.appendFileSync(
`${doc.log_path}`, `${absolutePath}`,
`${str}\n## 执行结束... ${new Date() `${str}\n## 执行结束... ${new Date()
.toLocaleString('zh', { hour12: false }) .toLocaleString('zh', { hour12: false })
.replace(' 24:', ' 00:')} `, .replace(' 24:', ' 00:')} `,
@@ -256,6 +258,8 @@ export default class CronService {
} }
let { id, command, log_path } = cron; let { id, command, log_path } = cron;
const absolutePath = path.resolve(config.logPath, `${log_path}`);
const logFileExist = log_path && (await fileExist(absolutePath));
this.logger.silly('Running job'); this.logger.silly('Running job');
this.logger.silly('ID: ' + id); this.logger.silly('ID: ' + id);
@@ -276,13 +280,13 @@ export default class CronService {
{ where: { id } }, { where: { id } },
); );
cp.stderr.on('data', (data) => { cp.stderr.on('data', (data) => {
if (log_path) { if (logFileExist) {
fs.appendFileSync(`${log_path}`, `${data}`); fs.appendFileSync(`${absolutePath}`, `${data}`);
} }
}); });
cp.on('error', (err) => { cp.on('error', (err) => {
if (log_path) { if (logFileExist) {
fs.appendFileSync(`${log_path}`, `${JSON.stringify(err)}`); fs.appendFileSync(`${absolutePath}`, `${JSON.stringify(err)}`);
} }
}); });
@@ -323,8 +327,10 @@ export default class CronService {
return ''; return '';
} }
if (doc.log_path) { const absolutePath = path.resolve(config.logPath, `${doc.log_path}`);
return getFileContentByName(`${doc.log_path}`); const logFileExist = doc.log_path && (await fileExist(absolutePath));
if (logFileExist) {
return getFileContentByName(`${absolutePath}`);
} }
const [, commandStr, url] = doc.command.split(/ +/); const [, commandStr, url] = doc.command.split(/ +/);
let logPath = this.getKey(commandStr); let logPath = this.getKey(commandStr);
@@ -353,6 +359,21 @@ export default class CronService {
return []; return [];
} }
if (doc.log_path) {
const relativeDir = path.dirname(`${doc.log_path}`);
const dir = path.resolve(config.logPath, relativeDir);
if (existsSync(dir)) {
let files = await promises.readdir(dir);
return files
.map((x) => ({
filename: x,
directory: relativeDir.replace(config.logPath, ''),
time: fs.statSync(`${dir}/${x}`).mtime.getTime(),
}))
.sort((a, b) => b.time - a.time);
}
}
const [, commandStr, url] = doc.command.split(/ +/); const [, commandStr, url] = doc.command.split(/ +/);
let logPath = this.getKey(commandStr); let logPath = this.getKey(commandStr);
const isQlCommand = doc.command.startsWith('ql '); const isQlCommand = doc.command.startsWith('ql ');
@@ -380,15 +401,27 @@ export default class CronService {
} }
} }
private getKey(command: string) { private getKey(command: string): string {
const start = const start =
command.lastIndexOf('/') !== -1 ? command.lastIndexOf('/') + 1 : 0; command.lastIndexOf('/') !== -1 ? command.lastIndexOf('/') + 1 : 0;
const end = const end =
command.lastIndexOf('.') !== -1 command.lastIndexOf('.') !== -1
? command.lastIndexOf('.') ? command.lastIndexOf('.')
: command.length; : command.length;
const tmpStr = command.substring(0, start - 1);
let index = 0;
if (tmpStr.lastIndexOf('/') !== -1 && tmpStr.startsWith('http')) {
index = tmpStr.lastIndexOf('/');
} else if (tmpStr.lastIndexOf(':') !== -1 && tmpStr.startsWith('git@')) {
index = tmpStr.lastIndexOf(':');
}
if (index) {
return `${tmpStr.substring(index + 1)}_${command.substring(start, end)}`;
} else {
return command.substring(start, end); return command.substring(start, end);
} }
}
private make_command(tab: Crontab) { private make_command(tab: Crontab) {
const crontab_job_string = `ID=${tab.id} ${tab.command}`; const crontab_job_string = `ID=${tab.id} ${tab.command}`;
@@ -400,7 +433,7 @@ export default class CronService {
var crontab_string = ''; var crontab_string = '';
tabs.forEach((tab) => { tabs.forEach((tab) => {
const _schedule = tab.schedule && tab.schedule.split(/ +/); const _schedule = tab.schedule && tab.schedule.split(/ +/);
if (tab.isDisabled === 1 || _schedule.length !== 5) { if (tab.isDisabled === 1 || _schedule!.length !== 5) {
crontab_string += '# '; crontab_string += '# ';
crontab_string += tab.schedule; crontab_string += tab.schedule;
crontab_string += ' '; crontab_string += ' ';
@@ -426,22 +459,22 @@ export default class CronService {
public import_crontab() { public import_crontab() {
exec('crontab -l', (error, stdout, stderr) => { exec('crontab -l', (error, stdout, stderr) => {
var lines = stdout.split('\n'); const lines = stdout.split('\n');
var namePrefix = new Date().getTime(); const namePrefix = new Date().getTime();
lines.reverse().forEach(async (line, index) => { lines.reverse().forEach(async (line, index) => {
line = line.replace(/\t+/g, ' '); line = line.replace(/\t+/g, ' ');
var regex = const regex =
/^((\@[a-zA-Z]+\s+)|(([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+))/; /^((\@[a-zA-Z]+\s+)|(([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+))/;
var command = line.replace(regex, '').trim(); const command = line.replace(regex, '').trim();
var schedule = line.replace(command, '').trim(); const schedule = line.replace(command, '').trim();
if ( if (
command && command &&
schedule && schedule &&
cron_parser.parseExpression(schedule).hasNext() cron_parser.parseExpression(schedule).hasNext()
) { ) {
var name = namePrefix + '_' + index; const name = namePrefix + '_' + index;
const _crontab = await CrontabModel.findOne({ const _crontab = await CrontabModel.findOne({
where: { command, schedule }, where: { command, schedule },
+3 -4
View File
@@ -119,15 +119,14 @@ export default class NotificationService {
private async pushDeer() { private async pushDeer() {
const { pushDeerKey } = this.params; const { pushDeerKey } = this.params;
// https://api2.pushdeer.com/message/push?pushkey=<key>&text=标题&desp=<markdown>&type=markdown
const url = `https://api2.pushdeer.com/message/push`; const url = `https://api2.pushdeer.com/message/push`;
const res: any = await got const res: any = await got
.post(url, { .post(url, {
timeout: this.timeout, timeout: this.timeout,
retry: 0, retry: 0,
body: `pushkey=${pushDeerKey}&text=${ body: `pushkey=${pushDeerKey}&text=${encodeURIComponent(
this.title this.title,
}&desp=${encodeURIComponent(this.content)}&type=markdown`, )}&desp=${encodeURIComponent(this.content)}&type=markdown`,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}) })
.json(); .json();
+14 -4
View File
@@ -16,6 +16,8 @@ export default class ScheduleService {
private intervalSchedule = new ToadScheduler(); private intervalSchedule = new ToadScheduler();
private maxBuffer = 200 * 1024 * 1024;
constructor(@Inject('logger') private logger: winston.Logger) {} constructor(@Inject('logger') private logger: winston.Logger) {}
async createCronTask({ id = 0, command, name, schedule = '' }: Crontab) { async createCronTask({ id = 0, command, name, schedule = '' }: Crontab) {
@@ -32,7 +34,10 @@ export default class ScheduleService {
_id, _id,
nodeSchedule.scheduleJob(id + '', schedule, async () => { nodeSchedule.scheduleJob(id + '', schedule, async () => {
try { try {
exec(command, async (error, stdout, stderr) => { exec(
command,
{ maxBuffer: this.maxBuffer },
async (error, stdout, stderr) => {
if (error) { if (error) {
await this.logger.info( await this.logger.info(
'执行任务%s失败,时间:%s, 错误信息:%j', '执行任务%s失败,时间:%s, 错误信息:%j',
@@ -50,7 +55,8 @@ export default class ScheduleService {
stderr, stderr,
); );
} }
}); },
);
} catch (error) { } catch (error) {
await this.logger.info( await this.logger.info(
'执行任务%s失败,时间:%s, 错误信息:%j', '执行任务%s失败,时间:%s, 错误信息:%j',
@@ -83,7 +89,10 @@ export default class ScheduleService {
); );
const task = new Task(name, async () => { const task = new Task(name, async () => {
try { try {
exec(command, async (error, stdout, stderr) => { exec(
command,
{ maxBuffer: this.maxBuffer },
async (error, stdout, stderr) => {
if (error) { if (error) {
await this.logger.info( await this.logger.info(
'执行任务%s失败,时间:%s, 错误信息:%j', '执行任务%s失败,时间:%s, 错误信息:%j',
@@ -101,7 +110,8 @@ export default class ScheduleService {
stderr, stderr,
); );
} }
}); },
);
} catch (error) { } catch (error) {
await this.logger.info( await this.logger.info(
'执行任务%s失败,时间:%s, 错误信息:%j', '执行任务%s失败,时间:%s, 错误信息:%j',
+1 -1
View File
@@ -51,7 +51,7 @@ export PUSH_KEY=""
## 下方填写app提供的设备码,例如:https://api.day.app/123 那么此处的设备码就是123 ## 下方填写app提供的设备码,例如:https://api.day.app/123 那么此处的设备码就是123
export BARK_PUSH="" export BARK_PUSH=""
## 下方填写推送图标设置,自定义推送图标(需iOS15或以上) ## 下方填写推送图标设置,自定义推送图标(需iOS15或以上)
export BARK_ICON="https://qn.whyour.cn/logo.png" export BARK_ICON="http://qn.whyour.cn/logo.png"
## 下方填写推送声音设置,例如choo,具体值请在bark-推送铃声-查看所有铃声 ## 下方填写推送声音设置,例如choo,具体值请在bark-推送铃声-查看所有铃声
export BARK_SOUND="" export BARK_SOUND=""
## 下方填写推送消息分组,默认为"QingLong" ## 下方填写推送消息分组,默认为"QingLong"
+8 -4
View File
@@ -43,7 +43,7 @@ let PUSHDEER_KEY = '';
//此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) //此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX)
let BARK_PUSH = ''; let BARK_PUSH = '';
//BARK app推送图标,自定义推送图标(需iOS15或以上) //BARK app推送图标,自定义推送图标(需iOS15或以上)
let BARK_ICON = 'https://qn.whyour.cn/logo.png'; let BARK_ICON = 'http://qn.whyour.cn/logo.png';
//BARK app推送铃声,铃声列表去APP查看复制填写 //BARK app推送铃声,铃声列表去APP查看复制填写
let BARK_SOUND = ''; let BARK_SOUND = '';
//BARK app推送消息的分组, 默认为"QingLong" //BARK app推送消息的分组, 默认为"QingLong"
@@ -383,7 +383,7 @@ function PushDeerNotify(text, desp, time = 2100) {
console.log(err); console.log(err);
} else { } else {
data = JSON.parse(data); data = JSON.parse(data);
// 通过反悔的result的长度来判断是否成功 // 通过返回的result的长度来判断是否成功
if ( if (
data.content.result.length !== undefined && data.content.result.length !== undefined &&
data.content.result.length > 0 data.content.result.length > 0
@@ -529,9 +529,13 @@ function tgBotNotify(text, desp) {
if (TG_BOT_TOKEN && TG_USER_ID) { if (TG_BOT_TOKEN && TG_USER_ID) {
const options = { const options = {
url: `https://${TG_API_HOST}/bot${TG_BOT_TOKEN}/sendMessage`, url: `https://${TG_API_HOST}/bot${TG_BOT_TOKEN}/sendMessage`,
body: `chat_id=${TG_USER_ID}&text=${text}\n\n${desp}&disable_web_page_preview=true`, json: {
chat_id: `${TG_USER_ID}`,
text: `${text}\n\n${desp}`,
disable_web_page_preview: true,
},
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/json',
}, },
timeout, timeout,
}; };
+1 -1
View File
@@ -271,7 +271,7 @@ def pushdeer(title: str, content: str) -> None:
print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送") print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
return return
print("PushDeer 服务启动") print("PushDeer 服务启动")
data = {"text": title, "desp": urllib.parse.urlencode({"text": content})} data = {"text": title, "desp": content, "type": "markdown", "pushkey": push_config.get("DEER_KEY")}
url = 'https://api2.pushdeer.com/message/push' url = 'https://api2.pushdeer.com/message/push'
response = requests.post(url, data=data).json() response = requests.post(url, data=data).json()
+7 -3
View File
@@ -5,8 +5,9 @@ const envFound = dotenv.config();
const accessKey = process.env.QINIU_AK; const accessKey = process.env.QINIU_AK;
const secretKey = process.env.QINIU_SK; const secretKey = process.env.QINIU_SK;
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey); const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
const key = 'version.ts';
const options = { const options = {
scope: process.env.QINIU_SCOPE, scope: `${process.env.QINIU_SCOPE}:${key}`,
}; };
const putPolicy = new qiniu.rs.PutPolicy(options); const putPolicy = new qiniu.rs.PutPolicy(options);
const uploadToken = putPolicy.uploadToken(mac); const uploadToken = putPolicy.uploadToken(mac);
@@ -14,8 +15,11 @@ const uploadToken = putPolicy.uploadToken(mac);
const localFile = 'src/version.ts'; const localFile = 'src/version.ts';
const config = new qiniu.conf.Config({ zone: qiniu.zone.Zone_z1 }); const config = new qiniu.conf.Config({ zone: qiniu.zone.Zone_z1 });
const formUploader = new qiniu.form_up.FormUploader(config); const formUploader = new qiniu.form_up.FormUploader(config);
const putExtra = new qiniu.form_up.PutExtra('', '', 'text/plain'); const putExtra = new qiniu.form_up.PutExtra(
const key = 'version.ts'; '',
'',
'text/plain; charset=utf-8',
);
// 文件上传 // 文件上传
formUploader.putFile( formUploader.putFile(
uploadToken, uploadToken,
+3 -3
View File
@@ -178,7 +178,7 @@ update_cron() {
notify_api() { notify_api() {
local title=$1 local title=$1
local content=$1 local content=$2
local currentTimeStamp=$(date +%s) local currentTimeStamp=$(date +%s)
local api=$( local api=$(
curl -s --noproxy "*" "http://0.0.0.0:5600/api/system/notify?t=$currentTimeStamp" \ curl -s --noproxy "*" "http://0.0.0.0:5600/api/system/notify?t=$currentTimeStamp" \
@@ -196,9 +196,9 @@ notify_api() {
code=$(echo $api | jq -r .code) code=$(echo $api | jq -r .code)
message=$(echo $api | jq -r .message) message=$(echo $api | jq -r .message)
if [[ $code == 200 ]]; then if [[ $code == 200 ]]; then
echo -e "成功" echo -e "通知发送成功"
else else
echo -e "失败(${message})" echo -e "通知失败(${message})"
fi fi
} }
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
echo -e "开始发布"
echo -e "切换master分支"
git checkout master
echo -e "合并develop代码"
git merge origin/develop
echo -e "提交master代码"
git push
echo -e "更新cdn文件"
ts-node sample/tool.ts
string=$(cat src/version.ts | grep "version" | egrep "[^\']*" -o | egrep "\d\.*")
version="v$string"
echo -e "当前版本$version"
echo -e "删除已经存在的本地tag"
git tag -d "$version" &>/dev/null
echo -e "删除已经存在的远程tag"
git push origin :refs/tags/$version &>/dev/null
echo -e "创建新tag"
git tag -a "$version" -m "release $version"
echo -e "提交tag"
git push --tags
echo -e "完成发布"
+69 -41
View File
@@ -7,14 +7,14 @@ dir_shell=$QL_DIR/shell
## 选择python3还是node ## 选择python3还是node
define_program() { define_program() {
local first_param=$1 local file_param=$1
if [[ $first_param == *.js ]]; then if [[ $file_param == *.js ]]; then
which_program="node" which_program="node"
elif [[ $first_param == *.py ]] || [[ $first_param == *.pyc ]]; then elif [[ $file_param == *.py ]] || [[ $file_param == *.pyc ]]; then
which_program="python3" which_program="python3"
elif [[ $first_param == *.sh ]]; then elif [[ $file_param == *.sh ]]; then
which_program="bash" which_program="bash"
elif [[ $first_param == *.ts ]]; then elif [[ $file_param == *.ts ]]; then
which_program="ts-node-transpile-only" which_program="ts-node-transpile-only"
else else
which_program="" which_program=""
@@ -76,41 +76,48 @@ run_nohup() {
## 正常运行单个脚本,$1:传入参数 ## 正常运行单个脚本,$1:传入参数
run_normal() { run_normal() {
local first_param=$1 local file_param=$1
define_program "$first_param" define_program "$file_param"
if [[ $first_param == *.js ]]; then if [[ $file_param == *.js ]]; then
if [[ $# -eq 1 ]]; then if [[ $# -eq 1 ]]; then
random_delay random_delay
fi fi
fi fi
log_time=$(date "+%Y-%m-%d-%H-%M-%S") log_time=$(date "+%Y-%m-%d-%H-%M-%S")
log_dir_tmp="${first_param##*/}" log_dir_tmp="${file_param##*/}"
log_dir_tmp_path="${first_param%%/*}" if [[ $file_param =~ "/" ]]; then
if [[ $file_param == /* ]]; then
log_dir_tmp_path="${file_param:1}"
else
log_dir_tmp_path="${file_param}"
fi
fi
log_dir_tmp_path="${log_dir_tmp_path%/*}"
log_dir_tmp_path="${log_dir_tmp_path##*/}" log_dir_tmp_path="${log_dir_tmp_path##*/}"
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}" [[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
log_dir="$dir_log/${log_dir_tmp%%.*}" log_dir="${log_dir_tmp%.*}"
log_path="$log_dir/$log_time.log" log_path="$log_dir/$log_time.log"
cmd="&>> $log_path" cmd="&>> $dir_log/$log_path"
[[ "$show_log" == "true" ]] && cmd="" [[ "$show_log" == "true" ]] && cmd=""
make_dir "$log_dir" make_dir "$dir_log/$log_dir"
local begin_time=$(date '+%Y-%m-%d %H:%M:%S') local begin_time=$(date '+%Y-%m-%d %H:%M:%S')
local begin_timestamp=$(date "+%s") local begin_timestamp=$(date "+%s")
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd [[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
local id=$(cat $list_crontab_user | grep -E "$cmd_task $first_param" | perl -pe "s|.*ID=(.*) $cmd_task $first_param\.*|\1|" | head -1 | awk -F " " '{print $1}') local id=$(cat $list_crontab_user | grep -E "$cmd_task $file_param" | perl -pe "s|.*ID=(.*) $cmd_task $file_param\.*|\1|" | head -1 | awk -F " " '{print $1}')
[[ $id ]] && update_cron "\"$id\"" "0" "$$" "$log_path" "$begin_timestamp" [[ $id ]] && update_cron "\"$id\"" "0" "$$" "$log_path" "$begin_timestamp"
eval . $file_task_before "$@" $cmd eval . $file_task_before "$@" $cmd
cd $dir_scripts cd $dir_scripts
local relative_path="${first_param%/*}" local relative_path="${file_param%/*}"
if [[ ! -z ${relative_path} ]] && [[ ${first_param} =~ "/" ]]; then if [[ ! -z ${relative_path} ]] && [[ ${file_param} =~ "/" ]]; then
cd ${relative_path} cd ${relative_path}
first_param=${first_param/$relative_path\//} file_param=${file_param/$relative_path\//}
fi fi
eval timeout -k 10s $command_timeout_time $which_program $first_param $cmd eval timeout -k 10s $command_timeout_time $which_program $file_param $cmd
eval . $file_task_after "$@" $cmd eval . $file_task_after "$@" $cmd
local end_time=$(date '+%Y-%m-%d %H:%M:%S') local end_time=$(date '+%Y-%m-%d %H:%M:%S')
@@ -122,7 +129,7 @@ run_normal() {
## 并发执行时,设定的 RandomDelay 不会生效,即所有任务立即执行 ## 并发执行时,设定的 RandomDelay 不会生效,即所有任务立即执行
run_concurrent() { run_concurrent() {
local first_param="$1" local file_param="$1"
local env_param="$2" local env_param="$2"
local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|") local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|")
if [[ ! $env_param ]]; then if [[ ! $env_param ]]; then
@@ -145,17 +152,24 @@ run_concurrent() {
local cookieStr=$(echo ${array_run[*]} | sed 's/\ /\&/g') local cookieStr=$(echo ${array_run[*]} | sed 's/\ /\&/g')
[[ ! -z $cookieStr ]] && export ${env_param}=${cookieStr} [[ ! -z $cookieStr ]] && export ${env_param}=${cookieStr}
define_program "$first_param" define_program "$file_param"
log_time=$(date "+%Y-%m-%d-%H-%M-%S") log_time=$(date "+%Y-%m-%d-%H-%M-%S")
log_dir_tmp="${first_param##*/}" log_dir_tmp="${file_param##*/}"
log_dir_tmp_path="${first_param%%/*}" if [[ $file_param =~ "/" ]]; then
if [[ $file_param == /* ]]; then
log_dir_tmp_path="${file_param:1}"
else
log_dir_tmp_path="${file_param}"
fi
fi
log_dir_tmp_path="${log_dir_tmp_path%/*}"
log_dir_tmp_path="${log_dir_tmp_path##*/}" log_dir_tmp_path="${log_dir_tmp_path##*/}"
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}" [[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
log_dir="$dir_log/${log_dir_tmp%%.*}" log_dir="${log_dir_tmp%.*}"
log_path="$log_dir/$log_time.log" log_path="$log_dir/$log_time.log"
cmd="&>> $log_path" cmd="&>> $dir_log/$log_path"
[[ "$show_log" == "true" ]] && cmd="" [[ "$show_log" == "true" ]] && cmd=""
make_dir $log_dir make_dir "$dir_log/$log_dir"
local begin_time=$(date '+%Y-%m-%d %H:%M:%S') local begin_time=$(date '+%Y-%m-%d %H:%M:%S')
local begin_timestamp=$(date "+%s") local begin_timestamp=$(date "+%s")
@@ -163,7 +177,7 @@ run_concurrent() {
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd [[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
local id=$(cat $list_crontab_user | grep -E "$cmd_task $first_param" | perl -pe "s|.*ID=(.*) $cmd_task $first_param\.*|\1|" | head -1 | awk -F " " '{print $1}') local id=$(cat $list_crontab_user | grep -E "$cmd_task $file_param" | perl -pe "s|.*ID=(.*) $cmd_task $file_param\.*|\1|" | head -1 | awk -F " " '{print $1}')
[[ $id ]] && update_cron "\"$id\"" "0" "$$" "$log_path" "$begin_timestamp" [[ $id ]] && update_cron "\"$id\"" "0" "$$" "$log_path" "$begin_timestamp"
eval . $file_task_before "$@" $cmd eval . $file_task_before "$@" $cmd
@@ -172,20 +186,20 @@ run_concurrent() {
single_log_time=$(date "+%Y-%m-%d-%H-%M-%S.%N") single_log_time=$(date "+%Y-%m-%d-%H-%M-%S.%N")
cd $dir_scripts cd $dir_scripts
local relative_path="${first_param%/*}" local relative_path="${file_param%/*}"
if [[ ! -z ${relative_path} ]] && [[ ${first_param} =~ "/" ]]; then if [[ ! -z ${relative_path} ]] && [[ ${file_param} =~ "/" ]]; then
cd ${relative_path} cd ${relative_path}
first_param=${first_param/$relative_path\//} file_param=${file_param/$relative_path\//}
fi fi
for i in "${!array[@]}"; do for i in "${!array[@]}"; do
export ${env_param}=${array[i]} export ${env_param}=${array[i]}
single_log_path="$log_dir/${single_log_time}_$((i + 1)).log" single_log_path="$dir_log/$log_dir/${single_log_time}_$((i + 1)).log"
timeout -k 10s $command_timeout_time $which_program $first_param &>$single_log_path & timeout -k 10s $command_timeout_time $which_program $file_param &>$single_log_path &
done done
wait wait
for i in "${!array[@]}"; do for i in "${!array[@]}"; do
single_log_path="$log_dir/${single_log_time}_$((i + 1)).log" single_log_path="$dir_log/$log_dir/${single_log_time}_$((i + 1)).log"
eval cat $single_log_path $cmd eval cat $single_log_path $cmd
[[ -f $single_log_path ]] && rm -f $single_log_path [[ -f $single_log_path ]] && rm -f $single_log_path
done done
@@ -210,14 +224,21 @@ run_designated() {
define_program "$file_param" define_program "$file_param"
log_time=$(date "+%Y-%m-%d-%H-%M-%S") log_time=$(date "+%Y-%m-%d-%H-%M-%S")
log_dir_tmp="${file_param##*/}" log_dir_tmp="${file_param##*/}"
log_dir_tmp_path="${file_param%%/*}" if [[ $file_param =~ "/" ]]; then
if [[ $file_param == /* ]]; then
log_dir_tmp_path="${file_param:1}"
else
log_dir_tmp_path="${file_param}"
fi
fi
log_dir_tmp_path="${log_dir_tmp_path%/*}"
log_dir_tmp_path="${log_dir_tmp_path##*/}" log_dir_tmp_path="${log_dir_tmp_path##*/}"
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}" [[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
log_dir="$dir_log/${log_dir_tmp%%.*}" log_dir="${log_dir_tmp%.*}"
log_path="$log_dir/$log_time.log" log_path="$log_dir/$log_time.log"
cmd="&>> $log_path" cmd="&>> $dir_log/$log_path"
[[ "$show_log" == "true" ]] && cmd="" [[ "$show_log" == "true" ]] && cmd=""
make_dir $log_dir make_dir "$dir_log/$log_dir"
local begin_time=$(date '+%Y-%m-%d %H:%M:%S') local begin_time=$(date '+%Y-%m-%d %H:%M:%S')
local begin_timestamp=$(date "+%s") local begin_timestamp=$(date "+%s")
@@ -266,14 +287,21 @@ run_else() {
define_program "$file_param" define_program "$file_param"
log_time=$(date "+%Y-%m-%d-%H-%M-%S") log_time=$(date "+%Y-%m-%d-%H-%M-%S")
log_dir_tmp="${file_param##*/}" log_dir_tmp="${file_param##*/}"
log_dir_tmp_path="${file_param%%/*}" if [[ $file_param =~ "/" ]]; then
if [[ $file_param == /* ]]; then
log_dir_tmp_path="${file_param:1}"
else
log_dir_tmp_path="${file_param}"
fi
fi
log_dir_tmp_path="${log_dir_tmp_path%/*}"
log_dir_tmp_path="${log_dir_tmp_path##*/}" log_dir_tmp_path="${log_dir_tmp_path##*/}"
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}" [[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
log_dir="$dir_log/${log_dir_tmp%%.*}" log_dir="${log_dir_tmp%.*}"
log_path="$log_dir/$log_time.log" log_path="$log_dir/$log_time.log"
cmd="&>> $log_path" cmd="&>> $dir_log/$log_path"
[[ "$show_log" == "true" ]] && cmd="" [[ "$show_log" == "true" ]] && cmd=""
make_dir $log_dir make_dir "$dir_log/$log_dir"
local begin_time=$(date '+%Y-%m-%d %H:%M:%S') local begin_time=$(date '+%Y-%m-%d %H:%M:%S')
local begin_timestamp=$(date "+%s") local begin_timestamp=$(date "+%s")
@@ -338,7 +366,7 @@ main() {
esac esac
;; ;;
esac esac
[[ -f $log_path ]] && cat $log_path [[ -f "$dir_log/$log_path" ]] && cat "$dir_log/$log_path"
elif [[ $# -eq 0 ]]; then elif [[ $# -eq 0 ]]; then
echo echo
usage usage
+1 -1
View File
@@ -226,7 +226,7 @@ export default function (props: any) {
selectedKeys={[props.location.pathname]} selectedKeys={[props.location.pathname]}
loading={loading} loading={loading}
ErrorBoundary={Sentry.ErrorBoundary} ErrorBoundary={Sentry.ErrorBoundary}
logo={<Image preview={false} src="https://qn.whyour.cn/logo.png" />} logo={<Image preview={false} src="http://qn.whyour.cn/logo.png" />}
title={ title={
<> <>
<span style={{ fontSize: 16 }}></span> <span style={{ fontSize: 16 }}></span>
+1 -1
View File
@@ -233,7 +233,7 @@ const Initialization = () => {
<img <img
alt="logo" alt="logo"
className={styles.logo} className={styles.logo}
src="https://qn.whyour.cn/logo.png" src="http://qn.whyour.cn/logo.png"
/> />
<span className={styles.title}></span> <span className={styles.title}></span>
</div> </div>
+1 -1
View File
@@ -135,7 +135,7 @@ const Login = () => {
<img <img
alt="logo" alt="logo"
className={styles.logo} className={styles.logo}
src="https://qn.whyour.cn/logo.png" src="http://qn.whyour.cn/logo.png"
/> />
<span className={styles.title}> <span className={styles.title}>
{twoFactor ? '两步验证' : config.siteName} {twoFactor ? '两步验证' : config.siteName}
+1 -1
View File
@@ -10,7 +10,7 @@ const About = () => {
<img <img
alt="logo" alt="logo"
style={{ width: 140, marginRight: 20 }} style={{ width: 140, marginRight: 20 }}
src="https://qn.whyour.cn/logo.png" src="http://qn.whyour.cn/logo.png"
/> />
<div className={styles.right}> <div className={styles.right}>
<span className={styles.title}></span> <span className={styles.title}></span>
+8 -2
View File
@@ -77,7 +77,7 @@ export default {
{ value: 'gotify', label: 'Gotify' }, { value: 'gotify', label: 'Gotify' },
{ value: 'goCqHttpBot', label: 'GoCqHttpBot' }, { value: 'goCqHttpBot', label: 'GoCqHttpBot' },
{ value: 'serverChan', label: 'Server酱' }, { value: 'serverChan', label: 'Server酱' },
{ value: 'PushDeer', label: 'PushDeer' }, { value: 'pushDeer', label: 'PushDeer' },
{ value: 'bark', label: 'Bark' }, { value: 'bark', label: 'Bark' },
{ value: 'telegramBot', label: 'Telegram机器人' }, { value: 'telegramBot', label: 'Telegram机器人' },
{ value: 'dingtalkBot', label: '钉钉机器人' }, { value: 'dingtalkBot', label: '钉钉机器人' },
@@ -114,7 +114,13 @@ export default {
serverChan: [ serverChan: [
{ label: 'serverChanKey', tip: 'Server酱SENDKEY', required: true }, { label: 'serverChanKey', tip: 'Server酱SENDKEY', required: true },
], ],
PushDeer: [{ label: 'PushDeerKey', tip: 'PushDeer的Key', required: true }], pushDeer: [
{
label: 'pushDeerKey',
tip: 'PushDeer的Keyhttps://github.com/easychen/pushdeer',
required: true,
},
],
bark: [ bark: [
{ {
label: 'barkPush', label: 'barkPush',
+9 -14
View File
@@ -1,15 +1,10 @@
export const version = '2.12.0'; export const version = '2.12.1';
export const changeLogLink = 'https://t.me/jiao_long/288'; export const changeLogLink = 'https://t.me/jiao_long/289';
export const changeLog = `2.12.0 版本说明 export const changeLog = `2.12.1 版本说明
1. 1.
2. openapi增加发送通知接口 2. pushdeer
3. pushDeer推送 https://github.com/NekoMio PR 3. python pushDeer推送 https://github.com/chen310 PR
4. public服务使 3. nodejs telegram推送改为json方式 https://github.com/kan3Git PR
5. ql check可视化错误提示 4.
6. openapi获取token逻辑5token 5. bug修复
7. logdbscriptsconfig等目录迁移到 /ql/data docker映射只需映射data目录
8. 便
9.
10. 退
11. bug修复
`; `;