php获取html内的纯文本

在写xml的时候,文档要求内容里面只要图片和段落就可以了,其他的css,js什么的都不需要。

所以,在输出的时候,就要用正则去过滤掉不需要的标签代码。

第一种:php正则去除js标签代码。

$preg = "/<script[\s\S]*?<\/script>/i";
$content = preg_replace($preg, "", $content);

第二种:php正则去除meta标签

$preg = "/<meta[\s\S]*?>/i";
$content = preg_replace($preg, "", $content);

第三种:php正则去除link标签

$preg = "/<link[\s\S]*?>/i";
$content = preg_replace($preg, "", $content);

第四种:php正则去除页内css样式

$preg = "/<style[\s\S]*?<\/style>/i";
$content = preg_replace($preg, "", $content);

第五种:php正则去除行内样式,id,class等

$preg = "/(style|id|class)=\"[\s\S]*?\"/i";
$content = preg_replace($preg, "", $content);

其他的标签可以自行脑补。

 

 

<pre>function getClearStr($str){
//去掉中,英文标点符号和HTML代码
    $str = preg_replace( "/<style[\s\S]*?<\/style>/i", "", $str );
    $str = preg_replace( "/<script[\s\S]*?<\/script>/i", "", $str );
    $str=preg_replace('/\s/','',preg_replace("/[[:punct:]]/",'',strip_tags(html_entity_decode($str,ENT_QUOTES,'UTF-8'))));

    return $str;
}</pre>

微信开发之module.exports用法 及module.exports和exports的区别

常见用法:在data.js文件中定义

var dataPost = {
“seller”: {
“name”: “粥品香坊”,
“description”: “蜂鸟专送”,
“deliveryTime”: 38,
“score”: 4.2,
“serviceScore”: 4.1,
},
}

module.exports={
myDataPost: dataPost // 对外暴露的变量名叫myDataPost,对应着内部的dataPost对象
}

在index.js中调用:
let Data = require(‘../../data/data.js’); // 引入公共代码
var dataList = Data.myDataPost.seller; // 开始通过对外暴露变量myDataPost,访问内部dataPost对象

微信开发中,可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。

需要注意的是:

推荐开发者采用 module.exports 来暴露模块接口。
小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中。
// common.js
function sayHello(name) {
console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}

module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
​在需要使用这些模块的文件中,使用 require(path) 将公共代码引入

var common = require(‘common.js’)
Page({
helloMINA: function() {
common.sayHello(‘MINA’)
},
goodbyeMINA: function() {
common.sayGoodbye(‘MINA’)
}
})
Tips

tip: require 暂时不支持绝对路径
require 用来加载代码,而 exports 和 module.exports 则用来导出代码。

其他例子:

1、返回一个JSON Object

var app = {
name: ‘app’,
version: ‘1.0.0’,
sayName: function(name){
console.log(this.name);
}
}
module.exports = app;
这种方法可以返回全局共享的变量或者方法。
调用方法:

var app = require(‘./app.js’);
app.sayName(‘hello’);//hello
或者这样用:

var func1 = function() {
console.log(“func1”);
};

var func2 = function() {
console.log(“func2”);
};

exports.function1 = func1;
exports.function2 = func2;
调用方法为:

var functions = require(“./functions”);
functions.function1();
functions.function2();
2、返回一个构造函数

CLASS.js:

var CLASS = function(args){
this.args = args;
}
module.exports = CLASS;
调用:

var CLASS = require(‘./CLASS.js’);
var c = new CLASS(‘arguments’);
3、返回一个实例对象:

//CLASS.js
var CLASS = function(){
this.name = “class”;
}
CLASS.prototype.func = function(){
alert(this.name);
}
module.exports = new CLASS();
调用:

var c = require(‘./CLASS.js’);
c.func();//”class”

exports 和 module.exports 的区别

exports就是module.exports的引用

module.exports 初始值为一个空对象 {}
exports 是指向的 module.exports 的引用
require() 返回的是 module.exports 而不是 exports

https://blog.csdn.net/LVXIANGAN/article/details/79351571

 

在node中我们为了实现模块化,会经常遇到这样的情况:一个文件中需要引用另一个文件中的某些function或者对象等(使用require() ),同时这个文件里面的某些function或者对象又会被其他地方给引用(使用model.exports或者exports)。

通常在一个文件里面有两个可用的用来暴露函数或者对象等的对象:module.exports、exports,一般用前者更好,在文章的最后将说明他们的区别。

这里就涉及到模块化的思想。在我再这里就简单的说一下怎么用。

module.exports

如果想在一个文件中暴露本文件的变量或者函数等可以在文件的最后使用module.exports。module是一个对象,像下面给出的代码一样。

var module = {
id: ‘hello’,
exports: {}
};
例子:

module.exports={key:value} //相当于暴露一个对象出去
module.exports.key = value
module.exports=function name(){} //暴露一个函数或者数组
require()

在一个文件中可以使用require()来引用另一个文件中的中暴露出来的函数或者变量等。

例子:

var hello = require(‘文件所在位置’)
注意此时引用到的是一个对象或者数组或者函数,具体看在另一个文件中使用module.exports暴露的是一个对象还是数组函数函数,如果是对象使用对象的访问方式去访问里面的属性,数组和函数也使用相应的访问方式使用。
module.exports和exports的区别

module的样子在前面已经列出来了。其实exports就是module.exports的引用。但是exports不能暴露函数和数组。也就是不能像下面这样暴露。

exports = function name(){}
可以像下面这样理解:

把exports看成是对module.exports的引用,可以用exports.foo往里面增加新的属性,但是如果直接对exports赋值,exports的指向改变,exports就不再是module.exports的引用了,所以moudule.exports仍然为空对象{}。

前面的例子中就是相当于函数返回一个新的引用,改变了exports的指向。


 

微信小程序中module.exports与exports的用法可以查看下面官方提供的文档,使用起来还是比较简单方便的,但时对于这两者的区别解释的不是很明白。

微信小程序官方文档–框架–逻辑层–模块化.png

为了更好的理解 exports 和module.exports 的关系,我们先来补点 js 基础。示例:

// index.js
Page({
    onLoad: function(){
        var a = {name: '张三'};
        var b = a;
        console.log(a);
        console.log(b);

        b.name = '李四';
        console.log(a);
        console.log(b);

        var b = {name: '王五'};
        console.log(a);
        console.log(b);
    }
})

运行 app.js 结果为:

{ name: '张三' }
{ name: '张三' }
{ name: '李四' }
{ name: '李四' }
{ name: '李四' }
{ name: '王五' }

解释一下:
a 是一个对象,b 是对 a 的引用,即 a 和 b 指向同一个对象,即 a 和 b 指向同一块内存地址,所以前两个输出一样。
当对 b 作修改时,即 a 和 b 指向同一块内存地址的内容发生了改变,所以 a 也会体现出来,所以第三四个输出一样。
当对 b 完全覆盖时,b 就指向了一块新的内存地址(并没有对原先的内存块作修改),a 还是指向原来的内存块,即 a 和 b 不再指向同一块内存,也就是说此时 a 和 b 已毫无关系,所以最后两个输出不一样。

明白了上述例子后,我们进入正题。我们只需知道三点即可知道exports 和module.exports 的区别了:

  • exports 是指向的module.exports 的引用;
  • module.exports 初始值为一个空对象{},所以exports 初始值也是{};
  • require() 返回的是module.exports 而不是exports。
    所以:我们通过
var name = '张三';
exports.name = name;
exports.sayName = function() {
    console.log(name);
}
exports 赋值其实是给module.exports 这个空对象添加了两个属性而已,上面的代码相当于:
var name = '张三';
module.exports.name = name;
module.exports.sayName = function() {
     console.log(name);
}

下面就在微信小程序中module.exports和exports的区别做出示例

// common.js 
function sayHello(name) {
    console.log(`Hello ${name} !`);
}
function sayGoodbye(name) {
    console.log(`Goodbye ${name} !`);
}
// 第一种情况,module.exports初始值为空对象,两个函数使用module.exports或exports都一样效果
module.exports.sayHello = sayHello;
module.exports.sayGoodbye = sayGoodbye; 
exports.sayHello = sayHello;
exports.sayGoodbye = sayGoodbye; 

// 第二种情况,module.exports初始值不为空对象,只能使用module.exports暴露接口,而不能使用exports暴露,会出现is not a function错误。
module.exports = {name:1};// module.exports给一个初始值

//以下两个正常使用
module.exports.sayHello = sayHello;  
module.exports.sayGoodbye = sayGoodbye;

//使用以下两个会报错误sayHello is not a function
exports.sayHello = sayHello;  
exports.sayGoodbye = sayGoodbye;

综上所述,当module.exports 指向新的对象时,exports 断开了与 module.exports 的引用,module.exports 指向了新的内存块,而 exports 还是指向原来的内存块。
因此,在不是很清楚两者关系的时候,请采用module.exports来暴露接口,而尽量不采用exports暴露接口。

作者:吕周坤
链接:https://www.jianshu.com/p/2431adaa97bf
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

linux查看占用端口程序 结束掉进程

前言

在OS X中使用GAE引擎来科学上网比如goagent或者wallproxy,可能会在启动过程中出现如下报错然后导致服务启动不成功。

原因

其实就是因为你曾启动过相同或者类似的服务占用了这个端口,一般来讲,在Mac上直接用Python启动的话,会导致退出不完整,你不能通过点击GUI的“退出”按钮来一步到位,后台的Python进程还是存在的,而它就是一直占用端口不释放的元凶。

解决办法

一个是改掉默认的80878086端口,另一个,就是干掉占用端口的程序。

前者立竿见影,但缺点是你总不能一天换一个的吧,如果说是因为其他应用占用端口还好说,那要是因为退出不完整呢?所以,后者才是治标治本的解决办法。但是想要找到这个占用端口的程序,就要引入下面的内容了:

lsof命令

简介

lsof(list open files)命令是一个列出当前系统打开文件的工具。在类UNIX环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以我们使用它来找出占用了端口的程序,看看它究竟是不是冲突是不是错误。

lsof -i 用以显示符合条件的进程情况

所以,我们使用如下命令即可查找出占用了某个端口的程序和其对应的PID

然后使用下面的命令干掉对应的进程:

亚马逊url参数分析

https://www.amazon.com/VicTsing-Non-Slip-Gaming-Typist-Office/dp/B072C93TQL/ref=sr_1_1?ie=UTF8&qid=1504531098&sr=8-1&keywords=B072C93TQL
https://www.amazon.com/Belkin-WaveRest-Mouse-Wrist-Support/dp/B00000JRRD/ref=pd_sbs_229_1?_encoding=UTF8&psc=1&refRID=VB2M27JXJ57RC3BTQD8E

https://www.amazon.com/OMOTON-Ultra-Slim-Bluetooth-Keyboard-Enabled/dp/B00GD1BGYO/ref=sr_1_1_sspa?ie=UTF8&qid=1531813108&sr=8-1-spons&keywords=keyboard&psc=1&smid=AG8D5TKU5UGTB

VicTsing-Non-Slip-Gaming-Typist-Office 这个叫Slug,是Amazon根据listing的title生成的,对于同一个listing而言,这个是固定的
dp/B072C93TQL 产品ASIN

ref=sr_1_1 搜索来源 后面1表示第1个产品 sr_1_1_sspa 广告参数 Sponsored
ref=pd_sbs_229_1 Customers who viewed this item also viewed【猜你喜欢】 模块点击的产品 1代表第一个产品
ref=sspa_dk_detail_0 Sponsored products related to this item 【广告】模块点击的产品 0 代表第一个产品

ie=UTF8 网页显示的编码
qid=1504531098 时间戳 :
每一个URL有一个时间戳,记录了每一个搜索点击的具体时间,使每个人为的搜索将只算作一次。若没规避这个机制,Super Url的安全性也就低了,无法做到模拟人工搜索。

sr=8-1 第1个产品 8-1-spons 第1个广告产品 Sponsored
keywords=B072C93TQL 搜索关键词参数
_encoding=UTF8 字符编码
psc=1
refRID=VB2M27JXJ57RC3BTQD8E
smid=AG8D5TKU5UGTB 商家merchant id
s=videogames 商品品类描述
refRID 该参数暂时未知

Windows下Git多账号配置,同一电脑多个ssh-key的管理

这一篇文章是对上一篇文章《Git-TortoiseGit完整配置流程》的拓展,所以需要对上一篇文章有所了解,当然直接往下看也可以,其中也有一些提到一些基础的操作。

本文以配置github.com账号和git.oschina.net账号来逐步演示在Windows环境下配置Git多账号支持即在同一个电脑上管理多个ssh-key,对git多一分了解。

  备注:这篇文章所有执行命令的地方都是在管理员模式下进行,即打开cmd,Git Bash客户端用管理员身份运行程序。


1. 生成github.com对应的私钥公钥(本文中文件地址C:\Users\popfisher目录)

执行命令 ssh-keygen -t rsa -C email 创建github对应的sshkey,命名为id_rsa_github,密码 123456 

ssh-keygen -t rsa -C 774232122@qq.com

 

2. 同样的方式生产git.oschina.net的私钥公钥(邮箱地址可以相同可以不同,本文相同)

执行命令ssh-keygen -t rsa -C email创建github对应的sshkey,命名为id_rsa_oschina,密码 123456

ssh-keygen -t rsa -C 774232122@qq.com

 

3. 把上面得到的文件拷贝到git默认访问的.ssh目录(win10在用户目录下,本文C:\Users\popfisher.ssh)

除了秘钥文件之外,config文件是后面的步骤中手动生产的,known_hosts文件是后续自动生产的

4. 把github对应的公钥和oschina对应的公钥上传到服务器

 GitHub添加SSH key的方式如下图所示:

 

git.oschina.net添加SSH key的方式如下图所示:

 

5. 在.ssh目录创建config文本文件并完成相关配置(最核心的地方)

每个账号单独配置一个Host,每个Host要取一个别名,每个Host主要配置HostNameIdentityFile两个属性即可

Host的名字可以取为自己喜欢的名字,不过这个会影响git相关命令,例如:
Host mygithub 这样定义的话,命令如下,即git@后面紧跟的名字改为mygithub
git clone git@mygithub:PopFisher/AndroidRotateAnim.git

 

HostName           这个是真实的域名地址
IdentityFile          这里是id_rsa的地址
PreferredAuthentications   配置登录时用什么权限认证–可设为publickey,password publickey,keyboard-interactive等
User            配置使用用户名

 

config文件配置如下:

复制代码
# 配置github.com
Host github.com                 
    HostName github.com
    IdentityFile C:\\Users\\popfisher\\.ssh\\id_rsa_github
    PreferredAuthentications publickey
    User username1

# 配置git.oschina.net 
Host git.oschina.net 
    HostName git.oschina.net
    IdentityFile C:\\Users\\popfisher\\.ssh\\id_rsa_oschina
    PreferredAuthentications publickey
    User username2
复制代码

 

 6. 打开Git Bash客户端(管理员身份运行)执行测试命令测试是否配置成功(会自动在.ssh目录生成known_hosts文件把私钥配置进去)

 

7. 测试成功之后就可以在电脑上同时使用git多多账号同时操作,互不影响了

clone github上的项目AndroidRotateAnim

打开github上AndroidRotateAnim项目,复制其对应的clone命令入下图所示

 执行clone命令如下:

 

clone oschina.net上的项目AndroidDevTools

打开git.oschina.net上AndroidDevTools项目,复制其对应的clone命令入下图所示

 执行clone命令如下:

 

学习心得

在使用git的过程中,一般都只关注单账号的情况吗,工作中的配置也是直接由自己的上级发一个配置文档之类的东西,然后对着搞一遍就行了,可是当自己真正有这个需求的时候,突然发现束手无策。我自己当时也属于这个情况,有一天在家里,突然发现自己需要一台电脑支持多个SSH key的时候才发现自己不知道怎么下手了,于是就下定决心自己动手研究一下。对于技术,还是要亲自动手实践,实践出来的东西才能形成自己的真理,才不那么容易忘记。

这篇文章是我基于Win10平台上的实践,由于知识有限,可能还是没有总结得很完整,也可能在其他平台上会遇到一些其他的问题,没有时间去研究了,如果读者有遇到什么问题,欢迎留言讨论,共同学习。

https://www.cnblogs.com/popfisher/p/5731232.html

git push origin codeannotation ssh: connect to host bitbucket.org port 22: Connection timed out fatal: Could not read from remote repository.

$ git push origin codeannotation
ssh: connect to host bitbucket.org port 22: Connection timed out
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

 

完美解决办法   windows  linux  找到.ssh目录

我做了下面提到的事情,它开始工作了。

 vim ~/.ssh/config

添加这些行并保存。

Host bitbucket.org
Hostname  altssh.bitbucket.org
Port  443

 

 

令人困惑的strtotime

经常会有人被strtotime结合-1 month, +1 month, next month的时候搞得很困惑, 然后就会觉得这个函数有点不那么靠谱, 动不动就出问题. 用的时候就会很慌…

这不, 刚刚就有人在微博上又问我:

鸟哥,今天是2018-07-31 执行代码:

  1. date(“Y-m-d”,strtotime(“-1 month”))

怎么输出是2018-07-01?

好的吧, 虽然这个问题看起来很迷惑, 但从内部逻辑上来说呢, 其实是”对”的, 你先别着急哈, 让我慢慢讲:

我们来模拟下date内部的对于这种事情的处理逻辑:

  • 1. 先做-1 month, 那么当前是07-31, 减去一以后就是06-31.
  • 2. 再做日期规范化, 因为6月没有31号, 所以就好像2点60等于3点一样, 6月31就等于了7月1

是不是逻辑很”清晰”呢? 我们也可以手动验证第二个步骤, 比如:

  1. var_dump(date(“Y-m-d”, strtotime(“2017-06-31”)));
  2. //输出2017-07-01

也就是说, 只要涉及到大小月的最后一天, 都可能会有这个迷惑, 我们也可以很轻松的验证类似的其他月份, 印证这个结论:

  1. var_dump(date(“Y-m-d”, strtotime(“-1 month”, strtotime(“2017-03-31”))));
  2. //输出2017-03-03
  3. var_dump(date(“Y-m-d”, strtotime(“+1 month”, strtotime(“2017-08-31”))));
  4. //输出2017-10-01
  5. var_dump(date(“Y-m-d”, strtotime(“next month”, strtotime(“2017-01-31”))));
  6. //输出2017-03-03
  7. var_dump(date(“Y-m-d”, strtotime(“last month”, strtotime(“2017-03-31”))));
  8. //输出2017-03-03

那怎么办呢?

从PHP5.3开始呢, date新增了一系列修正短语, 来明确这个问题, 那就是”first day of” 和 “last day of”, 也就是你可以限定好不要让date自动”规范化”:

  1. var_dump(date(“Y-m-d”, strtotime(“last day of -1 month”, strtotime(“2017-03-31”))));
  2. //输出2017-02-28
  3. var_dump(date(“Y-m-d”, strtotime(“first day of +1 month”, strtotime(“2017-08-31”))));
  4. ////输出2017-09-01
  5. var_dump(date(“Y-m-d”, strtotime(“first day of next month”, strtotime(“2017-01-31”))));
  6. ////输出2017-02-01
  7. var_dump(date(“Y-m-d”, strtotime(“last day of last month”, strtotime(“2017-03-31”))));
  8. ////输出2017-02-28

那如果是5.3之前的版本(还有人用么?), 你可以使用mktime之类的, 把所有的日子忽略掉, 比如都限定为每月1号就可以了, 只不过就不如直接用first day来的更加优雅.

现在, 搞清楚了内部原理, 是不是就不慌了? 🙂

替代crontab,统一定时任务管理系统cronsun简介

摘 要

cronsun 是一个分布式任务系统,单个节点和 Linux 机器上的 crontab 近似。是为了解决多台 Linux  机器上 crontab 任务管理不方便的问题,同时提供任务高可用的支持(当某个节点死机的时候可以自动调度到正常的节点执行)。支持界面管理机器上的任务,支持任务失败邮件提醒,安装简单,使用方便,是替换 crontab 一个不错的选择。

替代crontab,统一定时任务管理系统cronsun简介

 

一、背景

crontab 是 Linux 系统里面最简单易用的定时任务管理工具,相信绝大多数开发和运维都用到过。在咱们公司,很多业务系统的定时任务都是通过 crontab 来定义的,时间长了后会发现存在很多问题:

  • 大量的 crontab 任务散布在各台服务器,带来了很高的维护成本
  • 任务没有按时执行,甚至失败了很久才发现,需要重试或排查
  • crontab 分散在很多集群上,需要一台一台去看日志分析,头都大了
  • crontab 存在单点问题,对于不能重复执行的定时任务很伤脑筋
  • 我 X,crontab 被误删了,没备份?尼玛!
  • 我 Q,服务器要迁移,crontab 上的历史任务都是什么鬼?问了一圈居然都不知道

因此,我们非常需要一个集中管理定时任务系统,相信这也是的饱受 crontab 煎熬的运维或开发的心声。

二、选择

我们部门的开发人力一直都非常紧张,所以靠自己开发一套完善的定时任务管理系统不太现实。因此,希望找一个开源的系统来快速满足需求。

期间,我在网上看了不少相关文章,比如 http://ju.outofmemory.cn/entry/221885

发现这些系统对于我们的实际场景来说都过于臃肿,不太合适。偶然在 github 找了一个基于 Go 语言开源的定时任务集中管理系统—gocron,发现非常轻量,于是试用了一段时间。

不过最终我还是放弃了,因为 gocron 存在单点问题,项目地址:https://github.com/ouqiang/gocron

期间和作者有过一段时间的交流,提了不少改善建议,在和 gocron 作者交流期间,他针对我提到的单点问题,推荐了另一个开源项目:cronsun,也就是本文介绍的主角,通过试用,发现非常契合我们当前的使用场景,介绍如下:

cronsun 是一个分布式任务系统,单个节点和 Linux 机器上的 crontab 近似。是为了解决多台 Linux  机器上 crontab 任务管理不方便的问题,同时提供任务高可用的支持(当某个节点死机的时候可以自动调度到正常的节点执行)。支持界面管理机器上的任务,支持任务失败邮件提醒,安装简单,使用方便,是替换 crontab 一个不错的选择。

Github 地址:https://github.com/shunfei/cronsun

cronsun 的部署架构如下:替代crontab,统一定时任务管理系统cronsun简介

三、部署

本文主要介绍功能,这里就简单写下关键步骤:

1、安装 MongoDB,强烈建议使用集群模式

2、安装 Etcd3,强烈建议使用集群模式

3、部署 cronsun

①、下载 cronsun:https://github.com/shunfei/cronsun/releases  (选择最新版本即可)

②、解压后修改 conf 目录下的配置文件:db.json 和 etcd.json,分别修改 MongoDB 和 etcd 的实际地址。

③、启动 web:./cronweb -conf conf/base.json (若要后台运行则使用 nohup)

④、启动 node:./cronnode -conf conf/base.json (若要后台运行则使用 nohup)

⑤、访问前台:http://x.x.x.x:7079/ui/

4、部署鉴权组件 aProxy,cronsun 在鉴权方面做的非常粗糙,所以这里用到了 cronsun 团队开发的 aProxy 鉴权组件,实现的原理为基于 Go 语言,反向代理了后端 WEB,从而实现域名和页面地址的访问控制,介绍地址:https://www.cnblogs.com/QLeelulu/p/aproxy.html

我们这边是要用到生产环境,所以在部署上会着重考虑到可用性和可靠性,这里贴一下我们这边的部署架构图,供参考:
替代crontab,统一定时任务管理系统cronsun简介

Ps:目前新版本已支持历史日志定期清理。

这里,Etcd 和 MongoDB 复用了 5 台服务器(后续会继续复用其他公共组件),其中 MongoDB 采用分片+副本集的模式。

四、功能

部署完成后,访问前台就能看到 UI 比较简陋 cronsun 管理 WEB 了:
替代crontab,统一定时任务管理系统cronsun简介

Ps:右上方选择熟悉的语言之后,基本就可以按照页面标签进行任务添加操作了。

1、添加节点

cronsun 基于 etcd 实现了自动发现和注册的功能,所以添加节点非常简单,直接将 cronnode 和 conf 拷贝到客户端服务器启动之后,就能在前台->节点页面看到该服务器了,当然节点和 Etcd 以及 MongoDB 之间的网络必须畅通。替代crontab,统一定时任务管理系统cronsun简介

2、节点分组

添加了所需的节点服务器之后,我们可以将节点进行分组,从而方便定时任务的添加:替代crontab,统一定时任务管理系统cronsun简介

3、添加任务

节点和分组都搞定之后,我们就可以开始添加定时任务了。定时任务填写的信息略微复杂,不过按照提示还是可以轻松搞定的:替代crontab,统一定时任务管理系统cronsun简介

上图我简单的标注了一些需要特别说明的地方,其他的选项大家看中文描述都能自行搞定。当然,还有一点要说明的是,任务脚本必须要有执行权限,否则任务会执行失败。

4、任务列表

添加完成任务之后,在任务标签页就能看到所有添加的定时任务以及执行情况了,这里可以使用分组过滤或节点过滤来筛选关心的任务。替代crontab,统一定时任务管理系统cronsun简介

每一个任务的右侧有 3 个小按钮:

①、成功/失败:显示最近一个任务的执行是成功还是失败,点击后可以查看到任务详情,包括任务输出数据:替代crontab,统一定时任务管理系统cronsun简介

②、latest 按钮:点击后查看改任务的近期执行情况

③、刷新符号按钮:点击后可以弹出立即执行功能,方便调试任务替代crontab,统一定时任务管理系统cronsun简介

五、小结

通过一段时间的灰度试用,可以确定 cronsun 在中小型规模场景下,是 crontab 的一个比较好的替代品,它能够帮助运维人员脱离 crontab 难管理、难运维的苦海。

当然,作为一款开源产品,cronsun 很多功能细节还有很大的提升空间,目前我也和 cronsun 团队长期保持联系,将生产环境使用过程中遇到的一些问题和建议一一反馈,相信这款产品能够继续打磨优化,更加完善、完美。

六、问题及更新【持续】

问题记录:

1、告警配置

首先要清楚 cronsun 的告警是由 cronweb 发出的,而不是 cronnode(但是 cronnode 的 mail.json 也必须 Enable:true,否则还是无法发出告警)。

其次,编辑 cronweb 和 cronnode 的配置文件:mail.json,如下内容

Ps:LocalName 建议留空,HttpAPI 模式未使用到,这里省略之,请自行测试。

最后启动 cronweb 即可实现邮件告警。

当然, 还需要在 web 上的单向任务界面开启告警才行,如下图所示:替代crontab,统一定时任务管理系统cronsun简介

Ps:cronweb 的 mail.json 配置中必须将 Enable 填为 true 才可以看到上图的告警开关按钮,否则不显示。

2、更新记录

详见 github 版本发布页面:https://github.com/shunfei/cronsun/releases

重要功能更新:

①、已支持脚本参数;

②、已支持历史日志定期清理;

③、3.1 版本开始使用 UUID 作为节点唯一标识。

 

 

https://zhangge.net/5129.html