每天学习一个命令:xclip 与剪贴板交互

xclip 命令可以从 stdin,或者文件读入数据到剪贴板,或者将剪贴板内容粘贴到目的应用中。xclip 命令建立了终端和剪切板之间通道,可以用命令的方式将终端输出或文件的内容保存到剪切板中,也可以将剪切板的内容输出到终端或文件

安装

sudo apt-get xclip

命令格式

xclip [OPTION] [FILE] ...

常用参数:

-i      从 stdin 读入
-o      打印到标准输出

使用实例

不加选项时只在保存在 X PRIMARY(终端剪切板),加上选项 -selection c 后保存在 X CLIPBOARD(外部程序剪切板)

为了区分这二者的区别,可以简单的做一个试验。

echo "Hello World" | xclip

此时 Hello World 字符只是在终端的剪贴板中,可以尝试在终端鼠标中键粘贴,发现终端的粘贴板是已经被修改的,此时用 Ctrl + v 粘贴到其他 GUI 应用程序(比如 Chrome 地址栏)发现粘贴板并不是 Hello World。

echo "TEST OUTSIDE CLIPBOARD" | xclip -sel c

此时会发现 Chrome 中可以粘贴 TEST 这行文本,而鼠标中键粘贴到终端的还是上面的 Hello World。

终端输出保存到剪切板中

ls -al | xclip
echo "SOME" | xclip
xclip /etc/passwd
xclip < /etc/passwd

此时 ls -al 的输出内容已经保存在剪切板中了,此时 xclip -o 可以看到剪切板的内容。

但此时还不可以粘贴到终端以外的程序中,此时需要用到: xclip -selection c

ls -al | xclip -selection c
xclip -sel c /etc/passwd
xclip -sel c < /etc/passwd

剪切板内容输出到终端

xclip -o
xclip -selection c -o

剪切板内容输出到文件

xclip -o > ~/test.txt
xclip -selection c -o > ~/test.txt

reference

  • man xclip

2015-02-26 linux , command , xclip

Java 的 IO 操作 java.io 包

InputStream 和 Reader 的区别

  • InputStream 是 byte 导向
  • Reader Writer 是字符导向

2015-02-20 java , java-io , io

每天学习一个命令:ffprobe 查看多媒体信息

在 ffmpeg package 中有一个 ffprobe 工具,主要用来查看多媒体文件或者流媒体信息,在线的视频信息也能够快速获取。大部分情况下个人比较喜欢使用 ffmpeg -i input.mp4 来快速查看,这种时候在终端上比较快速,而如果有些时候想要分析一下媒体文件,需要编程获取得到的媒体文件结果,显然 ffmpeg 的输出结果简直无法忍受,而 ffprobe 提供非常清晰的输出格式,非常方便的可以提供给编程软件解析使用。

官网说明:http://ffmpeg.org/ffprobe.html

命令格式

ffprobe [OPTION] file

常用的参数

-show_format            显示输入多媒体流的容器格式信息
-show_streams           显示输入多媒体流中每一个流的信息
-i input_file           指定输入文件
-print_format json      json 形式输出
-of 或者 -print_format  default/compact/csv/flat/ini/json/xml

命令行:

./ffprobe -print_format json -show_format -show_streams -i ./video/c.ts

其中:  

-print_format json 以 json 格式输出 , 
-show_format 输出封装格式信息 ,
-show_streams 输出流信息,
-i ./video/c.ts 输入文件

使用实例

基本用法

ffprobe -v error -show_format -show_streams input.mp4

输出该视频的基本信息,如果上面的命令输出结果过多,而只想要比如 size 可以

ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1 input.mp4

如果只想要结果可以

ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1:nokey=1 input.mp4

上面的命令中:

  • -v 参数是日志输出级别
  • error 则略去了 build 和 generic 信息,暴露 error 错误
  • -print_format 则是输出结果格式

获取视频时长

ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4

直接输出视频时长。

下面是一段 shell 脚本,之前遇到过有一批视频地址,想要获取这批视频的市场,用 ffprobe 就能够完成。

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"

以 json 格式输出

ffprobe -show_streams -show_entries format=bit_rate,filename,start_time:stream=duration,width,height,display_aspect_ratio,r_frame_rate,bit_rate -of json -v quiet -i 98a74a06741a091b8a42aaa31b4edc66.mp4

输出:

{
    "programs": [

    ],
    "streams": [
        {
            "width": 720,
            "height": 1280,
            "display_aspect_ratio": "0:1",
            "r_frame_rate": "30/1",
            "duration": "40.833333",
            "bit_rate": "1710937",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "language": "und",
                "handler_name": "VideoHandler"
            }
        },
        {
            "r_frame_rate": "0/0",
            "duration": "40.890431",
            "bit_rate": "128102",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "language": "und",
                "handler_name": "SoundHandler"
            }
        }
    ],
    "format": {
        "filename": "98a74a06741a091b8a42aaa31b4edc66.mp4",
        "start_time": "-0.046440",
        "bit_rate": "1065995"
    }
}

外延

mediainfo 也是一个用来获取音频视频信息的工具,比如封装格式、音视频编码格式、码率等信息。

mediainfo 可以获取的信息包括

  • General: title, author, director, album, track number, date, duration…
  • Video: codec, aspect, fps, bitrate…
  • Audio: codec, sample rate, channels, language, bitrate…
  • Text: language of subtitle
  • Chapters: number of chapters, list of chapters

mediainfo 支持的格式

  • Video: MKV, OGM, AVI, DivX, WMV, QuickTime, Real, MPEG-1, MPEG-2, MPEG-4, DVD (VOB)…
  • Video Codecs: DivX, XviD, MSMPEG4, ASP, H.264, AVC…
  • Audio: OGG, MP3, WAV, RA, AC3, DTS, AAC, M4A, AU, AIFF…
  • Subtitles: SRT, SSA, ASS, SAMI…

mediainfo 输出的字段不容易被解析,表述方法不统一。例如,对于 h264 这种编码格式,mediainfo 可能输出的表述为 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10;还比如,对于 mp3 这样的音频格式,居然会分两个字段进行描述,分别说明 mpeg 和 layer3.

reference


2015-02-09 linux , ffmpeg , ffplay , ffprobe , command

每天学习一个命令:sed 流式字符编辑器

sed 全名叫 stream editor,是面向字符流的编辑器,能够完美地配合正则表达式使用。sed 提供的功能是交互式文本编辑器的延伸,提供的查找替换程序可以被全局应用于单个文件或多个文件。

面向字符流,是因为输入流通过程序并将输出直接输出到标准输出。

sed 处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用 sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非使用重定向存储输出。sed 主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

sed 功能:

  • 主要用来自动编辑一个或多个文件;
  • 简化对文件的反复操作;
  • 编写转换程序等。

awk 的典型示例是将数据转化为格式化报表。

行编辑器 ed

awk 的起源追溯到 sed 和 grep,再往前追溯就到了 ed,最初的 UNIX 行编辑器。关于 ed 编辑器可以参考之前的『文章

sed 使用参数

sed [-neifr] [ 命令 ]

选项与参数:

  • -n :只有经过 sed 特殊处理的那一行(或者命令)才会被列出来。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。
  • -e :直接在命令列模式上进行 sed 的命令编辑;
  • -f :从文件执行 sed 命令,-f filename 则可以运行 filename 内的 sed 命令;
  • -r :sed 默认支持正则表达式,使用 -r 开启扩展的正则表达式
  • -i :直接修改读取的文件内容,而不是输出到终端。

命令说明: [n1[,n2]]command

n1, n2 :在 n1 到 n2 行之间使用命令,举例来说,如果我的命令是需要在 10 到 20 行之间进行的,则 10,20[ 命令行为 ]

command:

a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :替换,通常这个 s 的命令可以搭配正则 `1,20s/old/new/g`

实例

行删除及增加

以行为单位的新增 / 删除

/etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除,这里的删除是指在输出结果中删除,并不是真正去删除文件中的内容,如果要直接对文件进行修改,可以参考后文中的 -i 参数。

nl /etc/passwd | sed '2,5d'
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

说明:

  • sed 的命令为 ‘2,5d’ ,d 就是删除
  • sed 后面接的命令,请务必以 '' 两个单引号括住

只要删除第 2 行

nl /etc/passwd | sed '2d'

要删除第 3 到最后一行

nl /etc/passwd | sed '3,$d'

删除空白行

sed '/^$/d' file.txt

在第二行后(即是加在第三行)添加内容

nl /etc/passwd | sed '2a drink tea'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
drink tea
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

那如果是要在第二行前

nl /etc/passwd | sed '2i drink tea'

如果是要增加两行以上,在第二行后面加入两行字

nl /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

以行为单位替换

以行为单位的替换与显示

将第 2-5 行的内容替换为自己的内容

nl /etc/passwd | sed '2,5c No 2-5 number'
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 sync:x:5:0:sync:/sbin:/bin/sync

显示特定行

仅列出 /etc/passwd 文件内的第 5-7 行

nl /etc/passwd | sed -n '5,7p'
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

这个 sed 的以行为单位的显示功能,就能够将某一个文件内的某些行号选择出来显示。

数据的搜寻并显示

搜索 /etc/passwd 有 root 关键字的行

nl /etc/passwd | sed '/root/p'
1  root:x:0:0:root:/root:/bin/bash
1  root:x:0:0:root:/root:/bin/bash
2  daemon:x:1:1:daemon:/usr/sbin:/bin/sh
3  bin:x:2:2:bin:/bin:/bin/sh
4  sys:x:3:3:sys:/dev:/bin/sh
5  sync:x:4:65534:sync:/bin:/bin/sync

如果 root 找到,除了输出所有行,还会输出匹配行。

使用-n的时候将只打印包含正则的行。

nl /etc/passwd | sed -n '/root/p'
1  root:x:0:0:root:/root:/bin/bash

输出指定的行数 (输出 2-5 行的数据)

sed -n '2,5p' file

数据搜寻删除

删除 /etc/passwd 所有包含 root 的行,其他行输出

nl /etc/passwd | sed  '/root/d'
2  daemon:x:1:1:daemon:/usr/sbin:/bin/sh
3  bin:x:2:2:bin:/bin:/bin/sh

搜索执行命令

搜索 /etc/passwd, 找到 root 对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把 bash 替换为 blueshell,再输出这行:

nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p}'
1  root:x:0:0:root:/root:/bin/blueshell

如果只替换 /etc/passwd 的第一个 bash 关键字为 blueshell,就退出

nl /etc/passwd | sed -n '/bash/{s/bash/blueshell/;p;q}'
1  root:x:0:0:root:/root:/bin/blueshell

最后的 q 是退出。

数据的搜寻并替换

结尾的 g 表示匹配所有的

sed 's/regex/replace/g' file.txt

假如没有结尾的 g,比如

sed 's/book/books/' file.txt

则表示匹配一个 book,并替换为 books。

多点编辑

一条 sed 命令,删除 /etc/passwd 第三行到末尾的数据,并把 bash 替换为 blueshell

nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
1  root:x:0:0:root:/root:/bin/blueshell
2  daemon:x:1:1:daemon:/usr/sbin:/bin/sh

-e表示多点编辑,第一个编辑命令删除 /etc/passwd 第三行到末尾的数据,第二条命令搜索 bash 替换为 blueshell。

直接修改文件内容

sed 可以启用 -i 选项直接修改文件的内容,不必使用管道命令或者重定向。

sed -i 's/\.$/\!/g' filename.txt         # 将文件每一行最后的 `.` 替换为 `!`
sed -i '$a # add to last' filename.txt   # 每一行后面 ($) 增加 (a) 后面的内容

sed 可以直接修改文件内容,这样对于大文本,可以不需要使用 vim 打开在进行编辑,直接使用 sed 行读取编辑就能够实现行修改和替换的作用。

过滤部分内容

利用替换可以将不需要的内容替换成空

sed -n -e 's/^.*id=//p'

可以打印 id= 后面的内容,然后再做处理。

Sed 处理 Tab

在 sed 的语法中,比如替换一行中的 Tab 到逗号,会发现

sed -i 's/\\t/,/g' some.txt

\t 其实并没有用,而是需要按下 Ctrl+v 然后输入 Tab 才有效。

sed -i 's/	/,/g' some.txt

这样才有效。

reference


2015-01-15 linux , command , sed , editor

Vim 插件之: vim-surrounding

vim-surrounding 插件可以轻松的一次性修改成对出现的,比如 (), [], {}, 双引号,XML 标签等等。提供了

  • 增加
  • 删除
  • 修改

包围内容的方法。

首先放上链接:

Installation

Plugin 'tpope/vim-surrounding'

Usage

用下面的例子做 demo

print("hello world")

光标定位在 hello world 包括引号,那么使用如下的命令可以实现双引号替换成单引号:

cs"'

change surrounding

Change surroundings is cs. 接受两个参数,目标,和替换内容

cs"'            # change " to '
cs"<q>          # change " to <q>
cs)]            # change ) to ]

如果要替换标签的内容,比如说将 h1 替换为 h2,则需要用到 t

<h1>Title</h1>

则需要 cst<h2>,同理要将 <h1> 替换成双引号,则 cst"

假如有一行内容

<h1>This is a title</h1>

cs 还有一个变种 cS,效果则是将变化的内容放到新行中。

add surrounding

给 hello 增加 <h2>

hello

那么可以使用 csw<h2>,简单记忆成 change surrounding of word <h2> ,给 word 增加 <h2> 标记

可以看到 cs 接受两个参数,会用后一个参数替换前一个。

delete surrounding

比如删除双引号,delete + surrounding + “

ds"             # delete surrounding "
ds(             # delete surrounding (
dst             # delete surrounding tags

dscs 都将 target 作为第一个参数,所有的 target (text-objects) 目前都是一个字符。

(), [], {}, <>
b, r, B, a 分别对应上面括号
', ", `
t 表示 HTML 或者 XML 标签
w, W, s 分别是 word, WORD, sentence
p 表示 paragraph

ys 给 surrounding 增加标记

给 hello 增加 <h2>

hello

使用更加复杂一点的 you surrounding inside word with <h2>

ysiw<h2>

ys 接受 vim motion 或者 text object 作为一个 object

如果要对整行操作可以使用 yss 后接修改的内容,比如给整行增加花括号

yssB

cS 一样,ys 也有变种版本 ySySS,会在新行添加内容,比如给 paragraph 添加双引号

ySS"

Visual mode

在选择模式下可以使用 S + 需要添加的内容,来看快速对选择的内容增加 surroundings。

比如我想要给下面这一行中的一部分内容,比如说 main title 增加一个 <h1> 标记。

This is the main title  sub title`

那么只需要将 This is the main title 使用 v 选中,然后按下 S<h1>Enter 回车之后前后就加上了 h1 标签。

在单行选择模式下, surroundings 会添加在行中,在 blockwise 选择模式,每一行都会 surround。

a = testa
b = testb
c = testc

加入上面的三行内容,想要给后面的内容增加双引号,那么可以使用列选选择然后 S + " 就可以快速添加。

Conclusion

Normal mode
-----------
ds  - delete a surrounding
cs  - change a surrounding
ys  - add a surrounding
yS  - add a surrounding and place the surrounded text on a new line + indent it
yss - add a surrounding to the whole line
ySs - add a surrounding to the whole line, place it on a new line + indent it
ySS - same as ySs

Visual mode
-----------
s   - in visual mode, add a surrounding
S   - in visual mode, add a surrounding but place text on new line + indent it

2015-01-04 vim , vim-plugin , vim-surrounding , tpope

jhat 使用

jhat 是 Java 的堆分析工具(Java heap Analyzes Tool),在 JDK 6u7 之后成为 JDK 标配。

用法

jhat [options] heap-dump-file

说明:

  • options 参数
  • heap-dump-file 二进制 Java 堆文件,可以使用 jmap 导出

可选参数

-stack false|true

关闭对象分配调用栈跟踪 (tracking object allocation call stack)。 如果分配位置信息在堆转储中不可用,则必须将此标志设置为 false. 默认值为 true.

-refs false|true

关闭对象引用跟踪 (tracking of references to objects)。 默认值为 true. 默认情况下,返回的指针是指向其他特定对象的对象,如反向链接或输入引用 (referrers or incoming references), 会统计 / 计算堆中的所有对象。

-port port-number

设置 jhat HTTP server 的端口号。默认值 7000.

-exclude exclude-file

指定对象查询时需要排除的数据成员列表文件 (a file that lists data members that should be excluded from the reachable objects query)。 例如,如果文件列列出了 java.lang.String.value , 那么当从某个特定对象 Object o 计算可达的对象列表时,引用路径涉及 java.lang.String.value 的都会被排除。

-baseline exclude-file

指定一个基准堆转储 (baseline heap dump)。 在两个 heap dumps 中有相同 object ID 的对象会被标记为不是新的 (marked as not being new). 其他对象被标记为新的 (new). 在比较两个不同的堆转储时很有用。

-debug int

设置 debug 级别。0 表示不输出调试信息。 值越大则表示输出更详细的 debug 信息。

-J< flag >

因为 jhat 命令实际上会启动一个 JVM 来执行,通过 -J 可以在启动 JVM 时传入一些启动参数。例如,-J-Xmx512m 则指定运行 jhat 的 Java 虚拟机使用的最大堆内存为 512 MB. 如果需要使用多个 JVM 启动参数,则传入多个 -Jxxxxxx.

实例

使用如下命令获取二进制堆转储文件

jmap -dump:format=b,file=heap-dump.hprof pid

然后使用

jhat -J-Xmx1024m heap-dump.hprof

来查看和分析堆信息,然后访问本地 7000 端口即可。

jhat 中可以使用 OQL(对象查询语言)来查询,这个 OQL 也是非常庞大,如果要展开说就很多了,这里举一个例子,比如要查找字符串对象中,保存了长度大于 100 的字符串可以使用

select s from java.lang.String s where s.count > 100

关于 OQL 更多的使用方法可以网上查询。

reference

  • map jhat

2015-01-03 java , jvm , jhat , heap , tool

jmap 命令使用

jdk 自带的命令用来 dump heap info,或者查看 ClassLoader info,等等。

命令格式

jmap [OPTION] PID

使用实例

不加任何参数

命令

jmap pid

查看 pid 内存信息。

查看堆信息

jmap -heap pid

查看堆对象信息

统计对象 count ,live 表示在使用

jamp -histo pid
jmap -histo:live pid

查看 classLoader

jmap -clstats pid

生成堆快照

jmap -dump:format=b,file=heapdump.phrof pid

hprof 二进制格式转储 Java 堆到指定 filename 的文件中,live 选项将堆中活动的对象转存。

执行的过程中为了保证 dump 的信息是可靠的,所以会暂停应用, 线上系统慎用

文件可以用 jhat 分析。

错误

在运行 jmap 的时候可能遇到如下错误:

Attaching to process ID 18078, please wait...
Error attaching to process: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 25.131-b11. Target VM is 25.152-b38
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 25.131-b11. Target VM is 25.152-b38
    at sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:435)
    at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:305)
    at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
    at sun.jvm.hotspot.tools.Tool.start(Tool.java:185)
    at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
    at sun.jvm.hotspot.tools.PMap.main(PMap.java:72)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.tools.jmap.JMap.runTool(JMap.java:201)
    at sun.tools.jmap.JMap.main(JMap.java:130)

解决办法就是保证 jmap 的版本 也就是 JDK 的版本和运行的 JVM 的版本,也就是 JRE 的版本一致。

我使用 Java VisualVM GUI 来查看当前进程使用的 Java 版本,或者直接 ps 查看进程,然后再使用对应的 jmap 的版本。

要保证 jmap 运行的版本和运行的 java 进程程序使用同一个的 JRE(JDK) 的方法就是在 Linux 下使用

sudo update-alternatives --config java

来配置保证使用相同的 Java 程序。

reference


2015-01-02 jmap , jstack , jdk , jvm , java

网件 WNDR3800 刷机

进入 U-boot

路由先断电,然后按住复位键或者 WPS 键开机,保持 10S 钟左右,然后用网线连接 LAN 口和电脑,打开浏览器进 192.168.1.1,就可以进入 U-boot 控制台,进去刷写固件

操作路径 :固件更新 -> 固件 -> 选择固件文件 -> 上传 -> 更新,刷完后机器会自动重启。

固件

自行编译

或者下载他人编译好的固件。


2014-11-25 openwrt , wndr3800 , router , linux , tutorial

继续折腾 WNDR3800 之 shadowsocks

之前 也说过在 Openwrt 下使用迅雷远程下载,现在因为不想在 PC 端总是开着一个 shadowsocks 的程序,所以将 shadowsocks 安装到路由器端。然后还顺带解决一下 DNS 污染,和流量智能转发。

Shadowsocks

下载 编译好的 ipk

opkg update
opkg install libpolarssl
opkg install shadowsocks-libev_1.5.1_ar71xx.ipk

shadowsocks 安装后有三个命令,ss-local 启动 sock5 代理,ss-redir 启动透明代理,ss-tunnel 启动隧道。这里使用了 ss-local 和 ss-redir

# 编辑 vim /etc/shadowsocks.json
{
    "server":"『服务器 ipv4/ipv6 地址』",
    "server_port":8388, #服务器端口
    "local_port":1081, #本地 sock5 代理端口
    "password":"『密码』",
    "timeout":300,
    "method":"『加密方式』"
}

修改配置文件/etc/init.d/shadowsocks

START=95
SERVICE_USE_PID=1
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1
CONFIG=/etc/shadowsocks.json
start() {
    service_start /usr/bin/ss-local -c $CONFIG
	service_start /usr/bin/ss-redir -c $CONFIG
}
stop() {
    service_stop /usr/bin/ss-local
	service_stop /usr/bin/ss-redir
}

添加执行权限,设置开机启动

chmod +x /etc/init.d/shadowsocks
/etc/init.d/shadowsocks enable

pdnsd

opkg update
opkg install pdnsd

配置/etc/init.d/pdnsd.conf

global {
    #debug = on;
    perm_cache=1024;
    cache_dir="/var/pdnsd";
    run_as="nobody";
    server_port = 1053;   #使用 1053 作为 DNS 端口,默认是 53,一定要修改否则会跟默认 dnsmasq 冲突
    server_ip = 127.0.0.1;
    status_ctl = on;
    query_method=tcp_only;#最重要的配置,只使用 tcp 查询上级 DNS
    min_ttl=15m;
    max_ttl=1w;
    timeout=10;
}
server {
    label= "googledns"; #这个 label 随便写
    ip = 8.8.8.8;    #这里为上级 dns 的 ip 地址,要求必须支持 TCP 查询,相关说明见后文注解
    root_server = on;
    uptest = none;   #不去检测 dns 是否无效。
}

启用 pdnsd,并设置为开机启动:

/etc/init.d/pdnsd enable
/etc/init.d/pdnsd restart

完成!

dnsmasq 和 ipset

openwrt 默认安装的 dnsmasq 不支持 ipset,需要先卸载,换成 dnsmasq-full,输入一下命令查看 dnsmasq 版本,写着 no ipset 的就需要安装完整版。

dnsmasq -v

运行以下命令:

opkg update
opkg install kmod-ipt-ipset ipset ipset-dns
opkg remove dnsmasq
opkg install dnsmasq-full

dnsmasq-full 从这里 下载,设置 dnsmasq 对特定域名使用本地的 pdnsd 进行解析: 为了保持配置文件整洁,建议在 /etc/dnsmasq.conf 最后加入:

conf-dir=/etc/dnsmasq.d

然后新建 mkdir 目录 /etc/dnsmasq.d ,在里面加入一个 conf,名字任选。譬如 /etc/dnsmasq.d/fuckgfw.conf , 下面是我的文件内容,你可以按自己需要整理自己的:

#Google and Youtube
server=/.google.com/127.0.0.1#1053
server=/.google.com.hk/127.0.0.1#1053
server=/.gstatic.com/127.0.0.1#1053
server=/.ggpht.com/127.0.0.1#1053
server=/.googleusercontent.com/127.0.0.1#1053
server=/.appspot.com/127.0.0.1#1053
server=/.googlecode.com/127.0.0.1#1053
server=/.googleapis.com/127.0.0.1#1053
server=/.gmail.com/127.0.0.1#1053
server=/.google-analytics.com/127.0.0.1#1053
server=/.youtube.com/127.0.0.1#1053
server=/.googlevideo.com/127.0.0.1#1053
server=/.youtube-nocookie.com/127.0.0.1#1053
server=/.ytimg.com/127.0.0.1#1053
server=/.blogspot.com/127.0.0.1#1053
server=/.blogger.com/127.0.0.1#1053

#FaceBook
server=/.facebook.com/127.0.0.1#1053
server=/.thefacebook.com/127.0.0.1#1053
server=/.facebook.net/127.0.0.1#1053
server=/.fbcdn.net/127.0.0.1#1053
server=/.akamaihd.net/127.0.0.1#1053

#Twitter
server=/.twitter.com/127.0.0.1#1053
server=/.t.co/127.0.0.1#1053
server=/.bitly.com/127.0.0.1#1053
server=/.twimg.com/127.0.0.1#1053
server=/.tinypic.com/127.0.0.1#1053
server=/.yfrog.com/127.0.0.1#1053

#Google and Youtube
ipset=/.google.com/setmefree
ipset=/.google.com.hk/setmefree
ipset=/.gstatic.com/setmefree
ipset=/.ggpht.com/setmefree
ipset=/.googleusercontent.com/setmefree
ipset=/.appspot.com/setmefree
ipset=/.googlecode.com/setmefree
ipset=/.googleapis.com/setmefree
ipset=/.gmail.com/setmefree
ipset=/.google-analytics.com/setmefree
ipset=/.youtube.com/setmefree
ipset=/.googlevideo.com/setmefree
ipset=/.youtube-nocookie.com/setmefree
ipset=/.ytimg.com/setmefree
ipset=/.blogspot.com/setmefree
ipset=/.blogger.com/setmefree

#FaceBook
ipset=/.facebook.com/setmefree
ipset=/.thefacebook.com/setmefree
ipset=/.facebook.net/setmefree
ipset=/.fbcdn.net/setmefree
ipset=/.akamaihd.net/setmefree

#Twitter
ipset=/.twitter.com/setmefree
ipset=/.t.co/setmefree
ipset=/.bitly.com/setmefree
ipset=/.twimg.com/setmefree
ipset=/.tinypic.com/setmefree
ipset=/.yfrog.com/setmefree

#Dropbox
ipset=/.dropbox.com/setmefree

#1024
ipset=/.t66y.com/setmefree

#shadowsocks.org
ipset=/.shadowsocks.org/setmefree

#btdigg
ipset=/.btdigg.org/setmefree

#sf.net
ipset=/.sourceforge.net/setmefree

#feedly
ipset=/.feedly.com/setmefree

按照这种格式指定特定的域名走代理。 server=/google.com/127.0.0.1#1053的含义是 google.com 通过本地 1053 端口解析地址 ipset=/google.com/setmefree 的含义给 google.com 的数据包打上标记,一会配置iptables时会用到 接下来配置iptables,在/etc/firewall.user里加上两行

ipset -N setmefree iphash
iptables -t nat -A PREROUTING -p tcp -m set --match-set setmefree dst -j REDIRECT --to-port 1081

每条记录都需要跟一条 ipset 设置,不要忘了。作用是把打上了标记的数据包重定向到 ss-redir 的透明代理端口

root@OpenWrt:~# cd /usr/bin
touch shadowsocks-firewall
vi shadowsocks-firewall

修改文件内容

#!/bin/sh

#create a new chain named SHADOWSOCKS
iptables -t nat -N SHADOWSOCKS

# Ignore your shadowsocks server's addresses
# It's very IMPORTANT, just be careful.
iptables -t nat -A SHADOWSOCKS -d YOUR-SERVERS-IP-ADDRESS -j RETURN

# Ignore LANs IP address
iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN

# Ignore Asia IP address
iptables -t nat -A SHADOWSOCKS -d 1.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 14.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 27.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 36.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 39.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 42.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 49.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 58.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 59.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 60.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 61.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 101.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 103.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 106.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 110.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 111.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 112.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 113.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 114.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 115.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 116.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 117.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 118.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 119.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 120.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 121.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 122.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 123.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 124.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 125.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 126.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 169.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 175.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 180.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 182.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 183.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 202.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 203.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 210.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 211.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 218.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 219.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 220.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 221.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 222.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 223.0.0.0/8 -j RETURN

# Anything else should be redirected to shadowsocks's local port
iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 1081

# Apply the rules
iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS

解释 iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 8024 这里的 8024 必须和 OpenWrt 路由器 /etc/shadowsocks.json里的 local_port 一样,也就是说,如果 /etc/shadowsocks.json"local_port":1081, 那这里的 8024 也要改成 1081(如果照着我上面的本地端口填了 8080,这里就改成 8080)

配置成功后,chmod +x shadowsocks-firewall给其运行权限。

运行

 /usr/bin/shadowsocks-firewall

重启 dnsmasq 和 firewall 就可以实现流量自动分流了

/etc/init.d/dnsmasq restart
/etc/init.d/firewall restart

以后只要修改dnsmasq的配置文件就可以指定更多的地址走代理

可选方案 解决 dns 污染

这里比较方便的是,通过 ChinaDNS 就可以了。

和安装 ShadowSocks 一样,可以先通过 WinSCP 上传到路由器。

opkg install ChinaDNS-C_1.0.0_ar71xx.ipk  # 安装
/etc/init.d/chinadns start                # 运行
/etc/init.d/chinadns enable               # 开机启动

reference

  1. http://hong.im/2014/07/08/use-ipset-with-shadowsocks-on-openwrt/
  2. http://www.jianshu.com/p/4800eec60516
  3. http://blog.berry10086.com/Tech/Openwrt/openwrt-shadowsocks-ipset/
  4. http://www.shuyz.com/install-shadowsocks-on-hg255d-openwrt-and-config-nat.html
  5. http://hong.im/2014/03/16/configure-an-openwrt-based-router-to-use-shadowsocks-and-redirect-foreign-traffic/

2014-11-24 shadowsocks , openwrt , knowledge , shadowsocks-libev

Play Clash of Clans

玩部落冲突(Clash of Clans)也已经四个多月了,这是我第一个花钱在上面的游戏,不过最近因为给别人看COC乱点花了我1200左右的钻石,顿时玩下去的信心都没有了,既然没有动力了,就来总结一下吧,就当是个结束。

很早知道这个游戏,看到很多人玩,包括很多身边的同学。但是机缘巧合有一好友也开始玩,就带着我一起开始玩了,于是从暑假开始,到今天11/5,差不多正好4个月时间,除了魔兽争霸这个游戏,还真没有一个游戏能让我坚持玩这么长时间的。什么吸引我呢?这个游戏依靠策略,攻打的策略,守家的策略,让人欲罢不能。另外就是好友及部落机制。再次就是不想偷菜种菜那么没有头脑,收集金币及圣水都是需要一定的技巧。虽然被人乱点坑了很多金币,并且不得不赞扬游戏公司对游戏参数的设置,让人无比的想花钱,并且会让人觉得花的很值得。

Clash of Clans 8本阵型

Clash of Clans

Clash of Clans 双菱形

##一些网站 YouTube Channal https://www.youtube.com/channel/UCxNMYToYIBPYV829BJcmUQg 这个频道从低等级开始,一步一步升级,单人模式,攻击策略,防御策略很全面,可以关注。

之前几个布阵的网站都是直接从Google点进去的,根本记不住网址,所以用Google喽搜喽。

##关于钻石 关于钻石,网上很多说免费的钻石的,千万别信,基本都是假的,稍微真的就是去赚礼品卡的钱,然后用礼品卡买钻石。游戏中成就和清理地面的灌木石块等等都能获取一定的钻石,所以省着点用很快能够买到第三个农民500钻,等第四个农民1000钻其实也应该很快,如果不出意外2000钻的第五个农民我马上也能有了,只是。。。。

最后有一点,我在升级过程中吃了很多苦头,就是千万不要着急升级大本营,COC匹配对手有一定的算法,当时也Google了,会根据一定的算法,等级越高越不好打,所以最好在每一个大本营造完全不建筑并且升级到最高等级不能升级再升大本营。

##一些技巧

  • 搜寻对手时可以多搜寻一些,直到找到一个资源丰富的
  • 搜寻对手时注意观察阵型及金矿圣水收集器的位置,如果在外围可以轻松拿下。
  • 单人模式一定要留到升级完气球之后,一个气球搞定

参考:


2014-11-23 游戏 , Game , ClashOfClans

电子书

最近文章

  • 如何进行有效的讨论 论 Clubhouse 这两天 Clubhouse 非常火热,又使得声音这一件事情被放到了台前,但听了多个 Room,并没有收获太多,反而是相对较大的「杂音」影响了收听,并且大部分的观点并没有让人眼前一亮的感觉。
  • 我的笔记法(借助 Zettelkasten 和 Obsidian) 在上次总结了2020读书笔记 之后,Tai 问我如何通过 Zettelkasten 和 Obsidian 来实践我的笔记。这里就也正好总结一下我自己的方法,希望可以在分享过程,或者和大家的讨论中来获取更多有效率方法。
  • 迟到的「给编程初学者的一封信」 这些天翻箱倒柜,翻出来一些大学时候的文档,其中一篇是当时上外教课时打印给我们的材料,虽然可以看得到当时也在上面做过笔记,但现在已经完全不记得有这样一份文档的存在了。但回过头再看文档的内容,每一句话都是非常珍贵的建议,是一份那个时期完全需要读一下的材料,但当时却并没有好好珍惜。这份文档的名字叫做「An open letter to those who want to start programming」,如果记得没错的话这份文档交到我手上的时候,应该就是我刚去学习如何编程的时候。如果当时就能够理解这一份文档内容的话,这些年来我肯定能少走不少的弯路。
  • 2020 读书记录 2020 年注定是会在历史上留下不平凡的一年,年初的疫情到年底问题依然还在,而且在不确定疫苗的情况,在加上英国的病毒变异情况,不清楚到什么时候才是结束。再回头看今年的大事小事,从年初的李文亮事件,到年末的蛋壳,以及阿里被禁止上A股,有些事情发生地太突然,来不及思考,但只有思考,不仅是在事前的还是事后的思考都有其价值。
  • 图片管理工具 Eagle 远在移动互联网还没有那么发达的今天,Google 曾经收购过一家图片管理与分享的网站叫做 Picasa,Picasa 同时提供了一个跨平台的照片管理工具 Picasa Desktop,用这个工具不仅可以非常方便的管理本地的图片文件,也可以非常方便的分享到 Picasa Web 上,然而随着移动互联网的到来,以及 Google 的转型,Picasa 的服务在 Google 变得没有那么重要,随即在 2016 年停止了服务,我的图片管理也被迫迁移到了 Google Photos。然而一切都开始变得不方便,Google Photos 内自动备份的照片,相册开始无法管理,并且 Google 停止了桌面版的开发,同样使得在桌面上管理图片变得困难,这些年来尝试了 Lightroom,TagSpaces 等等工具,都没有找到特别舒心的。