alibaba arthas 使用

Arthas is a Java diagnostic tool that promises to help developers troubleshoot production issues for Java applications without modifying the code or restarting the server.

Main features:

  • Useful for trouble-shooting jar file conflicts
  • Decompile a class to ensure the code is running as expected
  • View classloader statistics
  • View the method invocation details
  • Check the stack trace of specified method invocation
  • Trace the method invocation to find slow sub-invocations
  • Monitor method invocation statistics
  • Monitor system metrics, thread states and CPU usage, gc statistics, and etc
  • Support command line interactive mode, with auto-completed feature enabled.
  • Support telnet and WebSocket, enabling both local and remote diagnostics with command line and browsers

Install

安装非常简单

curl -L https://alibaba.github.io/arthas/install.sh | sh

然后使用 ./as.sh 启动即可。

其他安装方式

实例

全局监控

进入 arthas 之后使用 dashboard 可以快速查看全局信息,包括系统基本信息,CPU 使用率,堆内存,gc 次数,gc 耗时等等

查看 JVM 线程堆栈信息

使用 thread 可以查看线程堆栈信息。当 thread 没有参数时会打印所有的线程信息。

thread 命令也支持打印当前最忙的前 N 个线程

thread -n 3

后面增加 id 可以打印指定线程堆栈

thread id

使用 -b 参数一键找出当前阻塞其他线程的线程

thread -b

目前只支持找出 synchronized 关键字阻塞住的线程, 如果是 java.util.concurrent.Lock, 目前还不支持。

查看类从哪一个 jar 加载

当知道类的路径时可以直接使用 sc -d package.Class 这样的方式来查看当前类的详细信息

$ sc -d demo.MathGame
 class-info        demo.MathGame
 code-source       /home/einverne/arthas/arthas-demo.jar
 name              demo.MathGame
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       MathGame
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@5c647e05
                     +-sun.misc.Launcher$ExtClassLoader@197c17c6
 classLoaderHash   5c647e05

信息中可以清晰的看到加载的 jar 的路径等等一些信息。

代码为什么没有执行

要回答这个问题,最好的方法就是立马检查下当前正在跑的代码是否符合预期。

jad demo.package.Class

直接查看当前运行的代码

查看函数调用栈耗时

如果特别关心某一函数的耗时情况,可以使用 trace 来查看

trace package.Class method

监控有异常的接口

使用 tt 命令可以记录下指定方法被调用时的入参和返回值。tt 是 TimeTunnel 的缩写,为了解决 watch 命令的复杂。

tt -t package.Class methodName -n 100
tt -t package.Class methodName -n 100 > temp.log

-n 表示会统计之后的多少请求,> temp.log 表示输出到 arthas 的 cache 中,地址在 ~/logs/arthas-cache/

回放请求

上面使用 tt 命令记录的内容可以用来回放请求,在 temp.log 日志中找到 index 表示的即为该请求的入参,使用 tt 命令可以用来回放请求,下面命令中的 index 就是文件中的 index

tt --play -i index

在使用回放的时候需要注意:1. ThreadLocal 信息丢失 2. 引用对象, tt 命令将当前环境的对象引用保存,如果方法对入参进行了修改,那么 tt 命令无法查看到准确的值。

watch 命令查看有异常的入参

tt 命令可以一直监控方法的入参,但是有的时候并不关心正常运行的参数,而只关心有异常的方法的入参,这个时候就可以使用 watch 命令

watch package.Class method -e -x 2 '{params[0], params[1].toString, throwExp}'

监控 JVM 运行状态

使用 jvm 命令即可查看 JVM 的运行状态

jvm

sysprop sysenv 查看系统变量

sysprop 可以查看系统变量,sysenv 可以查看系统的环境变量。

reference


2019-01-23 arthas , java , diagnostic-tool

开源软负载均衡 HAProxy 使用及配置

HAProxy is free, open source software that provides a high availability load balancer and proxy server for TCP and HTTP-based applications that spreads requests across multiple servers. It is written in C and has a reputation for being fast and efficient.

Features:

  • Layer 4 (TCP) and Layer 7 (HTTP) load balancing
  • URL rewriting
  • Rate limiting
  • SSL/TLS termination
  • Gzip compression
  • Proxy Protocol support
  • Health checking
  • Connection and HTTP message logging
  • HTTP/2
  • Multithreading
  • Hitless Reloads

Performance:

Similiar:

  • LVS
  • Nginx

HAProxy 的负载均衡算法:

  • roundrobin,表示简单的轮询
  • static-rr,表示根据权重
  • leastconn,表示最少连接者先处理
  • source,表示根据请求源 IP,和 Nginx IP_hash 类似
  • uri,请求 URI
  • url_param,请求的 URI 参数
  • hdr(name), name 指定的 HTTP 首部
  • rdp-cookie(cookie), 根据 cookie(name) 哈希请求

##

HAProxy 关键配置

HAProxy 的配置文件共有 5 个域

  • global:用于配置全局参数
  • default:用于配置所有 frontend 和 backend 的默认属性
  • frontend:用于配置前端服务(即 HAProxy 自身提供的服务)实例
  • backend:用于配置后端服务(即 HAProxy 后面接的服务)实例组
  • listen:frontend+backend 的组合配置,可以理解成更简洁的配置方法

配置举例

HTTP

global
    daemon
    maxconn 256

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http-in
    bind *:80
    default_backend servers

backend servers
    server server1 127.0.0.1:8000 maxconn 32

定义监控

在配置文件中增加

listen stats    #定义监控页面
    bind *:1080                     # 绑定端口 1080
    mode http                       # http mode
    stats hide-version              # Hide HAProxy version
    stats refresh 30s               # 每 30 秒更新监控数据
    stats uri /stats                # 访问监控页面的 uri
    stats realm HAProxy\ Stats      # 监控页面的认证提示
    stats auth admin:admin          # 监控页面的用户名和密码

然后通过 http://ip:1080/stats 即可访问

HAProxy 主备

现在个人代理需求不强烈,等折腾到了再搞。

reference


2019-01-20 linux , load-balance , haproxy , proxy , tcp , http

oneplus 3 recovery ROM kernel 选择

所有下载链接建议有国外 VPS 的直接从国外的 VPS 下载,scp 拉回本地,浏览器下载太慢。

Recovery

ROM

AOSP Extended

LineageOS

Kernel

GApps

Magisk

Decryption Unsuccessful

在安装完新的 AOSP Extended ROM 之后启动突然出现了 “Decryption Unsuccessful” 的问题,一查可能是之前的数据分区加密过,新的系统无法解密读取这些文件了。

There’s some weird issues with the latest AOSP based ROM that makes encrypted ext4 based data partition unable to be decrypted in both system and older version of TWRP if you’re encrypted before (intentionally or unintentionally). This however doesn’t apply to F2FS and unencrypted ext4 data partition

xda 提供了两种解决方案:

推荐的方式是重新分配分区 F2FS,这需要提前备份所有 internal storage 数据,然后抹去所有数据

  • 通过 TWRP 挂载 SD 卡,备份全部数据
  • 格式化所有数据,在 TWRP 中选择 “Format”, 然后选择 “Wipe data”
  • 然后 Flash ROM 和 GApps

第二种方式是安装一个第三方修改过的 Kernel,这种方式不需要抹除数据

  • Xenial b25x or newer
  • Revolt EAS-R13

这里补充下 F2FS,很多人可能好奇 F2FS 是什么,具体做什么用,F2FS 是 “Flash-Friendly File system”,是一种新的文件系统,用于 NAND 闪存一类的储存设备,F2FS 和主流的 ext3/4 相比,有更好的加密特性,更快的读取速度,对碎片小文件读写优化,增加了固态存储的寿命等等优点。但 F2FS 也有其缺点,就是在大文件读写上性能可能会波动。


2019-01-19 oneplus , rom , kernel

Hive SQL 介绍及使用

Hive 是 Hadoop 生态中必不可少的工具,提供了 SQL 方言用于查询存储在 HDFS 中的数据和其他与 Hadoop 集成的文件系统(Amazon S3 ,HBase 数据库,Cassandra 的数据)

Hive 最适合数据仓库应用,使用应用进行相关静态数据分析,不需要快速响应得到结果,数据本身不会频繁发生变化。Hive 不是完整的数据库,Hadoop 和 HDFS 的设计约束和局限限制了 Hive 所能胜任的工作。最大的限制就是 Hive 不支持记录级别的更新、插入或者删除。

Hive 不支持 OLTP(联机事务处理)而更接近 OLAP(联机分析技术),如果要对大规模数据使用 OLTP,应该使用 NoSQL 数据库,例如 HBase 等。和大多数 SQL 方言一样,HiveQL 不符合 ANSI SQL 标准,和 常规的 MySQL,SQL Server 支持的 SQL 有很多方面差异,HiveQL 和 MySQL 提供的 SQL 方言最接近。

安装 Hive 运行环境

Hive 的运行依赖很多环境,需要一一配置

JDK

首先保证 Java 运行环境,jdk 1.7 及以上

java -version

验证

Hadoop 环境搭建

下载 tar,解压,配置环境变量

export HADOOP_HOME=/usr/local/hadoop
export HADDOP_CONF_DIR=$HADOOP_HOME/etc/hadoop

export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME

export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib/native"

export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin
export HADOOP_INSTALL=$HADOOP_HOME

配置完可以查看下版本:

hadoop version

配置文件

配置 core-site.xml

<property>
  <name>fs.default.name</name>
  <value>hdfs://localhost:9000</value>
</property>

配置 hdfs-site.xml

<property>
   <name>dfs.replication</name>
   <value>1</value>
</property>
<property>
   <name>dfs.name.dir</name>
   <value>file:///home/hadoop/hadoopinfra/hdfs/namenode </value>
</property>
<property>
   <name>dfs.data.dir</name>
   <value>file:///home/hadoop/hadoopinfra/hdfs/datanode </value >
</property>

配置 yarn-site.xml

<property>
   <name>yarn.nodemanager.aux-services</name>
   <value>mapreduce_shuffle</value>
</property>

配置 mapred-site.xml

cp mapred-site.xml.template mapred-site.xml

添加如下

<property>
  <name>mapreduce.framework.name</name>
  <value>yarn</value>
</property

验证,首先格式化 namenode

hdfs namenode -format

启动 Hadoop dfs

start-dfs.sh

启动 Yarn Script

start-yarn.sh

安装成功后访问

http://localhost:50070/
http://localhost:8088/

Hive 的大多数工作是使用 Hadoop 的 job,Hive 的行为可以反映出用户所使用的 Hadoop 运行模式。

Hive 环境搭建

下载 tar,解压,配置环境变量(根据不同的路径配置)

wget http://archive.apache.org/dist/hive/hive-2.1.0/apache-hive-2.1.0-bin.tar.gz
tar -xzf apache-hive-2.1.0-bin.tar.gz
export HIVE_HOME=/home/einverne/apache-hive-2.1.0-bin
export PATH=$PATH:$HIVE_HOME/bin

配置

cd $HIVE_HOME/conf
cp hive-env.sh.template hive-env.sh

编辑 hive-env.sh

export HADOOP_HOME=/usr/local/hadoop

配置 hive-site.xml

cp hive-default.xml.template hive-site.xml

使用 hive 内置的 derby (Apache Derby 非常小巧,核心部分 derby.jar 只有 2M,所以既可以做为单独的数据库服务器使用,也可以内嵌在应用程序中使用),初始化 Derby 数据库:

schematool -initSchema -dbType derby

验证

hive --version

进入 hive 之后

hive> show databases;

查看结果。默认会有一个 default 数据库,至此所有的安装都完成了。

Hive 目录的一些说明:

  • $HIVE_HOME/lib 下有很多 jar 包,每一个 jar 包提供 Hive 功能中的特定部分。
  • $HIVE_HOME/bin 目录下包含各种可执行文件,包括 hive 的命令行 CLI。
  • Hive 客户端都需要一个 metastoreservice 元数据服务,Hive 使用该服务来存储表模式信息和其他元数据信息。通常会使用一个关系型数据库的表来提供存储。默认情况下,Hive 会使用内置的 Derby SQL 服务,提供有限的单进程服务。
  • conf 目录下存放 Hive 配置文件。

Hive 的安装总体过程比较复杂可以具体参考这里

问题

启动 start-dfs.sh 时遇到

19/01/29 18:36:55 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

需要配置如下环境变量:

export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$HADOOP_HOME/lib/native"

关于使用 derby 的问题,hive 内嵌一个 derby ,如果要使用内嵌的 derby 那么在 hive-site.xml 中需要配置连接字串为:

<property>
   <name>javax.jdo.option.ConnectionURL</name>
   <value>jdbc:derby:metastore_db;create=true</value>
   <description>JDBC connect string for a JDBC metastore </description>
</property>

而如果选择单独启动 derby 那么需要配置:

<property>
   <name>javax.jdo.option.ConnectionURL</name>
   <value>jdbc:derby://localhost:1527/metastore_db;create=true </value>
   <description>JDBC connect string for a JDBC metastore </description>
</property>

而这个时候则需要单独的配置启动 derby.

使用

Metastore

Hive 的元数据都存放在 metastore 中,包括:服务和后台数据。metastore 的配置有三种方式:

  • 内置 metastore
  • 本地 metastore
  • 远程 metastore

在上面的安装步骤中,使用了内置的 Derby 数据库,但这个只适用于本地试验,如果要部署到生产环境还是需要单独配置 Metastore 数据库,使用外部的 Derby 或者 MySQL 等等。

当使用内置的 Derby 并且在本地一个目录中启动终端 hive,那么进入 hive shell 时,hive 默认会在当前目录下生成一个 metastore_db 目录,用来保存在 Shell 中的 sql 结果,新建的表,添加的分区等等。

这种存储方式导致同一个目录只能同时有一个 hive 客户端访问,切换目录使用 shell 时,无法查看之前创建的表。

如果要使用 MySQL 那么需要配置几点。首先将 mysql-jdbc-driver.jar 拷贝到 $HIVE_HOME/lib 目录下,然后配置 hive-site.xml 文件

<property>  
  <name>hive.metastore.local</name>  
  <value>true</value>  
</property>  
<property>  
  <name>javax.jdo.option.ConnectionURL</name>  
  <value>jdbc:mysql://localhost/hive?createDatabaseIfNotExist=true</value>  
</property>  
<property>  
  <name>javax.jdo.option.ConnectionDriverName</name>  
  <value>com.mysql.jdbc.Driver</value>  
</property>  
<property>  
  <name>javax.jdo.option.ConnectionUserName</name>  
  <value>hive</value>  
</property>  
<property>  
  <name>javax.jdo.option.ConnectionPassword</name>  
  <value>password</value>  
</property>

数据库相关

CREATE DATABASE demo;
CREATE DATABASE IF NOT EXISTS demo;
SHOW DATABASES;
SHOW DATABASE LIKE 'd.*';
DESCRIBE DATABASE demo;

CREATE TABLE IF NOT EXISTS mydb.employees (
    name    STRING COMMENT 'name',
    age     INT COMMENT 'age',
    salary  FLOAT COMMENT 'salary',
    subordinates    ARRAY<STRING> COMMENT 'Names of subordinates',
    deductions      MAP<STRING, FLOAT> COMMENT 'Keys are deductions name, values are percentages',
    address         STRUCT<street:STRING, city:STRING, state:STRING, zip:INT> COMMENT 'Home address'
)
COMMENT 'Description of the table'
TBLPROPERTIES ('creator'='me', 'create_at'='2019-01-01 00:00:00')
LOCATION '/user/hive/warehouse/mydb.db/employees';

DROP TABLE IF EXISTS employees;

reference


2019-01-17 hive , sql , hadoop , hbase

kudu 笔记

Kudu 是一个分布式结构化存储系统,由 Cloudera 开源,和 Apache Hadoop 生态紧密结合,共享了很多相同的工具集,可以跑在相同的硬件上,都支持水平扩展。

Kudu 要解决的问题

在了解 Kudu 之前先要了解两个概念 OLTP 和 OLAP:

  • OLTP,online transaction processing ,database modifying system 数据库
  • OLAP,online analytical procession, online database query answering system 线上分析处理

上面两种系统可以简单的理解为一类是需要频繁修改低延迟写入的数据库系统,一种是需要大量连续读分析的高性能分析系统

结构化数据在 Hadoop 生态系统中存储,通常分为两类:

  • 静态数据,二进制存储 HDFS (Avro ),HDFS 为高吞吐连续访问数据场景设计,单独行更新或者随机访问性能差
  • 动态数据,半结构化方式存储(HBase,Cassandra),低延迟读写单独行,对 SQL 分析连续大量读取性能差

两类系统各有自己的优缺点,为了解决各自的问题,一种常用的做法就是 pipeline,比如 Kafka,在数据快速写入到 HBase 的同时通过 pipeline 将其导出给其他分析系统,这时又会遇到一致性等问题。

Kudu 本意上为了解决上面的问题,寻求一个结合点,在一个系统的一份数据中,Kudu 结合了 HDFS 和 HBase 的有点,既能够支持 OLTP 实时读写能力,又能支持 OLAP 的分析能力。Kudu 提供简单的插入,更新和删除,同时通过 table scan 来处理数据分析。

Kudu 解决方案

Kudu 提供 table 概念,每个 table 都有预先定义好的 schema,Schema 定义多个 column,每一个 column 有名字,类型,是否允许 NULL 等。column 组成 primary key。在使用 Kudu 之前用户必须先建立 table,可以通过 DDL 语句添加或者删除 column,但不能删除包含 primary key 的 column。Kudu 的数据模型和关系型数据库非常相似。

Kudu 提供两种一致性模型:snapshot consistency 和 external consistency. snapshot consistency 为默认方式,更好的读性能。external consistency 能够保证写入数据后,任何读取都能读到最新数据。

Kudu 使用 Raft 算法来保证分布式环境下面数据一致性。

Kudu 应用场景

  • 实时分析,数据更新实时体现在分析结果上,比如实时报表
  • 迭代计算,每次计算的结果需要修改数据集
  • 时间序存储,通过 hash partition 可以防止出现热点

架构

Kudu 采用 Master-Slave 形式的中心节点架构,管理节点叫做 Kudu Master,数据节点叫做 Tablet Server。表数据被分割为一个或者多个 Tablet,Tablet 部署在 Tablet Server 提供数据读写服务。

Master 作用

  • 作为 catalog manager,存放 Schema 信息,负责处理建表请求
  • 作为 cluster coordinator,管理 Tablet Server,在 Tablet Server 异常后协调数据重新部署
  • 作为 tablet directory,存放 Tablet 到 Tablet Server 的信息

master 存放集群所有的信息,当 client 需要读写时先请求 master,然后路由到对应 client,但这样 master 一定会成为瓶颈,所以 client 会缓存最近路由,当失效时才会从 master 获取

Kudu 的数据模型类似于关系型数据库,数据存储在结构化的表中。同时 Kudu 是一个分布式的存储引擎,数据最终会分成很多的 tablets 存储在不同的机器上,而表的 partition 则定义了数据会被放到哪些 tablet 中。在同一个 tablet 中,数据根据主键有序排列。

column schema

Kudu column schema :

  • 表包含多个 column,至少需要包含一个 key column(主键)
  • column 必须指定 name 和 type
  • column 还可以指定 encoding 方式和压缩方式

partition

Kudu 支持两种类型的 partition:rang 和 hash

  • range partition 需要指定 N 个 splits key,这些 key 将数据的 key 空间分成 N+1 块,每块都对应与一个 tablet。一个表只可以指定包含一个 range partition
  • hash partition 需要指定根据哪些 column 来进行 hash 分桶,以及分桶的个数 M。一个 table 可以指定多个 hash partition,但 paritions 的 key column 之间不能有重叠

最终 table 的 tablets 数目为 N*M

Kudu 的分区可以按照 Range 和 Hash 方式划分到不同的 Tablet。Hash Partition 数据较均匀的分布在 Tablet 中,原来的数据排序特点被打乱。Range Partition 数据按照用户指定的有序 Primary Key Column 的组合 String 顺序分区。

Tablet 在 Kudu 中被切分更小的单位,RowSets,只存在内存的叫做 MemRowSets,而另一些使用 disk 和 memory 共享存放,叫做 DiskRowSets,任何一行数据只存在一个 RowSets 中。

任何时候,一个 Tablet 仅有一个单独的 MemRowSet 用来保存最近插入的数据,后台线程定期将 MemRowSet 刷入 disk。之前的 MemRowSet 被刷入 disk 后变成 DiskRowSet,空出新的 MemRowSet。

reference


2019-01-14 kudu , apache , sql , hbase , oltp

登录式 shell 和非登录式 shell 区别

昨天在 Tmux 中使用 gpg 时遇到了一个问题,在别人的回答中看到了 login shell 和 non-login shell 的区别。在我的情况下终端中 bash 或者 zsh 都是能够使用 gpg 签名 git commit 的,但是在 tmux 下却报了错误。所以才有了这样一篇总结。

登录式 shell 是用户使用自己的 user ID 登录交互式 shell 的第一个进程。这里又要提及另外两个概念就是交互式 shell 和非交互式 shell,幸而这两个概念比较好理解。

  • 交互式 shell 指的是在终端有交互的模式,用户输入命令,并在回车后立即执行的 shell,这种模式也是大部分情况下用户执行的一种方式,比如 ssh 登录
  • 非交互式 shell 指的是 bash shell 以命令脚本的形式执行,这种模式下,shell 不会和用户有交互,而是读取脚本文件并执行,直到读取到文件 EOF 时结束

说完这两个区别,回到主题:

  • 当你在已经存在的终端 session 中开启一个 shell,比如在 screen, Tmux, X terminal 等中,会得到一个交互式,非登录 shell,这时 shell 会读取对应的配置(~/.bashrc for bash, /etc/zshrc and ~/.zshrc for zsh)
  • 当 shell 执行一个脚本,或者通过命令行将命令传送过去执行,这时就是非交互,非登录的 shell。这种 shell 无处不在,在程序调用另外一个程序时非常常见

有一种判断 login shell vs non-login shell 的非常快速的方法,使用命令 echo $0

  • -bash- 表示当前是一个 login shell
  • bash 表示不是 login shell

Why

至于为什么会有这么多的模式,是因为不同的模式读取的配置文件有所区别。

login shell 会读取不同的配置文件,比如 bash 会读取 /etc/profile~/.profile~/.bash_profile 等配置文件。而 zsh 会是 /etc/zprofile~/.zprofile

而 non-login shell 只会读取 ~/.bashrc 配置。

reference


2019-01-12 shell , linux , tmux , bash

使用 Huginn 搭建自己的 IFTTT

IFTTT, Zapier

  • 给不提供 RSS 输出的站点输出 RSS,使用免费版的 Feed43 体验不是太好,更新频率太低,不能全文输出
  • 监控价格变化
  • 监控豆瓣高分电影
  • 自动保存 Instagram 发布的照片

安装

单镜像运行调试

使用 Docker 是最方便的了

docker pull huginn/huginn

如果不想自己安装 MySQL 之类的数据库,这个镜像中包含了一个打包的数据库,直接 run 就行

sudo docker run -it --name huginn -p 3000:3000 --rm huginn/huginn

注意命令中的 --rm 当终止命令后容器会被删除,如果不想一次性使用不要使用该参数。如果想要在后台运行使用 -d 参数。

镜像连接本机数据库

假设在本机以及启动了一个 MySQL 实例,不想使用捆绑到镜像中的数据库那么可以在启动时指定环境变量。不过首先需要设置数据库的连接设置和权限,设置 /etc/mysql/mysql.conf.d/mysqld.cnf 设置监听地址为 0.0.0.0,然后使用 ifconfig 查看 docker0 的 IP 地址,一般为 172.17.0.1,那么给该 IP 访问数据库的权限,界面或者命令:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'172.17.0.%' IDENTIFIED BY 'pass' WITH GRANT OPTION;
flush privileges;

然后使用 Docker

docker run --name huginn \
    -p 3000:3000 \
    -e MYSQL_PORT_3306_TCP_ADDR=172.17.0.1 \
    -e HUGINN_DATABASE_NAME=huginn \
    -e HUGINN_DATABASE_USERNAME=root \
    -e HUGINN_DATABASE_PASSWORD=pass \
    huginn/huginn

使用

Agent

在 Agent 标签页会看到一系列的默认 Agent,Agent 可以理解为一系列不同类型的自动化任务,举一个简单的例子,这些 Agent 可以帮助抓取网页,或者读取 API,甚至监听文件变化等等。

每一个 Agent 在创建完成后会有下面一些指标:

Age: 表示这个事件创建了多久
Schedule: 表示的是间隔多长时间执行,从几分钟,到几天,到固定时间都有
Last Check: 表示上次执行时间
Last Event out: 表示上次任务执行输出
Last Event In: 表示上一次外部触发任务,比如输出的,需要由外部调用
Events created: 事件自创建后触发的数目

在创建 Agent 的时候有几个参数可以注意下:

  • Name 无需多数
  • Schedule 定义了默认的 Agent 执行频率
  • Controller 如果官方定义的执行频率无法满足需求,可以自定义 Agent 来控制该 Agent 的执行频率
  • Keep Event 表示保留该 Event 的时间长度,Huginn 会保留数据一段时间用来校验,这个参数可以定义过期时间
  • Source 表示当前 Agent 会收到来自这些 Agent 的事件
  • Receivers 表示该 Agent 创建的事件会传递给这些 Agent
  • Scenarios 用来组织一系列的 Agent,方便管理和分享
  • Options 是一个 JSON 串,这是 Agent 最最重要的部分,用来定义 Agent 的核心逻辑

这里将 Options 单独拿出来,这里举一个例子,比如抓取豆瓣高分科幻电影,这个 JSON 的整体格式大致如下:

{
  "expected_update_period_in_days": "2",
  "url": [
    "https://movie.douban.com/tag/%E7%A7%91%E5%B9%BB?type="
  ],
  "type": "html",
  "mode": "on_change",
  "extract": {
    "url": {
      "css": "td:nth-child(2) > div > a",
      "value": "@href"
    },
    "title": {
      "css": "td:nth-child(2) > div > a",
      "value": ".//text()"
    },
    "cover": {
      "css": "img",
      "value": "@src"
    }
  },
  "headers": {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36",
    "Host": "movie.douban.com"
  }
}

说明:

  • 这里的 URL 是要抓取的内容
  • type 指定类型可以选择 xml, html, json, or text
  • mode 表示获取数据的方式,有 all,on_change, merge
    • on_change 在数据更改时才会获取产生事件
    • merge 把新数据和输入数据合并
    • all 获取所有数据
  • extract 中主要提取标题,链接,内容等等

extract 中用的语法可以是 css 选择器,或者是 xpath 语法。等创建好,可以点击下面的 Dry Run 来测试是否运行正确。

实例

输出 RSS

如果要输出一个网站的 RSS,可能需要需要新建两个 Agent,一个 Agent 来抓取网站内容,一个用来导出数据。

第一步,首先要新建 Agent,然后选择 Website Agent. Website Agent 会去抓取网页,包括 XML 文档,JSON feed 然后根据结果来触发事件。

获取网页中部分信息,可以在 extract 中使用 CSS 选择器,选择网页中想要提取的部分,比如下方提取页面中 url 和 title

Options

{
  "expected_update_period_in_days": "2",
  "url": "http://wufazhuce.com/",
  "type": "html",
  "mode": "on_change",
  "extract": {
    "url": {
      "css": ".one-articulo-titulo/a",
      "value": "@href"
    },
    "title": {
      "css": ".one-articulo-titulo/a",
      "value": "normalize-space()"
    }
  }
}

第二步新建 Agent,选择,Data Output Agent,这个 Agent 用来输出 RSS 或者 JSON 内容。这个时候需要注意将上一个 Agent 填到 Sources 中,在 Options 中将上一个 Agent 获取到的变量填到对应的位置。

{
  "secrets": [
    "one"
  ],
  "expected_receive_period_in_days": 2,
  "template": {
    "title": "ONE RSS",
    "description": "RSS ",
    "item": {
      "title": " - ",
      "description": "",
      "link": ""
    }
  },
  "ns_media": "true"
}

保存之后,Agent 会暴露一个地址:

https://localhost:3000/users/1/web_requests/:id/:secret.xml

地址中的 :secret 是 Options 中设定的值,结尾可以是 xml 或者 json。 在 RSS 阅读器中订阅该地址即可。

微信公众号转 RSS

大致思路和上面 One 一样,找到入口,抓取内容,微信没有公开入口,所以只能送搜狗的入口来

https://weixin.sogou.com/weixin?type=1&s_from=input&query=%E5%8F%8D%E6%B4%BE%E5%BD%B1%E8%AF%84&ie=utf8&_sug_=n&_sug_type_=

从页面获取最新文章链接

{
  "expected_update_period_in_days": "2",
  "url": [
    "http://weixin.sogou.com/weixin?type=1&query= 反派影评 &ie=utf8&_sug_=n&_sug_type_=&w=01019900&sut=2064&sst0=1470553392399&lkt=0%2C0%2C0"
  ],
  "type": "html",
  "mode": "on_change",
  "extract": {
    "title": {
      "css": "#sogou_vr_11002301_box_0 > dl:nth-child(3) > dd > a",
      "value": ".//text()"
    },
    "url": {
      "css": "#sogou_vr_11002301_box_0 > dl:nth-child(3) > dd > a",
      "value": "@href"
    }
  }
}

然后根据上一步的 url 获取全文内容

{
  "expected_update_period_in_days": "2",
  "url_from_event": "",
  "type": "html",
  "mode": "merge",
  "extract": {
    "title": {
      "css": "#activity-name",
      "value": "."
    },
    "fulltext": {
      "css": "#js_content",
      "value": "."
    }
  }
}

最后和导出 RSS 一样,将内容部分导出即可。

huginn 例子

下面的网站提供了很多 huginn 实现的例子,对刚刚接触 Huginn 的人来说帮助很大。

官网有更多的例子

衍生

IFTTT 同类型的网站有很多,上面提及的 Zapier,还有这个开源版本的 Huginn,然后在用的过程中又发现了 integromat 这个站点。

reference


2019-01-11 huginn , ifttt

notion 使用记录

很早就有人推荐 Notion,但是注册了用了一下,本以为就是一个在线的 Google Docs,可昨天在豆瓣看到一篇文章介绍比 Trello 更加智能的代替品,然后一看就是 Notion,于是就再来研究下 Notion。然后发现原来 Notion 可以是 Google Calendar, 可以是 Trello,可以是 Google Docs,可以是 todo list,可以是 Google Excel。甚至可以导入 word,markdown,html,csv。

为什么是 Trello

因为受到推荐,所以第一时间找为什么可以作为 Trello 的代替品,于是我在 “New Page” 的页面中找到了 “Board” 的选项,Board 是 “Database with a kanban board view”,点开新建会创建一个 Board View, 这个 View 就和 Trello 很类似。

属性

这个看板虽然第一眼看起来不是很好看,但是功能却一点都不缺。和 Trello 不相同的是 Board 中每个一个 card 都有 property ,每一个 property 都可以定义一定的内容,而这个内容可以作为过滤条件,比如可以新建一个选择属性,然后起名字叫做 Priority,分别有三个属性值,High,Medium,Low,然后可以给每一个卡片赋一个值,那么在右上角就可以按照这个 Filter 来过滤卡片。虽然这个在 Trello 可以用 Q 快捷键来过滤 assign 给自己的卡片,但是却做不到 Board 的这么强的过滤属性。

属性的类型

  • Text
  • Number
  • 单项选择 Select
  • 多项选择 Multi-Select
  • Date
  • Person
  • Files&Media
  • Checkbox
  • URL
  • Email
  • Phone

高级属性

  • Formula compute a formula using other properties of a page
  • Relation allow pages in this database to reference pages in another
  • Rollup display and summarize data from a relation
  • Created Time
  • Created By
  • Last Edited Time
  • Last Edited By

分组

和 Trello 不相同的另外一点就是 Board 可以按照不同的属性来分组,通常情况下 Trello 只能按照 Todo,Doing,Done,来分组,但是如果 Board 增加了一些属性,那么 Group By 就可以按照属性来分组显示,比如按照 Priority 来分组显示。

为什么是 Google Docs

和 Google Docs 不同的是 Notion 中的 Page 可以插入不同的内容,包括普通的 Header,to-do list 等等,还包括外部的 Github, Video, Bookmark, Code, File, Google Maps, Framer, Invision 等等。

为什么是 Google Calendar

在 New Page 里面有 Calendar, 和 Google Calendar 一样,也可以在 Calendar 上创建新的任务,每一个任务都是 Page,可以在里面增加任何一个上面提到的属性。和上面提到的 Board 一样,过滤,排序等等。


2019-01-06 notion , trello , docs

Google Cloud Platform 使用向导

Google Cloud 提供 300 刀的初始优惠,而最近我的 Linode 节点越来越不稳定,时常撞墙,所以不得不再别人强烈推荐下注册了一下 GCP。这里就记录一下遇到的问题,其他具体的细节网上已经够多,就不再赘述。

关于信用卡

国内的信用卡不太清楚为什么我试了几个都有报错,网上说把账单地址改成美国,信用卡签名也最好保持一致。

区域选择

GCP 的 Compute Engine 在不同的机房都有分布,在创建 Compute Engine 的时候可以参考这里 这里非常详细的介绍了各个机房的地理位置,以及该机房拥有的机器类型,特性等。

网页版 SSH 切换身份

sudo -i
sudo su

使用 SSH 登录

默认情况下 Google 是禁止密码登录 SSH,我一般情况下会创建一个新用户

adduser xxx

然后给该用户提供登录权限

vi /etc/ssh/sshd_config

编辑

PasswordAuthentication yes

然后重启

service sshd restart

2019-01-06 google , google-cloud

html 转 pdf 命令行工具 wkhtmltopdf

最近因为用 HTML 写了一个文档,当想要输出时保存为 PDF,而 Chrome 自带的打印功能,本来就能够快速的保存为 PDF,但是却保留不了页面中的链接,所以找到了这个 wkhtmltopdf.

官网地址:https://wkhtmltopdf.org/

wkhtmltopdf and wkhtmltoimage are open source (LGPLv3) command line tools to render HTML into PDF and various image formats using the Qt WebKit rendering engine. These run entirely “headless” and do not require a display or display service.

简而言之,wkhtmltopdf 是一个能够把 HTML 文档,或者在线 url 转换为 pdf 文档或者 image 图片的命令行工具。跨平台,支持 Linux,Windows,Mac。

安装

有两种方法,一种是直接使用编译好的版本,下载 安装即可,一种是用源码 编译安装。

验证

wkhtmltopdf -V

查看版本。注意只有 qt 版本才能保留页面中链接。

命令格式

命令用法

wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>

实例

将 HTML 文件转换成 PDF

wkhtmltopdf a.html a.pdf

将 URL 保存为 PDF

wkhtmltopdf https://douban.com douban.pdf

把网页转换为图片同理

wkhtmltoimage a.html a.jpg
wkhtmltoimage https://douban.com douban.jpg

全局参数解析

--collate             当输出多个副本时进行校验(这是默认设置)
    --no-collate          当输出多个副本时不进行校验
    --cookie-jar <path>   从提供的 JAR 文件中读写 cookie 数据
    --copies <number>     设置输出副本的数量(默认主 1),其实为 1 就够了
-d, --dpi <dpi>           指定一个要分辨率(这在 X11 系统中并没有什么卵用)
-H, --extended-help       相对 -h 参数,显示更详细的说明文档
-g, --grayscale           指定以灰度图生成 PDF 文档。占用的空间更小
-h, --help                显示帮助信息
    --htmldoc             输出程序的 html 帮助文档
    --image-dpi <integer> 当页面中有内嵌的图片时,
                          会下载此命令行参数指定尺寸的图片(默认值是 600)
    --image-quality <interger> 当使用 jpeg 算法压缩图片时使用这个参数指定的质量(默认为 94)
    --license             输出授权信息并退出
-l, --lowquality          生成低质量的 PDF/PS , 能够很好的节约最终生成文档所占存储空间
    --manpage             输出程序的手册页
-B, --margin-bottom <unitreal> 设置页面的 底边距
-L, --margin-left <unitreal>   设置页面的 左边距 (默认是 10mm)
-R, --margin-right <unitreal>  设置页面的 右边距 (默认是 10mm)
-T, --margin-top <unitreal>    设置页面的 上边距
-O, --orientation <orientation> 设置为“风景 (Landscape)”或“肖像 (Portrait)”模式,
                                默认是肖像模块 (Portrait)
    --page-height <unitreal>   页面高度
-s, --page-size <Size>         设置页面的尺寸,如:A4,Letter 等,默认是:A4
    --page-width <unitreal>    页面宽度
    --no-pdf-compression       不对 PDF 对象使用丢失少量信息的压缩算法,不建议使用些参数,
                               因为生成的 PDF 文件会非常大。
-q, --quiet                    静态模式,不在标准输出中打印任何信息
    --read-args-from-stdin     从标准输入中读取命令行参数,后续会有针对此指令的详细介绍,
                               请参见 **从标准输入获取参数**
    --readme                   输出程序的 readme 文档
    --title <text>             生成的 PDF 文档的标题,如果不指定则使用第一个文档的标题
-V, --version                  输出版本信息后退出

reference


2019-01-05 html , pdf , linux , command

电子书

最近文章

  • Vim 插件之全局搜索:ack.vim 这篇文章看开始陆陆续续记录一下用过的 Vim Plugin,虽然有些一直也在用但从没有好好整理过,正好这篇开一个计划吧。
  • 我可能要抛弃用了很多年的 Chrome 换用 Vivaldi 大概一两年前就听说了 Vivaldi 这样一款浏览器,它使用 Chromium 做内核,创始人是从 Opera 浏览器出来的,不满 Chrome 横扫浏览器市场,没有给 Opera 一点喘息的机会,很多 Opera 的特性在 Chrome 上都被摘掉了。所以他们就开始搞了这一个 Vivaldi 浏览器,我记得当时听到的第一个宣传语是,快,想来 Chrome 最初打开市场时的宣传语也是快,但是多少年过去了 Chrome 虽然自身保持非常干净,但是加上自定义的扩展,也变得越来越臃肿了,但倒是也在一个可以接受的范围内。两年前 Vivaldi 依靠这一条宣传没有吸引到我,但是我也下载尝试,并且这两年来一直存在我的电脑中。我记得之前在我看来最大的缺点便是不能同步数据,而这个功能也在之前的更新中被加上了。所以今天就非常值得拿出来讲一讲。
  • 使用 port knocking 隐藏 SSH daemon 端口 暴露在互联网上的服务器非常容易被恶意程序进行端口扫描,以前也整理过一篇 VPS 安全设置 的文章,但都是一些比较基础的设置,能够绕过一些简单的端口扫描,但是并不能从根本上解决端口扫描的问题。
  • 威联通折腾篇十四:迁移系统盘 当时安装系统的时候就直接插入了一块硬盘,安装在了第一块机械硬盘上面,虽然读写也没有遇到什么瓶颈,但是记录以做备份,可以用于将系统迁移到 SSD 上。
  • Intellij IDEA 支持 jQuery 在 设置中进行如下操作开启 jQuery 支持: