Recent Posts

17windy's avatar

[七日杀A18] 17windy的幻想风格武器包 Ver1.1

更新记录:

V1.1

增加了两款拳套类武器;

调整了拾取表,大幅度降低对枪械池的污染。

V1.0

初版

前言:

A18的枪械武器平衡很棒,近战武器略为弱势,种类也较少,简直逼疯懒人,好多天了也没出个正理八经完美适配A18的武器包,只能自己动手了。

说明:

武器包内包含11把适配各个近战天赋的新武器,属性各异,模型与人物适配度高,不是那种常见的塞一堆武器不管平衡和特色那种包(不包含拳套,这个调整起来麻烦,之后加)。

另外求弓、弩武器的A18文件与动画结构(官方太抠了)。

如何安装:

解压放进mods文件夹,注意看看路径别套娃。

武器获取:

搜刮和任务奖励。

如何汉化:

MOD文件夹内有Localization.txt

里面是汉化文本,请自行添加到7 Days To Die\Data\Config\Localization.txt文件的最后,就有汉化了。
(emmm,算是专门为a18开发的市面第一个近战武器模组了)

转载须知:

欢迎在国内七日杀网站转载或者整合包作者整合,转载或整合请备注该MOD作者17windy。

关于更新:

本MOD更新周期暂定于A18版本生命周期,会添加更多的武器和玩法,例如匕首+长棍合成矛等。

下载在哪:

链接:https://pan.baidu.com/s/1D8KrNdJj4iCItxEHyp6FvQ&shfl=sharepset
提取码:14s7

依云's avatar

红黑树到底是个什么树

本文来自依云's Blog,转载请注明。

红黑树使用得非常多,然而由于它不在我的本科教材上,我又不用自己实现它,所以我一直不知道它是什么样的。现在想了解一下,结果发现网上我看了好几篇的中文资料都是这种介绍方式——

假设要介绍的树叫梧桐树。文章会告诉你梧桐树会长多高,树叶长什么样,分叉有什么特征,它和棕榈树有什么不同,还会贴心地放一张或者多张梧桐树的照片给你看。

然而红黑树不是梧桐树啊!计算机科学也不是植物学啊!它是为特定目的人造的!所以你倒是说说它为什么会被设计成这个样子啊……

然后我去看了一眼英文维基百科上的介绍,才看了第一段就恍然大悟。

A red–black tree is a kind of self-balancing binary search tree in computer science. Each node of the binary tree has an extra bit, and that bit is often interpreted as the color (red or black) of the node. These color bits are used to ensure the tree remains approximately balanced during insertions and deletions.

意思是,红黑树是一种自平衡二叉树。每个节点有一个额外的比特,通常叫它颜色,并且是红的或者黑的。所以红黑树之所以叫红黑树,只是发明者为了方便叙述给加了点颜色,就跟数学里那些个着色问题(以及物理里夸克的颜色和味道)一样。为什么要加这些颜色呢?它们是用来保证树大致平衡的。

神奇了,为什么加了这么个颜色就能保证了?

Balance is preserved by painting each node of the tree with one of two colors in a way that satisfies certain properties, which collectively constrain how unbalanced the tree can become in the worst case. When the tree is modified, the new tree is subsequently rearranged and repainted to restore the coloring properties. The properties are designed in such a way that this rearranging and recoloring can be performed efficiently.

哦,是用特定的方法着色的,并且树被修改的时候会重新着色。神奇的算法使得这些操作非常高效。也算是用空间换时间了。

The leaf nodes of red–black trees do not contain data. These leaves need not be explicit in computer memory—a null child pointer can encode the fact that this child is a leaf—but it simplifies some algorithms for operating on red–black trees if the leaves really are explicit nodes.

红黑树的叶子节点总是黑色的,并且不包含额外的信息。所以实现的时候实际上不需要显式地存在,或者用同一个节点就好。它的存在只是为了简化算法描述而已。

红黑树的性质:

  1. 每个节点不是红色就是黑色。多出来一比特的信息,当然只有两种选择了。
  2. 根节点是黑色。
  3. 叶子节点是黑色。
  4. 红色节点的子节点是黑色。这是为什么非要加个不包含任何信息的黑色叶子节点了。不然弄出来红色叶子节点有点麻烦了。
  5. 任意节点到它下方的叶子节点,路径上的黑色节点数是相同的。再一次体现了黑色叶子节点的用处。

这些性质保证了,从根节点到所有叶子节点,最远的路径最多是最近的路径两倍远。不会特别远,甚至是退化成链表了。

然后是树上的操作。

查找就不用说了。二叉树的查找算法而已。

插入的时候,首先把新节点涂成红色,按二叉树的方式插进去,取代某个叶子节点,并自己长出两片叶子。然后修复一下。修复方案如下:

  1. 如果这是个根节点,那么涂黑就完事了。
  2. 如果它的上级节点是黑色,黑色节点下接红色节点,没事,不需要更多操作了。
  3. 如果它的上级节点是红色,并且它的上级邻节点是红色,这就坏事了,违反了性质4。那就把它们涂黑。可这样多了一层黑节点,又会违反性质5。那就把上上级节点涂红(由性质4,上上级节点之前肯定是黑色)。可如果上上级节点是根节点,又违反了性质2。不过上上级节点带的这部分子树肯定是没问题的,那就把整个上上级节点带的这棵子树当整体,递归修复一下好了。
  4. 如果它的上级节点是红色,并且它的上级邻节点是黑色,这还是破坏了性质4。而这个时候如果把上级节点涂黑,那么上上级节点不管涂不涂红,一边加了一个黑节点而另一边没有加,它这个子树本身就已经坏掉了,所以得想另外的办法。
    1. 第一步,如果上级节点在左边,而新加节点在右边,那就左旋。如果上级节点在右边,而新加节点在左边,那就右旋。其它情况不用动。由于是两个上下级红色节点在旋转,这样并不会再破坏任何性质。
    2. 第二步,两个红色节点和可以被取代的叶子节点已经准备好了,现在把上上级节点(也就是动过的子树的上级节点)用子树的根换掉,原来的挂到上一步空出来的叶子节点那里,并且把新根涂黑,把一开始那个碍事的黑色节点涂红。这样,两个红色节点就成了同一个黑色节点的子节点。性质4得到了保持,涂色过程只是把黑色上移取代之前的红色,一边的路径上少了个红色节点,另一边多了个红色节点而已,也不会破坏性质5。

删除就更复杂了。

  1. 如果被删除的节点有两个非叶子节点,按二叉树的方法删除节点,但是保持原来这个位置上节点的颜色。因为子树的根被保留颜色地替换了,所以这一步不会破坏性质。而少了的(被作为新子树根替换的)节点,递归这个删除算法就可以了,一直在深入,总能递归到没有两个非叶子节点的节点。
  2. 你不会想删叶子节点,也不能删它们。
  3. 所以剩下一种情况:被删除的节点最多有一个非叶子子节点。如果有的话就叫它 C 好了,没有就随便找个叶子节点当 C。那被删除的节点我们叫 M。
    1. 如果 M 是红色,那用 C 取代它即可。因为 C 肯定是黑色(而且是叶子节点)。
    2. 如果 M 是黑色,但 C 是红色,用 C 取代 M,并且把 C 涂黑。少了一个红色节点而已,没事的。
    3. 如果 M 和 C 都是黑色,这个时候 C 也一定是叶子节点。先用 C 取代 M,并叫新的 C 为 N,其上级节点为 P,P 的另一个子节点为 S。现在 N 这边少了个黑色节点,相对的,S 这边多了一个。
      1. 如果 N 是根节点(P 不存在),那么没事了。
      2. 如果 P 是黑色,并且 S 是红色,旋转一下,让 S 成为新的子树的根,并将 P 涂红。从颜色上看,只是红色从一个子节点跑到另一个,然后有棵子树从一边换到另一边了,性质不会被再度破坏。但之前被破坏的部分还没修复呢,现在是一个黑色下边有一个黑色的节点那里的路径上多了一个黑色节点,要走下边的步骤。
      3. 如果 P 和 S 都是黑色,N 那边不是被删掉了一个黑色节点吗,现在把 S 涂红,这样 P 的两边(N 和 S)都少了个黑色节点。子树没有问题,然而 P 这边的路径上少了个黑色节点。要么 P 是根节点,不用管了。要么 P 的邻节点那边的路径多了个黑色节点,情况就是一个子树,下方有一个黑色节点,并且这一边的路径上多了个黑色节点。如果子树的根是黑色,那么递归了,回去再走一遍上一步(3.3.2)就好。如果是红色,走下边的步骤。
      4. 如果 P 是红色,并且 S 和 S 的子节点都是黑色,把 P 和 S 的颜色交换一下,S 那边的路径少了个黑色节点,处理好了。
      5. 如果 P 是红色,N 位于左侧,并且 S 的左子节点是红色,右子节点是黑色。N 当然是黑色的啦。那么把 S 右旋,并且把旧 S 的左节点(新的子树根)涂黑,然后旧 S 自己(新右子节点)涂红。继续下边的步骤。
      6. 如果 P 是红色,N 位于左侧,并且 S 的左子节点是黑色,右子节点是红色,把 P 左旋一下,并把之前那个红色子节点涂黑。这样 N 那侧的路径多了个黑色节点。完成了。
      7. 如果 P 是红色,N 位于右侧。把上两步镜像一下就可以了。

总之就是各种涂色和旋转,来保持二叉树和红黑树的性质不被破坏(红黑树是二叉树,所以旋转需要点技巧,不是想旋转就一定能旋转的)。看着复杂,照着前人已经想好的步骤去做其实也并不难。然而中文网络上几乎没有人解释这些步骤的目的,以至于让人理解不能 :-(

AlisterTT's avatar

古米

乌萨斯三杰算是都画完了…

RecursiveG's avatar

Haskell 简易指南

Haskell 简易指南
Roy Binux's avatar

Zerotier Nat 网关出口 和 iptables 调试

每当看到各类教程中的 iptables 指令,在格式参数组合之下可以实现从防火墙,封禁 IP 端口到 NAT 的各种操作,就如同魔法一般,看不明白,却又感到无比强大。想学,但又好像不得要领,稍微不慎可能就再也连不上了。最近配置 Zerotier 的 Nat 网关的时候,看着

Roy Binux's avatar

少女前线拖尸脚本 和 生成它的可视化工具

最近在玩少女前线,这是一个手机游戏,over。不是,就真的没有什么好讲的嘛,了解的人早有耳闻,不了解的就只要知道这是个手机游戏就好了,嗯。

然后,我会好好地,正常地,氪金地去玩这个游戏吗?不可能的,玩游戏哪有破解它有意思呢。当年破解 Ingress 是因为它用的 HTTPS 通信的,算是本行。百万亚瑟王是因为别人已经逆向好了,我只是写了一些 bot。现在这么办,玩不了了吗?作为一个不会安卓,不会逆向,不会汇编的菜鸡,那我只好上按键精灵了啊。于是乎,我找到了这个: AnkuLua

AnkuLua 是一個專注在自動化的Android App
基本自動化動作有:

  • 抓取螢幕並找尋指定圖案
  • 對找圖結果採取使用者要的動作(例如點擊、抓放(drag and drop)、打字…等等)

最重要的是,它能运行 lua 脚本!虽然我是一个不会安卓,不会逆向,不会汇编的菜鸡,但是我会 lua 啊。

ankulua-vision

不过,在使用过程中发现,找寻指定图案,需要不断截图/裁剪,这样太麻烦了。于是我又用 electron 做了一个可视化的截图资源管理器 ankulua-vision,像这样的:

基本思路就是,一般游戏是由众多 UI 界面组成的,点击某个按钮能跳转到某个界面上去。那么通过截图,标注识别区域,那么程序就能知道游戏现在所处的界面。通过标注按钮区域,那么只需要 goto('battle'),程序就能自动规划从当前界面到 battle 的可行路径,然后点啊点啊就完成需要的操作了。这样一方面不需要自己去裁剪图片了,另一方面通过框架代码,在运行过程中能够有更多的错误检查,自动应对可能出现的各种异常。

理论上,对于点啊点的游戏,是能实现无代码的。即使不能,对于复杂的动作,也可以通过 lua 拓展。

源码在这里:https://github.com/binux/ankulua-vision

你依旧需要在安卓手机或者模拟器中安装 ankulua,然后加载生成的 start.lua 脚本。默认自带了一个简单的循环逻辑,运行后可以直接图形化界面配置运行。当然你也可以通过 lua 脚本拓展,除了 ankulua 本身的 API 可用之外,你也可以使用 stateMachine 这套界面跳转逻辑 API,重用简化步骤。stateMachine 的 API 在 README 中有简略的文档说明。

源码使用 GPLv3 或 MIT 许可证,取决于第一个有效 PR(例如 fix typo 不算),如果第一个 PR 之前有商业化需求或者 PR 作者要求,则 MIT。

少女前线拖尸脚本

WARNING: 任何使用脚本的行为都是官方禁止的,我不对下文所述任何内容以及其后果负责

于是,这里就是 少女前线的拖尸脚本:

https://github.com/binux/binux_github_com/releases/download/gf/shojo.zip

同时它也是一个 ankulua-vision 的项目,你可以通过 ankulua-vision 打开这个项目目录,调整截屏或者按钮位置。

脚本实现的功能

  • 43e, 02, 52n 拖尸
  • 自动重启后勤
  • 自动强化或者分解人形
  • 自动修理

使用方法

  1. 根据 [填坑结束?][失了智]萌新向拖尸教学帖[更新8-1N相关] 一文准备好打手和阵型,一队练级队,二队补给队,52n 还需要 3 队狗粮队。
  2. 解压拷贝脚本到手机中,在 ankulua 中加载 start.lua。
  3. 在启动界面中选择你的两个打手(每轮结束后,两个打手会交换),选择拖尸任务,如果仅自动后勤,选择 null 就好了。

其中 52n 会在战斗中撤退 5, 8 号位 (见 NGA 文 “43e的说明” 展开部分),02 在选择 m4a1 时会撤退 1, 7 号位。

然后开始吧!

WARNING: 任何使用脚本的行为都是官方禁止的,我不对上文所述任何内容以及其后果负责

over

Roy Binux's avatar

2018 新的冒险

真的又是好久没有写 blog 了。

年纪大了,记忆力下降,没有学习新东西的动力,也没精力折腾新的技术,新的领域了。每天就是看看斗鱼,打打游戏就过去了,现在的理想就是早点退休,当条咸鱼就好了。

2017 年主要给公司开发了一套基于 electron (chromium) 的页面渲染后端,可以保证抓取时和用户浏览器中看到的保持一致。同时这个服务器端的浏览器,可以通过 websocket 连接用户浏览器,双向同步页面内容变化,录下用户操作,在抓取时进行重放。这些功能我真的很想做给 pyspider,但是确实不方便。眼见着 pyspider stars 过万,而我却渐渐没有精力去维护了。我的希望是以后从现在的公司离职之后能有2-6个月全职开发 pyspider,算是这几年项目荒废的补偿吧。

公司终于把伦敦办公室关闭了,我也随着搬到了美国(湾区)。随便写一点美国的感受吧:

  • 加州税真高,比英国还高,英国人家好歹有免费医保啊
  • 美国真的是物资极大的丰富,真的可以理解为什么很多中国人来了就想要留下来,小富即安
    • 地广人稀,使得超市都是 super 起步的,这样会让选择非常多,卖的量都是加大号的
    • 充足的停车场,汽车出行不用担心不方便停车
    • 汽车让生活半径极大扩大,湾区各种中餐半小时车程都能到达,而半小时车程也不过是正常通勤所花的时间
    • 各种服务比起英国齐全多了,而且周六日不休
    • apartment 社区大都自带 365 天 7 * 24 开放恒温游泳池,健身房等设施(即使大冬天根本没有人去用,水也是恒温并更新的)
  • 非实时记账,很多场合真的需要使用支票,需要通过账单付费;因为是后付费,需要 SSN 查询你的信用记录。真的很不方便。
  • 租房好贵,宽带好贵,手机卡好贵,小费好贵

总体来说,英国更接近国内的政府+生活模式,而美国是只要你花钱,什么都有,不花钱,滚蛋。反正 L1 签证也就 3 年,也不能跳槽,而且就美国这个 H1B 抽奖 + 绿卡排队,比起英国来简直就是地狱模式。趁着这几年,在美国多玩一玩吧。9酱。

violet's avatar

给 Surface pro 3重新灌上 windows

之前写了一篇博客讲如何在 surface pro 3 上安装 Linux 的。装好之后其实一直没用,一来是因为我又买了个笔记本当主力军,二来是苏菲用来实在是让人非常不满意。

violet's avatar

搞起一个测试 Golang HTTP server 的性能测试

现在在工作中开始搞 Go 了,重构了一个工具,查了一波如何做性能测试,就当记个笔记。

Yeechan Lu's avatar

我的浏览器地址栏中的 A – Z(2017 秋)

前略,天国的 2017 酱。时光荏苒,又是半年过去。从镇江搬到上海,从学校进入公司,从淋了馄饨汤以至于两三年断电时间不超过二十分钟的 MacBookAir6,2 换成了崭新的 MacBookPro14,2,从镇江白天联通夜里电信的校园网变成了 24 小时的镇江移动、又变成了传说中的魔都电信。遇见了武汉,走过了西安,滑过了绍兴。即使如此,最近常用的浏览器仍然是 Google Chrome Canary (macOS & Windows)。

  • Airtable.com
  • Binux.github.io/yaaw/demo/
  • Cs.chromium.org
  • Dearti.me
  • E-hentai.org
  • Fastmail.fm
  • Git.orzfly.com
  • Hub.docker.com/r/gitlab/gitlab-ce/tags/
  • Ip.cn
  • Jd.com
  • Kuaidi100.com
  • Lab.hackplan.com
  • My.zerotier.com
  • Namesilo.com
  • Orzfly.com
  • Pan.baidu.com
  • Qcloud.com
  • Rm.66rpg.com
  • Strongpasswordgenerator.com
  • Taobao.com
  • U2.dmhy.org
  • V2ex.com
  • Weibo.com
  • Xiaomi.com
  • Yanfly.moe
  • Zerotier.com
's avatar

TINC - 构建 IPv6 隧道及私有网络

Tinc VPN 是一个轻量型的 GNU 协议下的开源软件,通过隧道以及加密技术在互联网点与点之间创立隧道。VPN 是 IP 层面上的,所以可以像普通的网络设备那样,不需要去适配其他已经存在的软件
's avatar

DN42 - 一个大型的 VPN 网络

DN42 是一个大型的 VPN 网络,通过 GRE, OpenVPN, Tinc, IPsec 等隧道将不同地区的用户连接在一起,同时使用 BGP 协议宣告自己的网段,实现用户之间的互联互通。
's avatar

Proxmox OpenVZ 虚拟机部属 IPv6 地址

最近趁着 Dacentec 的特价服务器上架了,趁机上了一台来玩耍。机子总体的性能还过得去,毕竟一分钱一分货,钱没到位货就不能要求太高。一开始装机的时候,是给了 IP-KVM 让我自行安装的,然而组了软 Raid1 然后 Debian / Ubuntu 等系统我都没做好启动的设置,所以干脆直接就安装了 Proxmax 这个虚拟化系统。
's avatar

DANE 简介以及配置方式

DANE 并不被浏览器原生支持,需要另外安装 Add-ons 才能看出效果
's avatar

NameSilo 配合 Rage4 DNS 部署 DNSSEC 功能

上回我简单讲了一下关于 DNSSEC 的内容,可以参考
's avatar

我所理解的 DNSSEC

起初,DNS (Domain Name System) 在设计上面并没有过多的去考虑安全的问题,也没有去考虑解析结果会不会被挟持的问题。当时的网络环境比较良好、安全,况且能接入互联网的人数并不多
's avatar

DNS 标志位简要解析

根据规范,一个 DNS 包可以分为下面的几个部分
's avatar

从 git commit 中永久删除某个文件

最近在帮别人看他的一个项目,项目通过 git 管理。在我 git clone 到本地的时候,发现这个工程目录十分大。经过分析,他将很多无谓的文件也 commit 上去,例如
's avatar

Amazon Glacier 简单介绍及服务器备份方案

最近突然想到要为自己的 VPS 做一个异地备份的方案,看了一下各家的方案,然后发现了 Amazon Glacier 可以满足我的需要,但是网络上却很少找得到备份到 Amazon Glacier 的文章,大多数都是备份到 Amazon S3 的,因此特意写一篇文章分享给大家。
's avatar

编译 OpenWRT 平台上的 gdut8021xclient 校园网客户端

gdut8021xclient 是 hazytint 在 njit8021xclient 基础上进行修改的、适用于广东某工业大学的 802.1X 客户端
's avatar

通过 Nginx 使用 Google Analytics 服务

一直以来,我的博客都是使用 Google Analytics 来统计网站的访问人数
's avatar

如何启用 Certificate Transparency

根据维基百科的解释,Certificate Transparency (CT) 目前是一项实验性的 IETF 开放标准以及开放源代码的框架,用于监控以及审计数字证书。通过证书日志、监控以及审计系统,将允许网站用户以及域名所有者来判断辨别错误或者恶意签发的证书,并且可以找出那些流氓的 CA 。
's avatar

关于 XSS 的思维导图

XSS1.png / XSS2.png 均转载自 长短短
's avatar

将域名加入 HSTS Preload List

大家可以参考我之前写的博文,里面有对 HSTS 的简介
's avatar

通过 JetBrains 学生认证免费使用 PhpStorm 等编辑器

今天给大家介绍以下 JetBrains 家的学生认证,JetBrains 家主要是做各种语言的编辑器,非常强大的编辑器!
's avatar

研究学校网络 hao123 被挟持的问题

前几个星期,在学校贴吧看到了有校园网用户反应 hao123 无法打开,目测存在循环重定向的问题:[校园网他妈的是被劫持了吗
's avatar

我所理解的 iptables u32 匹配

昨天晚上,为了解决运营商的网络挟持问题,我苦看了很久 iptables 的文档:iptables(8) - Linux man page
's avatar

gotunnel.org 网站简介

gotunnel.org 是一个非官方的 ngrokd 服务器,由本人建立并部署在一台香港的 VPS 上。
's avatar

「翻译」ngrok 1.X 配置文档

ngrok 的配置文件是完全可选的非常简单 YAML 格式文件,他可以允许你使用 ngrok 一些更高级的功能,例如:
's avatar

「翻译」ngrok 1.X 使用文档

ngrok 能让你映射一个正在本地运行的 web 服务到互联网上。只要告诉 ngrok 哪一个端口是你的 web 服务运行的即可
's avatar

正确地配置一个安全的 https 网站 (nginx/Apache/Lighttpd)

如果你想配置一个安全的 https 网站的话,你就可以需要下面这个了。
's avatar

Hello World

关注本站的同学都应该知道,本站由于某些不可抗力的原因已经关闭很久很久了。
's avatar

使用 Duo Secrity 二部验证保护你的 SSH 安全

Duo 可以轻松地使用在 Unix 系统中,以保护你的 SSH 或者本地连接。它已经在 Linux 系统 ( RedHat, Fedora, CentOS, Debian, Ubuntu, Gentoo, Amazon Linux)、BSD 系统 (FreeBSD, NetBSD, OpenBSD, MacOS X ) 、Solaris、HP-UX 以及 AIX 系统中经过测试。
's avatar

Duo Security - 一款好用的双因素身份验证产品

最近,某大型网站被纰漏出了可能存在严重的帐号泄漏漏洞。参考乌云的信息:
's avatar

Python 支付宝免签工具发布

这是一个比较简陋的工具,起码,暂时来说,比较简陋,但是功能确实实在的。
's avatar

2015.10.04 本站所做的一点优化

本篇博文主要讲一下今天我对本站所做的一些优化。
's avatar

生成并成功签署 ECC SSL 证书

椭圆曲线密码学(Elliptic curve cryptography,缩写为ECC),一种建立公开金钥加密的算法,基于椭圆曲线数学。椭圆曲线在密码学中的使用是在1985年由Neal Koblitz和Victor Miller分别独立提出的。
's avatar

树莓派通过 n2n 实现内网穿透

由于我将要把一台树莓派放在学校内网挂校内的 PT ,并且这台树莓派又是通过路由器接入校园网的,那这样问题就来了。
's avatar

gnutls.h: No such file or directory 的解决方案

同上文一样,同样是在安装pyspider的过程中遇到的问题。
's avatar

Could not run curl-config 的解决方式

在安装pyspider的时候我就遇到了这个问题,pyspider依赖pycurl这个库,而pycurl要求系统中存在相对应的库。
's avatar

Removed according to regulations.

Removed according to regulations.
's avatar

「翻译」阻止 DHCP 修改 resolv.conf 文件

最近在 vultr 新建了一个德国的 VPS ,由于我的某些需求,需要使用 VPS 访问某个域名下的资源。但很不幸,每次我尝试去连接这个资源的都是,都是提示域名解析失败诸如此类的错误,经过检查,我发现是 vultr 自带的 DNS 的问题造成的。
's avatar

利用闲置 VPS 挂 eBesucher 赚钱 (Debian)

eBesucher 是德国一家老牌的挂机网赚以及网站推广的网站,官网号称从2002年就开始经营,域名注册于2005年09月07日,经营了也快10年的,所以来讲信誉应该来说是值得信赖的。
's avatar

GOGETSSL 证书购买记

在这个神奇的国度,我们无时无刻都在被xx着,移动/联通等挟持我们的淘宝,自动为我们加上淘宝客的小尾巴,他们便以此牟利!连上个百度,都同样面临着被挟持的可能!
's avatar

将数据从 MySQL 迁移到 MongoDB

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
's avatar

发布 Python 库到 pypi 服务器

首先,你需要一个setup.py文件
's avatar

使用 R820T2 电视棒监测空中飞机

下载完上述文件后,我们需要先运行安装VirtualRadarSetup.exe,安装需要.net 3.5环境,建议你自己去其他地方下载,不然如果使用微软的服务器是很慢的
's avatar

使用 R820T2 电视棒收听 FM 广播

首先简单介绍一下我们的设备,就是一个十分简单、小巧的电视棒,他的芯片型号是:Rafael Micro R820T2。
's avatar

轻松组建分布式 pyspider 集群

写爬虫爬站,你只有一台机子怎么能叫一个科学的、高效的爬虫呢?你起码得要有成百上千台机子一起跑才叫爬虫吧~当然,我是开玩笑的,而且我觉得谁没事开成百上千个服务器来跑爬虫(当然,除了B/G等)
's avatar

Debian 8.1 安装配置 pyspider 爬虫

pyspider 是由 binux 开发的具有以下特性的开源 python 爬虫程序
's avatar

Linux 服务器被 DDoS / CC 时应急的封 IP 方法

当我们的 Linux 服务器受到少量攻击时,这时候我们可以使用 iptables 来手动封禁这些攻击者的IP。
's avatar

Shell 下免密码快速登陆 MySQL 数据库

当我们在Shell下想要通过mysql-client登陆到MySQL数据库的时候,我们总是需要非常麻烦的输入一次又一次的密码。
's avatar

MultiGet - 一个超简单的多线程下载工具

MultiGet 是一个跨平台的多线程下载软件,支持Windows/Linux/BSDs/MacOS等操作系统。软件编写于C++,界面使用的是wxWidgets。
's avatar

解决 mysql_config not found 的问题

在我使用pip install MySQL-python安装mysqldb的时候,就出现了下面的问题
's avatar

Debian 7.8 (Wheezy) 升级 Debian 8.0 (Jessie) 备忘及教程

本教程在 Debian 7.8 (Wheezy) 中测试通过,但由于服务器 / VPS的不同,不保证此教程在所有服务器 / VPS中都能正常运行。
's avatar

Chrome 通过HSTS强制使用 HTTPS

国际互联网工程组织IETE正在推行一种新的Web安全协议HTTP Strict Transport Security(HSTS)
RecursiveG's avatar

编写一个简易的Chrome扩展

时隔半年的毫无诚心的流水帐作品。
假设读者有基础的Javascript能力。

起因

常去的某资源站的某资源发布者喜欢把重要的内容加上花里胡哨的特殊效果并藏在页面的角落里。
虽说要尊重资源的发布者,不过这种给人添堵的行为实在令我感到不爽,于是研究了一下Chrome的扩展程序(Extension)。

基本思路

要干的事情有两件:

  1. 将内容移到页面的显著位置
  2. 去掉辣眼睛的特殊效果 好吧,其实这条并不重要,毕竟内容已经被移到显著位置了

很自然的,直接用Javascript操纵DOM树即可实现希望的效果。
那么要怎么自动载入脚本呢?

编写扩展

感谢Chrome提供了强大的扩展系统。自动载入脚本这种功能自然是小菜一碟啦。
首先编写一个脚本content_script.js操纵页面元素:

1
2
3
4
5
6
if (page_require_modification()) {
var content = document.getElementById("hidden-div").innerHTML;
var clean_content = document.createElement("p");
clean_content.append(document.createTextNode(content));
document.getElementById("main-div").append(clean_content);
}

没有魔法,想干啥就写啥,就像是HTML本身引用了一个JS文件一样。也不需要考虑document.ready的问题,因为Chrome默认会在文档加载完成后再加载自定义的JS。

接着需要一个manifest.json文件,这样Chrome才能将其作为一个Extension加载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"manifest_version": 2,

"name": "在这里填上扩展的名称",
"description": "这里填一些描述",
"version": "1.0",

"content_scripts": [
{
"matches": ["https://www.google.com/*"],
"js": ["content_script.js"]
}
]
}

你觉得我会把实际的URL写出来嘛?肯定不会啦!
Chrome把这种注入到页面中的脚本称做content_scripts。当页面的URL符合matches中的pattern时,就自动加载js中指定的脚本。当然,脚本的文件名可以自由决定,只要前后一致即可。

最后一步,将manifest.jsoncontent_script.js放入同一个文件夹。然后在chrome://extensions选择加载已解压的扩展程序即可加载扩展啦。

总结

  • manifest.json文件指示了一个Chrome扩展
  • Chrome扩展能将自定义脚本注入到符合指定URL的页面中
  • 这种单纯的脚本注入任务可能Greasemonkey更适合一些,不过这次就先研究Chrome扩展啦~ 有机会再研究油猴脚本。
  • Chrome扩展可以和浏览器本身做到更紧密的结合,比如提供菜单项或者是GUI之类的,不过这篇文章完全没有涉及。
  • Google的官方扩展指南永远是你的好伙伴
violet's avatar

纪念死掉某桌面

检查草稿箱的时候发现还有这么篇博客,大概看了看,反正也没心情再写了,就这么发出来吧。

violet's avatar

关于 Ubuntu 上时不时 SSID 消失的问题(二)

问题描述看这个 关于 Ubuntu 上时不时 SSID 消失的问题

本来嘛,这个 bug 复现率不高,于是都拿复现率低来挡回去,懒得修。结果有个同事是神人,能给我 100% 复现,我被他的老大日了一脸,灰头土脸修 bug 了。

Yeechan Lu's avatar

我的浏览器地址栏中的 A – Z(2017)

前略,天国的 2014 秋君。两年半时光飞逝,早已不如从前。OS X 已不在,Pebble 也退出了舞台。Chromium 不再内置 Google 的 API Key,因此无法再使用 Chrome Sync,我也疲于定期手动更新、装 Flash 插件。所以最近常用的浏览器是 Google Chrome Canary (macOS & Windows)。

  • Aria2c.net
  • Bilibili.tv
  • Chrome-extension://laookkfknpbbblfpciffpaejjkokdgca/dashboard.html (Chrome 的 Momentum 新标签页插件)
  • Douyutv.com/cave
  • Evolution.voxeo.com
  • Fastmail.fm
  • Git.orzfly.com
  • Haibara.*******.***
  • Ip.cn
  • Jjxke1.ujs.edu.cn
  • Kuaidi100.com
  • Lixian.xunlei.com
  • Msdn.itellyou.cn
  • Newrelic.com
  • Orzfly.com
  • Pan.baidu.com
  • Qingcloud.com
  • Rm.66rpg.com
  • Share.dmhy.org
  • Taobao.com
  • Urpgs.com
  • V2ex.com
  • Weibo.com
  • Xiaomi.com
  • Youtube.com
  • Zhuce.com
RecursiveG's avatar

借助IPsec和strongSwan建立隧道并分配IPv6地址

准备

在一年前,我写过一篇文章,介绍利用GRE隧道将一台服务器的IPv6地址“分配”给另一台电脑,令其能访问IPv6网络的方法。
不过那种方法存在一些问题:

  • 不能通过NAT
  • 数据不加密
  • 需要在服务器手动更新IP

于是热爱折腾作死的我研究了一下使用IPsec配合IKEv2对流量进行加密的方法。

服务器与本地均为ArchLinux(Arch大法好),strongSwan软件包可从AUR安装。
服务器需要至少有一个公网IPv4和一段Routed IPv6 Subnet。

生成密钥

我们一共需要三对“密钥-证书”对:

  • CA密钥和证书:用于签署其它的证书,同时CA证书需要分发到所有机器上。
  • 服务器密钥和证书
  • 客户端密钥和证书

我使用了ECC证书,因为其具有更短的长度。如果老版本不支持ECC的,也可以使用RSA证书。
先生成三把私钥:

certtool --generate-privkey --ecc --outfile ca.keycerttool --generate-privkey --ecc --outfile server.keycerttool --generate-privkey --ecc --outfile client.key

然后自签名CA证书,Common Name可以随意填,但是和之后的配置一定要统一:

certtool --generate-self-signed --load-privkey ca.key --outfile ca.crt

接着再用CA证书签名其它两把密钥,Common Name同样可以随意填,但是不要一样:

certtool --generate-certificate --load-ca-privkey ca.key --load-ca-certificate ca.crt --load-privkey server.key --outfile server.crtcerttool --generate-certificate --load-ca-privkey ca.key --load-ca-certificate ca.crt --load-privkey client.key --outfile client.crt

这样就一共产生了六个文件,保存备用。

服务端设置

首先需要把密钥文件放到对应的位置:

  • ca.crt放入/etc/ipsec.d/cacerts/
  • server.key放入/etc/ipsec.d/private/
  • server.crt放入/etc/ipsec.d/certs/

然后编辑/etc/ipsec.secrets文件,注意空格

"CN=IPsec server" : ECDSA "server.key"

前面CN=...那一串是证书的Subject,CN即Common Name,可以通过certtool -i < server.crt查看。

最后编辑/etc/ipsec.conf文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
config setup
charondebug="cfg 2, dmn 2, ike 2, net 2"

conn serverconn #此处是链接名称,可以自由填写
left=%any
leftcert=server.crt
leftid="{这边填入server.crt的Subject}"
leftca="{这边填入ca.crt的Subject}"
leftsubnet=::/0 #表示整个IPv6网络都在这端

right=%any
rightca="{这边填入ca.crt的Subject}"
rightsourceip=2001:abc:def:123:456::/80 #客户端IP所在的/80段

auto=add
keyexchange=ikev2
ike=aes256gcm128-sha2_512-modp4096! #选择你喜欢的加密方法

然后打开IPv6 Forwarding并启动服务

sudo sysctl net.ipv6.conf.all.forwarding=1sudo systemctl start strongswan

客户端设置

步骤基本相同。

  • ca.crt放入/etc/ipsec.d/cacerts/
  • client.key放入/etc/ipsec.d/private/
  • client.crt放入/etc/ipsec.d/certs/
  • 编辑ipsec.secrets"CN=..." : ECDSA "client.key"

编辑/etc/ipsec.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
config setup
charondebug="cfg 2, dmn 2, ike 2, net 2"

conn clientconn #此处是链接名称,可以自由填写
left=%any
leftcert=client.crt
leftsourceip=%config6 #从服务器获取一个IPv6地址

right={这里填上你服务器的IPv4地址}
rightid="{这边填入server.crt的Subject}"
rightsubnet=::/0 #表示整个IPv6网络都在另一端

auto=start #自动连接
dpdaction=restart #自动重连
keyexchange=ikev2
ike=aes256gcm128-sha2_512-modp4096!

然后执行sudo ipsec start --nofork,如果出现keeping connection path字样应该就连接成功了。网卡上会出现一个新的IPv6地址,然后就可以直接访问IPv6网络了。

如果连接不成功或者是无法访问网络,可以考虑检查一下防火墙是不是把数据包drop了。

References

violet's avatar

关于 Ubuntu 上时不时 SSID 消失的问题

久仰这个 bug 啊,自从李先生吃上了 Ubuntu 16.04 之后我就听闻了这个 bug,在 suspend 几次之后就会出现 SSID 扫不到的事。入职这边之后的确接触了很长时间 Ubuntu,然后碰到了这个 bug,复现率不算特别高,但是也经常出现烦人。偶尔逮到一次,于是来看看到底是怎么回事。

Roy Binux's avatar

Data Highlighter

又是好久没有写 blog 了。现在确实没有上学的时候愿意折腾了,能用钱解决的问题,就不自己动手了。但是,很久不写 blog 这事呢,其实就是因为懒 _ (:3」∠) _。

这里带来的是

violet's avatar

关于安装Fcitx输入法

我发现有些人啊,就是喜欢搞些大新闻,用了 Linux ,吵着非说输入法不会用,这么简单的东西,都不会配置,以后报道上出什么问题,你们可是要负责的啊!

1. 善用 `fcitx-diagnose`

这个工具就是提供来检测fcitx配置上出什么问题的工具。输出的红字就是你需要注意的地方。所以,不管怎样,安装上了之后先运行一遍 fcitx-diagnose 吧。

2. 最常见的错误!!!

这是我见过最多最多最多的错误,几乎每个人都会遇到。如果安装了 Gnome,默认的输入法应该是 ibus,系统会把输入法相关的X的配置都设置成 ibus ,所以就卡到了 fcitx 。如果你安装了之后默认输入法不是 ibus 那就跳过这段。

解决方法,首先检查你的系统里有没有装 ibus,如果装了,卸载掉,别管你用什么 im-selector, 什么 im-switch 之类的,统统把 ibus 卸载掉。

接着打开 `~/.xprofile`,把下面的配置写进去,如果没有这个文件就创建一个。

 export GTK_IM_MODULE=fcitx
 export QT_IM_MODULE=fcitx
 export XMODIFIERS=@im=fcitx

写进去之后,重启 X ,一般的 DE/WM 直接 logout session 就行,但是没那个按钮你就可以粗暴一点,直接杀掉 X 。

# pkill -9 X

接着从 DM 登录那里再登录回来,运行一下 `fcitx-diagnose`,基本上这个时候是没什么问题了。

3. 界面问题

这也是个很头疼的问题,之前好久都没有用过 Mint 了,有次装上了 Mint ,发现死活找不到 fcitx 的界面,这个就很尴尬了。后来问了问 Aron 才搞定。综合过来,界面记得要装 gtk2, gtk3, qt4, qt5,总之都装上再说。手头暂时没有 Debian 系的机器,等我有了把命令行补上。

其实我一直觉得输入法安装是个非常简单的问题,一直不想写篇博客说。但是好多人还是卡到这里,我觉得还是不够了解,像我们这种老鸟(呸!)一眼就能看出来的问题,可能别人还得搜索好久才能找到解决方案。而且我帮别人装的时候运行 fcitx-diagnose 的时候大家都是一脸惊异,看来都还是不知道有这个工具的存在。如果有人能看到这篇博文的话希望能有所帮助。

Roy Binux's avatar

bilibili 新番承包付费意愿调查

2014年10月1日 bilibili 正版新番承包上线,我就对 bilibili 这种自愿付费的方式感到好奇。而且经常听到「正版体验不佳」,「正版动画比起盗版,有何优势呢」的言论,那么中国用户在不插广告,不优先播放,不强制的情况下,到底愿意为「爱」付多少钱呢?

为什么 bilibili?

bilibili 早期,新番都是用户上传的,可以说是典型的「盗版网站」。那么这个拥有大量用户的「盗版网站」体验应该说不差吧。

随着 bilibili 开始购买版权,现在新番实际上是正版盗版共存的模式,而 bilibili 不插前置广告(当然现在有「约不约」了),不强制付费;从体验上看,特别相对其他国内视频网站,应该是最接近「盗版」的了。

付费人数

bilibili 新番承包人数可以非常方便的从番剧的介绍页面上获知:

但是由于动画的类型不同,热度不同,独播非独播用户(路人)成分不同,直接比较数字没有什么意义。需要首先找到一个基准来讨论播放和付费数之间的关系。

我抓取了新番承包上线以来新开播的 142 部新番(http://demo.pyspider.org/results?project=bgm_bilibili),去除话数小于10的 OAD,OVA 等,剩下 136 部。将总播放,追番人数,弹幕总数画为散点图:

由图可知,弹幕总数和总播放数相关性比追番人数相关性更大(参照 R^2)。独家和非独家新番在弹幕参与度上相差不大,但是非独家的追番率比独家新番少了一半。难道非独家新番用户大多是非 bilibili 注册用户吗?这说不通啊,明明应该是反过来,非会员不得不到 bilibili 上看才对啊。。

付费比例

在开始写这一节的时候,我本想应该挺简单的,承包人数要么和播放数正相关,要么和活跃(弹幕数)相关,要么就和追番人数相关。但是经过了3个小时,当我尝试了:

  • 总播放数
  • 平均每集播放数
  • 弹幕数
  • 收藏(追番)人数
  • 时间
  • 是否独家新番

画了20+张图之后发现,问题并没有这么简单。很难有一个什么方法能够预测出用户的付费意愿,有很多叫好不叫座,或者叫座不叫好,导致付费比例非常分散:

图中左边是独播新番,右边为非独播

这里面会发现一些有趣的地方:在独播和非独播中,都有一个承包比例非常高的点,分别是《电器街的漫画店》和《Fate/stay night [Unlimited Blade Works] 第一季》,他们都是2014年10月番,正好是新番承包刚上线时的作品,可能用户对承包模式的尝鲜,或者前期宣传上的增益。

将特异点排除之后,发现不管是否独播,他们的付费比例差别不大,但是非独播的方差大得多:

平均上来说,bilibili 的付费比例约为播放数的万分之 1.447,收藏人数的千分之5.373。但是这只能是整体估计,具体到单个番剧就没有意义了。

用户到底为了什么付费?

那么,具体到每一部番剧,用户到底因为什么因素愿意付费呢?

当我将付费比例前10与付费比例后10的放在一起比较,试图找出答案的时候,我真的失败了:

在前10中有在我看来「这什么鬼」的,在后10中也有追过的,完全搞不懂拥有更高收费比例的番剧是为什么。当然,通过加入声优,导演,制作,类型 tag 等因素,或许可能找到原因,但这样少的数据,又很容易陷入过拟合的境地(如果有兴趣,可以下载数据分析看看)。

付费金额

人均承包金额

虽然在 bilibili 页面中有承包商排名,但是并不知道付费的金额,仅在你承包的时候,给出你当前的排名。为了了解承包商们在这样没有强制金额的「捐献」中愿意付多少钱,我从1元开始承包,然后查看我当前的排名来获得各个区段的人数:

为了消除连载中,独播,类型等影响,这里选择了连载中,非独播的的 Re:Zero 和已完结,独播,稍微腐女向的 K RETURN

从图中可以看出:

  • 主要用户的付费金额在 5-13(不要吐槽为什么是13,手抖了!)
  • 不同类型的番剧,承包金额的分布几乎是完全一样的
  • TOP 付费用户的付费金额比较高,Re:Zero 我付到 500 元,依然有 3 个比我高的(于是我放弃了)
  • 同样付出 150 元,在 Re:Zero 中能排到 19,而在 K 中只能排到 37,还不论 K 的付费人数实际少于 Re:Zero(腐女还是有钱人多啊)

那么,假如我们不考虑前 3 位的土豪,人均承包金额约为 13.08 元。因为我们并不知道土豪能为我们拉升多少身价,那,即使我们现在假设排名前三的土豪均承包五千块,人均承包金额也不过18元。为了简化,我们取20块好了。因为选取了两部因素差异蛮大的动画,得知不同因素对承包金额的分布影响不大,这个人均承包金额是可以套用到不同番剧上的。

承包收入

那我们算一下,bilibili 通过新番承包,到底能赚多少钱呢?因为承包人数是公开的,乘以估计的人均20块的话,bilibili 承包收入收入排行:

根据网上的传言,每集非独播新番版权价格大约是5万,独播更贵。那么好,我们统统算1万一集吧(对,就是这么任性)!那么也就 《Fate/stay night [Unlimited Blade Works] 第一季》 和 《电器街的漫画店》 实现了盈利。记得我们前面说过的付费比例异常吗?对,就是这两部「盈利」了的番剧。

从整体来看,bilibili 通过承包总收入为 288.7 万,平均每部番剧的承包收入是 21388 元,不打折的话,一集都买不起啊!

我想说什么

经常有人会用「正版体验不佳」作为盗版的理由,说得好像正版体验一样了就会付费了似的。bilibili 同时有提供正版和盗版内容,正版有比盗版体验差吗?难道正版看得人就少了吗?好,就算确实看正版的人少了,我们不看绝对值,那这寒酸的千分之5.373的付费比例是怎么回事?什么「正版体验不佳」啊,「要付钱当然体验不佳」啦。

另外一个常见的理由是「学生党,没有钱」,人均 20 块太贵出不起。请回过头看看追番人数,要是每个人出一块钱,那也要比现在这千分之5.373,人均20块的总收入高啊!一块钱都出不起吗?这可是一季动画,而不是一集让你出一块钱啊!看动画都是因为爱,而这份爱,连一块钱都不值吗?

bilibili 不想通过广告那样半强制地收回那么一点点版权费,然而看起来这「爱」并不畅销。所以,我弱弱地提议,各位有爱的小伙伴,在看完一季动画后(是的,不喜欢可以不承包),从微信红包(是的,不用银行卡)中拿出那么一块钱(是的,最低承包不是5块,是可以改的),承包一下你喜欢的动画吧。。希望在「劣币驱逐良币」之前,良币不会先自己饿死吧。

Roy Binux's avatar

demo.pyspider.org 部署经验

经常有人会问 pyspider 怎么进行分布式部署,这里以

violet's avatar

在Surface Pro 3上安装双系统

其实拿到苏菲也有一年多了,本来想当普通的平板用看看B站,奈何Flash发热太过感人,风扇呼呼地吹,大腿刺啦刺啦地烫,玩游戏又没有独显,玩个奥利与黑暗森林也被卡成PPT,于是一直丢在书架上。昨天说苏菲对我来说鸡肋,然后被人果不其然地喷了。其实上网要有一定的意识,大家不过是各种站队然后互喷,不是比谁有理谁没理,而是比谁的声音大,想想还是挺无聊的。然而这让我意识到我手里有个还不错的设备,不如装上Linux来当个生产工具吧,也好让苏菲不那么鸡肋一点!

Roy Binux's avatar

足兆叉虫的2015

我是从来不记日子的,这导致我也不知道有些事情是2015年发生的,还是2014年发生的,亦或只是我的臆想。即便如此,2015年也是变化的一年。

跳槽,工资没涨…… 到这里居然和2013年是一样的,但是当我在2015写下这篇日志的时候,国内已经2016。

说来惭愧,这一年除了一月写了几篇教程之后,不但 blog 落下了,开源也没有做多少。看着 pyspider 的 star 数蹭蹭涨到 5813,但是并没有太多精力去更新。希望在 2016 年能有时间把 slime 模式的坑填了吧。

其他的项目也就在年末的时候又重新玩了一把 WebRTC,基于的 WebTorrent 经过一年的开发,已经成熟了很多,feross 在 javascript 上从 tracker 到 BT 协议都实现了一遍,比起我那时山寨的好了非常多,虽然 hybrid 模式还有很多问题。。。对了 2015 年参与过 technical review 的 Learning WebRTC 也出版了,算是一次挺有趣的经历吧。

8月到英国之后,就是各种适应,加上新公司的蜜月期,一门心思放在了公司的项目上。在新公司才算是第一次接触到了机器学习,给我带来了很多新的思路,有种能成的感觉吧。

希望2016年能更有趣吧。

英国(二)

然后说一些「关于英国生活」类似的东西吧,想到什么写什么

衣食住行

  • 夏天不热,这个冬天不冷
  • 冬天是雨季,几乎一半时间在下雨,但是从来没有在上下班的时候下
  • 英国不负「难吃国」之名,只要是英文店名的地方,那真是难吃 + 贵
  • 中午的饭点是1-2点,晚餐饭点是8-9点
  • 一个很大问题是,看菜单很多时候不知道是什么东西,查字典也没用
  • 一盒 200g 的毛豆都要卖20-30RMB,而且还被他们视为高贵的健康食品
  • 有很多中国人开的中餐馆和日式便当,这是唯一能吃的东西(除了 KFC)
  • 超市的肉类品种和部位很不同,炒出来很老,我用了3个月才想出来怎么吃
  • 鸡翅鸡腿比鸡胸便宜,只要10RMB/斤
  • 肉比蔬菜便宜
  • 住非常贵,北京的7-8倍
  • 行非常贵,北京的5-10倍
  • 伦敦很小,和北京比起来

公司

  • 公司现在有40+个人,但是有15种国籍,22+种语言
  • 有4个华裔同事,但是任意两者之间只能用英语交流(除英语外会的语言分别是普通话,粤语,日语,马来语,德语)
  • 没有印度人
  • 一年25天年假,8天法定假日,没有年终奖
  • 不加班的主要原因是没有晚餐,肚子饿
  • 公司以外听不懂别人说什么 =_=
RecursiveG's avatar

Linux环境TCP Socket与Epoll使用备忘

流水帐式地记录了 Linux 下 TCP Socket 通信的方法和基本的 Epoll 使用方法。
没有错误处理。

地址解析

1
2
3
4
struct addrinfo *listen_addr; //存放解析结果。参见`man getaddrinfo`
getaddrinfo("0.0.0.0", "55553", NULL, &listen_addr); // getaddrinfo([主机名],[端口],[hint],[结果])。成功返回 `0`
// ...
freeaddrinfo(listen_addr); //释放资源,返回void

监听

这种方式只能同时处理一个连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int fd = socket(AF_INET, SOCK_STREAM, 0); // int socket(int domain, int type, int protocol); 参见`man 3 socket` 创建文件描述符, 出错返回-1
bind(fd, listen_addr->ai_addr, listen_addr->ai_addrlen);
// int bind(int socket, const struct sockaddr *address,socklen_t address_len);
// 绑定地址,出错返回-1,参见`man 3 bind`
listen(fd, SOMAXCONN);
// int listen(int fd, int backlog(最大队列长度))
// 开始监听,出错返回-1
while (1) {
int new_fd = accept(fd, NULL, NULL);
// accept([fd], [监听地址], [监听地址结构体长度]) 第2,3个参数同bind()
// 接受连接请求,若无请求则阻塞(也有可能是EAGAIN,取决于你需要什么)
// 返回用于和对端通信的新的文件描述符,出错返回-1
// ... handle(new_fd);
close(new_fd); // 关闭文件描述符
}

发起连接

1
2
3
4
5
6
7
8
9
10
struct addrinfo *server_addr;
getaddrinfo("127.0.0.1", "55553", NULL, &server_addr);
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
connect(server_socket, server_addr->ai_addr, server_addr->ai_addrlen)
// 基本同bind() 参见 man 3 connect
// 成功后可用server_socket与服务器通信
// ... send(...)
// ... recv(...)
close(server_socket);
freeaddrinfo(server_addr);

传送数据

1
2
3
4
char *payload = "hello"
send(new_fd, payload, strlen(payload), 0); // send([fd], [buffer], [需发送消息长度], [flag]) 返回实际发送的消息长度
char buf[255];
recv(new_fd, buf, sizeof(buf), 0); // send([fd], [buffer], [最大接收消息长度], [flag]) 返回实际接收的消息长度。阻塞模式下,若无消息则阻塞

多进程请求处理

对于每一个请求fork()一个新的进程进行处理。

1
2
3
4
5
6
7
8
while(1) {
int new_fd = accept(fd, NULL, NULL);
if (fork() == 0) { // fork()返回0说明是子进程
// ... handle(new_fd);
close(new_fd);
break;
}
}

Epoll

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int epollfd = epoll_create(1024);
// 创建epoll文件描述符,出错返回-1
// int epoll_create(int size) 从Linux2.6.8开始,size值被忽略,不过为保持兼容需要设定为一个正整数
struct epoll_event ev; // 记录套接字相关信息
ev.events = EPOLLIN; // 监视有数据可读事件
ev.data.fd = fd; // 文件描述符数据,其实这里可以放任何数据。
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
// int epoll_ctl([Epoll FD], [Operation], [fd], [epoll_event]);
// 加入监听列表,当fd上有对应事件产生时,epoll_wait会将epoll_event填充到events_in数组里
// 出错返回-1
struct epoll_event events_in[16];
while(1) {
int event_count = epoll_wait(epollfd, events_in, 16, -1);
// 等待事件,epoll_wait会将事件填充至events_in内
// int epoll_wait([epoll fd], struct epoll_event *events, [最大事件数量], int timeout);
// 返回 获得的事件数量,若超时且没有任何事件返回0,出错返回-1。timeout设置为-1表示无限等待。
for (int i = 0; i<event_count; i++) { // 遍历所有事件
if (events_in[i].data.fd == fd) { // 新连接请求
int new_fd = accept(fd, NULL, NULL);
ev.events = EPOLLIN; // 参见man 7 epoll 如果要使用Edge Trigger还需将new_fd设为非阻塞
ev.data.fd = new_fd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, new_fd, &ev); // 将新连接加入监视列表
} else {
int new_fd = events_in[i].data.fd;
// ... handle(new_fd);
epoll_ctl(epollfd, EPOLL_CTL_DEL, new_fd, NULL); // 不再监听fd,最后一个参数被忽略
close(new_fd);
}
}
}

拓展阅读

violet's avatar

Some notes about libgit2/rugged

I learned libgit2/rugged when I involved in a project which is to analysis a repository. I found it's a little hard to use Rugged to do the basic things, e.g. `git pull`, `git push`, etc. This is the purpose that I want to add some notes here. In case of someday there's someone likes me who encounter into these kinds of stuff. ლ(╹◡╹ლ)

RecursiveG's avatar

Linux下建立GRE隧道并获取IPv6地址

虽然HE有提供免费的Tunnelbroker,不过那速度实在不怎么样。于是考虑在有IPv6地址托管主机上建立一个GRE Tunnel。
GRE Tunnel需要有内核模块ip_gre支持。远程主机有一段/64的IPv6,我将其中的一段/80分配给自己的机器。
使用iproute2工具。当然,你自己的机器需要有一个公网IPv4地址。

  1. 服务器的公网IPv4是$server_ipv4
  2. 自己电脑(或者路由器)的公网IPv4是$client_ipv4
  3. 服务器的IPv6段是a:b:c:d::/64
  4. 要分配下去的IPv6段是a:b:c:d:e::/80

服务器配置

脚本如下,需要root,建议用sudo -i

1
2
3
ip tunnel add gre-tunnel mode gre remote $client_ipv4 ttl 64
ip link set gre-tunnel up
ip addr add a:b:c:d:e::1/80 dev gre-tunnel
  • 第一行建立隧道,gre-tunnel是隧道名称,可以按自己喜欢的来,记得其他的也要一起改
  • 第二行激活隧道
  • 第三行分配IP地址

本地配置

脚本如下,和服务端配置几乎一样,同样需要root:

1
2
3
4
ip tunnel add gre-tunnel mode gre remote $server_ipv4 ttl 64
ip link set gre-tunnel up
ip addr add a:b:c:d:e::2/80 dev gre-tunnel
ip -6 route add default dev gre-tunnel
  • 第一行建立隧道,隧道名称不必和服务器的一样
  • 第二行激活隧道
  • 第三行分配IP地址,注意不要和服务器的冲突,这个IP也是将要暴露在网络上的IP
  • 第四行设定路由,让IPv6流量都走隧道

访问网络

现在,两台机器应该可以互ping了。有的比较奇葩的情况可能需要手动ip link set gre0 up一下,gre0似乎是内核模块自动加入的玩意儿,具体怎么回事我也不清楚–_–|
但是现在还不能访问外网,还需要在服务器执行以下命令:

1
2
3
sysctl net.ipv6.conf.all.forwarding=1
sysctl net.ipv6.conf.all.proxy_ndp=1
ip -6 neigh add proxy a:b:c:d:e::2 dev eth0

第一行开启forward
二三行和IPv6的NDP(邻居发现)有关,又是个没搞明白的东西真是残念……
eth0是服务器实际连接网络的接口。

删除 & 修改

要删除Tunnel,在两端均执行:

ip link set gre-tunnel downip tunnel del gre-tunnel

如果客户端IP变化:

ip tunnel change gre-tunnel remote $new_client_ipv4

注意事项

虽然叫做“隧道”,但是内容依然是明文,对保密要求高的同学们要注意了。
另外直接用命令建立的隧道在重启后会没有,所以可以考虑用networkd之类的东西来管理。
Linux在访问有IPv6地址的域名时会优先使用IPv6,所以要当心服务器流量爆炸。当然配置成IPv4优先也是可以的。
如果你的本地IPv4经常变动的话,你可能需要些脚本之类的东西自动更新服务器的Remote IP。
对于每一个新的IP(新的设备),都需要在服务端执行ip -6 neigh add,有知道怎么解决这个问题的请务必留言…

Roy Binux's avatar

英国

半年没有更新 blog 了,其实我在憋(wan)个(W)大(O)招(W)。一年半以前,我说过「想学日语,想出国」,虽然这一年半也是没有干劲地随随便便过的,但是至少出国了。

目的地英国,工作,8月初。

要说经历,其实简单到爆。

  1. 投简历(依旧是只投一家)
  2. 视频面试(用我8年没用过的蹩脚英语)
  3. 考雅思(而且只要4分,我只做了套剑9就去了)
  4. 对方办 certificates of sponsorship(虽然每月有名额限制,按照打分排,但是以往的数据,只要满足条件,名额都够。)
  5. 办签证(不像旅游签证,不用行程单,不用资产证明,有 COS 就 ok)
  6. 买机票
  7. over

工资没涨,物价大涨,难吃,加上烂英语,瞬间感觉生活甚是艰辛。。。不过, there is always a way,就当作一次挑战吧。

就酱

Yeechan Lu's avatar

用 aria2 拯救传输错误的文件

因为有时候用的网络,是按照流量计费的。如果从自己的服务器上传输一个很大的文件回来,却发现文件哈希对不上,你会怎么办(后来才知道其实只是坏了几个字节)?

也许你会想到 BitTorrent 的种子,因为这是带有文件分块的校验码。也许你会说不是有些客户端支持 Web Peer 嘛,但是好像这些都挺麻烦的。这时候就有请 aria2c:

  • 支持 BitTorrent,HTTP/HTTPS/FTP/SFTP;
  • 可以通过 BitTorrent 协议之外的方式下载种子里的文件;
  • 断点续传、多线程。

所以,首先在服务器上用 rhash 计算哈希创建种子文件,然后把种子传输到本地,打开 aria2c 就行。

--torrent-file 指示 aria2 使用种子文件提供的信息,-s10 -x10 -k1M 让其对每个文件用 10 个链接、每个服务器开 10 个链接、最小切块 1MiB,--check-integrity=true 指示其检查现有文件的完整性,--seed-time=0 禁止其下载完成后做种(毕竟只是传输自己的文件罢了)。

1 2 3 4 5 6 7 8 9 10
server$ rhash --torrent test.zip
server$ ls test.zip*
test.zip
test.zip.torrent
local$ wget https://example.com/test.zip.torrent
local$ ls test.zip*
test.zip
test.zip.torrent
local$ aria2c --torrent-file=test.zip.torrent -s10 -x10 -k1M --check-integrity=true --seed-time=0 https://example.com/test.zip

其实这个方法,是今天在搜索如何让 aria2 通过 HTTP 下载一个种子的时候突然看到的。当时碰到的页面是 Aria2c with and without using torrent files - Rescuing a failed download,如果你有兴趣,也建议你读一读。

如果你还不知道 aria2,不要再犹豫了,借此机会好好了解一下吧。虽然平常似乎见到最多的地方不是桌面而是路由器上……

顺带一提,aria2 0.19.0 中加入了对 SFTP 的基本支持。只是基本支持,但是也支持通过 SFTP 的多线程和断点续传了,虽然目前还只能用用户名和密码来认证。Homebrew 里的公式还没有更新,不过我是建议你马上就用这个 Homebrew 公式立刻换上崭新的 aria2 0.19.0。所以说刚刚也可以不用 HTTPS 而是利用 SFTP 来更加安全地从服务器上传输文件回来,毕竟 SSH 服务器哪儿都有,HTTP(S) 还得找支持断点续传和支持认证/加密的服务器……


其实用 rsync 也能做到这件事,不过印象中不支持多线程啊,所以我并不喜欢。如果你有需要,可以读一读这篇文章:Force rsync to use delta transfer to fix corrupt remote file

1
rsync -Pa --checksum --inplace --no-whole-file local.file remote.server:
Yeechan Lu's avatar

Oh My 2014

  • January
  • Translated Minecraft-related news actively at the Minecraft Chinese Forum.
  • Finished my first term at Jiangsu University.
  • End of my first followed season of Japanese animes.
  • Started contributions to the Alfred-inspired Windows application, Wox, built with C# and WPF.
  • February
  • Spent days and nights on Project MuduHS 2014, the video cheering for students of my high school whilst this is my first time to play with Adobe After Effects, Adobe Premiere Pro, FL Studio, Melodyne, Minecraft, CINEMA 4D and Mineways.
  • Discovered a logical bug on RenderBus, a cloud render farm for C4D, and registered a Wooyun account.
  • Brought my old Dell Inspiron 1420 to school with RAM upgraded to 3 GiB later.
  • Started to learn Node.js from the scaffold of Drywall.
  • March
  • Installed OpenWRT on Buffalo WZR-HP-G450H and configured automagically firewall bypassing.
  • Stayed in hospital for a week. During this time I contributed to Wox frequently.
  • April
  • Built the robust backend for Sanddudu's project NextDay-Desktop
  • Played with Xposed Framework on Android and wrote a Xposed module named FakeMyDevice (never published).
  • Joined HackPlan again.
  • Started working on bounties offered by Ripple Labs. Reminded by Soniji.
  • May
  • Bought MacBook Air (13-inch/Mid 2013/i5 1.4GHz/8GiB/128GB) which was my first Apple hardware. I was deeply impressed by the design and OS X Mavericks.
  • Received the first ticket of TOS violation from Linode due to insecure firewall configuration.
  • Became a reseller of ResellerClub.
  • Wrote Pingful(with Server and Web), a simple app utilising Gulp and Socket.io. Also redesigned the parking page.
  • June
  • Bought a modded Mercury MW151RM with OpenWRT installed to repeat the Wi-Fi hotspot provided by CMCC durning night hours in dormitories.
  • Wrote my first cross-platform native program as school homework, minipos.
  • Started working on the internal fork of Atom-Shell used by Pomotodo for Windows Desktop.
  • July
  • Started working on bounties on Bountysource.
  • Built the PrimCraft Wiki based on MediaWiki.
  • Leart to use n2n to create virtual networks between VPSs.
  • August
  • Bought a Crucial M500 480GB SSD for my portable workstation.
  • Started running a webpage spider using pyspider.
  • Built the activity page for BGMAD 2014 with Lynn° and c4605.
  • Rented a dedicated server in Canada and started running my own Jenkins.
  • Played the galgame School Days with CrossOver on OS X.
  • Applied for a passport.
  • Migrated my blog from WordPress to Ghost whilst I stayed in a McDonalds's all night long with Linghein.
  • Met with Pomotodo team members in Nanjing.
  • Had a “meaningless” meeting with IamI, forgot to give a bear hug.
  • September
  • Signed my first NDA and W-8BEN form.
  • Passed StartSSL Class 2 Verification.
  • Released Pomotodo for Windows Desktop.
  • Compiled Chromium for the first time.
  • October
  • Rode from Zhenjiang to Shanghai on the G312 highway.
  • Visited Shanghai Postal Museum and had a cup of coffee in Starbucks with Polaris Mi, Chi Rui, Jiang Ximeng.
  • Tasted the best minced pork congee with preserved eggs in Shanghai.
  • Met the worst "donburi congee" in my life.
  • University started to cut down the Wi-Fi hotspot provided by CMCC during the night hours.
  • Set foot on USA soil (embassy) and was refused getting USA visa under INA 214(b).
  • Impressed by the Time Machine but completely depressed by OS X Yosemite.
  • Replaced Samsung I9082 with Redmi 1S.
  • Wrote a network monitor running on the Loongson laptop.
  • Started to move Linux CI workers into OpenVZ containers on DigitalOcean.
  • November
  • Got my first VISA card (although it's a supplementary card).
  • Won the 1111 prize from HackPlan.
  • Attended China's largest & first college hackathon, HackShanghai 2014, at NYU Shanghai with Chino Chang, Cx Wang. Designed Hangry to help people order their take-outs in no time.
  • Failed to apply for a USA visa again.
  • Designed a stamp with my avatar.
  • Learnt to use GnuPG with Angurise.
  • December
  • My first time using Windows To Go. Bought a license for Sandboxie with friends. Wrote QQCamera to use the world-famous screenshotting function in QQ.
  • Rebuilt my blog with Jekyll.
  • Started using the new avatar designed by Lynn° with my favorite T-shirt from GitCafe.
  • Hot soup was spilled on the keyboard of my MacBook Air. It died and revived. The only problem is that the power button turned into a killer button.
  • Started Project Ainou with oott123.
  • 一月
  • Minecraft 中文论坛翻译了数篇 Minecraft 相关新闻。
  • 结束在江苏大学的第一个学期。
  • 看完我第一次追着看的这一季新番。
  • 参与 Windows 应用 Wox 开发。这是一个用 C# 和 WPF 写的类似 Alfred 的东西。
  • 二月
  • 寒假的日日夜夜忙于《木中加油 2014》的制作,给母校毕业生的加油视频。这几乎是我第一次跟 Adobe After EffectsAdobe Premiere ProFL StudioMelodyneMinecraftCINEMA 4DMineways 打交道。
  • 挖出 RenderBus(C4D 的云端渲染农场)的一个逻辑错误,成为了乌云用户。
  • 把我的 Dell Inspiron 1420 带去了学校,后来把内存升级到了 3 GiB。
  • 读着 Drywall 的代码开始学习 Node.js。
  • 三月
  • 给巴法络 Buffalo WZR-HP-G450H 刷上了 OpenWRT, 配置了自动翻墙
  • 住了一个星期院,在此期间频繁参与 Wox 开发。
  • 四月
  • 给白色箱子造了 NextDay-Desktop 文件的后端。
  • 玩了玩安卓上的 Xposed 框架,写了一个没发布的 FakeMyDevice 模块。
  • 回归 HackPlan
  • 索尼子的介绍下开始做 Ripple Labs 的悬赏。
  • 五月
  • 入了 MacBook Air (13 寸/Mid 2013/i5 1.4GHz/8GiB/128GB),我的第一个苹果设备。被其设计和 OS X Mavericks 系统折服。
  • 第一次收到 Linode 的服务协议违反工单,因为防火墙上暴露了几个危险的端口。
  • 成为 ResellerClub 代理。
  • 学习 Gulp 和 Socket.io,写了一个 Pingful(包括服务器前端),与此同时重新制作了域名停靠页
  • 六月
  • 买了个魔改版的水星 MW151RM,刷了 OpenWRT,用来中继宿舍里夜间的中国移动 Wi-Fi 信号。
  • 完成了我的第一个原生跨平台程序作为课程设计,minipos
  • 开始搞 Windows 桌面版番茄土豆用到的内部版本的 Atom-Shell 的。
  • 七月
  • 开始做 Bountysource 的悬赏。
  • 用 MediaWiki 搭建 PrimCraft 百科
  • 学会使用 n2n 在 VPS 之间构建虚拟网络。
  • 八月
  • 给移动工作站购入 Crucial M500 480GB 固态硬盘。
  • pyspider 搭建了几个资源站的爬虫。
  • 凌姐姐逸川BGMAD 新人战 2014的网页。
  • 租了一台加拿大独服,开始自己跑我的持续集成系统 Jenkins
  • 在 OS X 上用 CrossOver 玩了 GAL 游戏日在校园
  • 申办护照。
  • 跟凌瀚在 M 记呆了一夜,把我博客从 WordPress 迁移至 Ghost。
  • 番茄土豆团队成员在南京聚会。
  • IamI 见了“没有意义”的一面,走之前忘记来个熊抱。
  • 九月
  • 第一次签保密协议和 W-8BEN 表格。
  • 通过 StartSSL Class 2 验证。
  • 发布了 Windows 桌面版番茄土豆
  • 第一次编译出 Chromium。
  • 十月
  • 沿着 G312 国道从镇江骑行至上海。
  • 参观上海邮政博物馆,跟絮语池睿西萌在星巴克喝了一杯。
  • 品尝了我迄今为止最爱的皮蛋瘦肉粥。
  • 遭遇迄今为止最让我失望的“盖浇”皮蛋瘦肉粥。
  • 学校开始在夜间切断中国移动的 Wi-Fi 信号。
  • 踏上了美国领土(大使馆),根据美国法律 INA 214(b) 被拒签。
  • 被 Time Machine 震撼,但是 OS X Yosemite 令我大失所望。
  • 用红米 1S 换下了三星 I9082。
  • 写了一个跑在龙芯笔记本上的网络监视器
  • 把持续集成的 Linux 节点搬进了跑在 DigitalOcean 上的 OpenVZ 容器里。
  • 十一月
  • 拥有了第一张 VISA 信用卡(虽然是附属卡)。
  • HackPlan 抽中 1111 大奖。
  • 在上海纽约大学参加中国首次大型大学生创客马拉松活动创客上海 2014。与常昊王成欣组队设计了 Hangry,旨在帮助人们不花时间订外卖。
  • 美国签证再次被拒。
  • 用头像设计了一个印戳。
  • Angurise 带入 GnuPG 坑。
  • 十二月
  • 第一次用 Windows To Go、和朋友团购 Sandboxie。写了 QQCamera 来在 QQ 之外使用其世界闻名的截图功能。
  • 用 Jekyll 重建了我的博客。
  • 启用凌姐姐设计的新二次元形象,穿着我年度最爱的 GitCafe 短袖。
  • 不小心把馄饨的热汤倒在了 MacBook Air 的键盘上,死了又复活了。唯一的问题在于电源键一按就会爆炸
  • 三三开始搞 Ainou 企划
Roy Binux's avatar

pyspider 爬虫教程(三):使用 PhantomJS 渲染带 JS 的页面

英文原文:http://docs.pyspider.org/en/latest/tutorial/Render-with-PhantomJS/

在上两篇教程中,我们学习了怎么从 HTML 中提取信息,也学习了怎么处理一些请求复杂的页面。但是有一些页面,它实在太复杂了,无论是分析 API 请求的地址,还是渲染时进行了加密,让直接抓取请求非常麻烦。这时候就是 PhantomJS 大显身手的时候了。

在使用 PhantomJS 之前,你需要安装它(安装文档)。当你安装了之后,在运行 all 模式的 pyspider 时就会自动启用了。当然,你也可以在 demo.pyspider.org 上尝试。

使用 PhantomJS

当 pyspider 连上 PhantomJS 代理后,你就能通过在 self.crawl 中添加 fetch_type='js' 的参数,开启使用 PhantomJS 抓取。例如,在教程二中,我们尝试抓取的 http://movie.douban.com/explore 就可以通过 PhantomJS 直接抓取:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Handler(BaseHandler):
def on_start(self):
self.crawl('http://movie.douban.com/explore',
fetch_type='js', callback=self.phantomjs_parser)

def phantomjs_parser(self, response):
return [{
"title": "".join(
s for s in x('p').contents() if isinstance(s, basestring)
).strip(),
"rate": x('p strong').text(),
"url": x.attr.href,
} for x in response.doc('a.item').items()]
  • 我在这里使用了一些 PyQuery 的 API,你可以在 PyQuery complete API 获得完整的 API 手册。

在页面上执行自定义脚本

你会发现,在上面我们使用 PhantomJS 抓取的豆瓣热门电影只有 20 条。当你点击『加载更多』时,能获得更多的热门电影。为了获得更多的电影,我们可以使用 self.crawljs_script 参数,在页面上执行一段脚本,点击加载更多:

1
2
3
4
5
6
def on_start(self):
self.crawl('http://movie.douban.com/explore#more',
fetch_type='js', js_script="""
function() {
setTimeout("$('.more').click()", 1000);
}""", callback=self.phantomjs_parser)
  • 这个脚本默认在页面加载结束后执行,你可以通过 js_run_at 参数 修改这个行为
  • 由于是 AJAX 异步加载的,在页面加载完成时,第一页的电影可能还没有加载完,所以我们用 setTimeout 延迟 1 秒执行。
  • 你可以间隔一定时间,多次点击,这样可以加载更多页。
  • 由于相同 URL (实际是相同 taskid) 的任务会被去重,所以这里为 URL 加了一个 #more

上面两个例子,都可以在 http://demo.pyspider.org/debug/tutorial_douban_explore 中找到。

Roy Binux's avatar

pyspider 爬虫教程(二):AJAX 和 HTTP

在上一篇教程中,我们使用 self.crawl API 抓取豆瓣电影的 HTML 内容,并使用 CSS 选择器解析了一些内容。不过,现在的网站通过使用

Roy Binux's avatar

pyspider 爬虫教程(一):HTML 和 CSS 选择器

虽然以前写过 如何抓取WEB页面

Roy Binux's avatar

迁移 Python 3

porting pyspider project to Python 3 with Python 2 compatible
Yeechan Lu's avatar

Welcome to Jekyll!

You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.

To add new posts, simply add a file in the _posts directory that follows the convention YYYY-MM-DD-name-of-post.ext and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works.

Jekyll also offers powerful support for code snippets:

1 2 3 4 5
def print_hi(name)
puts "Hi, #{name}"
end
print_hi('Tom')
#=> prints 'Hi, Tom' to STDOUT.

Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll’s dedicated Help repository.

RecursiveG's avatar

IDEA下建立Forge开发环境的正确姿势

Minecraft mod developing in seperated folders under linux with IDEA.
Roy Binux's avatar

pyspider介绍

虽然已经发过一篇架构设计,但是觉得还是有必要发一篇介绍。而且拖了那么久的第二里程碑的commit数已经超过第一个版本了。。

那么由我再次介绍一下 pyspider。

缘起

pyspider 来源于以前做的一个垂直搜索引擎使用的爬虫后端。我们需要从200个站点(由于站点失效,不是都同时啦,同时有100+在跑吧)采集数据,并要求在5分钟内将对方网站的更新更新到库中。

所以,灵活的抓取控制是必须的。同时,由于100个站点,每天都可能会有站点失效或者改版,所以需要能够监控模板失效,以及查看抓取状态。

为了达到5分钟更新,我们使用抓取最近更新页上面的最后更新时间,以此来判断页面是否需要再次抓取。

可见,这个项目对于爬虫的监控和调度要求是非常高的。

pyspider 的主要特性

  • python 脚本控制,可以用任何你喜欢的html解析包(内置 pyquery)
  • WEB 界面编写调试脚本,起停脚本,监控执行状态,查看活动历史,获取结果产出
  • 支持 MySQL, MongoDB, SQLite
  • 支持抓取 JavaScript 的页面
  • 组件可替换,支持单机/分布式部署,支持 Docker 部署
  • 强大的调度控制

由于功能太多,更多请参考脚本编写指南

感谢 +PhoenixNemo 提供的VPS,提供了一个 demo: demo.pyspider.org。无需安装即可体验。

脚本样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from libs.base_handler import *

class Handler(BaseHandler):
'''
this is a sample handler
'''
@every(minutes=24*60, seconds=0)
def on_start(self):
self.crawl('http://scrapy.org/', callback=self.index_page)

@config(age=10*24*60*60)
def index_page(self, response):
for each in response.doc('a[href^="http://"]').items():
self.crawl(each.attr.href, callback=self.detail_page)

def detail_page(self, response):
return {
"url": response.url,
"title": response.doc('title').text(),
}

例如这就是创建任务后默认生成的一个脚本示例。

  • 通过 on_start 回调函数,作为爬取的入口点,当点击主面板上的 run 的时候,就是调用这个函数,启动抓取。
  • self.crawl 告诉调度器,我们需要抓取 'http://scrapy.org/' 这个页面,然后使用 callback=self.index_page 这个回调函数进行解析。
  • 所有 return 的内容默认会被捕获到 resultdb 中,可以直接在 WEBUI 上看到。

更多特性和文档

RecursiveG's avatar

Minecraft Coremod开发杂事记

Some notes on developing coremods for Minecraft, mainly about ASM & AccessTransformer
Roy Binux's avatar

签到 —— qiandao.today 介绍

qiandao.today 已经上线了一个半月,这篇blog一个半月以前就应该写了。直到我刷了14遍水晶塔没有ROLL到任何装备(不对,我最后通过贪婪ROLL到了!),打了两晚麻将,把把最小胡牌距离大于5(任意更换手牌达到胡牌的最小张数),房子里刷JJ怪之后。我觉得我必须做点什么。。。

好了,不扯蛋了。自动签到是我对于 “如何请求到数据” ,进行请求自动分析的一个尝试(实际是我 U2 因为45天没登录被封了)。通过浏览器捕获页面请求瀑布流,进行内容/请求分析,找出关键请求。所以,签到这个项目,我就是先从 HAR编辑器 开始做的。做的时候还玩了一下 angularjs然后其他部分都是随便写的

但是,对于签到来说,哪些请求是必要的,这个请求是怎么组装的(例如 token 参数怎么来),特征不明显。自动分析出来就能直接用的概率太低了,即使是人还得单步测试呢。于是 HAR编辑器 成为编辑和单步调试的辅助。自动分析变成了 “推荐相关请求”。

  • 用户部分系统尝试了一下 PBKDF2 进行密码加密。PBKDF2 的优势在于通过随机盐 加 可配置的多轮加密,加大了单个key的运算代价。
  • 模板执行部分通过提取页面信息,和 jinja2 引擎渲染,可以动态地改变请求的 url、header、data 各个部分。
  • 执行断言加上邮件系统,可以检测签到是否成功,在失败的时候给用户发送邮件提醒。

本来还想要做互助打码的验证码系统的,但是通过 雪月秋水cookie插件,其实大部分只有登录需要验证码,签到并不需要。关键是做这个东西不好玩,于是就算了。

运行了一个半月,目前有11个公开签到模板,400+个签到任务,每天进行300次签到。不过由于担心单IP登录帐号过多被封,只在v2ex做了一次广告,不敢大范围推广。。。


以下是面向普通用户的简介:

  • 云代签
  • 支持多个网站
  • 失败邮件提醒
  • 自制模板并分享(文档
  • https 传输安全保证
  • 一号一密用户数据加密
  • 开放源码,支持本地执行(提供本地lite版)

github: binux/qiandao
网站: https://qiandao.today

Yeechan Lu's avatar

音乐分享的点名游戏(2014)

总算把博客搬离了 WordPress,在整理旧文的时候看到音乐分享的点名游戏。哎呀,已经是五年前的事情了。突然觉得很有趣,就再来玩一次好了 :)

规则就不再重复了,也不点名了,自己玩玩就好。

  1. If someone says, “Is this okay?” You say: 与你最后的夏天 - 西国の海妖

  2. How would you describe yourself? 心の旋律 - 白浜坂高校合唱部 (TARI TARI ミュージックアルバム 〜歌ったり、奏でたり〜)

  3. What do you like in a guy/girl? GATE OF STEINER - 阿保剛 (STEINS;GATE Symphonic Material)

  4. How do you feel today? Shine Days - Girls Dead Monster (Little Braver)

  5. What is your life’s purpose? 立body機motion - 澤野弘之 (進撃の巨人 Original Soundtrack 1)

  6. What is your motto? 光る轍 - 吉野裕司 (狼と香辛料 O.S.T 狼と旅の音楽)

  7. What do your friends think of you? BRYNHILDR IN THE DARKNESS -Ver.EJECTED- - 鴇沢直 (極黒のブリュンヒルデ オリジナル・サウンドトラック)

  8. What do you think of your parents? 妄想髪長少女、再び - 田中公平 (冰菓 Original Sound Track)

  9. What do you think about very often? Sing All Overtures - キリト(CV.松岡禎丞)、アスナ(CV.戸松 遥)、リーファ(CV.竹達彩奈)、ユイ(CV.伊藤かな恵)、シリカ(CV.日高里菜)、リズベット(CV.高垣彩陽) (Sword Art Online 特典 CD)

  10. What do you think of your best friend? ウタウタウ -miku ver.- - トラボルタP (TORABOTIC WORLD2)

  11. What do you think of the person you like? Love Changes Everything - Michael Ball (Best Of Voices)

  12. What is your Life Story? ☆Lovely Super Idol☆ - シリカ(CV.日高里菜) (Sword Art Online 特典 CD)

  13. What do you want to be when you grow up? Alchemy - Girls Dead Monster (Crow Song)

  14. What is your hobby/interest? My Next Move - Dreamtale (World Changed Forever)

  15. What is your biggest fear? 田舎小径 - 戸越まごめ (CLANNAD -クラナド- ORIGINAL SOUND TRACK)

  16. What is your biggest secret? Dreams of the Dead - Two Steps From Hell (Legend)

  17. What do you think of when you see the person you like? 最強を示す者 - 井内舞子 (とある科学の超電磁砲S ORIGINAL SOUND TRACK 2)

  18. What will you dance to at your wedding? to the beginning - Kalafina (THE BEST “Blue”)

  19. What will they play at your funeral? 男子高校生と文化祭 - Audio Highs (男子高校生の日常 Original Soundtrack)

  20. What do you think of your friends? Desire Blue sky - Clean Tears (Science Adventure Dance Remix 'CHAOS;HEAD' 'STEINS;GATE')

Yeechan Lu's avatar

我的浏览器地址栏中的 A – Z(2014 秋)

前略,天国的 2014 君。趁着从 WordPress 搬迁到 Ghost 的机会,今年再来一发好了。最近常用的浏览器是 Google Chrome (OS X & Windows) 娘。

  • Alipay.com
  • Bilibili.tv
  • Cnlogin.resellerclub.com/servlet/ResellerIndexServlet
  • Dns.miv.im
  • Ele.me
  • Files.miv.im
  • Git.miv.im
  • Humblebundle.com/weekly
  • Ip.cn
  • Jjxke1.ujs.edu.cn
  • Kuaidi100.com
  • Linode.com
  • Mail.google.com/mail/u/0/
  • Nyaa.cat
  • Orzfly.com
  • Plus.google.com
  • Qiniu.com
  • Ripplecharts.com
  • Steamcommunity.com/id/orzFly/
  • Twitter.com
  • Urpgs.com
  • V2ex.com
  • Wiki.primcraft.com
  • Xuxian.****.**
  • Youtube.com
  • Z.cn

不知不觉,又变化了好多。

Yeechan Lu's avatar

Welcome to Ghost!

You're live! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. You can manage your content by signing in to the admin area at <your blog URL>/ghost/. When you arrive, you can select this post from a list on the left and see a preview of it on the right. Click the little pencil icon at the top of the preview to edit this post and read the next section!

Getting Started

Ghost uses something called Markdown for writing. Essentially, it's a shorthand way to manage your post formatting as you write!

Writing in Markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use shortcuts to style your content. For example, a list:

  • Item number one
  • Item number two
    • A nested item
  • A final item

or with numbers!

  1. Remember to buy some milk
  2. Drink the milk
  3. Tweet that I remembered to buy the milk, and drank it

Links

Want to link to a source? No problem. If you paste in url, like http://ghost.org - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to the Ghost website. Neat.

What about Images?

Images work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:

Not sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:

![A bowl of bananas]

Quoting

Sometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.

Wisdomous - it's definitely a word.

Working with Code

Got a streak of geek? We've got you covered there, too. You can write inline <code> blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.

1 2 3 4
.awesome-thing {
display: block;
width: 100%;
}

Ready for a Break?

Throw 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.


Advanced Usage

There's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.

That should be enough to get you started. Have fun - and let us know what you think :)

Yeah,博客上线了!这篇文章的目的是向你介绍 Ghost 编辑器并帮你快速上手。通过 <your blog URL>/ghost/ 链接就可以登录系统后台管理你的博客内容了。当你进入后台,你就能看到左侧文章列表处列出的这篇文章,右侧就是这篇文章的预览效果。点击预览栏右上角的铅笔图标就能进入内容编辑页面。

快速入门

Ghost 使用 Markdown 语法书写内容。简单来说,Markdown 就是一种简化的书写格式!

用 Markdown 语法写作是很容易的。在编辑界面的左侧就是你写作的地方。在你认为需要的时候,可以使用以下这些语法来格式化你的内容。例如下面这个无序列表:

  • 第一项
  • 第二项
    • 层叠项

  • 最后一项

还可以是有序列表:

  1. 记得买点牛奶
  2. 喝掉牛奶
  3. 发个微博说我记得买牛奶了,而且喝了

链接

如果要链接其它页面,可以直接把页面的 URL 粘贴过来,例如 http://ghost.org - 会被自动识别为链接。但是,如果你想自定义链接文本,可以像这样:Ghost 官网。很简单吧!

图片

插入图片也没问题!前提是你事先知道图片的 URL,然后像下面这样:

如果图片在本地的硬盘里怎么办?也很简单!像下面这样书写就能为图片预留一个位置,然后你可以继续写作,回头再通过拖拽的方式把图片上传到服务器上。

![一张图片]

引用

有些时候我们需要引用别人说的话,可以这样:

Wisdomous - it's definitely a word.

代码

或许你是个码农,需要贴一些代码到文章里,可以通过两个引号(Tab 键上面的那个键)加入行内代码 <code>。如果需要加入大段的代码,可以在代码前加 4 个空格缩进,这就是 Markdown 的语法。

1 2 3 4
.awesome-thing {
display: block;
width: 100%;
}

分割线

在任一新行输入 3 个或更多的短横线(减号)就是一条分隔线了。


高级用法

Markdown 还有一个特别用法,就是在你需要的时候可以直接书写 HTML 代码。

只要掌握了上面的这些介绍,你就已经入门了!继续写作吧!

Roy Binux's avatar

如何从 WEB 页面中提取信息

已经五个月没有更新 blog 了,这五个月全身心投入到了两个关于如何从页面上抽取结构化数据的项目上。这也是我加入某厂最主要的原因。其中一个全自动模板生成抽取器,虽然还不完全能够实用,但比1年前效果好太多,同时也让我想明白了一些问题。这都是下文主要讨论的问题。

RecursiveG's avatar

域名注册商更换

昨天折腾了一天,把域名从Godaddy转移到了Name.com
表示基本没遇到什么麻烦,信用卡借用了家长的,付款也很方便。
关键是便宜啊。转入9美刀,续期11美刀,比Godaddy坑爹的18刀便宜太多了啊~
而且还有免费的WHOIS保护啊
优惠码PRIVACYPLEASE超好记有木有!
虽然不是最便宜的但是Name.com的控制台相当美观呐~
结尾吐槽一句:在万网注册的都是真的勇士。

RecursiveG's avatar

Programming with PTRACE, Part6 - 时间控制

不同的时间计算方法

程序运行会占用一小段时间(废话),事实上,我们有不止一种方法来表示一个程序运行了多长时间。最直观的应该是“墙上时间”,也就是说,你掐个秒表,看看程序从开始到结束用了多长时间。除此之外,还有“用户态时间”和“内核态时间”,这两个时间都是以CPU实际运算的时间,也就是CPU周期,来计数的。“用户态时间”就是程序在用户态执行的时间,包括程序所引用的库中的代码(比如STL),“内核态时间”就是指程序在内核态执行的时间,一般是各种系统调用(比如各种IO操作)。这两种时间和墙上时间的区别在于,因为CPU其实是在多个程序中快速切换的,所以在运行某个程序的时间里,CPU也处理了属于其他进程的任务,而且CPU切换任务也需要一定的时间(真的很短)。如果处于被调试状态,tracer的运行时间也会被计算在内,这些不属于这个进程的时间片也会被计算在这个进程的“墙上时间”里。所以一般以用户态时间和内核态时间的总和作为进程的运行时间。

在Linux系统里有一个叫time的命令可以查看一个命令执行了多长时间。这个命令有两个版本,一个是shell内置的,另一个是独立的可执行文件,可以用type time命令查看。虽然可执行版本功能更强一点,但内置的功能足够,这一点区别可以不管。用法是: time [命令] <参数>。给个例子:

time ffmpeg -i sample.mp4 target.mp3...5.42s user0.10s system100% cpu5.520 total

动手写个带时限的time

还在对上个PART的setrlimit耿耿于怀么?我们现在就来用它!相关的定义位于sys/resource.h头文件里。我们这次要用到RLIMIT_CPU,这个选项限制进程所能占用的CPU时间,以秒为单位,可以把它理解为用户态时间和内核态时间的和。我们首先要使用getrlimit获得当前的限制:

struct rlimit TimeL;getrlimit(RLIMIT_CPU,&TimeL);

rlimit结构有两个成员:

  • rlim_cur 软限制
  • rlim_max 硬限制

系统一般会用比较平和的方式对待那些达到软限制的进程,比如发个SIGSEGV什么的。而那些达到硬限制的进程会被直接SIGKILL。我们接下来要修改软限制,注意单位是秒。

TimeL.rlim_cur=Timeout;

以上工作都要在fork()之前完成,之后要在子进程里应用这个限制(没错就是exec那里)

setrlimit(RLIMIT_CPU,&TimeL);

这样,如果子进程超过软限制,系统就会发送SIGXCPU信号给子进程。当然,因为ptrace的原因,信号会被先发送给父进程,这样就可以用part3里介绍的方法进行处理。这样子进程是要清蒸还是油炸就都由父进程决定了。
当然,我们还有别的方法获取时间信息。一是用gettimeofday()函数配合timeval结构,可以获得当前时间,精确到微秒(百万分之一秒)。在程序开始时调用下,结束时调用下,相减即可得到墙上时间。另一种方法是利用wait4里的ru参数,它其实是个rusage结构,成员见此。其中的ru_utimeru_stime成员是timeval结构,分别记录了用户态时间和内核态时间,同样精确到微秒。

程序睡着了

RLIMIT_CPU大多数情况下都能正常工作,配合timeval结构甚至能进一步提高精度。但是有两个例外(如果有更多请务必告诉我):

  1. 程序主动调用sleep()
  2. 交互状态下scanf()一类的函数等待键盘输入

在这两种情况下:进程不占用CPU时间,RLIMIT_CPU管不着;没有系统调用,wait4()不返回。为了能够在这种情况下依然能够限制时间,我想出了两种方法。一是限制和sleep()相关的系统调用,二是父进程设置ALARM。我在这里讲一下第二种方法。
Linux提供了一个alarm()函数,可以在指定的秒数(墙上时间)后给这个进程本身发送SIGALRM信号。而且,我们可以给信号绑定一个处理函数(就是当信号到达时调用的函数),在这个处理函数里,可以用kill命令给子进程发送信号(比如SIGUSR1),这样就能使父进程里的wait4()返回,就可以控制子进程了。以下是一个简要指导:
首先我们需要一个信号处理函数,记得把pid改成全局变量:

void AlarmIn(int sig){    if(sig==SIGALRM)    kill(pid,SIGUSR1);}

然后在子程序开始执行的时候绑定信号并设置Alarm,我在这设置超时一秒:

signal(SIGALRM,AlarmIn);alarm(1);

然后请根据part3所讲的内容在while循环里正确处理SIGUSR1。最后记得取消Alarm,如果没超时的话:

alarm(0);

完整代码?

表示完整代码太长了,放这儿太不美观,我会稍后贴到gist上去。代码被幽幽子吃掉了大家自己写把。

拓展阅读

violet's avatar

音乐以及黑魔法

一直使用cmus来播放音乐,因为首先没有必要多开一个window来播放音乐,其次它看上去很酷啊!很拽啊有木有!终端里播放音乐啊!还是vim键绑定啊!

看上去逼格还行吧!

其实以前的界面略挫,而且如果使用tmux+powerline的话遇到歌曲名比较长的话会发生奇怪的现象,暂且称其为feature。

cmus界面的设置如下,我是借鉴过来的。。。嗯。。。

set color_cmdline_bg=black
set color_cmdline_fg=lightyellow
set color_win_bg=black
set color_win_fg=green
set color_separator=green
set color_info=red


# Bottom status line
set color_statusline_bg=black
set color_statusline_fg=lightgreen

# Bottom title line
set color_titleline_bg=black
set color_titleline_fg=lightyellow

# Top title area
set color_win_title_bg=black
set color_win_title_fg=lightgreen

##### Playing File Colors #####
# Unselected currently playing track's text
set color_win_cur=lightyellow
# Active selection for currently playing track
set color_win_cur_sel_bg=black
set color_win_cur_sel_fg=lightyellow
# Inactive selection for currently playing track
set color_win_inactive_cur_sel_bg=black
set color_win_inactive_cur_sel_fg=yellow

##### Non-Playing File Colors #####
# Active selection
set color_win_sel_bg=black
set color_win_sel_fg=lightyellow
# Inactive selection
set color_win_inactive_sel_bg=black
set color_win_inactive_sel_fg=yellow

##### File Browser View Colors #####
# Directory listing color
set color_win_dir=lightgreen

噢我一开始说啥黑魔法来着,这个是某菊苣写的脚本来着,github上搜zhuaxia有真相。。。由于是不负责任的无版权的黑魔法,只适合私下传播嗯。。。

RecursiveG's avatar

Programming with PTRACE, Part5 - 内存管理

Fifth part of serial of tutorial: Programming with PTRACE
RecursiveG's avatar

Programming with PTRACE, Part4 - 系统调用进阶

Fourth part of serial of tutorial: Programming with PTRACE
RecursiveG's avatar

Programming with PTRACE, Part3 - 进程的终止与信号

在Part2中,我们粗略了解了如何使用ptrace获得系统调用信息,即在一个大循环里不断获取程序信息,如果程序退出则停止循环。当然,那个判断异常简陋,几乎无法处理任何特殊情况。我将在本Part中详细解说各种异常情况的处理,同时讲解各种信号相关的问题。

一些重要的宏

在使用wait4后,程序的信息被存储在sta变量中,这些信息被存储在这个整数的不同二进制位上,这儿有一系列宏用于帮我们提取这些信息。以下信息是我对man 3 wait中相关部分的翻译,同时参考了这个页面

WIFEXITED   如果进程正常退出,返回一个非0值(通常是进程调用了`exit()`或是`_exit()`)WIFSIGNALED 如果进程由于一个未被捕获的信号而被终止,返回一个非0值WIFSTOPPED  当进程被停止(非终止)时,返回一个非0值(通常发生在当进程处于`traced`状态时)WEXITSTATUS 当`WIFEXITED`为非0值,获得进程`main()`函数的返回值WTERMSIG    如果`WIFSIGNALED`为非0值,获得引起进程终止的信号代码WSTOPSIG    如果`WIFSTOPPED`为非0值,获得引起进程停止的信号代码

除了这六个,还有WIFCONTINUEDWCOREDUMP两个宏,不过我们用不到,我也没仔细研究,就不说了。
当进程自行终止时,WIFEXITED即为true,配套使用WEXITSTATUS获得返回值,不做过多解释。当子进程进行系统调用时,WIFSTOPPEDtrue,同时WSTOPSIG等于SIGTRAP(信号代码为7),我们可以用这种方法区分syscall-stopsignal-delivery-stop。当有一个外部信号要发送给子进程,这个信号会先到达父进程,使WIFSTOPPEDtrue,同时WSTOPSIG等于该信号的信号代码。父进程可以选择将这个信号继续传递或是不传递,甚至传递另一个信号给子进程。一旦信号真正到达子进程,就进入子进程自己的处理流程或是系统默认动作,可能触发WIFSIGNALED,比如SIGINT
在所有信号中,SIGKILL是一个例外,它不会经过父进程引发WIFSTOPPED,而是直接传递到子进程,引发WIFSIGNALED

信号的传递与修改

之前提到,父进程需要将信号传递给子进程,这是由ptrace(PTRACE_SYSCALL,pid,0,0)的第四个参数决定的。如果为0,就不传递信号,否则传递对应代码的信号,比如ptrace(PTRACE_SYSCALL,pid,0,9)就将信号9(SIGKILL)传递给了子进程。
修改信号简直信手拈来,传一个你想要传的信号即可。

strsignal()和代码

strsignal()接受一个整数参数,返回const char*,用于把信号代码变为对应的、人类可读的字符串描述,定义于string.h。下面给出判断程序退出的代码:

1
2
3
4
5
6
7
8
wait4(pid,&sta,0,&ru);
if(WIFEXITED(sta)){printf("Exited with code %d",WEXITSTATUS(sta));break;}
if(WIFSIGNALED(sta)){printf("Terminated by signal: %s",strsignal(WTERMSIG(sta)));break;}
int sig_no;
if(WIFSTOPPED(sta))sig_no=WSTOPSIG(sta);
if(sig_no==SIGTRAP)sig_no=0;
......
ptrace(PTRACE_SYSCALL,pid,0,sig_no);

来自ptrace的高级选项

你也许会纠结,如果外部传递了一个SIGTRAP信号,那么如何分辨呢?答案是使用PTRACE_SETOPTIONS设置PTRACE_O_TRACESYSGOOD标记,即在while之前,第一个wait之后,第一个PTRACE_SYSCALL之前,使用ptrace(PTRACE_SETOPTIONS,pid,0,PTRACE_O_TRACESYSGOOD)。这会使得syscall-stop导致的WSTOPSIGSIGTRAP变为SIGTRAP|0x80,而普通的来自外部的SIGTRAP依然是SIGTRAP

violet's avatar

尝试一发Node.js

不论说啥,反正就是没工作_(:3 JZ)_

来来来,不如折腾点项目玩耍。

久闻Node.js大名,然后各种事件驱动的黑魔法,于是来玩耍一发。

 

Yeechan Lu's avatar

orzFly’s Music Collection: Winter 2013

  1. 突然好想你 – 五月天 04:25
  2. 没离开过 – 林志炫 05:17
  3. 凶夢伝染 – ALI PROJECT 04:25
  4. 一番の宝物 (Original Version) – 麻枝准 06:00
  5. Alpha – C418 10:03
  6. For River - Piano (Sarah & Tommy's Version) – Kan R. Gao 02:58
  7. ここにしか咲かない花 – コブクロ 06:11
  8. 木中友谊之歌 – 李雨婷; 王海宇; 王昕尧; 冯丽; 张天成; 陶聪聪; 倪一舟 06:11
  9. secret base ~君がくれたもの~ (10 years after Ver.) – 茅野愛衣; 戸松遥; 早見沙織 05:52
  10. 影 – 柴咲コウ 04:26
  11. My Soul, Your Beats! – Lia 04:35
  12. My Soul, Your Beats! -Zephyr Violin Edition- – Zephyr Cradle; TAM 05:00
RecursiveG's avatar

Programming with PTRACE, Part2 - 系统调用入门

Second part of serial of tutorial: Programming with PTRACE
RecursiveG's avatar

Programming with PTRACE, Part1 - 起步

First part of serial of tutorial: Programming with PTRACE
violet's avatar

monitors

这又是啥!!! 今天看面试题的时候看到 monitors VS semaphore, 简直就是这是啥! monitors是啥! 啥啥啥...
让你不好好看书!搜索了一发于是来写总结...

violet's avatar

isn't a Gem

RecursiveG's avatar

有屏幕的地方就有烂苹果

如果你还不知道Bad Apple是什么东西,请移步这里
播放的原理很简单,就是不停的打印清屏再打印清屏。任何一个略有编程基础的人都能做到。比较令人头大的是如何把原视频转化为一个易于解析而且又不占地方的文件。
其实,借助FFmpegImageMagick和一点点的编程小技巧就可以轻松完成。

第一步当然是要去下一个视频文件,我已经下好了,叫做BadApple.mkv

第二步要把视频变成一帧一帧的图片,请出FFmpeg来帮忙:

ffmpeg -i BadApple.mkv -s 80x60 -r 15 Ba%d.png

然后你就会得到Ba1.png Ba2.png Ba3.png等一大堆文件,这就是各帧了。注意我在这一步同时把大小缩小到了80*60和把帧速率调到了15帧每秒。

第三步用ImageMagick将图像转换成黑白图,然后再转换成xpm格式。XPM格式本质上是一个文本文档,可以直接被#include。我们这一步要用到一点点脚本技巧。

1
2
3
4
for x in *.png
do
convert $x -monochrome `basename -s .png $x`.xpm
done

最后写一段C语言小程序,利用游程编码进一步缩小文件体积。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include "xpm.h"
void main(){
FILE *f=fopen("BA.dat","a");
char count;
int t=ARR[0][6]=='1'?1:2;
for(int i=1+t;i<61+t;i++){
count=1;
for(int j=1;j<80;j++){
if(ARR[i][j]==ARR[i][j-1]){
count++;
}else{
if(ARR[i][j]=='.')count=-count;
fprintf(f,"%c",count);
count=1;
}
}
if(ARR[i][79]==' ')count=-count;
fprintf(f,"%c",count);
fprintf(f,"%c",0);
}
fclose(f);
}

当然,离不了脚本和编译器的帮助,我这里使用了tcc进行编译

1
2
3
4
5
6
for (( i=1; i<=3288; i++))
do
cp Ba$i.xpm xpm.h
tcc -DARR=Ba$i bad_apple.c && ./a.out
rm xpm.h
done

其中,那个3288就是总帧数。这样就得到了一个BA.dat文件。文件内容是一堆用二进制存储的数字,正数代表连续的白色,负数代表连续的黑色,零代表换行。一帧60行,总计3288帧。这样就把一个80多兆的视频压缩到了900多K。有了数据文件剩下的就好办了。

未完待续。。。。。。

via these people and places