HBase 基本使用

Hbase – Hadoop Database,是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文《Bigtable:一个结构化数据的分布式存储系统》。HBase 是 Google Bigtable 的开源实现,就像 Bigtable 利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了类似于 Bigtable的能力,利用 Hadoop HDFS 作为文件系统,利用 Hadoop MapReduce 来处理 HBase 中海量数据,利用 Zookeeper 作为协同服务,HBase是Apache的Hadoop项目的子项目,

HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是HBase基于列的而不是基于行的模式。

HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。HBase 不是关系型数据库,不支持 SQL。

Apache HBase™ is the Hadoop database, a distributed, scalable, big data store.

Use Apache HBase™ when you need random, realtime read/write access to your Big Data. This project’s goal is the hosting of very large tables – billions of rows X millions of columns – atop clusters of commodity hardware. Apache HBase is an open-source, distributed, versioned, non-relational database modeled after Google’s Bigtable: A Distributed Storage System for Structured Data by Chang et al. Just as Bigtable leverages the distributed data storage provided by the Google File System, Apache HBase provides Bigtable-like capabilities on top of Hadoop and HDFS.

HBase 结构

3维map,三个维度分别是

  • rowkey 主键
  • column 由 family:qualifier 两部分组成, family 列族,和 qualifier 来确定唯一的列
  • timestamp 数据写入时间戳

HBase的map是按照key来排序的, 其将key转换为byte[], 然后顺序进行存储.

  • 表名为字符串
  • Rowkey 和 ColumnName 是二进制 byte[]
  • Timestamp 是 64 位整数 Java 中 long 类型
  • value 是一个字节数组 byte[]

行主键 rowkey

行以 rowkey 作为唯一标示, rowkey 是一段字节数组,任何东西都能保存进去,字符串,数字等等。行按照字典序由低到高存储在表中。rowkey 可以是任意字符串,最大长度 64KB。

HBase 不支持条件查询和 Order by 查询,读取记录只能按照 rowkey 及其 range 或全表扫描,因此 rowkey 需要根据业务来设计以利用其字典序特性排序提高性能。

行的一次读写是原子操作,这个设计使得 HBase 的并发更新操作更加易懂。

列族和列 column family

列族是列的集合,要准确表示一个列,列族:列名 方式。列族(Column family)需要 在创建表时指定 ,列(Column)则不需要,可以随时在使用时创建。列族的成员在文件系统中都存储在一起,列族中所有列存储方式都一致。HBase 的每一个列都属于一个列族,以列族名为前缀,例如 A:aA:b 都属于 A 列族。

时间戳 timestamp

HBase 通过 row 和 column 确定一份数据(Cell),不同版本值按照时间倒序排序,查询时默认返回最新数据。存储的值根据 tableName + RowKey + ColumnKey + Timestamp => value 唯一确定。Cell 中数据没有类型,字节码存储。

每个保存的 Cell 数据都会保存多版本,版本通过时间戳来索引,时间戳由 HBase 在数据写入时自动赋值,时间戳为系统时间毫秒。如果客户端想要显示赋值也可以,每个Cell中,不同时间版本数据按照时间倒序排列,最新的数据排在最前。

为了避免数据存在过多版本造成的的管理 (包括存贮和索引)负担,HBase 提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本(比如最近七天)。用户可以针对每个列族进行单独设置。

基本使用

包括安装和基本使用

安装

Apache Download Mirrors 下载,从 stable 目录下下载 .tar.gz 的文件,比如 hbase-0.94.27.tar.gz

$ tar xfz hbase-0.94.27.tar.gz
$ cd hbase-0.94.27

安装依赖基础

  • Linux
  • JDK,需要 1.6及以上

确保 /etc/hosts 目录下

127.0.0.1 localhost
127.0.0.1 ubuntu.ubuntu-domain ubuntu

不要有 127.0.1.1 类似的出现,用 # 注释掉,如果有 ipv6 的地址也最好注释掉或者删掉。

编辑 conf/hbase-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>hbase.rootdir</name>
    <value>file:///DIRECTORY/hbasedata</value>
  </property>
  <property>
    <name>hbase.zookeeper.property.dataDir</name>
    <value>/DIRECTORY/zookeeper</value>
  </property>
</configuration>

配置其中的 hbase.rootdir 指向本地的目录,目录保存 HBase 的文件,HBase 会自动创建。 默认数据存储目录为 /tmp/hbase-${user.name} ,一旦重启Linux,数据就会丢失

编辑 conf/hbase-env.sh 文件,配置如下两项,找到本地 Java 安装目录,可以使用 whereis java 来获取,将 JDK 的根目录配置如下:

export JAVA_HOME="/usr/lib/jdk"
export HBASE_MANAGES_ZK=true

然后使用如下命令启动 HBase:

$ ./bin/start-hbase.sh

starting Master, logging to logs/hbase-user-master-example.org.out 单机模式启动,停止的脚本也在同目录下

连接 HBase

使用自带的客户端连接

$ ./bin/hbase shell
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell
Version: 0.90.0, r1001068, Fri Sep 24 13:55:42 PDT 2010
hbase(main):001:0>

初步熟悉

创建表,插入数据

hbase(main):003:0> create 'test', 'cf'
0 row(s) in 1.2200 seconds
hbase(main):003:0> list 'test'
1 row(s) in 0.0550 seconds
hbase(main):004:0> put 'test', 'row1', 'cf:a', 'value1'
0 row(s) in 0.0560 seconds
hbase(main):005:0> put 'test', 'row2', 'cf:b', 'value2'
0 row(s) in 0.0370 seconds
hbase(main):006:0> put 'test', 'row3', 'cf:c', 'value3'
0 row(s) in 0.0450 seconds

cf 为 column family 列族

可以使用 list 命令来查询表名

然后可以使用 scan ‘test’ 来查询

hbase(main):006:0> scan 'test'
ROW    COLUMN+CELL
 row1    column=cf:a, timestamp=1480648404221, value=value1
 row2    column=cf:b, timestamp=1480648416039, value=value2
 row3   column=cf:c, timestamp=1480648427572, value=value3
3 row(s) in 0.0450 seconds

也可以使用 get 命令

hbase(main):008:0> get 'test', 'row1'
COLUMN      CELL
cf:a        timestamp=1288380727188, value=value1
1 row(s) in 0.0400 seconds

删除记录

delete 方法只能删除 column

hbase(main):020:0> delete 'test', 'row2', 'cf:b'
0 row(s) in 0.0080 seconds

使用 deleteall 来删除 rowkey 的所有 column

hbase(main):001:0> deleteall 'test', 'row1'
0 row(s) in 0.3090 seconds

使用 disable 和 drop 来删除表

hbase(main):012:0> disable 'test'
0 row(s) in 1.0930 seconds
hbase(main):013:0> drop 'test'
0 row(s) in 0.0770 seconds

不清楚命令使用格式,可以使用 help "list" 来查看命令的具体使用帮助。

退出使用 exit

最后退出可以使用 ./bin/stop-hbase.sh 来停止 hbase。

其他问题

Mac 下尝试

Mac 下安装 HBase 可以参考这篇

http://chase-seibert.github.io/blog/2013/02/01/getting-starting-with-hbase-and-pig.html

其他问题

Hbase error zookeeper exists failed after 3 retries

16/12/02 10:45:28 INFO zookeeper.ClientCnxn: Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)

16/12/02 10:45:28 WARN zookeeper.ClientCnxn: Session 0x0 for server null, unexpected error, closing socket connection and attempting

配置

更多的配置可以参考

http://hbase.apache.org/0.94/book/configuration.html

standalone mode

Pseudo-Distributed mode

Distributed mode

reference


2017-02-16 HBase , Database , Apache

获取在线视频的时长

这是清理记事本的文章,解决一个问题之后,将之前整理的内容,整理发布。清空 WizNote 计划。

问题

手上有一些视频链接的 URL,如何快速的得到这些视频的时长信息?

答案

经过一番调研,发现使用 ffprobe (和 ffmpeg 套件一起) 可以完美解决这个事情。将命令 -i 参数后面的地址改成线上URL 地址即可。

ffprobe -i https://cldup.com/po79gkocrO.mp4 -show_entries format=duration -v quiet -of csv="p=0"

也可以将此代码保存为 get_video_duration.sh 来使用 ./get_video_duration.sh URL 这样的方式来跑。

ffprobe -i $1 -show_entries format=duration -v quiet -of csv="p=0"

具体 bash script, 文件中每一行中,前面为 视频ID,空格,再是视频连接,使用下面脚本,将视频时长保存到 duration.txt 文件中。

set -o nounset                              # Treat unset variables as an error
while IFS='' read -r line || [[ -n "$line" ]]; do
    lineArray=($line)
    echo ${lineArray[0]}
    duration=$(ffprobe -i ${lineArray[1]} -show_entries format=duration -v quiet -of csv="p=0")
    echo $duration
    echo "${lineArray[0]} ${duration}" >> duration.txt
done < "$1"

扩展

如果视频文件在本地的话,可能会方便很多, ffmpeg, ffprobe 都能够胜任。

ffmpeg -i input.mp4 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,//
# 或者
ffprobe -show_format input.mp4 | sed -n '/duration/s/.*=//p'

reference


2017-02-11 ffmpeg , ffprobe

Linux 下自动更新 Chrome

最近使用 Gmail 竟然告诉我“即将不支持此版本浏览器”,于是看了一样 Chrome 版本号 —- v52 , 感觉还很新啊,查了一下发现 Chrome 版本已经更新到了 v56。 但是 Linux 下 Chrome 不会自动更新, chrome://help/ 来查看也不会自动更新。所以搜索了一下,发现 Google 其实维护了自己的 Linux Repository

因为我是通过网站下载 GUI 安装的,所以没有自动更新的模块,添加 Chrome 的 source 即可。

添加 PPA 源

如果使用 PPA,则可以通过下面的命令,让 apt 每一次检查更新时将 Chrome 的更新带下来。

$ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
$ sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
# 如果是 64 位系统,则使用如下命令
$ sudo sh -c 'echo "deb [amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'

如果已经安装过 Chrome,则使用如下命令更新:

$ sudo apt update
$ sudo apt install google-chrome-stable

2017-01-27 Linux , Chrome , Google , APT

RESTful 接口

RESTful 为 Representational State Transfer 的缩写,拆分开这三个单词来就是:

  • Representational - REST resources can be represented in virtually any form, include XML, JSON, or even HTML 表现层,资源的表现形式
  • State - concerned with the state of a resource 状态,指的是互联网上资源的状态
  • Transfer - transferring resource data 转换,服务端/客户端的转换

Put more succinctly, REST is about transferring the state of resources in a representational form that is most appropriate for the client or server from a server to a client (or vice versa).

These HTTP methods are often mapped to CRUD verbs as follows:

  • Create — POST 新建资源,也可用于更新资源
  • Read — GET 获取资源
  • Update — PUT or PATCH 更新资源,PUT时客户端提供修改的完整资源,PATCH 为客户端提供改变的属性
  • Delete — DELETE 删除资源

什么是RESTful架构:

  1. 每一个URI代表一种资源;
  2. 客户端和服务器之间,传递这种资源的某种表现层;
  3. 客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”。

看到这里便可以回答:”PUT 和 POST” 的区别了 —- POST 用来新建资源,而 PUT 和 POST 都可以用来更新资源提交更新。

对于一个 HTTP 请求可以分成一下部分:

VERB is one of the HTTP methods like GET, PUT, POST, DELETE, OPTIONS, etc

URI is the URI of the resource on which the operation is going to be performed

HTTP Version is the version of HTTP, generally “HTTP v1.1” .

Request Header contains the metadata as a collection of key-value pairs of headers and their values. These settings contain information about the message and its sender like client type, the formats client supports, format type of the message body, cache settings for the response, and a lot more information.

Request Body is the actual message content. In a RESTful service, that’s where the representations of resources sit in a message.

对于一个 Http Response 可以分成一下部分:

HTTP Version

Response Code

Response Header

Response Body contains the representation if the request was successful

一些常见问题

API版本控制

将API版本放入 URI

https://api.example.com/v1

或者将版本信息放入 HTTP 头信息中。

以下是读 《Oreilly REST API Design Rulebook》 的一些笔记。

A Web API conforming to the REST architectural style is a REST API.

URI

格式

RFC 3986 * defines the generic URI syntax as shown below:

URI = scheme "://" authority "/" path [ "?" query ] [ "#" fragment ]

建议:

  • 使用前置的 “/” (forward slash separator) 来表达资源层级,在 URI 结尾不添加 “/”
  • 使用 Hyphens “-” 来增加可读性,不使用 Underscores “_”
  • 使用小写
  • 不使用 File extensions

Resource Archetypes

A REST API 有 4 种不同的资源原型( Resource Archetypes ) : document, collection, store and controller. 下面四种资源类型翻译出来不伦不类,直接原文反而比较容易明白。

  • A document resource is a singular concept that is akin to an object instance or database record. A document’s state representation typically includes both fields with values and links to other related resources.

  • A collection resource is a server-managed directory of resources. 服务端托管资源的目录

  • A store is a client-managed resource repository. 客户端管理的资源

    The example interaction below shows a user (with ID 1234) of a client program using a fictional Soccer REST API to insert a document resource named alonso in his or her store of favorites:

    PUT /users/1234/favorites/alonso
  • A controller resource models a procedural concept. Controller resources are like executable functions, with parameters and return values; inputs and outputs.

URI Path Design 路径设计

  • 单数名词用于 document
  • 复数名词用于 collection
  • 复数名词用于 store
  • 动词或者动词短语用于 Controller 名字
  • Variable path segments may be substituted with identity-based values
  • CRUD 名字不应该在URI中使用,而应该使用 DELETE /users/1234

URI Query Design 参数设计

  • The query component of a URI may be used to filter collections or stores

    比如 GET /users?role=admin

  • 用来分页

    GET /users?pageSize=25&pageStartIndex=50

Interaction Design with HTTP

REST API 使用 HyperText Transfer Protocol , version 1.1 (HTTP/1.1) , 包括:

  • request methods
  • response codes
  • message headers

RFC 2616 defines the Status-Line syntax as shown below:

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

Request Methods

请求的方法区别:

The purpose of GET is to retrieve a representation of a resource’s state. HEAD is used to retrieve the metadata associated with the resource’s state. PUT should be used to add a new resource to a store or update a resource. DELETE removes a resource from its parent. POST should be used to create a new resource within a collection and execute controllers.

需要注意:

  • GET and POST must not be used to tunnel other request methods
  • GET must be used to retrieve a representation of a resource
  • HEAD should be used to retrieve response headers
  • PUT must be used to both insert and update a stored resource
  • POST must be used to create a new resource in a collection
  • POST must be used to execute controllers
  • DELETE must be used to remove a resource from its parent
  • OPTIONS should be used to retrieve metadata that describes a resource’s available interactions

Response Status Codes 返回码

Category Description 分组描述

1xx: Informational Communicates transfer protocol-level information.

2xx: Success Indicates that the client’s request was accepted successfully.

3xx: Redirection Indicates that the client must take some additional action in order to complete their request.

4xx: Client Error This category of error status codes points the finger at clients. 客户端请求错误

5xx: Server Error The server takes responsibility for these error status codes. 服务器内部错误

具体的状态码:

  • 200 表明成功, response 需携带 response body
  • 201 Create 表示资源创建成功
  • 202 Accepted 用于表示成功开始了异步动作
  • 204 No Content,通常用于 PUT,POST,和 DELETE 请求的response,如果 GET 返回结果为空,通常也用204
  • 301 “Moved Permanently”,通常应该在返回结果 header 中包含 Location 重定向的请求地址
  • 302 (“Found”) should not be used
  • 303 “See Other” refer the client to a different URI
  • 304 Not Modified preserve bandwidth , client already has the most recent version of the representation
  • 307 Temporary Redirect tell clients to resubmit the request to another URI
  • 400 Bad Request may be used to indicate nonspecific failure,客户端请求错误
  • 401 Unauthorized,must be used 客户端无授权,令牌,密码等无验证
  • 403 Forbidden,should be used to forbid access regardless of authorization state
  • 404 Not found,must be used when a client’s URI cannot be mapped to a resource 不存在该记录
  • 405 (“Method Not Allowed”) must be used when the HTTP method is not supported
  • 406 Not Acceptable,must be used when the requested media type cannot be served
  • 409 Conflict should be used to indicate a vialation of resource state
  • 412 Precondition Failed should be used to support conditional operations
  • 415 Unsupported Media Type must be used when the media type of a request’s payload cannot be processed
  • 500 Internal Server Error should be used to indicate API malfunction

Metadata Design

HTTP Headers

  • Content-Type must be used

  • Content-Length should be used, Content-Length header 给出了整个 body bytes 大小,给出他的理由有两个:1. 客户端可以检查是否读取完整的大小 2. 客户端可以通过 HEAD 请求来得知整个body 的大小,而不同下载。

  • Last-Modified should be used in responses

  • ETag should be used in responses ETag是HTTP协议提供的若干机制中的一种Web缓存验证机制,并且允许客户端进行缓存协商。 这就使得缓存变得更加高效,而且节省带宽。 如果资源的内容没有发生改变,Web服务器就不需要发送一个完整的响应。 ETag也可用于乐观并发控制,作为一种防止资源同步更新而相互覆盖的方法。

  • Location must be used to specify the URI of a newly created resource

  • Cache-Control, Expires, and Date response headers should be used to encourage caching

Media Types

Media Type 有如下语法:

type "/" subtype *( ";" parameter )

type 的值可以有: application, audio, image, message, model, multipart, text 和 video.

A typical REST API will most often work with media types that fall under the application type.

text/plain

A plain text format with no specific content structure or markup. ‡

text/html

Content that is formatted using the HyperText Markup Language (HTML). §

image/jpeg

An image compression method that was standardized by the Joint Photographic

Experts Group (JPEG). ‖

application/xml

Content that is structured using the Extensible Markup Language (XML). #

application/atom+xml

Content that uses the Atom Syndication Format (Atom), which is an XML-based

format that structures data into lists known as feeds. *

application/javascript

Source code written in the JavaScript programming language. †

application/json

The JavaScript Object Notation (JSON) text-based format that is often used by

programs to exchange structured data. ‡

Media Type Design

Client developers are encouraged to rely on the self-descriptive features of a REST API.

Representation Design

REST API 通常使用 response message 的 body 来传递资源的状态。 REST APIs 通常使用文本格式来表示资源。

  • JSON should be supported for resource representation

Client Concerns

Versioning

  • 使用新的 URIs
  • Schemas
  • Entity tags

Security

  • OAuth

CORS(Cross-origin resource sharing 跨域资源共享) should be supported to provide multi-origin read/write access from JavaScript,克服了 AJAX 只能同源使用资源的限制。

Access-Control-Allow-Origin

该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

Access-Control-Allow-Credentials

该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

Access-Control-Expose-Headers

该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。

CORS 请求默认不发送 Cookie 和 HTTP 认证信息,如果想要把 Cookie 发送到服务器,一方面要服务器同意,指定 Access-Control-Allow-Credentials 为 true。

调试 RESTful 接口

接口调试工具 Postman https://www.getpostman.com/

其他工具


2017-01-10 Web , API , RESTful

修复 Linux mint 下 sogou 输入法

记录一下 Linux 下 Sogou 输入法失效的问题,以及解决修复过程。 Linux 真是太难折腾了,一些配置总是太乱,没有文档,没有集中的 Q&A ,导致使用过程非常困难,一些基础设施都很难用。当然如果调教的好,也是能够非常高效的。比如解决了这个基础打字问题之后的这篇文章就是在 Linux Mint 下完成的。

问题描述

不知道是系统升级还是因为输入法升级,(可在我印象中完全没有做任何干扰到输入法的事情),搜狗输入法 Linux 版,就这么挂掉了,而其他设置一切正常,其他的输入法也都一切正常,但是实在无法用的过来, RIME没有一个可更新的词库,google pinyin 也是词库不全,使用起来总还是不太方便,虽然 sogou 输入法在 Linux 下有些问题所在,但是还是相对来说比较好用的,但是它就这么挂了。

解决过程

在刚开始的时候以为是 Fcitx 的问题,卸载 sudo apt remove fcitx,重装,登入登出好几回,发现并没有任何用,期间也尝试使用过 iBus,但是实在无法使用。

最后在网上查阅问题的时候,发现 搜狗输入法在系统的 ~/.config 下会有三个配置文件夹,包括

  • SogouPY
  • SogouPY.user
  • sogou-qimpanel

将此三文件夹,移动位置,或者删除,重新安装搜狗输入法,登出,登录,即可。


2017-01-03 Linux , Linux Mint , Sogou

Samba 使用

Samba,是种用来让UNIX系列的操作系统与微软Windows操作系统的SMB/CIFS(Server Message Block/Common Internet File System)网络协议做链接的自由软件。1 Samba能够为选定的Unix目录(包括所有子目录)创建网络共享。该功能使得Windows用户可以像访问普通Windows下的文件夹那样来通过网络访问这些Unix目录。

命令

smbd

启用 smb

sudo service smbd start

Samba 进程,使用 -D 参数开启守护进程。

或者

sudo /etc/init.d/samba start

smbpasswd

smbpasswd 命令属于 samba ,能够实现添加或删除samba用户和为用户修改密码。

语法

smbpasswd [option] [username]

smbpasswd(选项)(参数) 选项

-a:向smbpasswd文件中添加用户;
-c:指定samba的配置文件;
-x:从smbpasswd文件中删除用户;
-d:在smbpasswd文件中禁用指定的用户;
-e:在smbpasswd文件中激活指定的用户;
-n:将指定的用户的密码置空。

用户名:指定要修改SMB密码的用户。

添加用户

首先在 /etc/passwd 中添加一条,按照此格式:用户名:密码:uid:gid:用户描述:主目录:登陆shell

einverne:*:1000:65534:einverne:/var:/bin/false

然后添加 Samba 用户:

smbpasswd -a einverne

修改用户密码

smbpasswd einverne

配置

文件地址 /etc/samba/smb.conf

[global]
    netbios name = OpenWrt 
    display charset = UTF-8
    interfaces = 127.0.0.1/8 lo 192.168.1.1/24 ipv6 address/60 br-lan 
    server string = OpenWrt Samba Server
    unix charset = UTF-8
    workgroup = WORKGROUP	# Windows 默认
    browseable = yes
    deadtime = 30		# This is useful to stop a server's resources being exhausted by a large number of inactive connections
    domain master = yes
    encrypt passwords = true
    enable core files = no
    guest account = root
    guest ok = yes
    #invalid users = root
    local master = yes
    load printers = no
    map to guest = Bad User
    max protocol = SMB2
    min receivefile size = 16384
    null passwords = yes
    obey pam restrictions = yes
    os level = 65
    passdb backend = smbpasswd
    preferred master = yes
    printable = no
    security = user
    smb encrypt = disabled
    smb passwd file = /etc/samba/smbpasswd
    socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=40960 SO_SNDBUF=40960
    syslog = 2
    strict allocate=no
    use sendfile = yes
    writeable = yes
    large readwrite = yes
    aio read size = 40960
    aio write size = 40960
    read raw = yes
    write raw = yes

# 创建了一个 Share 名为 OpenWrt
[OpenWrt]
    path = /mnt/sda1			# 目录
    valid users = root			# 允许root读写操作
    read only = no				# 允许写
    guest ok = no				# 不允许匿名
    create mask = 0777			# 新文件权限
    directory mask = 0777		# 新文件夹权限

配置参数

正如上面提到的,创建一个新的 名为 Openwrt 的共享,需要有些配置,有些配置看名字就能够看出,但是有一些有些复杂。

如果想要创建一个只读的,任何人都可以访问的分享:

[Share]
    path = /media/movie
    comment = this is folder sync from bt
    read only = yes
    guest ok = yes
    create mask = 0777			# 新文件权限
    directory mask = 0777		# 新文件夹权限

参数:

  • create mode – 这个配置定义新创建文件的属性。Samba在新建文件时,会把dos文件的权限映射成对应的unix权限,在映射后所得的权限,会与这个参数所定义的值进行与操作。然后再和下面的force create mode进行或操作,这样就得到最终linux下的文件权限。
  • force create mode – 见上面的描述。相当于此参数所设置的权限位一定会出现在文件属性中。
  • directory mode – 这个配置与create mode参数类似,只是它是应用在新创建的目录上。Samba在新建目录时,会把dos–>linux映射后的文件属性,与此参数所定义的值相与,再和force directory mode相或,然后按这个值去设置目录属性。
  • force directory mode – 见上面的描述。相当于此参数中所设置的权限位一定会出现在目录的属性中。
  • 说明一点,上面的create mode和create mask参数是同义词,用哪个都可以;而directory mode和directory mask参数是相同的。

reference


2016-12-27 Samba , SMB , Openwrt , Linux

2016年读书笔记

又到了一年的年末,翻开去年的记录,吃惊的发现去年竟然只看过16本。今年年初的时候,计划阅读100本书,也的的确确一直坚持了一年,中途可能因为工作耽误了一些进度,但也一直坚持到现在。然而遗憾的是到目前为止,距离2016年结束还有短短一个礼拜的时候,又发生了和去年一样的问题,欠下了10本左右的债。

耳边总有人说,“为什么总要在意那几个数字?”,而对我而言,那不仅仅是那几个数字,他是年初的一句承诺,对整个年度的一句承诺,如果不能达到这个承诺,那过去说过的话还有什么意义。

今年的书单印证了一句话“因为一本书,爱上一个人,迷上一个类型”,我也曾经在 G+ 上说过,多少年了,还是在三年级到初中的那段时间疯狂的迷过Verne,多少年的时间里因为学业,因为各种,再难爱上一位作家,再难爱上一段文字。而今年因为一本《解忧杂货铺》让我知道了东野圭吾,也打开了我认知的另一扇窗户。今年的近90本中有很大一部分都是东野的作品。而有趣的事,和东野的经历一样,让我们结识悬疑推理的经历竟然如此的相似,这一段经历可以参考《我的晃荡的青春》,东野的青春竟然也如此的淘气和真实。

而我从年初,从东野最著名的小说开始读《嫌疑人X的献身》、《白夜行》在到加贺恭一郎系列,再甚至到不怎么出名,甚至默默无闻的早期作品《以眨眼干杯》《沉睡森林》,再到毒舌三部曲《毒笑小说》《黑笑小说》《怪笑小说》,东野圭吾的书读不到尽头也几乎没有重复,这让我佩服的五体投地。

按时间排序读过

  • 解忧杂货铺 五星
  • 白夜行 五星
  • 空中杀人现场,短篇,四星
  • 嫌疑人X的献身,五星
  • 秘密 五星
  • 放学后 四星
  • 恶意 五星
  • 流星之绊 五星
  • 彷徨之刃 五星,强烈推荐
  • 幻夜 四星
  • 信 五星
  • 单恋 四星
  • 时生 四星
  • 名侦探的守则 四星
  • 圣女的救济 五星
  • 宿命 四星
  • 超杀人事件 五星,短篇可以看看
  • 名侦探的诅咒 四星
  • 浪花少年侦探团 四星
  • 再见了忍老师 四星
  • 十一字杀人 四星
  • 没有凶手的杀人夜 四星
  • 分身 四星
  • 同级生 四星
  • 只差一个谎言 四星
  • 祈祷落幕时 四星
  • 虚无的十字架 五星
  • 湖畔杀人事件 四星
  • 布鲁特斯的心脏 三星
  • 毒笑小说 五星
  • 从前我死去的家 四星
  • 新参者 五星
  • 黑笑小说 五星
  • 天空之蜂 四星
  • 美丽的凶器 四星
  • 濒死之眼 四星
  • 杀人之门 四星
  • 以眨眼干杯 四星
  • 毕业 四星
  • 学生街杀人 四星
  • 我的晃荡的青春 四星
  • 红手指 四星
  • 谁杀了她 四星
  • 怪人们 四星
  • 麒麟之翼 四星
  • 梦幻花 四星
  • 变身 五星
  • 假面饭店 四星
  • 天使之耳 五星
  • 沉睡的森林 四星

今年的书摘如果都放到这边可能有些多,甚至没有什么必要,有些内容经过整理和摘录,我都放到了 Evernote 。有些比较长的内容,也有格式化。

其他小说

  • 围城,毕竟有些年代,不过依然值得一读
  • 追风筝的人,带领我走进阿富汗
  • 灿烂千阳,追风筝同作者的书,依然讲述阿富汗的故事
  • 岛上书店,毕竟畅销书,明年可以按比例提高产销书比例

技术

但回头看自己今年的书单,深感技术类书籍占比略少,去年至少系统的看过 Bash,和基础 Linux,而今年除了看一些基础的 Java 知识,再没有系统地学习一项内容,除了年末恶补了一些 Spring MVC 和 Redis, HBase 的相关知识。因此在制定明年的计划时要讲技术书籍内容比例提高到10%左右,有些书值得反复阅读思考和实践,技术类的书既有消费品也有值得反复品味的内容。

今年读过的技术类书:

  • Effective Java 五星,所有Java编程者都应该读一读
  • Java 与 模式,稍显啰嗦,但是讲的非常细致
  • Maven 实战,熟悉 Maven 入门速成
  • Redis 入门指南,入门书籍,不讲求细节和实现原理
  • 其他的都没有完整的读完,明年一定要提高一定的比率。

摄影

而其他摄影的类:

  • 摄影师的视界,迈克尔弗里曼摄影构图与设计,讲构图的书,还是值得一看,只是还没有来得及实践
  • 穿透黑暗夜景和暗光摄影,匆匆读过,夜间摄影还是需要一些技巧
  • 昨天的中国,在学校法盟偶然遇见的一本纪实摄影,顶赞

设计

  • 设计准则,第一次参加读书会时借阅的书,讲到一些日常生活中的设计,当要装修的时候再参阅
  • 设计心理学

其他

  • 人在欧洲,真的是讲人在欧洲的一些见闻和思考感悟
  • 民主的细节,五星强烈推荐
  • One Billion Customers ,五星强烈推荐
  • 黑客与画家,其实早读过,今年又翻出来推荐给一些人
  • 乖,摸摸头,小故事,有人说的”鸡汤“
  • 秦始皇的秘密,也是听人推荐一口气读完的,当故事看吧
  • 断舍离,整理啊
  • 怦然心动的人生整理魔法 1,2 第一部比较笼统,第二部比较仔细,第二部中的衣服整理法则好好
  • 从你的全世界路过,畅销书,小故事看吧
  • TED 演讲的8个秘诀
  • 失控,大部头的书,好像就记得蜜蜂了。
  • 三人行,第一次见到那么排版的书籍, 针对同一个主题,两岸三地不同世界的人不同的故事。

还有一些就不列了。


2016-12-22 book , reading

更新隐私政策

今天突然收到 Google Play Store 发来的邮件通知,说违反社区准则,原因是没有隐私政策说明。全文如下:

Our records show that your app, {Application Name}, with package name {package name}, currently violates our User Data policy regarding Personal and Sensitive Information.

Policy issue: Google Play requires developers to provide a valid privacy policy when the app requests or handles sensitive user or device information. Your app requests sensitive permissions (e.g. camera, microphone, accounts, contacts, or phone) or user data, but does not include a valid privacy policy.

Action required: Include a link to a valid privacy policy on your app’s Store Listing page and within your app. You can find more information in our help center.

Alternatively, you may opt-out of this requirement by removing any requests for sensitive permissions or user data.

仔细研读几遍之后发现其实只要增加一条链接,说明一下隐私政策。其实主要的原因就是应用中使用到了 android.permission.GET_ACCOUNTS,android.permission.READ_CONTACTS 这俩权限,都是 Firebase SDK 里卖弄登陆要用到的。

仔细研究了一番 Google 的隐私政策Instagram 的隐私政策

然后随着大概意思拷贝了一份


2016-12-21 Privacy

pdnsd 使用

Pdnsd 是用来缓存本地DNS信息的 DNS 服务器。和 BIND 和 dnsmasq 相比,Pdnsd 在重启之后依然可以保存 DNS 缓存,名字中的 p 表示 persistent。

Installation

Ubuntu/Debian 系下使用如下命名安装:

sudo apt install pdnsd

Configuration

默认配置地址 /etc/pdnsd.conf

下面配置示例,后面的分号不可缺少。

配置示例:

global {                                                                        
        perm_cache=1024;        # 要缓存多少DNS信息                                                
        cache_dir="/var/pdnsd";                                                 
#       pid_file = /var/run/pdnsd.pid;                                          
        run_as="nobody";                                                        
        server_port = 1053;                                                      
        server_ip = 127.0.0.1;  # Use eth0 here if you want to allow other       
                                # machines on your network to query pdnsd.       
        status_ctl = on;                                                         
#       paranoid=on;       # This option reduces the chance of cache poisoning   
                           # but may make pdnsd less efficient, unfortunately.   
#       query_method=udp_tcp;                                                    
        query_method=tcp_only;  # 使用 TCP 方式去查询 DNS 服务器                                                 
        min_ttl=15m;       # Retain cached entries at least 15 minutes. 缓存 DNS 最短有效期         
        max_ttl=1w;        # One week. 缓存 DNS 信息最长有效期                                           
        timeout=10;        # Global timeout option (10 seconds).                 
        neg_domain_pol=on;                                                       
        udpbufsize=1024;   # Upper limit on the size of UDP messages.            
}                                                                                

server {                                                                         
    label= "googledns";                                                          
    ip = 8.8.8.8, 8.8.4.4;                                                       
    timeout=30;                                                                  
    interval=30;                                                                 
    root_server = on;                                                            
    uptest = ping;                                                               
    ping_timeout=50;                                                             
    purge_cache=off;                                                             
    exclude=.cn, .douban.com, .taobao.com                                         
}             

Pdnsd 读取配置时,优先级从上到下,上面的 DNS 服务器配置优先于下一层。

DNS servers

pdnsd 需要至少知道一个上游 DNS 服务器用来收集信息

  • label,用来标示服务器,随意,但最好写上服务器名字
  • ip,DNS 服务器地址,可以分多行,也可以使用逗号分割

/etc/resolve.conf 中指定了一些DNS服务器地址,在配置 pdnsd 的时候,修改为

nameserver 127.0.0.1

测试

启动 pdnsd 服务

/etc/init.d/pdnsd start 
nslookup www.douban.com 127.0.0.1

或者

dig @localhost -p port www.douban.com

如果返回正常,和 webdnstools 比照,则说明配置成功

清空本地缓存

sudo pdnsd-ctl dump   # Print information stored in the cache about name.
sudo pdnsd-ctl empty-cache

查看端口占用

sudo netstat -anp | more

pdnsd 只能优化 DNS 解析,并不能避免 DNS 污染

reference


2016-12-19 Linux , DNS , pdnsd

笔记整理法则

最近 Evernote, WizNote 纷纷宣布收费,一时间让我手足无措,原本按部就班的一些流程纷纷被打破。但是笔记和摘录总是那样的顺其自然,在翻看自己曾经摘录过得一些整理法则的时候,发现其中有些问题确实自己也已经犯下,在电脑玩物的《Evernote 超效率数位笔记术》书中,作者总结了“Evernote 用户最容易犯的10个错误[^1]”:

  1. 无目的的存储。收集资料的目的性是非常重要的,所谓的目的应该紧紧围绕自身的现实需要,如果漫无目的地搜集,将来使用到的几率是非常低的,对于你自身的提高和发展毫无裨益。
  2. 过度分散。这个可能在利用Evernote当做GTD执行系统中出现。
  3. 不愿意舍弃。参考“断舍离”整理法,需要放弃“把东西占为己有的观念”,现在能够收集到的有价值的资料一定会在网络上更新与流通保存,你一定能够在网络上再次找到需要用到的时候才去寻找,能够得到更新更准确的资料。不会过期的资料便是你自己的心得、感想、经验与故事。笔记本不是仓库,而是用于行动的工具,收纳的东西越少,你的人生就越轻松。
  4. 笔记之间不流动。可以参考建立笔记中枢的做法。
  5. 笔记方式太枯燥。有的时候拍照或者录音会更方便快捷。
  6. 没有在行动中使用
  7. 过度在意版面编排。需要专注于笔记内容,舍弃其他多余的东西。
  8. 停留在文档处理思维。放弃处理文档时候细琐、分散、独立的思维,需要更多的整理沟通。
  9. 没有把记忆交给Evernote。没有形成一有想法就记录下来的习惯,是没有办法真正释放记忆的压力,也就不用说用好Evernote了。
  10. 过度整理。笔记的整理时一个长期的过程,也需要根据自己的实际需要来增加或者删减内容,不需要苛求一开始就整理得漂亮详细,一切都需要根据实际需要来进行操作,目的是为了以后能够用到。如果不能用到,便是在做无用功。

对于这些错误,最严重的就是第一条,因为 Evernote 和 WizNote 的网摘插件实在太好用,在摘录了大片的内容之后,就忘记整理总结,躺在笔记本中就“死亡”了。幸而这些天这么折腾让我想起了那些笔记墓地,也正好抽出时间来整理一下。正像最后写的那样,”笔记是为了在以后用到,如果用不到,那便是在做无用功”。

建立合理的分类

早之前就总结过分类和标签,这两者在使用上还是有些区别的,最直观的区别就是一篇笔记只能属于一个分类,而可以归属于多个标签。分类是方便我们整理,而标签是便于我们检索和记忆,同样分类是给我们自己看的,而标签是给机器看的。因而建立一个合理的分类是非常必要的。之前看电脑玩物使用标签整理法,在我个人使用一段时间之后便放弃了,转而使用分类管理,而在过程中打上标签。

根据自己的使用,可以将笔记划分为不同的分类:

  • Notes 通用的未处理笔记,包括大部分文摘,网摘
  • Archive,归档,当笔记无法分类时,归到此类,处理完之后归档
  • 读书笔记,看书时做的记录,通常一本书一篇
  • 豆瓣影评,电影观后感,或者电影相关资料
  • 蜂窝游记,平时有些游玩准备,或者游记,图片之类
  • 微信收藏,微信公众号中值得看第二遍的内容
  • 我的邮件,通过邮件收藏的内容,通常由 InoReader 中内容发送过来
  • 购物清单,又包括许多子分类

等等分类,每篇文章,在未处理之前都在未分类中,在处理完之后都有自己的归属。

标签管理

这里使用购物清单来作比喻,对于使用记事本来做类似 TODO list 这样的事情来说,没有比使用标签来得更加方便的事情。大部分人可能已经习惯了 List 这样的 Todo 清单,但是对于一件需要长期进行的计划来说,单一的清单可能已经完全不能满足需求。因此才出现了 Trello 这样的多Board 的清单列表。而对于记事软件比如 Evernote 或者 Wiznote 来说,没有了 Trello 这样的多列待办清单,使用 Tag 来模拟也是可以轻易的实现的。

我的标签命名方式从电脑玩物学来,使用如下:

  • !01.GTD
  • !01.重要
  • !02.今日事
  • $02.Shopping
  • $01.想要
  • $02.调查
  • $03.不需要
  • $04.满足

对于这样的分类能够一目了然并且能轻松快速的找到想要的内容。而使用“!”这样的方式不仅增加了趣味,也让标签更加形象,”$” 就表示和购物相关。

而对于购物清单的子标签中分成想要,调查,不需要,满足四个标签,对于我自己,当在平时浏览网页,阅读RSS,或者好友推荐,甚至广告中获取某一个产品时,优先添加到想要的标签中。而第二个调查标签为自己在调查想要的产品时可能主动浏览或者搜索的重要内容。而调查的内容可能有两种归宿,一种是在调查过程中发现确实不需要,最后将内容添加到不需要中,另外一种就是为最后列出了需要购买的几点理由,而不得不买时,将内容拖到满足中,并完成购物。当且仅当物品出现在调查中,并且有几点强烈需求时才能将其拖入到满足中。

对于文档标题,使用物品内容+型号+价格来标识。对于同一件物品使用尽量同一个文档来保存。比如文档” Dji Marvic Pro 6999“ 在想要中记录。然后可能会调查他的摄像分辨率,飞行高度等等参数然后记录。当然最重要的是列出需要购买的理由,不单纯仅限于玩一玩啊。

reference

[^1]: http://www.haiyue.info/pc-player-evernote-taking-notes.html


2016-12-18 Evernote , WizNote

Google+

最近文章

  • vim presentation 大纲
  • Vim 寄存器 Vim 的寄存器可以看成 Vim 中额外用来存储信息的区域,虽然看不见,但是如果使用 x, s, y, p 等等命令的时候都无意识的使用到了 Vim 的寄存器(register).
  • vim normal 命令 替换::%s/^/#/g visual block:ggI# 注释第一行后用.重复执行每一行 我们可以在第三种方法之上用normal命令实现上述需求,步骤:
  • Vim 中的宏命令 Vim 的设计哲学中有这样一句话:”if you write a thing once, it is okay. However if you’re writing it twice or more times, then you should find a better way to do it”.
  • headless chrome puppeteer Headless 最早的时候在 PhantomJS 听说过这个概念,后来在 GitHub 各种项目中总有人不断提起这个概念,而最新看到的新闻便是 Chrome 开始支持 Headless,也正激起了我了解的欲望。