fastboot and adb 工具

早之前曾经写过过一篇文章总结 adb 的常用命令,这次刷机也复习了一些命令,这里再补充一下刷机中必不可少的 fastboot 命令。

就像之前adb中说过的那样, adb 用来向开机的 Android 设备发送指令,而 fastboot 则是向开机的 Android bootloader 来发送指令,因此在刷机过程中,如果手机重启进入 bootloader 基本之后使用的 命令都离不开 fastboot。比如在安装第三方 recovery 时,要用到 fastboot flash recovery recovery.img 这样的指令。虽然不能依靠此命令来刷入ROM,但是 fastboot 也能够做一些 adb 命令无法实现的功能。

bootloader

关于 bootloader 部分可以参考 之前的文章

fastboot

adb 和 fastboot 两个工具都是跟随着 Android SDK 分发的,但是由于这两个工具需求过高,Google 单独提供了两个工具集的下载

在下载之后,需要将文件路径添加到系统环境变量中,以便于在各个路径下访问。

假设加压后的路径为 ~/Android/Sdk/platform-tools/, 那需要在 ~/.bashrc 或者 ~/.zshrc 中配置。

export PATH="$PATH:/home/einverne/Android/Sdk/platform-tools"

WIndows 同理,在系统配置环境变量。

然后在终端下使用 adb devices ,就能够查看连接的设备。同样在 bootloader 下,也可以使用 fastboot devices 来查看连接设备,如果未出现已经USB连接的设备,查看驱动是否安装完好即可。


2017-02-25 Android , Fastboot , adb

Android 反编译

本文介绍 Android 反编译工具,只介绍工具名字及工具简单使用,详细开来再具体讲吧。本文主要包含工具的作用,工作的简单用法,以及反编译的基本步骤。

概述

反编译 Android APK 主要需要依靠如下几个工具:

  • apktool:A tool for reverse engineering Android apk files 查看 APK 包中的 AndroidManifest.xml 等 XML 资源文件
  • dex2jar:Tools to work with android .dex and java .class files 将 APK 包中的 Dalvik 字节码文件(.dex)转换为 .jar 文件
  • JD-GUI:Java Decompiler is a tools to decompile and analyze Java 5 “byte code” and the later versions 查看 .jar 文件的 Java 源码

相关项目及工具地址后文贴出。

使用方法

apktool

Apktook 是一个反编译(reverse engineering) 工具,可以用来反编译Android APK。几乎可以将APK中的 resources.arsc, classes.dex9.png 以及 XMLs 等等源文件反编译得到。

安装需要:

  1. JRE 1.7 及以上
  2. 关于 Android SDK, AAPT 以及 smali 的基本知识

地址: https://ibotpeaches.github.io/Apktool/

安装

各平台的安装指南,如果使用 Linux 可以使用如下简易步骤:

  1. 右击链接 将 Linux 的脚本保存为 apktool,并移动到 /usr/local/bin/ 目录下
  2. 下载最新版本 apktool.jar (https://bitbucket.org/iBotPeaches/apktool/downloads/)
  3. 确保 Linux 64 位系统中安装了 ia32-libs,使用 apt search ia32 ,然后 apt install ia32-libs 安装,可跳过
  4. 将下载的 apktool-x.x.x.jar 重命名为 apktool.jar
  5. apktool.jarapktool 移动到 /usr/local/bin/ 目录中,需要 root 权限
  6. 给予以上两者执行权限 chmod +x /usr/local/bin/apktool
  7. 在终端执行 apktool

使用

  1. 拿到 APK 安装包,比如 xxx.apk
  2. 在APK同目录下,执行 apktool d xxx.apk
  3. 目录下会多一个与 APK 同名的文件夹,是解压后的 APK,其中的 XML 资源文件和各种 drawable 图片资源等可以直接看, 不想看 XML 文件的话,可以不用 apktool,直接将 APK 后缀改为 .zip 后解压即可,此时得到的解压目录中的结构和 apktool 解的是一样的,但是 XML 都处在压缩状态不能看。

Apktool 其实还可以用来做另外一件事情,就是汉化,或者将语言包替换之后,重新打包,此时需要使用 apktool b xxx.apk 来重新打包 APK。

dex2jar

dex2jar 能够将 dex 转换为 jar

地址:https://github.com/pxb1988/dex2jar

  1. 不使用 apktool,直接修改后缀解压 APK,将解压后 APK 中的 .dex 文件复制到 dex2jar 目录下
  2. 进入该目录执行 ./d2j-dex2jar.sh xxx.dex(注意赋予该 shell 可执行权限 chmod +x d2j-dex2jar.sh)

JD GUI

JD GUI 用来反编译源文件jar包,查看源代码

地址:http://jd.benow.ca/

  1. dex2jar 目录下会多一个 .jar 文件,用 GUI 工具 JD-GUI 打开看就可以了(当然,混淆过的代码中变量名都是 a, b, c, d)

总结

总的来说 apktool 可以让你轻松的拿到应用的资源文件,包括图片,xml等,而 dex2jar 和 JD GUI 可以反编译源代码,看到一些基础的代码结构。

Update

后来 Google 搞了一个 ClassyShark,看起来不错,不过还没来得及尝试

http://classyshark.com/

还有一个 不错的 smali 查看插件看起来也不错,还未尝试

https://github.com/JesusFreke/smali

另外有一个 MAC 专属的一键反编译工具,可以一试:

https://github.com/Jermic/Android-Crack-Tool

又一个查看 dex 到 jar 的反编译工具:

https://github.com/skylot/jadx


2017-02-22 Android , Java , Apktook , Google

HBase Shell Command

HBase Shell 是 HBase 提供的一个简单方便的命令行工具,用它可以直接操作 HBase,对 HBase 进行各种设置。 HBase Shell 提供的命令可以对对 HBase 数据进行增删改查。在上一篇HBase 介绍中对 HBase 做了简答的介绍,也初识了一些命令行。

根据官方的解释 Apache HBase Shell 是 (J)Ruby 下的 IRB(Interactive Ruby Shell),任何在 IRB 下的命令,在 HBase Shell 下都可以使用。1

可以在启动 HBase 之后,通过 $ ./bin/hbase shell 来进入 HBase Shell。

常用命令

基础命令

  • status

    查询服务器状态

  • version

    查询 HBase 版本

  • whoami

    查看连接用户

基本 SHELL 命令

查询所有表名

列举数据库中所有表

list

创建表

create 命令

create 'table_name', 'cf1', 'cf2'

其中的 cf1 和 cf2 为列族名1,列族名2,列族需要在见表时确定,列则不需要, Column Family 是 Schema 的一部分,设计时就需要考虑。

测试表是否存在

exists 'table_name`

会显示表是否存在:

hbase(main):002:0> exists 'test'
Table test does exist
0 row(s) in 0.2650 seconds

增加记录

put 命令

插入数据,对于同一个 rowkey,如果执行两次 put,则认为是更新操作

put 'table_name', 'rowkey', '列族名1:列名1', 'value'

put 't1', 'r1', 'c1', 'value', ts1 一般情况下 ts1(时间戳) 可以省略, Column 可以动态扩展,每行可以有不同的 Column。

增加指定表,行或者列的值

incr

显示表结构

describe 命令查看表结构,显示HBase 表 schema,以及 column family 设计

describe 'table_name'

查询表行数

计算表的行数,count 一般比较耗时,使用

count 'table_name'

查询所有 rowkey

count 'table_name', { INTERVAL => 1 }

查询记录

get 命令获取数据,HBase 的shell操作,大概顺序就是命令后接表明,rowkey,列名然后在后面用花括号加上其他条件。

获取指定rowkey的指定列族指定列的数据,每个Column 可以有任意数量的 Values,按照 Timestamp 倒序自动排序,可以使用 scan 'table_name', {VERSIONS => 10} 来验证,详细请查看 scan 命令

get 'table_name', 'rowkey', '列族名:列名'

获取指定rowkey的指定列族所有的数据

get 'table_name', 'rowkey', '列族名'

获取指定rowkey的所有数据

get 'table_name', 'rowkey'

获取指定时间戳的数据

get 'table_name', 'rowkey', {COLUMN=>'列族名:列', TIMESTAMP=>1373737746997}

获取多个版本值,查询默认返回最新的值

get 'table_name', 'rowkey', {COLUMN => '列族名:列名', VERSIONS => 2}

HBase 按照rowkey 字典序(1, 100, 102, 20) 自动排序,每行包含任意数量 Column,每列按照 列名 Column Key 排序。如果有列族 cf,其中有列 cf:a, cf:b, cf:c, 则按照字典序排序。

每个数据由 TabelName+RowKey+Column+Timestamp=>Value 唯一确定。

删除记录

delete 命令删除表中数据,delete 命令只能用来删除某一列。

删除指定 rowkey 的指定列族的列名数据

delete 'table_name', 'rowkey', '列族名:列名'

删除指定 rowkey 指定列族的数据

delete 'table_name', 'rowkey', '列族名‘

使用 deleteall 命令来删除 rowkey 所有 column 的Value,删除整行数据

deleteall 'table_name', ’rowkey'

删除表

在删除表之前需要使用 disable 命令,让表失效。在修改表结构时,也需要先执行此命令

disable "table_name'

删除表使用 drop 命令

drop 'table_name'

使表有效

enable 命令,和 disable 命令对应

enable 'table_name'

修改表结构

alter 修改表的结构,新增列族,删除列族。在修改之前要先 disable ,修改完成后再 enable

新增列族

alter 'table_name', ‘列族'

删除列族

alter 'table_name', {name=>‘列族’, METHOD=>'delete'}

列族不能被重命名,通常创建新列族名,将数据复制过去,并删除旧的列族名。

hbase(main):049:0> alter 'test','cf2'
Updating all regions with the new schema...
1/1 regions updated.
Done.
0 row(s) in 1.7520 seconds
hbase(main):050:0> describe 'test'
DESCRIPTION                                                                                                                               ENABLED
 'test', {NAME => 'cf', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0', VERSIONS => '3', COMPRESSION => ' false
 NONE', MIN_VERSIONS => '0', TTL => '2147483647', KEEP_DELETED_CELLS => 'false', BLOCKSIZE => '65536', IN_MEMORY => 'false', ENCODE_ON_DI
 SK => 'true', BLOCKCACHE => 'true'}, {NAME => 'cf2', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0', COM
 PRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', MIN_VERSIONS => '0', KEEP_DELETED_CELLS => 'false', BLOCKSIZE => '65536', ENCO
 DE_ON_DISK => 'true', IN_MEMORY => 'false', BLOCKCACHE => 'true'}
1 row(s) in 0.1680 seconds
hbase(main):052:0> alter 'test', {NAME => 'cf2', METHOD => 'delete'}
Updating all regions with the new schema...
1/1 regions updated.
Done.
0 row(s) in 1.5880 seconds
hbase(main):053:0> describe 'test'
DESCRIPTION                                                                                                                               ENABLED
 'test', {NAME => 'cf', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0', VERSIONS => '3', COMPRESSION => ' false
 NONE', MIN_VERSIONS => '0', TTL => '2147483647', KEEP_DELETED_CELLS => 'false', BLOCKSIZE => '65536', IN_MEMORY => 'false', ENCODE_ON_DI
 SK => 'true', BLOCKCACHE => 'true'}
1 row(s) in 0.2010 seconds

全表扫描

scan

全表扫描

hbase(main):043:0> scan 'test', {VERSIONS => 12}
ROW           										COLUMN+CELL
 rowkey1                                               column=cf:a, timestamp=1487295285291, value=value 3
 rowkey1                                               column=cf:a, timestamp=1487294839168, value=value 2
 rowkey1                                               column=cf:a, timestamp=1487294704187, value=value 1

```

删除全表数据 truncate

删除全表数据,这个命令也是 disable,drop,create命令组合而成。

truncate 'table_name'

hbase shell 脚本

shell 命令,把所有的 hbase shell 命令写到一个文件内,类似与 Linux shell 脚本顺序执行所有命令,可以使用如下方法执行。

hbase shell test.hbaseshell

reference

下面是比较完整的一个列表:

https://learnhbase.wordpress.com/2013/03/02/hbase-shell-commands/

官方reference

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


2017-02-18 hbase , linux , apache

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

每天学习一个命令:perf 性能分析工具

Perf 全称Performance Event,是随着 Linux 2.6+ 一同发布的性能分析工具。通过它,应用程序可以利用 PMU,tracepoint 和内核中的特殊计数器来进行性能统计。它不但可以分析指定应用程序的性能问题 (per thread),也可以用来分析内核的性能问题,当然也可以同时分析应用代码和内核,从而全面理解应用程序中的性能瓶颈。

安装

perf 工具在 linux-tools 下面,安装如下三个包即可

apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`

Perf 能触发的事件分为三类:

  • hardware : 由 PMU 产生的事件,比如 cache-misses、cpu-cycles、instructions、branch-misses …等等,通常是当需要了解程序对硬件特性使用情况时使用
  • software : 是核心程序产生的事件,比如 context-switches、page-faults、cpu-clock、cpu-migrations …等等
  • tracepoint : 是核心中的静态 tracepoint 所触发的事件,这些 tracepoint 用來判断在程序执行时期核心的行为

使用

当通过非 root 用户执行 perf 时会遇到权限不足的错误,需要 sudo -i 切换到 root 用户来执行

打印出 perf 可触发的 event

perf list

实时显示当前系统的性能统计信息

perf top

通过概括精简的方式提供被调试程序运行的整体情况和汇总数据

perf stat ./test

perf 命令过于复杂,他有很多子命令集,更多的信息可以参考下面的链接。

reference


2017-02-02 linux , 监控 , 资源占用 , command , perf

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

每天学习一个命令: base64 编解码

Base64 是一种使用 64 个可打印的字符来表示二进制数据的方法,base64 中仅且包括字母 A-Za-z0-9+/ 共64个字符。Base64 通常处理文本数据,表示、传输、存储二进制数据。

Base64编码由来

有些网络传送渠道不支持所有字节,比如邮件发送,图像字节不可能全部都是可见字符,所以受到了很大限制。最好的解决办法就是在不改变传统协议的情况下,利用一种扩展方式来支持二进制文件的传送,把不可打印的字符用可打印字符来表示。 Base64 就是一种基于64个可打印字符来表示二进制数据的方法。

原理

Base64 索引中,64个字符使用 6 bit 位就可以全部表示,一个字节有 8 个bit位,所以在 Base64 编码中,使用3个传统字节(8bit位) 由4个 Base64 字符来表示,保证有效位数一致。

  • Base64 按照字符串长度,每3个 8 bit 组成一组,正对每组,获取每个字符的 ASCII 编码
  • 将 ASCII 码转成 8bit 的二进制,得到 3*8=24 bit 的字节
  • 将 24 bit 划分为 4 个 6bit 的字节,每个 6 bit 的字节前填两个高位0,得到4个 8bit 的字节
  • 将4个 8bit 字节转化成10进制,对照 Base64编码表,得到对应编码后的字符。

下面对 Tom 三个字符进行编码

            T           o           m
ASCII:      84          111         109
8bit字节:   01010100    01101111    01101101
6bit字节:   010101      000110      111101      101101
十进制:     21          6           61          45
对应编码:   V           G           9           t

因此 Tom 在 Base64 编码之后变成了 VG9t

要求:

  1. 要求被编码字符是8bit, 所以要在 ASCII 编码范围内, \u0000-\u00ff 中文就不行
  2. 编码字符长度不是3倍数事,用0代替,对应的输出字符为 =,所以实际 Base64 有65 中不同的字符。

因此 Base64 字符串只可能末尾出现一个或者两个 = ,中间是不可能出现 = 的。

使用

Base64编码主要用在传输、存储、表示二进制等领域,还可以用来加密,但是这种加密比较简单,只是一眼看上去不知道什么内容罢了,当然也可以对Base64的字符序列进行定制来进行加密。

简单字符串的加密,图片文件二进制的加密。

常用方式

格式:base64

从标准输入中读取数据,按Ctrl+D结束输入。将输入的内容编码为base64字符串输出。

示例一

[root@web ~]# base64 
hello 
Ctrl+D

aGVsbG8K
[root@web ~]#

[root@web ~]# 
[root@web ~]# base64 -d 
aGVsbG8K 
Ctrl+D hello
base64: invalid input 
[root@web ~]#

你会发现,base64命令会输出 base64: invalid input,似乎它把按Ctrl+D后的空行也作为输入来处理了。

格式:echo "str" | base64

将字符串str+换行 编码为base64字符串输出。

格式: base64 <<< "hello"

将字符串 hello 编码为 base64 , bash 中 <<< 三个小于号意味着将右边的字符转为左边命令的输入

格式:echo -n "str" | base64

将字符串 str 编码为 base64 字符串输出。无换行。

在 zsh 中,无换行会以 % 百分号结尾,在bash中,命令提示符会直接跟在输出结果的后面 []$,而 zsh 会强制转换。

格式:base64 file

从指定的文件file中读取数据,编码为base64字符串输出。

格式:base64 -d

从标准输入中读取已经进行base64编码的内容,解码输出。

示例二

[root@web ~]# cat >1.txt 
hello
world

Ctrl+D 
[root@web ~]# base64 1.txt 
aGVsbG8Kd29ybGQK
[root@web ~]# base64 1.txt >2.txt 
[root@web ~]# base64 -d 2.txt 
hello
world
base64: invalid input 
[root@web ~]#

格式:base64 -d -i

从标准输入中读取已经进行base64编码的内容,解码输出。加上-i参数,忽略非字母表字符,比如换行符。

man base64 中

-i, --ignore-garbage
When decoding, ignore non-alphabet characters.

use --ignore-garbage to attempt to recover from non-alphabet characters (such as newlines) in the encoded stream.

格式:echo "str" | base64 -d

将base64编码的字符串str+换行 解码输出。

格式:echo -n "str" | base64 -d

将base64编码的字符串str解码输出。

格式:base64 -d file

从指定的文件file中读取base64编码的内容,解码输出。

[root@web ~]# echo "hello" | base64 
aGVsbG8K
[root@web ~]# echo "aGVsbG8K" | base64 -d 
hello
base64: invalid input 
[root@web ~]# echo -n "aGVsbG8K" | base64 -d 
hello
[root@web ~]#

使用echo输出字符串时,如果没有-n参数会自动添加换行符,这会令base64命令发晕。

reference


2017-01-20 base64 , linux , encode , decode

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

每天学习一个命令:lscpu 查看 CPU 信息

lscpu 显示 CPU 的架构信息

lscpusysfsproc/cpuinfo 中收集信息。这个命令的输出是规范的可以用来解析,或者给人来阅读。该命令显示的信息包括,CPU 的数量,线程 (thread),核心 (core),Socket 还有 Non-Uniform Memory Access (NUMA) 节点数。

  • Socket 具体是指的主板上 CPU 的插槽数量,一般笔记本只有一个,而服务器可能会有多个。如果有两个插槽,通常称为两路
  • Core 具体是指 CPU 的核心,也就是平常说的几核,比如八核之类
  • thread 是指的每个 Core 的硬件线程数,超线程

举例来说,如果某个服务器”2 路 4 核超线程”,也就是 2 个插槽,4 核心,默认为 2 thread,也就是 242 是 16 逻辑 CPU。对操作系统来说,逻辑 CPU 的数量就是 Socket * Core * Thread

比如下面我的台式机,1 Sockets, 4 Cores,2 Threads,那么就是 4 核 8 线程。

如下示例:

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    2
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 94
Model name:            Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
Stepping:              3
CPU MHz:               1075.117
CPU max MHz:           4000.0000
CPU min MHz:           800.0000
BogoMIPS:              6816.61
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              8192K
NUMA node0 CPU(s):     0-7
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb invpcid_single intel_pt retpoline kaiser tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp

Byte Order

Big endian vs Little endian 大端和小端,对于整型、长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节);而 Little endian 则相反,认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放据的低位字节到高位字节)。

一般来说,x86 系列 CPU 都是 little-endian 的字节序,PowerPC 通常是 big-endian,网络字节顺序也是 big-endian 还有的 CPU 能通过跳线来设置 CPU 工作于 Little endian 还是 Big endian 模式。

扩展

Linux 有很多命令可以用来查看 cpu 的信息,如果不使用 lscpu 那么可以直接查看 less /proc/cpuinfo 文件。

或者使用 sudo lshw -class processor

或者

sudo dmidecode -t 4 | less

或者

sudo apt install hardinfo
hardinfo | less

或者

sudo apt install cpuid
cpuid

或者

sudo apt install inxi
inxi -C

reference


2017-01-09 linux , command

电子书

最近文章

  • MySQL 中的日志配置和管理 MySQL 中默认是没有开启日志记录的,所以需要手动修改配置文件开启日志。而在 MySQL 中我们需要关心的有三类日志:
  • Java 查漏补缺之:ThreadLocal 使用 ThreadLocal 线程本地变量,每个线程保存变量的副本,对副本的改动,对其他的线程而言是透明的。
  • 为知笔记导出和备份 WizNote 已经用了好几年,虽然也一直在续费,但总感觉将死不死,基于整理这几年近 4000 条的笔记的目的,也一方面为迁移出 WizNote 的目的,研究一下 WizNote 笔记导出和备份的方法。
  • Nginx location 匹配规则 之前的关于 Nginx Config 的文章是当时看 Nginx 书记录下来的笔记,很大略,没有实际操作,等终究用到 location 的时候发现还是有很多需要注意的问题,比如匹配的优先顺序,比如 root 和 alias 的区别等等,所以单独拿一篇文章来记录一下目前遇到的问题,并来解决一下。
  • koajs 简单使用 Koa 是一个背靠 Express 的团队设计的全新的 Web 框架,旨在使之成为一个更轻量,更丰富,更加 robust 的基础框架。通过促进异步方法的使用,Koa 允许使用者抛弃 callback 调用,并且大大简化了错误处理。Koa 并没有将中间件绑定到核心代码,而是提供了一组优雅的方法让编写服务更加快速,通过很多第三方的扩展给 Koa 提供服务,从而实现更加丰富完整的 HTTP server。