Recent Posts

Liu Yuyang's avatar

I'm back again

After nearly three years without posting here, I'm back again.
IceHoney Blog's avatar

GIthub如何省略每次输入验证信息

项目开发中经常会遇到CI自动拉取Github库的情况,我们个人使用的时候会手动输入账户密码信息,但是针对CI来说,我们一般会把敏感的认证信息放在环境变量里。所以针对认证信息的自动输入,需要做一些处理。

环境变量自动替换

针对 Travis CI,我们一般把认证信息放在环境变量里,所以在执行clone其他repo的时候,可以先设置认证信息。

git config --global url."https://${CI_USER_NAME}:${CI_USER_TOKEN}@github.com/".insteadOf "https://github.com/"'

这样设置的话,会自动替换git clone的网址。

URL里面写入认证信息

有时候需要以另外一个身份进行clone repo的时候,会直接在repo的URL前面加上认证信息。

git clone https://${USER_NAME}:${USER_TOKEN}@github.com/{username}/{repo}

这样可以很方便的clone信息,但是认证信息会存在当前库的git config文件里,有泄漏的风险。

netrc设置

netr文件用于存储网站的认证信息,一般位置在~/.netrc。格式是:

machine github.com login username password xxxxxxx

总结

总共有这么三种省略认证信息的方式,根据实际情况选择自己方便的一种认证方式即可。

参考:

GitHubでユーザ名・パスワード省略

's avatar

大侦探皮卡丘 - 中文外挂字幕

第一版的翻译,有些地方没有仔细翻译。很多地方选择“意译”而非原句翻译。

之前找到过一个版本的字幕,竟然能把 "Hello" 听成 “Halo” 然后翻成“光晕”,也是很硬核。只好自己动手。

英文字幕从 OpenSubtitles 找了个质量更好的版本,基本上都听对了。把这个校对了后做的翻译。

片源是韩版,所以在原来有韩文的地方强行盖住了 hh;不过可能有一两个遗漏。

用不同的颜色标注了人名、地名、宝可梦名、叫声和皮卡丘的发言,可能有所遗漏,希望诸位能喜欢。

译名(人名、地名、宝可梦名)则是从神奇宝贝百科里找的,免得闹笑话。

字幕仅供学习交流之用,禁止用于商业用途。

论坛讨论:https://bbs.jixun.moe/discussion/9/


第一版字幕 (粗翻/无校对):Yandex

(最新) 第二版字幕 (粗校一遍):Yandex | 射手网 (伪)

's avatar

彻底关闭网易云音乐反代服务

因为失去了维护的兴趣,决定关闭。

现在主要在 Youtube 听歌,也懒得去下载了。

反代列表应该会留着,不过对应的法国服务器以及 pac 文件都删掉了。

感谢这段时间大家提供的服务器(当然,很多到现在也已经下线了):

以及:如果有需要解锁版权限制,也许可以参考 Unblock Youku 项目。


更新:

如果对网易云音乐反代有需求,可以参考 acgotaku/NetEaseMusicWorld 这个项目 (感谢 fireattack 提供)。

Kouga's avatar

从 Ghost 0.x 升级到 2.x 的正确姿势

今天花费了一整天在这上面,终于成功了喵!趁着还没遗忘先整理一下正确的升级姿势供参考喵~

系统准备

注意!坑最大的竟然在这里喵!如果你的系统缺少一些组件会导致整个流程非常折腾喵……以下使用 Ubuntu 18.04 系统作为基准喵~

  • 安装必要软件包 apt install sudo build-essential curl (一些VPS登录就是 root 但是偏偏没 sudo 包……
  • 创建 Ghost 安装/维护账户:
sudo adduser {username}
sudo usermod -aG sudo {username}
sudo su {username}
  • 安装 NVM ,这一步很关键,因为 Ghost 的奇葩设计导致它只能在特定版本运行……
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

升迁流程

  • 使用 NVM 安装 node 6.9.x 版本,nvm install v6.9.5 (Ghost 0.x 只能在该版本下运行

  • 启动 Ghost 0.x node index.js

  • 进入后台管理页面,在 Lab 里导出(Export) 全站 json ,在 Design 里下载主题 Theme

    当然你如果用的官方主题并且只是修改过 Disqus 的话,主题完全可以不用下载,直接去官网下载最新主题并插入修改的代码即可。

  • 做完备份后 Ctrl + C 停掉 Ghost 0.x 版本

  • 新建一个 ghost-xxx 目录,准备安装 Ghost 1.x 版本

    这里才是重点问题所在,Ghost 只能按照 0.x -> 1.x -> 2.x 的顺序升级,而 1.x 和 2.x 依赖的 node 版本竟然不一致(扶额

nvm install lts/carbon
npm i -g ghost-cli@latest
cd ghost-xxx
ghost install --v1 # --db=sqlite3 #如果使用 sqlite 数据库
vim config.production.json
  • 在开启的 vim 中仔细修改 config, 否则各种作死起不来……而且不兼容之前的 config.js 配置……我的配置供参考(密码密钥什么的是没有的喵~ :
{
  "url": "https://kouga.us",
  "server": {
    "socket": {
      "path": "./content/注意如果用 Linux socket,则路径必须在 content 下面否则权限错误",
      "permissions": "0666"
    }
  },
  "database": {
    "client": "sqlite3",
    "connection": {
      "filename": "./content/??????"
    }
  },
  "mail": {
    "transport": "SMTP",
    "options": {
      "service": "???",
      "auth": {
        "user": "???@???.???",
        "pass": "????????????????????????????????"
      }
    }
  },
  "logging": {
    "transports": [
      "file",
      "stdout"
    ]
  },
  "process": "systemd",
  "paths": {
    "contentPath": "升级的时候要注意这个绝对路径!"
  },
  "bootstrap-socket": {
    "port": ???,
    "host": "localhost"
  }
}
  • 使用 ghost run 尝试运行,如果成功,直接去站点后台 /ghost 路径完成初始化向导

  • 初始化完成后,直接在管理页点 Lab -> Import File -> Import ,等待完成

    这一步可能会出现大量警告,注意看警告都是哪些 Post,可能要用 vs code 一类能编辑大文件的工具来修正对应的 json 错误……(扶额),但是其中关于 duplicate content/theme 可以忽略,因为本来就导不进来

  • 导入完成后去 Posts 里看看文章是否正常,如果 OK 则再次进入 Lab 进行一次导出(避免后续升级失败再来一次 v0.x -> v1.x 数据转换……

  • 做完导出后 Ctrl + C 停掉 Ghost 1.x 版本,准备升迁到 Ghost 2.x

nvm install lts/dubnium
npm i -g ghost-cli@latest # yesterday once more
cd ghost-xxx
ghost update # 心惊胆颤的等它完成
ghost run
  • 在新启动的 Ghost 2.x 后台 /ghost/ 下登录,看看 Post 是否还在,主站现在可能是个 500 状态,因为主题还没安装;
  • 进入 Design 重新上传并激活主题
  • 进入 Lab 关掉旧API兼容等等不安全开关
  • 一切就绪后可以 nvm uninstall {version} 清理一下前面安装的多余 node 版本,并且 ghost brust 清理一下 yarn cache.

好,重新开始写作喵!

Phoenix Nemo's avatar

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

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

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

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

论点:架构的改动

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

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

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

ホロ's avatar

各自开始的新生活

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

结束了。

布偶君 <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))
  • 从公司收到台新笔记本,然后发现手边的内存装不上去只好现买 😂
  • 说不定有机会……?
  • 就这样。
's avatar

QMC 解码 (源代码已放出)

使用方法:
  qmc-decode <输入路径> <输出路径>

程序不会判断文件是否有效,或者原本的后缀名。

已知后缀名对应关系:
  qmc0 -> mp3
  qmc3 -> mp3
  qmcflac -> flac

用 C 改写了一遍,然后用 cygwin gcc 编译,应该支持在 xp 下运行。

不过 64 位的检查宏好像用不了?不过也无关紧要了。

项目已在 GitHub 开源:JixunMoe/qmc-decode

最新版下载:GitHub

青色旋律's avatar

服务故障……

由于青色旋律的一些疏忽,导致博客有一段时间无法访问。现在已经修复……

至于何时恢复更新……

咕,咕咕咕?

h404bi's avatar

35 年后,竹内玛莉亚的《Plastic Love》有了官方 MV

在 2018 年 YouTube 上引起广泛关注、病毒式传播的歌曲,竹内玛莉亚(竹内まりや)的 Plastic Love,在其发布的 35 年后,“意外地”拥有了它的官方 MV。受蒸汽波等亚文化热 度持续存在的影响,上世纪 80 年代的日本 City Pop 音乐正在当下焕发出新的魅力。
's avatar

宿舍用小型 UPS 电源与新台灯

去年 11 月,我购买了一部二手的联想手机,把自己的电信米粉卡塞了进去,用来运行 Telegram SMS 和开热点。这部手机其实一切都好,但是有个问题:电池不耐用。因为我们会定时熄灯,导致手机并不能 24 小时充电,因此:

  • 如果一直开热点,第二天就没电了。
  • 如果按需开热点可以解决,但这部手机开热点的过程很麻烦,需要进入多级菜单。

我其实还考虑过使用充电宝,但是:

  • 我的品胜充电宝,如果重新插入电源,那么充电过程就会中止,必须手工再启动一次。
  • 我的紫米充电宝,尽管可以即插即用,但是如果在断电的情况下手机充满电,那么就会自动停止充电。
  • 我的 Anker 充电宝,容量太小了(只有 5000 毫安)。

虽然我理解这些充电宝的设计是有道理的,但显然不能满足我的需求。几个月以后,忍无可忍的我决定试试传说中的那种适合宿舍用路由器的 UPS。

几天以后,UPS 到了。

我选购的这款 UPS 可同时提供 USB、5V 和 9V / 12V 输出(可以通过开关切换 9V / 12V);最大输出电流为 2A(所有端口总和)。

同时,它使用 DC 输入,非常节约空间。

我把它接上了我的手机,让这部 UPS 为我的手机持续供电。效果还是不错的:我同时开着 Telegram SMS、代理软件和热点,也不用担心手机中途断电啦。


不久以后,我们团队在一个省级比赛获得了一等奖,每个人都得到了这样的奖品:飞利浦台灯。

因为这部台灯使用 12V 输入,功耗很低,我便把它接入了我的 UPS。这样,即使熄灯也可以使用啦。

⇧ 旧的『宿舍神灯』。

⇧ 新的飞利浦台灯。从我的实际感觉看,光线还是比那部『宿舍神灯』要舒服的,而且还有四档调光,非常灵活。

总之,很开心获得这么一套装备升级。我可以变得更懒惰了!

20190612 更新:一加 3T

我的联想电池鼓包了,连盖子都盖不上了。考虑到这部联想的坑爹之处,我买了一部二手一加 3T 作为 Telegram SMS 服务器使用。

目前来看,它的电池并不是很坑爹,所以只需要用普通的 2A 电源定时充电即可。

于是这 UPS 的供电目标就只剩下那个台灯了。不过不知道未来还会发生什么…… 😅

's avatar

自动更新 frps/frpc

自行根据需要修改,比如 架构(linux_amd64)、安装路径(PREFIX, 默认 /usr/local[/bin])。

#!/usr/bin/env bash

# FRP updater
# MIT License - Jixun<https://jixun.moe>

[ -z "${PREFIX}" ] && PREFIX=/usr/local
[ -z "${SUDO}" ] && [ "${NO_SUDO}" != "Y" ] && which sudo >/dev/null 2>&1 && SUDO=sudo

VER=$(${PREFIX}/bin/frpc -v)

RELEASE_URL="https://api.github.com/repos/fatedier/frp/releases/latest"
TMP_NAME=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
TMP_DIR="/tmp/frp_${TMP_NAME}"

mkdir -p "${TMP_DIR}"
pushd "${TMP_DIR}" >/dev/null

DL_URL=$(curl -s ${RELEASE_URL} | grep linux_amd64 | grep browser_download_url | cut -d '"' -f 4)

if (echo ${DL_URL} | grep ${VER}) >/dev/null 2>&1; then
    echo already latest version!
else
    wget ${DL_URL} -O frp.tar.gz
    tar zxvf frp.tar.gz
    cd frp_*

    $SUDO cp -f "frpc" "${PREFIX}/bin/"
    $SUDO cp -f "frps" "${PREFIX}/bin/"

    CUR_VER=$(${PREFIX}/bin/frpc -v)
    echo "Update FRP Complete (${VER} -> ${CUR_VER})!"
fi

popd >/dev/null

rm -rf "${TMP_DIR}"
Phoenix Nemo's avatar

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

's avatar

开了个论坛

开了个论坛,不过现在还什么都没有。

看会不会有人来,不过也不知道有什么好讨论的就是…

https://bbs.jixun.moe/

一些不成熟的东西可能会在这里发个预告然后链接到论坛,等稳定后在这边转发吧?

h404bi's avatar

利用 CSS 媒体查询让网页配色跟随 macOS 深色模式

苹果公司的操作系统 macOS 从 10.14 Mojave 版本开始,为用户提供了深色模式的可选外观。用户可以在系统中的通用设置里选择启用深色模式,整个系统的界面会全局变为暗色调。对于夜间使用场景而言,深色模式的界面可能会显得更加友好,也更能让用户集中注意力。

Office 365 Dark Mode (Twitter @derek_snook)

利用苹果公司提供的接口,各类原生桌面应用程序都开始陆续支持深色模式,可根据 macOS 用户的系统设置进行换肤,比如 Google Chrome、Microsoft Office 等。

但对于 Web 应用而言,似乎还没有什么讨论。好消息是 CSS 的媒体查询(media queries)新增加了一个叫做 prefers-color-scheme 的媒体特征,开发者可以通过该设置特征,让网站的配色随着 macOS 系统的界面外观色调改变而改变。

/* 常规浅色模式下的网页背景颜色及文本颜色 */
body {
  background: #fff;
  color: #222;
}

/* 深色模式下的网页背景颜色及文本颜色 */
@media (prefers-color-scheme: dark) {
  body {
    background-color: #222;
    color: #ddd;
  }
}

prefers-color-scheme 支持三个值,分别是 no-preferencelight、以及 dark,对应是“无指定”、“浅色主题”以及“深色主题”。详情可以查看 MDN 说明。

这个还在 CSS 草案阶段的媒体特征[1],显然尚未被主流浏览器大规模支持,不过已经开始受到部分浏览器支持了。可以从 MDN 或者 Can I Use 上看到,Firefox 67 以及 Safari 12.1 开始支持该媒体特征。

prefers-color-scheme 兼容性

如果你是 macOS 用户,又正巧使用的是支持该特征的浏览器的话,可以通过切换系统的外观色调,查看到我的博客配色跟随系统色调的变化。

配色跟随系统色调切换而变化

除了 Firefox 浏览器之外,也可以用 macOS 系统的 Safari 查看到效果。

浅色 深色

图中的文章见《总结下博客最近的调整》。不过其实 prefers-color-scheme 只是帮助做到随系统自动变化而已,网站的深浅配色系统本身还是要开发者预先设计好。


  1. https://drafts.csswg.org/mediaqueries-5/#descdef-media-prefers-color-scheme ↩︎

's avatar

Dream Diary - 2.5

我站在一个小巷前。面前有两盏灯。

一盏,挂在左手边的墙上,灯是蓝色的。灯下面是一张破旧的办公桌,不知道是谁不用了丢在那里的。

另外一盏,稍微靠后,挂在右手边的墙上,鲜红色的。灯照亮了下面的一扇门。但奇妙的是,不像蓝色的灯那样,有灰尘在其中飞舞,红色的灯光中没有灰尘。光柱反倒像是什么实体一样,散发出象牙般的光泽。

我上前去试探红色的灯。我的手触摸到了坚硬的物体——好像这不是灯光,而是一块巨大的红宝石。

有点麻烦了,我想。我手上拿着这扇门的钥匙,可灯光却阻挡着我进去。

我回到外面,试图找到一点线索。当我眼睛瞟过那张破旧办公桌的桌角的时候,一抹白色引起了注意。

我凑上前去端详。是一副 3D 眼镜。不像现在常用的那种墨镜一样的 3D 眼镜。这是一块纸板,夹上红色和蓝色的透明塑料片做成的那种简陋的 3D 眼镜。

现在怎么还有这种东西,我心想。

我捡了起来,翻来覆去地查看。没有什么异常。但没有异常就是最大的异常,这东西不属于这里。

我看向两块塑料片,红色和蓝色

搞不好是这样,我想。我带上了这副眼镜,除了世界变得单色以外,好像没有什么变化。不对。

起先发出光泽的红色灯光,现在失去了那份光泽。好像光泽转移了似的,蓝色的灯光开始带起光泽。

这个世界因为你所见而不同,我想起不知道谁说的一句话。

总之现在是可以通行了,我掏出钥匙,开锁进了屋子。


进了屋子,一股腥臭味扑鼻而来。

拿了东西就走,不在这里呆着了,我告诉自己。

可这股腥臭味实在是令人难以忍受,于是我寻找窗户,给屋子换气。

我到了厨房,厨房的窗户紧锁,上面落满了灰尘,从里面看不见外面。这房子是几十年没住人了,我一边感慨,一边打开锁,推开窗户。

出现在眼里的是尸体。人的尸体。像垃圾一样堆在外面。垃圾桶里更是趴满了软体动物一样的死人,血顺着垃圾桶流下,汇聚到下水道。我感到一阵寒战,空气里腥臭味仿佛更浓了。

我立马把窗户重新关上,试图将刚才的景象赶出脑海。

我要找的东西是一个小盒子,首饰盒那样的。我很快就找到它了——它被放在靠里的卧室的床头柜上。我转头,想赶快离开这个鬼地方。

“我等你很久了。”背后突然有女声叫住了我。回头。女性坐在窗台上,黑暗中看不清她的脸。

外面打起了闪电,她的影子直伸到我脚下。

's avatar

梦日记 02

写在前面

跟第一篇一样,也是把做的梦做了点加工,放在这里。有的地方过于臭屁,以至于无可救药的地步,也只能死马当活马医了。

这是 23 号晚上做的梦。离第一篇差不多正好 10 个月。

1

我面对这家里堆满杂物的角落。

没经过多少翻找,我就立即发现它了。箱子体积很大,虽然藏在最深的角落里,但不难发现。

箱子很沉。打开之后是一把步枪。

我拿了出来,看着它修长的枪身,一股熟悉的感觉油然而生。

上一次用这把枪是什么时候了呢?模模糊糊的想起那次在荒野,开枪时激起的飞扬的尘土。除此以外就什么也没有了。

我突然感到陌生。我还知道如何使用这把枪吗?我还会使用这把枪吗?

我不清楚,但至少我知道,我又回到这里了。

2

口袋里的手机震动了起来。

回来之后,我没有联系任何人,在这种情况下会联络的,肯定是他了。

我不情愿的按下接听键,将手机放在耳边。

那一头传来的依旧是那个声音。我不知道他是谁,也从未和他见过面。听他的声音,我的脑海里浮现的是一个小个子的,带着微笑面具的少年。

“唷,过得还好吗?”他问道。

“嗯。”我敷衍地答应。

“哈哈,你还是这副老样子,”他咳嗽了一声,“任务来了。”

……

“你怎么知道我回归的?”在对话的最后,我问他。

“这还用说,”他笑了,笑声里没有温度,“我一直在看着你啊。”

3

我趴在一所废弃教学楼的四楼,几张拼在一起的破旧课桌上,透过瞄准镜盯着百米开外,土包上目标所在的小屋。

天气晴朗,无风。视野开阔,没有障碍。

但是当目标出现时,我没能开枪。

倒不是因为目标是一个小女孩或是孕妇:他是一个稀松平常,胡子拉茬的中年男性。也不是因为他的左右还有两个警察——不如说这是预想到的,我需要在他自首前将他解决。

只是单纯的,突然的,扳机变得沉重,没有扣下去。

是一股神秘的、难以控制的力量阻止了我;或是我重又对剥夺别人生命这一行为产生了犹豫?

不过对任务来说,这种无用的思考是有害的。我眨了眨眼,重新看向了瞄准镜。

4

过了一会儿,目标重新出现在视野里的时候,他到坡下停着的警车只有十几米的距离了。

要解决就趁现在。我准备食指用力的时候。

一瞬间,他停下脚步,抬起头,看向这边。像是透过瞄准镜,直勾勾的盯着我一样。

我才是目标,我突然有这样一种不寒而栗的想法。

但没有时间了,我扣下了扳机。

最后,他张了张嘴,好像在说什么,但我没法听见,也无心在意了。

IceHoney Blog's avatar

使用WebAssembly编译C++到JS

实际项目开发中遇到了一些已经使用C++实现的功能,需要在新的Web客户端使用。由于主要是数学和算法的计算,没有平台依赖性。所以需要一个成本最低的移植方式,显然WebAssembly是一个非常好的方式。现在官方的编译工具是emscripten

移植方式

从C++编译到JS。官方提供了两种编译方式embindWebIDL Binder。这两种方式,一开始我也很困惑。不过现在也是有所了解了。向大家介绍一下如何选择。如果你的C++项目中有很多高级数据结构要使用,例如vector,map。那推荐使用embind,如果你的项目主要是简单数据类型,例如数字,字符串,bool,都可以简单的映射到JS,并且是用class封装的,那推荐使用WebIDL Binder。

封装处理

由于C++数据结构比JS复杂的多,很多时候没有直接暴露成JS函数。我们需要进行封装,例如C++中的引用调用,可以改变传入的参数的值。但是编译成JS的话,就不会生效。所以这时候我们需要写wrap函数,封装这些引用调用的C++函数,然后再单独写get函数,得到修改的值。

webpack打包

官方的demo是使用src的方式来引入,并且暴露成Module的全局变量。但是现代化的Web项目都是使用webpack打包,并且自动化引入的。所以我们也不想为了WebAssembly搞特殊。接下来就讲述如何配置来引入。首先,使用emscripten输出 mjs 文件,这样才可以作为模块被导入。具体的编译参数可以参照emcc。 首先,wasm格式并不能被webpack正确识别,我们需要添加loader

{
  test: /\.wasm$/,
  type: 'javascript/auto',
  loader: 'file-loader',
}

然后在项目中,分别 import mjs文件和 wasm文件。

import lib from './wasm.mjs';
import libWasm from './wasm.wasm';

const module = lib({
  locateFile(path) {
    if(path.endsWith('.wasm')) {
      return libWasm;
    }
    return path;
  }
});

然后在调用的时候替换掉默认的locateFile函数,即可完美导入到我们的项目中。

总结

编译C++到JS,不仅需要JS的知识,还需要C++知识,我们需要先把所有需要的C++文件,先全部编译到LLVM bitcode(.o 文件)。这里编译C++可以使用GCC的全部编译参数,推荐使用O3参数来优化代码。最后编译到JS文件的时候,需要按照emscripten的规范来书写胶水文件。

参考:

webpack-emscripten-wasm

h404bi's avatar

总结下博客最近的调整

Old Days

我建博客始于 2013 年,时间也不长。那会儿也不过是一个从 WordPress 加免费空间入坑的新手,免费空间关了就买了个域名和虚拟空间继续折腾。啊对,也改成了 Typecho 一段时间,仿过几个主题。之后便是在流行之下,一个 commit 换成了静态博客 Hexo。于是开始在这个“自留地/实验室”里摆弄各种新玩意,做做小试验。没写过几篇文章,却也一直延续至今。

Changes

A. 核心系统

将使用了近 4 年的 Hexo 换下是博客最近最大的改变,换上的是基于 Vue、Webpack 等当前主流技术的 Saber 静态博客系统。

以 React、Vue、Webpack 等当代主流前端技术为基础的静态网站生成器系统持续出现并开始崭露头角,Gatsby、Nuxt、VuePress[1],势必会抢占 Jekyll、Hexo 等以字符串模版为主的“更加静态[2]”的旧式静态博客系统,我相信这也是这个社群中的趋势。

在最初规划迭代的时候,预期是更换至 Gatsby 这个基于 React 技术栈的系统,其中的原因是受到 Daniel Eden(知名 CSS 动画框架 animate.css[3] 的作者)的博客改版影响。他在稍早的一段时间将他的博客 —— daneden.me 从 Jekyll 换成了 Gatsby。我的博客受其影响很大,即使到目前为止,在我博客中你仍然能够找到一些来源于他的博客的设计元素。最明显的是在文章图文排版上的借鉴,在大屏幕下,你可以在如《推特背后的 Notch 之道》等文章中看到左右溢出的插图。这个我非常喜欢的排版设计,便源于:「Design Elitism」,我博客的整个排版系统很大程度上受他影响,只是彼此经过多次迭代,已不太能找出相似点了。

Gatsby

没有选择 Gatsby 是因为在我对 React 生态的还不了解,头疼一连串硬啃 React、GraphQL 等技术的时候,VuePress 出世了,我还是更倾向于相对比较熟悉的 Vue。

VuePress

然而,在我尝试 VuePress 后,其更加面向于项目文档的设计,让我感觉从 Hexo 迁移显得力不从心。对比 Gatsby 这或许是因为还是刚起步阶段,生态还不完善吧,截至目前其博客方面的支持还在陆续开发中[4]

于是我便在等待/寻找一款能让我更加平滑地进行迁移的系统。然后 Peco 出现了,并在后来被现在的 Saber 所替代。我不想在此大谈如何迁移至 Saber 的,真要这样或许会另起一篇文章写这个。只想说,非常感谢 EGOIST 的开源工作,让大家能够用上前沿的技术。

B. 主题外观

得益于 Saber 的系统设计,将我的原有 Hexo 自用主题迁移至新系统并没有感觉到费力。迁移后整体上我还是使用此前的主题,只是在原有的基础上完成了一些更加细致的迭代,使其更符合我的现存观感。除了调整了列表的布局变得紧凑些、完善响应式文字排版设计外,最大的一点是从以前一直使用的 CSS 预处理器 Stylus 切换成了 SASS,并用上了原版 Bulma 框架。在生态上,果然还是 SASS 更胜一筹。

Bulma.io

期间学会了几个以前不了解、不常用的 CSS 属性,并应用到了主题中。

  • text-align: justify; —— 文字两端对齐,在单栏布局中排版差异尤为明显[5]
  • font-display: swap; —— 修改 Web 字体加载显示逻辑,可避免字体下载过程中闪白[6]

不过整个主题目前还是有缺陷,只能后续随着时间推移再慢慢优化。

C. 部署架构

在我刚开始使用 Hexo 或者说刚入坑静态博客系统的时候,我就已经在使用持续集成工具来帮助我进行构建和部署工作,一直在使用 Travis CI 的社区版。静态博客系统通过使用持续集成做自动构建部署,真的能省下不少重复劳动。

旧部署架构

旧架构如此的原因是以前部署到 GitHub Pages 上觉得速度不行,同时又不支持自定义域名使用 HTTPS,我也有一台闲置的香港 VPS,于是就通过 Webhook 触发 VPS 同步 GitHub Pages 的内容,然后在 VPS 上使用 Nginx 提供服务,这样能解决前述的两个问题。后来因为域名的 SSL 证书过期(那时还没用 Let's Encrypt)和 VPS 不稳定的原因,就加了层 CloudFlare。然后就没管了,一直这样。

新部署架构

调整后实际上就是将提供服务的后端从 VPS 迁移到了 Netlify。其一是图方便,Netlify 自动申请 Let's Encrypt 不用自己麻烦在 VPS 上设置,其二是 Netlify 自带 CDN,速度还不错,最后是因为我需要调整整个博客各页面的固定链接,同时希望旧有的链接能重定向到新的固定链接上,保留可用性。而刚好 Netlify 原生支持重定向服务 —— Netlify Redirect,这样就不用因为 CloudFlare 免费版只有 3 个 Page Rules 而显得拘谨。

构建文件依然推送到 GitHub Pages 分支上后再同步到 Netlify 的原因是,我希望保留能够在 GitHub 仓库中查看构建后的文件的功能,构建后直接推送到 Netlify 上我就看不到构建文件和历史变更了。

Wappalyzer 检查

故意加了个假的 Hexo Generator 的 Meta 标签,所以被检测出用 Hexo(大雾)。关于这个扩展程序,可以看我之前写的文章《我都在用些什么 Chrome 扩展程序》里有介绍。

D. 其它变化

整个核心架构变化,于是现在托管仓库的项目架构也有所调整,改成了 Monorepo 并用 Lerna 进行管理[7]

修改了内容授权协议,具体可见 About 页面。因为细想了一下,真有人取走内容的话大概也不会在意你的协议,于是干脆放飞自我。

RSS Feed 调整,增加 JSON Feed 的支持,路径 /feed/index.json,同时原有的 Atom Feed 的路径会从 /blog/atom.xml 调整为 /feed/atom.xml,原有路径会重定向至新路径。

完整的迁移记录可见仓库 Commit Log


  1. https://www.staticgen.com/ ↩︎

  2. https://vuepress.vuejs.org/zh/guide/#hexo ↩︎

  3. https://daneden.github.io/animate.css/ ↩︎

  4. https://github.com/vuejs/vuepress/issues/36 ↩︎

  5. https://developer.mozilla.org/zh-CN/docs/Web/CSS/text-align#Justify ↩︎

  6. https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face/font-display ↩︎

  7. https://github.com/h404bi/www.h404bi.com/tree/592c99120e8452a816d51fbec6fb7eabf3f15448 ↩︎

ホロ's avatar

离开 Google 的 Android 之路

好聚好散?

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

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

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

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

's avatar

upld 修改版

基于 lfiore/upld 修改而来,目前项目托管于 GitHub: JixunMoe/upld


主要修改:

  • 多图片(支持拖拽)上传
  • 多 url 批量上传
  • 允许禁止用户注册。
  • 举报并不会实际发送出来,因为懒得改发邮件的代码

改过的部分很挫,主要是自己用。 所以基本上都是在原版的基础上缝缝补补来实现我要的那堆功能, 也因为个人化太多了,所以就没提交到上游了。

欢迎代码审计。


测试图片,由 CloudFlare 提供云加速,图片为 Chris LawtonUnsplash 上传的照片:

依云's avatar

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 时结果会不对。

暂时就这些了。

AlisterTT's avatar

春天好

Processed with VSCO with c2 preset
IceHoney Blog's avatar

前端中的e2e测试

对于单页面应用,我们需要由前端来控制每个页面的路由。但是在开发过程中,我们经常要对路由进行调整。每次调整都要手动检查所有页面是否正常显示。这个过程实在是太浪费生命了, 所以我们需要选择一个测试框架来自动完成这个过程,结合CI系统,在每次PR的时候都自动测试一遍,只有通过测试才会进行下一步的review。

Nightwatch

Nightwatch是基于W3C WebDriver API。WebDrive主要是为了满足浏览器的自动化测试需求,把最终的接口统一成HTTP协议。 所以可以统一不同浏览器的自动化测试接口。我们只要安装每个浏览器的WebDriver实现,就可以同一套代码在不同的浏览器中进行测试。老版本的NightWatch需要使用Selenium来管理各个浏览器,但是从1.0版本开始便不需要也不推荐。所以我现在的项目中并没有安装Selenium。

依赖

由于不需要安装Selenium,所以并不需要安装Java依赖。我使用Chrome浏览器来进行自动化测试,所以需要测试环境安装Chrome,注意安装的必须是Chrome,Chromium不可以。 在Travis CI中可以很方便的添加Chrome。还需要安装ChromeDriver依赖来驱动Chrome完成自动化测试。

配置

在Linux测试环境下,基本上都是没有图形化界面的,所以我们在配置Chrome的启动参数中需要加入--headless选项,这样就可以不启动UI。当我们以root权限启动的时候还需要添加--no-sandbox选项,这两个选项基本上是必须的。在我的实际情况下,需要测试不同UA下的展示效果,所以还需要添加--user-agent=Mozilla/5.0 (Macintosh; Test自定义的UA。 下面给出一个配置的例子供大家参考:

// http://nightwatchjs.org/gettingstarted#settings-file

module.exports = {
  output_folder: "tests/e2e/reports",
  custom_assertions_path: ["tests/e2e/custom-assertions"],
  globals_path: "globalsModule.js",
  src_folders: ["tests/e2e/specs/web"]

  webdriver: {
    start_process: true,
    server_path: require("chromedriver").path,
    cli_args: ["--verbose"],
    port: 9515
  },

  test_settings: {
    default: {
      desiredCapabilities: {
        browserName: "chrome",
        javascriptEnabled: true,
        chromeOptions: {
          args: ["--headless", "--no-sandbox"]
        },
        acceptSslCerts: true
      }
    }
  }
};

每个参数的详细含义可以参考官方的说明文档。

总结

在集成Nightwatch的时候,我是卡在了安装浏览器上。在Mac系统上可以正常执行,在CentOS的docker里面却不行。找了半天发现是自己用了Chromium,之前对Chromium能代替Chrome深信不疑。。。 在遇到问题的时候,还是多怀疑,多找找可能性比较好。

Felix Yan's avatar

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 镜像。

依云's avatar

系统在解析哪些域名呢?

本文来自依云'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 写的脚本,刚写好,一跑就抛个异常出来,提示我哪里不小心写错了。好不容易调试好了,跑着跑着,遇到意外情况就挂掉了……

依云's avatar

正确的隐藏挂载点的方法

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

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

mount --make-rprivate /

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

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

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

ホロ's avatar

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 …

依云's avatar

迁移系统到 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 超快的!

17windy's avatar

[七日杀原创MOD] 17windy的卡通幻想风格武器包 Ver1.4 0422

emmmm 最近七日杀服务器比较荒凉 为了避免美羽姐姐的服务器空转 研究了下七日杀的MOD开发 所以有了这个武器包 嗯嗯…

应该会适合比较喜欢这类卡通风格道具的玩家们:) 毕竟废土太阴暗啦!

内含5把双手剑 3把双手斧 6把单手武器 4枚投掷玩具

武器参数和性能经过了平衡 各有所长 例如某把武器割肉相当厉害的!

只能通过搜刮获得(因为毕竟属性还是比原版的要强力)这又到了看脸的时候了……

更新日志

Ver 1.05 武器特效
为几把武器增加了特效
部分武器的细微平衡

Ver 1.1 新武器和特性
增加了三把新武器和两把挖矿镐
部分武器性能平衡
部分武器增加了特殊的隐藏效果

Ver 1.2 新的地刺方块和远程武器
增加了四种地刺方块
增加了三把远程武器
部分武器性能平衡

Ver 1.4 地刺方块可修复和新的武器特殊能力
部分武器的视觉特效修改;
灰狼会加强玩家的潜行能力;
钢鼠会加强玩家的移动能力;
冰噬有几率会无视抗性击倒敌人;
四种地刺方块现在均可修复。

下载地址:

N网 https://www.nexusmods.com/7daystodie/mods/301/

Git https://github.com/17windy/17windy-s-cartoon-fantasy-weapon-pack

希望大家用的开心!

后续有时间会继续更新的!

RecursiveG's avatar

Haskell 简易指南

Haskell 简易指南
HY's avatar

Horror game

最近玩了生化2重制版,有点感想就随便写点东西_(:3」∠)_ 生化2全程给我的精神压力都不大,大多被吓到的场景 […]
依云's avatar

使用 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 有可能会找不到模块的。(所以更新内核之后还是重启一下以避免尴尬吧。)

依云's avatar

使用 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 硬盘的事情~

Roy Binux's avatar

Zerotier Nat 网关出口 和 iptables 调试

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

IceHoney Blog's avatar

localStorage互斥锁的使用

JavaScript是单线程语言,所以我们在写代码的时候根本不会遇到互斥锁的问题。但是当用户打开多个Tab页面的时候,这些页面却是共享同一个localStorage的。当我们试图修改localStorage的时候就会遇到竞争问题,如果两个页面同时修改了localStorage,程序的可靠性就无法保证。

多Tab互斥

这个问题查了不少时间,目前有的解决方案:Shared Web Workersfast mutex。由于想尽可能的支持更多浏览器,所以我们选择了后者。

实现localStorage互斥

fast mutex的源码也不是很多,所以读起来也没有很复杂。当执行lock函数的时候,会为一个key存储 _MUTEX_LOCK_X_KEY_MUTEX_LOCK_Y_KEY。以下简称X和Y。 首先存X,然后读Y。如果Y存在说明别人已经拿到互斥锁了,所以重新执行函数。直到获取到互斥锁。如果Y不存在,说明没有人竞争锁。所以往下继续执行存储Y。 但是我们不能保证这段时间没有别的tab来存储X或者Y。所以继续读取X,如果X没有发生变化,说明没有人来竞争锁。我们就可以resolve传入的回调函数了。 如果X发生了变化,说明有人来竞争互斥锁,这时候的函数设置了一个50ms的延迟执行,就是保证检测的足够晚。竞争的tab能够执行完自己的lock函数。50ms之后再去读取Y,如果发现Y没有发生变化,则自己还拥有这个互斥锁,可以顺利执行resolve。否则自己丢失了互斥锁,重新执行lock函数。

总结

fast mutex的实现确实很巧妙,通过添加两个localStorage值和setTimeout完成互斥锁的实现。看到这个项目之前,一直以为想做到localStorage的互斥是不现实的事情。

SgDylan's avatar

音频互联笔记兼 VB-Audio 使用小结

farseerfc's avatar

東方歌詞翻譯遷移至 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:`例|れい`

然後所有那些歌詞上標註的假名都是這樣一句一句標註好之後,再手動校對修改的。

's avatar

《还愿》很棒,可是为什么要乳滑,为什么啊?

前几天,台湾游戏制作团队「赤烛」发布了它们的第二部作品《还愿》。本身是很正常的恐怖游戏,有许多人觉得它非常恐怖,也有许多游戏主播不畏恐惧地在给害怕自己玩的人直播。这是对于一个非常恐怖的恐怖游戏来说,再正常不过的现象了。只是里面有一个彩蛋,引起了不和谐的风波:

「习近平小熊维尼」,用篆体写在了一张贴图上。

明明是这么优秀的游戏,为什么偏偏要乳滑啊?为什么啊?这实在太可惜了——我看到许多人这样想。如果是曾经的我,大概也会这样觉得。但是现在如果你有这样想法的话,我写出了这篇文章,希望可以缓解一下你的心情。

「明明是非常棒的作品,可为什么偏要加入这样侮辱的东西啊?」我也经常有这样的感受。自己喜欢的东西,却不得不和自己非常讨厌的东西纠缠着,对于这两者的结合,要是讨厌它也太浪费了,可要是喜欢它的话,对于自己讨厌的部分却无法释怀。这毫无疑问是一件令人难受的事情。可是,在这次事件中,这个令人讨厌的部分,自己真的有必要那样讨厌吗?

简单地说,我觉得这没有什么大不了的。游戏彩蛋拿国家领导人开玩笑,并不是一个需要非常反感的事情。

拿一个人开玩笑再正常不过了。当然,要除了当这个玩笑是对着自己开,而我们觉得这个玩笑开得很不恰当的时候;或者当这个玩笑会冒犯到我们喜欢的人的时候(是广义上的喜欢,包括朋友、家人,还有偶尔遇见的路人)。而习近平,需要被我们当作是喜欢的人吗?他当然是国家领导人,可这也并没有使他在这个方面变得有多么特殊,事实上作为政治人物,被骂是再正常不过的事情了。在世界的大部分地方,开政治人物的玩笑也是很平常的事情。我们说奥巴马长得像跳跳虎,安倍长得像驴,川普在各种演讲上的发言以及推文上的错别字实在是太搞笑了。这些都没有问题,那么说习近平小熊维尼,为什么就不可以了呢?游戏彩蛋没有针对对我们玩家中的任何一个人,而只是针对习近平开玩笑。为了这样一个遥远的人被开玩笑而生气,实在是太没有必要了。我们可能觉得这个玩笑一点也不好笑,但也不必因此反感它嘛。而且作为一国之主,习近平显然不会被这么一个小游戏团队的一句话冒犯到。

台湾独立一直是个敏感的话题,你可能会因为这个游戏宣扬了支持台湾独立的观念而讨厌它。但值得思考的是,为什么在许多观点不同的时候,我们都可以相对和平地相处,而只要涉及一点政治,就不得不暴跳如雷呢?我们在游戏中遇到一个不喜欢的东西,通常都会继续玩下去,如果令我们不喜欢的东西有很多,也最多是批评这个游戏并告诉其它人不要去玩,并希望开发者能在以后改进。遇到自己不支持的政治观点时也是一样,我们只需要表达自己的不认同就足够了,而不需要像 Steam 上的许多评论评论中一样辱骂开发者,诅咒他们早点解散。当然,你可能还是会觉得一个游戏加入了自己讨厌的政治观点是无可救药的——可是如果我们回来看,《还愿》的这只彩蛋里面,也并没有说任何支持台湾独立的话啊。

不管你是觉得台湾独立是非常坏的主意,或者是需要双手赞成的提案,还是觉得都无所谓,都和这个游戏没有关系。《还愿》又不是一个政治游戏,它只是一个包含了「习近平小熊维尼」这句彩蛋的恐怖游戏罢了。赤烛的成员的确可能抱着支持台湾独立的想法,其实大部分台湾人都这样想,但要是仅仅因为作者抱有了和我们不同的观点就要抵制他们的所有作品的话,那世界上有这么多怀有不同观点的作者,岂不是许多作品都需要抵制了?至少基本上所有台湾出产的文学、艺术作品,还有游戏,都会变成需要抵制的对象了,这怎么想都太夸张了嘛。

实际上,即使是面对表达了支持台湾独立的游戏,也没有必要看到就直接拒绝。你也许觉得台湾独立是一件很坏的事情,是分裂国家、挑起战争、对生活影响巨大的事情,但从另一方面想,这有比杀人放火,炸掉政府大楼,宣扬恐怖主义这样的政治理念更加可怕吗?没有吧?但实际上,从电子游戏这方面看来,扮演杀人狂魔和恐怖分子的游戏却备受欢迎。而台湾独立不但远没有这么可怕,也和恐怖主义不同,它在世界上还有非常多的人支持。我们也许认为它是不应该被支持的,但这只是我们的观点,从客观的事实上来说,应该怎样还不知道呢。

当然啦,这篇文章也不是一篇我表达政治观点的文章,我只是希望能够为大家减少一些气愤。真的,一个游戏彩蛋而已,有必要上纲上线吗?如果你也在看完了这篇文章之后,觉得没有必要,那么谢谢你让我的文章变得有用,也祝愿你能够享受游戏,在其它的地方能够少遇见令自己不愉快的事情。如果你完全不同意我的说法,那么也感谢你至少没有马上关掉文章拉黑我,而是耐心的把它读完了。不管怎样,大家怎样做都是大家的自由,对吧?


除特殊说明外,本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。转载时请注明来自 FiveYellowMice's Blog ,以及原文链接

虽然 RSS 是一种很好的新闻获取方式,但是不同的 RSS 阅读器所显示的内容可能会有很大差距,有些甚至无法显示所有内容。所以为了能够获取到完整的内容,最好还是点开网页链接看。
之所以还是保留了 RSS 的全文输出,是因为摘要输出会被很多人讨厌……

cuihao's avatar

留言板备份

null
's avatar

与萌狼的笔谈

是一个平常的夜晚,萌狼少见地发来一条消息,说想要和友情链接里的各位来一次笔谈。然后黄鼠很荣幸地,成为了第一位。正好,黄鼠也经常发愁博文没灵感写、博客日渐荒废呢,要做笔谈的话,不但是个介绍自己和了解别人的机会,也顺便能够给博客补充一点活力。于是就开心的答应了(虽然咕咕咕了 3 天才写有出来)。

所以「笔谈」这样东西是什么呢?

一开始萌狼提起的时候,黄鼠也有些疑惑,可又感觉似乎在其他地方有听说过这样的东西。记得是跟歌手和主播之间互相客串类似的做法, 互相向对方提一些问题,然后各写一篇文章来回答 ——至少萌狼觉得黄鼠这样理解是没有问题的呢。

但黄鼠还是好奇的查询了一下,笔谈具体是什么,然后维基百科说……

笔谈,是指人们在面对面的情况下不使用口头语言而是通过互相书面书写或键盘输入文字的方式,来传达彼此意思的沟通行为。

……是汉字文化圈地域内不同母语的文人相互交流的方法之一。主要使用汉字以及文言文(汉文)的交流方式。

唔唔,诶?原来是东亚国家之间的人以前因为用的文字一样,所以用来勉强交流的方式嘛……好像差距有点大诶。嘛,不管了,总之就当作互相提问的意思好了。

下面就是萌狼提出的问题了

Q1. 除了博客的「关于」页面以外,还愿意再向咱介绍一下自己嘛?

这样的打算,其实很早之前就有呢。看到许多人都有专门的个人主页,做得很漂亮,黄鼠也打算过效仿着做一个。这也是黄鼠购买 fym.moe 域名的原因。结果嘛……点开那个链接的话就显而易见了,个人主页一直处在咕咕的状态,大概已经快要有两年的时间处在这样的状态了。所以要让黄鼠现在做出一些个人介绍的话,也不知道要从哪里讲起呢……

——每次都是这样,自从有了那个个人主页予定的域名之后,黄鼠在每次遇到简略介绍自己的机会的时候,都会这样想:唔啊……这里要怎样说呐……还是等到以后写好个人主页上那篇完整、系统的自我介绍之后,再放一个链接过去好了,在这里写简略的介绍,果然还是太浪费脑筋了。就是因为每次都这样想,而个人主页又一直咕咕咕,所以最后落得黄鼠不管是长的自我介绍还是短的自我介绍,都没有写出来过。

话说,既然说到博客的「关于」页面,那个似乎也需要不小的更新了呢……不过既然黄鼠有决定之后写一篇完整的自我介绍,还是等到那里写好之后再链接过去吧,单独写一下果然还是太废脑筋了。

萌狼是想要黄鼠在这里做出一些自我介绍嘛?可是黄鼠已经有打算在个人主页上面写一篇完整的介绍了,觉得还是等到黄鼠写好的时候,直接去那里看会比较好呢。

(咕咕咕)

Q2. 这个名字是怎么想到的呢?

这其实是自己真的还在中二的时候,做出的一些饱含中二成分的决定啦……唔,实际上也不只是中二呢。要说出来的话,还是太羞耻了。

总之总之,大家先这样看。

首先, Five ,是一个很吉利的数字,对吧?一个正常人就是有五根手指,所以这就是 Five 的来源。至于一个人有一只手还是两只手,那种事情就先不管啦。

然后 Yellow ,是因为,呃,那个,柠檬的颜色,对吧?柠檬吃起来很甜,一点都不酸,对吧?黄鼠可以一口气吃下 5 个,所以这就是 Yellow 的原因。

最后呢,这个, Mice ,怎么说呢,就是就是,唔,要怎样解释大家才会相信呢。就是这个……老鼠!老鼠……呃,老鼠很厉害对吧?可以吃掉猫咪,所以这就是 Mice 的来源,嗯。

以上的解释都是真实的 FiveYellowMice 的名字的来源,而且没有一点点事实错误哦。(光速逃)

Q3. 是怎么喜欢上视觉小说的呢?

剧透警告:这里会有对《守护甜心》第二季的开始,对藤咲的介绍的小剧透喔。虽然不算是很重要的内容,但失去这个惊喜还是很可惜的。

其实主要的原因很简单呢,说是令人大跌眼镜也不为过,当时自己可以使用到的电脑,性能非常差劲,连 Ubuntu 的 Unity 桌面都会让显卡吃力无比。主流的游戏都没有办法运行,于是就只好推视觉小说了 _(:3)<)_ 。

一开始接触视觉小说,是因为看到《守护甜心》里面的藤咲凪彦,觉得很厉害,所以就到百度百科上面看了看,就发现,原来这样类型的角色不但有专门的名称,而且还有很多诶!兴奋的黄鼠又看到里面说这样类型的角色的始祖是一个被称作《少女爱上姐姐》的视觉小说,于是黄鼠就找来玩了玩,便把新世界的大门打开了(双重意义上的)。

说到现在黄鼠依然喜欢视觉小说的原因的话,就要复杂一些了。黄鼠对 RPG 的剧情很感兴趣,但是又很讨厌维护各种属性值,也不愿意跑来跑去,只想看剧情对话。视觉小说刚刚好就是和去掉游戏成分、只剩下剧情的 RPG 一样,所以在听说了有这样类型的游戏的时候,黄鼠觉得简直就是像找到了知己一样的感觉呢。而且和其它类型的游戏不一样,视觉小说一点难度都没有,对于手残的黄鼠来说再合适不过了。

不过其实黄鼠觉得,把视觉小说和「游戏」比较不是一个很合适的分类。名字都叫做视觉「小说」,内容也是和小说一样,一直往下读就可以了,仅仅是有偶尔出现的选项,能够带来的游戏性和真正的游戏比还是相差太多了。而和真正的小说比较的话,视觉小说不但有多出了背景和立绘,还会经常有很棒的 BGM ,再加上偶尔会有的语音的话,还有一半的动画的感觉,而有了这些附加的东西以后,主要的故事表现手段还是文字。黄鼠觉得文字是一种能够有深度和艺术性的很棒的媒介,漫画和动画都很难避免会失去一些这样的东西,而视觉小说却能够在不破坏小说的优点的情况下,依靠图像和声音弥补了很多的缺点。这就是黄鼠认为视觉小说最棒的地方呢。

Q4. 对咱的印象怎么样?

萌狼嘛……因为第一次认识的时候,萌狼的设定还没有出现,所以一开始的印象是那种很厉害,做事情又有行动力又有坚定想法的大佬。只是后来嘛……才渐渐熟悉起来,意识到其实萌狼是和大家都一样的人(狼?),拥有自己的喜怒哀乐,也有失落的时候。

然后就是萌狼的设定,除了支仓冻砂带来的「狼」的设定以外,萌狼带给黄鼠的印象,就是很喜欢发送「😂」,遇见很多东西的时候都会用「😂」来作为回应。在很多时候向群里面发送一些东西,会一点回应都收不到,黄鼠就会觉得自己发出的内容非常无趣,直到有看到萌狼的「😂」的时候,才欣慰感受到,还是有人觉得黄鼠发送的东西是有趣的呢。是萌狼的「😂」在这些时候给了黄鼠继续下去的动力。

再接下来的话,就是音游的方面了。黄鼠也忘记了是在什么时候知道的萌狼喜欢音游,在意识到以前,音游狼的印象就已经刻印在脑中了。萌狼的音游水平,在黄鼠感觉是那种很厉害,但也不是遥不可及的那种,就像是漫画里的「前辈」一样,让黄鼠把音游渐渐熟悉了。

最后一点,是黄鼠不喜欢萌狼的一点。萌狼喜欢说讽刺的话,或者是叫做风凉话。像是在有新人被推荐东西的时候说「不要用。反正都是被大佬鄙视的」这样的话,以及在完全没有提起萌狼如何的时候说「您您您,咱就是弱鸡」这样的话。萌狼说这是在音游圈子里面的普遍现象,可是黄鼠觉得,音游圈里面会崇拜水平高的玩家,对其他人卖弱,但没有必要说讽刺的话嘛。

Q5. 还记得第一次接触 GNU 是什么时候嘛?

如果是说第一次用到 GPL 的软件的话,那应该是很久以前了。也许 Firefox 是黄鼠第一个在自己家的设备上使用过的 GPL 软件,但也不能确定有没有更早的呢。

如果是说第一次知道 GNU 这个理念的话,大概是在 2015 年,黄鼠使用 Ubuntu 的时候了。觉得 GNU 非常厉害,能够使开源的东西也这样好用呢。黄鼠也很认同利用自己的开源软件,使别人在使用了黄鼠的开源软件的时候也不得不开源的做法。开源作为一个大家共有的东西,索取了再返还,也是合理的事情。然后黄鼠就成为了 RMS 的粉丝,开始传教……(逃)不过大概没有萌狼厉害啦。

Q6. 现在有在做什么嘛?

自从高中毕业了之后,黄鼠就越来越颓废了。以前本来是计划了好久,雄心勃勃的计划,都越来越缺少动力去做了。两年前有着想写一个评论系统的计划,到了现在一直也没有见到里程碑。再之前打算写的可以自定义项目的追番列表 sedosipE ,即使有了想要看许多列表里面都没有记录的冷门漫画的需求,也还是随着各种其它的事情渐渐淡化了。

现实方面的,去年有试过健身,但果然体育方面的事情还是没有办法让黄鼠有动力去做呢。脱离了教练的监督以后,就一直颓废下去了。另外也担心健身效果太好的话,女装的计划就得抛弃了,黄鼠觉得这样是很大的损失。

不过女装最近倒是有开始尝试了。之前放假的时候心血来潮,在超市里面买了一盒脱毛膏,又痛苦又耗时地把两条腿处理完毕了。不过那个时候,黄鼠还没有打算马上开始女装,是在同一天,一位群友的说「既然已经脱毛了,不如就开始女装吧,要不然之后还得来一次」,使黄鼠提早产生了女装的动力。现在有到下半身的程度,但是上半身的挑战看起来更加严峻呢……要化妆什么的更是听起来就令人望而却步,于是就连这也开始停滞了。

也是在假期的时候,觉得自己越来越滞后的黄鼠,感到自己一定要继续学习才行,于是就把放置了很久的《Head First C》拿出来看了。里面有一章是有写用 Arduino 做出东西,黄鼠想「诶, Arduino ,是听说过很多次的名字诶,大家好多人也都有玩过的样子」,于是在新年回到中国的时候,依靠淘宝进入了这个大坑。这次黄鼠再次雄心壮志地立下了自己要做出一个带有 16x16 LED 屏幕的东西,但是组件比想象中地多了很多,黄鼠又因为面基 Eq彼得,还有过年回老家探访亲戚什么的,错过了春节快递停运之前的时间,只好等到回到澳洲之后才能梳理需要的组件。但是这样子的话,成本就噌噌地上涨了呢。时间也是大概要等到一个月之后,材料到达之后才能开始了……希望到达的时候,黄鼠的热情没有消减才好呢。

还有还有最后一点,就是想要恋爱 ( > ∀ <) /!虽然在这样的方面,黄鼠看起来也没有什么可以 take initiative 的事情就是啦。

Q7. 有什么话要对咱说嘛?

平常都有说话的机会,所以硬要黄鼠说下什么的话,也不是一件容易的事情呐。总之……萌狼好吃!

萌狼好吃!
萌狼好食!
萌狼好吔!

(在被追到之前赶紧逃)

笔谈还有另一边喔!

上面是黄鼠对萌狼提出的问题的回答,那么既然是交换提问回答的笔谈,黄鼠也向萌狼提出了一些问题,让萌狼在萌狼的博客上面回答呢。如果还没有看过的话,可以走向这里喔。

🍎😋


除特殊说明外,本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。转载时请注明来自 FiveYellowMice's Blog ,以及原文链接

虽然 RSS 是一种很好的新闻获取方式,但是不同的 RSS 阅读器所显示的内容可能会有很大差距,有些甚至无法显示所有内容。所以为了能够获取到完整的内容,最好还是点开网页链接看。
之所以还是保留了 RSS 的全文输出,是因为摘要输出会被很多人讨厌……

ホロ's avatar

和 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 (不过在这之前是不是该先考虑能找到几个愿意和咱 这样笔谈的笔友(?)的问题) 😮

  • 😋 ?

    😋!

那么下一个是?

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

HY's avatar

TwitterImg Downloader

想必不少朋友也和我一样关注了很多画师,定期收图。 Pixiv的图片文件名可以直接反推出图源,直接保存就可以,但 […]
h404bi's avatar

彻底搞懂 Windows 控制台的设置

Windows Console Host(即 conhost.exe,下称“ConHost”[1])中的设置可能有点难以理解,主要是因为在过去几十年中这个设置系统不断发展。根据 ConHost 如何被调用,这些设置项会存储在不同的位置。

控制台设置

设置加载的层级

决定一个控制台设置的加载与存储是基于以下层级进行的:

  1. 写死在 conhostv2.dll 里面的设置
  2. 用户定义的控制台默认设置,存储在注册表 HKCU\Console
  3. 每个控制台应用程序[2]单独的设置,存储在注册表 HKCU\Console\ 中,其中 sub-key 使用以下两种值中的一种:
    • 控制台应用程序的文件路径(其中的 \ 会替换成 _
    • 控制台应用程序的标题
  4. Windows 快捷方式(.lnk)中的设置
注册表中的控制台设置键值

当一个控制台应用程序被启动后,ConHost 会依据加载情况决定使用哪些设置,同时会按照前述的层级先后对一些进行覆盖。每一个设置项将取其最后加载的值,也就是说在第 4 级(Windows 快捷方式)中的值会覆盖掉第 2 级(用户定义的默认设置)中的值。

这样一个层级设计解释了为什么在每个控制台实例窗口的标题菜单中,都会有一个“默认值” 选项以及一个“属性”选项。

控制台窗口标题菜单

修改“默认值”时,改动会存储到注册表 HKCU\Console 中,写入用户定义默认设置(即前述层级中的第 2 级)。

修改“属性”时,改动会存储到注册表中的控制台应用程序单独设置或者 Windows 快捷方式中:

  • 如果这个控制台应用程序是被直接(比如是从 Win+R,Windows 运行对话中)启动的,则改动会存储到前述的控制台应用程序单独存储位置(层级中的第 3 级)中。
  • 如果这个控制台应用程序是通过 Windows 快捷方式被启动的,则改动会直接存储到这个快捷方式 .lnk 文件中(层级中的第 4 级)。你可以右键这个控制台应用程序的快捷方式,选择“属性”查看其设置。
快捷方式中的设置

当一个控制台应用程序被启动后,ConHost 会根据前述的层级,从第 1 级写死的默认设置开始覆盖设置,最后确定使用哪些设置。这意味着在 Windows 快捷方式中的设置会覆盖掉注册表中的控制台应用程序单独设置以及默认设置。

值得注意的是在注册表中的设置是“稀疏”的,意味着如果某个设置项为空,则不会修改正在使用的值。这允许用户在所有控制台应用程序之间共享部分设置项的同时指定其它一些特定设置项。

而快捷方式文件则会将每个设置项都存储其中,不管是否有默认设置。这些设置会以不透明的数据块存储在快捷方式中。

下面是 Windows 控制台的设置列表,包含了简短的描述以介绍其作用。

设置项名字 类型 描述
FontSize Coordinate (REG_DWORD) 字体像素大小
FontFamily REG_DWORD GDI 字体族
ScreenBufferSize Coordinate (REG_DWORD) 屏幕缓冲区大小,宽x高个字符
CursorSize REG_DWORD 光标大小
WindowSize Coordinate (REG_DWORD) 窗口大小,宽x高个字符
WindowPosition Coordinate (REG_DWORD) 窗口位置,宽x高个像素(如果没有设置则进行自动定位)
WindowAlpha REG_DWORD 窗口透明度(取值范围:0x4D-0xFF)
ScreenColors REG_DWORD 前景色与背景色
PopupColors REG_DWORD 显示弹窗(CMD.exe 按 F2)时的前景色与背景色
QuickEdit REG_DWORD 快速编辑模式是否开启
FaceName REG_SZ 字体名字 (默认使用 __DefaultTTFont__,根据你的代码页 CodePage 选择最合适的字体)
FontWeight REG_DWORD GDI 字重
InsertMode REG_DWORD 插入模式是否开启
HistoryBufferSize REG_DWORD 命令记录缓冲区大小
NumberOfHistoryBuffers REG_DWORD 命令记录缓冲区数量
HistoryNoDup REG_DWORD 是否丢弃旧的副本
ColorTable%% REG_DWORD 16 色的调色盘中每个颜色的 RGB 值
ExtendedEditKey REG_DWORD 是否启用扩展的文本选择键
WordDelimiters REG_SZ 分词符列表(例:' .-/\=|,()[]{}'
TrimLeadingZeros REG_DWORD 选取复制文字时是否删除首部零宽字符(使用 00000001 表示 1
EnableColorSelection REG_DWORD 选择时是否同时复制颜色
ScrollScale REG_DWORD 使用滚轮滚动时一次滚动多少行
CodePage REG_DWORD 代码页 CodePage
ForceV2 REG_DWORD 是否使用新版控制台
LineSelection* REG_DWORD 是否启用对选定内容自动换行
FilterOnPaste* REG_DWORD 是否在粘贴时筛选剪贴板内容(如:将弯引号替换为直引号)
LineWrap REG_DWORD 是否在调整窗口大小时对输出的文本换行
CtrlKeyShortcutsDisabled REG_DWORD 是否启用 Ctrl 键快捷方式
AllowAltF4Close REG_DWORD 是否禁用 Alt-F4 热键
VirtualTerminalLevel REG_DWORD 控制台 VT 支持级别

*仅在新版控制台中有效

已知问题

与大多数复杂的事物一样,有一些问题需要注意:

系统更新会导致设置被重置

每当你升级到新版本的 Windows 时,系统级的快捷方式以及“「开始」菜单”中的设置会被重置为默认值。这意味着如果你升级了系统,你自定义的字体、颜色等设置将会全部重置为 Windows 的默认值。

后记

我一直在使用 concfg 作为我管理我的 Windows 控制台设置的工具,近期成为了该项目的协作者进行项目维护,便开始稍微深入地了解 Windows 控制台相关知识。本文是微软官方 Windows Console & WSL 团队的一篇博文的译文,原文见 Understanding Windows Console Host Settings,有些许删改。


  1. 在 Wikipedia 上也称 Win32 控制台 ↩︎

  2. 注意“控制台”与“控制台应用程序”的区别,前者指 ConHost 宿主程序,后者是运行在 ConHost 下的应用,如 cmd.exe/powershell.exe ↩︎

's avatar

FLAC / MP3 / WAV 批量转 aac

自动检查 ffmpeg 是否有启用 fdkacc-lib,如果没有则使用 native_aac 编码器。

关于编译带有 fdk 支援的 ffmpeg 请参见官方文档;因为 GPL 病毒的原因,就不放出编译版了。

#!/usr/bin/env node
/**
 * FLAC/MP3 to aac script
 * MIT License
 * (C) 2019 Jixun.Moe
 */

/* configuration */
const srcExt = ['flac', 'mp3', 'wav'];
const maxThreads = 4;

/*
 * override with command line options
 * node to_acc.js ./rip ./aac
 */
const srcDir  = process.argv[2] || './rip';
const destDir = process.argv[3] || './aac';

/* import modules */
const fs = require('fs');
const util = require('util');
const readdir = util.promisify(fs.readdir);
const copyFile = util.promisify(fs.copyFile);
const exec = util.promisify(require('child_process').execFile);

/* global variables */
let threads = [];
let files = [];
let aacCodec = 'aac';

function getExt(name) {
    const m = name.toLowerCase().match(/\.(\w+)$/);
    if (m) return m[1];
    return '';
}

async function scanDir(dir, outDir) {
    const scanResult = (await readdir(dir)).filter(d => d[0] != '.');
    for (let i = 0; i < scanResult.length; i++) {
        const inPath = dir + '/' + scanResult[i];
        let outPath = outDir + '/' + scanResult[i];

        const stat = fs.statSync(inPath);

        // sync directory structure.
        if (stat.isDirectory()) {
            // create subdirectory
            try {
                fs.statSync(outPath);
            } catch {
                fs.mkdirSync(outPath);
            }
            await scanDir(inPath, outPath);
            continue;
        }

        const inExt = getExt(inPath);

        // Music file to convert
        if (srcExt.indexOf(inExt) != -1) {
            outPath = outPath.slice(0, -inExt.length) + 'aac';

            try {
                fs.statSync(outPath);

                // file exists, skip...
                continue;
            } catch {}

            files.push([inPath, outPath]);
            continue;
        }
        
        // other file type
        console.info('copy %s...', inPath);
        await copyFile(inPath, outPath);
    }
}

async function doWork(thread) {
    while (true) {
        let work = files.shift();
        if (!work) break;

        const [input, output] = work;
        console.info('[T%d] converting %s...', thread, input);
        await exec('ffmpeg', ['-i', input, '-c:a', aacCodec, '-vbr', '3', output]);
    }

    console.info('thread T%d complete.', thread);
}

async function detectFdk() {
    const {stdout, stderr} = await exec('ffmpeg', ['-codecs']);

    // test for libfdk
    const useFdk = /encoders:[\w\s]* libfdk_aac/.test(stdout);
    console.info('libfdk: %s', useFdk);

    aacCodec = useFdk ? 'libfdk_aac' : 'aac';
}

async function main() {
    // let detect and scan run at the same time.
    const detect = detectFdk();
    await scanDir(srcDir, destDir);
    await detect;

    console.info('to process: %d files.', files.length);

    // create threads
    for(let i = 1; i <= maxThreads; i++) {
        threads.push(doWork(i));
    }

    // wait for thread complete
    // 感谢 orzFly
    await Promise.all(threads);
    
    console.info('done');
}

main();
依云's avatar

在 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 的哦。

brainbush's avatar

OpenWrt 编译安装 Nginx rtmp module

参考 https://wonpn.com/2018-03-15-compile-nginx-with-ssl.html

1. 下载 OpenWrt SDK

这里我使用的是斐讯K3,所以下载 bcm53xx 的。

wget https://downloads.openwrt.org/releases/18.06.2/targets/bcm53xx/generic/openwrt-sdk-18.06.2-bcm53xx_gcc-7.3.0_musl_eabi.Linux-x86_64.tar.xz
tar xf openwrt-sdk-18.06.2-bcm53xx_gcc-7.3.0_musl_eabi.Linux-x86_64.tar.xz

2. 下载 Nginx rtmp module

wget https://github.com/arut/nginx-rtmp-module/archive/v1.2.1.zip
unzip v1.2.1.zip

3. 下载nginx并添加设置选项

./scripts/feeds update
./scripts/feeds search nginx
./scripts/feeds install nginx

修改 package/feeds/packages/nginx/Congif.in 添加:

config NGINX_RTMP
         bool
         prompt "Enable RTMP module"
         help
                 Enable RTMP module
         default n

修改 package/feeds/packages/nginx/Makefile ,在213行附近(TARGET_CFLAGS前)添加:

ifeq ($(CONFIG_NGINX_RTMP),y)
  ADDITIONAL_MODULES += --add-module=/path/to/nginx-rtmp-module
endif

4. 修改和编译

make menuconfig
# 在network->Web Servers/Proxies->Nginx->Configuration->开启 Enable SSL module 和 Enable RTMP module 
# (如没有RTMP module请检查是否在Config.in重添加)
make -j4

5. 抱走 Nginx 包

cp bin/packages/arm_cortex-a9/packages/nginx_1.12.2-1_arm_cortex-a9.ipk /where/you/want
摸完了
's avatar

空白的 2018

总而言之,Benpigchu 的整个 2018 年几乎什么像样的事情都没有做。如果是有心观察 Benpigchu 的人的话,大概已经发现这一点了吧。

现在看来过去的这一年和接下来的几个月会是人生中比较困难的一段时间了。

发生了什么

这个……我也不是很清楚,只能大概描述一下。下面的文字会比较混乱。

其实一直以来 Benpigchu 对于自己的未来一直处于迷茫,或者说是,逃避的态度,以至于没有为未来做任何的准备,所以也没有科研经验和实习经历。

而在 2017 年的后半,也就是大三下学期,迎来了 THU 计算机系的五大金刚课程(编译原理、网络原理、计算机组成结构、软件工程、信号处理原理)。这个学期可以说是榨干了我的行动力,虽然挺过来了,但是似乎也产生了一些不好的后果。

我们 THU 计算机系的保研安排是在大四下学期,在这之前我的家长因为看我犹豫不决,所以建议我争取保研,但是……总之我没有动力为这个目标去努力。到了暑假的后半,母上甚至来协助……或是强制我准备申请。这份好意我是理解的,但是在我的抗拒之下理所当然地失败了。

再之后就是这一年的后半,大四上学期。按理说我应该在此时通过秋季校园招聘找到一份工作,但是由于履历的缺失、简历投递少,我并没有获得一份 offer。然后就到了现在了。

过去的一年大概上就是这样的情况吧。

可是为什么不行动起来啊

你说得对,错的是我。

可是为什么我会是错的呢?我其实也不太清楚,但是似乎有一些线索在……确实感觉自己有些地方不太对。

一个……应该是比较低的自我评价。毕竟一方面自己没有什么建树,另一方面 THU 计算机系真是人才辈出,无论是什么方面都能找到能碾压你的人,自然就无法自信起来。更可怕的是这种思维一旦建立起来,就很难从外界改变,别人的赞美会被当做是恭维,而就算真的做到了什么也只会有“这不是大家都能搞定的事情么”而没有什么成就感。这种自我评价甚至还会自我应验,因为怀疑自己所以不敢尝试,因为没有尝试所以把事情搞砸。可以说算是一个蛮严重的问题的。

还有一个就是害怕和逃避未来吧。确实大学这几年来并没有思考过将来的打算,或者说是在害怕这种不确定性而不去做这种思考。事实上我能确定的比较大的计划仅仅是不去做某件事情而已。我不知道我的前路该如何走,我也不去考虑,所以我只能这样子混日子混下去。

于是我就成为了一个没有行动力的人。没有目的就没有推力,害怕结果就会产生阻力,最后当然什么也做不到。

于是,我的困境

现在的我是一个没有毕业去向的人。工作肯定是要找的,但是就算我是 THU 计算机系的,没有个像样经历,GPA 又低于半数同学,我能得到一个还可以的 offer 么?

由此引发而来的是来自家庭的压力。我既然是 THU 计算机系的,那肯定能有不错的前程。就算这句话以一种鼓励的语气说出来,也会被理解成一种过高的期许,甚至是一种嘲讽。我不知道我该如何回应这种鼓励,更不用说批评和鼓励了。

更重要的是我要如何修复这种糟糕的心态,毕竟长此以往就算有偶尔的成就,也于事无补的。

我要如何重回正轨?

我不知道。

也许我应该行动起来,但是我要如何行动起来,或者说有什么能让我行动起来?

我真的不知道要如何回答这个难题。

也许我写下这段文字就能帮助我解决一些问题,但是也许不会有什么实质性的效果。

总之祝我好运吧。也祝你们好运。

ホロ's avatar

舞律炫步体(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 是有 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……
  • 和隔壁鹅舞形成了鲜明的对比……
依云's avatar

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 理解起来就容易多了,行为也更符合预期。

farseerfc's avatar

用 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 到了我的設備上, 我就能控制他的鍵盤了耶~

's avatar

莉兹与女装变态杀人魔的选择

有人提醒我 SSL 证书过期,于是我想起来,我还有一个博客。

或许是因为 acme.sh 更新,或是什么变化,总之就是挂了,十分遗憾。但挂在 GitHub pages 上的主页大多数情况下都不会挂,所以可以去那里看一看。

回不来的时间

新年的冬风,今年也是格外的刺骨。虽然没有新闻里芝加哥那么冷,但至少晚间在回去的路上,不穿上厚外衣,戴上手套,捂紧帽子,是免不了要瑟瑟发抖一番的。

农夫冻得手脚冰凉,在与蛇的战斗中,两手僵硬,有劲无处使,落得一个被蛇咬的下场。

元月27日或许是一切混乱的起点。

这一天,弄到了一个卖手机亏损的公司生产的家用主机。于是 Jirga Para Lhao 被拯救了。但 30 个小时就这样过去了。

青鸟不会做杀人的梦

我有时候会思考应该如何写一篇感想。

客观性是我试图避免的:我想写一些主观的、个人的感受,而不是所有人都会感受到、都可以表达出来的东西。我想写的是我个人的感想,而不是所有人的感想。之前的尝试在这一方面都不算是令人满意——大多时刻只是事实的罗列,或者是单纯的侃侃而谈。

聊天倒是也不坏。蔡康永的情商书(为什么我会看这么大众的书,不过转念一想,倒也有种别样的趣味)里就有“分身”这一说法。人每时每刻都需要和他人交流,但往往会忽视与自己的交流。与自己的交流听起来好像很奇怪。尝试培养另外一个不同的自己,跟这个自己对话。这可以说是一种审视自己的方式,也可以是一种批判性思考的方式。从这一个方向用尽九牛二虎之力也推不开的门,说不定换个方向就能轻松打开。

回到侃侃而谈。可能变成侃侃而谈也能从侧面说明,想从心灵这个湖里,捞出感想的鱼,不是件容易的事情,把捞上来的鱼卖给他人,也不是件容易的事情。不过鱼还没有捞上来,就想着销路,算是有点眼高手低了。

不过鱼有大的鱼和小的鱼,就像苹果有甜的苹果和不甜的苹果。大的鱼属于那种容易发现的。比如看完《活着》,感受到悲伤、无奈、沉重。不过转念一想,悲伤和喜悦都只是游在表面上的鱼,而在深水里的,是那种达观、顽强、活下去的力量,是这股力量支撑着人走下去。活着才有酸甜苦辣,活着才有风雨彩虹。

结果又变成万人都能说出的感想了。我大概不适合这差事。

同学聚会

参加了高中的同学聚会。令我惊奇的是,我没那么快活。

用一句大俗话来说,就是感觉少了点什么。

我曾经不止一次梦到过和高中同学搞事——建车站、开组会,无所不为。这或许这是我高中过于安分的反作用。搞事的时候我是快乐的,虽然在梦里的事都说不清楚,但大概的确是这样。

所以一个很大的可能就是,因为没怎么搞事。

灰姑娘是不是因为穿上了水晶鞋,所以不能自由奔跑了呢?

我翻遍了卡拉 OK 的歌单,翻遍了火锅的锅底,但都没有找到答案。

冬天来了,冬天还会远吗

在严寒中,在风雪里,食堂一个接着一个地关门了。有的等春暖花开之际会像燕子一般归来,有的则永远也不会回来了。

可我仍然没有吃到藤椒口味的浇汁饭。

IceHoney Blog's avatar

亚马逊S3服务简单介绍

最近在做后端的开发,需要一些二进制数据保存在服务器云端。团队决定调查AWS的S3服务是否满足需求,所以就做了一些调查工作。不过也遇到很多坑的地方。所以记录下来,防止以后再遇到。

基本需求

需要云服务有稳定性保证,并且可以批量上传文件。可以设置上传和下载链接的有效期。

AWS试用

AWS提供免费试用,但是注册的时候需要填写信用卡信息。确实有点不安,万一不小心被收费了就不好了。

生成上传凭证

我使用的是AWS的 JavaScript SDK。使用createPresignedPost API可以创建用于上传的凭证。这个凭证是根据用户的AccessId,AccessKey和Policy策略等计算生成的,并没有和AWS服务器直接进行交互。所以不用担心这个接口和AWS直接的流量费用问题。

var params = {
  Bucket: 'bucket',
  Conditions: [
    ['starts-with', '$key', 'path/to/uploads/']
  ]
};
s3.createPresignedPost(params, function(err, data) {
  if (err) {
    console.error('Presigning post data encountered an error', err);
  } else {
    data.Fields.key = 'path/to/uploads/${filename}';
    console.log('The post data is', data);
  }
});

官方提供的例子中,可以使用starts-with的方式来指定上传文件的key必须是以什么开头的,这样就可以指定上传的文件夹。很多文件也可以使用这一个上传凭证来完成上传。

上传Policy构造

AWS提供了一个详细文档说明如何构造合法的Policy:Creating a POST Policy。例如常见的需求就是在上传的时候添加meta信息声明文件的格式或者MD5值。 Policy的Conditions数组里面可以添加["starts-with", "$x-amz-meta-md5checksum", ""]。最后一个参数为空字符串代表可以上传任何数值。

构造POST表单

AWS也有文档说明了如何构造一个上传的表单。这个表单中最重要的是一句注释:The elements after this will be ignored。在file字段之后的所有信息都会被忽略掉,我测试的时候一直把x-amz-meta-md5checksum字段放在file字段之后导致上传一直报错。直到Stack Overflow上面有人解释了才恍然大悟。

构造下载链接

我们使用getSignedUrl API来生成下载链接,下载链接也是根据自己的AccessId和AccessKey生成链接的凭证,也没有和AWS服务器直接进行交互。当请求文件的时候,AWS再计算凭证是否有效。所以后端无需和AWS交互就可以返回客户端有效的AWS下载链接。针对需要返回实际文件的API接口,可以采用返回302的跳转链接来完成需求。示例代码如下:

var params = {Bucket: 'bucket', Key: 'key'};
var url = s3.getSignedUrl('getObject', params);
console.log('The URL is', url);

可能有人会问,这个API也可以用来上传啊。但是这个API接口必须指定key值,这样我们就需要为每个文件来生成一个独立的上传URL。这样太麻烦了。

总结

我们使用pre-sign的方式来生成URL主要是为了对客户端透明。虽然我们可以设置最小权限的IAM User给客户端,但是客户端很容易被逆向拿到敏感数据。这样难免会有风险,所以生成一个单纯的URL供客户端使用一定程度上保证了安全性也减少了客户端的复杂性。毕竟我也不想引入一个AWS的SDK进来。

's avatar

Transmission WebUI 批量添加磁链

抓到一堆磁链,手动加入下载很麻烦… 于是做了个简单的脚本。

(() => {

async function request (object) {
  return new Promise((resolve, reject) => {
    transmission.remote.sendRequest(object, resolve);
  });
}

async function addMagnets(urls) {
  for(let i = 0; i < urls.length; i++) {
    const url = urls[i];

    console.info('add %d/%d: %O', i + 1, urls.length, await request({
      method: 'torrent-add',
      arguments: {
        'paused': false,
        'download-dir': $("#download-dir").val(),
        'filename': url
      }
    }));
  }
}

addMagnets(`
此处填入地址,一行一个 (填入时删除此行)
`.split('\n').map(n => n.trim()).filter(n => n));

})()
ホロ's avatar

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 学习一下。

's avatar

拆解我爸 2010 年装的廉价 PC

2010 年,我爸觉得我家的 P4 台式机太过时了,所以就花 2k 托人组装了一台新 PC。

然而这台 PC 不仅卡顿时常发生,而且非常不稳定,经常死机、蓝屏,期间我还被母上大人认为我是让那台 PC 不稳定的罪魁祸首,因为我安装的那么几款软件,结果我没少被母上大人数落。😒😒😒半年以后,那台机器突然无法开机,甚至不会 POST,然后我爸只好把同一位 JS 叫过来进行维修。然后,JS 把那块烧掉的双敏主板换掉了。

2011 年,我爸给我买了一块 1TB 的希捷移动硬盘,但是在那台机器上带!不!动!,必须连接外置电源才能正常启动。

2013 年,因为母上大人实在不能忍受那台 PC,所以购买了一台戴尔整机(经过我的几次硬件升级,目前还在我家服役中)。而那台廉价 PC 就拿到我爸那边做监控机,结果半年以后硬盘就完蛋了,SMART 状态为不良,0x05 爆表。随后,我舅舅又拿来一块闲置 80 GB 硬盘,在我爸那边做工控设备,直到 2018 年 7 月彻底完蛋,甚至不再 POST 了。然后那台机器就在仓库里又放了半年。

2019 年,我把那台 PC 从我爸仓库搬了回来,决定看看还有没有什么利用价值。

做工廉价的机箱

这个机箱从外面看还像是那么回事,但是轻飘飘的,而且金属部分甚至会划手。

不过我丢掉了这个机箱才想起来忘了拍照了。

做工粗糙,而且接线的地方是用热胶固定的……什么鬼……

机箱内部

散发着寒意而且相当脏乱差的内部。

安装在主板上的 CPU 和 768 MB DDR2 内存。CPU 与风扇之间的硅脂所剩无几的样子,不知道是当年给我爸装机的那 JS 敷衍了事,还是发生了什么黑魔法。

AMD Athlon 7750。这台机器是 2010 年装的,但是据 @qwe7002 说,这片 CPU 在 2008 年就属于比较慢的了。

擦干净的主板,是 ASUS M2N68-AM PLUS。也是低端板子呢。

PHILIPS SPD2213,据说是市场上最便宜的光驱。

大炸弹

嗯,来自惠州高级工厂的产物。这台机器的不稳定,一定程度上就是这个大炸弹搞得鬼了(包括 USB 供电不足的问题)。

顺便这个序列号其实没什么卵用,因为看起来他家所有产品都用这个序列号。

于是我把大炸弹的风扇拆了出来,发现了绿色的奇怪地方。那是做什么用的呢?

原来特么是用来遮盖固定两组线缆的部分!看起来这玩意还是从奇怪的电子垃圾上迫真剪下来的风扇,然后这样凑合固定一下,就装到电源里面了。

结论

这台机器,最后除了两根 SATA 线被我拆了出来,被我原封不动的扔到垃圾桶了。

对于我们这种装机小白,看起来还是买品牌整机比较好。虽然性价比不是那么高,但最起码很靠谱啊。

以及便宜没好货。

ホロ's avatar

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
's avatar

从 HMV 英国站导出 CD 音轨信息

买了张 EAC 读不出自动填写信息的音乐光盘(freedb 服务),只好自己去网上抓一下音轨的信息。

HMV 英国 找到了整理好的表格,用脚本提取所有信息然后通过 mp3tag 批量导入。

导出脚本如下:

// HVM UK Track Info Dump Script for mp3tag by Jixun<https://jixun.moe>
// MIT License, use at your own risk.

document.body.querySelectorAll('.table--track-listing').forEach((disc, i) => {
  const pad = (n) =>  `0${n}`.slice(-2)
  const tracks = ([].map.call(disc.querySelectorAll('tr>td:first-child'), (x, i) => ({
    track: i + 1,
    name: x.nextElementSibling.textContent.trim(),
    artist: x.nextElementSibling.nextElementSibling.textContent.trim(),
  })))

  console.info('Disc %d\n%s', i + 1, tracks.map(track => `${track.artist} / ${track.name}`).join('\n'))
})

将每张光盘的导出数据另存为文本文档,然后在软件选中光盘文件,然后在菜单选择「Convert」→「Text File - Tag」,填入文本文件,以及格式填入 %artist% / %title%

点击「Preview」检查数据是否与光盘后面的曲目相对应,如果对的话就回到这个界面点击「OK」即可。

h404bi's avatar

历经数月,GitHub 章鱼猫寄来的 T 恤竟然……

Get Your Pull-Request Merged!

竟然寄到了,而且还有小惊喜。


起因是参加了由 GitHub 和 DigitalOcean 联合举办的 Hacktoberfest 2018 活动。据说已经是第五届了,活动目的就是鼓励更多的人对开源社区做出贡献,支持开源项目。在活动期间内在 GitHub 上发出并且被合并 5 次 Pull-Request,就能登记领取文化 T 恤。挺好的。

Hacktoberfest 2018

当时觉得 5 个 Pull-Request 被合并其实不难。倒是在想,这文化 T 到底能不能顺利漂洋过海来到手中。毕竟,我还有 2018 年中从宝岛台湾寄给自己的明信片到现在还是了无音讯的(悲伤)。抱着一丝希望,完成了任务填写了信息。之后就当作没有这回事不管了。

数个月后,突然收到邮政打电话过来询问是不是“茶某某”,说有份国际快件让我去自提。彼时我在上班砍需求中,一时没想起来,就纳闷我名字里没茶这个字啊,这时对面已经挂线了。缓过神来才想起可能是 Hacktoberfest 的 T 恤,就只好等下班去邮政仓库转一圈。

邮政晚上 9 点下班关门,赶着时间提前溜去了目的地拿到了包裹。

打码打码打码...

居然是从 Germany 德国寄过来的,我还以为是你大 USA 呢(图中的邮票是打码加上去的,谁会寄快件贴邮票哈哈哈),贴的满满的邮寄信息贴纸。这里有个小插曲要说下。去自提其实没有很顺利,到场后说是外国包裹,被告知要出示身份证并且不能代领。我不是代领,但是还是遇到了问题,在仓库现场根据我的身份证信息找不到包裹。我想到前面打电话叫我 “茶(Cha)某某”,才醒悟到当时填邮寄信息时,我心大填了英文名而不是姓名拼音。后面拿笔纸写了英文名才找到。被告知国家实行实名制,快件要写实名,不能只凭电话收取云云。还好最后拍了快件照片,让我签收了。工作人员要回收签收贴纸,但由于贴纸贴了太多不好撕,就让我现场剪开了包裹拿走了物品,留下了袋子。在剪开之前拍了上面那张照片。

经过这次后,觉得涉及实物相关的特别是跨国的东西,邮寄信息等资料最好还是写拼音。心大写英文还是不太行,有时候会造成麻烦。


接下来算是“开箱”。

除了 T 恤之外还有……

小惊喜就是包裹里除了一件 T 恤外,还有几张 Stickers。现场拆包裹时邮政的工作人员心细帮我拿了出来,不然我可能拿了件衣服就跑了。

整件衣服就是稍微浅色一点的酒红色。挑了最小号的,感觉刚刚好。正面一个大号 Hacktoberfest LOGO,右侧衣袖印了活动主办方的产品 LOGO,这样你穿出去就是“移动广告”啦。

DigitalOcean、GitHub 以及不认识的 Twilio。

Hacktoberfest 2018 LOGO 整件衣服所有能找到的图案 District - VERY IMPORTANT TEE

哈哈哈,我看得这个“VERY IMPORTANT TEE”的时候真的笑了。这衣服牌子起的名字真有意思。

面料产地

一半棉一半涤纶……倒是摸得出来棉量一般。产地 Honduras 洪都拉斯,拉丁美洲国家…… 所以这件衣服有飞了快一圈地球了吗?

Hacktoberfest 2018 LOGO 细节 Hacktoberfest 2018 LOGO 细节 Hacktoberfest 2018 LOGO 细节

其实可以很明显地看出来,衣服的 LOGO 印花做得是相当直接粗暴的,也有些“粗糙”吧。这种衣服,放洗衣机里拉扯几次,估计印花就烂的差不多了。所以这些文化广告 T 呢,很多情况下要么穿的话就手洗,要么就……不愿做移动广告,供起来做收藏咯哈哈哈……

Stickers

四张贴纸,分别对应 GitHub 章鱼猫、DigitalOcean 鲨鱼、Hacktoberfest LOGO 以及不认识的 Twilio。剩下那个大概是马克杯垫。贴纸是真的小惊喜了,章鱼猫挺好的。

Stickers

有 DigitalOcean 的新用户广告,还有让你收到衣服后穿上然后去 Twitter 上的 #Hacktoberfest 发推分享 2333。我在推上搜索看到有不少分享了,并且才知道除了这一款 DigitalOcean 联名的酒红色 T 恤外,还有微软款等其它款的!我觉得还更好看,有点羡慕……

来自推特用户 @tanhengyeow

看到大眼睛的回形针了吧!好赞啊。不过不管怎样,能收到还是很高兴,于是就记录下来了。有下一届的话,我应该还会参加的,嘿嘿。

Felix Yan's avatar

用脏办法解决 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 堆满了各种没有回答的错误报告,目测不是那么好修的……

ホロ's avatar

啥???三年了????

其实还是差几天😂

活动

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

问题

  • 文章的数量在下降?

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

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

计划?

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

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

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

な。

AlisterTT's avatar

2019开年的不高兴

2018年末的时候,一个朋友和我聊起去台湾玩的事,我想着挺好呗,干脆计划19年一起出去一波吧,今天和去过的同事仔细咨询了一下,把情况告诉我朋友,结果他丫的前些天已经去过了。

没办法只能另找人组队,问了一个基友倒是很乐意去,他们那边能去两对4个人,问题是我就处于一个电灯泡的状态了,他很随意的告诉我“你找个妹子不就行了”,真想抽他一大嘴巴子,感觉就像我傻呵呵的开了个团,结果因为自己单身的原因被踢出来了,头一次体会到了单身狗的绝望,比那种一个人去吃自助餐还凄惨,真不是开玩笑的,当时简直丧到极点。

现在的情况是,今年要想出去玩,还得先找个独立的队友才行,一个人出远门肯定会有诸多不方便,想想就头大呀,谁来教教我怎么办…

依云's avatar

解析 zxinc IPv6 数据库

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

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

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

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

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

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

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

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

's avatar

我的 2018

好耶,我终于把 2018 年瞎鸡巴过完了!让我们看看究竟发生了什么吧。

新增项目

大学以后,自由的时间越来越多啦,于是自己糊了一些奇怪的项目:

以及其它一些奇怪的多人合作和为别人糊的东西(小声

非主流氪金(?

没想到曾经作为网易云音乐、Spotify 等串流服务的忠实用户的我,居然在 qwe 前辈的影响下,开始买专辑听了。其中实体专辑占了相当一部分,而且基本上都是捡垃圾

同时终于意识到,听专辑其实是另外一种完全不同的听音乐的方式。一张专辑里面的曲目安排等等,按顺序听下来其实相当有趣的!而串流服务上的那些歌单,却把这些有趣的地方都掩盖了,就相当尴尬了(

以及

毕竟我还是相信那句话,要是真的喜欢的话,就花钱支持他们吧。(ref)

(我知道我的数字收藏还是比大佬们差远了 QAQ

设备的变迁

2018 年初,我给我家安装了网件的 GS308 千兆交换机,还买了块 2TB 的东芝监控盘和硬盘盒,用一部 NUC 搞起了自家的云存储服务。

然后我意识到我其实并不需要那么多存储……直到 2018 年底,我只使用了不到 200GB。毕竟以前很多垃圾文件盒所谓资源塞满了我的移动硬盘什么的,删除它们其实就没啥了。于是大概很长时间都不用担心存储空间不足的问题了。

蛤,你说那种网盘?我现在都几乎不用了(

以及手机的话,我的主力开始转向一部 iPhone 6S Plus 了(虽然是我爸淘汰的,他换了部高级黑色 oppo)。一个原因嘛,就是我跟 macOS 进行互联互通,不至于那么胶水化。以及 iOS 真的是不折腾党的福音啊!

杭州、上海、厦门

今年暑假,我做了件相当作死的事情:一个人去杭州、上海和厦门瞎几把玩。

(TODO:添加相关图片)

结果当然是不尽如人意的:我在杭州的最后一天中暑了,然后在上海的酒店休息了半天,最后潦草的去了趟外滩,隔着河观赏了东方明珠塔;同时中暑的其它后遗症一直持续到我的厦门行程,那是相当尴尬了……

不过其实游玩景点并不是重点。在这期间还是和许多在网络上认识的、从未谋面的人见了面,感觉相当开心!qwe7002、Librazy、TonyPrince、SJoshua、rsqppp、Jack Works、M0xkLurk3r,以及其它最终因故没有与我会面的朋友们,感谢你们的支持!

结果我关于美丽的景色毫无印象,却对与沙雕网友的交流印象深刻

杂项成就

  • 通过了英语四级考试

已知问题

  • 瞎几把花钱导致自己山穷水尽(比如 Bandcamp 上的音乐和各种蜜汁转接头
  • 我用的 MacBook Pro 没有 Touch Bar(因此也没有另外两个雷电 3 接口,导致我的外设设定是相当的 clunky 啊。。后悔死了,但我当时真的糊涂了
  • 对一些底层的事物了解不深
  • 很多东西只会瞎几把做,然后搞得一塌糊涂

2019 年要做点啥?

  • 把 Pomment 项目写到能够发布的程度
  • 去更多的城市旅行,包括但不限于南京 / 福州 / 广州 / 成都等等
  • 停止瞎氪金,买一些重要的东西:
    • Nintendo Switch
    • Hades Canyon
    • 2019 款 15 寸 MacBook Pro
    • 一个还行的 1080p 或 2k 显示器
  • 通过科目二考试
  • 把三次元的其它事情处理好

啊,差不多就这些了。

2019 年,大家要一起努力哦。

lwl12's avatar

Bye 2018, Hi 2019

L2019, runway 18R, clear for take off.


Cee's avatar

Oh My 2018

Summary

変わる世界、 変わらない私。

Moments

2 第一次在国外过年,跨年的时候正好在面 Tumblr

3 和郑老板的自由女神像之旅

3 HackNYU First Prize

3 Frank 走了

4 和腾壕、岛娘的日本 LongHash Hackathon

5 买了吉他

5 西海岸旅行

6 开始在 Tumblr 写 iOS

7 Miku Expo 2018

8 搬家

9 换了纽约州驾照

9 秋招开始

10 第一封 Offer,来自 GrubHub

11 Chara Expo USA

11 决定当一名 Googler 了

12 决战 C95(三日)

Input & Output

+ Sony RX100 VI

- iPhone 7 Plus (Jet Black)

+ iPad Pro 12.9-inch (Space Gray)

- iPad Pro 10.5-inch (Silver)

+ Sony WH-1000XM3 (Gray Silver)

- Sony MDR-1000X (Gray Silver)

Numbers

  • 9,567 photos
  • 0 posts (?)
  • 2,853 twitter followers
  • 760 instagram followers
  • 11 books
  • 245 contributions (only on GitHub)

Hall of Fame

The Next

  • 写完 One Clock!
  • 努力找到另一半😘(真丢人,退群吧)

PS:拖这么晚才发的原因是升级了系统 Ruby 挂了…没法生成静态网页

SgDylan's avatar

2018 年终总结

还有三天,2018 就要从指缝流走了。
是时候总结一下了。


ホロ's avatar

知识管理 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 放置文字内容。 然后在汝自己的知识库中放置各种文件。然后可以把它们一起加密起来备份到其他地方。

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

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

's avatar

以此纪念逝去的圣诞节

纵使有千言万语欲与诉说,坐到电脑面前便一个字也不想打。

放一个 Ujico*/Snail’s House 前几天的曲子吧。Magical Holiday。因为暂时上不了 SoundCloud,就放 Youtube 上的视频吧,也很漂亮。

另外,在点 Profile 的时候请戴上耳机。

别的留给新年再说吧。

依云's avatar

Ant Design 彩蛋事件之我见

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

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

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

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

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

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

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

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

farseerfc's avatar

【聽譯】君さえいなけりゃよかった

君さえいなけりゃよかった 如果你從未出現過該多好
降り出した雨の中で 君に出会った時から 下起雨的那一刻 從遇到你那時起
君がいないということが 当たり前じゃなくなった 身邊沒有你的情況 就已經不再是平常
ああ こんなはずじゃない 啊 不應該是這樣的
ずっと自分勝手にさ 過ごせたはずなのに 明明一直是散漫地過着自己的日子
まるで僕じゃないような僕が さらけ出されてくよ 就像是帶出了不是我的另一面的我

君さえいなけりゃよかった こんな気持ちは知らないから 如果你從未出現過該多好 就不會知道這種心情
やらなくちゃいけないことが 手つかずのまま積もってく 一堆不得不做的事情 堆在手頭越積越多
僕じゃなくてもいいのなら こっちを見て笑わないでよ 如果不是我也可以的話 就別看着我這邊笑啊
大袈裟じゃなくてそれだけで 忘れられなくなるの 甚至那些不重要的事情 都變得難以忘記了

君の適当な話も 全部心に刺さります 你無意間隨口說的話 全都刺在心頭
気にしなけりゃいいのにな 残らずかき集めちゃうの 雖說只要不在意就可以了 卻一句不剩全收集了起來
ああ こんなはずじゃない こんなはずじゃない 啊 不應該是這樣的 不應該是這樣的

君に出会わなきゃよかった こんなに寂しくなるのなら 如果沒遇到過你該多好 就不會變得如此寂寞
君じゃなくてもいいことが もう見つからないの 已經找不到 和你無關也可以的情況了
忘れられないから 君じゃなかったら 無法忘記了 要不是你的話

いっそ見損なってしまうような そんなひとだったらなあ 乾脆變成根本看不起的人 如果是那種人的話
でもそれでも どうせ無理そう 嫌いになれないや 但是即使如此 大概反正也不可能 無法變得討厭

僕がいなくてもいいなら いっそ不幸になってしまえ 如果不是我也可以的話 乾脆變得不幸吧
最後にまた僕の元に 泣きついてくればいい 最後還是會回到我身邊 哭着湊過來的話就可以
君さえいなけりゃよかった こんな気持ちは知らないから 如果沒有你該多好 就不會知道這種心情
やらなくちゃいけないことが 手つかずのまま積もってく 一堆不得不做的事情 堆在手頭越積越多
僕じゃなくてもいいのなら こっちを見て笑わないでよ 如果不是我也可以的話 就別看着我這邊笑啊
大袈裟じゃなくてそれだけで 甚至那些不重要的事情
君のこと 間違いなく 對你 毫無疑問
苦しいほど 好きになっちゃうよ 刻骨銘心地 變得喜歡上了啊

忘れられないから 君じゃなかったら 因爲無法忘記 如果不是你的話
君に出会わなきゃ 僕じゃなかったら 要是沒遇到過你 如果不是我的話
君さえいなけりゃよかった 如果你從未出現過該多好
SgDylan's avatar

简易 FM 电台搭建

发霉派发射 FM 最简单的方法是从 GitHub 找个相关的 repo 然后装上。
但是那样音质太菜了,所以有了本文。

h404bi's avatar

我都在用些什么 Chrome 扩展程序

Chrome 好用的一大原因是拥有各种各样数不清的扩展程序,丰富的扩展资源能给用户 带来许多方便的增强功能。可以说这可能是一篇 Chrome 扩展程序推荐文,但其实扩 展的使用跟个人平时日常生活的使用习惯是有很大关联的,比如喜欢浏览些什么网站、 使用什么服务、以及从事什么工作等等。
ホロ's avatar

备份 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 …
Phoenix Nemo's avatar

制作 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
Liu Yuyang's avatar

矮人要塞冒险故事:历法

关于矮人要塞中的历法
's avatar

感到烦躁?先休息一会吧

Stuck? Switch to “Play Mode” 有感。

摘抄:

... Instead of trying to get things right, I should put myself in “Play Mode”. From his email:

In “Play,” just write or work on something you want... At the end, if you like what you’ve done, bring it in... If you don’t, discard it... It’s okay if nothing comes from it.

粗翻:

与其烦躁的逼着自己去做某些事情(如工作时卡住),不如先撒会欢 —— 随便写、玩或者休息一会(比如一个小时);如果撒欢时做的事情无关的话,就先放到一边。

即使做的事情无关,但是心情却会因此好起来,能够继续专注于工作。

farseerfc's avatar

【譯】使用 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 添加好用戶最初做的事情就是安裝 …

17windy's avatar

[美羽释厄录] 0.95 发布贴 性能和游戏性大优化 12.07.2018更新

12月7日21点15分前下载的小伙伴拜托重新下载下,解决了一个蛙人关卡浣熊叶子无效的bug。

0.95更新日志:

1,感谢美羽和咲冥两位大佬的倾力支持,美羽和灵梦(卷)有了新形象,其中灵梦(卷)的形象由美羽进行了精确描述

2,伤害系统整个重构,优化性能至少50%,消灭卡顿!

3,载入功能升级,加载关卡更快更快更快

4,修改美羽的移动控制,改为弹幕类游戏通用的RAW方式,即按下移动键不会有加减速的缓冲和惯性,直接固定每次的移动距离,改善游戏体验

5,每个BOSS都有了特殊的弹幕风格,蛙人和大X王BOSS战重做,更有挑战性和观赏性

6,BOSS战胜利后会全屏消弹避免喜闻乐见

7,部分关卡的小怪会有偶尔的上下刷新

8,通常关卡整体难度下降,便于刷钱

9,美羽的特殊武器蓄能速度增加了50%

10,灵梦(卷)提供了增益!增加了30%-50%的资金获取量(视不同关卡)

11,部分武器进行了小改动,斩龙剑改造

12,战斗魔偶特殊道具更改为浣熊的叶子

13,修正了某个会导致美羽无敌的BUG

14,修正了英雄愿望有时只会造成一次伤害的BUG

15,修正了修改音量后部分关卡失效的BUG

16,灵梦(卷)商店增加了商品的描述提示,鼠标移到商品上显示

17,主菜单美化

新DLC关卡BOSS征集!请想要暴打美羽/被美羽暴打的碰友至喵窝社区论坛报名哦!

 

目前暂时只提供windows版,还望谅解。

下载链接:

0.95版本地下载

下载 Miu DB V0.95
点击次数: 200, 文件大小: 267.2 MB, 日期: 2018 12月 07

0.95版百度云分流 链接:https://pan.baidu.com/s/1ofJR7Ue4d_YGKgYiXOytAw 提取码:o19f

 

PS:之后可能会有一个月-一个半月的时间暂停更新,忙主要项目,不然会被卷素质三连~

ホロ's avatar

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

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

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

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

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

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

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

太长不看版小结

(来自 https://twitter.com/sissisiisi/status/1070522944298893312
  1. 全盘加密要小心冷启动攻击 …

's avatar

法国服务器将在一月迁移 终止部分服务

法国服务器准备不再续约了。

考虑到十二月没有时间来迁移网站,暂时决定将服务器续期到 2019 年 1 月 31 日。

届时受影响的服务:

  • 网易云音乐反代 - 关闭服务

其他服务会在一月中旬无缝迁移到新的服务器,不受影响。

AprocySanae's avatar

谁在里面

这篇文章完全是虚构的,比如我几乎晚上不加班,也没有会 JOJO 立的同事。毫无疑问我看过冰菓小说,当然日常系推理也并非冰菓的专利。

我的确寻思过写个和千反田类似的女孩放入书中,以读者的身份引出线索。但是构思时候很悲伤地发现我并不熟悉女性的思考方式。

文辞相当市侩,但是毫无疑问这才是我熟悉的生活。

's avatar

Redis Desktop Manager (RDM) 0.9.999 x64 个人编译版

官方的 Windows/Mac 构建版本需要订阅或做出贡献才能下载,否则只能自己编译。

用 QT 折腾大半天后终于编译好了。

已知问题

  1. 无法切换语言。原因未知,有懂 QT 的大佬指点一下吗?

说明

因为使用的是 VS2017 x64 编译器,需要 Win7+ x64 操作系统。

VS 2017 运行时下载:微软

RDM 下载

青色旋律's avatar

短暂的休止符

最近忙于生活,暂时没有更新,非常抱歉的说。

希望能早点安定下来,静下心来做自己想做的事情……青色的旋律只是进入了短暂的休止,并没有迎来终结。

更多的脑洞…… JavaScript 的教程等等等等,未完待续……

IceHoney Blog's avatar

前端开发地图应用的调研

我司的产品终于发布了新版本,所以忙碌的开发暂时告一段落。最近在做下一期的规划,然后就是要做前端网站来满足用户的需求。由于我们的产品是和地图强相关的,所以也对地图做了很多调研。

基本需求

产品需要在国内和国外使用,费用合理,可以换地图的贴图并且能在地图上绘制各种信息。例如多边形或圆形还有贝塞尔曲线。

MapKit JS

苹果居然也出了网页版本的地图产品MapKit JS,可谓是良心。但是目前还处于Beta版本。如果以后要考虑产品的全平台化,显然不是一个很好的选择。不过苹果的产品可以在国内国外使用不用太担心地图偏移问题,而且可以贴图和绘制图形,但是目前网页版还不能绘制贝塞尔曲线,iOS客户端倒是可以。

MapBox

MapBox是一个地图服务提供商,经过调研MapBox使用最新的WebGL技术来渲染,摆脱了传统的下tile来贴图的方式,渲染速度得到了大大的提升。也能解决国内和国外的地图显示问题,但是画图功能就只有画线和多边形。不过提供了底层的画图层的接口,需要自己写WebGL的shader。这就增加了开发成本。。。

GoogleMap

谷歌地图当然好,但是我最后才说。因为谷歌无法在国内使用,这种情况下我就不得不写两套接口来对应,例如国内高德地图,国外谷歌地图,会大大增加开发成本。而且谷歌地图最近刚升级付费条款,费用是按照请求次数来收,所以用户大量增长之后的开销也会非常大。不过谷歌也不能画贝塞尔曲线。。。

地理坐标系

由于是需要在地图上绘制新的tiles,所以自然就涉及到坐标的转换和计算。如何计算一个经纬度落在哪一张tiles上,以及在不同缩放级别下tiles的正常显示和重绘。这些都是需要自己来实现的。 这里有一个还算有名的官方介绍,并给出了Python的源码。可以参考这个来进行实现。

坐标系转换

每个国家都有自己的坐标系系统,虽然GPS使用的WGS 84标准非常流行,但是这个是美国制定的。每个国家当然都需要根据自己国家需要来定制自己的标准。例如中国就有北京54坐标系,西安80坐标系。北京54和西安80是参心坐标系,大地原点分别在苏联和西安。难以表达高度信息,目前国家正在推广2000国家大地坐标系,这个和WGS84一样是地心坐标系,即以地球质量中心为原点。日本也有自己的平面直角坐标系,我们当然需要各种坐标转换,还好有现成的开源项目proj4js

总结

各个地图服务商都各有优劣,但却没有一款完美的。主要是用途也比较特殊,可能在地图服务上进行二次开发的可能性比较高吧。不过提供地图服务的也没几家可以选择的。。。

ホロ's avatar

在 在 GNU/Linux 的桌面环境中设置自动切换壁纸 (GNOME 篇)

在 GNU/Linux 的桌面环境中设置壁纸,是怎么样的呢?

如何设置壁纸?

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 的桌面环境中设置自动切换壁纸

's avatar

网站部分功能下线 [已恢复]

VPS 因未知原因下线,问题还在排查中。

部分服务器的内容受到影响,包括:

  • 英文博客 (jixun.uk)
  • 评论系统 (c.jixun.moe)
  • 本站的静态资源 (s1.jixun.moe)
  • 托管于本站的资源 (jixun.downloaddl.jixun.moe)
  • 网易云音乐反代服务
  • … 以及其他个人用的子域名服务。

已经修复,根据 Uptime Robot 提供的数据,本次事件导致服务器下线总计 2 小时 25 分。

依云's avatar

通过 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

这样就大功告成了。

依云's avatar

正确地上传至 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 的资料是挺多的,但是细节不够详细,陈旧信息很多,唉。

Phoenix Nemo's avatar

使用 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

搞定(┌・ω・)┌超简单的吧。

's avatar

十一月十七日 -- 前女友小说,字体,摄影

今天没打游戏。

小说

磨了一点 Your Diary 的感想,就没动了,买了另外一本三秋的书,加上一本书凑免邮。反而是看纸城境介的继母的拖油瓶是前女友看到快 6 点。

很有趣的小说。男性向的。

因为看轻小说不用带脑子,所以这也是不带脑子的评论。这也是我的一种心理安慰。一个人如果因为一本无趣的小说而熬夜,那未免也太空虚了吧。

在访谈中,关于连载,作者纸城大致是这么说的:如果小说被印刷成书出版,那只能让读者享受 3 小时;而如果放在网络上连载,则能够让读者每周都享受 168 小时。

关于这部书有趣的地方,作者大致是这么说的:我写这部作品,就专注于这一点,而不是加入学园祭等各种元素来充实内容,这使得这部作品非常纯粹。

因为我记的不太清楚了,所以就不加 quote 了。当然这也不代表我个人观点,虽然说人会把记忆改造成自己想要的样子,但我觉得这观点怎样都好,所以就忘的差不多了,更别说根据自己的好恶改造了。

我个人觉得误会是这部作品的一个支撑,也是全篇反复出现的一个要素。男女主人公因为小小的误会,关系出现了隔阂,导致最终的分手。男主自认为讨厌女主,但心里还给女主留着位置,他并努力和女主保持着适当的距离;而反观女主,男主在面前的时候针锋相对,不在面前的时候变身大花痴。导致怎么看,都是变相秀恩爱。

这让我想起了作品时间和现实时间同步的一部网络小说,其天气也是忠实于日本某地的天气。可名字忘了。

今天下雨。

看了一点人间失格,感觉不能理解。先不管三张相片是想表达什么(从内容上看推测是概括了主角的一生),几页看下来,大致是一位神经性厌食症少年的独白。具体是不是还要继续往下看。

摄影

我不摄影。

看了一篇关于 Magnum Contact Sheets 的博客,讲的很长很详细,地址忘了。

Contact sheets 是在底片时代,摄影师为了降低成本,就先把底片的缩小版印下来,再在其中挑选想要的照片。从 contact sheets 中可以看到摄影师的思考,过程,以及失败。Magnum 是有名的摄影师社区,其成员都是经过遴选的,因此这本书里的 contact sheets 也可算是大师级别的作品。

看到 Dali Atomicus 的时候,我以为里面的人是随便一个演员,结果一查是达利本人,而其创意也来自达利的画 Leda Atomica,里面的物体都是漂浮着的,在照片中该画被悬在右侧。照片里的猫也是真的,是助手丢出去的。大概那时候没有动物保护组织,可以随便来。照片一共拍了28次,可以说不管是摄影师,达利,打扫的人,还是猫都辛苦了,猫还会被水浇到,所以可能最辛苦。

总而言之,文章想对广大摄影爱好者表达的几点建议,一个是多拍,一个是拍了要看,一个是以前拍的也要看,说不定会有新的发现(因此不要立即删掉觉得不好的照片)。

字体

方正面向移动端阅读,推出了方正悠宋。当然要钱,而且不能发布。因此我没用。当然如果遇到什么好的免费的衬线体,大概是会换的,不然英文是衬线,中文是黑体,不免有些不协调。

注:移动端是这样,电脑端可能不是这样。

Hymmnos 字体也会加回来的,大概。

其他的记不清了。

想不到要写什么了。

's avatar

Fedora 29/30 安装 FCITX 输入法 + Rime/拼音

上图为安装后的效果

安装 fcitx 本体包

首先安装适配各种程序的基础包:

sudo dnf install fcitx-{ui-light,qt{4,5},table,gtk{2,3},table-{extra,other,chinese},configtool}

安装「中州韵」

因为官方源没有,而 FZUG 也去掉了这个包,因此我在 Gitlab 部署了一个适用 Fedora 29/30 x86_64 架构的 fcitx-rime 源:

# 启用 fcitx-rime 第三方源
sudo dnf install https://fcitx-rime-fedora-jixun.gitlab.io/fcitx-rime-fc$(rpm -E %fedora)/RPMS/noarch/fcitx-rime-jixun-release-$(rpm -E %fedora)-0.1.noarch.rpm

# 安装中州韵
sudo dnf install fcitx-rime

如果不想安装第三方源,可以安装普通的拼音(或带有词频的 sunpinyin):

# 标准拼音输入法
sudo dnf install fcitx-pinyin

# sunpinyin 拼音输入法
sudo dnf install fcitx-sunpinyin

Gnome 下启用 fcitx

首先安装 gnome-tweaks

sudo dnf install gnome-tweaks

在开机启动添加 fcitx

放入 /etc/profile.d/fcitx.sh

sudo tee /etc/profile.d/fcitx.sh <<EOF
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS="@im=fcitx"
EOF

如果需要输入法托盘图标,则需要到应用中心安装 Tray Icon 这个插件。

如果需要使用 Win + 空格组合键切换输入法,则需要先到 Gnome 设定将原始输入法切换键关闭(设定新按键处按下退格禁用快捷键)。

最后重新启动电脑即可(也许重新登陆也可以?)。

Cinnamon 下启用 fcitx

运行「im-chooser」,在弹出的界面选择 fcitx,然后登出重新登录即可生效。

FZUG 的 fcitx-rime 源

因为 FZUG 的源不再提供 fcitx-rime,此处内容进供参考。

# 启用 fzug - 中文社区源
sudo dnf install https://mirrors.tuna.tsinghua.edu.cn/fzug/free/29/x86_64/fzug-release-29-0.1.1.noarch.rpm

# 关掉 fzug 的 non-free(非自由软件) 源,因为这个源并不存在
sudo sed -i.bak 's/enabled=1/enabled=0/' /etc/yum.repos.d/fzug-nonfree.repo

# 安装中州韵
sudo dnf install fcitx-rime
's avatar

100% 橙汁修改器更新 (4.0)

更新 4.0

很久没有更新这个修改器了…原因是对修改器进行了重做,现在改用 C++ 开发,抛弃掉 .net 环境。

支持联网获取修改器所需数据,希望能解决每个版本的游戏都需要重新编译修改器的问题。

缺点:

  1. 不支持离线使用。每次点击“寻找游戏”都需要联网查询所需数据,可能在后续版本会建立一个缓存机制。
  2. 不支持 XP,也希望我能不需要支持 XP。如果真的需要 XP 的支持的话,请在留言告诉我,我会更新编译器使其兼容。

以后如果不是游戏有大更新,修改器应该也不用更新。

100% Orange Juice 修改器

Felix Yan's avatar

为 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(咚咚咚,敲门声

's avatar

如何被 GitHub Pages 蹬鼻子上脸

被什么蹬鼻子上脸?

GitHub Pages 是 GitHub 不知道在哪一年推出的网站托管服务。用户将网站内容放在一个 GitHub 仓库中(无论仓库是公共还是私有的),然后喝口水的功夫,网站就建立起来了。

GitHub Pages 有如下几个好处:

  1. 不要钱(以这种寒酸网站为基准)
  2. 方便,一键部署,一键 TLS
  3. 使用 GitHub CDN,不容易炸
  4. 炸了也是 GitHub 背锅

用户可以通过如下的几种方式部署 GitHub Pages:

  1. 使用名为 <username/org name>.github.io 的仓库作为网站的根目录 (webroot)
  2. 使用一个仓库的 mastergh-pages 分支作为网站的根目录
  3. 使用一个仓库的 master 分支的 docs/ 文件夹作为网站的根目录

在方式 1 下,默认可以通过<username/org name>.github.io 访问建立的网站;而在方式 2 和 3 下,默认通过 <username/org name>.github.io/<repo name> 进行访问。

除了给定的域名,GitHub Pages 还提供了自定义域名的选项,支持 example.comwww.example.com 形式的域名。具体看 wiki 。

被 GitHub Pages 怎么上脸?

通常来说,建一个博客需要如下几个部分:

  1. IP
  2. 域名
  3. 服务器
  4. 内容

使用网页托管服务,相当于用户交出了对服务器的完全控制,这有其两面性:用户可以不管什么阿帕奇,什么引擎X,但用户在服务器层面上能有多大的自由,完全取决于托管服务商的支持。

在 GitHub Pages 为例,用户失去了:

  1. HTTP redirect 的能力,具体来说,用户只能用一个 meta 标签做重定向,而不是返回 HTTP 301/302 进行重定向。
  2. 个性化错误页面,只能按照 GitHub Pages 的要求指定一个网页作为 404 页面(虽然大多情况下这就够了)。

你说的我都明白,所以这又怎么了?

其实没怎么。

由于上一篇博客中做的修改,现在的 RSS 变成了一个到中文 RSS Feed 的 HTTP 重定向。用 GitHub Pages 会使得无法重定向,导致 RSS 订阅会掉。

另外一个没有提及的问题是 GitHub Pages 的罪恶连锁:

不使用 .github.io -> 自定义域名不能使用 CNAME -> 自定义域名使用 A 记录 -> 每次部署的时候报警

以及

不使用 .github.io -> 自定义域名不能使用 CNAME -> 自定义域名使用 A 记录 -> 随机 302

其中第二个问题是由于 GitHub 方面需要平衡负载而导致的。

下一步?

再说。

's avatar

育碧 key 切断了那条蛇

Yubikey & PAM

之前没看懂 PAM 怎么用,今天重新看了一下pam(8),打算搞好之前想弄的 yubikey 解锁桌面。

pam(8)的结果:这在说什么?

看了一篇讲 PAM 的博客:噢,我明白了(没有懂),甚至应该修改 /etc/pam.d下的哪一个文件都不清楚。

还是另一篇博客让我豁然开朗。

先在 Arch Linux 上安装yubico-pam包。

然后修改/etc/pam.d/system-auth,将下面一行添加到 auth required pam_unix.so ... 那一行的前面。如果添加到后面的话,还会先调用 pam_unix.so 来索取密码,而且失败了就失败了,并不能 fallback 到 Yubikey 登陆,然而将 sufficientpam_yubico 放在最前,当 yubikey 验证成功了就一定成功。

如果写的是 required 而不是 sufficient ,结果就是不仅要 yubikey 验证成功,而且还要接着再输一遍密码,相当于倒过来的二步验证。

auth sufficient pam_yubico.so id=<yubikey API id> authfile=/etc/yubikeys

这样就大功告成了!现在 sudo,解锁屏,登陆都可以用 Yubikey 一摁完成了!

当然,如果 KDE 的用户

  • 只想用它解锁屏,就把这一行放到 /etc/pam.d/kde 里的对应位置,注意当前用户需要有 authfile 的读权限,否则无法使用
  • 只想用它登陆,就把这一行放到 /etc/pam.d/sddm 里的对应位置

如果只想用 yubikey 登陆 console (估计没有这样的人),就把这一行放到 /etc/pam.d/login 里就行了,ssh类似,大概。

而如果想离线也能验证,或者嫌在线验证时间过长的话,就换用 challenge-response 模式就可以了。具体见 Yubico 官网的相关页面,就懒得再翻译一遍了。设置好之后甚至连一摁都不需要了。

Arch Wiki 关于 Yubikey 的条目可以说比较混乱,而 Fedora Wiki 的页面则较为简洁直白,可以作为参考。

顺便一提,也是 Fedora Wiki 告诉我有 modhex 这种东西。 Yubikey 作为键盘输入,它只会向机器发送键盘扫描码,机器再将其转换为按键。因此 Yubikey 不能控制键盘的 layout ,也就导致如果随意输入,在不同的键盘 layout 上可能会输出不同的字符。比如QWERTY的Y,在德语键盘上就成了Z(它交换了Y和Z),而在日语键盘上差不多就是假名 N (说差不多的意思是在假名输入下才是 N)。因此 Yubikey 选择了那些在任何键盘 layout 下都不会变的16个字符,用以表示16进制数,这就是 modhex 。

请关掉假名输入!不然そそそそそそりこはすいきまにすこまきましすいりそなままりこのかいそひひしきのにすきしのき

中断

今天读了一篇关于硬件中断,以及如何用 PIC 处理的博文,因为没怎么看懂,就不翻译了。

玩蛇?玩个蛇皮!

Arcaea 潜力值终于上 9 了,或者说,才上 9 。啊……

慢慢来吧。

imi415's avatar

Mbed OS 5的自定义开发板移植 - NRF51

前言

最开始看到Mbed OS5的时候没太在意,然而最近Nucleo买多了就变成了……

真香!


步骤

正好手头的BLE开发板就又开始痒痒,那就上咯

手头的NRF51开发板是微雪的NRF51822开发板,芯片型号为_AC,意即32KB SRAM+256KB Flash的型号。我们首先用Mbed CLI新建一个项目,起名叫nrf51_hello就好了。

mbed new nrf51_hello

会在当前目录创建工程目录,随便写一个main.cpp,包含main函数用来对付链接问题((

#include <mbed.h>

DigitalOut led(LED1);

int main() {
        while(true) {
                led = !led;
                wait(0.5);
        }
}

嗯,点灯工程师。

于是我们来处理板子的问题。Mbed OS 5的大致结构如下

's avatar

面向人气编程

我设计一款软件有个毛病:常常设计一大堆自己根本用不上的无用功能,并美其名曰『为了我的用户』。

但是为什么我常常这样想?为什么我要觉得他们喜欢的东西就是我必须做的?为什么我要追捧他们喜欢的无用功能一大堆的软件?

为了讨好他们。

我从以前就有一种错觉:当我的软件变得有很多人使用,便是黑魔法发生的时候。越来越多的人会对我产生好感,那些 block 了我的人会 unblock 我,我的安全感会得到越来越多的提升,并得到更多的自信。

但是别人的实践却在给我自己打脸。贴吧签到助手等一系列开源软件,都是人气很旺的东西,但为什么最后它们都停止开发了呢?总会发生一些奇怪的事情吧。

其实我这种思想就太矛盾了。毕竟当使用我软件的人越来越多,用户群的质量自然会逐步下降啊。

市面上还有很多软件有很多在实践中没用的功能,但它们其实并不是程序员设计出来的,他们只是在实现既定的计划。那么既然我有机会自己设计和开发一款软件,为什么我就不能做的简单一些呢?

所以在接下来的 Pomment 开发中,我还是放弃那些思想,只开发我自己需要的功能好了,毕竟我这轮子首先还是为我自己服务(

lwl12's avatar

更新至第三代服务器环境 | Docker 萌新体验记

博客算是 lwl 第一个用上 VPS 的项目了,和很多初学者一样,lwl 一直在使用一键包来完成服务器环境的架设。随着时间的推移以及请求量的增加,现有的服务器环境维护变得越来越困难,甚至开始出现了一些无法找到原因的问题。为此, lwl 决定开始着手设计和部署第三代服务器运行环境。
IceHoney Blog's avatar

后端开发的技术总结

说实话,最近前端开发的事情并不是很多。所以自己也慢慢开始做后端开发,逐渐向全沾工程师靠拢。现在的开发工作,分工分明,后端也只需要专注API的请求与返回就好了。

API文档

使用API Blueprint作为API规范,并使用RSpec API Blueprint来自动生成文档。 生成的Markdown文件,可以很方便的转换成网页便于客户端开发。例如这个工具aglio

后端开发

现在采用的开发技术框架是Ruby on Rails。不得不吐嘈一句,Ruby on Rails在日本真是压倒性的流行。Ruby on Rails还是MVC架构,原生支持RESTful API。但我觉得下一代的接口标准应该是facebook推出的GraphQL,不过先阶段RESTful API也足够了。

Models

Models主要是用来描述数据库结构,表与表之间的关系。还可以定义对数据库操作的方法,数据之间复杂的业务逻辑基本都是放在这里。

Views

Views主要是用来定义相应的数据的格式,把数据整合成统一的JSON标准供客户端使用。

Controllers

Controllers是请求的入口,用来定义请求的参数,并接收请求进行参数的过滤处理。然后调用Models里定义的方法完成数据的操作,并调用Views来完成数据的响应。

权限管理

权限管理是一件非常复杂的事情,定义某个接口在什么条件下可以调用,需要检查用户是什么身份。所以推荐是使用现有的成熟框架来进行管理。这里使用pundit来管理各个请求的权限检查。

软删除

在实际的项目中,我们需要进行软删除操作。例如用户加入了某个组织,以组织成员的身份发表了文章。当用户退出这个组织的时候,我们并不能直接删除数据库记录。否则无法显示文章的作者。这时候我们就需要软删除操作,对用户来说这条记录已经消失了。但对开发者来说,这条记录还是需要的。我们也使用框架来解决这个问题,这里采用的是Paranoia

测试

后端开发是偏向于纯逻辑的开发,所以测试非常重要。正常情况下的输入输出非常简单,代码的80%都是需要考虑到各种各样的边界条件。需要考虑到用户的各种不同情况下的操作,给出合适的错误提示。所以需要完善的测试来覆盖所有场景,这里采用的是e2e测试,模拟请求,测试后端服务器的响应输出是否符合预期。采用的测试框架是rspec-rails

参考:

Ruby on Rails Guides

via these people and places