解决 Linux Mint 18.1 安装 NVIDIA 驱动后黑屏

Mint 下有一个 Driver Manager 驱动管理,手贱升级了一下到 378,下载,自动安装,重启倒是没有什么但问题,最关键的是,第二次重启的时候直接黑屏,之前也遇到过一回,记忆中是修改了 /etc/X11/xorg.conf 才修复这个问题,没想到这一次又遇到了这个问题。但是无论我怎么修复笔记本始终黑屏在,开机闪过 Linux Mint 的 logo 之后始终无法启动 x server。

第一步尝试卸载NVIDIA驱动

凭借这记忆中的印象,在启动登录之后 Ctrl+Alt+1~7 1~7中的任意一个键,进入 tty 终端,用 root 用户登录,成功后在其中 apt purge nvidia* 移除所有 NVIDIA 驱动。然后重启。

第二部修改 xorg.conf

在第一步尝试不成功之后,尝试修改 xorg.conf 文件,在 /etc/X11 目录下发现了,原始的 xorg.conf 的备份,在尝试恢复以前版本的时候,X server 不断的报错,在查看 cat /var/log/Xorg.0.log 的时候发现 xorg.conf 配置有很大问题,尝试恢复原始设置失败,尝试自己手动修改配置失败。

Section "ServerLayout"
    Identifier "layout"
    Screen 0 "nvidia"
    Inactive "intel"
EndSection

Section "Device"
    Identifier "intel"
    Driver "intel"
    BusID "PCI:0@0:2:0"
    Option "AccelMethod" "SNA"
EndSection

Section "Screen"
    Identifier "intel"
    Device "intel"
EndSection

Section "Device"
    Identifier "nvidia"
    Driver "nvidia"
    BusID "PCI:1@0:0:0"
    Option "ConstrainCursor" "off"
EndSection

Section "Screen"
    Identifier "nvidia"
    Device "nvidia"
    Option "AllowEmptyInitialConfiguration" "on"
    Option "IgnoreDisplayDevices" "CRT"
EndSection

尝试重新安装 NVIDIA 驱动

甚至在终端下安装了 370, 331 版本的驱动多次尝试,尝试使用 NVIDIA 自带的命令 nvidia-xconfig 重新生成 xorg.conf ,终究无法成功启动 Cinnamon.

dpkg-reconfigure nvidia-331

终极解决办法

寻找解决办法的时候,偶然间在论坛上看到有人留言,说,删除 xorg.conf 文件之后一切就正常了,我保证尝试的心态,将 mv xorg.conf xorg.conf_backup 之后,启动 startx 竟然进去了 Cinnamon。顿时感觉有希望,直接重启,用自己账户登录,果然可以了,同时还发现竟然把鼠标延迟的问题解决了。有时间真应该好好研究下 Linux 的启动过程和驱动配置。

外延

关于 Xorg,X.org 项目旨在创建和维护开源可在发行版 X11,在运行的硬件和图形界面之间提供接口。

关于 X server,是 X.org 项目的部分,是 X Window System 的重要组成部分。xorg.conf 文件是 X server 的主要配置文件

Mint 中系统额外的默认 Xorg 配置地址 /usr/share/X11/xorg.conf.d

linux_trovalds_fuck_nvidia

reference


2017-03-05 Linux , Nvidia , Linux Mint

IO 重定向

上一篇讲了 shell 脚本的基本语法,然后这篇补一补标准输入输出重定向命令,以及管道命令。

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为 0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为 1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为 2,Unix程序会向stderr流中写入错误信息。

管道命令

管道命令的操作符是”|”, 它将前一个命令的输出给下一个命令作为输入。

command1 | command2 | command3

将前一个命令的输出作为下一个命令的输入,比如 cat text.txt | less。 管道命令不处理错误输出。

输出重定向

> filename.txt

将 stdout 重定向到文件,如果不存在则创建,否则覆盖

: > filename

此操作将文件 filename 变为空文件, size 为0。文件不存在则创建,与 touch 命令相同。 冒号是一个占位,不产生任何输出

>>

追加到文件末尾

2> filename

重定向 stderr 的输出到文件

2>> filename

重定向并追加 stderr 到文件

&> filename

将 stdout 和 stderr 都重定向到 file

下面是一个例子:

cat *.txt | sort | uniq > result-file
# 对所有.txt文件的输出进行排序, 并且删除重复行.
# 最后将结果保存到"result-file"中.

在 crontab 任务中,需要使用 2>&1 来输出到日志

* * * * * command >> file.log 2>&1

输入重定向

command < file

将右边文件作为输入给左边的命令

command <<< string

后面接 string,将 string 内容给 command

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

$ command > /dev/null 2>&1

reference


2017-03-02 Linux , Shell , Bash

Shell script 学习笔记

上一篇写 Bash 的文章 ,只是介绍了 terminal 下面的一些快捷键,并没有对 Bash 和 Shell 本身展开多少的介绍,因此正好趁此机会。

sh(或者叫做 Shell Command Language), 是由 POSIX 标准 定义的一门语言。 它有很多实现(ksh88,dash…)等等, bash 同样可以认为是 sh 的一个实现。1

因为 sh 是一个规范,而不是实现,所以在大部分的 POSIX 系统上 /bin/sh 是一个 symlink。比如在 Debian/Ubtuntu 中, sh 便指向 dash.

bash 在创造初期是作为 sh 兼容的实现,但是随着时间发展,延伸出了很多扩展功能。而许多新功能改变了原来 POSIX shell 的设计。因此, bash 自身并不是正宗的POSIX shell,而是 POSIX shell 的一种方言。

bash 支持 --posix 模式,用来兼容 POSIX shell。很长一段时间来, 在 GNU/Linux 系统中 /bin/sh 都指向 /bin/bash,久而久之人们便忘记了这两者之间的区别。

一些非常著名的系统 /bin/sh 并不指向 /bin/bash 的例子(甚至在有些系统中 /bin/bash 甚至不存在):

  1. Debian/Ubuntu 系统中 sh 默认指向 dash
  2. BusyBox 使用 ash 来作为 sh 的实现
  3. BSDs, OpenBSD 使用 pdksh .

到此,基本也就解释了 sh 和 bash 的重要区别,但是就目前的学习, bash 因为实现比较流行,几乎绝大部分 shell 脚本都交由 bash 解释执行,并且 bash 相比较于 sh,功能更加强大,语法更加简洁。

Shell 实现

  • sh sh 由Steve Bourne开发,是Bourne Shell的缩写,sh 是Unix 标准默认的shell。
  • ash shell 是由 Kenneth Almquist 编写的,Linux中占用系统资源最少的一个小shell,它只包含24个内部命令。
  • csh 它由以William Joy为代表的共计47位作者编成。它产生于 Unix 第六版 /bin/sh, 是 Bourne Shell 的前身。
  • ksh 是 Korn shell 的缩写,由 David G. Korn 编写。该shell最大的优点是几乎和商业发行版的ksh完全兼容,这样就可以在不用花钱购买商业版本的情况下尝试商业版本的性能了。
  • bash 由Brian Fox和Chet Ramey共同完成,是BourneAgain Shell的缩写。

下面的命令和使用基于 bash。

Shell 适用

因为Shell似乎是各UNIX系统之间通用的功能,并且经过了POSIX的标准化。因此,Shell脚本只要“用心写”一次,即可应用到很多系统上。因此,之所以要使用Shell脚本是基于:

  • 简单性:Shell是一个高级语言;通过它,你可以简洁地表达复杂的操作。
  • 可移植性:使用POSIX所定义的功能,可以做到脚本无须修改就可在不同的系统上执行。
  • 开发容易:可以在短时间内完成一个功能强大又妤用的脚本。

但是,考虑到Shell脚本的命令限制和效率问题,下列情况一般不使用Shell:

  • 资源密集型的任务,尤其在需要考虑效率时(比如排序,hash等等)。
  • 需要处理大任务的数学操作,尤其是浮点运算,精确运算,或者复杂的算术运算(这种情况一般使用C++或FORTRAN 来处理)。
  • 有跨平台(操作系统)移植需求(一般使用C 或Java)。
  • 复杂的应用,在必须使用结构化编程的时候(需要变量的类型检查,函数原型,等等)。
  • 对于影响系统全局性的关键任务应用。
  • 对于安全有很高要求的任务,比如你需要一个健壮的系统来防止入侵、破解、恶意破坏等等。
  • 项目由连串的依赖的各个部分组成。
  • 需要大规模的文件操作。
  • 需要多维数组的支持。
  • 需要数据结构的支持,比如链表或数等数据结构。
  • 需要产生或操作图形化界面 GUI。
  • 需要直接操作系统硬件。
  • 需要 I/O 或 socket 接口。
  • 需要使用库或者遗留下来的老代码的接口。
  • 私人的、闭源的应用

如果你的应用符合上面的任意一条,那么就考虑一下更强大的语言吧——或许是Perl、Python、Ruby——或者是编译语言比如C/C++,或者是Java。

初识Shell

#!/bin/bash
echo "Hello World !"

“#!” 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行。通常这一行被称作 Shebang

chmod +x ./test.sh  #使脚本具有执行权限
./test.sh  #执行脚本

Linux 系统会去PATH里寻找有没有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin等在PATH里 要用 ./test.sh 告诉系统说,就在当前目录找。

再一个稍微复杂一点的脚本:

echo "What is your name?"
read PERSON
echo "Hello, $PERSON"

变量

学习每一门编程语言都是从变量开始。

定义

变量定义时,变量名不加 $,如

variableName="value"

变量名和等号之间不能有空格,变量名需遵循规则:

  • 首字符必须为 [^a-zA-z]
  • 中间不能有空格,可是有下划线 _
  • 不能使用标点
  • 不能使用 bash 关键字, help 命令可查看保留关键字

引用

使用定义过的变量,在变量名之前添加美元符号 ${variableName}

yourName="einverne"
echo $yourName
echo ${yourName}

花括号是可选的,用来识别变量边界,建议每次都加上。

重新定义变量

不加美元符号,直接重新赋值即可

yourName="einverne"
echo "your name is ${yourName} !!"
yourName="Ein Verne"
echo "your name is ${yourName} !!"

只读变量

yourName="einverne"
echo "your name is ${yourName} !!"
readonly yourName
yourName="Ein Verne"

会发生错误,

your name is einverne !!
./demo.sh: line 25: yourName: readonly variable

删除变量

使用 unset 命令删除变量

unset variableName

unset 不能删除只读变量

变量类型

同时存在三种变量:

  1. 局部变量,字脚本或者命令中定义,仅在当前 shell 实例中有效,其他启动的程序不能访问
  2. 环境变量,所有陈旭,包括 shell 启动的程序都能访问,有些程序需要依赖环境变量 PATH 来保证其正常运行
  3. shell 变量

有 shell 程序设置的特殊变量

shell 特殊变量

变量 含义
$$ 当前Shell进程ID , PID
$0 当前脚本的文件名
$n 传递给脚本或函数的参数, n 是数字,表示第几个参数
$# 传递给脚本或函数的参数个数
$* 传递给脚本的所有参数
$@ 传递给脚本的所有参数,被双引号包围稍有不同
$? 上个命令的退出状态,或者函数的返回值

$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(“ “)包含时,都以”$1” “$2” … “$n” 的形式输出所有参数。

但是当它们被双引号(“ “)包含时,”$*” 会将所有的参数作为一个整体,以”$1 $2 … $n”的形式输出所有参数;”$@” 会将各个参数分开,以”$1” “$2” … “$n” 的形式输出所有参数。

测试脚本

set -o nounset                              # Treat unset variables as an error

echo "File name is $0"
echo "First parameter : $1"
echo "First parameter : $2"
echo "This script have $# parameters"
echo "They are $*"
echo "They are $@"

for var in "$*"
do
    echo "${var}"
done

for var in "$@"
do
    echo "${var}"
done

结果:

./demo.sh p1 p2
File name is ./demo.sh
First parameter : p1
First parameter : p2
This script have 2 parameters
They are p1 p2
They are p1 p2
p1 p2
p1
p2

转义

转义表

转义字符 含义
\ 反斜杠
\a 报警
\b 退格
\f 换页,将当前位置移到下页开头
\n 换行
\r 回车
\t Tab
\v 垂直制表符

使用 echo -e "value is ${variableName} \n" 中的 -e 选项来进行转义,否则会原样输出。

echo 的 -E 禁止转义,默认不转义, -n 来禁止插入换行符。

结果暂存

将输出结果保存到变量中,在合适的地方使用

Data=`date`
echo "Date is ${Date}"

变量替换

根据变量的状态,来改变变量的值

形式 说明
${var} 变量原本值
${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。

表达式

基本表达式

#!/bin/sh

a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $b / $a`
echo "b / a : $val"

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then
   echo "a is equal to b"
fi

if [ $a != $b ]
then
   echo "a is not equal to b"
fi
  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2
  • 乘号(*)前边必须加反斜杠()才能实现乘法运算
  • 条件表达式要放在方括号之间,并且要有空格,例如 [$a==$b] 是错误的,必须写成 [ $a == $b ]

关系运算符

关系运算符只能用于数字,或者字符串中只能包含数字

运算符 说明
-eq 相等返回 true
-ne 不相等返回 true
-gt great than 返回true
-lt less than 返回 true
-ge great or equal than ,返回 true
-le less or equal than , 返回 true

布尔运算

运算符 说明
!
-o 或 or
-a 与 and

字符串

# 单引号中的任何字符都原样输出
# 单引号中不能出现单引号
echo '${hi}: "einverne"\t\n\r'

# 双引号可以有变量
# 双引号可以出现转义字符

yourName='einverne'
hi="hi, ${yourName} !\n"

# 字符长度
echo "your name length: ${#yourName}"

echo "first two character of your name ${yourName:0:2}"

text="0123456789-0123456789"
echo $text
echo '${text:position}' "${text:1}"
echo '${text:position:length}' "${text:1:3}"
# 从变量$string的开头, 删除最短匹配$substring的子串
echo '${text#01}' "${text#01}"
# 从变量$string的开头, 删除最长匹配$substring的子串
echo '${text##01}' "${text##01}"
# 从变量$string的结尾, 删除最短匹配$substring的子串
echo '${text%89}' "${text%89}"
# 从变量$string的结尾, 删除最长匹配$substring的子串
echo '${text%%89}' "${text%%89}"

# 使用$replacement, 来代替第一个匹配的$substring
echo '${text/substring/replacement} ${text/01/ab}' "${text/01/ab}"
# 使用$replacement, 代替所有匹配的$substring
echo '${text//substring/replacement} ${text//01/ab}' "${text//01/ab}"

# 如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
echo '${text/#substring/replacement} ${text/#01/ab}' "${text/#01/ab}"

# 如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
echo '${text/%substring/replacement} ${text/%01/ab}' "${text/%01/ab}"

数组

array_name=(value0 value1 value2 value3)
# 或者
array_name=(
value0
value1
value2
value3
)
# 或者
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
# 读取数组
valuen=${array_name[2]}
# 获取所有元素
${array_name[*]}
${array_name[@]}
# 长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

条件语句

IF

if [ expression ]
then
   Statement(s) to be executed if expression is true
fi


if [ expression ]
then
   Statement(s) to be executed if expression is true
else
   Statement(s) to be executed if expression is not true
fi

# 更复杂
if [ expression 1 ]
then
   Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
   Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
   Statement(s) to be executed if expression 3 is true
else
   Statement(s) to be executed if no expression is true
fi

CASE

echo 'Input a number between 1 to 4'
echo 'Your number is:\c'
read aNum
case $aNum in
    1)  echo 'You select 1'
    ;;
    2)  echo 'You select 2'
    ;;
    3)  echo 'You select 3'
    ;;
    4)  echo 'You select 4'
    ;;
    *)  echo 'You do not select a number between 1 to 4'
    ;;
esac

循环语句

for 变量 in 列表
do
    command1
    command2
    ...
    commandN
done


while command
do
   Statement(s) to be executed if command is true
done

函数

function function_name () {
    list of commands
    [ return value ]
}

reference


2017-03-01 Linux , Shell , Bash

mitmproxy 抓包

在之前的文章Android 抓包 中介绍过 Mac 下 Charles 进行客户端的抓包,那篇文章中最后介绍其他工具的时候提到了 mitmproxy 这样一款命令行工具,最近使用来看,也是非常强大的工具。这里就简单记录一下。

mitmproxy 是用 Python 和C 开发的一款支持 HTTP(S) 的中间人代理软件(man-in-the-middle proxy),不同于Fiddler2,burpsuite等类似功能工具,mitmproxy可在终端下运行并且可以用来拦截、修改、重放和保存HTTP/HTTPS 请求。mitmproxy 可以辅助 WEB 及客户端调试、开发和测试,是一个渗透测试的工具。

安装

sudo apt-get install python3-pip python3-dev libffi-dev libssl-dev libtiff5-dev libjpeg8-dev zlib1g-dev libwebp-dev
sudo pip3 install mitmproxy  # or pip3 install --user mitmproxy

或者从源里面拉,但是可能不是最新版本

sudo apt install mitmproxy

我从源里面拉的版本为 0.15 版,而 pip3 安装的为 1.02 版本,相差版本足有一年。

工作原理

mitmproxy 实现原理:

  1. 客户端发起一个到 mitmproxy 的连接,并且发出HTTP CONNECT请求,
  2. mitmproxy 作出响应(200),模拟已经建立了CONNECT通信管道,
  3. 客户端确信它正在和远端服务器会话,然后启动SSL连接。在SSL连接中指明了它正在连接的主机名(SNI),
  4. mitmproxy 连接服务器,然后使用客户端发出的 SNI 指示的主机名建立SSL连接,
  5. 服务器以匹配的 SSL 证书作出响应,这个 SSL 证书里包含生成的拦截证书所必须的通用名(CN)和服务器备用名(SAN),
  6. mitmproxy 生成拦截证书,然后继续进行与第3步暂停的客户端SSL握手,
  7. 客户端通过已经建立的SSL连接发送请求,
  8. mitmproxy 通过第4步建立的SSL连接传递这个请求给服务器。

how-mitmproxy-works-transparent-https

mitmproxy 工作步骤:

  1. 设置系统\浏览器\终端等的代理地址和端口为同一局域网中 mitmproxy 所在电脑的 IP 地址,比如我的PC 开启 mitmproxy 之后,设置 8080 端口,本地IP 为 192.168.1.130,那么设置 Android HTTP 代理为 192.168.1.130:8080
  2. 浏览器或移动端访问 mitm.it 来安装 mitmproxy 提供的证书
  3. 在 mitmproxy 提供的命令行下,或者 mitmweb 提供的浏览器界面中就能看到 Android 端发出的请求。

官方提供的安装方式:http://mitmproxy.org/doc/certinstall.html

三个命令

在完成 mitmproxy 的安装之后,mitm 提供的三个命令

  • mitmproxy 会提供一个在终端下的图形界面,具有修改请求和响应,流量重放等功能,具体操作方式有点vim的风格
  • mitmdump可设定规则保存或重放请求和响应,mitmdump的特点是支持inline脚本,由于拥有可以修改request和response 中每一个细节的能力,批量测试,劫持等都可以轻松实现
  • mitmweb 提供的一个简单 web 界面,简单实用,初学者或者对终端命令行不熟悉的可以用 mitmweb 界面

mitmproxy 基本使用

可以使用 mitmproxy -h 来查看 mitmproxy 的参数及使用方法。常用的几个命令参数:

  1. -p PORT, --port PORT 设置 mitmproxy 的代理端口
  2. -T, --transparent 设置透明代理
  3. --socks 设置 SOCKS5 代理
  4. -s "script.py --bar", --script "script.py --bar" 来执行脚本,通过双引号来添加参数
  5. -t FILTER 过滤参数

在 mitmproxy 命令模式下,在终端显示请求流,可以通过 Shift + ? 来开启帮助查看当前页面可用的命令。

基本快捷键

b  保存请求/返回头
C  将请求内容导出到粘贴板,按 C 之后会有选择导出哪一部分
d  删除flow 请求
E  将 flow 导出到文件
w  保存所有 flow 或者该 flow
W  保存该 flow
L  加载保存的 Flow
m  添加/取消 Mark 标记,会在请求列表该请求前添加红色圆圈
z  清空flow list 和 eventlog
/  在详情界面,可以使用 / 来搜索,大小写敏感
i  开启 interception pattern 拦截请求

移动

j, k       上下
h, l        左右
g, G   go to beginning, end
space    下一页
pg up/down   上一页/下一页
ctrl+b/ctrl+f    上一页/下一页
arrows 箭头     上下左右


全局快捷键
q   退出,或者后退
Q  不提示直接退出

同样在 mitmproxy 中不同界面中使用 ? 可以获取不同的帮助,在请求详细信息中 m 快捷键的作用就完全不同 m 在响应结果中,输入m可以选择body的呈现方式,比如json,xml等 e 编辑请求、响应 a 发送编辑后的请求、响应。 因此在熟悉使用 ? 之后,多次使用并熟悉快捷键即可。就如同在 Linux 下要熟悉使用 man 命令一样,在不懂地方请教 Google 一样,应该是习惯性动作。多次反复之后就会变得非常数量。

使用脚本

使用 s 参数制定 inline 脚本

mitmproxy -s script.py

比如将指定 url 的请求指向新的地址

用于调试Android 或者 iOS 客户端,打包比较复杂的时候,强行将客户端请求从线上地址指向本地调试地址。可以使用 mitmproxy scripting API mitmproxy 提供的事件驱动接口。

加上将线上地址,指向本地 8085 端口,文件为 redirect_request.py

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
def request(flow):
    if flow.request.pretty_host == 'api.github.com':
        flow.request.host = '127.0.0.1'
        flow.request.port = 8085

则使用 mitmweb -s redirect_request.py 来调用此脚本,则通过 mitm 的请求都会指向本地。

更多的脚本可以参考:https://github.com/mitmproxy/mitmproxy/tree/master/examples/simple

一个完整的HTTP flow 会依次触发 requestheaders, request, responseheadersresponse

启用 SOCKS5 代理

添加参数 --socks 可以使用 mitmproxy 的 SOCK5代理

透明代理

透明代理是指将网络流量直接重定向到网络端口,不需要客户端做任何设置。这个特性使得透明代理非常适合不能对客户端进行配置的时候,比如说 Android 应用等等。

几个问题

对于 Openwrt 的路由器,在无线接口配置中一定要注意查看,“禁止客户端之间的通信”这个选项不启用。或者在 /etc/config/wireless 配置中, wifi-iface 配置中

option isolate 0

为关闭状态,否则无法让无线局域网中的设备之间通信。

reference


2017-02-27 mitmproxy , Android

我的一加3手机设置

最近屏幕摔碎了一次,维修过程中无奈抹掉了所有数据,于是只能从头开始开搞。这里只是简单的记录一下,以免哪一天又有同样的悲剧发生,当然不可能再有下次了。

刷回原厂设置

对于 Nexus 机型来说,Google 都提供了原厂镜像,一加同样也是,可以从官网下载 ,不过亲身经历一加官网的好多链接都挂掉了,直接从 xda 找反而要方便许多。官网的链接使用迅雷下载还遭遇了掉包,所以对于刷机包,一定要验证md5,一定一定。

刷 Oxygen OS (氧OS) , 有很多方法,如果使用的 stock recovery ,可以使用 adb sideload full-rom.zip 来刷入(官网有详细教程)。 而如果安装了 TWRP 或者 twrp-3.0.2-0_blu_spark_v11-op3.img 等等第三方的 recovery , 可以直接在 recovery 中 install ROM。虽然间隔遇到了一些问题,在使用 recovery 刷机的时候遇到 “this package is for OnePlus 3 devices this is one plus 3”,这样奇怪的错误。但是最后找原因还是因为 recovery 的关系,使用 TWRP 3.0.2 及以前的版本即可,或者 blu spark 的版本都可以完美解决。

root

使用下面地址给出的 superSu, systemless 可以完美root。

https://forum.xda-developers.com/oneplus-3/how-to/oneplus-3-how-to-unlock-bootloader-t3398733

xda 终究是一切的开端,很多内容都是从这边开始,然后被无数人复制粘贴搬运到互联网的各个角落。因此,遇到任何刷机或者root,或者 Android 相关的任何折腾的问题,用英语关键词来这里搜索有的时候比直接在 Google 搜索要灵得多。这有的时候就像是要查找某一款产品的型号或者功能时,直接在 jd.com 或者 淘宝搜索要来的快得多。或者垂直搜索领域确实值得深入发展一下,感觉这也是 Google 越来越担心亚马逊存在的原因之一吧。

修改 DPI

在root之后,开机进入,就会发现一加默认的DPI 实在感人,远看像老人机,每一个图标都老大老大。Oxygen OS 默认的DPI是 480,实际使用感受设置在 420 到 440 最佳。基本上Launcher 中一行 5 个 图标,原始设置一行只能放下 4 个图标。

一加3 修改 DPI ,可以有很多方法,最最简单的方法就是下载 Le DPI Changer 这个应用,直接在应用中修改(记得上一次可以修改成功,但是这一次差点将系统搞坏,这里要注意,修改 build.prop 文件一定要备份,否则有可能遇到无法开机的情况。幸亏这一次在系统中找到了 build.prop 的备份,在 recovery 中恢复了之前的设置)。

另外一种情况就是,直接修改 /system/build.prop 系统目录下的 build.prop 文件,直接修改文件内容。

ro.sf.lcd_density=420

同样也可以利用 BuildProp Editor 应用来修改,开启应用,右上角设置,中添加,键为 ro.sf.lcd_density ,值为 420 的条目。重启手机便可以生效。记住修改 build.prop 文件,以及任何系统文件一定要备份系统,或者可以在 recovery 中能够恢复修改的内容,否则有可能无法开机。建议使用 BuildProp Editor 这个应用来修改。

Magisk

从 Play Store 中下载 Magisk Manager,安装打开,保证ROOT,此时从 Magisk 中更新组件,重启,即可。

下文中的 boot.img 不要轻易刷入,其他未经验证的 boot.img 也不要轻易刷入。 https://forum.xda-developers.com/oneplus-3/how-to/guide-oneplus-3-magisk-install-android-t3433093

https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445

Xposed

在安装好 Magisk 之后,从 Magisk 中可以选择安装 Xposed ,然后参照之前整理过的文章 我使用的 Xposed Module 安装一遍。还很快。

如果不想使用 Systemless 的 Xposed ,可以使用官网的地址,直接从 recovery 中刷入。

Kernel

一直使用的 ElementalX 的 kernel ,直接从 Play Store 上下载 ElementalX Manager,在应用中安装即可,应用会自动选择相应的版本。

中间遇到的几个问题

The dm-verity is not started in enforcing mode

原厂给我刷了 Android 7.0 的系统,在开机的时候除了解锁 bootloader 的提醒之外,还多了这个提醒,猜测可能是 Android 7.0 导致的,在刷完 Oxygen OS 3.2.8 (Android 6.0.1) 之后,这个提示就消失了。

Adblocker 被移除

在原本的 Xposed 列表中我曾经写过, Adblocker 这样一款广告去除 Module,但是这个 module 莫名其妙被 Xposed 仓库和 xda 移除,没有任何消息。有人说是因为有木马导致的,但是我更加觉得是因为去广告有用,得罪了不少人才导致下架的。

更多的细节可以参考下面的文章:

  • https://forum.xda-developers.com/xposed/happened-to-adblocker-t3453144
  • https://forum.xda-developers.com/android/general/guide-ad-blocking-t3218167
  • https://www.reddit.com/r/xposed/comments/50s0ow/discussion_the_adblocker_module_has_been_removed/

不过还是能从 Coolapk.com 来下载到下架版本。个人感觉还是能够屏蔽很多广告的。

至此所有系统级别设置都已经完成。附上一张桌面

OnePlus3 Wallpaper

reference


2017-02-26 OnePlus , Android , Xposed , Magisk , Root

终端使用 sock5 代理

为了解决 Linux Mint/Ubuntu 下安装 Dropbox 的问题,而认识了 proxychains。proxychains 是 Linux 下的代理工具,他允许其他程序通过其代理上网,支持 HTTP, SOCKS4 和 SOCKS5 类型的代理服务器,并可配置多个代理方式。

一直使用的 Dropbox 因为其被屏蔽,所以安装及使用必须通过代理,而 Shadowsocks 作为天然的 socks5 代理成为了最佳选择,在安装 Dropbox(Linux) 之后,设置中可以设置 Socks5 代理。于是剩下的问题便是,如何安装 Dropbox 了。在 Dropbox 官网下载的安装程序会自动下载相关组件,但是因为没有走代理,几乎在直连的情况下无法成功。所以在解决这个问题的时候知道了 proxychains。在了解其作用之后,发现也可以利用其特性来达到在 Linux 终端下让任何命令走代理的目的。

安装 Proxychains

安装 proxychains 可以有很多方法,最简单的方式就是使用 apt

sudo apt install proxychains

如果想要使用最新版,也可以自己手动编译源码

# 安装
git clone https://github.com/rofl0r/proxychains-ng.git
./configure --prefix=/usr --sysconfdir=/etc
make
sudo make install
sudo make install-config

配置

在安装完成之后,一般在 /etc/proxychains.conf 处会有默认配置文件,编辑该文件

sudo vim /etc/proxychains.conf
# 然后将如下内容添加到文件末
socks5 127.0.0.1 1080

# 开启本地 socks5 代理

然后使用

proxychains dropbox start -i

就可以启动 Dropbox 安装程序。

或者使用

proxychains wget url

使用 curl ip.gs 来验证是否成功

$ curl ip.gs 
当前 IP:124.xxx.xxx.xxx 来自:中国北京北京 电信

$ proxychains curl ip.gs
ProxyChains-3.1 (http://proxychains.sf.net)
|DNS-request| ip.gs 
|S-chain|-<>-127.0.0.1:1080-<><>-4.2.2.2:53-<><>-OK
|DNS-response| ip.gs is 45.116.12.10
|S-chain|-<>-127.0.0.1:1080-<><>-45.116.12.10:80-<><>-OK
当前 IP:106.xxx.xxx.xxx 来自:日本东京都东京linode.com kddi.com

来现在任何内容

延伸

在配置完 proxychains 之后,在终端如果任何命令无法连接成功时,在其前加上 proxychains 就可以走代理方式来执行该命令。

在网上查阅的时候同样发现还有其他类似的工具,比如 polipo,这是一个 socks5 转 http 的代理,设置之后可以使用 export http_proxy=http://localhost:port 来让终端走代理。`

reference


2017-02-25 Socks5 , Linux , Proxy , Ternimal

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 反编译工具,只介绍工具名字及工具简单使用,详细开来再具体讲吧。

概述

主要需要依靠如下几个工具

  • 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/

安装

安装指南

  1. 右击链接 讲 Linux 的脚本保存为 apktool.
  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 needed
  6. 给予以上两者执行权限 chmod +x
  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

地址: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

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

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

Update

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

http://classyshark.com/

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

https://github.com/JesusFreke/smali

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

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


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

Google+

最近文章

  • 知乎上被删除的良心回答之油猴脚本 今天偶然间看到一个知乎问题:“最良心的软件可以良心到什么程度?”,当时在 Google+ 上点进去粗略看了一样,看到油猴脚本也就坦然了,而添加到稍后阅读,在晚上回来之后准备细看时却惊讶于知乎屏蔽的速度,在尝试使用 Google,bing 和 web archive ,baidu 的历史记录之后终于找回了一些渣滓。
  • Ubuntu/Debian install nginx installation sudo apt-get install nginx
  • celery best practice 不要使用数据库作为 AMQP Broker 随着worker 的不断增多可能给数据库IO和连接造成很大压力。 Docker 上很多 相关的镜像。
  • Git 使用过程中遇到的小技巧 Git 使用过程中遇到的小技巧,平时没有 commit, merge, branch 用的那么勤快,但是需要时也需要查看一下,因此记录一下,以免忘记。
  • URL 短域名 逛博客看到别人在讨论短URL的设计实现,然后偶然间发现了 GitHub 曾经推出1过的短域名服务 Git.io https://github.com/blog/985-git-io-github-url-shortener ↩