Arch Linux 星球

July 11, 2019

中文社区新闻

libbloom>=1.6-2 更新需要手动干预

libbloom 包在 1.6-2 之前的版本缺少了一个动态库的链接。这个问题已经在 1.6-2 中修复, 所以更新过程需要覆盖掉 ldconfig 创建出的未被跟踪的链接文件。如果你在更新时遇到这样的报错:


libbloom: /usr/lib/libbloom.so.1 exists in filesystem

请通过:


pacman -Suy --overwrite usr/lib/libbloom.so.1

来完成更新

by farseerfc at July 11, 2019 01:12 PM

June 30, 2019

中文社区新闻

mariadb 10.4.x 更新需要手动干预

遵从上游的建议, mariadb 更新到 10.4.6-1 或者之后的版本需要改变配置文件的布局。
主配置文件的位置从 /etc/mysql/my.cnf (以及它的引入文件夹 /etc/mysql/my.cnf.d/ )移动到了 /etc/my.cnf (相应的 /etc/my.cnf.d/ )。请确保迁移您的配置。

逐实例的服务(像 mariadb@foo.service 这种)不再用单独的文件配置(像 /etc/mysql/myfoo.cnf 这种),而是移动到了主配置文件中的带群组后缀的配置块里面,每个服务一个带后缀的配置块。一个配置块看起来类似这样:


[mysqld.foo]
datadir = /var/lib/mysql-foo
socket = /run/mysqld/mysqld-foo.sock

和之前几次 mariadb 功能性升级一样的是,这一次也需要升级 data 文件夹。在修改好配置文件之后请运行以下命令进行升级:


systemctl restart mariadb.service && mariadb-upgrade -u root -p

by farseerfc at June 30, 2019 07:52 AM

June 03, 2019

Lainme

在CentOS 7上安装Dropbox

因为工作上的一些缘故必须使用centos 7,但现在dropbox必须要glibc2.19以上才能运行,还不能用旧版本。

去年的时候,这个问题还能用glibc版本号欺骗的方式绕过去,但现在一定要实际的glibc2.19以上才行。解决的办法只能是自己编译一个高版本的glibc供dropbox使用。具体方法参考了此文:https://gist.github.com/jazzl0ver/d896ddf16fe2c39fb7ab52df47dcd2f0

编译的glibc放到家目录或者/opt都行。以/opt为例,先准备配置文件

sudo mkdir -p /opt/glibc-2.27/etc/ld.so.conf.d
sudo cp /etc/ld.so.conf /opt/glibc-2.27/etc/
sudo cp /etc/ld.so.conf.d/kernel-$(uname -r).conf  /opt/glibc-2.27/etc/ld.so.conf.d

然后进行编译

wget https://ftp.gnu.org/gnu/glibc/glibc-2.27.tar.gz
tar xzvf glibc-2.27.tar.gz
cd glibc-2.27
mkdir build
cd build
../configure --prefix=/opt/glibc-2.27
sudo make
sudo make install

再安装dropox并用patchelf更改一些链接信息

cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -
ver=`cat $HOME/.dropbox-dist/VERSION`
dir=$HOME/.dropbox-dist/dropbox-lnx.x86_64-$ver
patchelf --set-interpreter /opt/glibc-2.27/lib/ld-2.27.so  $dir/dropbox
patchelf --set-rpath /opt/glibc-2.27/lib $dir/dropbox

之后再链接一些系统的lib过来

ln -s /lib64/libgcc_s.so.1 $dir
ln -s /usr/lib64/libstdc++.so.6 $dir
ln -s /lib64/libz.so.1 $dir
ln -s /lib64/libgthread-2.0.so.0 $dir
ln -s /lib64/libglib-2.0.so.0 $dir

这样基本好了,不过只复制这些lib似乎并不能让GUI正常工作,只能用命令行的Python脚本来控制。命令行版下载地址:https://www.dropbox.com/download?dl=packages/dropbox.py

此外dropbox的启动也需要一些额外参数,最好建立一个bash脚本,方便调用

#/bin/bash
ver=`cat $HOME/.dropbox-dist/VERSION`
dir=$HOME/.dropbox-dist/dropbox-lnx.x86_64-$ver
LD_LIBRARY_PATH=$ver DISPLAY='' dropbox.py start

另外,现在dropbox更新的挺勤快,而且每次都要强迫升级客户端,否则就罢工,所以时不时就需要把patchelf后面的步骤重新操作一遍。真的很烦。可以考虑再写一个脚本,专门拿来更新dropbox,比如

upgradedropbox.sh
#!/bin/bash
 
cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -
 
ver=`cat $HOME/.dropbox-dist/VERSION`
dir=$HOME/.dropbox-dist/dropbox-lnx.x86_64-$ver
 
patchelf --set-interpreter /opt/glibc-2.27/lib/ld-2.27.so  $dir/dropbox
patchelf --set-rpath /opt/glibc-2.27/lib $dir/dropbox
 
ln -s /lib64/libgcc_s.so.1 $dir
ln -s /usr/lib64/libstdc++.so.6 $dir
ln -s /lib64/libz.so.1 $dir
ln -s /lib64/libgthread-2.0.so.0 $dir
ln -s /lib64/libglib-2.0.so.0 $dir

by lainme (lainme@undisclosed.example.com) at June 03, 2019 12:16 PM

June 01, 2019

Phoenix Nemo

软件工程实践上的一点思考

曾经大学时对于软件工程这类理论课不屑一顾,认为这些课本都是只在大学里讲学而并不实际参与工程的教授写的东西。但是经过这些年从自己开发程序编写代码,到与公司团队同学、兴趣圈的朋友一起开发项目,也积累、总结了一些经验和教训。正巧昨晚在游戏建设里参与了这类讨论,于是记下一些思考免得忘记。

案例 1

命令方块是 Minecraft 里用于执行游戏命令、实现各种触发性或持续性功能的方块。在游戏地图中需要展示一些浮空的名称标签,便是用命令方块生成隐形盔甲架实现的。这些盔甲架参数复杂且需要在地图里很多特定位置生成,负责的同学便在每个生成的位置下面放了重新生成的命令方块,生成的坐标是相对坐标,因此写好标签的命令方块便可被无限复用。

由于盔甲架属于实体,而实体在 Minecraft 中被认为是不可靠的:有无数种可能这实体会被移动或被清除。
因此我的建议是:将这些命令方块全部放到控制室,坐标写成绝对坐标并加上统一标签,便可做到一键生成全部、一键清除全部。

该同学表示:不想写绝对坐标,因为很麻烦。

案例 2

由于游戏玩法的需要,编写了新的插件。几天后按照原计划应当可以准备第一次基本功能测试时,负责开发的同学表示只写了大约 1/4 的功能。进度很慢的原因是 Minecraft 的实现过于糟糕,而 Spigot 和 Paper 等修改版也没有很好封装 API 导致几乎所有的事件都需要手动处理。

接下来的协同开发中该同学又在反复尝试对配置文件中属性类似的部分使用同一个序列化/反序列化方法处理、对不同配置文件中的不同物品记录项也加上了一层包装来使得其能够被一个序列化/反序列化方法处理、在其他一些程序逻辑上也在尝试复用代码减少冗余度。

我说,你先专心把功能快速叠出来,然后再去想优化的事情。
这位同学表示不能接受,他认为代码应该从编写时就是整洁的。

论点:矫枉过正的代码复用

代码复用是很常见的代码结构优化方式。更少的代码冗余可以减少维护的复杂度,也降低出错的可能。

但是在案例 1 中,如此复用代码(放置同样的命令方块)却实际上造成了更多的冗余:如果要修改一个属性,就需要记录整个世界里每一个命令方块的位置,然后一个个去修改它。相反,由于游戏世界地图里的建筑几乎不可能变化(虽然现实需求很少会有这种条件),统一放在控制室、hard code
所有的坐标作为一个大方法调用,却是在这需求前提下的更好的实现方式。如果需要修改属性,可以只在一个地方修改所有的命令方块。

或者说,重复放置命令方块的过程,就是 copy’n’paste 冗余代码的过程。

而案例 2 则更具有代表性。在项目初期,是否应当关注代码质量?
我认为是应当关注的,但是这基于开发者的工程实践经验。优秀的、熟练的开发者应当在代码编写时就能灵活使用各种简单的优化手段减少初期的代码冗余,但是对于在校大学生没有足够的项目经验时,面对紧凑的项目时间安排应当集中更多精力实现功能。此时过分关注代码优化会被分心导致各种问题——例如这位同学编写的代码基本没有能够一次通过所有测试的情况,而且绝大多数的错误都看起来只是粗心,并不是不理解、写不出的问题。

论点:实现,调整,优化

“Make it work, make it right, make it fast.” – Kent Beck

这是很多软件工程推崇的敏捷开发指导方向。在案例 1 中,该同学只做了第一步——复用同样的、带有相对坐标的命令方块(方法)快速实现了所有的功能。但是从后续维护的角度来讲,这样的实现没有 make it right,更不用提 fast。

而在案例 2 中,这位同学将三个阶段在初期就全部揉进去,但是由于工程经验不足,在思考优化方案时花费了过多的精力,也导致了代码精度不够,反复修改也无法顺利通过测试。

从个人经验来看,前期的代码编写应注重功能实现,并在编码能力基础上直接编写清晰的代码结构。功能实现后,再根据需求和测试中的问题「重构」打磨细节、尝试更好的实现方式。这个过程不仅在完善整个程序,对自己的系统架构把握和设计经验也有很大的提升。最后一个阶段,则是针对性的优化少量代码使整个系统更加稳定、高效。

论点:架构的改动

这是一个比较小型的项目。需求和基本功能架构从一开始便已经讨论清楚。后续的调整不大,但是每当有少量的需求修改或架构微调,都导致了很大的代码变动。而按照这位同学的思路,每次改动都要重新思考代码结构,这浪费很多的时间。

从实际工程角度,需求变化并带来架构的微调甚至大改动都可以说是很常见的事情。在前期编码实现阶段如果揉入过多对于代码结构的过多考量,每次改动都可能会使这些思考的时间被浪费。因此,在前期编码时不应为架构考虑消耗过多的时间,而在重构过程中,由于已经完成基本的功能实现,且对已有代码还处在熟悉的热度,可以快速适配需要修改、调整的架构,并基于前期编码时的各种尝试和实验的结论选择最佳的实现方式。

以上是基于近期项目中的讨论,在软件工程层面上的思考。如有缺漏不当之处,欢迎指正。

曾经大学时对于软件工程这类理论课不屑一顾,认为这些课本都是只在大学里讲学而并不实际参与工程的教授写的东西。但是经过这些年从自己开发程序编写代码,到与公司团队同学、兴趣圈的朋友一起开发项目,也积累、总结了一些经验和教训。正巧昨晚在游戏建设里参与了这类讨论,于是记下一些思考免得忘记。

June 01, 2019 06:04 AM

May 26, 2019

ヨイツの賢狼ホロ

各自开始的新生活

总有一些开始和结束值得留念。

结束了。

布偶君 <shadowrz@disroot.org>
离别告知,能扩散多远就扩散多远
如果你们能看到这句话的话,
我告诉你们点东西。

以前的我,各种意义上都很正常。嗯,这很好。
也许是直到和你们接触开始,
家长发现我自己总是和别人有不一样的想法和性格。

然后,各种各样的矛盾接踵而至……
……我的性格影响了好多人——它变坏了。
……争执,吵闹,宛如发疯……

昨天我和父母吵了起来,他们一定要看我在用电话做什么。我要是不让他们看,就会觉得是电话害了我(我现在才发现)
然后我只有妥协的命(不然他们不会让我玩的,这样的话也会是离别)。
于是他们(只)看到了 #archlinux-cn-offtopic 的聊天记录,
然后……他们……
……觉得你们都是一群疯子……
希望我永远不要记起你们……
还说做不到就要不停吃药,死也可以……
还要彻底删掉你们,让你们碰不到我……

…………

为什么,为什么会变成这样啊!!!!
我和你们这些年……为什么让我变成了一个不能在世界存活(没人接受我的性格)的状态啊!!!!!!!

告诉我回答啊啊啊啊啊啊啊啊啊啊啊!!!!!!!!!!!!!!

--
布偶君 | 雨宫恋叶 | ShadowRZ (同一身份)
2019-05-22

Update (2019/05/23, ref https://wxw.moe/@ShadowRZ/102142677608282951 ):

我再声明几点:

1. 只是退群+不和你们往来而已
2. 不想反对父母,不要对我提这样的建议
3. 对话都给父母看了(除私信)
4. 以后不在处理任何通知,包括小号
5. 我不会再依存于你们
6. 现在父母也希望非常非常了解我

望周知。
2019-05-23
(为什么好好的告别,说了三天)

愿他安好。

(不知道以后还有没有机会在“没有黑暗的地方”相见……)

开始了。

开始了?

https://twitter.com/Ken_Ookami_Horo/status/1128784581400727553

  • 去深圳啦 ~
  • 在去之前买了很多稀奇古怪(?)的家伙(例如某地狱牌交换机,某粗粮牌玻璃板和某雨林牌泡面盖什么的 😂)
  • 见到了大学同学 x1 (以后说不定会有 x2 , x3 ?)
  • 当然不是去玩的 😢 (结束了长达六个月的失学无业辣鸡时光(x))
  • 从公司收到台新笔记本,然后发现手边的内存装不上去只好现买 😂
  • 说不定有机会……?
  • 就这样。

by ホロ at May 26, 2019 04:00 PM

May 08, 2019

Phoenix Nemo

WireGuard 真香

真是老了跟不上时代了,这么好的东西为什么我现在才开始用??

其实这东西刚出来就在关注了不过确实前段时间才有机会尝试折腾一下。优点很多,也有无数人写过文章介绍,所以就不再多废话。主要看中它的 PtP 特性(服务器之间)和支持漫游(服务器-客户端)。当然目前在梯子方面的表现,即便是优秀的隧道方案,但由于折腾的人多了,面对万里城墙,这谁顶得住哇。

所以本文只讨论 WireGuard 作为访问企业网的隧道方案,算是初步折腾的笔记。

服务器配置

一个基本的 PtP 配置结构 /etc/wireguard/wg0.conf

1
2
3
4
5
6
7
8
9
[Interface]
Address = 10.0.0.1/32
PrivateKey = [CLIENT PRIVATE KEY]

[Peer]

PublicKey = [SERVER PUBLICKEY]
AllowedIPs = 10.0.0.0/24, 10.123.45.0/24, 1234:4567:89ab::/48
Endpoint = [SERVER ENDPOINT]:48574
PersistentKeepalive = 25

生成私钥

1
2
wg genkey > privatekey
chmod 600 privatekey

基于私钥生成本机的公钥

1
wg pubkey < privatekey > publickey

或者一步完成的操作

1
wg genkey | tee privatekey | wg pubkey > publickey

额外生成预共享密钥来进一步增强安全性

1
wg genpsk > preshared

这样服务器之间的互联配置就基本完成了。使用 wg-quick up <config> 来快速启动 WireGuard。

如果要配合客户端使用,则需要配置 NAT。顺便如果客户端没有 IPv6,也可以通过此法来给客户端提供 IPv6 Enablement。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[Interface]
Address = 10.200.200.1/24
Address = fd42:42:42::1/64
SaveConfig = true
ListenPort = 51820
PrivateKey = [SERVER PRIVATE KEY]

# note - substitute eth0 in the following lines to match the Internet-facing interface
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

[Peer]

# client foo
PublicKey = [FOO's PUBLIC KEY]
PresharedKey = [PRE-SHARED KEY]
AllowedIPs = 10.200.200.2/32, fd42:42:42::2/128

[Peer]
# client bar
PublicKey = [BAR's PUBLIC KEY]

AllowedIPs = 10.200.200.3/32, fd42:42:42::3/128

在此例中需注意 Allowed IPs 不可 overlap 否则会造成包转发错误。

客户端

与上文中服务器配置相照应的客户端配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
[Interface]
Address = 10.200.200.2/24
Address = fd42:42:42::2/64
PrivateKey = [FOO's PRIVATE KEY]
DNS = 1.1.1.1

[Peer]
PublicKey = [SERVER PUBLICKEY]
PresharedKey = [PRE-SHARED KEY]
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = [SERVER PUBLIC IP ADDRESS]:51820

客户端的 AllowedIPs 如果使用 catch-all 0.0.0.0/0, ::/0 也就会默认转发所有的流量到服务器。该选项实际作用是路由表,控制哪些流量需要经由服务器转发。

配置完毕即可使用 wg-quick up <config> 启动 WireGuard。如果一切顺利,通过路由追踪应该可以看到流量已经交由服务器转发。

总结

由于工作需要,经常合上笔记本动身前往其他地方。在接入传统企业网例如 L2TP/IPSec 甚至 AnyConnect 都无法保证设备下次进入工作状态时可以立即恢复连接。而 WireGuard 在不同网络、不同地域、不同网络中断时间等各种情况下均可在下次进入网络覆盖时立即恢复连接,再也不必担心网络中断恢复时手忙脚乱配置隧道或者不小心泄密啦。

目前唯一的不足,大概就是还没有 Windows 客户端,没有办法推广到非技术部门(虽然影响不到我…

总之,真香.jpg

Reference:

[1] https://wiki.archlinux.org/index.php/WireGuard

真是老了跟不上时代了,这么好的东西为什么我现在才开始用??

May 08, 2019 02:43 PM

April 19, 2019

ヨイツの賢狼ホロ

离开 Google 的 Android 之路

好聚好散?

要说现在流行的移动设备操作系统的话肯定有 Android 的一席之地,Google 在 AOSP 下 开放了 Android 的大部分源代码,吸引了众多硬件生产商和开发者。

如果汝是 Android 用户的话,有没有做过这些事情了呢?

  • 获得手机的 Root 权限(从 Zergrush 到 SuperSU 再到 Magisk?)
  • 安装第三方 Recovery 和 ROM(甚至自己移植流行的 ROM 到自己的手机上,从此 踏上了一条不归路……)
  • 各种方式修改系统(修改系统分区, Xposed 和 Magisk 等等)
  • 刷写或自制定制内核。
  • ……

然而时过境迁, Google 已经不是以前那个不做恶的 Google 了, Stallman 也撰文声讨过: https://stallman.org/google.html

所以 Google 使了哪些坏?

罄竹难书啊(大嘘)

  • Google 自己开发了一套私有的称作 Google Mobile Services 的软件包,包含了大多数 的 Google 应用,也有迹象表示 Google 正在把越来越多 AOSP 里的东西塞进 GMS 里。
  • Google 网站越来越依赖非自由的 JavaScript (虽然这大概是现在的趋势吧,唉……), 甚至登录和注册都需要。
  • 任何大体量的公司都容易被用于大规模监控, Google 也不例外。(人家也是要恰饭的不是?)
  • 有新闻报道称 Google 终止了转卖 Pixel 手机的用户的 Google 账户。(服务的使用条款能扩大到物理设备么)
  • Google 愈发向审查妥协,例如 不再支持域前置同意为部分政权提供审查支援 等等。

所以是时候放弃 Google 了(雾)

等等我们一直就没有用 Google 啊 -- 来自地球外的某处

开始之前?

开始之前的话,汝最好准备一部合适的 Android 手机,那么什么样叫做合适呢?

  • 最好有流行的第三方 Android ROM 适配(例如 LineageOS 等等)

    • 能解锁 Bootloader 大概是这个的充分条件。
    • 因为第三方 ROM 一般都不含 Gapps,所以适合用作基底。
    • 所以内置 GMS 的 ROM (例如 Pixel Experience) 不在推荐范围内。
    • 特别的,虽然 /e/ 在做的事情和咱现在做的事情类似,但是有不少人不推荐, 例如 https://ewwlo.xyz/evil
  • 至于哪些手机解锁 Bootloader 的难度,咱踩过的坑(?)有:

    • 早些年的不少手机是没有锁的,不在意性能的话可以考虑。(例如以前的小米和三星?)
    • 能通过一条命令( fastboot flashing unlock )解锁的设备 非常值得推荐,例如 Nexus/Pixel 和 OnePlus。
    • 像 Moto / LG / HTC 之类的主流厂商会要求汝去它们的网站上 提供一些信息生成一些解锁代码,有一点点麻烦,但又不是不能用~
    • 有些厂商解锁会失去一些功能(例如 SONY,解锁会使 TA 分区无法访问,典型 的副作用就是相机退化),如果汝不是很需要那些功能的话再考虑。
    • 有些厂商虽然允许解锁,但解锁条件过于刁钻(没错说的就是现在的小米)。 只有在汝能忍受那些恶心的条件的情况下才能考虑。
    • 有些厂商不给官方解锁,但奈何不了有些野路子(例如 HMD 的 Nokia),虽然 算作能解锁,但因为不容易的缘故,大概没有多少人为它开发。
    • 不能解锁的厂商当然不要考虑啦。 (蓝绿海军警告,以上)

在这篇和接下来的文章(如果有的话,咕咕咕)里咱就拿一台 OnePlus 3 作为演示机咯~

然后备份好所有的数据(这不是废话么)

microG - 自由的 Google Service Framework 实现

A free-as-in-freedom re-implementation of Google’s proprietary Android user space apps and libraries.

microG 是一组代替 Google 私有的 Android 程序和库的程序和库的合称。 像 Google 之类的服务大概很难一下完全放弃的, 那就慢慢来好了……

然而不少应用只认 Google 的 Google Play Service 的签名,所以咱们还需要摆弄一下系统 让它把 microG 的签名当作 Google 的。放在一起的话方法有很多:

在经历了各种方法把 microG 安装上以后,可以通过 microG 自己的 Self Check 确认 microG 的工作状态。

MicroG 的自检

接下来像普通的方法一样添加 Google 账户啦,不过咱用的时候有注意到几个问题:

  • 不能添加 G Suite 账户(?)
  • 咱不打开 microG 里的 Google Device Registration 的话没法保存 Google 账户的信息。

又不是不能用*2

如果汝哪一天下定决心完全告别 Google 的话,只要把这些东西卸载掉就 OK(大嘘)

Yalp Store - Google Play 商店的替代品

Yalp Store lets you download apps from Google Play Store as apk files. It can search for updates of installed apps and lets you search for other apps.

Yalp Store 可以直接下载 Play 商店上的应用,如果汝在里面登录了汝自己的 Google 账号, 可以下载汝购买的付费应用。

(虽然 Yalp Store 的开发者说这么干其实会违反 Google Play 商店的 TOS 因此有帐号被关闭 的风险,但是 Yalp Store 内置的 Google 帐号还存活,也没有听说过谁因为用了它被封号……)

可以在 F-Droid 上找到 Yalp Store ,或者 去它们的 Github 上下载 , Magisk 上有 Yalp Store 安装为系统应用的模组包。

F-Droid - 自由的 Android 应用程序仓库

F-Droid is an installable catalogue of FOSS (Free and Open Source Software) applications for the Android platform. The client makes it easy to browse, install, and keep track of updates on your device.

F-Droid 是一个应用目录应用,很像 Play 商店对不对?不过这里面收录的全是自由软件 (至少客户端是,虽然某些软件会有一些诸如会推广非自由服务的“反功能”)。 通过 F-Droid Priviliged Extension 可以做到自动安装应用等额外功能。

可以从这里下载 F-Droid :https://f-droid.org/en/ , Magisk 仓库中有 F-Droid Priviliged Extension 模块,NanoMod 也提供了 F-Droid 模组。

Guardian Project - 保护手机用户的隐私和自由

While we think that a secure, privacy-enhanced mobile phone is a good thing for just about anybody going about their daily lives, we like to also consider the extreme cases, where this technology might change the course of someones life.

Guardian Project 是一群开发保护手机用户隐私应用的开发者,最出名的作品是 Orbot 和 Orfox ,将 Tor 带到了 Android 的世界中。

除了 Play 商店以外,汝也可以添加它们的 F-Droid 仓库: https://guardianproject.info/fdroid/

旅途愉快 :-)

by ホロ at April 19, 2019 04:00 PM

April 09, 2019

百合仙子

T470p 使用N卡运行 Xorg

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

这么做的原因是:这样 minecraft 帧率高,不卡顿。

  • intel 显卡:帧率低,好像是20fps左右吧。开不了光影
  • optirun:坏了
  • primusrun:帧率高了一些,不多
  • nvidia-xrun:丝般顺滑,只是切换回我之前跑程序的 Xorg 时,发现我的 Awesome 已经没了。一开始是黑屏,经过配置之后倒是能得到 LightDM 的登录画图。另外 nvidia-xrun 无法卸载模块,因为被 Xorg 使用了,需要停止 lightdm。

那么,既然 nvidia-xrun 效率不错,我要是把整个桌面都搬上去呢?经过了一些折腾之后,取得了不错的结果。一个意料之外的好处是,播放视频、网页浏览器里滚动页面时常出现的画面撕裂好了~

当然这样做会费电,降低续航时间。不过既然是 T470p,一开始我就没打算整天带着它到处跑,所以无所谓啦。需要的时候再切回去好了。有个叫 optimus-manager 的软件,看介绍是帮助这么切换的。不过我对一切自动化程度太高的软件都心存疑虑,不确定它到底干了什么,会不会和我其他的配置相冲突。所以以后再看看啦。

最终的配置方案是这样的——

首先,把 bumblebeed.service 关掉并禁用。

然后,Xorg 配置一份,放 /etc/X11/xorg.conf.d/ 下就好。这份配置来自于惠狐的《Archlinux 下 Intel 和 NVIDIA 双显卡 de 折腾笔记》一文。

Section "OutputClass"
    Identifier "intel"
    MatchDriver "i915"
    Driver "modesetting"
EndSection

Section "OutputClass"
    Identifier "nvidia"
    MatchDriver "nvidia-drm"
    Driver "nvidia"
    Option "AllowEmptyInitialConfiguration"
    Option "PrimaryGPU" "yes"
    ModulePath "/usr/lib/nvidia/xorg"
    ModulePath "/usr/lib/xorg/modules"
EndSection

lightdm.conf 里在 [Seat:*] 里加一个 hook 配置,否则会黑屏的:

display-setup-script=/usr/local/bin/lightdm-setup

这个脚本内容如下:

#!/bin/bash -e

xrandr --setprovideroutputsource modesetting NVIDIA-0 || exit 0
xrandr --auto

写了一个 systemd service,用来启用 N 卡。因为默认它是关的。

[Unit]
Description=Switch On nvidia card
ConditionPathExists=/proc/acpi/bbswitch
Before=display-manager.service

[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo ON > /proc/acpi/bbswitch"

[Install]
WantedBy=graphical.target

我之前在 ~/.xprofile 配置了视频的硬件加速,现在得删掉。GM108M [GeForce 940MX] 这个显卡的视频加速没法用的。

设置内核模块的选项 options nvidia_drm modeset=1,不然 xrandr --scale 时结果会不对。

暂时就这些了。

by 依云 at April 09, 2019 04:45 AM

April 04, 2019

Felix Yan

nspawn.org:简单的 systemd 发行版容器

如果你想要运行一个发行版容器,而又不想被 docker 一类的重量级方案打扰,现在有一个新的简单方案了。

nspawn.org 目前提供了 Arch、CentOS、Debian、Fedora、Ubuntu 的各版本镜像,并可以直接用 systemd-nspawn 的验证机制进行签名验证。

推荐的用法是使用其提供的 “nspawn” 工具。下面以创建一个 Fedora 30 容器为例:

1、获取工具:

$ wget https://raw.githubusercontent.com/nspawn/nspawn/master/nspawn
$ chmod +x nspawn

2、获取 Fedora 30 镜像:

$ sudo ./nspawn init fedora/30/tar

3、启动容器并获取 shell:

$ sudo machinectl start fedora-30-tar
$ sudo machinectl shell fedora-30-tar
Connected to machine fedora-30-tar. Press ^] three times within 1s to exit session.
[root@fedora30 ~]#

一些背景:容器默认的存储路径在 /var/lib/machines/。nspawn.org 的创建者是 shibumi,目前是 Arch Linux Trusted User。所有的镜像使用 mkosi 制作,定义文件均在 GitHub 上。除了 nspawn 容器镜像,这个站点还提供可引导的 GPT-UEFI 镜像。

by Felix Yan at April 04, 2019 10:03 PM

百合仙子

系统在解析哪些域名呢?

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

最近用 Rust 写了个叫 capture-dns 的小程序,实时显示 DNS 查询结果的。配合 ipmarkup 的效果是这样的:

>>> sudo capture-dns lo | ipmarkup
[sudo] lilydjwg 的密码:
github.com -> 52.74.223.119(新加坡Amazon数据中心)
github.com -> 13.229.188.59(新加坡Amazon数据中心)
github.com -> 13.250.177.223(新加坡Amazon数据中心)
live.github.com -> 192.30.253.125(美国弗吉尼亚州阿什本GitHub)
live.github.com -> 192.30.253.124(美国弗吉尼亚州阿什本GitHub)
collector.githubapp.com -> 34.193.248.191(美国弗吉尼亚州阿什本Amazon数据中心)
collector.githubapp.com -> 52.20.29.9(美国弗吉尼亚州阿什本Amazon数据中心)
collector.githubapp.com -> 34.197.57.23(美国弗吉尼亚州阿什本Amazon数据中心)
api.github.com -> 13.250.94.254(美国Amazon数据中心)
api.github.com -> 13.250.168.23(美国Amazon数据中心)
api.github.com -> 54.169.195.247(新加坡Amazon数据中心)
ocsp.digicert.com -> 117.18.237.29(澳大利亚美国MCI通信服务有限公司(韦里孙商业Verizon Business)EdgeCast亚太网络CDN节点)

可以看到本地的软件们都在查询哪些域名,得到的 IP 又是什么。抓取的是应答,所以没得到 IP 结果的不会显示。我抓取的是 lo 网络接口,因为我本地有用 dnsmasq 做缓存。

其实这个程序一开始不是这样子的。群里有人想抓取系统上进行的 DNS 查询的域名。一开始是用 tshark 抓取的,然而它太占用内存了。我粗略看了一下 Python 的 scapy 工具,也用掉了大几十M内存。那么,用 Rust 写一个好了,也顺便练习一下 Rust。

这个程序运行时只有几M的内存占用,CPU 占用也是非常低的。不过它并没有做完全的协议分析,而是假设抓得的包是以太网帧封装的 IPv4 报文封装的 UDP 数据包里包着 DNS 应答报文。所以如果你是在 eth0 上跑 PPPoE 的话,抓 eth0 上的包就不行了,得抓 ppp0 这种了。当然你要是 IPv6 啊 DoH、DoT 啥的就更抓不到了。

后来我用 bcc 的 tcpretrans 脚本查看我这里到哪些地方的 TCP 连接不太通畅,然而经常会看到一些我猜不到是干嘛的 IP。所以就把这个程序改了一下,把域名对应的解析结果显示出来了。

Rust 不仅节省资源,而且开发的体验真的很棒呢,编译成功之后就能按我预期的运行了。也不用担心什么时候遇到个有问题的报文导致程序崩掉,因为写的时候就已经处理好了出错的情况。不像 Python 写的脚本,刚写好,一跑就抛个异常出来,提示我哪里不小心写错了。好不容易调试好了,跑着跑着,遇到意外情况就挂掉了……

by 依云 at April 04, 2019 02:21 PM

April 03, 2019

百合仙子

正确的隐藏挂载点的方法

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

脚本需要挂载文件系统,但是不希望外部看到。正确的做法是:

mount --make-rprivate /

然后该干嘛干嘛。当然如果你不知道在执行之前先调用 unshare 或者等价的系统调用,说明这篇文章不适合你阅读。

错误的做法是在挂载的时候加 --make-private 或者把 / --make-private。这个标志(MS_PRIVATE)的意思是挂载/卸载事件在这里停止传播,而不是这个挂载点的事件是否传播出去。至于为什么需要使用 --make-rprivate(增加了 MS_REC 标志),暂时我还不理解。

这个用法是从 unshare 工具的 strace 结果里挖掘出来的。因为我的目的跟 unshare -m 一样嘛,当然首先想到的是看看它是怎么干的了。你问我为什么不用 unshare -m?你自己写脚本的时候试试看啰?

by 依云 at April 03, 2019 11:05 AM

April 02, 2019

ヨイツの賢狼ホロ

PackageKit:统一(?)GNU/Linux 发行版包管理器操作的前端

如果汝是 GNU/Linux 爱好者的话,一定有自己喜欢的 GNU/Linux 发行版了吧。 对那个发行版使用的软件包管理器的操作大概也已经谙熟于心了呗~

直到汝有时需要摆弄别的发行版的时候:

horo@debian:~ $ sudo pacman -Syu
sudo: pacman: command not found

emmm......

虽然 pacman 的话,有 pacapt 这样的工具来包装其它 软件包管理器的操作。但如果汝不适合这种状况呢(例如常用 Ubuntu ?(打死……) )?

PackageKit 出手相助~ 等等那是?

PackageKit is a system designed to make installing and updating software on your computer easier.

The primary design goal is to unify all the software graphical tools used in different distributions, and use some of the latest technology like PolicyKit.

https://www.freedesktop.org/software/PackageKit/pk-intro.html

PackageKit 是一个在不同的软件包管理器中统一操作的高阶前端(比 apt / dnf 一类的更高阶?), 当然没有打算取代各位的意思啦(笑)。

和 gcc 类似, PackageKit 通常也是由若干个前端和若干个后端组成的。

  • 后端通过一系列抽象工具和 packagekitd / libpackagekit 交互。
  • 前端为用户提供界面。例如 PackageKit 自己提供的 pkcon。

所以它怎么用?

基本操作和普通的软件包管理器差不多:

# pkcon install <package>
# 如果汝的账户具有管理员权限(在大多数桌面环境中认为 wheel 组的成员具有管理员权限),
# 安装时会询问汝的密码(通过 Polkit 完成)。
$ pkcon install tk
Resolving                     [=========================]
Finished                      [                         ] (0%)
The following packages have to be updated:
tk-8.6.9-2.x86_64   A windowing toolkit for use with tcl
Proceed with changes? [N/y]
Testing changes               [=========================]
Installing                    [=========================]
Installing updates            [=========================]
Finished                      [=========================]
# pkcon search <keyword>
$ pkcon search fcitx
Searching by details          [=========================]
Querying                      [=========================]
Finished                      [=========================]
Installed           fcitx-4.2.9.6-1.x86_64 (installed)                              Flexible Context-aware Input Tool with eXtension
Available           fcitx-anthy-0.2.3-1.x86_64 (community)                          Fcitx Wrapper for anthy.
Available           fcitx-chewing-0.2.3-2.x86_64 (community)                        Fcitx Wrapper for chewing
Available           fcitx-chewing-git-0.2.3.r4.ge4bb273-4.x86_64 (archlinuxcn)      Fcitx Wrapper for chewing
Available           fcitx-cloudpinyin-0.3.6-2.x86_64 (community)                    Standalone module for fcitx that uses pinyin API on the internet to provide additional input candidates
Installed           fcitx-configtool-0.4.10-3.x86_64 (installed)                    GTK based config tool for Fcitx
Available           fcitx-googlepinyin-0.1.6-6.x86_64 (community)                   Fcitx Wrapper for googlepinyin
Installed           fcitx-gtk2-4.2.9.6-1.x86_64 (installed)                         GTK2 IM Module for fcitx
Installed           fcitx-gtk3-4.2.9.6-1.x86_64 (installed)                         GTK3 IM Module for fcitx
......
# pkcon get-updates 可以检查更新
$ pkcon get-updates
Getting updates               [=========================]
Downloading list of packages  [=========================]
Finished                      [=========================]
Normal              adwaita-icon-theme-3.32.0-1.any (extra)                         GNOME standard icons
Normal              apache-2.4.39-1.x86_64 (extra)                                  A high performance Unix-based HTTP server
Normal              archlinux-appstream-data-20190320-1.any (extra)                 Arch Linux application database for AppStream-based software centers
Normal              archlinuxcn-keyring-20190315-2.any (archlinuxcn)                Arch Linux CN PGP keyring
Normal              babl-0.1.62-1.x86_64 (extra)                                    Dynamic, any to any, pixel format conversion library
......
# pkcon refresh 可以更新软件仓库列表。
$ pkcon refresh
# pkcon backend-details 可以查询 PackageKit 使用的后端的详细信息。
$ pkcon backend-details
Name:               alpm
Description:        alpm
Author:     Aleix Pol i Gonzàlez <aleixpol@kde.org>, Fabien Bourigault <bourigaultfabien@gmail.com>, Jonathan Conder <jonno.conder@gmail.com>

其它 pkcon 的命令可以通过查询手册页了解(pkcon(1))

那有没有图形前端?

当然有啦,例如 gnome-packagekit 和 apper, 它们通过 PackageKit 提供了安装,查找和卸载软件包的功能:

gnome-packagekit 的界面 apper 的界面

如果汝更中意类似应用商店的体验, GNOME 有 GNOME Software, KDE Plasma 有 Discover:

GMOME Software Discover

至于怎么用请参考它们和汝正在使用的 GNU/Linux 发行版的文档 (懒了……)

PackageKit 不是什么?

PackageKit 不能代替汝正在使用的软件包管理器(毕竟没了它们做后端这家伙啥也干不了)

emmm......

by ホロ at April 02, 2019 04:00 PM

March 31, 2019

百合仙子

迁移系统到 SSD

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

最近一段时间,不知道是磁盘、缓存相关算法的更新,还是我开的服务太多,又或者是新软件占用内存太高,我的系统越来越卡了,尤其是更新系统的时候(备份系统时也特别卡,然后我用限制内存占用的办法解决了)。我当然知道最主要的原因是因为机械硬盘的处理能力就那么多,于是经过一些了解和计划之后,还是决定换 SSD 了。

刚才查看了一下历史数据。从去年七八月份起,平均内存使用量从2G多升高到了3G多。大概是火狐更占内存了吧。我都尽量减少内容进程数量了……也可能是 PHP / MediaWiki 的锅,因为使用 SQLite 存储时,经常发生错误也是这段时间的事情。不过也可以理解为由于磁盘负载重导致的。算了不管了。

准备工作

当然首先要去买块 SSD 啦。我买的是 LITEON T11 Plus 512,512GB,800块。实际操作系统得到的空间是 477GiB,因为硬盘产业还在沿用1000进制的单位词头。它比我预期的要小不少呢,不过拿在手里感觉比一般同样大小的电路板要重。

拆开我的 T470p,把空闲接口旁边的螺丝下下来,然后 SSD 标签朝外插进去。我也不清楚这个接口叫什么。插进去之后它是翘起来的,难怪要用螺丝固定。然后用下下来的螺丝固定好,再把机器装好,就好了。启动系统,可以看到 /dev/nvme0n1 设备在了~GNOME 磁盘软件不能读取到 SMART 信息,用 smartctl -a /dev/nvme0n1 命令就好了。

设备没问题了,接下来当然是备份系统啦。

开始迁移

备份妥当之后,我就开始格式化 SSD。计划是 EFI 分区 512M,400G 给我的 Arch Linux,然后剩下 76G 左右的空间预留给我的 Win10。

然后这 400G,首先上一层 LUKS 加密,然后格式化为 btrfs 文件系统。其实我想要 btrfs 很久了,快照、去重、压缩都挺棒的。但是听说它的性能比较差,而我已经在受磁盘 I/O 能力不足的苦了,所以到现在有了 SSD,是时候换 btrfs 了!

其实之前 zfs(zfsonlinux)也是候选项,并且已经在工作本上使用过了。然而最近我的 zfs 备份两度出现问题(磁盘掉线之后 zfs 元数据损坏,导致一整个 zfs 文件系统一写就卡住;近期莫名其妙 rsync 跑着跑着就卡在那里不动了,磁盘也没有什么活动),再加上之前遇到的各种大小问题(ARC 被算进内存使用量中;挂载期间一旦磁盘离线就卡死;克隆出来的文件系统无法摆脱原文件系统;不支持 overlayfs;因为是树外模块所以需要专门准备的支持 zfs 的系统来执行安装),以及 TRIM 支持刚刚才加入,我已经停用 zfs 并将其排除考虑范围了。

然后就是规划子卷。参考了 openSUSE 的方案,最终决定分为这么几个子卷:/, /var/cache, /var/tmp, /var/log, /var/lib/lxc/lxc-debian/rootfs, /var/lib/lxc/lxc-centos6/rootfs, /home/lilydjwg, /home/lilydjwg/.cache。主要考虑的是快照。另外我给 /var/log/journal 和 /var/lib/postgres chattr +C 禁用了 CoW。这样也会禁用压缩,不过本来它们基本上就没什么可压缩的。需要排除的有:我的公开第三方源码和各类大文件用的 /ldata 还是放在机械硬盘上、/var/cache/pacman/pkg 缓存不要、/var/lib/pacman.fs 不用单独放连续的文件里了、/home/lilydjwg/.cache 缓存不要、/home/lilydjwg/.debug 这个 perf top 用的目录会有 libc 的硬链接,rsync 时会失败所以就不要了。

最终的同步命令如下:

sudo systemd-run -p MemoryMax=64M --scope \
  rsync -aviHAXKhPS --inplace --delete --exclude='*~' --one-file-system \
  / /mnt/root --exclude=/var/cache/pacman/pkg --exclude=/home/lilydjwg/.cache \
  --exclude=/var/lib/pacman.fs --exclude=/ldata --exclude=/home/lilydjwg/.debug

同步好之后,重启进入 live 系统再同步一次以保证最新数据也同步好了。然后把部分被排除的目录再同步一下:~/.cache/winetricks 这个以后不一定能够下到、~/.cache/sxiv 都是有效缓存(我有清理)而且生成耗 CPU、/var/lib/pacman 这个是被 --one-file-system 排除掉的。

然后是在 /etc/default/grub 里更新内核命令行 cryptdevice=/dev/disk/by-partlabel/ssd:ssd:allow-discards。这个 allow-discards 会轻微地降低安全性,不过在中国没什么用的。更新 /etc/fstab。

然后还有 /boot 要处理。其实就是把内核和 initrd 复制过去,然后重新安装 grub、生成 grub 配置。位于机械硬盘上的旧文件之后再删掉即可。

重启,使用 fallback 版 initrd 进入系统,开始修复各种问题。

首先是更新默认的 initrd。不过在更新它之前,我要修改一下我自己的 hook。之前这个 hook 里只有 partprobe 我解密之后的机械硬盘分区,因为我在它上边又分了 xfs 和 swap 两个区。现在因为 encrypt hook 解密的是 SSD 上的分区,所以这个机械硬盘上的加密分区的解密也要自己做。其实也很简单,给这个加密分区添加一下文件密钥,然后

cryptsetup open --type=luks --key-file=/etc/keys/hdd.luks /dev/disk/by-partlabel/main main

就可以了。不需要输入两次密码。

/ldata 使用 automount 延迟挂载,所以需要写 ldata.mount 和 ldata.automount 两个文件,然后 enable ldata.automount 那个。不知道写在 /etc/fstab 里是不是也行。然后把机械硬盘里的目录结构调整一下,把原来 /ldata 下的东西上移一级,旧的 / 里的其它东西都放到隐藏的 .oldroot 里去好了。

swap 本来我是保留着的,不过发现这样子我会时不时听到机械硬盘启动了。而且因为机械硬盘启动比较费时,所以系统会卡好一会儿(大概有一两秒)……所以我默认就不开 swap 了,但是 resume hook 还是保留,需要的时候打开 swap 就可以休眠了。这个 resume hook 也是我需要在启动的时候就解密机械硬盘上的加密分区的原因。

加了一个每周运行的 fstrim -v / cron 任务。没有使用 fstrim.timer 是因为它会 trim 所有设备。而我可不希望它去 trim 我挂载的机械硬盘上的 loop 设备,会造成大量碎片的。

还有一些小问题要处理。chattr +i /etc/resolv.conf 以避免 DNS 服务器被不知不觉修改了。我有用 dnsmasq 的所以这个文件不用动。我有一个 MediaWiki 实例的文件是使用 overlayfs 的,它现在挂载提示「failed to verify upper root origin」。后来才发现相关目录上有同步到几个 trusted. 开头的、overlayfs 使用的扩展属性。是它还挂载的时候被同步到的,不知道为什么最后一次同步时没有被清除掉。手动使用 setxattr 删除掉就好了。

rsync 还出了另外几个莫名其妙的问题。我在 /usr/local/sbin 下有个最近新加的文件的执行权限消失了,造成使用它的 systemd 服务失败。另外有个最近被删除的配置文件竟然还在。我不是有指定 --delete 选项吗?火狐缓存的网站图标也都没有了,需要访问之后才会重新出现。~/.cache 下有很多 root 所有的空目录,也许是我哪次忘记 --exclude 它然后又中断才加上?

Wine 有几个文件有几十 KiB 大的 user.wine.sd 扩展属性。太大了以至于 btrfs 里放不下,报「No space left on device」错误。我刚看到时还吓一跳,以为是我的 SSD 满了,仔细一看才发现只是扩展属性写不下而已。

我于是又带 --dry-run 参数同步了一次,确定再没有什么需要的东西被落下。这次 rsync 出现这些问题很是奇怪,不过我没有留日志,加上操作的时候其实是有不少修修改改的,所以就不深究了吧。

修好所有发现的问题,再次重启之后,systemctl status 和 systemctl --user status 没有失败项了~撒花 O(∩_∩)O~

后记

现在我的系统超快的!比如启动时间:

>>> systemd-analyze
Startup finished in 9.257s (firmware) + 1.466s (loader) + 15.110s (kernel) + 6.945s (userspace) = 32.780s 
graphical.target reached after 6.945s in userspace

firmware 和 loader 咱管不了。kernel 那儿包含了我输入密码解密,以及解密和探索机械硬盘上的分区,所以花了些时间。userspace 那里你别看花了好几秒,其实大部分时间都是花在联网上了。不依赖网络的服务在差不多一秒的时间内就全部启动好了。

之后我还要更新备份脚本,因为我用了 --one-file-system 而现在它们在不同的子卷上。再写一下每日快照的脚本,就不用一不小心删错文件啥的都要去备份里找了。

关于写入量,smartctl -a /dev/nvme0n1; sleep 300; smartctl -a /dev/nvme0n1 统计了一下,因为我开了 collectd 收集一些系统数据,每分钟大概会写入 60MiB 的数据。算下来,一年要写 20T 左右。这块 SSD 标称的是 280TBW,也就是可以写 280TB 的数据。这么算起来能用十年,所以就这样吧,不用再优化了。顺便说一下,SMART 信息里的「Data Units Written」数据,乘以 512000 之后是字节数。

就这样啦。最后还要说一句:SSD 超快的!

by 依云 at March 31, 2019 07:28 AM

March 02, 2019

百合仙子

使用 cgroups net_cls 来让 docker 走代理

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

我这里 docker hub 连不上或者连上了访问很慢,根本没法用。本来我常规代理的办法,要么是 proxychains,要么是用 iptables 代理特定的 IP 段。至于 docker 嘛,亚马逊的 IP 段那么多,它用到的域名我也不是很清楚,一点点加好麻烦。作为系统服务,用 proxychains 不仅得修改 systemd 服务配置,而且不知道会不会出什么幺蛾子。最近刚好在某个地方看到这一手,就试试啰。

其实用法很简单的。去 /sys/fs/cgroup/net_cls 下建立个目录,往 net_cls.classid 里写一个整数(支持十六进制的 0x 表示法),然后把 dockerd 的 pid 写到 cgroup.procs 里去。最后用 iptables 代理这部分流量即可。现在都用 443 端口啦,所以只要代理它便好,也避免影响了别的东西:

iptables -t nat -A OUTPUT -p tcp --dport 443 -m cgroup --cgroup 0x110001 -j REDIRECT --to-ports XXX

XXX 是 ss-redir 的端口啦。

注意不要把进程的 pid 往 tasks 文件里写。那里得写的是 task 的 id 而不是 process 的 id,也就是说(用内核的术语来说)是线程的 pid 而不是进程的 tgid(thread group id)。所以非要写 tasks 文件的话,得把 docker 所有的线程的 pid 都写进去才行。真是混乱呢……画个表格好了:

用户态 内核 相关系统调用
pid tgid getpid, kill
tid pid gettid, tgkill
process task group fork, clone without CLONE_THREAD
thread task clone with CLONE_THREAD

另外如果更新过内核的话,那句 iptables 有可能会找不到模块的。(所以更新内核之后还是重启一下以避免尴尬吧。)

by 依云 at March 02, 2019 04:15 PM

使用 cgroups 限制指定进程的内存使用

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

最近我的系统有这么个问题:在备份或者系统更新等高 I/O 负载的时候,系统整体性能下降严重,界面经常卡到动不了。经过分析发现此时比平常多了许多磁盘读操作。平常的时候磁盘读操作是很少的,会有大量的缓存命中,反倒是写操作一直都有(因为我本地搭了个监控系统)。啊对,分析用到的磁盘性能数据就是来自于这个监控系统。

所以原因很清楚了:备份和系统更新不仅造成了大量缓存未命中,还占用了本来存放着热数据的缓存,导致常规使用的缓存命中率也急速下降,结果我的机械硬盘就忙不过来了。

那么,要是能够限制这些操作占用的缓存,性能不就能好一点吗?那些新读进来的数据反正是短期内再也用不到了,缓存起来也只是浪费有限的内存空间啊。

研究了一下 /sys/fs/cgroup/memory/memory.stat,看起来 cgroups 内存限制是包含缓存部分的,于是就试试呗。正好 systemd 直接就能设置了:

$ sudo systemd-run -p MemoryMax=512M --scope pacman -Syu

本来我是设置的 256M 限制,结果发现 dkms 编译内核模块的时候超级慢,还用掉了不少 swap……于是分了 512M。效果还是不错的,常规操作偶尔还是卡一卡(毕竟还是有一些 I/O 操作),但比起不限制的时候要少很多。

要注意一点的是,不使用 cgroups v2 的话(Arch Linux 默认),这个命令不能加 --user 以在用户级的 systemd 下跑的。而使用 cgroups v2 的话,lxc 和 docker 都跑不了……

备份也是类似的,而且因为 rsync 自己用不到多少内存,这个效果更好:

$ systemd-run -p MemoryMax=256M --scope ./backup-my-system

终于又一次在半小时内完成了备份 QAQ 之前动不动就一两小时的。

我也不知道为什么这个问题近期才出现,总之现在是缓解了。(接下来有空继续计划换 SSD 硬盘的事情~

by 依云 at March 02, 2019 03:51 PM

February 23, 2019

farseerfc

东方歌词翻译迁移至 sak.uy

最近几个月在这个博客发了不少歌词翻译 似乎有要转型成音乐博主的趋势 ,前段时间买了个新域名 sak.uy ,准备专门用来放这些东方歌曲的歌词翻译,于是分设了单独的博客「 Sakuya的音乐盒 」。主博客这边右侧边栏会有到音乐盒的链接。

曾经在这边的那些歌尽量保持 URL 跳转过去,新的歌词翻译会发到那边去,还想继续听歌的话请继续订阅那边的 RSS 呀。

主博客这边还是像往常一样保持记录生活点滴和技术经验好了。说道介绍技术, 有人问过我那些日语歌词上给汉字标注的假名都是我一个个手输的么? 一开始是手输的,后来发现了不错的自动化方案,于是这里介绍一下。

首先是 python-furigana

这是个 python 写的小程序(严格说是库),可以把一段日文转换成标准的 HTML 形式的 <ruby> 标签的振假名( 振(ふ) り 仮名(かな) )。 它本身只是个方便的格式化库,实际工作是用 python-mecab 这个 binding 去查询 mecab 这个著名的日语语料分析库。要用它还得配合一些开源的 mecab 词典,这些在 [archlinuxcn] 都有打好的包了,直接安装:

$ sudo pacman -Syu python-furigana mecab-git python-mecab mecab-ipadic

装好之后用法也很直接,甚至没有 binary 直接调用 python 的 module 就可以:

$ python -m furigana.furigana "振り仮名の例"
<ruby><rb>振</rb><rt>ふ</rt></ruby>り<ruby><rb>仮名</rb><rt>かめい</rt></ruby>の<ruby><rb>例</rb><rt>れい</rt></ruby>

就是提供日语作为输入,然后输出 HTML 形式的 <ruby> 标签而已。 像上面的例子中出现的错误(「振り仮名」完整的一个词中「仮名」意思是「平仮名」应该发音「がな」而非意为「假的人名」的「かめい」) 可以看出其实标注的准确率还是有些问题的。嘛日语作为一个非常依赖上下文判断的语言, 经常日本人都会搞错某些汉字的发音,这些也不能强求机械化的算法能 100% 正确实现。 好在单纯的词典匹配也能满足大部分标注的需要了,用这个标注总体来说 95% 以上的情况都是正确的(歌词的话正确率低一些,毕竟歌词中古语啦当て字啦训読み这些情况很常见)。

把输出插入我的博客

然后我的博客用 reStructuredText 语法写,不能直接用 HTML 标签(虽然我加了 :html: 这个 行内角色(inline role) 但是大量用也不方便)。这个博客一开始用 Pelican 重写主题的时候 我就实现了个自己的 :ruby: 行内角色(inline role) 用来标发音,于是一段 sed 就能把 python-furigana 的输出转换成我用的 rst 语法:

$ which clipboard Co Ci Ct
clipboard: aliased to xclip -selection clipboard
Co: aliased to clipboard -o
Ci: aliased to clipboard -i
Ct () {
    t=$(mktemp /tmp/furigana-XXXX)
    python -m furigana.furigana $(Co) | sed 's@<ruby><rb>@ :ruby:`@g;s@</rb><rt>@|@g;s@</rt></ruby>@` @g' | sponge $t
    cat $t | tee /dev/tty | perl -pe 'chomp if eof' | Ci
}

上面这些 alias 在我的 .bashrc 中。有了这些之后, 我只要把需要标注的日语文本放入剪切版,执行 Ct ,再粘帖结果就好了。

$ echo "振り仮名の例" | Ci
$ Ct
:ruby:`振|ふ` り :ruby:`仮名|かめい` の :ruby:`例|れい`

然后所有那些歌词上标注的假名都是这样一句一句标注好之后,再手动校对修改的。

by farseerfc at February 23, 2019 11:37 PM

February 19, 2019

ヨイツの賢狼ホロ

和 FiveYellowMice 交换问题!

终于还是咕咕出来了?

所以这笔谈是个啥东西?

笔谈,是指人们在面对面的情况下不使用口头语言而是通过互相书面书写或键盘输入文字的方式,来传达彼此意思的沟通行为。 是汉字文化圈地域内不同母语的文人相互交流的方法之一。主要使用汉字以及文言文(汉文)的交流方式。

看这家伙已经懒到直接抄维基百科了……

🐁🐁🐁🐁🐁 的问题和咱的回答~

  • 看到萌狼有经常尝试非常正统的 GNU 操作系统,一点点不清真的东西也容不下的那种, 然后因为来自硬件和软件的支持都很少,用起来就很辛苦。虽然黄鼠也同样幻想着 GNU 能够成为被主流支持的东西,但是如果现实地讲,萌狼觉得纯正的 GNU 有怎样的意义呢? 比起其它的相对来说更接受非自由软件的存在的理念而言。

    如果 🐀 去翻翻以前的史话什么的,大概就会发现软件本来都是自由的啦。 RMS 也许只是在回归本源而已(笑)。以及现在计算机科学越来越发达了, 汝真的放心让那些私有的黑盒子走(kong)进(zhi)汝的生活嘛(😂)。

    // 关于自由软件的必要性和思想什么的, RMS 编辑的 Free Software, Free Society ( BLUG 哪边有中文翻译 https://beijinglug.club/fsfs-zh/ )整理了一些文章, 🐀 可以去看一看咯~

    // 至于完全自由的生活会不会比较难过(虽然咱其实还没达到), 咱现在觉得除了游戏基本上已经没有什么问题啦。不少领域里自由软件都已经达 到了可用甚至优秀的水平,也有不少可以自由驱动的硬件了(虽然都有点旧但是还能用)。 总之还是充满希望的啦~

  • 街机音游看起来很有趣呢。但比起在自己的设备上玩的游戏, 除了要碰运气才能够在自己生活的地方附近找到想玩的游戏以外,每次玩还都要付钱, 玩不了几次就会比买一份普通的 PC 或者主机游戏花得钱多了。 对这样按照回合收费的商业模式,萌狼有着怎样的看法呢?

    如果家里有矿的话可以自己买一台街机回家啊(大雾)

    怎么说呢,如果汝真的喜欢上了什么的话,那么在自己能力范围内的消费大概就会逐渐被 自己忽略了吧……还有啊,几乎大多数游戏类型里,想要提升自己的水平的话只 有靠长时间的练习对不对(当然有些时候也需要玩家间的交流和相互支持),当汝 看到自己从一开始手忙脚乱到后来能行云流水的游玩自己擅长的谱面的时候, 那股欣慰和成就感应该也能冲刷掉一点氪金的伤感(?)

    总之不管付费方式怎么样,遇到合适自己的游戏,玩家还是会心甘情愿的买单的不是?

  • 萌狼觉得自己在最近的几年,有着怎样的改变呐?

    觉得自己快成和以前不同的另一个(zhi)人(lang)了 😂

    可能就是从各种各样的第一次开始吧,开始思考一些以前觉得稀松平常的问题了 (例如隐私和安全什么的)。最直接的结果就是出门带上的东西成倍增加 😂

  • 萌狼是怎样知道「何でも言うことを聞いてくれる」的梗,又是为什么会喜欢上的呐?

    和朋友一起打 maimai 时听来的,然后就去搜索了下那首歌的 BGA , 莫名还挺好(mo)看(xing)的 ?以及茜酱超会听(fu)话(yan)的对不对~

  • 除了狼以外,觉得毛茸茸的四脚哺乳动物中,哪种最喜欢呢?

    🐱,因为自己只亲手摸过猫的样子? 😂

  • 觉得自己总体来说,是外向还是内向的人呢?在哪些地方是外向的,哪些地方是内向的?

    总体应该算是内向的吧(只是看起来而已,和咱一起久了的家伙都觉得咱挺活 (gao)泼(shi)的。要是问方面的话咱自己也不太能搞清楚的样子…… 😞

  • 做出和各种人交换笔谈的决定,黄鼠觉得会很辛苦呢。尤其是越到后面, 别人想问萌狼的问题也许很多都被问掉了,萌狼想问别人的问题也会很容易变得重复和单调。 这样的困难,萌狼准备怎样应对呐?

    其实咱一开始根本没有考虑到这一点 😂,大概就是突然有了这么做的想法就 付诸实施的样子。不过咱大概能做到打出的问题不至于太重复吧, 至于收到的问题是什么样的就 emmm (不过在这之前是不是该先考虑能找到几个愿意和咱 这样笔谈的笔友(?)的问题) 😮

  • 😋 ?

    😋!

那么下一个是?

其实还没想好 😂,如果咱友链里剩下的谁愿意自告奋勇也热烈欢迎啦 ……

by ホロ at February 19, 2019 04:00 PM

February 16, 2019

百合仙子

在 Linux 下整理磁盘碎片

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

磁盘碎片其实有两种:文件碎了,和空闲空间碎了。使用 FIEMAP 命令可以获取到文件在磁盘(的逻辑地址上)的分布情况。也是 filefrag -v 命令输出的东西。比如我的 pacman.log 就很碎:

Filesystem type is: 58465342
File size of /var/log/pacman.log is 11052443 (2699 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..    2015:  170210423.. 170212438:   2016:
   1:     2016..    2017:  170567879.. 170567880:      2:  170212439:
   2:     2018..    2027:  170569969.. 170569978:     10:  170567881:
   3:     2028..    2030:  170574582.. 170574584:      3:  170569979:
   4:     2031..    2031:  170574631.. 170574631:      1:  170574585:
   5:     2032..    2033:  170592662.. 170592663:      2:  170574632:
....
 123:     2683..    2687:   56903805..  56903809:      5:   56906403:
 124:     2688..    2698:   56903011..  56903021:     11:   56903810: last,eof
/var/log/pacman.log: 125 extents found

整理的办法也很简单,复制一下,基本上就好了。只要剩余空间足够,小文件会变成一整块,大文件也是少数几块。如果非要弄一整块大的,比如我存放 pacman 数据库的那个小文件系统,可以用 fallocate -l 200M pacman.fs2 这样子的命令分配空间,然后把数据 dd 进去(cp 不行,因为它会先截断文件再写入,之前分配的空间就释放掉了)。

介绍完毕,重点来了:怎么找到那些被写得很碎很碎的文件呢?

对每个文件调用 filefrag 肯定太慢了,所以我写了个库和工具 fiemap-rs 直接调用 FIEMAP。它提供两个工具。一个是 fraghist,统计碎片数量分布直方图,用来了解一下某群文件有多碎。另一个是 fragmorethan,用来寻找碎到一定程度的文件。运行起来是这样子的:

/var/log:
# Number of samples = 712
# Min = 1
# Max = 297
#
# Mean = 11.338483146067423
# Standard deviation = 40.138129228003045
# Variance = 1611.0694179238724
#
# Each ∎ is a count of 13
#
  1 ..  31 [ 658 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
 31 ..  61 [  11 ]:
 61 ..  91 [   9 ]:
 91 .. 121 [  10 ]:
121 .. 151 [   6 ]:
151 .. 181 [   5 ]:
181 .. 211 [   3 ]:
211 .. 241 [   2 ]:
241 .. 271 [   3 ]:
271 .. 301 [   5 ]:
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 271
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 277
/var/log/journal/00000000000000000000000000000000/system.journal: 274
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 297
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 274

我系统上最碎的两群文件是 journal 日志和 python2-carbon 的数据文件。carbon 优化做得挺不好的,明明是预分配的固定大小文件啊,不知道怎么的就弄得很碎了。部分程序的日志(如 pacman、getmail)和火狐的 SQLite 数据库也挺碎的。后边这些我已经处理掉了所以示例输出只好用 journal 的啦。

找到想要整理的过碎的文件之后,复制一下就好啦:

for f in $(<list); do sudo cp -a $f $f.new; sudo mv $f.new $f; done

啊对了,工具的编译方法是,获取源码并安装 Rust 之后,在项目根目录里 cargo build --release 然后就可以在 target/release 下找到新鲜的可执行文件了~顺便说一下,这东西是支持 Android 的哦。

by 依云 at February 16, 2019 08:54 AM

February 09, 2019

ヨイツの賢狼ホロ

舞律炫步体(tu)验(cao)

嗯…… 大概就是标题那样,在咕咕咕和没零件交错后咱玩到了 国行版的 DANCERUSH STARDOM ,中文名叫舞律炫步 😂

等等 DANCERUSH STARDOM 是什么东西?

DANCERUSH STARDOM 是KONAMI目前(2019年1月)最新的 BEMANI 系列游戏。 事先以 STEPSTAR, ShuffleDancerz, DANCE GENERATIONS, 和 DANCE RUSH 的名义进行了场测, 直到 JAEPO 2018 展会才以 DANCERUSH STARDOM 作为正式名义推出。

DANCERUSH STARDOM 是一款和舞蹈进化非常相似的跳舞机. 但并没有使用之前舞蹈进化使用的微软Kinect for Windows来捕捉玩家的动作, 而是采用了英特尔 RealSense 410 (RS410)作为新的动作感应器, DANCERUSH 还有一个非常大 的感应地板, 作为主游玩感应设备。

可以去它们的官方网站看到具体是啥样子

早些时候就有了世宇科技(?)要代理 DRS 的消息,还在中山展出过(可以叫场测嘛……), 虽然说的是一月开始铺货,但是因为下方的踏板没能和框体一起送到的缘故咕咕咕到 2 月 2 日才开始运营……

那么这游戏该怎么玩?

官方有教程视频

那国行有啥区别咧?

国行框体的标题画面

^ 国行框体的标题画面(那个“请在按下面按”是什么鬼?)

中国专用 e-amusement 了解一下?

  • 和以前引进的 BEMANI 街机一样,肯定不能连官方的 e-amusement 啦,于是就搞出了个 “中国专用 e-amusement” 那样的东西
  • 所以理所当然的砍掉了刷卡器和数字键盘。登录?又是微信扫码的日常套路……
扫码登录
  • 价格奇坑(待会儿再讲)
  • 既然某 Y 字头网站在国内不存在,自然没有录影功能。
  • 默认简体字界面,当然语音也中文化了。不过能在开始时选择其它语言,和官机一样。
  • 没有储星星等各种解禁元素,取而代之的是星星提升等级解禁……
  • 然而全曲只有 76 首(20190130),而且一如既往的删了些?(例如咱没见到 Butterfly)
  • emmm ......

为啥说国行价钱坑?

默认只有 1 Stage (官机哪怕是 LIGHT 也是两 Stage 保证咧),后来发现世宇还搞了个啥会员?

中国专用 e-amusement 的会员价格

就这个,不知道这会员是一个游戏一个游戏的卖还是和官方一样(e-amusement 是有 Subscription 的, 然后不同的游戏可能会单独卖个像会员的东西,例如 beatmania IIDX 的 Platium Members Card)。 顺便说一句这个 am 点是他们自己搞出来的啥,1 am 点 = 1 元人民币,看起来挺像 PASELI 的哈……

于是不氪 VIP 是进不了 EXTRA STAGE 的(官方的话是 STANDARD 模式两曲合计 180 分以上就能进,以及这游戏 满分是 100 分),更甚不氪会员都没法存档,嗯可以的……

drs这个收费 30和50都是废物.jpg -- 一位不愿意透露姓名的 L 姓玩家

以及氪了 VIP 的话 Gauge 不会下降?(EXTRA STAGE 本来是 10 次 Bad 就游戏结束的,咱打完发现一把 Bad 的后 开始怀疑这点了……)

那咱觉得怎么样呢?

啊有的玩已经很不容易了……

如果汝有音游基础(特别是街机音游玩家)或者舞蹈基础(推测?)的话,这个游戏还是挺简单的。 (反正咱玩了一下午可以瞎蹦蹦 9 级曲了,目前最难 10 级不敢试……)

游戏除了一般的教程的话还有几种常见动作的指导和训练,刚上手(严格来说是上足?)的时候建议玩玩看。

杂记

  • 虽然教程汉化了还是有路人直接跳过教程…… 于是就能见到 emmmm……
  • 和隔壁鹅舞形成了鲜明的对比……
鲜明的对比?

by ホロ at February 09, 2019 04:00 PM

February 08, 2019

Hexchain Tong

在 Linux 上使用 Docker 和 Java 开发酷 Q 插件

最近出于一些奇怪的原因,我需要写个 QQ 机器人。

酷 Q 是个比较常见且好用的机器人框架,但很可惜是 Windows only 的。虽然有官方支持的(使用 Wine 的) Linux Docker 镜像,但为了开发插件,还要设立交叉编译开发环境,十分麻烦。在论坛上发现酷 Q 有 Java 插件,就可以借助 JVM 使用各种原生的工具开发插件,然后扔进 Docker 里的 Wine 的 JRE 去运行。

获取 Docker 镜像和 Java 插件

首先要获取 CoolQ 的 Docker 镜像,并启动一次。这是为了建立基本的酷 Q 目录结构:

coolq/
├── app
│   ├── com.coxxs.music.cpk
│   ├── com.coxxs.start
│   │   └── start.cfg
│   ├── com.coxxs.start.cpk
│   ├── com.coxxs.status.cpk
│   └── moe.min.qa.cpk
├── bin
│   ├── CQP.dll
│   ├── gzip.dll
│   ├── htmlayout.dll
│   ├── libeay32.dll
│   ├── libiconv.dll
│   ├── sqlite3.dll
│   └── zlib1.dll
├── conf
└── CQA.exe

然后下载 酷 Q Java SDK 并按提示放入 coolq/app/ 目录中,启动酷 Q 并在插件管理器中启用 Java 插件。插件会提示找不到 JRE,暂时忽略。

下载 Windows JRE

然后,到 http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html 获取32 位的 Windows JRE 压缩包,如 jre-8u202-windows-i586.tar.gz。这里使用压缩包是为了避免额外的安装步骤。

然后将 tar 包解压至 coolq 目录下,解压之后应该有 jre1.8.0_202/bin 等目录。

编辑 coolq/data/app/com.sobte.cqp.jcq/conf/setting.ini 文件,修改 JrePath 指定 JRE 路径(Docker 中的根目录对应 wine 中的 Z:\):

[JavaVM]
JrePath=Z:\home\user\coolq\jre1.8.0_202\

然后重启酷 Q,此时插件应该能找到 JRE。

做插件

参考论坛提供的 Demo 写插件。需要注意 json 文件中的 appid 字段,和 appInfo() 的返回格式。

然后编译构建,将 jar 包和 json 按正确的名称复制到 coolq/app/com.sobte.cqp.jcq/app/ 下,重启酷 Q 就会生效。

使用 maven-assembly-plugin 可以将依赖打进最终生成的 jar 包中。

stdout(竟然)是可用的,可以简单的使用 println() 输出调试信息。但输出的中文会乱码,原因是 Java 在 Windows 上的输出并不是 UTF-8 编码的。参考 https://stackoverflow.com/a/29231668 修改 System.out 的编码后解决。

by hexchain at February 08, 2019 08:46 PM

February 07, 2019

百合仙子

docker 里几个基本概念的简单类比

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

首先说明一下,这是一位 docker 新手对于 docker 的粗浅理解。如有不对还请谅解。我很早之前就尝试过使用 docker,然而由于术语的差异,导致我每次运行东西时都傻乎乎地创建了一个新的容器……现在感觉用法终于是弄对了,所以整理一下,将其类比到 Linux 上的普通软件的概念上。

image
相当于软件分发中的软件(安装)包
Dockerfile
跟 PKGBUILD 类似,是用于制作一个 image 的打包脚本。用 docker build -t name:tag . 就可以制作。
container(容器)
一个容器就像是一个安装好了的软件包。该软件已经准备好,随时可以运行了。
docker run
安装」指定的 image。也就是从 image 制作出容器来,顺带着进行首次运行。如果反复使用,会把同一个软件给安装多次。
docker start
就像是「运行」一个已经安装好的软件,容器跑起来了。之前容器的状态(文件的修改)也会生效。
docker ps
列出运行中或者已安装(带 -a 参数)的软件们。前者和 UNIX 命令 ps 类似,后者则没什么相似之处了。
docker exec
在正在运行的软件的环境内执行命令。有点类似于 ssh。
repository
跟 Linux 的包含众多软件的软件源并不一样。这个东西跟软件名类似,用于标识为特定功能的 image 集。发布出来的 repository 名的格式通常是 `owner/name`,跟 GitHub 差不多的。
tag
软件的版本,跟什么 lite、pro、beta 之类区分类似。它并不是用于分类的标签,也不是 git 中对于指定版本的不变的称呼。它更像是 git 的分支在某些情况下的作用,比如 latest tag 就跟 git 仓库的 master 分支一样,总是指向最新的版本。

我经过以上这样的映射之后,docker 理解起来就容易多了,行为也更符合预期。

by 依云 at February 07, 2019 12:24 PM

February 06, 2019

farseerfc

用 usbip 转发 raspberry pi 的 USB 键盘鼠标给 Arch Linux 的 PC

惠狐 megumifox 写了篇 用PulseAudio将电脑的声音用手机放出来 ,文末提到想知道我怎么用树莓派转发 USB 的,于是写篇文章记录一下。

起因

家里有个装了 Arch Linux ARM 的树莓派3B 闲置着,装了 Arch Linux ARM 偶尔上电更新一下, 不过因为性能实在不适合做别的事情于是一直在吃灰。某日 给老婆安利幻想万华镜和老婆看片 的时候, 老婆不吃安利于是迁怒键盘鼠标键盘鼠标被长长的 USB 线扯着感觉很难受 ,于是偶发奇想,能不能利用一下树莓派的多达 4 个 USB 2.0 端口接鼠标键盘呢, 这样鼠标键盘就可以跟着树莓派来回走,不用拖着长长的 USB 线了。

上网搜了一下, Linux 环境有个 usbip 工具正好能做到这个。原理也很直观, usbip 能把 USB 端口上的数据封装成 IP 协议通过网络转发出去,从而两个网络间相互联通的电脑就可以远程转发 USB 了。 设置好的话,就像是一台 PC 多了几个位于树莓派上的 USB 端口,插上树莓派的 USB 设备统统作为 PC 的设备。

这篇文章假设有一个装了 Arch Linux 的 PC ,和一个装了 Arch Linux ARM 的树莓派, 并且两者间能通过网络互相访问到。别的发行版上大概也可以这么做,只是我没有试过。 usbip 工具似乎普遍被发行版打包了,除此之外需要的也只是 Linux 内核提供好的功能而已。

设置 Arch Linux ARM 的树莓派端

假设树莓派上面网络已经设置妥当,开机插电就能自动联网。接下来安装 usbip 工具:

$ sudo pacman -Syu usbip

然后需要记录一下树莓派的 IP 地址:

$ ip addr
3: wlan0: ......
inet 192.168.0.117/24 brd 192.168.0.255 scope global noprefixroute wlan0
......

接下来给 udev 添加一个规则,当插入 usb 设备的时候,执行我的脚本 usbipall.sh 把 usb 设备通过 usbip 共享出去:

$ cat /etc/udev/rules.d/usbipall.rules
ACTION=="add", SUBSYSTEM=="usb", RUN+="/usr/bin/bash /usr/local/bin/usbipall.sh"

这个 rules 文件 可以在我的 dotfiles 里面找到

然后规则调用的 usbipall.sh 我这么写的, 文件同样在我的 dotfiles 里面

#!/bin/sh
(
allusb=$(usbip list -p -l)
for usb in $allusb
do
    busid=$(echo "$usb" | sed "s|#.*||g;s|busid=||g")
    if [ "$busid" = "1-1.1" ]
    then
        # ignoring usb ethernet
        continue
    fi
    echo "$(date -Iseconds): Exporting $busid"
    usbip bind --busid="$busid"
done
) >>/var/log/usbipall.log 2>&1

这个脚本做了这样几件事。

  1. 调用 usbip list --local 列出本地所有 usb 设备。
  2. 针对每个设备
    1. 取出它的 busid
    2. 判断是不是树莓派的 USB 以太网卡,不是的话继续
    3. 通过 usbip bind --busid= 命令把这个 usb 设备导出到网上
  3. 最后把所有输出记录到 /var/log/usbipall.log 日志里面

树莓派这边设置就完成了。从此之后插入的 usb 设备就会统统导出出去。

这里需要注意一下,启用了 udev 规则之后,就没法插键盘鼠标到树莓派上控制它了……我都是从另一端 ssh 上树莓派操作的。如果有什么地方设置错误,可能需要把树莓派的 SD 卡拔下来插到电脑上,删除掉 rules 文件……

仔细检查设置正确了之后,重新载入 udev 规则,或者重启树莓派:

# systemctl restart systemd-udevd

这样树莓派这边就设置好了。

设置 Arch Linux 的 PC 端

同样假设 PC 这边也已经联网。接下来同样安装 usbip 工具:

$ sudo pacman -Syu usbip

然后我写了个小脚本去链接树莓派端, 这个文件 usbiprpi3.sh 也在我的 dotfiles

#!/bin/sh
rpi3="192.168.0.117"

modprobe vhci-hcd

allusb=$(usbip list -p -r $rpi3 | cut -d":" -f1 -s | sed 's|^[ \t]*||;/^$/d')
for busid in $allusb
do
    if [ "$busid" = "1-1.1" ]
    then
        # ignoring usb ethernet
        continue
    fi
    echo "Attaching $busid"
    usbip attach --remote=$rpi3 --busid="$busid"
done

其中脚本第一行填入上面记录下来的树莓派的 IP 地址,接下来脚本做了这么几件事:

  1. 用 modprobe 确认加载 vhci-hcd 通用虚拟键鼠驱动
  2. usbip list --remote= 列出远程设备上已经导出了的 USB 设备,取出他们的 busid
  3. 对每个设备用 usbip attach 接上该设备

然后就已经准备妥当,接下来是见证奇迹的时刻:

$ sleep 10; sudo ./usbiprpi3.sh
Attaching 1-1.4.3
Attaching 1-1.4.1

因为只有一套键盘鼠标,所以先 sleep 个 10 秒,在此期间快速把键鼠拔下来插到树莓派的 USB 口上去。 如果对自己手速没自信也可以把时间设长一点。然后用 root 权限执行 usbiprpi3.sh 。

一切正常的话,先能观测插上树莓派的键盘鼠标被树莓派初始化了一下,比如键盘灯会亮, 然后这些设备会被导出出去,从而键盘灯灭掉,然后 10 秒等待结束后他们被远程接到了 PC 端, 又会被初始化一下,同时 PC 端这边会有上述 Attaching 的输出。然后键盘鼠标就能像平常一样用啦。

使用体验

因为就是通过 IP 转发 USB 嘛,所以就和普通地接 USB 的体验差不多,当然前提是网络环境足够稳定。 在我家间隔 5 米到无线路由器的环境下,基本感觉不到网络延迟的影响。 通过这种方式聊天上网应该和直接接 USB 设备完全一样。本文就是在通过树莓派转发的前提下用键盘打字写的。

不过如果网络负载本身就很大的话,可能会一些延迟,比如我开着 OBS 直播打东方的时候,原本就手残 的我感觉更加手残了……

试过拿着树莓派在房间到处走,走到无线信号覆盖不到的地方, usbip 会断掉,PC 上的现象就像是 USB 设备被拔下来了……所以如果无线网络不稳的话,可能需要对上面脚本做个循环?不过那样可能会用起来很别扭吧。

以及,上述操作 usbip 是走 TCP 3240 端口,数据包大概完全没有加密,所以考虑安全性的话, 最好还是在内网环境使用。不过转念一想,万一有别人接上了我导出出去的 USB ,也就是截获我的键盘, PC 这边没法 attach 设备了,应该马上会发现吧。我敲打 sudo 之类命令的时候 shell 里面没有回显, 就不会再继续敲密码了。而且似乎对攻击者也没有什么好处?要是他 usb attach 到了我的设备上, 我就能控制他的键盘了耶~

by farseerfc at February 06, 2019 05:14 PM

January 19, 2019

ヨイツの賢狼ホロ

Arch Linux 中文社区仓库从使用到打包(大雾)

/me 自从用了 Arch Linux 以后,就有了那种想要做些什么的感觉了呢(大雾)

Arch Linux 中文社区仓库是啥,我该怎么用?

Arch Linux 中文社区仓库 是由 Arch Linux 中文社区驱动的非官方用户仓库,包含一些额外的软件包以及已有软件的 git 版本等变种。部分软件包的打包脚本来源于 AUR。

Emmmm 这个介绍应该够看了吧……

要使用的话,编辑 /etc/pacman.conf ,加入中文社区的仓库地址:

[archlinuxcn]
Server = https://cdn.repo.archlinuxcn.org/$arch

这个 Server 的 CDN 除了国内几乎都能用,国内的话可以去 https://github.com/archlinuxcn/mirrorlist-repo 看一下可用的镜像。

然后安装 keyring (不然汝是装不上里面的包的):

# pacman -Syyu archlinuxcn-keyring

如果在使用的过程中遇到了啥问题的话,除了 上社区交流群吹水 以外,也可以去 中文社区仓库在 Github 上的 Issues 页面 提问。(问之前记得看看模板和现有的问题,以及老生常谈的提问的智慧)

然而上面的这些都不是重点(雾),要是汝有心意的话,为啥不来一起打包呢(期待的眼神)

申请成为中文社区仓库的维护者

直接参考 https://github.com/archlinuxcn/repo/wiki/申请当维护者 就好啦~

如果汝有幸通过了的话,可以接着往下看了(滑稽)

向中文仓库新增软件包之开始之前

开始之前的话,有一些软件包需要装:

  • base-devel (这个应该在汝用 AUR 的时候就装上了吧)
  • devtools (可以生成一个干净的环境来编译软件包)
  • devtools-cn-git (上面的小修改版,如果汝的软件包的依赖有 [archlinuxcn] 的软件包时可以使用)
  • archcn-tools-meta (一些工具的合集的元包)

如果可以的话,最好打开 testing 和 community-testing 仓库 来提前为用户踩坑……

向中文仓库新增软件包之手动打包篇

既然汝有心意加包(?)了的话,应该对 makepkg 的使用很谙熟了吧,这里就 偷下懒不赘述了 😂

中文社区仓库对手动打包的要求大概是这样的:

如果是在本地打包,请将包文件上传至编译服务器自己主目录下的临时目录 ,上传完毕后移动到 /home/repo 目录,以避免网络中断或者其它原因造成不完整的包被添加到源中。

如果汝有翻过 wiki 的话会发现咱漏掉了在服务器上打包那部分对不对?(不要在意那些细节.webp.png) 在生成完软件包后,用 gpg 生成一个分离签名:

$ gpg --detach-sign /path/to/your/package.pkg.tar.xz

签名完毕以后汝就会在打好的软件包目录中发现同名的 sig 文件,把这个文件和软件包一起上传到编译机上就 OK 啦~

  • 不要直接上传到 ~/repo 中,而是先上传到汝的主文件夹的一个位置上再通过 ssh mv(移动) 过去 😂

向中文仓库新增软件包之紫丁香篇(?)

然而实际操作中手动打包的场合越来越少了,现在大家都会用一些技巧来自动的更新啦,例如 紫丁香 lilac。

Lilac 是 Arch Linux CN 目前主要的打包机器人,主要由百合负责开发 ( lilydjwg )。

要想找 lilac 帮忙的话,有两个文件不可少:

  • lilac.yaml , 一些诸如维护者和更新时机的元数据。
  • lilac.py , lilac 看到这个文件的时候才会尝试自动更新的哦~

lilac.yaml的详细结构和语法可以在 https://archlinuxcn.github.io/lilac/ 上找到。 如果不知道怎么写的话,翻翻仓库里已经有的 lilac.yaml 咯~

在提交前记得运行一下仓库里的 ./pre-commit 来检查一下自己的的 lilac 的设置有没有问题, 可以通过设置 git hooks 做到在提交之前自动运行(其实就是一个 ln)

ln -sr pre-commit .git/hooks/pre-commit

Lilac 常见问题 收集了一些大家在用 lilac 的时候遇到的问题,如果汝有遇到类似的问题的话可以参考,自己的经验也可以写在上面。

以收养(?) AUR 的软件包为例举一个使用 lilac 的栗子

AUR 里的包大概是 [archlinuxcn] 里的主要成分 😂

这里就用咱在 AUR 和 [archlinuxcn] 里都有维护的 parsoid 举例了 ~

首先从 AUR 获得 PKGBUILD 和一系列安装时会用到的文件,然后放在仓库的 archlinuxcn/ 文件夹中。

然后在里面新建一个 lilac.yaml:

# maintainers 就是这个包的维护者啦,如果编译遇到啥问题不通过的话
# lilac 会给相应的维护者发邮件哦~
# 基本上设置成汝 Github 的用户名就可以,如果汝没有设置公开邮件地址的话,
# 记得另外设置个 email 属性。
maintainers:
- github: KenOokamiHoro
# build_prefix 就是编译时要使用哪一个 devtools 里的命令啦(大概),
# 对于大多数包来说, extra-x86_64 就 OK。
# 可以使用的各种类型去翻 schema 啦
build_prefix: extra-x86_64
# pre_build 和 post_build 是 lilac 在编译之前和之后运行的函数,
# 对于大多数 AUR 的包, aur_pre_build 和 aur_post_build 就 OK。
pre_build: aur_pre_build
post_build: aur_post_build
# update_on 是更新来源的列表,对于想在 AUR 更新时更新的这种状况而言,
# - aur: <AUR 上的软件包名称> 就好啦~
# 记得第一项应当是软件的来源,剩下的是重新打包的时机。
update_on:
- github: wikimedia/parsoid
  use_max_tag: true
- aur: parsoid

然后新建一个空白的 lilac.py 用来提示(?) lilac 自动更新。

在自己编译 OK 和 pre-commit 测试通过以后就可以提交啦,lilac 会在每日北京时间1, 9, 17点17分在社区编译机上运行, 以检查软件的新版本及自动打包。

https://build.archlinuxcn.org/ 上可以查看软件包的编译状态和上次更新时间等相关信息。 在 #archlinux-cn 频道里可以通过 !cnbuild 命令看个大概(大嘘

所以那个 lilac.py 是一直都是空白的嘛?

如果汝要在编译之前执行某些操作,汝可能需要在 lilac.py 里写些东西,例如:

  • AUR 中的 PKGBUILD 已经 out-of-date ,但是希望通过 AUR 中的 PKGBUILD 来构建软件包,需要修改 pkgver 和 hash 值时;
  • AUR 中的 PKGBUILD 修改包括依赖、构建函数等才能正确构建软件包时;
  • 通过 sourceforge 等其他网站直接检查版本更新,但希望通过修改 AUR 中的 PKGBUILD 来构建软件包时。
  • ……

这里有一些例子 , 需要的话也可以翻翻仓库里不为空的 lilac.py 学习一下。

by ホロ at January 19, 2019 04:00 PM

January 18, 2019

ヨイツの賢狼ホロ

Sailfish OS 移植中(3)- 更新和各种杂务续篇

如果 Target 更新了该怎么办? _(:з」∠)_

更新 Target SDK

在 Platform SDK Shell 里运行:

# sdk-assistant 方式
$ sdk-assistant update <target-name>
# sdk-manage 方式
$ sdk-manage tooling update <name>
$ sdk-manage target update <name>

当然要是布星的话把 /srv/mer 删了重新来一遍也行啊 ……

更新源代码和 submodules

切换到 libybris 的目录,然后运行 repo sync --fetch-submodules

  • 记得先提交汝的修改。

还有一些 submodule 需要更新:

  • rpm/dhd
  • hybris/droid-configs/droid-configs-device
  • hybris/droid-hal-version-$VENDOR-$device/droid-hal-version

在这些目录里运行:

# git remote -v 获得远程分支
$ git remote -v
github      https://github.com/mer-hybris/droid-hal-configs (fetch)
github      https://github.com/mer-hybris/droid-hal-configs (push)

# 拉取远程的源代码
$ git fetch github
$ git pull github master

然后把 hybris-boot 和 droid-hal 重新打包一下就好(忘了怎么搞? 去翻翻以前的文章或者文档吧 😂)

跳过教程

每次刷机都要重新设置和看一遍教程很烦? 在教程画面从左上角顺时针点按屏幕即可跳过(大嘘

hybris-15.1 移植的相关事项

在编译 hybris-hal 之前:

cd $ANDROID_ROOT
mkdir -p hybris/mw
cd hybris/mw
git clone --recurse-submodules https://github.com/mer-hybris/libhybris.git -b android8-initial

以及不要在 build_package.sh 时编译 libhybris ,而是先手动单独编译:

rpm/dhd/helper/build_packages.sh  -b hybris/mw/libhybris/

然后再编译剩下的包(记得跳过 libhybris)。

When running build_package.sh always skip building libhybris and instead run in PLATFORM_SDK

接着把 https://github.com/mer-hybris/droid-config-sony-nile/tree/master/sparse/usr/libexec/droid-hybris/system/etc/init 复制到汝的 config repo 然后运行:

build_packages.sh -c

通过 adb 解压 tarball 和刷写内核映像

有时可能用得上?(例如不想整个重新来过的时候)

# adb push <汝本地的文件路径> <手机的文件路径>
$ adb push your_sailfishos_tarball.tar.gz /sdcard/
$ adb push out/target/product/$DEVICE/hybris-boot.img /sdcard/
adb shell
# 如果汝是在 TWRP 里运行的话默认就是 root 了,于是不需要 su 这一步
# (但是有可能需要先把 /data 挂载上)
su
# 解开 tarball
mkdir -p /data/.stowaways/sailfishos
tar --numeric-owner -xvzf /sdcard/our_sailfishos_tarball.tar.gz \
-C /data/.stowaways/sailfishos
# 汝可能需要自己确定一下汝手机 boot 分区在哪个设备上
dd if=/sdcard/hybris-boot.img of=/dev/block/platform/msm_sdcc.1/by-name/boot

在 Android 中操作 Sailfish OS 的 chroot

前提是汝的 /data 没有加密(不然是启动不了 Sailfish OS 的)

$ adb shell
# 这里只是表示进了 Android 的 shell 😂
(android) $ su
# 挂载各种虚拟文件系统
(android) # mount -o bind /dev /data/.stowaways/sailfishos/dev
(android) # mount -o bind /proc /data/.stowaways/sailfishos/proc
(android) # mount -o bind /sys /data/.stowaways/sailfishos/sys
# chroot 进去
(android) # chroot /data/.stowaways/sailfishos/ /bin/su -
# 生成 /etc/resolv.conf ,然后就能用 Android 的网络上网了。
(sailfish) # echo "nameserver 8.8.8.8" >/etc/resolv.conf

by ホロ at January 18, 2019 04:00 PM

January 10, 2019

Felix Yan

用脏办法解决 BLE 鼠标重连后指针不动的问题

我的蓝牙鼠标(雷柏 MT750)使用 BLE(Bluetooth Low Energy) 连接笔记本时,时常遇到自动重连后电脑这边认为已连接,而鼠标那边灯自动灭掉,鼠标指针无反应的问题。在网上反复搜索 bluez 相关问题找到了许多类似问题,鼠标类型也集中在罗技、ThinkPad 等 BLE 鼠标上。

偶然间发现每次重连后,如果手动用 bluetoothctl 发一个 “pair” 指令(会超时失败),就能令鼠标正常连接。给 bluez 报了一个 bug 后,我写了下面的简单脚本先绕过问题:

#!/usr/bin/python

import dbus
import dbus.mainloop.glib
from gi.repository import GLib

adapter = "hci0"
device = "xx:xx:xx:xx:xx:xx"
device_path = '/org/bluez/' + adapter + "/dev_" + device.replace(":", "_")

dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
system_bus = dbus.SystemBus()
device_object = system_bus.get_object('org.bluez', device_path)
device_interface = dbus.Interface(device_object, 'org.bluez.Device1')

def device_info(_arg0, event, _arg2):
    if event.get("Connected"):
        print("Mouse connected, attempt to pair...")
        try:
            device_interface.Pair()
        except dbus.exceptions.DBusException:
            pass

system_bus.add_signal_receiver(
    device_info,
    dbus_interface='org.freedesktop.DBus.Properties',
    signal_name="PropertiesChanged",
    arg0='org.bluez.Device1')

GLib.MainLoop().run()

保持在后台运行即可。我自己测试了一段时间,效果非常好。

PS: bluez 上游 bugzilla 堆满了各种没有回答的错误报告,目测不是那么好修的……

by Felix Yan at January 10, 2019 06:39 PM

January 09, 2019

ヨイツの賢狼ホロ

啥???三年了????

其实还是差几天😂

活动

  • 挖了一些新坑,例如把 Sailfish OS 移植到 Nexus 6 、随便翻译了些文章和软件的文档、和开始写一个连名字和基础发行版都没确定下来的 GNU/Linux 教程 😂
  • 向所谓的垃圾佬(?)迈出了第一步?
  • 自己作出了人生(?)中第一个重要(?)决定。(???)
  • 继续肝音游。(Emmmm
  • 认识了更多的人和地方(也有的地方好久没去过了的样子)
  • せやなー

问题

  • 文章的数量在下降?

    也许是因为有不少东西都放到别的地方写了的原因……

  • Seyana... Soyana... Sorena... Arena... わかる

计划?

  • 当然是填坑啦(虽然很有可能咕咕咕)
  • 一直有想法和友链的各位来一次笔谈呢,就是不知道该怎么开始 😔
  • 知らんけど~ 知らんがな~

新年的第一篇文章竟然就是篇水文?

せーやっ せーやっ せーやっ せーやっ せーやっ せーやっ

な。

by ホロ at January 09, 2019 04:00 PM

January 02, 2019

百合仙子

解析 zxinc IPv6 数据库

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

很久以前,我就开始使用纯真 IP 数据库来进行简单的 IP 归属查询。离线数据库的好处在于快速、可依赖,我可以使用 ipmarkup 程序来快速地给文本中的所有 IP 地址注解。

然后随着 IPv6 的普及,我越来越多地需要查询 IPv6 地址了。每次 whois 或者找 ipip.net 实在是太没效率了,还暴露隐私。于是看到这个IP地址查询网站提供离线数据库下载之后,就也做了一个和 LinuxToy 介绍的这个程序类似的工具。

数据格式部分参考《纯真IP数据库格式详解》以及该网站自带的简略说明。

ipdb 程序库(带命令行)使用截图:

ipdb 命令行使用截图

用于在文本中标注 IP 的 ipmarkup 工具链接开头给了。另外有一个 cip 可以根据情况调用 ipdb 或者 QQWry。

ipdb 解析部分只依赖 Python 3.5+,下载及更新部分会依赖我同一仓库中的 myutils 库。

顺便我也优化了一下 QQWry 模块:一是没必要保留一个低效率的版本,二是既然用 mmap 了,就去掉了所有的 seek 操作,目前大概是线程安全的了。这种跳转来跳转去的二进制格式,就算不用 mmap,也可以用 pread 来操作,免得要维护个当前文件位置,还线程不安全。

by 依云 at January 02, 2019 01:05 PM

December 27, 2018

ヨイツの賢狼ホロ

知识管理 ABC

Why, what, how? 😂

所以这是个啥玩意?

「咱可是贤狼啊。起码还是知道这世界上有很多东西是咱所不了解的。」

知识管理嘛,翻译成英文大概就是 Knowledge Management。汝在 Wikipedia 上大概能找到这样的定义:

Knowledge management (KM) is the process of creating, sharing, using and managing the knowledge and information of an organisation. It refers to a multidisciplinary approach to achieving organisational objectives by making the best use of knowledge.

内容管理指的是创建、分享、使用和管理知识和组织信息的过程。它指的是运用多种方法 充分利用知识实现有组织的目标的方法。

是不是很难懂,这么巧咱一向不擅长定义……

那为啥要管理知识呢?

「有句话是这么说的:『知道方法的人会求得工作,知道这些人为何要工作的人,则会成为雇主』。」

就咱自己的经(che)验(dan)来说呢,构建一个属于自己的知识库大概有这么几个好处:

  • 节省时间

    有很多内容,【不】需要全部都记在脑子里。在信息时代,这么干是不现实滴。 不过虽然汝可能不需要完完全全的记住,但肯定要记住一些关键点。 (例如汝可能不会记住光速的具体数值,但是汝可能会记下需要的时候上网搜索一下就 OK,是呗~)

    再进一步,如果汝有一个自己的知识库(暂且这么叫?)的话,汝找到自己需要的知识的速度也会在简单 的搜索网络上更快一级咯(因为搜索范围小了?)

  • 促进系统化

    在收集知识构建自己的知识库的过程中,汝也许会发现自己的知识结构有哪些不足之处,说不定会激励汝自己 去学习。

  • ......

嗯上面(和下面)都是咱瞎说的,有什么问题和建议的话记得让咱知道 😂 具体对汝有没有好处的话还需要汝自己尝试一段时间来验证一下。

实现知识管理面面观

如果要打造一个汝自己的知识库的话,汝可能会考虑下列因素:

  • 反应迅速,可以在汝需要时就立刻准备好。
  • 组织合理,有一套相对合理的组织结构(例如目录一样的树形结构、或者分类标签一类的网状结构)。 日后查找起来也会更得心应手。
  • (对自己来说)操作简便,有人习惯功能丰富的图形界面,有人习惯简单强大的源代码风格。不过 适合自己的就是最好的啦~
  • 运行灵活,可以在汝的各种设备上(例如手机和电脑等)查阅和修改。
  • 安全可靠,例如可以通过加密保护自己的知识库不被外人查看,支持备份可以防止丢失。
  • 等等……

而实现知识库的方法咱认为有很多啦,例如:

  • 文件型,就是简单的文件存储。
  • 笔记型:和传统的笔记本(不是电脑)类似。
  • 维基(Wiki)型,典型的例子就是维基百科。

实现知识管理之文件型

所谓的文件型,大概就是把汝收集来的各种知识稍微组织一下放在某个存储空间上吧(强行定义)。

  • 因为文件都在本地,所以找起来应该会很快。只是如果要找不同类型的文件的话预览可能会麻烦一些。
  • 至于组织嘛,目录就是天然的树形结构,然而标签那种的网状结构就 emmmm......
  • 至于操作,文件管理器不会用嘛 😂 如果要在各种设备上访问的话,可以找一个都能连上的电脑(例如 一台服务器)?
  • 加密和备份就和普通的文件一样咯 ~

实现知识管理之笔记型

首先汝来回忆一下笔记本,汝可能有一个或者多个笔记本带在身上,需要的时候就打开对应的笔记本查找内容, 或者再拿出笔来写些什么。

  • 所以博客有时也算笔记的一种?
  • 或者其它的一些专门的笔记软件,例如 Gnote 和 OneNote 等。
  • 基本上笔记本软件都支持多个笔记本和分区功能,有的还提供标签功能,算是提供了两种组织结构吧……
  • 笔记本文件可以单独加密并携带,或是上传到各种云端存储中同步存取。

实现知识管理之 Wiki 型

现在用浏览器打开维基百科看看?(虽然 Wiki 并不等于维基百科,但谁让维基百科太著名了呢)

  • 像维基百科使用的 MediaWiki 的分类既支持树形结构(字分类),又可以支持网状结构 (一个条目可以属于多个分类,就像博客软件常用的标签一样)
  • 以及这种 Web 应用只要有一个浏览器就能打开?
  • 加密和备份就是带上 wiki 的文件夹、数据库和 Web 服务器配置咯 ~

实际上呢?

实际上的话,汝完全可以把一种或者几种方法组合起来用啊。例如心智图作为梗概,笔记或 Wiki 放置文字内容。 然后在汝自己的知识库中放置各种文件。然后可以把它们一起加密起来备份到其他地方。

如果汝有能力而且愿意的话,完全可以自己写一个自己用起来顺手的知识管理系统咯(特别是汝自称是程序猿的话)。 或者自行创造一个新的知识管理流派(大雾)。

然而首先要汝自己肯动手去做才行……以及就算汝有了这些知识,要是不会使用的话…… 那不是百忙活了? 😂

by ホロ at December 27, 2018 04:00 PM

December 25, 2018

百合仙子

Ant Design 彩蛋事件之我见

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

事情是这样的:一个叫「Ant Design」的大概有挺多人用的前端框架加入了一个彩蛋,在12月25日这天会更改按钮样式并修改提示文字为无意义的消息。

由于使用广泛,此事搞得比较严重,听说有程序员因此被开除,还有不少老板在跟甲方解释。事发之后,作者发布了道歉,并称「这完全是我个人的一意孤行且愚蠢的决定」。

确实很愚蠢,因为当事人似乎还没有意识到自己为什么「愚蠢」。在程序库中加入未预期的行为,是十分不负责任的表现。

库应当提供机制而非策略,并且具有良好定义的行为。软件中彩蛋这种东西由来已久,为什么这次影响这么大呢?其根本原因不在于它是开源软件,也不在于使用广泛,而是在于——它是库。库能不能提供彩蛋呢?是可以的,只要它是以 opt-in 的形式提供的,并且有文档明确其行为,使用方需要显式启用就没有任何问题。库的作者不需要知道圣诞节还可能在1月,也不需要知道代码是运行在哪个国家,他的职责应当是提供清晰明确的行为,而不是某天给你耍个花招。只有最终面向用户的应用才知道什么样的彩蛋对于它的用户是合适的,所以决定权在于应用。

至于那些在 issue 下边滥骂的人,真是给中国人丢脸唉。

PS: 关于「洋节」,shell909090 有篇文章《关于抵制洋节》。关于阿里巴巴,shell909090 还有篇《最近的阿里月饼事件》。

PPS: 每当国外发生这种令程序员们关注的事件的时候,Internet ArchiveArchive.is 上都有会很多的存档来保留历史,而国内发生这种事件,却并没有多少人去存档。大概有保存意思的人们也只是自私地本地截图保存了吧。

by 依云 at December 25, 2018 06:11 AM

December 23, 2018

farseerfc

【听译】君さえいなけりゃよかった

君さえいなけりゃよかった 如果你从未出现过该多好
降り出した雨の中で 君に出会った时から 下起雨的那一刻 从遇到你那时起
君がいないということが 当たり前じゃなくなった 身边没有你的情况 就已经不再是平常
ああ こんなはずじゃない 啊 不应该是这样的
ずっと自分胜手にさ 过ごせたはずなのに 明明一直是散漫地过着自己的日子
まるで仆じゃないような仆が さらけ出されてくよ 就像是带出了不是我的另一面的我

君さえいなけりゃよかった こんな気持ちは知らないから 如果你从未出现过该多好 就不会知道这种心情
やらなくちゃいけないことが 手つかずのまま积もってく 一堆不得不做的事情 堆在手头越积越多
仆じゃなくてもいいのなら こっちを见て笑わないでよ 如果不是我也可以的话 就别看着我这边笑啊
大袈裟じゃなくてそれだけで 忘れられなくなるの 甚至那些不重要的事情 都变得难以忘记了

君の适当な话も 全部心に刺さります 你无意间随口说的话 全都刺在心头
気にしなけりゃいいのにな 残らずかき集めちゃうの 虽说只要不在意就可以了 却一句不剩全收集了起来
ああ こんなはずじゃない こんなはずじゃない 啊 不应该是这样的 不应该是这样的

君に出会わなきゃよかった こんなに寂しくなるのなら 如果没遇到过你该多好 就不会变得如此寂寞
君じゃなくてもいいことが もう见つからないの 已经找不到 和你无关也可以的情况了
忘れられないから 君じゃなかったら 无法忘记了 要不是你的话

いっそ见损なってしまうような そんなひとだったらなあ 干脆变成根本看不起的人 如果是那种人的话
でもそれでも どうせ无理そう 嫌いになれないや 但是即使如此 大概反正也不可能 无法变得讨厌

仆がいなくてもいいなら いっそ不幸になってしまえ 如果不是我也可以的话 干脆变得不幸吧
最后にまた仆の元に 泣きついてくればいい 最后还是会回到我身边 哭着凑过来的话就可以
君さえいなけりゃよかった こんな気持ちは知らないから 如果没有你该多好 就不会知道这种心情
やらなくちゃいけないことが 手つかずのまま积もってく 一堆不得不做的事情 堆在手头越积越多
仆じゃなくてもいいのなら こっちを见て笑わないでよ 如果不是我也可以的话 就别看着我这边笑啊
大袈裟じゃなくてそれだけで 甚至那些不重要的事情
君のこと 间违いなく 对你 毫无疑问
苦しいほど 好きになっちゃうよ 刻骨铭心地 变得喜欢上了啊

忘れられないから 君じゃなかったら 因为无法忘记 如果不是你的话
君に出会わなきゃ 仆じゃなかったら 要是没遇到过你 如果不是我的话
君さえいなけりゃよかった 如果你从未出现过该多好

by farseerfc at December 23, 2018 02:04 PM

December 16, 2018

ヨイツの賢狼ホロ

备份 GNU/Linux 操作系统的经(che)验(dan)合集

备份 GNU/Linux 操作系统的经(che)验(dan)合集

为啥要备份?

  • 防震减灾(雾),其实就是防止各种意外情况(例如硬盘坏掉,电脑丢失等)发生时手足无措……

    那备份的硬盘也坏了怎么办(先有鸡还是先有蛋?)

  • 方便迁移(例如买了新电脑的时候)

  • ……

Point 0: 要备份些啥?

一个典型的 GNU/Linux 的根文件系统大概像这个样子:

lrwxrwxrwx   1 root root     7 Aug 21 22:21 bin -> usr/bin
drwxr-xr-x   4 root root 16384 Jan  1  1970 boot
drwxr-xr-x  22 root root  3460 Dec 19 11:27 dev
drwxr-xr-x   1 root root  3464 Dec 19 14:13 etc
drwxr-xr-x   1 root root     8 Dec 19 10:55 home
lrwxrwxrwx   1 root root     7 Aug 21 22:21 lib -> usr/lib
lrwxrwxrwx   1 root root     7 Aug 21 22:21 lib64 -> usr/lib
drwxr-xr-x   1 root root   114 Dec 19 14:19 mnt
drwxr-xr-x   1 root root   138 Dec 17 09:19 opt
dr-xr-xr-x 298 root root     0 Dec 19 11:26 proc
drwxr-x---   1 root root   212 Dec 19 14:47 root
drwxr-xr-x  24 root root   640 Dec 19 14:13 run
lrwxrwxrwx   1 root root     7 Aug 21 22:21 sbin -> usr/bin
drwxr-xr-x   1 root root    14 Nov 20 23:34 srv
dr-xr-xr-x  13 root root     0 Dec 19 11:26 sys
drwxrwxrwt  15 root root  1460 Dec 19 14:46 tmp
drwxr-xr-x   1 root root    80 Dec 19 14:13 usr
drwxr-xr-x   1 root root   116 Dec 19 08:46 var

熟稔 FHS 的话应该知道有些目录其实是不在 硬盘上的(例如 /dev , /sys 和 /proc 等等),还有些目录下的文件没什么用(例如 /tmp , /var/tmp 等等)。

那么该备份哪些呢?

Point 1: rsync

rsync 是 Unix 下的一款应用软件,它能同步更新两处计算机的文件与目录, 并适当利用差分编码以减少数据传输量。

rsync 中的一项同类软件不常见的重要特性是每个目标的镜像只需发送一次。 rsync 可以拷贝 / 显示目录内容,以及拷贝文件,并可选压缩以及递归拷贝。

既然备份只是把文件从一个地方复制到另一个地方而已,本来只用 cp 说不定也行。 但是为了省事(例如只复制变化的部分),处理各种状况(例如文件属性和权限), 跨设备和网络复制(例如通过 SSH ),就有了 rsync 咯~

rsync 核心的用法和 cp 几乎一样:

rsync <source> <target>

例如要把 /home 下的内容复制到 /data:

rsync /home /data

当然为了应对各种情况, rsync 也有不同的参数:

  • --archive / -a :存档模式,等于 -rlptgoD (这些短参数是啥啦……), 会保留文件的大多数属性(例如不会留扩展属性、ACL 和硬链接)和符号链接。

    想要保留扩展属性 / ACL 和硬链接的话,可以分别使用 --xattrs (-X) , --acls (-A) 或 --hard-links (-H) 参数。

  • --one-file-system:只备份这一个文件系统的内容,于是就不会备份 /sys 啊 /proc 啊 /dev 啊 /tmp 这类目录了,当然如果汝和咱一样 /home 是单独挂载的话也会……

  • --numeric-ids:把用户名/组名处理成数字而不是实际的名称,跨不同的系统备份时 可能会有用。

  • --verbose:顾 GNU 参数列表思义的 “罗嗦” 模式,会详细输出正在传送的文件的信息。

  • --progress:显示一个传送文件的进度显示。

  • --exclude 和 --exclude-from:指定传送过程中排除哪些文件。 --exclude 用来明确地指出 排除哪些文件, --exclude-from 是一个包含文件名列表的文件。

    当然和 --exclude 相对的自然有 --include 和 --include-from,用法类似。

  • --dry-run / -n:模拟运行,防止手抖 😂

当然 rsync 的参数远不止这些啦,剩下的自己查手册页( man rsync )咯。于是咱自己备份的话通常是这样:

rsync --archive --acls --xattrs --verbose --progres /source /target

啥,汝问为啥没有 --one-file-system ?那是因为咱一般都会把根分区单独再挂载到别的地方再 rsync。 没有 --exclude 纯粹就是懒了 😂

Point 2: btrfs 的 subvolume

btrfs 的子卷(subvolume)看起来和普通的目录无异,但是可以通过不同的挂载参数让它作为单独的分区挂载, 例如挂载 /dev/sda2 上的子卷 ./root 到 /mnt :

当然汝也能在 -o 后面加上别的参数啦,例如 --compress=lzo 启用压缩什么的,记得不同的参数用 逗号分开。

# mount -o subvol=root /dev/sda2 /mnt

要创建一个子卷的话,可以用 btrfs subvolume create 命令:

# btrfs subvolume create <name_of_your_subvolume>

要列出子卷的列表的话,可以用 btrfs subvolume list 命令:

# btrfs subvolume list <path/to/your/volume>
root@yoitsu_optiplex /run/media/horo/External
# btrfs subvolume list .                                             :(
ID 257 gen 2007 top level 5 path data
ID 258 gen 2088 top level 5 path local
ID 294 gen 2016 top level 5 path backup
ID 295 gen 2012 top level 294 path backup/home_20181031
ID 328 gen 2086 top level 294 path backup/parabola_root_20181031
ID 353 gen 1998 top level 294 path backup/home_20181215
ID 360 gen 2005 top level 294 path backup/parabola_root_20181215
ID 373 gen 2086 top level 294 path backup/arch_optiplex
ID 432 gen 2089 top level 5 path temp

建立的子卷可以是某个子卷的快照:

# btrfs subvolume snapshot [-r] <source> <target>

-r 参数用来创建只读快照

可以通过 btrfs send 和 btrfs recieve 在两个 btrfs 卷之间传送子卷(或子卷的快照),不过要是 只读的才行:

# btrfs send <path/to/your/subvolume> | btrfs recieve <path/to/your/save/place>

如果创建快照时忘记设置只读,可以通过 btrfs property 命令设置上(当然也可以取消只读):

# btrfs property set -ts <path/to/your/subvolume> ro [true|false]

汝也可以传递增量快照,就像这样:

# btrfs send <path/to/your/subvolume> -p <path/to/your/parent_subvolume> | btrfs recieve <path/to/your/save/place>

不过汝要先把父快照传送到目标才行。

例如建立今天的快照然后以 2018 年 10 月 31 号的快照为基础发送出去:

date 命令返回今天的日期和时间,也可以指定一个格式字符串来按某个特定的格式输出。

以 $ 包围的命令会以它的结果填充,例如 echo "root_$(date +"%Y%m%d")" 的 结果是 20181219 (咱写完这篇文章的时间,汝自己运行的话结果肯定会和咱有变化)。

# btrfs subvolume snapshot -r root root_$(date +"%Y%m%d")

# btrfs send root_$(date +"%Y%m%d") -p root_20181031 | btrfs revieve /backup

Point 2: 使用 dm-crypt 加密分区

为啥要加密应该不用再解释了吧,毕竟汝主目录里是不是有不少公开或者隐私的数据是不是? 例如 cookies 和帐号配置啦,邮件啦,和聊天记录等等。

cryptsetup 是操作 dm-crypt 用的前端,可以这样创建一个加密的设备:

# cryptsetup luksFormat <设备文件的名称>

如果需要的话,可以在 luksFormat 之前加上一些选项呐:

参数的名称 这啥? 推荐是多少? 一些废话
--cipher 加密方式 aes-xts-plain64 AES 加密算法搭配 XTS 模式
--key-size 密钥长度 512 XTS 模式需要两对密钥, 每个的长度是256
--hash 散列算法 sha512  
--iter-time 迭代时间 >10000 单位是毫秒。该值越大,暴力破解越难; 但是相应的汝打开加密分区时就要等一下啦~

例如这样?

# cryptsetup --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 10000 luksFormat /dev/nvme0n1p1

WARNING!
========
这将覆盖 /dev/nvme0n1p1 上的数据,该动作不可取消。

Are you sure? (Type uppercase yes):
# 上面要打大写的 YES
# 然后输入两遍加密分区的密码。
输入密码:
确认密码:

然后等一下就好咯~

然后用 cryptsetup open 打开分区:

# cryptsetup open <已经加密的设备文件名称> <映射名称>

解密的分区会映射到 /dev/mapper/<汝设置的映射名称> 呗~

例如咱解密 /dev/nvme0n1p1 ,然后映射到 /dev/mapper/sysroot :

# cryptsetup open /dev/nvme0n1p1 sysroot

接下来就像操作普通分区一样操作 /dev/mapper/sysroot 就好啦,例如创建文件系统:

# mkfs.btrfs /dev/mapper/sysroot

by ホロ at December 16, 2018 04:00 PM

December 14, 2018

Phoenix Nemo

制作 Arch Linux 内存系统启动盘

之前尝试过 Arch Linux in RAM 完全运行在内存中的轻量业务系统,最近在维护一些物理服务器看到没有安装系统的服务器不断重启,想到了可以制作类似的内存系统启动盘,以高效完成系统测试、安装、远程维护等任务。

这时候就要祭出 mkarchiso 大法了。这是自动化制作最新版 Arch Live 镜像的工具集,当然也可用于制作定制化的 Arch 镜像。

准备

首先安装 archiso

1
~> sudo pacman -Syy archiso

它提供了两种配置方案,一种是只包含基本系统的 baseline,一种是可以制作定制 ISO 的 releng。要制作维护用 ISO,当然是复制 releng 配置啦。

1
2
~> cp -r /usr/share/archiso/configs/releng/ archlive
~> cd archlive

定制

整个过程不要太简单。先来了解下各个文件的用途:

  • build.sh - 用于制作镜像的自动化脚本,可以在这里修改一些名称变量或制作过程的逻辑。
  • packages.x86_64 - 一份要安装的包列表,一行一个。
  • pacman.conf - pacman 的配置文件,不用多说了吧。
  • airootfs - Live 系统的 rootfs,除了安装的包之外,其他的定制(以及启动执行脚本等)都在这里。遵循 rootfs 的目录规则。
  • efiboot / syslinux / isolinux 用于设置 BIOS / EFI 启动的配置。

[archlinuxcn] 仓库加入 pacman.conf

1
2
[archlinuxcn]
Server = https://cdn.repo.archlinuxcn.org/$arch

然后修改 packages.x86_64,加入 archlinuxcn-keyring 和其他需要预安装的包:

1
2
3
4
5
archlinuxcn-keyring
htop
iftop
iotop
ipmitool

按需修改即可啦。

要启动为内存系统,需要加启动参数 copytoram

修改文件 syslinux/archiso_pxe.cfgsyslinux/archiso_sys.cfg 文件,在启动参数后加 copytoram,像这样:

1
2
3
4
5
6
7
8
9
10
11
INCLUDE boot/syslinux/archiso_head.cfg

LABEL arch64
TEXT HELP
Boot the Arch Linux (x86_64) live medium.
It allows you to install Arch Linux or perform system maintenance.
ENDTEXT
MENU LABEL Boot Arch Linux (x86_64)
LINUX boot/x86_64/vmlinuz
INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img
APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram

启动时即可将整个 SquashFS 文件复制到内存。如果内存比较小,也可以指定 copytoram_size 来限制 tmpfs 占用内存的最大数量。

同样,也需要修改 efiboot/loader/entries/archiso-x86_64-usb.conf 的启动参数。在 options 行添加

1
options archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram

制作

创建工作目录和输出目录

1
mkdir -p work out

最后一步,只需要以 root 权限执行 ./build.sh 就可以啦。

要看具体执行过程的话,加 -v-h 看所有参数。

完成后,即可在 out 目录得到准备好的 ISO 文件。将其 dd 到 USB 闪存盘,大功告成(‘・ω・’)

Ref:

  1. https://wiki.archlinux.org/index.php/Archiso
  2. https://git.archlinux.org/archiso.git/tree/docs/README.bootparams#n53

之前尝试过 Arch Linux in RAM 完全运行在内存中的轻量业务系统,最近在维护一些物理服务器看到没有安装系统的服务器不断重启,想到了可以制作类似的内存系统启动盘,以高效完成系统测试、安装、远程维护等任务。

December 14, 2018 04:40 AM

December 07, 2018

farseerfc

【译】使用 GNU stow 管理你的点文件

译注

这篇是翻译自 Brandon Invergo 的博客的英文文章 Using GNU Stow to manage your dotfiles 。 Brandon Invergo 的博客采用 CC-BY-SA 3.0 授权,因此本文也同样采用 CC-BY-SA 3.0 ,不同于其它我写的文章是 CC-BY-NC-SA 4.0 授权。

我自己已经使用此文中介绍的方案管理 我自己的 dotfiles 快 3 年了。最早想采用这样的管理方案是为了方便在多台 Arch Linux 系统之间同步配置, 后来逐渐主力系统也更新换代了一次,又同步到了自己的 vps 上去,目前管理多个 Arch Linux 上都多少都有这套配置。甚至装好 Arch Linux 添加好用户最初做的事情就是安装 stow git 然后 clone 了我自己的 dotfiles repo 下来,然后按需取想要的配置,快捷方便有效。

废话不多说,下面是原文和翻译。与之前的翻译一样,正文部分给出原文引用以便对照参考。

使用 GNU stow 管理你的点文件

我昨天偶然间发现一些我觉得值得分享的经验,就是那种「为毛我没有早点知道这个?」那一类的。 我将在这篇文章中介绍如何使用 GNU Stow 管理你的 GNU/Linux 系统中位于用户家目录里的各种配置文件 (通常又叫「点文件(dotfiles)」比如 .bashrc)。 I accidentally stumbled upon something yesterday that I felt like sharing, which fell squarely into the "why the hell didn't I know about this before?" category. In this post, I'll describe how to manage the various configuration files in your GNU/Linux home directory (aka "dotfiles" like .bashrc) using GNU Stow.
这件事的困难之处在于,如果能用版本管理系统(VCS, Version Control System)比如 Git, Mercurial(hg), Bazaar(bzr) 管理点文件的话会非常方便,但是这些点文件大部分都位于家目录的顶级目录下, 在这个位置不太适合初始化一个版本管理仓库。这些年下来我试过很多程序,设计目的在于解决这个问题, 帮你把这些配置文件安置在某个下级目录中,然后安装或者链接这些文件到它们应该在的位置。 尝试下来这些程序没有一个真正能打动我。它们要么有很多依赖(比如 Ruby 和一大坨库), 要么需要我记住如何用它,考虑到同步配置这种不算经常使用的场合,要记住用法真的挺难。 The difficulty is that it would be helpful to manage one's configuration files with a version control system like Git, Mercurial or Bazaar, but many/most dotfiles reside at the top-level of your home directory, where it wouldn't be a good idea to initialize a VCS repository. Over time I've come across various programs which aim to manage this for you by keeping all the files in a subdirectory and then installing or linking them into their appropriate places. None of those programs ever really appealed to me. They would require a ton of dependencies (like Ruby and a ton of libraries for it) or they would require me to remember how to use them, which is difficult when really for such a task you rarely use the program.
最近我在用 GNU Stow 来管理我从源代码在本地编译安装到 /​usr/​local/​ 中的一些程序。 基本上说,在这种常见用法下,是你把这些本地编译的包配置安装到 /​usr/​local/​stow/​${PKGNAME}-{PKGVERSION} 这样的位置,然后在 /​usr/​local/​stow/​ 目录中执行 # stow ${PKGNAME}-${PKGVERSION} ,然后它就会为程序所有的文件创建符号链接放在 /​usr/​local 中合适的地方。然后当你想用 Stow 卸载这个程序的时候,就不必再考虑会留下什么垃圾文件, 或者找不到安装时用的 Makefile 了。这种安装方式下也可以非常容易地切换一个程序的不同版本 (比如我想尝试不同配置选项下的 dwm 或者 st 的时候)。 Lately I've been using GNU Stow to manage programs I install from source to /usr/local/. Basically, in this typical usage, you install locally built packages to /usr/local/stow/${PKGNAME}-{PKGVERSION} and then from /usr/local/stow/ you run # stow ${PKGNAME}-${PKGVERSION} and the program generates symbolic links to all the programs' files into the appropriate places under /usr/local/. Then, when you uninstall a program via Stow, you don't have to worry about any stray files that you or a provide Makefile may have missed. It also makes handling alternate versions of a program quite easy (i.e. when I'm experimenting with different configurations of dwm or st).
前段时间在我扫邮件列表的时候,看到某个帖子中某人在说使用 Stow 管理安装他的点文件。 当时我没特别在意这个帖子,但是大概我大脑潜意识把它归档保存为今后阅读了。 昨天我想起来试试这种用法,试过后我不得不说,这比那些专门设计用来做这任务的点文件管理器要方便太多了, 虽然表面上看起来这种用法没那么显而易见。 Some time ago I happened across a mailing list posting where someone described using Stow to manage the installation of their dotfiles. I didn't pay much attention to it but my brain must have filed it away for later. Yesterday I decided to give it a try and I have to say that it is so much more convenient than those other dedicated dotfile-management programs, even if it wasn't an immediately obvious option.
方法很简单。我建了个 ${HOME}/​dotfiles 文件夹,然后在里面为我想管理的每个程序配置都 创建一个子文件夹。然后我把这些程序的配置从原本的家目录移动到这每一个对应的子文件夹中, 并保持它们在家目录中的文件夹结构。比如,如果某个文件原本应该位于家目录的顶层文件夹里, 那它现在应该放在这个程序名子目录的顶层文件夹。如果某个配置文件通常应该位于默认的 ${XDG_CONFIG_HOME}/​${PKGNAME} 位置 ( ${HOME}/​.config/​${PKGNAME} ), 那么现在它应该放在 ${HOME}/​dotfiles/​${PKGNAME}/​.config/​${PKGNAME} ,如此类推。然后在那个 dotfiles 文件夹里面,直接运行 $ stow $PKGNAME 命令, Stow 就会为你自动创建这些配置文件的符号链接到合适的位置。接下来就很容易为这个 dotfiles 目录初始化版本管理仓库,从而记录你对这些配置文件做的修改(并且这也可以极度简化在不同电脑之间 共享配置,这也是我想要这么做的主要原因)。 The procedure is simple. I created the ${HOME}/dotfiles directory and then inside it I made subdirectories for all the programs whose cofigurations I wanted to manage. Inside each of those directories, I moved in all the appropriate files, maintaining the directory structure of my home directory. So, if a file normally resides at the top level of your home directory, it would go into the top level of the program's subdirectory. If a file normally goes in the default ${XDG_CONFIG_HOME}/${PKGNAME} location (${HOME}/.config/${PKGNAME}), then it would instead go in ${HOME}/dotfiles/${PKGNAME}/.config/${PKGNAME} and so on. Finally, from the dotfiles directory, you just run $ stow $PKGNAME and Stow will symlink all the package's configuration files to the appropriate locations. It's then easy to make the dotfiles a VCS repository so you can keep track of changes you make (plus it makes it so much easier to share configurations between different computers, which was my main reason to do it).
举个例子,比如说你想管理 Bash, VIM, Uzbl 这三个程序的配置文件。Bash 会在家目录的顶层文件夹 放几个文件; VIM 通常会有在顶层文件夹的 .vimrc 文件和 .vim 目录;然后 Uzbl 的配置位于 ${XDG_CONFIG_HOME}/​uzbl 以及 ${XDG_DATA_HOME}/​uzbl 。于是在迁移配置前,你的家目录的文件夹结构应该看起来像这样: For example, let's say you want to manage the configuration for Bash, VIM and Uzbl. Bash has a couple files in the top-level directory; VIM typically has your .vimrc file on the top-level and a .vim directory; and Uzbl has files in ${XDG_CONFIG_HOME}/uzbl and ${XDG_DATA_HOME}/uzbl. So, your home directory looks like this:
home/
    brandon/
        .config/
            uzbl/
                [...some files]
        .local/
            share/
                uzbl/
                    [...some files]
        .vim/
            [...some files]
        .bashrc
        .bash_profile
        .bash_logout
        .vimrc
然后迁移配置的方式是,应该建一个 dotfiles 子目录,然后像这样移动所有配置文件: You would then create a dotfiles subdirectory and move all the files there:
home/
    /brandon/
        .config/
        .local/
            .share/
        dotfiles/
            bash/
                .bashrc
                .bash_profile
                .bash_logout
            uzbl/
                .config/
                    uzbl/
                        [...some files]
                .local/
                    share/
                        uzbl/
                            [...some files]
            vim/
                .vim/
                    [...some files]
                .vimrc
然后执行以下命令: Then, perform the following commands:
$ cd ~/dotfiles
$ stow bash
$ stow uzbl
$ stow vim
然后,瞬间,所有你的配置文件(的符号链接)就安安稳稳地放入了它们该在的地方,无论原本这些目录结构 有多么错综复杂,这样安排之后的 dotfiles 文件夹内的目录结构立刻整理得有条有理, 并且可以很容易地转换成版本控制仓库。非常有用的一点是,如果你有多台电脑,可能这些电脑并没有 安装完全一样的软件集,那么你可以手选一些你需要的软件配置来安装。在你的 dotfiles 文件夹中总是 可以找到所有的配置文件,但是如果你不需要某个程序的某份配置,那你就不对它执行 stow 命令,它就不会扰乱你的家目录。 And, voila, all your config files (well, symbolic links to them) are all in the correct place, however disorganized that might be, while the actual files are all neatly organized in your dotfiles directory, which is easily turned into a VCS repo. One handy thing is that if you use multiple computers, which may not have the same software installed on them, you can pick and choose which configurations to install when you need them. All of your dotfiles are always available in your dotfiles directory, but if you don't need the configuration for one program, you simply don't Stow it and thus it does not clutter your home directory.
嗯,以上就是整个用法介绍。希望能有别人觉得这个用法有用!我知道对我来说这个非常有帮助。 Well, that's all there is to it. Hopefully someone else out there finds this useful! I know I've found it to be a huge help.

by farseerfc at December 07, 2018 06:35 PM

December 05, 2018

ヨイツの賢狼ホロ

当汝看到加密(encryption)时应该想到什么

来自 https://ssd.eff.org/en/module/what-should-i-know-about-encryption

这个页面引用了 https://ssd.eff.org 的图片呐,汝可能需要根据情况调整汝浏览器 扩展的设置来查看它们。

汝大概已经从别的地方听说过“加密”这个词了呗,有时还和其他的单词组合在一起。 一般的,加密是指把一段数据转化为除了持有可以用来解密的密钥的人以外无法读取的形式 的一种数学过程。(这啥?)

放眼历史(嗯?)人们一直在用不同的方法加密消息,希望它们不会被除了接收者的其他人读到。 今天,借助计算机的力量,咱们不止可以用加密的方式传送消息。还可以达成其他的目的,例如 验证消息的发送者。

加密是在坏人,政府和服务提供商之间保护自己的信息的最加手段。 而且只要运用得当,几乎可以做到无懈可击(然而往往做不到完美的运用得当啦~)。

这篇指南里咱们会讨论到加密的两种主要应用方式:加密静态数据和流。

太长不看版小结

(来自 https://twitter.com/sissisiisi/status/1070522944298893312
  1. 全盘加密要小心冷启动攻击(Cold Boot Attack) ,全盘加密但是 RAM 没有加密, 因此解密的 master key 在 RAM 里面是明文出现.解决的办法嘛,用 Tails. 还有别在开机状态下被敌人物理的接触到电脑.

  2. 全盘加密的主要作用是为了防止 有能力物理接触 你的电脑的人, 比如你的家人,同事,商业间谍,FBI等等

  3. 传输加密 这块,这里要分清楚两个概念: 传输层加密,**端对端加密** 区别在于中间的服务器能不能看到加密内容

  4. 传输加密 不能加密元数据(metadata)比如发送端对端的信息的时候,对方的ID, 发送的时间,密文的长度等等

    所以高度敏感的人,应该想办法匿名.还有就是网络代理,比如你的敌人主要是本地 ISP 以及政府, 可以想办法比如利用 tor 的加密,然后发送端对端的加密邮件而不是直接发送. 这样本地的 ISP 只会看到链接 tor 的事实,而不会知道你发送了邮件.

加密静态数据

静态数据 就是存储在各种地方的数据啦。例如汝的电脑、手机、移动硬盘上的那些。 (因为上面的数据不会移动到别的介质上?)

全盘加密 (“full-disk”encryption,有时也被称作“设备加密”)是一种保护 这种静态数据的常见方法。当汝设置完成以后,就要使用密码(或其它的验证手段)解锁 来读取上面的数据。

智能手机和笔记本电脑上锁定屏幕的示例

在手机之类的移动设备上,它可能表现的就和普通的锁定屏幕一样。但锁定汝的设备不一定 表示汝启用了全盘加密……

记得检查汝操作系统中关于加密的设置来确认它有没有启用(因为不是所有的操作系统 在所有的情况下都会启用)。如果汝的设备没有加密的话,只要能解开汝设备上的锁定, 就能拿到上面的数据。

以及有些系统会把明文的数据保存在内存上,虽然内存是只要关机一会儿就会让上面的数据消失 的易失介质,但是高明的攻击者可能会尝试通过 冷启动攻击 获取内存上的数据。

全盘加密可以保护汝的数据不被能物理接触到汝设备的人获取,例如汝的室友啦、同事和雇员啦、 家人啦、各种官员(不管他们是来自学校政府还是法院)啦等等。对了还有当汝不小心弄丢了它的 时候。

除了全盘加密以外,还有诸如文件加密(加密指定的文件)和分区(磁盘?)加密(加密设备上指定的 一块区域)这样的加密方法。汝当然可以把它们组合起来使用。

除了 Surveillance Self-Defense 以外,汝还可以在其它地方找到各种有关加密设备的指南,不过要记得 检查它们是不是最新的哦~

加密传输中的数据

未加密的数据的传输流程

如果数据没有加密的话,把数据送到目标的全过程中间的环节都能看到,例如基站和服务商。

传输中的数据 是指通过网络从一处移动到另一处的数据。例如即时通讯应用中,汝编写的消息 从汝的设备中到达服务商的服务器再到接收者的设备上。又或者例如浏览网页,网站的服务器把网站 发送到汝的设备上。

有些流行的应用会提供一些诸如阅后即焚这样的看起来能保护消息的功能。然而只是给汝一种安全的 感觉 ,并不会意味着 安全的。毕竟传输过程中的设备还是能看到的不是?

有两种方式可以用来加密传输中的数据,传输层加密和端到端加密。验证汝的消息是用哪种方法加密 的和验证汝的消息是否被加密一样重要 😂 。服务提供商支持的加密类型可能 是决定哪些服务适合汝自己的重要因素,是呗~

传输层加密

传输层加密的数据的传输流程

一个传输层加密的例子,左侧的手机加密一条消息并将它发送到服务商的服务器。服务商(能够)解密消息, 再加密、发送到右侧的目标。最后目标手机解密消息。

传输层加密,有时也叫做传输层安全(TLS),保护你的数据不被汝和汝连接到的服务器中间的谁和 汝连接到的服务器到目标之间的谁读取。不过在中间,汝所使用的应用的服务商还是能看到(和保存)汝未加密的 明文消息,于是就有可能因为强制要求或被入侵而泄露……

传输层加密的一个例子:HTTPS

一个显示着 https 网址的地址栏

现在,抬起头来,看看汝浏览器上的地址栏,有没有看到 https:// 和一个绿色的锁啊 😂 HTTPS 就是传输层加密的一个汝经常能碰到的例子。为啥它比没加密的 HTTP 更安全呢? 因为 它使网络上的窃听者不能看到汝从服务器接收或向服务器发送的数据。

如果有窃听者视图获得用户正在访问的网站的数据,HTTP 连接不能提供保护,但 HTTPS 可以, 甚至能保护汝正在浏览的网站的路径。(例如这个时候窃听者就只能看到汝正在访问 https://ssd.eff.org

因为 HTTP 的问题太多了(例如可能会被注入、cookie / 用户名和密码被窃取、被针对性审查等等),所以现在 越来越多的网站都开始用 HTTPS 了。我们推荐使用电子前哨基金会制作的 HTTPS Everywhere 扩展,它可以在确定一个网站同时支持 HTTP 和 HTTPS 时强制使用 HTTPS 连接。

不过一个服务商提供了 HTTPS 网站不代表它会保护访问它网站的用户的隐私。例如心术不正的服务商 还是可以通过 cookies 在 HTTPS 网站上追踪用户,或是安装恶意软件。

传输层加密的一个例子:VPN

VPN(虚拟专用网络)是传输层加密的另一个例子,在使用 VPN 的情况下,汝的网络流量会以加密的形式经过汝的 ISP (互联网服务提供商)到达 VPN 服务商的服务器。如果有人(例如汝的 ISP?)想窃听汝的网络来了解汝访问了 些什么网站的话,它们会发现除了汝在用 VPN 这个事实以外并不会知道更多。

不过虽然使用 VPN 可以让汝对 ISP 隐藏汝的浏览历史,但是这些还是会被汝的 VPN 服务商看到(以及存储或修改, 如果它有这个打算的话)。所以信任汝的 VPN 服务商是一件要事。

SSD 也有一篇关于如何选择 VPN 的文章

端到端加密

端到端加密的一个例子

一个端到端加密的例子,左侧的手机加密一条消息并将它发送到服务商的服务器、再发送到右侧的目标。 最后目标手机解密消息。和传输层加密不同,只有终端(编写和接收消息的手机)持有解密消息的密钥, 因此剩下的地方(不管是基站还是服务商)都无法解密这条消息。

端到端加密在汝的消息从发件人到收件人之间全程保护。它可以保证汝的信息离开汝时会被加密而且只能被 汝的目标解密,包括汝正在使用的应用和中间的窃听者都不行。

汝自己读取端到端加密消息实际上意味着运营汝所使用的应用的公司也不能读取它们。 这是良好加密的核心特征:就算是设计和部署它们的家伙也不能破坏它,是呗。

Surveillance Self-Defense 中的 Communicating With Others 一节提供了一些支持端到端加密的聊天工具。

传输层加密还是端到端加密?

在汝考虑是选择传输层加密还是端到端加密时的问题只有三个:

  • 汝信任汝正在使用的应用和服务嘛?
  • 汝信任它的基础结构嘛?
  • (汝正在使用的服务)有没有政策防止执法请求,如果有的话,又是怎样做的?

只要汝有一个答案是“不”,那么汝就需要端到端加密,就是这样。

利用 OTR 进行端到端加密聊天的动画演示

我们制作了一个动画来演示端到端加密和传输层加密是如何保护汝传输中的消息的。 左侧是一个支持端到端加密(通过不留记录(OTR)实现)的聊天工具,右侧是支持传输层 加密的聊天对话框(Google Hangouts 支持 HTTPS)

在这个 GIF 中,用户首先通过 Google Hangouts 发送了一条消息:

“Hi! This is not end-to-end encrypted. Google can see our conversation.”

“嗨!这不是端到端加密, Gooole 能看到我们的对话。”

然后用户通过左侧的窗口启动了 OTR 聊天:

“Attempting to start a private conversation with [gmail account]. Private conversation with [gmail account] has started. However, their identity has not been verified.”

“正在尝试和 [gmail account] 进行私密聊天。 和 [gmail account] 的私密聊天已启动,但未验证对方的身份。”

同时, Google Hangouts 的对话框上出现了一些看起来像胡言乱语一样的消息。 表明了现在的消息都通过端到端加密来传输。

“Now the conversation is end-to-end encrypted, Google can see that we are chatting, but is unable to read what we'are actually saying.”

“现在这是个端到端加密的对话了, Google 能看到我们在聊天,却看不到我们到底在聊什么。”

“It looks like gibberish to anyone else.”

“对其他人来说就像胡言乱语一样”

“Yup, it looks like nonsense.”

“嗯,对它们丝毫没有用处。”

😃

加密传输中的数据不能做什么

加密不是万能药,汝加密的数据最终还是需要被和汝交谈的人解密并读取。 如果汝的目标被攻击(例如被威胁/被收买)或者汝的目标的设备被入侵, 这个加密通讯还是被破坏了。以及他/她/它还是可以通过一些手段(例如屏幕截图)来保存汝等的记录。

如果汝有把加密的对话备份到其他的地方的话,最好也加密那些备份。
消息的元数据不会被加密

传输中进行加密可以保护汝的消息,却不会加密汝消息的元数据。例如汝和汝的朋友虽然可以通过加密 保护聊天记录,但是加密不会隐藏:

  • 汝等在通过加密进行交流的事实

  • 和交流有关的其它数据,例如位置,时间和长度。

    如果因为担心加剧的监控(例如主动的监视)而只在敏感时期或特定情况使用加密却会让汝陷入危险之中, 为啥?因为只是一段时间内使用加密的话,就有可能把元数据和一些重要的日期和时间关联起来。

    所以就算是普通的日常活动也要记得使用加密来保护自己哦~

以及要是只有汝自己在使用加密的话,汝所产生的元数据可能会被认为是可疑的(?)。 这就是鼓励大家都尽可能的使用加密工具的原因:为真正需要加密的人泛化加密的使用。

放在一起?

把静态数据和传输中的数据一起加密可以为汝提供更全面的安全性,就是那些信息安全专家所说的 “深度防御”啦~ 通过利用多种方法来保护汝的数据,就可以实现更深层次的保护,是呗。

例如,要是汝通过加密的设备发送未加密的消息(只加密了静态数据),虽然这些消息没有汝设备的密码 就不能在汝的设备上存取,但是政府,服务提供商或高明的攻击者可以在网络上窃听和拦截它们。

反过来说,要是汝没加密的设备发送通过端到端加密的消息(只加密了传输中的数据),虽然消息不会被网络上 的谁窃听和拦截,但是能接触到汝的设备的家伙就能打开汝的设备读取这些消息。

在看完这两个例子以后,汝大概能明白加密传输中的数据和静态数据是保护汝自己免于广泛的潜在风险的理想方法 了吧……

汝想更深入的了解如何使用加密?请继续阅读 关于加密的关键概念

by ホロ at December 05, 2018 04:00 PM

December 02, 2018

Lainme

用EXCEL来记账

现在有不少记账的APP,我也用过一段时间。不过由于隐私方面的考虑,现在把数据全部删除了,同时参考网易有钱和一些EXCEL模板做了一个EXCEL的记账表出来。目前实现了下面几个功能:

  • 多币种:记账时可以选择币种,可以不同币种转账。但是汇率是手填的,没法自动更新。
  • 收支类别:自定义收支类别,并在记账时选择。只支持一级分类。
  • 资金账户:自定义资金账户,记账时可以选择。有三个特殊账户“借入账户”、“借出账户”和“报销账户”
  • 数据汇总:账户、收支、币种都有各自的汇总统计数据

下载: finance.xlsx

by lainme (lainme@undisclosed.example.com) at December 02, 2018 07:45 AM

November 26, 2018

ヨイツの賢狼ホロ

给 GNU/Linux 萌新的 Arch Linux 安装指南

给会用点 Windows 的彻头彻尾的 GNU/Linux 新手的 Arch Linux 安装指南 😣

为啥要搞这个?

因为 ArchWiki 上的 Beginner Guide 已经和 Installation Guide 合成一个啦😂,然后有小白开始抱怨看不懂啦(误 (╯・∧・)╯ ┻━┻

其实咱最早看的也是 Beginner Guide ……

算了概念用到时再解释 😂

我是一个彻头彻尾的Linux新手,我应该用Arch吗?

如果你是新手,要使用 Arch 就必须愿意花时间学习新系统,接受 Arch 是一个 DIY 的系统,每个用户都是自己系统的组建者。

在开始问任何问题之前,自己先通过Google、Wiki或者论坛进行搜索。我们为你创建了这些资源并让你可以随时访问,上千志愿者为你提供了大量的信息资源。

推荐阅读: Arch terminology#RTFM

首先说点废话

备份……

万一手抖格错了盘别抱怨 GNU/Linux ……

但如果汝有备份的话,是不是已经下定决心把整个硬盘格式化掉了?(雾)

下载 ISO

https://www.archlinux.org/download/

BT 种子和磁力链接在上面,直接下载的话往下拉,找 China 下面的镜像网站挑一个下载就好。 (っ╹ ◡ ╹ )っ

如果是用 HTTP/HTTPS 下载的话,下载完以后最好验证一下文件的散列值来确定文件下载完了 (╯艹︿艹)╯ ┻━┻

Windows 上这样的工具有很多呐,例如 HashTab 和 FCIV。

但是如果汝正好没有这些工具或者从来没听说过散列(或者另一种译名叫哈希)的说法的话,可以用 Windows PowerShell 来完成:

# 例如获得某一个文件的 md5 散列值,用汝下载的 ISO 的路径换掉 <filepath>
Get-FileHash <filepath> -Algorithm MD5

# 尽管 md5 和 sha1 已经被认为是不安全的散列算法了(容易发生两个文件不同但散列值相同的情况,
也被称作散列碰撞”,然而 Arch Linux 的官方网站上还是只有这两种 😂, 先凑合着用吧……

至于下面那个 PGP 签名,又是个大坑,先鸽了(咕咕咕……)

确定启动类型

  • 首先打开设置 ( Windows 8/8.1 叫做 "电脑设置"),然后通过 "更新和恢复" -> "恢复" -> "高级启动" 重启电脑.

    Windows 10 的话,按住 Shift 再点击电源按钮里的重启也行……

如果是 UEFI 启动的话,大概是这个样子:

UEFI 系统启动之后大概像这样

没错就是有个 "使用设备" 的选项 😂

  • 或者同时按下键盘上的 Windows 徽标键(就是有 Windows 标志那个) 和 R 键,会打开“运行” 对话框。
“运行”对话框

在里面输入 msinfo32 然后回车(按 Enter 键)确认,打开”系统信息”应用。

“系统信息”窗口

看“BIOS模式”里是不是 UEFI 😂😂,还有下面那个 “安全启动状态”是不是“以关闭”(咱这台电脑的 UEFI 太旧所以显示的是不支持)

如果安全启动是打开的还需要自己进 UEFI 固件设置里手动关闭 😂

具体怎么关因为每种电脑的方法不一样于是汝要自己 STFW (Search the f**king Web,搜索一下) 了😂
  • 再或者打开磁盘管理(Windows 8 以后的系统可以通过按下 Windows + X 的菜单里找到 “磁盘管理”)
磁盘管理在这~

嗯,大概就是这样子的呗 (虽然具体的磁盘分区可能和咱的不一样)

大概长这样~

看汝的硬盘上有没有一个 EFI 系统分区 😂😂😂


还是搞不懂的下面也不用看了,准备下最后的晚餐吧 😋 (误

在硬盘上准备一块空闲空间

不然要把 Arch Linux 装到哪里去呐?

这里拿来演示的是 Windows 7 以后都自带的 “磁盘管理” 程序,应该能解决大多数问题 _(:з」∠)_

  • Windows 8 以后的系统可以通过按下 Windows + X 的菜单里找到 “磁盘管理”
磁盘管理在这~
  • 嗯,大概就是这样子的呗 (虽然具体的磁盘分区可能和咱的不一样)
大概长这样~
  • 汝哪个硬盘分区比较空闲? 右键点击它,有一个"压缩卷的选项"
”压缩卷“ 在这~
  • 输入压缩的大小 _(:з」∠)_
多少
  • 然后就多了一块未分配的空间 😂
多了一块未分配的空间

如果汝的硬盘分区有些刁钻而磁盘管理没法解决的话,AOMEI 家的分区助手不错, 这是官方网站 , 这是分区教程

制作启动盘

但前提是汝的电脑能从 U 盘启动 😂 (不过最近几年生产的电脑都应该可以了吧……

Windows 下咱比较推荐一个叫 rufus 的软件,官方网站在这

下载完以后双击运行,需要管理员权限,记得看有没有数字签名。(有数字签名时用户账户控制的对话框是蓝色的)

Rufus 自带多国语言(当然也包括中文啦),如果汝系统语言不是中文的话,点击那个地球图标就可以修改语言了啦~

选择语言

然后戳有点像光盘的按钮选择刚下载好的 ISO 镜像

选择映像

然后选择一种启动类型,UEFI 就选最后一个,不是的话就选第一个。

选择启动类型

写入方式选推荐的就好 (´_`)

选择写入方式

确认(要知道汝按下确认以后就没有回头路了,所以记得提前备份 U 盘上的资料 😂)

确认

然后坐等完成,完成以后汝的 U 盘卷标应该是 "ARCH_201610" 这样的 (后面四位年份和两位月份),不要改成别的,万一不对记得照 ISO 改回来 😂😂

准备启动

重启电脑,然后让电脑从 U 盘启动。

具体怎么搞还是要看电脑的硬件啦 😂

大多数的电脑都有一个在开机时按下一个按键来选择从哪里启动的选项(例如 Dell 和 ThinkPad 是 F12)。 UEFI 的话, 刚才提到的那个“使用设备” 的选项也可以。

还是去翻一翻汝自己的电脑生产商的说明书更快一点 ……

  • MBR 成功启动以后像这样
MBR

选第一项。😂 (除了 CPU 不支持的都应该用x86_64 😋)

后来 Arch Linux 不再支持 i686 啦,所以这里应该只会看见 x86_64 那一项(但是咱懒得换图片啦……)
  • UEFI 成功启动以后像这样
UEFI

还是选第一项。😂

然后等待一会以后会出现……

root@archiso ~ #

这就表示已经启动完毕啦 ~(>_<~)

root是用戶名,前面那個數字是上一個命令的exit status啦,如果正常結束的命令exit status是0,就不會顯示出來,你有 1 2 127 這種都是某種東西報錯了.

----现任 Arch Linux TU 之一的 farseerfchttps://www.zhihu.com/question/45329752/answer/98733823 中写到……

联网

因为 ArchISO 就是个重启就没了的 Live 环境,安装时需要的软件包都要另外下载。

首先当然是联网啦,如果是自动获取 IP 地址的有线网络,那么应该啥也不用做,ping 一下试试?

root@archiso ~ # ping archlinux.org
# 汝应该会看到像这样的东西 ……
PING archlinux.org (138.201.81.199) 56(84) bytes of data.
64 bytes from apollo.archlinux.org (138.201.81.199): icmp_seq=1 ttl=49 time=361 ms
……

(把电脑用网线接到家里的路由器上就有相同的效果)

如果没网的话…… 😂


  • 先用 ip link 确定一下网卡
root@archiso ~ # ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp4s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000
    link/ether c8:9c:dc:a8:ab:c3 brd ff:ff:ff:ff:ff:ff
3: wlp0s29u1u1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 44:94:fc:0f:63:b9 brd ff:ff:ff:ff:ff:ff

这个例子里,lo 是本地环回不用管它,enp 开头的是有线网卡,wlp 开头的是无线网卡。

如果汝明明有无线网卡却没识别的话,有可能汝是某无线网卡厂商受害者😂😂

这时可以:

  • 有 Android 手机的话,手机连 WiFi ,然后用“USB 网络共享”共享给电脑。
  • 找个 USB 无线网卡插上 😂
  • 连有线😂😂
  • 如果有无线网卡的话,试试连接到 WiFi ……

    如果汝的 WiFi 是用 WPA2-Enterpise 验证的(输入用户名和密码那种),还是放弃吧…… wifi-menu 现在还不支持这个(

** 输入 wifi-menu ,等一下会看到找到的 WiFi 网络的列表

WiFi 列表

** 选择一个网络,保存网络配置文件

保存配置文件

** 如果有密码的话,输入密码

WiFi 密码

** 然后按 Enter 确认,连到 WiFi 的话会返回 Shell。

谁叫 Arch 连不上网的话都装不了 😂

另外,如果汝连接的网络需要网页登录(Captive Portal),可以用 elinks 碰碰运气 😂

# 用汝的门户的 URL 替换 <your_captive_portal_url>
# 如果不知道的话,随便访问一个 HTTP 网站试试,应该就会被重定向到 Portal 了
root@archiso ~ # elinks http://<your_captive_portal_url>

时间同步

timedatectl set-ntp true 保证时间同步 。

root@archiso ~ # timedatectl set-ntp true
root@archiso ~ # timedatectl status
    Local time: Fri 2016-10-28 17:39:42 UTC
    Universal time: Fri 2016-10-28 17:39:42 UTC
    RTC time: Fri 2016-10-28 17:39:42
    Time zone: UTC (UTC, +0000)
Network time on: yes
NTP synchronized: no
RTC in local TZ: no

因为有不少操作需要准确的时间呐,例如 HTTPS 和 GnuPG 都需要准确的时间来验证证书的有效性。

但是如果因为各种原因没法同步的话,那就只好手动设置咯~

# timectl set-time "yyyy-MM-dd hh:mm:ss"
root@archiso ~ # timectl set-time "2016-10-28 17:39:42"

准备硬盘空间

这里用 cgdisk (UEFI)/ cfdisk (MBR) 来给硬盘分区。

首先输入 lsblk 看看汝的硬盘是哪个设备:

root@archiso ~ # lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 463.9G  0 disk
├─sda1   8:1    0   512M  0 part
├─sda2   8:2    0    16M  0 part
├─sda3   8:3    0 103.4G  0 part
└─sda4   8:4    0 253.4G  0 part
sdb      8:16   1   7.5G  0 disk
└─sdb1   8:17   1   7.5G  0 part /run/archiso/bootmnt
sr0     11:0    1  1024M  0 rom
loop0    7:0    0 346.1M  1 loop /run/archiso/sfs/airootfs

如果那是一块新硬盘或者已经清空的硬盘的话,汝大概看不到 /dev/sda1 一类的分区。


如果汝没看到 /dev/sda 却看到了一些其它的东西的话:

  • /dev/nvme0n1 一类的:表示汝的电脑上有一块 NVMe SSD (发出了羡慕的目光(咳咳))
  • /dev/mmcblk0 一类的:表示汝的电脑上有 eMMC 存储(例如是早期的 Windows 8 平板电脑啥的)

这种时候的话可能汝 ArchISO 的 U 盘就跑到 sda 去了,在下面的操作时记得注意一下。

比如咱这里 sda 是咱的硬盘,于是运行 cgdisk 时加上 /dev/sda 这个参数:

/dev 是一个虚拟目录(也就是并不在硬盘上),它会把电脑上的设备映射成一个个文件 _(:з」∠)_

再学究的解释真不会了……

cgdisk

root@archiso ~ # cgdisk /dev/sda

如果汝在用 cgdisk 的话汝可能会看到这样的提示:

Warning! Non-GPT or damaged disk detected! This program will attempt to
convert to GPT form or repair damage to GPT data structures, but may not
succeed. Use gdisk or another disk repair tool if you have a damaged GPT
disk.


                                            Press any key to continue....

这表示 cdgisk 在这块硬盘上找不到 GPT 分区表。如果这是一块新硬盘或者已经清空的硬盘的话 不必担心,继续即可。否则请立即停下来检查一下硬盘(或者汝有这块硬盘的备份的话也可以继续)。

                                            cgdisk 1.0.1

                                        Disk Drive: /dev/sda
                                    Size: 972906545, 463.9 GiB

Part. #     Size        Partition Type            Partition Name
----------------------------------------------------------------
            1007.0 KiB  free space
1           512.0 MiB   EFI System                EFI system partition
2           16.0 MiB    Microsoft reserved        Microsoft reserved partition
3           103.4 GiB   Microsoft basic data      Basic data partition
4           253.4 GiB   Microsoft basic data      Basic data partition
            106.6 GiB   free space





    [ Align  ]  [ Backup ]  [  Help  ]  [  Load  ]  [  New   ]  [  Quit  ]  [ Verify ]  [ Write  ]

cgdisk 的界面大概像这样啦,用上下方向键把光标移动到汝之前的空闲空间上去(例如咱这里是最后一个)

新硬盘的话应该只有一个 free space 😂

用左右方向键把下面一排按钮上的光标移动到 New 上,然后按 Enter。

(这里看不出光标😂,黑色背景下光标应该是白的吧😂😂)

接下来会问几个问题(# 开头的是咱加上的注释😂):

# 数字可能和汝看到的不一样😂
# 起始扇区的位置,直接 Enter 就行
First sector (749424640-972906511, default = 749424640):
# 大小,可以是扇区数,也可以是实际的大小(例如 100M,20G一类的),要用掉整个剩余空闲空间的话,直接 Enter 就行。
Size in sectors or {KMGTP} (default = 223481872):
# 分区类型,默认的就好
# 但是如果要建立新的 EFI 系统分区的话 ,分区类型是 :code:`ef00`
# 但是如果要建立新的 交换空间(就是虚拟内存啦)的话 ,分区类型是 :code:`8200`
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300):
# 设置卷标,不设置也行。
Current partition name is ''
Enter new partition name, or <Enter> to use the current name:

然后汝应该会发现下面的空闲空间变成 Linux filesystem 了呗~

要保存分区表的话,用左右方向键把下面一排按钮上的光标移动到 Write 上,然后按 Enter。

Are you sure you want to write the partition table to disk? (yes or no):

        Warning!! This may destroy data on your disk!

在这里输入 yes (就是 yes,不是 y Y YES 啥的😂),然后按 Enter。

然后下面会闪过一行 "The operation has completed successfully" ,这时就可以退出了。

用左右方向键把下面一排按钮上的光标移动到 Quit 上,然后按 Enter。

cfdisk

如果汝在用 cfdisk 的话汝可能会看到这样的提示:

                        ┌ Select label type ───┐
                        │ gpt                  │
                        │ dos                  │
                        │ sgi                  │
                        │ sun                  │


        Device does not contain a recognized partition table.
Select a type to create a new label or press 'L' to load script file.

这表示 cfgisk 在这块硬盘上找不到可以识别的分区表。如果这是一块新硬盘或者已经清空的硬盘的话 不必担心,选择 dos 继续即可。否则请立即停下来检查一下硬盘(或者汝有这块硬盘的备份的话也可以继续)。

这就是 cfdisk 的主界面啦:

                                                    Disk: /dev/sdc
                                Size: 465.8 GiB, 500107862016 bytes, 976773168 sectors
                                        Label: dos, identifier: 0x178bfb32

    Device            Boot               Start              End          Sectors         Size       Id Type
>>  Free space                            2048        976773167        976771120       465.8G










┌──────────────────────────────────────────────────────────┐
│Filesystem UUID: 3AB8802AB87FE2B5                                                                                   │
│     Filesystem: ntfs                                                                                               │
└──────────────────────────────────────────────────────────┘
                            [   New  ]  [  Quit  ]  [  Help  ]  [  Write ]  [  Dump  ]


                                        Create new partition from free space

也是选择 new 然后输入大小:

Partition size:
# 然后可能会让汝选择是主分区还是扩展分区,按需选择就 OK
[primary]  [extended]

但是如果汝需要调整分区类型的话,选中要改变的分区然后把光标移动到 Type 上按 Enter,选择一个分区类型:

                                                    Disk: /dev/sdc
                                Size: 465.8 GiB, 500107862016 bytes, 976773168 sectors
                                        Label: dos, identifier: 0xe0a3ecf7

    Device           Boot               Start             End        Sectors        Size      Id Type
>>  /dev/sdc1                            2048         1050623        1048576        512M      ef EFI (FAT-12/16/32)
    /dev/sdc2                         1050624       976773167      975722544      465.3G      83 Linux










┌──────────────────────────────────────────────────────────┐
│Partition type: EFI (FAT-12/16/32) (ef)
└──────────────────────────────────────────────────────────┘
            [Bootable]  [ Delete ]  [ Resize ]  [  Quit  ]  [  Type  ]  [  Help  ]  [  Write ]  [  Dump  ]

要保存分区表的话,用左右方向键把下面一排按钮上的光标移动到 Write 上,然后按 Enter。

Are you sure you want to write the partition table to disk? (yes or no):

在这里输入 yes (就是 yes,不是 y Y YES 啥的😂),然后按 Enter。

然后下面会闪过一行 "The operation has completed successfully" ,这时就可以退出了。

用左右方向键把下面一排按钮上的光标移动到 Quit 上,然后按 Enter。


然而汝以为这样就结束了?还没格式化呢 (╯°Д°)╯︵/(.□ . )

创建文件系统+挂载

所以挂载是啥玩意?

GNU/Linux 不是用 Windows 那样的盘符来分区的啦,GNU/Linux 继承了 Unix 的整个目录结构 从根目录 / 开始。然后下面是各种子目录。

大多数的 GNU/Linux 发行版都遵循一个叫做“文件系统层次结构标准”(Filesystem Hierarchy Standard, 有时也简称作 FHS)的标准,汝可以 ls / 一下看看会不会发现一些例如 /bin /home /usr 一类的目录? 这就是拜这个标准所赐 😂

在 Windows 里,汝大概会把不同的文件放在不同的盘符下的硬盘分区里。 在 GNU/Linux 中,咱们通常就是把不同的分区 挂载到整个目录结构中的一处。向挂载好的目录写入的文件就会保存在被挂载的磁盘分区上。

首先还是用 lsblk 确定一下分区的名称,为了以防万一记得加上 -f 参数:

root@archiso ~ # lsblk -f
NAME   FSTYPE   LABEL       UUID                                 MOUNTPOINT
sda
├─sda1 vfat               3C44-B4ED
├─sda2
├─sda3 ntfs               42E243C5E243BBC3
├─sda4 ntfs   新加卷      58741F29741F0A00
└─sda5
sdb
└─sdb1 vfat   ARCH_201610 EAC8-F012                            /run/archiso/bootmnt
sr0
loop0  squashfs                                                  /run/archiso/sfs/airootfs

第一排分别表示设备名称,文件系统类型,卷标,UUID和挂载点。

咱这里的话 sda1 那个 vfat 分区就是 EFI 系统分区啦,sda5 就是刚刚新建的分区啦~(因为还没格式化所以没有文件系统😂)

mkfs.ext4 把那个分区格式化成 ext4 文件系统咯~

mkfs 可以格式化成某一个汝指定的文件系统(就像刚才那样 mkfs.ext4 可以格式化出一个 ext4 文件系统)

ext 家族大概是 GNU/Linux 最古老,应用的最广泛的文件系统了吧……

当然可以用的文件系统有很多啦,如果汝想再了解一些的话,可以去 ArchWiki 看一看:

https://wiki.archlinux.org/index.php/File_systems

记得自己看清楚是哪个分区别格式化错了 😂

root@archiso ~ # mkfs.ext4 /dev/sda5
mke2fs 1.43.3 (04-Sep-2016)
Creating filesystem with 27935234 4k blocks and 6987776 inodes
Filesystem UUID: a3943e57-6217-4a5f-8e57-ade5771315c0
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done

root@archiso ~ #

等一排文字闪过就格式化完了……

如果要格式化新的 EFI 系统分区的话,用 mkfs.vfat

如果要格式化新的 交换空间的话,用 mkswap

接下来用 mount 挂载分区啦~ (。>ω<)。

# mount <设备名称> <目标文件夹>
# /mnt 挺合适的
root@archiso ~ # mount /dev/sda5 /mnt
# 如果要挂载 EFI 系统分区的话,建议挂载到 /mnt/boot
# 所以先建立相应的文件夹
root@archiso ~ # mkdir /mnt/boot
root@archiso ~ # mount /dev/sda1 /mnt/boot
# 有交换空间的话不用挂载,用 swapon 命令。
root@archiso ~ # swapon /dev/sda6

选择软件仓库镜像

软件仓库(在Debian系发行版中,又叫做“软件源”)是软件包存储的地方。通常我们所说的软件仓库指在线软件仓库,亦即用户从互联网获取软件的地方。

用 nano 打开 /etc/pacman.d/mirrorlist

root@archiso ~ # nano /etc/pacman.d/mirrorlist


GNU nano 2.7.0                        File: /etc/pacman.d/mirrorlist

##
## Arch Linux repository mirrorlist
## Sorted by mirror score from mirror status page
## Generated on 2016-10-01
##

## Score: 0.2, France
Server = http://archlinux.polymorf.fr/$repo/os/$arch
## Score: 0.3, France
Server = http://arch.tamcore.eu/$repo/os/$arch
## Score: 0.3, Germany
Server = http://mirrors.cicku.me/archlinux/$repo/os/$arch
## Score: 0.3, Czech Republic
Server = http://ftp.sh.cvut.cz/arch/$repo/os/$arch
## Score: 0.3, Germany
Server = http://mirror.js-webcoding.de/pub/archlinux/$repo/os/$arch
## Score: 0.4, Netherlands
Server = http://ftp.nluug.nl/os/Linux/distr/archlinux/$repo/os/$arch
## Score: 0.4, Poland
                                        [ Read 517 lines ]
^G Get Help    ^O Write Out   ^W Where Is    ^K Cut Text    ^J Justify     ^C Cur Pos     ^Y Prev Page
^X Exit        ^R Read File   ^\ Replace     ^U Uncut Text  ^T To Spell    ^_ Go To Line  ^V Next Page

这是 GNU nano 的主界面,最简单的方法还是把下面那些 Mirrors 先全删掉然后输入一个新的, 用光标指向某一行以后同时按下 Ctrl+K 就好。然后自己输入一个 Mirror ,下面给出几个中国国内的 Mirror:

(所谓的 Ctrl+K 就是这两个键一起按😂)

# 网易
Server = http://mirrors.163.com/archlinux/$repo/os/$arch
# 清华大学 TUNA 协会
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch
# 中国科学技术大学
Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch
# 西安交通大学
Server = https://mirrors.xjtu.edu.cn/archlinux/$repo/os/$arch

输入完以后按下 Ctrl+O 写入,按 Enter 确定,再按 Ctrl+X 退出。

然后用 pacman -Syy 刷新一下软件包数据库。

root@archiso ~ # pacman -Syy
:: Synchronizing package databases...
core                                  120.9 KiB  4.92M/s 00:00 [##################################] 100%
extra                                1755.6 KiB  5.24M/s 00:00 [##################################] 100%
community                               3.7 MiB  6.82M/s 00:01 [##################################] 100%
root@archiso ~ #

安装基本系统

用 pacstrap 安装基本系统,默认会安装 base 组(就是最基本的软件包咯), 要通过 AUR 或者 ABS 编译安装软件包,还需要安装 base-devel 啦:

评论里 farseerfc 提到装几个连接无线网络需要的软件包。(iw dialog wpa_supplicant wpa_actiond)
root@archiso ~ # pacstrap /mnt base base-devel iw dialog wpa_supplicant wpa_actiond

这个组并没有包含全部 live 环境中的程序,有些需要额外安装, packages.both 页面包含了它们的差异呗~

其他软件以后会用 pacman 再安装啦~

安装完以后大概会是这个样子 (´・ω・`)

pacstrap /mnt base base-devel   29.09s user 2.61s system 85% cpu 37.271 total

准备进入 chroot 环境

生成 fstab 啦 ~

所以 fstab 又是个啥玩意?

fstab(5)文件可用于定义磁盘分区,各种其他块设备或远程文件系统应如何装入文件系统。

每个文件系统在一个单独的行中描述。这些定义将在引导时动态地转换为系统挂载单元,并在系统管理器的配置重新加载时转换。 在启动需要挂载的服务之前,默认设置会自动fsck和挂载文件系统。例如,systemd会自动确保远程文件系统挂载 (如NFS或Samba)仅在网络设置完成后启动。因此,在/etc/fstab中指定的本地和远程文件系统挂载应该是开箱即用的。

emmmmm

# genfstab
usage: genfstab [options] root

Options:
    -L             Use labels for source identifiers (shortcut for -t LABEL)
    -p             Exclude pseudofs mounts (default behavior)
    -P             Include printing mounts
    -t TAG         Use TAG for source identifiers
    -U             Use UUIDs for source identifiers (shortcut for -t UUID)

    -h             Print this help message

genfstab generates output suitable for addition to an fstab file based on the
devices mounted under the mountpoint specified by the given root.
root@archiso ~ # genfstab -U /mnt >> /mnt/etc/fstab

然后用 arch-chroot 向新系统出发~

因为还有些配置没完成嘛……
root@archiso ~ # arch-chroot -help
usage: arch-chroot chroot-dir [command]

    -h                  Print this help message
    -u <user>[:group]   Specify non-root user and optional group to use

If 'command' is unspecified, arch-chroot will launch /bin/bash.
root@archiso ~ # arch-chroot /mnt /bin/bash
[root@archiso /] #

设置基本系统

# 开头只表示以 root 用户运行,汝不用把 # 输入到终端里啦~
  • 设置时区(中国的时区是 Asia/Shanghai)
# ln -s <源文件> <目标> 创建一个符号链接

# ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  • 设置时间标准 为 UTC,并调整 时间漂移:
# hwclock --systohc --utc

如果汝正在尝试安装双系统,在进入 Windows 以后可能会发现 Windows 的时间不对了 ,因为 Windows 默认的硬件时钟是 localtime(

可以用一条注册表键值让 Windows 使用 UTC 作为硬件时钟(在早于 Windows 7 的系统上发现过这样做会出现一些严重的问题: http://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html

reg add "HKEY_LOCAL_MACHINESystemCurrentControlSetControlTimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f
  • /etc/locale.gen 是一个仅包含注释文档的文本文件。指定您需要的本地化类型,去掉对应行前面的注释符号(#)就可以啦,还是用 nano 打开,建议选择帶UTF-8的項:
# nano /etc/locale.gen

en_US.UTF-8 UTF-8
zh_CN.UTF-8 UTF-8
zh_TW.UTF-8 UTF-8
  • 执行 locale-gen 以生成 locale 讯息:
# locale-gen
  • 创建 locale.conf 并提交您的本地化选项:

    将系统 locale 设置为en_US.UTF-8,系统的 Log 就会用英文显示,这样更容易问题的判断和处理。用户可以设置自己的 locale。

    警告: 不推荐在此设置任何中文locale,或导致tty乱码。

# echo 用来输出某些文字,后面的大于号表示把输出保存到某个文件里啦~

# 或者可以用文字编辑器新建这个文件加上这一行。

# echo LANG=en_US.UTF-8 > /etc/locale.conf
  • 设置一个喜欢的主机名(用汝的主机名代替 myhostname ):
# echo myhostname > /etc/hostname
  • 设置 root 的密码(输入密码的时候就是啥也没有 ╮( ̄▽ ̄)╭ ):
[root@archiso /]# passwd
New password:
Retype new password:
passwd: password updated successfully

以及汝大多数时候应该是用不到这个密码的(

  • 安装启动管理器(例如 GRUB ):

** UEFI 用户先再安装几个必要的软件包咯~

# pacman -S efibootmgr dosfstools

** 然后安装 GRUB

# pacman -S grub os-prober

** 把 GRUB 安装到硬盘:

# MBR 用户这么做 (记得用汝自己硬盘的名称代替 sda ,不要带上表示分区的数字啦~):

# grub-install --target=i386-pc /dev/sda --recheck

# UEFI 用户这么做:

# grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub --recheck

EFI 安装成功以后大概像这样 😂

[root@archiso /]# grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub --recheck
Installing for x86_64-efi platform.
Installation finished. No error reported.

然后生成必要的配置文件:

[root@archiso /]# grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-linux
Found initrd image(s) in /boot: initramfs-linux.img
Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img
WARNING: Failed to connect to lvmetad. Falling back to device scanning.
done

这个时候多半找不到 Windows 😂,建议重启以后再生成一下……

设置 sudo

所以这又是个啥玩意? (´_`)

因为 root 用户的权力很大而且很危险,所以轻易不会用到它 (。>ω<)。

所以就有了 sudo(substitute user do) 使得系统管理员可以授权特定用户或用户组作为 root 或其他用户执行某些(或所有)命令,同时还能够对命令及其参数提供审核跟踪。

(话风突变)

sudo 应该已经作为 base-devel 的一部分装上去了,如果没有的话汝也可以自己手动安装一下:

[root@archiso /]# pacman -S sudo

sudo 的配置文件是 /etc/sudoers ,但是咱们不会直接去编辑它(因为一旦搞坏了不好修)。 所以有一个 visudo 的命令用来代理编辑它(就是先编辑一个临时文件,然后检查有没有错误, 一切 OK 后再覆盖)。

嗯…… visudo? 如果汝觉得 vi 哪里眼熟的话,没错! 这个命令默认会用 vi 去编辑那个文件。 如果汝想用其他的编辑器(例如刚刚用的 nano)的话,可以通过一个环境变量:

[root@archiso /]# EDITOR=nano visudo

现在大概像这个样子:

GNU nano 3.2                                        /etc/sudoers.tmp

## sudoers file.
##
## This file MUST be edited with the 'visudo' command as root.
## Failure to use 'visudo' may result in syntax or file permission errors
## that prevent sudo from running.
##
## See the sudoers man page for the details on how to write a sudoers file.
##

##
## Host alias specification
##
## Groups of machines. These may include host names (optionally with wildcards),
## IP addresses, network numbers or netgroups.
# Host_Alias    WEBSERVERS = www1, www2, www3

##
## User alias specification
##
                                                [ Read 97 lines ]
^G Get Help    ^O Write Out   ^W Where Is    ^K Cut Text    ^J Justify     ^C Cur Pos     M-U Undo       M-A Mark Text
^X Exit        ^R Read File   ^\ Replace     ^U Uncut Text  ^T To Spell    ^_ Go To Line  M-E Redo       M-6 Copy Text

虽然这个文件有很多行,但是咱们还是先从让它能够工作开始来最小的修改它。

找到下面的这一行,然后把 %wheel 前面的注释符号(#)去掉,不过百分号要留下:

## Uncomment to allow members of group wheel to execute any command
# %wheel ALL=(ALL) ALL

然后就可以保存退出啦~ (效果就是注释里说明的,给 wheel 组执行所有命令的权限)

如果汝想进一步了解 sudo 的配置的话,还是去看 ArchWiki: https://wiki.archlinux.org/index.php/Sudo

安装桌面环境 (可能不一定需要)

  • 安装桌面环境需要的基础包 (就是 xorg 啦)
[root@archiso /]# pacman -S xorg
:: There are 80 members in group xorg:
:: Repository extra
1) xf86-input-evdev  2) xf86-input-joystick  3) xf86-input-keyboard  4) xf86-input-libinput
5) xf86-input-mouse  6) xf86-input-synaptics  7) xf86-input-vmmouse  8) xf86-input-void
9) xf86-video-amdgpu  10) xf86-video-ark  11) xf86-video-ati  12) xf86-video-dummy
13) xf86-video-fbdev  14) xf86-video-glint  15) xf86-video-i128  16) xf86-video-intel
17) xf86-video-mach64  18) xf86-video-neomagic  19) xf86-video-nouveau  20) xf86-video-nv
21) xf86-video-openchrome  22) xf86-video-r128  23) xf86-video-savage  24) xf86-video-siliconmotion
25) xf86-video-sis  26) xf86-video-tdfx  27) xf86-video-trident  28) xf86-video-vesa
29) xf86-video-vmware  30) xf86-video-voodoo  31) xorg-bdftopcf  32) xorg-docs  33) xorg-font-util
34) xorg-fonts-100dpi  35) xorg-fonts-75dpi  36) xorg-fonts-encodings  37) xorg-iceauth
38) xorg-luit  39) xorg-mkfontdir  40) xorg-mkfontscale  41) xorg-server  42) xorg-server-common
43) xorg-server-devel  44) xorg-server-xdmx  45) xorg-server-xephyr  46) xorg-server-xnest
47) xorg-server-xvfb  48) xorg-server-xwayland  49) xorg-sessreg  50) xorg-setxkbmap
51) xorg-smproxy  52) xorg-x11perf  53) xorg-xauth  54) xorg-xbacklight  55) xorg-xcmsdb
56) xorg-xcursorgen  57) xorg-xdpyinfo  58) xorg-xdriinfo  59) xorg-xev  60) xorg-xgamma
61) xorg-xhost  62) xorg-xinput  63) xorg-xkbcomp  64) xorg-xkbevd  65) xorg-xkbutils  66) xorg-xkill
67) xorg-xlsatoms  68) xorg-xlsclients  69) xorg-xmodmap  70) xorg-xpr  71) xorg-xprop
72) xorg-xrandr  73) xorg-xrdb  74) xorg-xrefresh  75) xorg-xset  76) xorg-xsetroot  77) xorg-xvinfo
78) xorg-xwd  79) xorg-xwininfo  80) xorg-xwud

Enter a selection (default=all):

这时会让汝选择需要哪些软件包啦,其实大多数时候默认的就行……

  • 接下来挑一个喜欢的桌面环境包组装上咯~

    (咱这里就只举例 GNOME KDE 和 xfce 啦,其他官方支持的桌面环境可以去 https://wiki.archlinux.org/index.php/Desktop_environment_(简体中文) 查看)

    GNOME , 想要 GNOME 全家桶的话带上 gnome-extras

    # pacman -S gnome

    KDE Plasma , 想要 KDE 全家桶的话用 kde-applications-meta 代替 kde-applications。 kde-applications 会提示汝选择要安装哪些包。

    # pacman -S plasma kde-applications

    或者只安装 Dolphin (文件管理器),Kate(文字编辑器)和Konsole(终端模拟器)

    # pacman -S plasma dolphin kate konsole

    xfce4,xfce 不带显示管理器,所以要装个其他的(例如 lightdm,还要装一个 greeter)

    # pacman -S xfce4 xfce4-goodies lightdm lightdm-gtk-greeter

    桌面环境大多数使用 NetworkManager :

    # pacman -S networkmanager

  • 然后安装中文字体( 同样 pacman -S 😋)

    Google Noto Fonts 系列: noto-fonts noto-fonts-cjk noto-fonts-emoji

    思源黑体:adobe-source-han-sans-otc-fonts

    文泉驿:wqy-microhei wqy-zenhei

更多的字体可以在 https://wiki.archlinux.org/index.php/Fonts_(简体中文) 找到。

收尾工作

  • 新建一个用户

    -m 为新用户创建一个目录,-s 设置用户的登录 Shell -G 会把新建的用户追加到某个组中 (这里是刚刚 sudo 里的那个 wheel)

    记得最后是用户名就好 😂

    # useradd -m -G wheel horo

    然后设置密码(记得输入

    # passwd horo

  • 激活需要的服务(显示管理器啦)

    # systemctl enable gdm

    or

    # systemctl enable sddm

    当然还有 NetworkManager:

    # systemctl enable NetworkManager

    (这个里面有大写😂)

    systemd 是 Arch Linux 现在唯一的 init 程序,当内核加载完毕后,首先被加载的 就是 init (这里就是 systemd 啦)。然后 systemd 会接着加载剩下的部分。

    https://wiki.archlinux.org/index.php/systemd

  • 设置用户级别的 locale

    用 su 切换到刚建立的用户,然后编辑 ~/.config/locale.conf 修改自己的 Locale ,例如:

LANG=zh_CN.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=

或者可以重启以后用桌面环境的设置程序改 😂

完工啦

  • 离开 chroot 环境:

    # exit

  • 卸载挂载的分区,(其实不是必须的,因为马上就重启啦~)

    # umount -R /mnt

  • 重新启动,准备迎接新的系统吧 ~(>_<~)


欢迎来到 Arch Linux 的世界!

Cheers! 汝刚刚成功的安装 Arch Linux 到汝的电脑中了呐!

那接下来要干啥呢?

by ホロ at November 26, 2018 04:00 PM

November 25, 2018

ヨイツの賢狼ホロ

在 在 GNU/Linux 的桌面环境中设置自动切换壁纸 (GNOME 篇)

在 GNU/Linux 的桌面环境中设置壁纸,是怎么样的呢?

如何设置壁纸?

GNOME Tweaks 设置壁纸

GNOME 的话,可以用 Tweaks 设置。

汝是不是已经看见了那里设置的壁纸不是图片而是个 XML?😂

或者可以用 gsettings 设置:

gsettings set org.gnome.desktop.background picture-uri 'file:///path/to/my/picture.jpg'

所以那个 XML 是啥?

打开看一下不就知道了 ?😂

<background>
<starttime>
    <year>2011</year>
    <month>11</month>
    <day>24</day>
    <hour>7</hour>
    <minute>00</minute>
    <second>00</second>
</starttime>

<!-- This animation will start at 7 AM. -->

<!-- We start with sunrise at 7 AM. It will remain up for 1 hour. -->
<static>
<duration>3600.0</duration>
<file>/usr/share/backgrounds/gnome/adwaita-morning.jpg</file>
</static>

<!-- Sunrise starts to transition to day at 8 AM. The transition lasts for 5 hours, ending at 1 PM. -->
<transition type="overlay">
<duration>18000.0</duration>
<from>/usr/share/backgrounds/gnome/adwaita-morning.jpg</from>
<to>/usr/share/backgrounds/gnome/adwaita-day.jpg</to>
</transition>

<!-- It's 1 PM, we're showing the day image in full force now, for 5 hours ending at 6 PM. -->
<static>
<duration>18000.0</duration>
<file>/usr/share/backgrounds/gnome/adwaita-day.jpg</file>
</static>

<!-- It's 7 PM and it's going to start to get darker. This will transition for 6 hours up until midnight. -->
<transition type="overlay">
<duration>21600.0</duration>
<from>/usr/share/backgrounds/gnome/adwaita-day.jpg</from>
<to>/usr/share/backgrounds/gnome/adwaita-night.jpg</to>
</transition>

<!-- It's midnight. It'll stay dark for 5 hours up until 5 AM. -->
<static>
<duration>18000.0</duration>
<file>/usr/share/backgrounds/gnome/adwaita-night.jpg</file>
</static>

<!-- It's 5 AM. We'll start transitioning to sunrise for 2 hours up until 7 AM. -->
<transition type="overlay">
<duration>7200.0</duration>
<from>/usr/share/backgrounds/gnome/adwaita-night.jpg</from>
<to>/usr/share/backgrounds/gnome/adwaita-morning.jpg</to>
</transition>
</background>

这文件看起来好简单啊咱就不加注释了……

于是汝就能自己写一个脚本来生成这样的 XML (例如 https://pastebin.com/019G2rCy )

如果想更懒一些的话可以试试 Shotwell (选择想要的图片然后 File → Set as Desktop Slideshow)

是不是很简单鸭 😂

不是 GNOME ?

KDE Plasma 的话可以参考兔兔的 [Linux/KDE] 一步步教你给 KDE 用上 macOS 专属动态壁纸

虽然例子是 macOS 的那个沙漠,但是汝自己可以用别的啊 😂

其它桌面可以参考布偶君的 在 GNU/Linux 的桌面环境中设置自动切换壁纸

by ホロ at November 25, 2018 04:00 PM

November 24, 2018

百合仙子

通过 Cloudflare DNS 验证来申请 Let's Encrypt 证书

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

我本地的 MediaWiki 的证书过期啦,干脆申请个免费证书好了。之所以用 HTTPS,是因为 MediaWiki 不喜欢不加密的 HTTP,会登录不了……

在网上寻找时,发现 certbot 就有 Cloudflare 的插件呢!这下就方便了。首先 pacman -S certbot-dns-cloudflare 装上,然后把自己的 Cloudflare 凭证信息写到一个 ini 文件里:

dns_cloudflare_email = cloudflare@example.com
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567

就这么两行。保存好,设置好权限,然后就可以申请证书了:

sudo certbot certonly -d 域名列表 --dns-cloudflare --dns-cloudflare-credentials 凭证ini文件路径

稍微回答几个问题,证书就在 /etc/letsencrypt/live 下准备好啦。在 nginx 里配置一下就好了。

然后还要加个 cron 任务来更新证书(dcron 格式):

@weekly         ID=cert-renew   certbot renew -q

这样就大功告成了。

by 依云 at November 24, 2018 07:30 AM

November 19, 2018

百合仙子

正确地上传至 PyPI 并展示文档

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

数年过去了,今天经过多次尝试和询问,我终于成功让 nvchecker 的文档以富文件的形式展示在 PyPI 上了!

正确地打包上传命令是这样的:

rm -rf dist && python setup.py sdist && twine check dist/* && twine upload -s dist/*

如果 twine check 不通过,那么修正后重新执行。如果文档包含错误,PyPI 会以纯文本形式展示。

  • 听说要设置 long_description_content_type。好像 Markdown 才要设置的,rst 不用。
  • 听说不支持 # 开头的链接。实际上现在已经支持了。
  • 听说要用 twine,那就用吧。

原来我之前的文档一直没有正确地渲染,是因为有一个标题的「-」少了两个……

关于 PyPI 的资料是挺多的,但是细节不够详细,陈旧信息很多,唉。

by 依云 at November 19, 2018 07:17 AM

November 18, 2018

Phoenix Nemo

使用 fs.WriteStream 编写超简单的日志流

虽然 console.log 很好用,但是生产环境需要保存日志的时候就比较蛋疼。暴力 fs.appendFile 会消耗大量的 file handler,因此用 writable stream 来复用 file handler 是更好的选择。

大概是个不能再简单的思路了。先创建一个写入流

1
2
3
const fs = require('fs');

let logStream = fs.createWriteStream('./test.log');

这样便创建了一个文件写入口,需要时直接调用 logStream.write 即可写入数据。
接下来编写一个用于记录日志的函数替代 console.log

1
2
3
function logger (message) {
logStream.write(message);
}

至此基本功能就写完啦。但是太简陋了对不对,还是要再加点装饰。

重写 logger 函数,区分 stdoutstderr

1
2
3
4
5
6
7
8
9
10
11
12
let logInfo = fs.createWriteStream('./stdout.log');
let logError = fs.createWriteStream('./stderr.log');

let Logger = {};

Logger.info = (message) => {
logInfo.write('[INFO] ' + message);
}

Logger.error = (message) => {
logError.write('[ERROR] ' + message);
}

感觉还是少了点什么…日期?

1
2
3
Logger.info = (message) => {
logInfo.write(new Date().toISOString() + ' [INFO] ' + message + '\n');
}

嗯嗯。这就像样了。把代码整合起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const fs = require('fs');

let logInfo = fs.createWriteStream('./stdout.log');
let logError = fs.createWiteStream('./stderr.log');

let Logger = {};

Logger.info = (message) => {
logInfo.write(new Date().toISOString() + ' [INFO] ' + message + '\n');
}
Logger.error = (message) => {
logError.write(new Date().toISOString() + ' [ERROR] ' + message + '\n');
}

module.exports = Logger;

需要用时

1
Logger.info('This is an information.');

现在看对应的 stdout.log 文件就有相应内容啦。

1
2
~> tail -f stdout.log
2018-11-18T10:52:57.333Z [INFO] This is an information.

不够刺激?

1
2
3
[...Array(10000)].forEach((item, index) => {
Logger.info('Hello! ' + index);
});
1
2
3
4
5
6
7
8
9
10
11
12
~> tail -f stdout.log
...
2018-11-18T10:58:30.661Z [INFO] Hello! 9990
2018-11-18T10:58:30.661Z [INFO] Hello! 9991
2018-11-18T10:58:30.661Z [INFO] Hello! 9992
2018-11-18T10:58:30.661Z [INFO] Hello! 9993
2018-11-18T10:58:30.661Z [INFO] Hello! 9994
2018-11-18T10:58:30.661Z [INFO] Hello! 9995
2018-11-18T10:58:30.661Z [INFO] Hello! 9996
2018-11-18T10:58:30.661Z [INFO] Hello! 9997
2018-11-18T10:58:30.661Z [INFO] Hello! 9998
2018-11-18T10:58:30.661Z [INFO] Hello! 9999

搞定(┌・ω・)┌超简单的吧。

虽然 console.log 很好用,但是生产环境需要保存日志的时候就比较蛋疼。暴力 fs.appendFile 会消耗大量的 file handler,因此用 writable stream 来复用 file handler 是更好的选择。

November 18, 2018 11:01 AM

November 08, 2018

百合仙子

与 Android 进行 WLAN Direct 连接

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

首先 iw list 看是否支持。如果支持,那就

iw dev wlan0 interface add p2p0 type __p2pdev

这样其实并不会多出一个叫 p2p0 的网络接口。iw dev 能看到多了个「Unnamed/non-netdev」设备。不执行这个也可以连接上 WLAN Direct,但是当前的 managed Wi-Fi 连接会断掉。执行之后再连接,managed 连接会持续,iw dev 里会有两个 Unnamed,不知道何故。另外这个 type __p2pdev 加上去了我就不知道怎么删除了。试了几个命令,结果搞得内核 oops 了……

然后是 wpa_supplicant 配置文件:

ctrl_interface=/run/wpa_supplicant_p2p
ap_scan=1

device_name=起一个名字
device_type=1-0050F204-1

driver_param=use_p2p_group_interface=1

wpa_supplicant 跑起来。注意这里的接口名还是那个 managed 接口的。

wpa_supplicant -i wlan0 -c p2p_config.conf

然后 wpa_cli 连过去操作:

wpa_cli -p /run/wpa_supplicant_p2p

首先用 p2p_find 开启搜索。这时候对端设备能够看到自己了。使用 p2p_connect 对端MAC pbc go_intent=0 连接,在对端接受连接即可。go_intent=0 是让对方作为 group owner,这样对端 Android 才会提供 DHCP 服务(否则要本地提供了)。

然后就可以给自己添加 IP 地址了。此时是可以用 dhcpcd 的,然而直接跑的话它会抢走默认路由,所以知道地址范围之后手动加一个好了:

ip a add 192.168.49.22/24 dev p2p-wlan0-1

Android 设备的地址是 192.168.49.1。

之后就可以用 adb connect 然后 scrcpy 了。

PS: Android 很喜欢四十几的 IP 段呢。USB 网络共享是 192.168.42.129/24,Wi-Fi 网络共享是 192.168.43.1/24,而 WLAN Direct 是 192.168.49.1/24。不知道蓝牙网络共享是多少呢。

PPS: scrcpy 在我的 XZ2C 上运行完美,但是在 MIUI 10 上需要去开发者选项里开启选项「USB 调试(安全设置)」,否则会是「只读模式」,只能看,所有交互操作无效。

参考资料

by 依云 at November 08, 2018 09:40 AM

November 03, 2018

Felix Yan

为 glibc localedata 添加民国纪年支持

昨天被 @聞其詳 问起 glibc 对日本平成XX年的纪年支持情况(感谢 @farseerfc 老师),发现 glibc localedata 中并未包括民国纪年支持。在查询文档后稍微鼓捣了一下,简单实现了这个功能:

$ LC_TIME=zh_TW.UTF-8 date +%EY
民國107年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1912/4/3"
民國元年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1913/4/3"
民國2年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1911/4/3"
民前1年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1900/4/3"
民前12年

修改方法:

编辑 /usr/share/i18n/locales/zh_TW 文件,找到 END LC_TIME,在它之前加入这样三行:

era "+:2:1913//01//01:+*:民國:%EC%Ey年";/
    "+:1:1912//01//01:1912//12//31:民國:%EC元年";/
    "+:1:1911//12//31:-*:民前:%EC%Ey年"

保存后重新 locale-gen 即可。

不足:暂时没有弄明白怎么实现中文数字,不过阿拉伯数字也还过得去……

提交:glibc 的提交方式好像比较麻烦,所以先写篇博客好了。已提交并合并到 glibc。

发散:这个方法当然还可以用来实现各种自定义年号,比如朝鲜的主体纪年同样在 1912 年为元年,另外还有1970 “Unix 元年”、2013(咚咚咚,敲门声

by Felix Yan at November 03, 2018 02:11 PM

October 11, 2018

百合仙子

获得高精度环形镜子一枚

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

如图:

高精度环形镜子

这面镜子上边有好几百G数据呢,然而早已读不出来了。

镜子来源于九年前的西数移动硬盘。因为太老了所以坏掉了吧,反正是识别不了了。最近看到 YouTube 上有人各种折腾硬盘,群里又有人拆了好几面镜子出来,所以我把它找出来拆啦。这镜子比我那总也擦不干净的丽塔芙镜子清晰多了呢,就是小了点儿。

拆起来也不难。首先想办法把壳弄开。然后见着螺丝就旋下来,见着贴纸就撕掉。那覆盖一个螺丝孔的小圆片不用撕下来,直接螺丝刀往中间捅,然后把螺丝旋下来就好了。

HDD 拆解中

覆盖磁头的那块金属有两个螺丝,其中一个在洞里。它上边有块形状奇怪的磁铁,照片里吸了很多螺丝的就是了。磁头是直接翻个面,让重力把它拉下来就可以了,我之前以为还有螺丝之类的还弄了好久呢,结果手一翻它自己掉下来了。马达中间那个螺丝很不容易取下,因为整体会跟着转。我是用剪刀卡住它的两个洞才给旋下来的。剩下的手拆就可以了。

HDD 拆解完毕

by 依云 at October 11, 2018 03:31 PM

October 08, 2018

ヨイツの賢狼ホロ

利用 XMPP 和 OTR 进行私密聊天

基本上就是某篇文章的翻版……

https://hardenedlinux.github.io/cryptography/2018/02/01/pidgin_xmpp_otr_debian.html

关于 OTR 的原理啥的因为咱不懂,于是就接着抛这同一块砖引不同的玉了 😂

以及数了数发现文章数量年趋下降?(可能是因为不少东西开始往别的地方写了的缘故)

演示环境

PC :Parabola GNU/Linux Libre

其实有 Pidgin 用的发行版就 OK 😂 ,安装 pidgin, pidgin-otr 和 pidgin-xmpp-receipts 软件包(可能随发行版不同而不同)

Android:Xabber

虽然 Conversations 也支持但是只有 Conversations 侧发起 OTR 会话才能用,好迷 😂

启动加密

从工具 - 插件中启用 OTR:

Pidgin 通过插件可以支持 OTR

然后就可以在会话中发现 OTR 菜单。

Pidgin 会话中的 OTR 菜单 OTR 会话已启动

启动以后的 OTR 会话大概就是这个样子。

如果汝眼睛注意到的话,会发现菜单栏上的图标上有个感叹号,以及下面会提示未验证(Unverified)。 这个问题一会儿再解决 😂

Xabber 的话,点击下方锁形图标里的“启动加密”。

在 Xabber 中启动 OTR

加密连接建立成功后,锁会闭合。不过里面有个问号表示 OTR 指纹未验证。

在 Xabber 中启动 OTR

验证 OTR 指纹 - 概述

为啥要验证 OTR 指纹呢,因为汝不能确定汝收到的指纹对应的私钥的持有者和 汝收到的消息的发送者是不是同一个人嘛 😂 (毕竟大部分 XMPP 服务器只通过用户名 和密码进行认证,密码强度不够的话还是很容易被盗用的)

而验证显然不能通过刚建立的 OTR 会话来完成验证(先有鸡还是先有蛋?),所以需要借助一些外部手段完成验证啦~

Pidgin 中支持的验证方式

Pidgin 和 Xabber 支持 OTR 标准的三种验证途径(这个菜单可以从 OTR - Authenticate buddy 中打开):

  • 通过指纹手动验证。
  • 通过共享的秘密进行验证
  • 通过问答进行验证

手动验证

手动验证是最简单的方式,画面中会展示汝和对方的 OTR 指纹,在确认两边显示的指纹相同时, 汝可以标记为该指纹已通过验证。

Pidgin 中的 指纹验证
  • 因为要求通过另一个安全的信道交换指纹,所以能够当面验证当然是最好的啦,毕竟不会受到其它因素干扰。
  • 如果做不到的话,就看汝自己的需求和安全性要求啦,例如通过电话和加密的邮件也是种选择

通过验证以后 Pidgin 会提示“私密对话已建立”,而 Xabber 中锁形标志中间会变成对勾表示验证完毕。

通过共享的秘密/提问和回答进行验证

Pidgin 中通过共享的秘密验证 Pidgin 中通过问题验证

共享的秘密和提问验证的核心是,汝和朋友拥有相同的秘密,如果对方能回答出和这个秘密 有关的问题,那么对方很有可能就是和汝拥有相同秘密的那位朋友啦~

不过,这个验证的过程中双方不会看到对方的输入,只是如果双方的输入相同(共享的秘密)或者 对方的答案和汝设置的答案是相同的(提问和回答),双方的指纹就会标记成已信任。

其实这个方法并没有直接验证指纹来的实用……

多份指纹或者指纹发生了改变?

如果汝在多个设备上登录了一个 XMPP 账户,那汝就会有多个 OTR 指纹,重新登录也会使 OTR 指纹发生变化,汝的朋友也是如此。

如果汝在一开始只验证了部分指纹,而对方开始用新设备和汝进行 OTR 聊天时,汝会重新发现 验证提示的。

这时汝可以像以前一样进行验证,或者要求对方通过已经验证的实例把新设备的 OTR 指纹给汝发送一份,例如:

“汝今天这设备上的 OTR 指纹咱好像不认识啊,方便用咱俩 验证过的那部设备把这个设备上的 OTR 指纹发给咱嘛?”

如果汝双方有验证过 openPGP 密钥的话,也可以让对方用汝认识的密钥签名他的 OTR 指纹后把签名后的消息 发给汝,作用是相同的。

不过实际操作时要注意,记得是让对方把指纹发给汝,而不是把汝要验证的指纹发给对方。

准备一份指纹清单

如果汝日常会在好几部设备上使用 XMPP ,可以考虑整理一份指纹清单,在第一次验证时就让 汝的好友把汝现有的指纹验证完毕。

消息的主题大概像这样:

I hereby claim:

* I am bob, who owns the following PGP key(s):

    6B25C1C7 7E739D1B 6C5E86B0 D3CED892 A6AEB68B

* At the same time, I am the owner of the following OTR key(s):

    3340D56D 2C750734 F9869A1B 26CFAC08 04823F52
    1063A0B9 F9EE4D3B 06250142 2A720531 DD2D0DC4

* The following OTR key(s) are used for mobile phone,
    they may get revoked at any time.

    49AF52C4 53FF6323 635728B6 9325628C 0FF2E547

* And I declare revocation of the following OTR key(s), their
    private keys are destroyed, please don't trust them:

    8DF79391 B8082682 42D5483E 976503B8 E458AEA8

* To prove the claims above, this message is signed by my PGP key
    mentioned above.

You could also collect all fingerprints linked to your frequently
used xmpp accounts into a list like this, clear-sign it with gnupg,
and send it to your trustful friends, in order for them to trust you.

然后把这则消息通过 gpg 进行明文签名,效果大概像这样(下面这条消息也是咱的指纹清单):

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

I hereby claim:

  * I am KenOokamiHoro, who owns the following PGP key(s):

    C41D545A 576AC1FE 4DBE90C9 B6CF41D1 879E8002

  * At the same time, I am the owner of the following OTR key(s):

    B9A0DE73 1F9689D7 856F1C40 41C6D1D0 059A2E70
    EC63BC9D FAFC37FA C4331842 1357CCF6 D67961F9

  * The following OTR key(s) are used for less stable mobile devices,
    they may get revoked at any time.

    49AF52C4 53FF6323 635728B6 9325628C 0FF2E547
    EFEBAF65 78722ED3 3FB5A8C5 B20B4B14 2A20F48E

  * To prove the claims above, this message is signed by my PGP key
    mentioned above.

You could also collect all fingerprints linked to your frequently
used xmpp accounts into a list like this, clear-sign it with gnupg,
and send it to your trustful friends, in order for them to trust you.
-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQQjv2kr4UE70DFaNrtMlLVI0dRI/gUCW6n1sQAKCRBMlLVI0dRI
/n5PAQDobS25Xn06yBI+HhOQpi97J9JZuyvPOGbc6L8bm0t/1AD/Ye4xvA9+9NPt
zh9i9QVrupW3FvINUd8q/M9Y1wqOsQI=
=knz+
-----END PGP SIGNATURE-----

有一个问题是某些客户端会对消息排版(如 Pidgin 会用 html 排版),而这会破坏 clear-sign 的一致性。 一个有效的解决方法是用gpg --store -a将 clear-sign 的文本编码成不怕排版的 radix-64 形式, 用gpg -d即可还原。该命令默认会对输入作透明的压缩,故比压缩再 base64 的“传统”做法操作更简便。

就像这样:

-----BEGIN PGP MESSAGE-----

owF1U0uS2zYQ9Zqn6GWSkS1+QcJVXoAfSLQ9+o48GXtFSZCEiCQ0ACmZvltOkE3O
kVOkRdmpisvmAkR14/V7rxv465/1i09//v3i5fWLs1E+gdloBst8NMlSuM+WSzbK
+qQ1LszhNSzHzA2IZeVwEFqsO9iUhaxeWxbAb5BDUcE7UU/VsajkWGk1gMtBgbrU
BpqDgJ0qS3WR9b5nOYruF/NrjwVIfCcN/IBBEBKWODwDP40zaicUYpJwzDoQhTSL
bNu9sbGmr2mKSkAjKzG48V9jSCg0qN13pNOHxf9JY8rsNAs9cDglEU1DiALCncS3
wXcSkjqpDXZAmZuFdg/IEuLFCU2BM554IWeo2/OcyHfB8YIwSTiBlISUYMGbyoef
KIBCC2iN2GJWQymMAdMU61JApdYSf1txlhthBj0v+uigKjrYiwa0OKsjAosGirrr
vb+6+fEp44Gb+BB4nBPP9YCgKjeKCVAP5+ZGCdicu1nghzc/PIsZJwGEUei6WeqB
x+OARUkAsWvHfuz44DLX5n6UffWj4KTVWfSt7YdvoFhjYIARaaBCJ8VeAG6N3Nco
Ey9J1X0beM9aibqR6prrkSj+SbWwUW2JkdIo3Jal2KC9soQd9k3ok5Z1Y6CU9dV5
o6BTrYadFs8tFis7q2/l5+p0gmKDla6HEaGgQIxpcDmKXuAARYtCv7yKA9nARTYH
2NftaT+winoLRuCC8W8UjW5Ns2tRh5aYQrysQekt3q/r4LAL1fVsf+yKeGX94C2x
h9Xi6zOy5HiVscVTzmL7MZ/P/zi7R+2v8IKlvJjo5r58/yG3t4t8uF8lj6R2zJy9
Sxbxf3FrWAczNk/VeukGv9c26eL8bnyYzk+Shm/p249td55NR+sNeR+tK7sZOiwd
Pgn/85nROzqZNdaXA5V0/kG3p0ePk3M+WW2j5+E9fXIuz1Mzz99Yb471l7ubkWyS
/sjGvw==
=jMb7
-----END PGP MESSAGE-----

如果使用这个方法的话,就算现在建立的 OTR 通道没被信任也不要紧(如果汝信任对方的 PGP 密钥的话)

组合验证

这好几种方法其实是可以组合在一起的:

  • 如果正好遇上了或者约定好了要见面(例如参加 PGP Signing Party时),可以顺便完成验证指纹。

    不过根据汝的威胁模型,可能要加入窃听者的威胁。

  • 如果汝或者汝信任的第三方信任对方的 PGP 公钥,可以用 PGP 完成指纹验证呗~

  • 如果安全要求稍低的话,可以使用电话,短信或者其它 IM 完成(例如 Wire 或 Signal?)

  • 可以的话也可以继续拆分多通道信息交换,通过多个通道获得的信息的组合组成最终的共享秘密。 不过需要注意尽量不要在某一通道内提到通过其他通道交换的消息的内容。

by ホロ at October 08, 2018 04:00 PM

Felix Yan

请不要把 Wifi Dongle 翻译成加密狗

在许多翻译过来的文本里,无线网卡(Wifi Dongle / Wifi Adapter)被翻译成了“加密狗”。最近在微博大火的一篇《俄罗斯特工又蠢了!实名行动暴露自己还卖了300多特工队友…..》里面,又出现了类似的错误,让我不得不想说说这个问题。

先来看看这个例子:

文章描述了几个黑客在目标附近发射伪造热点钓鱼,此处的未翻译单词包括了 Wifi 和 Dongle。根据上下文,带一个无线网卡发射热点应该是正确的意思,而加密狗在这里和上下文没啥关系……

我尝试在搜索引擎里搜索对应词组,很不幸,惨状令人叹息:

就连正规电子产品的用户界面都中了枪:

这个问题的来源,看起来是国内加密狗早年被简单称呼为 Dongle:

Dongle,按照维基百科的解释,是和 Adapter(适配器)很类似的一个词,泛指了一大类连接、转换器。

Wireless/Wifi Dongle = Wifi 适配器,Bluetooth Dongle = 蓝牙适配器,以此类推。所以,在看到类似 USB Dongle 这样模糊名字的时候,请务必联系上下文。如果原文用了 Wifi Dongle 这样比较明确含义的词组,请翻译为 Wifi 适配器,或者无线适配器,不要再翻译成加密狗了。

by Felix Yan at October 08, 2018 08:25 AM

September 29, 2018

Phoenix Nemo

重构 StickerSetBot

关注 Telegraf 有一段时间了。特别是最近 Telegram 上 spammer 猖獗导致 Telegram 对于用户行为限制越来越严格,由此想过写一个简单的 bot 来处理加群请求之类的。

总之原因都是没时间。终于搞定一些事情之后发现之前瞎写的 Telegram 导出贴图 bot 居然备受欢迎…正好 Telegram Bot API 也更新了,来重构吧!

拆分逻辑代码

最头疼的事情首先是当时写这 bot 的时候只顾着考虑各种情况,逻辑像流水一样全部写成一坨。虽然实际不复杂吧但这不是 best practice。于是把每个功能单独拆出来先。

on('command') 的逻辑代码整块移出来作为 handler,然后能够原子化的功能再单独拆分成函数调用。目前的效果虽然还是有不少逻辑层在 handler 里,但是基本达到了比较方便维护的目的。

handler 本来就是拿来写逻辑的啊摔

接下来再清理冗余代码和各种 hard code,加了两个方法让代码看起来更整洁一些。于是就先这样。

迁移框架

好在 Telegraf 和之前用的框架在参数上很多兼容,所以这没有花太多时间。顺便尝试采用了一部分 ES6 的风格,嘛…果然不喜欢。

所以就不要吐槽为什么 ES5 和 ES6 的风格混写了。

之前要一大长串的传参现在只要一个 context 了好方便啊。中间件也好方便啊~

以上。

调试:无尽的 bugfix

并不指望一通大换血之后的代码能一次跑起来…但是没跑起来的原因是我传错了中间件值这不能忍!!为什么一会儿传的是函数本体一会儿传的是函数调用啊摔!!

而且这问题还让我调了两个小时!!!

调通了之后就很舒服了

遇到的坑还有 context 本身不能当 session 用,然而不想再引入 session 中间件于是自己写了个超简陋的内存 session。就是为了多语言支持。因为一觉醒来发现这 bot 语言莫名其妙变中文了(messages 成了全局变量 = =

当然还有 Telegram 自己的坑,比如什么贴纸就是死下载不能然后整个程序就 hang 着了。

一键导出贴纸包

终于!Telegram bot API 添加了 StickerSet 类型。只要有贴纸包名称,就可以获取整个贴纸包的信息。考虑不改变用户习惯的情况下(你哪有什么用户啊可恶)对本身处理贴纸和其他消息的函数做了修改,顺便又拆了俩函数出来(怎么代码越来越多了啊喂!

最后结果就是没有一屏看不到头的函数啦~(你快够

以及加入了用贴纸包链接导出一整组贴纸的功能,算是真正意义上的 StickerSetBot 了。

然后贴纸过多卡死了 Telegram 的 ratelimiting

直接导出单张贴纸

既然功能拆分了那也就方便加更多别的功能啦。比如不新建任务,直接甩过去一张贴纸来获得 PNG 文件~

这只 bot 在这里,源码在这里。欢迎各种玩坏~(记得去发 issue

就酱(,,•﹏•,,)

关注 Telegraf 有一段时间了。特别是最近 Telegram 上 spammer 猖獗导致 Telegram 对于用户行为限制越来越严格,由此想过写一个简单的 bot 来处理加群请求之类的。

总之原因都是没时间。终于搞定一些事情之后发现之前瞎写的 Telegram 导出贴图 bot 居然备受欢迎…正好 Telegram Bot API 也更新了,来重构吧!

September 29, 2018 06:26 AM

September 28, 2018

百合仙子

每次修 Python 代码的 bug 的时候总会想念 Rust

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

俗话说:由俭入奢易,由奢入俭难。

之前写 Python,老是在实现完一个特性之后,弄出来几个 AttributeError: 'NoneType' object has no attribute 或者 TypeError: list indices must be integers or slices, not str,还有 TypeError: can only concatenate str (not "int") to str 这样的错误。一看就明白自己又是哪里一不小心疏忽了,稍微修一下就好。

后来啊,我遇见了 Rust,整个流程就变了。之前写的时候,基本上都是通过手动测试来发现这种问题。为了高效、不破坏性地测试,需要控制测试的数据量,需要保证出错的时候相关的数据不会处于某种中间状态。当然在服务器上跑的脚本,我还要来来回回地传更新的脚本,或者弄个本地测试环境。而这一切,可能不过是为了跑一个成功之后再也不会用到的小程序,比如之前分析抓包数据的那次。而在 Rust 里,这些最容易犯的错误,cargo check 一下,编译器基本上能全给你指出来。所以有时候写一些小工具我也用 Rust,虽然写起来慢,但写好就能正常运行,不用反复试错,多好啊!

最近给 Arch Linux 中文社区的自动打包机器人 lilac 增加新特性。结果实现完部署之后,夜里就被 lilac 叫起来修 bug 了,还一下子就是仨……(lilac 很难本地测试,而短暂地服务中断又没多大影响,所以我都是不进行本地测试的。)

第一个 bug 是,与 dict.get 不一样,getattr 是没有默认值的。Python 里这种不一致很多,比如 configparser 里默认值要用关键字参数指定。Rust 遇到类似的情况,就会返回一个 Option。或者如果 API 决定如果不存在就 panic 的话,那么它就会直接返回我要取的值的类型,而不会包一层 Option。而我后边的代码是预期到这里可能取不到那个属性的,所以弄错了就会类型不匹配。

第二个 bug 是局部变量在一个分支上没有初始化。Rust 当然不会允许这种情况了。实际上 C 都不用担心这种问题,编译器会给出警告的,还有一些 linter 可以用。而 Python,很遗憾的是,我所使用的 pyflakes 并没有对此发出警告。我当然知道 pylint 那些。我很讨厌 pylint 和 jslint 这种不区分潜在 bug 和风格问题的 linter。我只需要工具在我可能疏忽的时候提醒我,而不需要它对我的编码风格指指点点,特别是那些指指点点往往是不对的。比如我的文件描述符变量名不叫 fd 难道要叫 fildes?

第三个 bug 是一个可能为 None 的变量我忘了先作 is not None 判断。这段代码如果初写的话我肯定是会注意到的,但是改的时候,只想着如果 pkg 里有冒号我得处理一下,就忘记了根本没有关联的包名的情况。Python 的 None,以及 C 和 C++ 的 NULL、Java 的 null、Lua 和 Ruby 的 nil、JavaScript 的 undefined 和 null,被称作是十亿美元错误,给无数程序员和用户带来了无尽的 bug。幸好这个东西在 Rust 里不存在:表达「没有值」的值没有被作为特殊值存在于几乎所有类型中,而是作为一类类型的可能的值之一。想要使用「正常」的值,就需要显式地进行类型转换,所以不可能被不小心忽略掉。顺便说一下,Go 里也有 nil 这种东西,以至于会出现这种不容易发现的 bug

Python 现在也给出了解决方案:类型注解,提供类似的类型检查。不过检查器是第三方的,也并不十分完善。等我找到机会试用过之后再来写感想啦。

by 依云 at September 28, 2018 01:37 PM

Felix Yan

Thunderbolt 3 eGPU Bumblebee 方案尝鲜

最近从公司淘了一块 GTX 1060,淘宝了一个显卡盒折腾 TB3 eGPU 方案。由于笔记本经常带出门,打算采用即插即用的 bumblebee 方案(回家插上盒子用独显,拔下盒子可以带出门,可以正常待机不用重启)。下面记录一下 Arch 上配置的步骤和遇到的坑。

1、准备软件包

# pacman -S bumblebee primus lib32-primus nvidia-dkms lib32-nvidia-utils bolt

2、修改 bumblebee 配置

修改 /etc/bumblebee/xorg.conf.nvidia,在 Section “Device” 中加入:

Option "AllowExternalGpus" "true"

修改 /etc/bumblebee/bumblebee.conf,在 [optirun] 中修改:

Bridge=primus

3、插入 TB 线,验证设备(不建议完全关闭设备验证!)

输入 boltctl 查看设备信息,记下设备的 uuid。

$ boltctl
 ● TUL TBX-550CA
   ├─ type:          peripheral
   ├─ name:          TBX-550CA
   ├─ vendor:        TUL
   ├─ uuid:          00xxxxxx-xxxx-xxxx-ffff-ffffffffffff
   ├─ status:        authorized
   │  ├─ domain:     domain0
   │  └─ authflags:  none
   ├─ authorized:    Fri 28 Sep 2018 08:23:25 AM UTC
   ├─ connected:     Fri 28 Sep 2018 08:23:21 AM UTC
   └─ stored:        Thu 27 Sep 2018 05:22:07 AM UTC
      ├─ policy:     auto
      └─ key:        no

验证设备并设置为自动验证:

$ boltctl enroll --policy=auto 00xxxxxx-xxxx-xxxx-ffff-ffffffffffff

4、启动 bumblebeed

# systemctl start bumblebeed

5、测试、运行程序

$ optirun glxspheres64
Polygons in scene: 62464 (61 spheres * 1024 polys/spheres)
Visual ID of window: 0x13f
Context is Direct
OpenGL Renderer: GeForce GTX 1060 5GB/PCIe/SSE2
……

6、安全删除设备(参考了 jpamills 博客里的脚本)

#!/bin/bash

secs=5
tbt_chain=/sys/bus/thunderbolt/devices/0-0/../../../..

echo "Unplug eGPU script started."
if [ "$(id -u)" != "0" ]; then
        echo "Please run using sudo. Exiting."
        exit 1
fi

systemctl restart bumblebeed
sleep 2
modprobe -r nvidia_modeset
modprobe -r nvidia-uvm
modprobe -r nvidia

if [ -e $tbt_chain/remove ]
then
        echo 1 > $tbt_chain/remove
        echo "Thunderbolt chain removed from PCI tree. Please unplug eGPU now."
        while [ $secs -gt 0 ]; do
                echo -ne "$secs to rescan...\033[0K\r"
                sleep 1
                : $((secs--))
        done
        echo 1 > /sys/bus/pci/rescan
        echo "Rescanned the PCI bus. Completed."
        exit 0
else
        echo "eGPU does not appear to be attached. Exiting."
        exit 1
fi

如果和我一样在盒子上插了外置硬盘,还可以在脚本里加上相应的 umount 语句。删除设备时需要先把使用设备的程序退出。

效果展示

剩下的问题

  • 脚本里可以考虑通过判断 nvidia-smi 列出的 PID 自动杀掉所有还在用卡的进程
  • Vulkan 应用程序暂时无法使用外置卡运行(仍然使用集显),可能需要 bumblebee 提供支持

by Felix Yan at September 28, 2018 08:54 AM

September 27, 2018

ヨイツの賢狼ホロ

扫盲 XMPP(Jabber) - 一个自由开放的即时消息协议

这标题的命名方式哪里眼熟……

想和谁在网上聊天的话,可以用的 IM 软件有不少,当然槽点也很多(这家伙要求真多.png):

  • WhatsApp , Line 之流: 从客户端到协议都是私有的,以及似乎有向审查屈服的倾向?
  • Telegram ,服务端是私有的,官方客户端的源代码经常咕咕咕……
  • Signal 和 Wire ,虽然服务端和客户端都是自由的,但是有人成功运行起来自己的服务端嘛 🤔

……

于是是时候试试看 XMPP 啦(编不下去了.webp.png 😂)

XMPP 是啥?

可扩展消息与存在协议(XMPP,全称为Extensible Messaging and Presence Protocol,前称Jabber) 是一种以XML为基础的开放式即时通信协议,是经由互联网工程工作小组(IETF)通过的互联网标准。

Jabber是一个开放源代码形式组织产生的网络即时通信协议。XMPP原本是为即时通讯而量身定制, 但由于XML Stanza本身是XML元素,在基于XML灵活发展的特性下,使得XMPP也可以适用其他方面, 已经得到了IETF的批准。XMPP与IMPP、PRIM、SIP(SIMPLE)合称四大IM协议主流,在此4大协议中,XMPP是最灵活的。

(从维基百科抄的(雾))

有不少聊天软件是 XMPP 的实现,例如 Google Talk 和 Facebook Messenger,以及 AOL 和 一些网络游戏的聊天等。

因为传送的是 XML 嘛,所以 XMPP 协议本身十分灵活,不过传送二进制文件来就稍微有些困难了(不过有不同的扩展 可以提供文件上传等功能)。

和电子邮件一样, XMPP 也是非中心化的协议,可以均衡负载和对抗封锁。当然有可以多处登录啦, XMPP 通过优先级来 区分不同的设备,优先级高的设备会收到相应的消息(有人认为这是个缺点,于是有了 MAM 在不同的设备间同步消息)。

XMPP/Jabber实现多人聊天(MUC,Multiply User Chat)是采用聊天室的方式实现的,形如 room@domain.tld 的形式, 用户可以添加这个聊天室进行群聊,不过介于不少客户端不支持群聊加密,于是 XMPP 更多的还是以私聊为主。

注册一个 XMPP/Jabber 帐号

因为 XMPP 是个自由开放的协议啦,所以网上有很多公开的 XMPP 服务, 这里 有一个大而全的列表。 但是如果汝只是想找个速度合适的服务器的话,BLUG 整理出了一个 经过测试的部分 XMPP 服务器清单

可以看到大多数的 XMPP 服务器对注册没有任何要求,只需要汝选择一个 Jabber ID 然后输入密码就 OK 啦, 当然这么做的后果之一就是忘记密码就不能找回了,所以创建一个强密码并记住它特别重要。

除了在网页上注册以外,不少服务器也支持在客户端上注册,所以……

安装一个 XMPP 客户端

不同平台上可以推荐的客户端有很多:

  • 比如跨平台的 Pidgin (顺便还可以跨协议,但是 Pidgin 支持 XMPP 是挺优秀的)。 Windows 可以从 https://pidgin.im/download/ 下载安装包,GNU/Linux 可以从包管理器安装,或者下载源代码编译
  • macOS 用户可以安装 Adium,可以从 https://adium.im 下载。
  • iOS 用户推荐 ChatSecure,可以从 App Store 下载安装。
  • Android 用户推荐 XabberConversations 前者支持 XMPP 中常用的 OTR 端到端加密, 后者支持 MUC 和新的 OMEMO 和 openPGP 加密。

每一个 XMPP 客户端的登录和注册方法都不尽相同,但都比较简单。这里就偷个懒不指导啦 😂

和好友聊天或进行群聊

添加汝好友或群聊的 Jabber ID 就 OK 啦~

大概长这样

加密聊天

主要说的是端到端加密,毕竟 8102 年了,传输加密已经是刚需了吧 😂

目前 XMPP 中常用的端到端加密方式有三种 ,都是通过非对称加密实现的:

  • OTR(Off-the-Record Messaging,不留记录即时通讯) 是 XMPP 中最常用的端到端加密方式,被大多数客户端所支持。加密迅速而且前向安全。 缺点是更换客户端或重新登录时 OTR 指纹会发生变化, 可能会无法保证消息身份的一致性而需要重新验证。以及对文件的加密尚未标准化(不同客户端加密的文件 可能无法相互存取,因此习惯是发送文件的链接),另外称为下一代 OTR 的 OTRv4 正在开发中。
Pidgin 通过插件可以支持 OTR

Pidgin 通过插件可以支持 OTR,上面介绍的客户端中除了 Conversations 都支持 OTR。

  • OMEMO(OMEMO Multi-End Message and Object Encryption,OMEMO 多终端消息和对象加密) 是 一种新型的端到端加密协议,可以跨设备同步加密的消息记录和文件,验证起来也比较简单( 因为都盲目信任了? )。 不过除了 Conversations 以外好像都没支持好的样子……
  • openPGP 也能用于 XMPP 的端到端加密,不过毕竟是面向邮件的非对称加密,客户端不一定都支持 (Gajim、Psi+ 和 mcabber 支持)速度可能没那么快,还有可能把服务器娘累坏(雾)。

一些注意事项?

  • 因为大多数 XMPP 服务没有提供找回密码的功能,** 所以所以创建一个强密码并记住它!**
  • 传输加密是必须的,端到端加密最好也用上。
  • 端到端加密最好验证下双方的身份,除了传统的指纹验证以外 OTR 还可以通过共享秘密和问答验证。
  • 只使用自由开源的客户端, 这个不解释。

自己搭建 XMPP 服务器

好啊好啊,这就是非中心化服务的优势之一呢~

比较推荐的是 Prosodyejabberd , 前者轻量,配置简单。后者功能丰富,扩展性强。 咱就用 Prosody 搭了一个

读点别的?

https://tonghuix.io/2015/03/xmpp-chat/

⇪网页标题:弃用QQ和微信!全面转向基于XMPP(Jabber)的即时聊天

这篇文章简单的介绍了下 XMPP 的基本特点,也推荐了些不同平台的客户端。

https://beijinglug.club/wiki/lib/exe/fetch.php?media=xmpp-guide.pdf

⇪网页标题:XMPP(Jabber) 聊天快速指南

由北京 GNU/Linux 用户组(BLUG)成员编写的 XMPP 入门指南,图文并茂值得一读(?)

https://hardenedlinux.github.io/cryptography/2018/02/01/pidgin_xmpp_otr_debian.html

⇪网页标题:Debian/Ubuntu 用户使用基于 XMPP 即时通信协议的 OTR 保护隐私的标准化部署流程

介绍了 OTR 的原理, Debian 上使用 Pidgin 进行 OTR 聊天的流程,以及验证身份的一些技巧。

by ホロ at September 27, 2018 04:00 PM

September 20, 2018

百合仙子

永远不要 tail -f 管道

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

运维同事为了收集日志,配置程序将日志写入一个命名管道。然后他在外边拿 tail -f 去读,结果发生了灵异事件。通过 strace 可以看到,tail 进程读取了日志,但是却并没有再输出来。但是如果不启动输出日志的程序,而是在实例启动之后再进去往管道里写数据,却又是可以立即得到 tail 的输出的。

很奇怪的行为,一群人在那里研究半天,猜测是不是环境变量造成的啊,是不是放后台组执行造成的啊,是不是 XYZ 啊。——典型的「霰弹枪式」除错法

我当时也被带沟里了。于是跑去尝试复现,接着去读 tail 的源码。花了好久才明白这是一个很简单的问题:tail -f 的语义首先是 tail 这个词本身——先读文件最末尾的数据(默认是十行),然后再是 -f 选项的语义,即在文件更新时接着读取数据并输出。所以,当程序往里边写日志时,管道写端一直没关闭,tail 就一直读不到文件结束,也就无法确定最后十行是什么。当他们测试的时候,因为使用的是 echo shell 命令,打开文件、写入数据、关闭。这样 tail 一下子就读取到了文件末尾,然后把数据输出来了。接下来就是边读边输出了。

其实这种使用方法本身就很奇怪了,以至于这个执行流是兼容许多系统的 tail 的各种分支里,最最不常规、无可奈何的那一个分支。你都用管道了,cat 一下嘛。如果怕遇到管道被 reopen 的情况,就在 while true 里 cat 就好。

这个事件中,我也是见识了很多人解决问题的奇怪思路:「我猜猜猜。猜对了哦耶,猜错了,哎呀编程好难啊,Linux 系统好难啊……」猜你妹啊!你长的是大脑又不是骰子,用逻辑一步一步地取得结果不好吗!

有一个小游戏——猜数字。比如甲确定一个 1 到 1000 之内的整数,然后乙来猜。每当乙给出一个猜测时,甲回应猜对了,还是过大或者过小。如果乙知道什么叫二进制的话,乙可以保证在十次之内猜中的。

计算机系统和编程世界里,最棒的一点是确定性和逻辑性。虽然经常也不是像上例那样完全确定的,但至少比起人类社会要容易确定得多。特别是在有源码的时候。所以解决问题的路线也很简单,顺着问题的症状一路回溯,确认然后排除那些没有问题的部分,逐步缩小问题所在的范围,直接你看见它。就跟上边的猜数字游戏或者地毯式搜索一样。每一次猜测都是带着排除一部分没有问题的地方而去,而不是明明有证据表明某个地方不可能有问题,你还偏偏怀疑问题在那里,做无用功。

就像调查一个凶案,这些人放着有作案嫌疑的人不管,非要费劲地去调查那些有相当好的不在场证明的人。

Arch Linux 中文社区这边也有很多这种人。出了问题描述不清楚症状。新手嘛,没经验也没学习过如何描述事实,讲不清楚也没什么,引导对方获取截屏、日志,逐步排查问题就好了嘛。可就是有些热心人,喜欢提出自己的猜测。重点是:都不尝试证实猜测是否属实,就急着上解决方案。结果就是,我询问细节事实的消息没人理,求助者试试这个,试试那个,最终问题能否解决,就跟买彩票能否中奖一样,全凭运气。

by 依云 at September 20, 2018 03:08 PM

September 18, 2018

ヨイツの賢狼ホロ

听着节拍敲手指

这标题哪里眼熟……(划掉)

要是有一种游戏,它的唯一玩法就是按着音乐的节奏敲手指,要是有这样的游戏就好了。 但当时的我没有去做任何了解,只是将这个想法憋在了肚子里。 因为我觉得,这需求太小众了,才不会有人做这样的游戏的。

结果显然我错了,这样的游戏不但有,而且还有一大堆! 它们就叫做「音乐游戏」,简称「音游」。

听着节拍敲手指 - FiveYellowMice's Blog

不过按照维基百科的说法的话,音乐游戏其实还包括乐器模拟一类的游戏。而大家比较常说 的跟着节奏敲手指的那一类游戏的话,有一个更狭义的名称叫做节奏(动作)游戏 😂

所以下面所说的都是这种啦……

入坑

大概是六年前的时候,咱入手了咱的第一部 Android 系统的智能手机(Motorola XT535)。 随着 iPhone 和一批 Android 手机的出现,手机游戏的画质和体验突然就进步了起来 (和 Java 和 Symbian 时期的游戏相比)。于是当时有不少优秀的手机游戏出现了, (和不少推荐的文章)。

大概某一天咱在浏览游戏推荐文章的时候看到了 Cytus,画面看起来很漂亮,音乐也很动听。 于是就下载来试了试,就这样,一个新坑挖开了…… 😂

Cytus是款音樂節奏遊戲,遊戲方式簡單直覺,隨著歌曲旋律畫面上出現節奏拍點, 而玩家要做的就是配合動態掃描線的上下移動抓準時機點擊拍點。 遊戲畫面為細膩的手繪風格,同時網羅多位大牌日本樂師陣容參與音樂製作, 包括知名音樂遊戲的樂師Tsukasa,BMS同人編曲師Naotyu-、樂師Sta等人, 多樣化的曲風、高質感的畫面,是雷亞遊戲的自信力作。

(以上是官方介绍)

Cytus 的游戏截图

这就是 Cytus 的画面啦,音乐播放的时候,中间那条黑色的线(称作扫描线)会循环的上下移动, 汝要做的就是在扫描线和目标(像泡泡一样的)重合时触摸目标啦 ~ 按下的时机越准,分数就会越高呐~

后来这个游戏更新了数次,多了不少的新曲,甚至还出了续作)

https://play.google.com/store/apps/details?id=com.rayark.Cytus.full

借这个机会,咱也了解到了这个游戏的开发商 Rayark,一家台湾游戏公司。在 Cytus 之后,它们还制作了 数部音乐游戏作品,例如 Deemo 和 VOEZ。游戏的品质都属上乘,咱偶尔也会玩一玩(为啥是偶尔呢?)……

提速

后来咱买了第一部可以被称为“平板电脑”的家伙,就是 Samsung Galaxy Tab 2 啦,然后发现平板的 屏幕更大,同时可以用更多手指。可以说是玩音游的利器……

又是浏览游戏推荐文章的时候,发现有一篇文章除了提到咱玩过的 Cytus 和 Deemo 以外,还提到了另外两个游戏, Dynamix 和 OverRapid 。

OverRapid 的游戏截图

OverRapid 是一群韩国人开发的下落式音乐游戏(就是判定线不动,目标从上往下落下的类型, 这是音乐游戏的一种经典玩法)。不过这个游戏貌似主打的是高速(Rapid?),以及中间的两个 轨道有时会落下红色 note ( note 是音乐游戏对需要点击或按下的目标的一种习惯的表述方式), 这个时候就需要在判定线上滑动了,和普通的下落式游戏有些区别不是?

C4Cat推出的首款游戏Dynamix,是一款三重下落式音乐手机游戏。与一般下落式音乐游戏不同, Dynamix分为左、中、右3个下落方向的区域,每个区域作为一个乐器的音轨。 三区的设计令游戏更具变化,为游戏提供更有趣和更高难度的挑战。 另外,同时处理三个音轨也令玩家有亲身演奏整首音乐的临场感,加强音乐节拍。

(以上还是官方介绍)

Dynamix 的游戏截图

(三条轨道是不是很刺激?)(笑)咱一开始玩的时候也是手忙脚乱的呢,不过玩的久了就习惯了。 (虽然现在智能开着 Bleed 打打 12 以下的难度养老了, Event 肝不动啦……)

这两个游戏开始有一定难度了呢,不过咱还是会偶尔打开玩一阵的。

偶像的力量(雾)

曾经一阵很喜欢初音未来一系列的 VOCALOID 家族,(当然现在也很喜欢啦,不过现在更喜欢各大音乐游戏的原创曲了) 听歌的时候也接触到了以她们为主题的音乐游戏,就是 Project DIVA 系列啦~

Project DIVA Future Tone 的游戏截图

又是一种新的玩法,在画面上的目标和飞来的目标重合时按下对应的按键。也有长按和同时按等一系列的特殊音符。

既然叫做“初音未来 Project DIVA”系列嘛,自然收录的都是 Crypton 家的 VOCALOIDs 的曲目(3DS 版的 Project Mirai 有几首 INTERNET 家的 GUMI 客串出场)。每首歌都有特别制作的 PV (或者有时会偷懒直接拿原来的 PV),画面漂亮,就是偶尔 会光顾着看 PV 漏按了几个(雾),咱的 PSV 和 PS4 就是为了玩这个系列买的呢(然后又了解到了不少好游戏,又入了不同的坑)

新世界的大门

然后过了两三年。

有一天咱去街机游戏厅的时候,偶然瞥见了一台看起来很像洗衣机的街机(大概可以知道是啥了)。 有两位玩家正在游玩,还有一群人在围观。咱也凑近去看了一眼,感受到了熟悉的感觉,那个 随着音乐拍打按键的感觉……

一局游戏结束以后,有老玩家看到咱很有兴趣,便让出位置让咱来尝试一下。当时的感觉是记不清楚了, 只是觉得比手机上的那些不知道难了多少倍的样子……特别是看到老玩家们打高难度的歌曲时那行云流水的 样子,更是投下了羡慕的目光。

后来知道了这个游戏叫 maimai,当时还有个中文名叫做“舞萌”。这个名字听起来挺不错的,毕竟自己玩的 时候跟着音乐拍按键或者在屏幕上滑动的时候,真的和跳舞很像。不过咱当时还没有要深入的决心。

又过了一阵子,咱发现了家旁边的另一家游戏厅,于是便去看了看。这次除了 maimai 以外,还发现了其它的 音乐游戏街机。比如一个有按键两边还有盘子的(Beatmania IIDX)和看起来像弹吉他的(GutiarFreaks)。

这次不知道是为什么咱就去尝试了,虽然结果惨不忍睹到连 Beginner 难度都过不去( Beatmania IIDX 的 最简单的难度)。不过倒是喜欢上了,后来就经常去玩了。不知不觉就成了咱的兴趣之一了呢……

IIDX 的游戏截图

这就是 Beatmania IIDX 的游戏画面啦,没想到这个游戏竟然已经有接近 20 年的历史了呢~

Maimai 的玩法介绍

Maimai 的玩法介绍,目标靠近屏幕边缘时敲击屏幕周围的按键或者触摸屏幕边缘就好啦~

是不是很简单呢(露出了不怀好意的笑容.png)

太鼓达人的玩法介绍

像敲太鼓一样游玩的太鼓达人,除了街机版以外在 PSP/PSV/PS4/3DS/Nintendo Switch 等各种 平台上还有家用版。

遍地开花

后来了解信息的渠道越来越多,玩到的音乐游戏也越来越多。

在 Bilibili 上关注了些玩音乐游戏的 UP 主,接触到了不少优秀的音乐游戏,例如……

“和蔼的纯白色光芒,正在那失落世界的旋律斗争中等待着你。”

在这个挑战性十足的街机风格音乐游戏中随着旋律而触碰、按压与滑动; 聆听来自以日本为首的世界各地作曲者所写的歌曲!

体验全新的音符种类「音弧」:淋漓尽致地利用屏幕空间来滑动并跟随流动的旋律。 在这光芒与斗争相互纠缠的失落世界中遗失自我。

Arcaea 的游戏截图

特别像某个街机音游 SOUND VOLTEX 的 Arcaea,在普通的下落式的基础上加了第二条轨道, 玩起来完全是另一番景象。是咱现在经常玩的游戏之一。

https://play.google.com/store/apps/details?id=moe.low.arc

扮演主角探索地图,以音乐游戏进行「调律」,让黑白无声的世界恢复生机。
Lanota 的游戏截图

圆形的下落式音乐游戏,剧情和收录曲都很优秀。(然而咱才刚开始玩……)

https://play.google.com/store/apps/details?id=com.Noxygames.Lanota

Tone Sphere 的游戏截图

由 Bit192 Labs (其实只有 Sta 一个人)开发的音乐游戏, 看起来很像 osu! ,不过完成度似乎还可以。还是感叹又会画画又会作曲还能自己写游戏的 Sta 好天才啊……

https://play.google.com/store/apps/details?id=com.bit192labs.tonesphere

osu! 的游戏截图

俄亥俄州立大学专用播放器(雾)

一个结合了多种游戏模式的音乐游戏,曲库和谱面在玩家的努力下正在茁壮成长。

(其实优秀的音乐游戏还有不少啦,咱就先偷个懒…… 😂)

音乐游戏对咱的影响?

大概有:

  • 音乐播放器里的列表里都成了音乐游戏里玩过的曲目……
  • 因为在游戏里玩过某一部动画的曲目然后就去追了)
  • 听音乐时脑内会浮现出谱面(或者想象谱面)
  • ……

一些想法

玩了这么久的音乐游戏,还是觉得自己没入门……特别是看到其他人优秀的成绩的时候,心里还是会小别扭一下。 然后就继续练习去了……

音乐游戏玩家又被分成了不少更小的圈子呢,比如玩过街机音乐游戏的可以算上是“核心玩家”的一群人中的个别经常 会看不起只玩手机游戏的“休闲玩家”,反过来也有玩了某几部游戏以后就到处宣扬“** 天下第一”等等的(这种人好像 有些时候叫做睿智?)

然而周围的人看到自己在玩音乐游戏总是会问是不是节奏大师(&^$$^%^W^%$$^&......)

快取得突破的时候(例如要 Full Combo(没有失误)或者满分的时候)突然被打断, 又以“不就是游戏嘛”等一系列理由敷衍的时候……

在群聊打招呼的时候都说自己很弱然后突然发送了一张成绩很好的截图(大佬卖弱是音游玩家的一环?)

又说了不少的废话呢……

如果要咱推荐音乐游戏的话……

推荐手机上的音乐游戏的话:

  • 核心向(接近街机音乐游戏的游玩体验,有些挑战性):Arcaea,OverRapid,Dynamix,GROOVE COASTER 2 Original Style
  • 剧情向(画面出色,有一个好故事):Deemo,Lanota ,Tone Sphere,Cytus II
  • 听歌向(选曲优秀,简单上手):Cytus,VOEZ,MUSYNX

其实上面提到的游戏不止这一个方面有优势啦……

至于想体验街机音乐游戏的呢,(没想好)

😂


以上的游戏或网站截图来自各游戏的开发商。

by ホロ at September 18, 2018 04:00 PM

September 15, 2018

百合仙子

人生苦短,我用 skim

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

前两天我又看到了基于子序列匹配的字符串过滤工具 fzf 的绚丽效果了。实际上我很早就听说了这个工具,只是懒得动手配置。此次提及,我发现 fzf 已经在官方软件源里了,而我也正好有时间,所以打算试一试。

然后呢,Arch Linux CN 群组里艾穎初提到 skim 这么一个工具。了解了一下,这个就是 Rust 版本的 fzf,并且在 archlinuxcn 源里也有(git 版本,即 skim-git)。这太好了,就是它了!

skim 的操作很简单。文章开头的链接里已经有效果演示了。常用的也就是输入子序列去过滤,然后再输入一个进一步过滤,直到看到想要的。使用 ! 前缀可以反向过滤,^ 匹配开头 $ 匹配结尾。Ctrl-p/n 来上下移动。提示符那里也支持通常的行编辑。

到现在为止,我自行实现了 sk-cd、sk-search-history、sk-vim-mru 三个功能。另外使用了自带的 completion.zsh 文件。由于各种不满意,没有使用自带的 key-bindings.zsh 文件(也就包含 cd 和历史命令搜索功能啦)。

completion.zsh 里目前有两个功能。kill 时通过 ps 补全进程 pid。这个想法很好,以后我可能专门做一个通用的方便 strace 啊 lsof 啊 gdb 啊之类的用。

另一个是遇到两个星号(**)时按 Tab 补全,查找并替换成当前目录下的文件。

我实现的 sk-cd 是从 autojump 取目录列表,然后喂给 skim。于是就成了交互式的 autojump~这是一个我很需要的功能。原来我都是通过 Tab 补全列出可能的项,然后再 Tab 过去选的,有些慢也有些麻烦。

sk-search-history 就是在历史命令里找东西。因为遇到特殊字符时无法正确地加载预览,我并没有开启预览功能。反正找到的命令只会放在命令行上,并不会自动执行的,选错了可以及时取消。

以上两个功能分别绑定到 Alt-s d 和 Alt-s r 上。我使用 Alt-s 作为 skim 快捷键的开头,以便保留 zsh 原本的快捷键,避免冲突,特别是以后可能会有更多功能被加入。我在 Vim 里,也是类似的做法,Alt-q 是 easymotion 的开头快捷键,Alt-d 是 denite 的开头快捷键。

sk-vim-mru 仅仅是个命令了。使用的数据是 mru.vim 的历史记录文件。然后做了两个函数:vim-mru 使用 Vim 编辑文件,vv-mru 使用我自己的 vv 命令在已有的 gVim 里编辑文件。

我做的版本和 skim 自带版本,最大的差别在于,我的版本会尽量使用全部的窗口空间,而 skim 自带的总是会使用 40% 窗口高度。(所以我有个函数用来获取当前光标位置,有需要的可以自己拿去用。)

如果你想用我的配置,可以 wget https://github.com/lilydjwg/dotzsh/raw/master/plugins/sk-tools.zsh 回去,然后 source 一下就好。有需要的话(比如数据来源、键绑定等)可以自行修改。


2018年09月17日更新:我尝试了一下把 sk-search-history 映射到 Ctrl-r 上,然后很快就放弃了。因为 skim 的结果是不可预测的,而默认的 Ctrl-r 的结果是完全可预测的(只要还记得;当然你不能开(那个让我在服务器上误杀过进程的)实时历史共享)。可预测性对提高效率非常关键,因为你不需要中断思维,停下来等结果。

by 依云 at September 15, 2018 05:20 PM

September 12, 2018

quininer kel

the-grail-of-forward-secrecy

0-RTT and Forward Secrecy

Tue Sep 11 00:43:19 2018

前向保密是一個已經被人熟知的安全特性。 基於密鑰交換的前向安全廣泛存在於各種密碼協議之中,例如 TLS、Signal Protocol、WireGuard。

Session based

一般我們所說的前向保密方案是基於會話的,每次會話通過握手產生一個獨立的會話密鑰。 會話結束之後銷毀該會話密鑰便可保證前向保密。

但基於會話的前向保密並不適用於所有場景, 很多情況下我們沒有握手的條件、或者通信開銷非常之大。 例如 Email、IoTInternet of Things。

“如何在這些情況下保證前向保密”成爲了一個聖盃級的公開問題, 數十年來衆多密碼學家爲此付出心力。

幸運的是,這並非是無可能的。

Interval based

基於時間段的前向保密方案聽起來不太優雅,但非常實用。

基本思路是將密鑰分成不同的時間段。 在某個時間段過去之後,銷毀該時間段對應的私鑰,從而達到前向保密。

Weekend scheme

我相信這個方案在歷史上被設計過不止一次,最後一次見到它是在 openpgp 討論中 1。 我不清楚它的名字,本文將之稱爲週末方案。

用戶每逢週末更換一次自己的密鑰,並將新的公鑰公佈在網絡上。 其他用戶加密時必須檢索對方的最新公鑰。

這個方案很簡單,但缺點也很明顯

  • 要求其他用戶加密時有檢索最新公鑰的能力
  • 多設備不友好

每次都要更新公鑰實在是太麻煩了,那可不可以再給力點?

HIBE scheme

有的!我們首先通俗的介紹一下 HIBEHierarchical Identity Based Encryption2

HIBE 有一個中心的 PKGPrivate Key Generator,它可以通過 ID 產生所有用戶的私鑰。 每個用戶也能通過子用戶的 ID 產生子用戶的私鑰,自然的,子用戶不能恢復父用戶的私鑰。

其他用戶加密時只需要知道 MPKMaster Public Key 和子用戶的 ID。

我們可以基於 HIBE 構造出一個不需要更換公鑰的前向保密方案。

  1. 用戶加密時根據當時的時間產生用戶 ID,並用此進行加密。例如

    CT = enc(MPK, ["2018", "9", "10"], MSG)

  2. 用戶解密時,根據 PKG 或父用戶的私鑰產生對應 ID 的私鑰,並用其解密,例如

    SUB_SK = keygen(SK, ["2018", "9", "10"]) MSG = dec(SUB_SK, CT)

  3. 當一個時間段過去時,用戶先用 PKG 或父用戶的私鑰產生剩餘所有子用戶的私鑰,並銷毀 PKG 和父用戶的私鑰。例如

    (_, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC) = keygen_year(YEAR) delete(YEAR)

完美!這個方案完全解決了週末方案的兩個缺點, 其他用戶不需要時時檢索對方的最新公鑰,用戶自己也不需要在多個設備之間同步自己的新私鑰。

但是基於時間段的方案有一個共同的缺點,

試想一個情景,alice 在 2018年9月30號 執行加密,但由於各種原因到達 bob 手中時遲了一日。 可惜當時 bob 已經將 9月 所對應的私鑰銷毀了,所以他無法解密 alice 的密文。

這顯然不是我們想要的效果,那可不可以再給力點?

Puncture based

除了時間段這個思路之外,我們還有沒有其他實現前向保密的辦法呢?

可穿刺加密是另一種思路, 原始狀態下的私鑰包含所有信息,可以解密所有密文。 當用戶成功解密一個密文後,用戶可以從私鑰中消除(我們將之稱爲穿刺Puncture)一部分信息, 使得新私鑰不能解密該密文。

Binary Tree Encryption scheme

BTEBinary Tree Encryption3,4 是一個有趣的設計,它同樣基於 HIBE。

它相當於使用 IBE 產生一個巨大的私鑰集, 然後使用和密文對應的 tag 確定其中一個 ID 或密鑰(通過一個 Hash)。

穿刺時,通過 Hash 該 tag 來確定私鑰,然後銷毀它。

但是一個夠用的私鑰集相當大,假設一個私鑰大小爲 64b,我們期望有 2^32 個私鑰可以用, 那最終儲存這個密鑰集我們需要 274877.907 MB。

這是不現實的。

但我們可以通過 HIBE 來懶惰式的生成私鑰,這可以有效的將最壞情況下的密文尺寸降低一半。

Bloom Filter Encryption scheme

BFEBloom Filter Encryption5 是 BTE 的一個有趣變種。

它使用一個 Bloom Filter 來降低 tag 的碰撞率,代價是較快的空間使用速度。

  • 加密時,使用 IBBEIdentity Based Broadcast Encryption 將消息廣播加密 給 bloom filter 選擇出的 k 個 ID。
  • 解密時,使用 k 個 ID 中其中一個可用的 ID 進行解密,若均不可用則解密失敗。
  • 穿刺時,將這 k 個 ID 對應的私鑰銷毀。

無論如何,基於 IBE 的可穿刺加密仍有相當大的私鑰尺寸。那,可不可以再給力點?

Non-Monotonic ABE scheme

照例我們先簡單介紹一下 NM-ABENon-Monotonic Attribute based encryption6

ABE 就像 IBE,但它使用屬性Attribute 而不是 ID 來進行加密。 KPKey Policy-ABE 是指是加密時爲密文指定屬性,只有符合某個規則的私鑰可以解密。

而一般 ABE 的規則是單調的,即是說只有 And 和 Or 兩種規則。 非單調性 ABE 的有趣之處是支持 Not 規則。

有了 NM-ABE,構建可穿刺加密變得非常直觀。加密解密時和普通 ABE 一樣。 穿刺時,只需在私鑰規則中增加一條 Not(tag)7

至此,該方案的私鑰大小只會隨着穿刺次數線性增長,而不會爆炸。

Binary Tree Bloom Filter Encryption?

我們可以將 BTE 和 BFE 結合, 利用 HIBBEHierarchical Identity Based Broadcast Encryption 構造出 BTBFEBinary Tree Bloom Filter Encryption。

理論上這可以將 BFE 的私鑰尺寸降得更低,但我沒有找到合適的 HIBBE 方案實現它。

Perfect?

我們介紹了數個在限制情況下保證前向保密的加密方案,看起來似乎足夠讓人們戴着鐐銬跳舞。

如果這些方案足夠高效,是不是意味著我們再不需要握手,無延遲的 0-RTT 通信可以全面推廣呢?

很遺憾並不是,這些方案只能保證“前向保密”。

而基於會話的方案除了前向保密之外還保證了“弱後向保密”, 即在泄漏長期私鑰時,若敵手在之後沒有參與協議,那協議仍能保證之後密文的保密性。

當然,這一切在量子敵手面前都毫無意義。


  1. Clarify status of subkeys with certification use
  2. Hierarchical Identity Based Encryption
  3. Binary Tree Encryption: Constructions and Applications
  4. 0-RTT Key Exchange with Full Forward Secrecy
  5. Bloom Filter Encryption and Applications to Efficient Forward-Secret 0-RTT Key Exchange
  6. Encryption with non-monotone access structure
  7. Forward Secure Asynchronous Messaging from Puncturable Encryption

by quininer kel at September 12, 2018 09:23 AM

August 31, 2018

ヨイツの賢狼ホロ

Sailfish OS 移植中(2)- droid-hal 和根文件系统

Droid HAL,对应 HADK 文档的第七,第八和第十章 _(:з」∠)_

为新设备生成必要的模板

进入 Platform SDK (sfossdk),引入需要的环境变量(如果汝没有写进 bash_profile 或 bashrc 的话)。

接下来就是依样画葫芦啦 😂

PLATFORM_SDK $

cd $ANDROID_ROOT
mkdir rpm
cd rpm
git init
# 引入必要的 submodules (例如这里的 dhd)
git submodule add https://github.com/mer-hybris/droid-hal-device dhd
# 必要的替换成汝的手机型号和品牌
sed -e "s/@DEVICE@/shamu/" \
-e "s/@VENDOR@/moto/" \
-e "s/@DEVICE_PRETTY@/Nexus 6/" \
-e "s/@VENDOR_PRETTY@/Motorola/" \
dhd/droid-hal-@DEVICE@.spec.template > droid-hal-shamu.spec
# 然后提交到汝自己对应的 git 仓库中
# 最好提前检查一下新生成的文件中的内容
git add .
git commit -m "[dhd] Initial content"
# 如果汝偏好使用 SSH ,换成 git@github.com:myname/your_repo_name
# 例如 git@github.com:myname/droid-hal-shamu
# 以及别忘了把 myname 换成汝自己的用户名,下同……
git remote add myname https://github.com/myname/droid-hal-shamu.git
git push myname master
cd -
# 下面的其实也差不多 😂
mkdir -p hybris/droid-configs
cd hybris/droid-configs
git init
git submodule add https://github.com/mer-hybris/droid-hal-configs \
droid-configs-device
mkdir rpm
sed -e "s/@DEVICE@/shamu/" \
-e "s/@VENDOR@/moto/" \
-e "s/@DEVICE_PRETTY@/Nexus 6/" \
-e "s/@VENDOR_PRETTY@/Motorola/" \
droid-configs-device/droid-config-@DEVICE@.spec.template > \
rpm/droid-config-shamu.spec
# Please review rpm/droid-config-shamu.spec before committing!
git add .
git commit -m "[dcd] Initial content"
# Create this repository under your GitHub home
git remote add myname https://github.com/myname/droid-config-shamu.git
git push myname master
cd -
rpm/dhd/helpers/add_new_device.sh
#  On Nexus 6 the output of the last command is:
#  Creating the following nodes:
#   sparse/
#   patterns/
#   patterns/jolla-configuration-shamu.yaml
#   patterns/jolla-hw-adaptation-shamu.yaml
cd hybris/droid-configs
COMPOSITOR_CFGS=sparse/var/lib/environment/compositor
mkdir -p $COMPOSITOR_CFGS

把手机连接到电脑上,从日志输出中找到汝的触屏是哪一个设备(例如 /dev/input/event0), 然后新建一个 $COMPOSITOR_CFGS/droid-hal-device.conf :

# Config for $VENDOR/$DEVICE
EGL_PLATFORM=hwcomposer
QT_QPA_PLATFORM=hwcomposer
# 用汝获得的 /dev/input/event 替换 /dev/input/event0,还有记得这是一行
LIPSTICK_OPTIONS=-plugin evdevtouch:/dev/input/event0 -plugin evdevkeyboard:keymap=/usr/share/qt5/keymaps/droid.qmap

然后继续建立 Git 仓库:

git add .
git commit -m "[dcd] Patterns and compositor config"
git push myname master
cd -
mkdir -p hybris/droid-hal-version-shamu
cd hybris/droid-hal-version-shamu
git init
git submodule add https://github.com/mer-hybris/droid-hal-version
mkdir rpm
sed -e "s/@DEVICE@/shamu/" \
-e "s/@VENDOR@/moto/" \
-e "s/@DEVICE_PRETTY@/Nexus 6/" \
-e "s/@VENDOR_PRETTY@/Motorola/" \
droid-hal-version/droid-hal-version-@DEVICE@.spec.template > \
rpm/droid-hal-version-shamu.spec
# Please review rpm/droid-hal-version-shamu.spec before committing!
git add .
git commit -m "[dvd] Initial content"
# Create this repository under your GitHub home
git remote add myname \
https://github.com/myname/droid-hal-version-shamu.git
git push myname master

全部完成以后,别忘了修改汝自己的 manifest 文件,加上相应的仓库:

<project path="rpm/"
    name="myname/droid-hal-hammerhead" revision="master" />
<project path="hybris/droid-configs"
    name="myname/droid-config-hammerhead" revision="master" />
<project path="hybris/droid-hal-version-hammerhead"
    name="myname/droid-hal-version-hammerhead" revision="master" />

等汝的移植工作完成而且可用的时候,可以去向官方的 manifest 仓库提交一个汝的设备的 Pull Request :-)

打包 droid-hal-device

其实只有一步:

rpm/dhd/helpers/build_packages.sh

以后要是汝改了什么地方的话,记得再运行一次就 OK 啦~

如果汝遇到了 Installed (but unpackaged) file(s) found 错误的话,记下不在包中的文件, 把文件名添加到 rpm/droid-hal-$DEVICE.spec 的 %include 之前,例如:

%define straggler_files \
/init.mmi.boot.sh \
/init.mmi.touch.sh \
/init.qcom.ssr.sh \
/selinux_version \
/service_contexts \
%{nil}

然后在 droid-configs/patterns/jolla-hw-adaptation-$DEVICE.yaml 中加上 "- droid-hal-$DEVICE-detritus"。

再次打包就好。

打包 Sailfish OS 的根文件系统

生成 KickStart 文件:

rpm2cpio droid-local-repo/$DEVICE/droid-configs/droid-config-$DEVICE-ssu-kickstarts-1-1.armv7hl.rpm | cpio -idmv

HA_REPO="repo --name=adaptation-community-common-$DEVICE-@RELEASE@"
HA_DEV="repo --name=adaptation-community-$DEVICE-@RELEASE@"
KS="Jolla-@RELEASE@-$DEVICE-@ARCH@.ks"
sed \
    "/$HA_REPO/i$HA_DEV --baseurl=file:\/\/$ANDROID_ROOT\/droid-local-repo\/$DEVICE" \
    $ANDROID_ROOT/usr/share/kickstarts/$KS \
    > $KS

使用 MIC 生成安装包:

# 选择一个版本,例如写这篇文章时最新的 2.2.0.29
RELEASE=2.2.0.29
# 设置一个自定义名称,用来区分汝自己的不同版本,不过不能用 "."。
EXTRA_NAME=-my1
# 生成需要的 patterns 。
# 最后一定会抛出一个 AttributeError: "'NoneType' object has no attribute 'px_proxy_fa..
# 异常,可以安全的忽略掉。
hybris/droid-configs/droid-configs-device/helpers/process_patterns.sh
# 用 Mic 生成根文件系统安装包
sudo mic create fs --arch=$PORT_ARCH \
    --tokenmap=ARCH:$PORT_ARCH,RELEASE:$RELEASE,EXTRA_NAME:$EXTRA_NAME \
    --record-pkgs=name,url \
    --outdir=sfe-$DEVICE-$RELEASE$EXTRA_NAME \
    --pack-to=sfe-$DEVICE-$RELEASE$EXTRA_NAME.tar.bz2 \
    $ANDROID_ROOT/Jolla-@RELEASE@-$DEVICE-@ARCH@.ks

如果一切 OK 的话,汝就会在汝的 $ANDROID_ROOT 文件夹下发现一个 sfe-$DEVICE-$RELEASE$EXTRA_NAME 文件夹里面放着一个 sfe-$DEVICE-$RELEASE$EXTRA_NAME.zip ,这就是汝的根文件系统的刷机包咯~

刷入测试

进入汝手机的第三方 Recovery (例如 TWRP),把汝 hybris 对应的 LineageOS 的底包 和刚刚生成的根文件系统复制到汝的手机上并安装。或者 adb sideload 也行。

  • 如果一切都 OK 的话,汝应该能见到 Sailfish OS 的开机画面,试着完成设置看看吧~
  • 要是不行的话,在看看 HADK FAQ 找找问题, 或者上 IRC 问一下其他人吧 _(:з」∠)_

在启动早期和手机建立连接

如果手机和电脑相连以及 hybris 能成功加载的话,汝的电脑上应该会多出一个网络适配器, 和 Android 启动 USB 网络共享类似。 GNU/Linux 的话可以通过 ip 命令确认。

可以用 telnet 连接到早期启动阶段的手机:

telnet 192.168.2.15

如果连接不上,可能是 Sailfish OS 已经在加载但是显示不出界面。 这个时候 telnet 的端口是 2323。

连接上以后,可以用 devel-su 命令进入 root shell:

devel-su

然后就可以通过 dmesg 或者 journalctl 等命令查看日志啦,在调试的时候可能会派上用场。

如果反复重新启动

反复重新启动有这么几种情况:

  • 启动后立刻重启(或进入 Recovery 模式):大概是 SELinux 的问题 _(:з」∠)_

    所有基于 CyanogenMod 11 以后(Android 4.4)的移植都必须停用 SELinux。 尝试在编译内核的选项中停用 SELinux ,或者设置 CONFIG_SECURITY_SELINUX_BOOTPARAM=y , 然后在启动参数中加上 selinux=0 (启动参数通常在 $ANDROID_ROOT/device/$VENDOR//BoardConfig.mk 中的 BOARD_KERNEL_CMDLINE 中)

  • 启动后数分钟后重启:尝试停用 ofono 服务,启动时尽快通过 telnet 进入 root shell:

    ln -s /dev/null /etc/systemd/system/ofono.service

  • ……

by ホロ at August 31, 2018 04:00 PM

August 27, 2018

Lainme

在Linux上设置天河二的VPN和SSH

天河二的VPN用的是Hillstone的VPN,Windows和Mac都有客户端,但给出的Linux使用说明通常都是用命令行的VPNC,也没有配置路由的方法(否则VPN是全局的)。另外在SSH连接时也需要一些额外的设置,否则不是很好用。这里记录一下用Network Manager连接VPN和相关的配置。

VPN连接设置

先安装vpnc和nm插件

pacman -S vpnc networkmanager-vpnc

用Network Manager新建一个vpnc的VPN链接,在Identity栏设置如下:

至此应该可以连接VPN了。但默认情况下,VPN是全局的,也就是所有请求都会通过天河2,导致实际上无法上其它网址。要解决这个问题就需要设置路由。

在刚才建立的连接中切换到IPv4一栏,并设置如下:

SSH设置

由于登录节点IP会实际对应多个服务器,导致指纹校验经常失败。如果不想每次都去动known_hosts的话,可以在.ssh/config里设置如下:

Host tianhe
    HostName [登录节点IP]
    Port [登录节点端口]
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

这样就可以用

ssh tianhe

方便的直接登录了。

by lainme (lainme@undisclosed.example.com) at August 27, 2018 11:44 AM

“见鬼”的Gnome桌面冻结问题

最近去北京开会的时候,我的Archlinux突然不正常了。桌面每隔几分钟就要停止响应一会,键盘鼠标都不能动,甚是奇怪。这个系统已经挺久没更新了,之前也没法这个问题,怎么忽然就罢工了呢?Windows是没有故障的,所以硬件问题先排除了。用journalctl查了查日志,也没发现任何有价值的信息。

既然很久没更新那就先更新吧,虽然没滚挂,但问题也没解决。最开始,我感觉是显卡驱动的问题,在google上用“archlinux freeze”等关键词搜索了一番,确实找到很多症状和我很像的帖子(https://bbs.archlinux.org/viewtopic.php?id=236686),然后把里面提到的方法都试了一遍:

  • 改用Xorg登录,鼠标不怎么卡了,键盘依旧。
  • 改用LTS的内核
  • 改用旧版的驱动
  • 禁用TLP等电源管理程序
  • 禁用swap
  • 加内核参数intel_idle.max_cstat=0,1,2,都试了一遍

结果该怎么卡还是怎么卡,前前后后还花了不少时间。

最后想到有些帖子提到了无线网可能会引起问题,孤注一掷之下禁用了Networkmanager,居然奏效了……不过问题来源找到了,然而并没有解决方案。因为我的无线网卡是intel的,就对着iwlwifi各种折腾,当然都是徒劳的。当时想着这简直是要治我的网瘾啊……

就在我准备放弃治疗的时候,忽然发现Gnome的通知区域每隔一会就提示Gmail收信失败,非常的可疑,于是用gnome tweak tool把“gnome email notifications”插件给关掉了,再打开网络,世界终于清净了。

这样看来是由于开会地点的网络不好,代理可能也有点慢,导致插件频繁查信失败引起的卡机。但是dropbox等同样连不上却不会卡,是插件自身的问题么?于是我跑去插件的github主页看了看,发现它前段时间有个提交——“ Removed synchronous calls to prevent gnome shell from freezing up. ”。真相大白。

by lainme (lainme@undisclosed.example.com) at August 27, 2018 08:12 AM

August 26, 2018

Felix Yan

Arch Linux 社区中不成文的约定(一)

作为一个年轻和小众的社区(咳咳),Arch Linux 社区中有着许多不成文的约定。本文希望通过稍稍讲解一二,来消除一些新人们常常感到的困惑。由于预感到日后可能还会有更多问题,暂且认为这是系列里的第一篇 😛

  • 修理“坏”包和提醒更新

仓库里一般的包可能有一个或多个维护者,也可能没有维护者,成为“孤儿”。如果坏掉或者过期的包是一个孤儿,申请从仓库里删掉是更有效的方法,这样它可以在 AUR 找到新的主人。发邮件到 aur-general 解释一下情况,并表明自己或者别人想维护它,一般都会很快得到解决。

如果“坏”包有维护者,但他太忙了呢?这种情况下,这个包很可能已经在 Bug Tracker 里泥足深陷。这种时候可以通过帮维护者一个小忙的方式来促进问题的解决。如果有人找到了上游 Bug Report,并且上游已经修复提供了 patch 的话,可以考虑把 patch 贴到 Arch 的 Bug Tracker;如果这件事已经有人做了,可以修改 PKGBUILD 打上 patch,然后把改好的 PKGBUILD 贴上去;如果连 PKGBUILD 都有人准备好了,而且过去了一段时间的话,可以考虑把这份准备好的 srcpkg 或者 diff 直接发邮件给维护者,附上简短的感谢和一个笑脸 🙂

同样的道理,如果一个过期包已经被标记过期很久了,也可以准备一个新版的 PKGBUILD 发邮件给维护者。

  • 提供旧版软件包

因为懒得迁移各种各样的原因,你可能希望某些软件包的新旧版本同时提供。在 Arch 的实践中,这种情况被尽量避免了。把无法迁移的古老软件删掉还是提供一个旧版库让古老的软件能用,一定程度上取决于维护者对这个古老的软件有多坚持。

另一个考虑的因素是上游如何看待新旧版本。有的软件新版发布后,旧版就不再维护了,这种情况下 Arch 通常尽力避免成为新的上游。而有的上游则同时维护多个版本,Arch 这边根据其他软件的依赖情况,可能会有选择性地同时维护几个。

  • 第三方 patch 能不能加上

Arch 对 patch 的态度比较保守,在规则里写的是一般只有修复编译和主要功能的上游已经接受的 patch 会考虑。在实践中,有些时候没有这么严格,比如开发者自己写的 patch 一边提交给上游,还没等答复,一边就加到了包里。因为 Arch 打包并没有 Review 过程,实际上加了什么 patch、靠不靠谱就全靠开发者自己掂量了。

一般来说,被上游明确拒绝的功能性 patch 是不怎么会考虑的。修复一个特定问题,尤其是影响比较大的问题的上游有点意见的 patch 有可能会被考虑。修复一个安全问题的 patch 经常会被接受,尤其是已经拿到 CVE 号的。

  • 使用上游二进制 vs 从源码编译

一般常识是发行版们倾向于从源码编译一个软件,理由包括确保二进制真的来自这份源码、尽量使用系统中的动态链接库而不是静态编译一份以满足安全更新和体积方面的考虑、进行必要的修改等。

但是因为太懒一些问题,即使是在 Arch 官方仓库里也直接重新打包了一些上游的二进制。这些问题包括:源代码不开放(nvidia、flash 等)、编译过程中会去下载东西,而且不容易解决(dart、一些 java 软件等)。

  • 文档是否打包

现在互联网十分发达,开发者们查询文档通常都是直接上网搜索。在这样的背景下,是否打包软件包的文档(通常都是开发文档)成为了一个问题。早些时候的包开启文档较多,如果太占体积还会考虑拆一个单独的文档包。后来才增加的新包则很多都没有启用文档,除非被用户要求提供文档才考虑这件事。

by Felix Yan at August 26, 2018 05:33 PM

August 07, 2018

ヨイツの賢狼ホロ

和 Android 玩耍的那些日子

也可以说是 root Android 的过程 ……

最近 Android Pie 发布了,于是随便写写杂感 (雾)

Android 2.x :蛮荒时代和 ZergRush

(记得那是咱自己的第一部 Android 手机, Motorola Defy XT535) 拿来的时候还是 Android 2.3,当然是不能用现在的审美去看 Gingerbread 的界面啦……(不过 2.3 时期的 TouchWiz 是真的比 Motorola 那几乎没怎么改 的漂亮,虽然现在……)至于当时怎么想到去 root 了呢,动机大概是 想不起来了,大概只是为了移除某些系统应用而已 😂 。2.x 时期最著名的 大概就是 ZergRush 漏洞了,通吃大多数 2.2-2.3 版本……

后记:那 XT535 后来收到了 4.0.4 更新,然后又坚持了两年,最后掉了……

Android 3.x :没用过

于是跳过 😂

Android 4.x:CyanogenMod,CWM,CF-Auto-Root,Superuser,SuperSU 和 Xposed

和 XT535 同时入手的其实还有 Samsung Galaxy Tab2,当时那上面已经是 Android 4.0.3 了。虽然三星魔改的很厉害,但是乍一看就和旁边的 2.3 不一样不是? 😂

以及到了 4.0 时代, ZergRush 就不能用咯。当时咱还处于一种啥都不懂的状态 (当然现在也只是懂些皮毛而已啦),上网搜索到了一个叫做 CF-Auto-Root 的家伙。 ( https://autoroot.chainfire.eu/

用过三星手机的应该都知道,人家是没有 fastboot 模式的,但是有个 Download 模式 (因为早些时候的 Download 模式上有个施工造型的 Android 机器人,所以有时有人 也把它叫做挖煤模式)。然后需要用到一个叫做 odin 的工具刷机。

大概长这样

当时 root 手机的方法,基本上都是先把一个称作 Recovery 的东西放在手机上, 然后利用一个小 zip 包把 su 可执行文件放在对应的位置上,再安装一个应用来控制 root 权限就 OK 啦~

其实汝的手机上是有一个 Recovery 的,重置或者系统更新的时候会需要。不过 官方的 Recovery 通常功能不多而且会检查更新的签名,所以就需要刷入一个第三方 的 Recovery 来实现更多功能。比较著名的第三方 Recovery 的话,以前有 ClockWorkMod (简称 CWM),现在有 Team Win Recovery Project(简称 TWRP)

而 CF-Auto-Root 把这些过程简化到一个供 odin 刷入的 tar 包中,于是咱当时就用它 root 了。

至于 Root 权限管理应用的话,当时比较流行的是 Superuser (忘了是谁开发的了) 和 SuperSU (Chainfire,也是 CF-Auto-Root 的作者,虽然已经是前开发者了)。两个当时都很优秀 (虽然现在都凉了)

然后有一次咱尝试系统加密玩脱了,系统进不去了,于是死马当活马医的装了个 CyanogenMod 进去, 打开了新世界的大门(雾)。

以至于现在咱用不习惯任何非类原生 Android 界面了 😂

大概是 4.4 时期,有了个叫做 Xposed 的东西。大概是一个通用的系统框架, 可以实现上至系统界面调节下到应用权限控制等一系列千奇百怪的功能。咱当时也 装了不少的模块用了一阵子。

后记:那个 Galaxy Tab 2 一直坚持到 CyanogenMod 13.0 ( Android 6.0.1),性能是真的不行了, 于是就闲置在家里,然后屏幕外面的玻璃被压碎了……

Android 5.x - 6.0 时期:没啥特别的

大概是 15 年的时候买了台 Galaxy A8 ,然后兴致勃勃的用以前的方法 root 的时候, 遇到了一个叫做 KNOX 的神奇大坑。

4.3 以前的三星手机刷入自定义操作系统以后,启动时会显示一个感叹号三角形, Download 模式里也会记录刷入了自定义操作系统。不过当时可以很轻松的去掉 (例如用 Triangle Away)。后来有了 KNOX 以后,修改操作系统的行为会导致 KNOX WARRANTY VOID 变成 0x1 从而失去保修。以及某些功能将无法使用(例如 My Knox 和后来的 S Health,Samsung Pay 等等),而且据说因为这是个硬件 设计于是不可逆……

自此咱就再也没买过新的三星 Android 手机……

如果不考虑那些的话,还有一个问题,修改过系统分区的话,就不能收到厂商的系统更新了。 于是不动 /system 的 system-less root 方法应运而生,典型的方法是修改内核映像(boot.img)……

以及那时候自从 ART 代替 Dalvik 以后, Xposed 适配新版本的速度慢了下来。

Android 7.x - 8.x 时期:SafetyNet,Magisk ,LineageOS 和 Project Treble

7.0 一上来就是猛料,比如所谓的 SafetyNet ,反正咱现在也没搞清楚这是啥…… 以及不知道是不是 7.0 的 Xposed 鸽了太久的原因, 有人写出了 Magisk。 和 Xposed 大概具有类似的功能,但是不动系统分区,于是接收 OTA 更新能稍微容易一点…… 以及介于 Superuser 年久失修和 Chainfire 宣布不再参与 SuperSU 开发以后, Magisk 还有一个 Root 权限管理程序。总之也有不少人用啦~

这个时期也出现了很多不必须 root 权限的系统管理工具,例如 Brevent 和 AppOps, 它们都是通过 adb 启动一个外部脚本来协助完成某些任务,给了不 root 或没法 root 手机的人一些选择。

以及那年商业化失败的 CyanogenMod 宣布关闭,不过过了一阵子以后又有一群有志之士 成立了 LineageOS 社区,目前正在活跃开发中。

Oreo 时有了 Project Treble 和 A/B 无缝系统更新,前者把 Android 系统的部件和 OEM 定制的部分分开,声称能使 OEM 适配最新版 Android 系统的速度提升。后者可以做到更新时可以 继续使用设备,而且不容易坏(笑)。

对于喜欢搞机的开发者们呢?看起来 Project Treble 使第三方 ROM 移植起来稍微容易了一些, 比如汝可以在 xda 上找到 Treble 兼容的 AOSP 和 LineageOS 的通用系统映像(GSI),然后 刷入进汝支持 Treble 的手机上,大多数的功能应该都能运作。 不过 A/B 无缝更新可能就是个 美丽的麻烦了,因为没有了单独的 Recovery 分区,所以给这种手机适配 TWRP 的进度似乎慢了下来。

Android P ?

咱现在用的是 Nokia 7 plus ,当时有官方的 Android P Beta 支持,于是咱就这么用了下去。 除了前几个 DP 每次都要全新安装以外其实海星 😂 。 Magisk 在 Android P 上也比较稳,原来 不少需要魔改的功能也或多或少的集成进系统里了。然而以前那个愉快的折腾的日子似乎回不来了呢……

PS: #when_I_buy_a_phone

如果咱要换手机的话:

  • 能解 Bootloader 锁的通常很快都会有 LineageOS 适配,优先考虑。
  • 上面一条不满足的话,如果是类原生系统的体验也可以考虑。
  • 最好不是异形屏幕(就是所谓的刘海啥的),屏幕比例最好是普通的 16:9/16:10 一类。
  • 有物理键盘最好。

于是现在(这篇文章完成的时候)这么下来,貌似就不剩几个了吧 😂

by ホロ at August 07, 2018 04:00 PM

August 04, 2018

百合仙子

XZ2C: 没有 root 的日子(也还过得去)

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

现在手机两三年不换新,日子就没法过了!所以我明知没有 root 还是买了 Sony Xperia XZ2 Compact(XZ2C),用于替换之前使用的 Z5C。

嗯,还是 Compact 版本。尤其是尝试在地铁上操作小米 Note 3,结果发现为了避免自己跌倒或者手机被摔地上,我不得不使用嘴唇来点击部分区域的时候,我决定绝不放弃能够安稳地握紧的 Compact 版本了。

啊,我知道有单手模式的!XZ2C 底部那三个虚拟键的位置,向左或右滑,就可以启动了,很方便!然而,最需要此功能的小米 Note 3,使用的是实体触摸按键,中间还是个凹下去的指纹识别,我很难成功启动单手模式。而且由于手机过大,这个动作操作的时候,手只能握住手机的下半部分,重心还是悬在外边,列车适时地颠一下说不定就会脱手而出了。

XZ2C 比 Z5C 重了很多,背面还是弧面的,手感意外地很棒呢。指纹识别在背部,拿在手里的时候倒是很好按,也不会有小米那握不稳的问题。不过你们懂的,放桌面上的时候,不拿起来就按不了。而且双击唤醒屏幕被禁用了(除非已抬起手机,屏幕已显示时间),密码解锁也并不方便。双击唤醒大概还是可以启用的吧,不过 Z5C 拿在手里走路的时候,屏幕经常被会意外点亮不说,还会一不小心就把锁屏时钟给换了样式。所以就不用啦。

这指纹解锁速度比起 Z5C 的侧面那个小的,快了非常多。而且可以配上很好看动画效果啊!就是 Sony 宣传片里的那种,不过它竟然不仅仅是在主屏幕上呈现,在任何应用打开的时候也能出现呢。

哦还有,XZ2C 充电、看视频时都不会像 Z5C 那样烫了~

系统是 Android 8 Oreo。最棒的莫过于通知管理了!之前我一直希望某些不重要的通知出现,但是不要发出声音(比如微信的「加好友」通知),但是只能寄希望于应用本身提供这种设置。现在不用啦,系统通知管理可以直接设置了。而且应用还可以给通知分门别类,然后用户按需要给不同类别的通知不同的设置(比如 Telegram 就能精确到会话)。在通知出现的时候,长按选择「所有类别」打开设置的时候,对应的类别也会闪动一下,不用用户去猜这是哪个类别的通知。

其次是应用图标的长按功能,可以查应用信息,可以访问应用提供的快捷入口,也可以把这些入口添加到主屏幕,或者添加该应用的小部件。而且应用信息里可以直接打开 Google Play 了!我之前都只好去搜索应用名的。在 YouTube 上看到有人直接把应用图标拖到一个控件上就能打开商店,然而我并不知道那是什么应用。

还有很重要的一点是:运行很流畅!不只是我以前新手机刚到手的那种流畅,而且装个应用一两秒、开机启动完了我还没反应过来,超出了预期好多!当然并不是说开机刷一下子就完了,而是我没想到 Android 的开机能有这么快。

啊,最后进入正题:没有 root,只能找替代了。

首先是权限管理。Android O 的权限管理已经强大了不少,而且我已经把大部分国内应用转移到小米上了,所以还好吧。

时间显示秒。这个功能,在「系统界面调谐器」里已经有选项了。长按下拉通知出现的齿轮图标,直接它转动起来,然后就可以在「设置」里看到「系统界面调谐器」了。

互联网访问。放弃修补好的 fqrouter,发现现在的主流软件其实也挺不错的。只是偶尔需要手动切换节点了。另外就是 SSRR 这个东西,连接上的时候如果切换节点,有大概率导致网络故障(DNS 解析异常等)。需要重启手机才可解决。

绿色守护。被黑阈取代了。但我发现其实需要黑阈掉的应用也不多。我目前添加到黑阈名单里的有微信、彩云天气、企业微信、Inoreader、形色、高德地图等,基本上都是国产应用。微信一大堆服务在后台跑着,虽然支持 FCM(GCM 升级版),被黑阈干掉之后会收不到新消息(而 Telegram 和 Twitter 什么的好像都能)。

Wi-Fi adb。这个其实开机后接 USB 线,adb tcpip 5555 一下,就可以一直通过网络连接了。黑阈等需要通过 adb 执行命令的应用,也可以自行调用。

「去你大爷的内置浏览器」。现在火狐支持 Custom Tabs 了呢,所以大部分应用都能够调用火狐了。虽然 Custom Tabs 里是不加载扩展的,不过再选择在火狐中打开就可以了,大部分内容都缓存了,再加载一遍也是挺快的。Inoreader 有「webview」、「chrome tab」和「外置浏览器」三种方案,其中「chrome tab」其实就是「Custome Tabs」。Google 自家的大部分应用也会使用「Custom Tabs」,除了「Google 搜索」仍然坚持调用 Chrome,不过它可以设置为在外置浏览器中打开。「新闻与天气」也需要设置为在外置浏览器中打开,不然因为没加载扩展,会有大量广告辣眼睛的。微信当然是无解的,只能在需要时浪费些流量和时间手动选择在浏览器里再开一次了。

五笔输入法。这个之所以和 root 权限有关,是因为之前我都是拿 XPrivacy 禁用输入法的联网能力,所以什么百度啊触宝啊,我都能接受。现在没法断它网了,我自然是不会再用不开源又非系统自带的输入法了,尤其是触宝这种,一联网立马弹出好几个广告的。一开始找到叫「五笔输入法」的试验品。功能很简洁,但不愧是试验品,不能输入中文标点也就算了,一次输入英文还不能超过四个字母……然后想起 trime——rime 在 Android 平台上的版本。使用感受是:我从未经历过如此简单的码表导入!把我的 fcitx 码表导出,然后一行命令调整一下格式就可以了!然后把码表和五笔输入方案推到内部存储设备上,「部署」一下,我终于可以在手机上使用我自己的码表了!

ssh、备份和调试。这个没办法。通过 termux 能很方便地启动个 sshd,但是权限很有限,比如只能只读访问外置 SD 卡。所以我通过 adb 起了一个 dropbear 来同步这些内容。系统分区没办法访问,只能依靠 Google 和 Sony 的在线备份功能了。

啊对了,Sony 的「Xperia 换机助手」真是垃圾啊。首先,很多应用不能带数据迁移。其次,我这里一次传输只能传一项内容!不然就会出现连接错误。好不容易在论坛上找到的方案,一次只传少量数据,所以短信和通讯录什么的都可以过来,小一些的应用也能过来。大的应用就没办法了。

还有些小功能。通话振动。这也是个 Xposed 模块,就是电话接通的时候振动一下。属于锦上添花的功能,没了就没了吧……还有 Xposed Torch 也是。不能长按音量键开手电筒,那就划开通知点按钮好了。微X模块,很好用,但也不是非要不可。

整理下来,因为没有 root 而失去的功能并不是很多,最严重的是没有完整、增量的备份了。其它的,相对于运行流畅所带来的体验提升,其实并没有那么重要。这次我真的是换了手机才知道旧手机已经全面卡顿了……

by 依云 at August 04, 2018 11:37 AM