Hypercube's Channel
68 subscribers
35 photos
2 videos
2 files
20 links
随便搞的一个 channel,还不知道会变成什么样

可以使用 Telegram 的转发功能转发消息
Download Telegram
浏览器里的 canvas 好难用。说两个听起来很简单但实际上很难实现对的需求:

1. 让 canvas 的像素和物理像素一一对应,来确保绘制出的图像是像素级完美的。很多人知道 devicePixelRatio 的概念,以及 1px 并不真的是一个物理像素,但不少网站错误地假设 devicePixelRatio 一定是整数。还有一个概念叫 visualViewport.scale。1px 其实对应 devicePixelRatio * visualViewport.scale 个物理像素。

2. 在 1 的基础上,确定鼠标所在的精确物理像素,以便在鼠标所在处绘制内容。鼠标相关事件中给出的几种坐标都是以 px 为单位的整数,由于 1px 不是一个物理像素,鼠标肉眼可见地移动了几个像素时,JS 获取到的坐标经常并没有变化,相关信息在取整后丢失了。screenX 和 screenY 是以物理像素为单位的,不会丢失信息,但并不容易把它换算到 canvas 坐标系,我还没发现任何可靠的方法获取 canvas 在 screen 上的物理像素坐标。
GitHub 发布了 fine-grained personal access tokens。以前这个问题很难解决:你和别人在一台服务器上合作,你们希望这台机器有权限读写某几个 GitHub 私有仓库。
1. 某个人在这台机器上创建一个 SSH key 并添加到自己的 GitHub 账号,坏处是合作者可以访问他的所有私有仓库了。
2. 某个人创建一个 personal access token 并放在这台机器上,坏处同上,因为 personal access token 不能按 repo 设置权限,只能允许读写所有私有仓库。
3. 为每个仓库创建一个 deploy key,坏处是要管理很多个不同的 deploy key,执行各种 git 命令时都要选择正确的那个 key,很不方便。(GitHub 不允许任何 deploy key 相同)

这个新功能就是给 2 加上了细粒度权限设置,一个 personal access token 最多可以拥有 50 个仓库的权限。可惜不能为每个仓库分别设置不同的权限,目前只支持指定一堆仓库,再指定对所有这些仓库都拥有什么权限。

https://github.blog/2022-10-18-introducing-fine-grained-personal-access-tokens-for-github/
一般的 Linux 包管理器都做不到这两件事:
1. 一个软件包的多个版本共存。当两个软件包都依赖第三个软件包时,只能选一个版本装,不能装两个版本分别给两个软件包用。
2. 非 root 用户方便地安装喜欢的软件版本和所有依赖。如果系统装了 vim 8.2,非 root 用户想用 vim 9.0 就只能自己找来所有依赖,编译安装,没有包管理器这样方便的方案。

为什么一个软件在整个系统中只能装一个版本呢?存储不同版本的软件以及依赖,让它们各用各的依赖,听起来并没有本质上的困难。我最近研究了一番 Nix,它看似可以解决这种需求,但实际上它使我意识到了这里实际的困难。

各种软件里面都有写死的其他软件的名字或路径(一般不带精确版本),Nix 打包时改写了这些内容,为它们加上了精确版本。这样一来,两个软件可以分别调用自己的依赖,互不干扰,这些依赖也都不会暴露给最终用户。最终用户如果也想用这个依赖,要自己指定想用哪个版本(可以是和这两个软件用的都不同的第三个版本)。

但是 Nix 并没有改掉一切,例如 git commit 会自动调用 vi 来编辑提交信息,git diff 会自动调用 less 来分页,Nix 并没有将 vi 或 less 视为 git 的依赖并锁定版本。我想这是比较合理的,因为用户会希望用自己喜欢的 vi/vim 或 less 版本,而不是 git 这个软件打包时锁定的某个版本。虽然 git 提供了配置选项来自定义使用的命令,但默认值也是很重要的。如果每个软件都必须自定义一番才能用上自己在全局安装的 vim 或 less,体验应该会很差。

还有一个小问题是家目录中的配置文件和数据,如果系统中装了多个版本的 vim,却共用一个家目录下面的 .vimrc 和 .viminfo,很可能会出现问题。如果试图让它们用不同的家目录,恐怕不仅不会解决问题,反而可能会更混乱。

所以这里存在本质上的矛盾:所有软件的所有依赖都被锁定和相互隔离的话,好处是省心,依赖都是开发者预期的版本,自己写的程序随便起名也不会被意外调用,坏处是用不上自己喜欢和熟悉的版本,家目录中的数据文件可能不支持不同版本的程序读写,以 daemon 形式存在的服务可能无法工作(因为 client 和 server 版本不一致,例如 git clone 时 git 自己的 ssh 版本可能无法连上 control master)。更高层的应用程序可能还好,对于底层的各种基础工具(git vim curl less ssh 等),看来想实现不同版本共存确实有难度。
我怎么解决 Linux + 高分辨率屏幕的缩放问题(MATE 桌面环境,不考虑多显示器缩放比例不一致的需求):

先确认屏幕的真实 PPI(每英寸像素数,可以用尺子量),我的屏幕是 213。

在 /etc/lightdm/lightdm.conf 中设定真实 DPI:
[Seat:*]
xserver-command=X -dpi 213

确认 Appearance - Fonts - Details 中 DPI 设置为 142。确认 MATE Tweak - Windows 中 HiDPI 设置为 Regular。这两处改了的话很多程序会出现文字尺寸、图标尺寸、控件尺寸之间不匹配的问题。

在 Appearance - Fonts 中设置自己喜欢的字号,对于我来说,默认值(10、10、10、10、11)就不错。
https://gwern.net/Turing-complete

这个博客里面超链接的机制真不错,虽然有点疯狂😂我也希望能给我写的东西加上这样的超链接,各种术语不懂的话都能一下子就看到是什么意思。

虽然复制粘贴 Google 一下也行,但更简单的操作确实会让我更多查一些东西,原本我可能只有特别想知道含义的术语才会去 Google。另外,每个链接按作者的意图,有的展示 Wikipedia,有的展示一篇论文,有的展示作者的另一篇文章,有的展示当前页面的某个段落(真的跳过去的话也会有点烦),确实比读者自己 Google 要好。
https://humanbenchmark.com/users/63df251ed6060e00087176bf

玩了这么久 CS:GO reaction time 还是好差

感觉几个关于 memory 的测试不是很有参考价值,结果很大程度上受运气影响——随机生成的内容是否恰好比较容易记住

对触控屏的支持有 bug
Forwarded from Welcome to the Black Parade (Ashes)
馒头的 real world haskell in 2023,充满了 Learn You a Haskell for Great Good 等书学不到的现代 Haskell 工业界的最佳实践: https://notes.0x01.me/
真是太过奖了
因为以前很久没有好好刷牙,牙结石和牙龈发炎比较严重,最近开始关注这个问题。

目前做了洗牙,但改善有限,医生认为有必要做龈下刮治,是需要麻醉进行的操作,可怕😨自己研究了一番,感觉结论也是应该做,不做的话继续发展下去会导致损害牙根和牙床,过早掉牙。另外即使做了这样的治疗,仍然要坚持良好的卫生习惯才能有效。

牙龈和牙齿之间出现缝隙(“牙周袋”)是不好的,刷牙的一个主要目的就是破坏这样的缝隙中的牙菌斑。如果牙菌斑连续 12~24 小时没被扰乱,就会形成无法靠刷牙去除的牙结石,导致牙龈发炎并加深缝隙。所以正确的刷牙方式要求将刷毛指向这些缝隙,稍微伸进其中振动来破坏牙菌斑。每天应当刷两次牙以保证及时破坏,还应当用牙线处理刷牙时不容易触及的牙缝。

牙龈发炎时,用上述正确的方法刷牙非常容易导致出血。打算试试使用超声波电动牙刷,或许可以避免大幅运动伤害牙龈,还能更方便有效地破坏牙菌斑。

网上很多人提到冲牙器,我的调研结论是好像不必要,使用不当的话还有一些坏处。每天刷牙和使用牙线应该就合适了。
https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/

推荐使用 HTTPS 而非 SSH 的 git remote,有若干好处,包括不需要在 remote 换 host key 的时候手工信任新的 key,以及不需要确保手工信任的 key 真的是正确的。

使用 HTTPS 时,会询问用户名和密码,如果开启了 2FA 的话,密码这里不能输 GitHub 账号的密码,要输入在 https://github.com/settings/tokens 创建的 token(创建时设置合适的权限)。

设置 git config --global credential.helper store 可以做到只输入一次用户名和密码,之后会自动使用之前保存的。
https://xdgbasedirectoryspecification.com/

如今很多人主张程序不应该创建 ~/.steam ~/.ssh ~/.bashrc 这样的文件或目录,而应该按照 XDG Base Directory Specification,把它们都挪到 ~/.cache ~/.config ~/.local 里面。

我一直认为这种主张是奇怪和讨厌的。参见 https://lists.debian.org/debian-user/2014/11/msg01817.html ,XDG 标准是在解决 desktop 场景下,不同的程序需要共用配置文件的这个需求,例如每个图形界面实现都要从同一个目录中读取用户安装的应用程序列表。XDG 规定了这类共享的路径的位置,而 XDG Base Directory Specification 只是 XDG 规定的一个组成部分,它的效力并不应当延伸到 XDG 解决的问题范围之外。~/.steam ~/.ssh ~/.bashrc 这类情况都只和一个特定软件相关,并不需要多个软件共享路径,是遵守 Filesystem Hierarchy Standard 的,和 XDG 无关。

这个网页上举的“clean and tidy”的例子中,家目录竟然还有 ~/.bashrc~/.profile。如果 bash 的 rc 文件可以破例留在家目录中,~/.bash_history ~/.vimrc ~/.ssh/id_ed25519 不能也留在家目录吗?这些都是非 desktop 场景下常用的文件,没理由因为 XDG 这个规定就挪走。

有人会说家目录里面太乱了,看着不整洁。把这些东西挪到别处就不乱了?这只是把乱藏起来了而已,想藏起来的话,ls 不要加 -a,文件管理器设置成不显示隐藏项目,不就行了?这些人可能觉得自己永远不需要和这些文件打交道,所以不在意他们的主张会让别人使用这些文件时变麻烦。

这些人跑去给各种项目提 issue,很多时候开发者没时间好好研究这里面是怎么回事,就按要求修改程序的行为来“遵守规范”了,这让我觉得很坑,我又没有精力去盯着各种项目的 issues 一个一个反驳。不过说不定再这样下去,这样做的程序越来越多,就真的成为新的惯例/规范了🤪
阿里云:硬盘可以在线扩容,然后需要手工执行命令扩容分区和文件系统,全程 0 downtime。
DigitalOcean:关机时可以扩容硬盘和升级配置,会帮你扩容分区和文件系统。
AWS Lightsail 和 Azure VM:完全不能扩容,自己打个快照然后去删除重建机器吧。

我来用云不就是为了能灵活地 scale??
我在 AWS Lightsail 上有一个一直在记录数据的数据库,不希望有 downtime,但最近系统盘快要装不下了,我决定把旧的数据备份到别的地方,这台机器上只保留最近一段时间的数据。

但剩余的硬盘空间不够把旧数据打包成备份,AWS Lightsail 又不能扩容硬盘。为了没有 downtime,具体执行的时候,我创建了一个另外的 block storage,暂时挂到机器上,把备份打包到里面并传输走,然后再把这个 block storage 删掉就好了,只用一小会几乎不产生费用的。

(是的,我知道我可以一边打包备份一边串流到别的机器,没必要全存储在硬盘上的。但反正用一小会 block storage 几乎不花钱,这样方便一点。)

现在我全都搞好了,打算删掉这个 block storage,才发现虽然当初不用关机就能 attach,但现在必须关机才能 detach,必须 detach 才能删除,必须删除才能停止计费。

傻逼 AWS。
在买了 Undertale 5 年半之后终于玩了,真是不错。角色和剧情设计我非常喜欢,战斗的难度也是恰到好处。

游戏过程:
- 因为反正不用打就能解决战斗,所以一开始就走的是和平路线。
- 遇到 Napstablook 时发现不打就走不了,只好杀了。
- 和 Toriel 战斗时发现不打也能通过,意识到任何 NPC 应该都不用打,于是 reset。
- reset 之后一路到底,发现 Asgore 必须 fight?!
- spare Asgore,fight Flowey
- 我没进 true pacifist route?我没和 Papyrus hangout??我去他家里了啊!还把所有东西都查看了一遍。哦,原来是没在他的房间和他对话,只在客厅和他对话了。这也太不明显了吧。
- 补 3 个朋友任务,打最终 boss,回去找所有人说话,看结局。
- 狗狗,嘿嘿嘿,长脖子狗狗,嘿嘿嘿。


拖了这么久才玩主要是因为我知道玩它会花比较多时间和精力,而它应该是个很棒的游戏,所以我希望专门找出较大的整块时间来认真玩。没想到一等就是 5 年半,唉。
之前重装 Windows 时把一些游戏的存档搞丢了,这次特别仔细检查了一遍所有 Steam 游戏的存档情况。大部分游戏好好地在用云同步,但有相当不少游戏没有在用,或者(更糟)看起来在用云同步但其实并不云同步所有数据。各个游戏保存数据的位置真是五花八门:
- 多数游戏保存在家目录下面的 AppData 或者 Documents 等目录中,备份家目录就能覆盖,还行。很多支持保存和读取无限数量个存档,或者存档文件比较大的游戏,都并不把存档文件云同步,只同步一些比较小的非存档数据,要当心。
- 有游戏保存在游戏本身的安装目录下,这种感觉很容易丢,因为不了解的玩家很可能会以为 steam 安装游戏的目录没有备份的必要,重装系统或硬盘空间紧张时可以随意删掉,反正能再下载。
- 有游戏保存在 C:\ProgramData 目录下。
- 大多数游戏都会在注册表中存储一些信息,注册表是完全不支持云同步的。居然有游戏把存档也保存在注册表中,不在文件系统存储任何信息,给备份带来了特别的麻烦。
很多平台最近统一将“帐号”改成了“账号”,虽然我一直不太确定哪个更正确,尤其是考虑到“帐本”等说法看起来还蛮正确的。但总之现在有一个可以遵循的标准了,是好事。我日常在文案中还会注意的其他几个词:
- “其他”(“其它”永远不是正确的)
- “登录”(除非在讨论“登陆”一个岛)
- “账号”、“账目”、“账本”,全部统一用“账”字而非“帐”字
- “发帖”、“帖子”(除非在讨论百度“贴吧”和上面的“贴子”)
- “请稍候”(除非在说“稍后”将会发生某事)
#生活观察
搞了一个电动自行车。
Chrome(以及 Edge 和 Chromium)在 Windows 上居然把所有它能打开的文件类型都注册成“Chrome HTML document”???

我能接受它用一种模糊的称呼,例如“Chrome document”,但把不是 HTML 的文件说是 HTML 太离谱了吧。

结合上 Windows 默认不显示扩展名的这个设计,感觉能坑害无数新手。我看到网上有很多人问自己的 PDF 怎么突然变成 Chrome HTML document 了,还很难搞清楚该去哪个软件那边问(Windows/文件管理器/Chrome)。
Azure 做了两个我没见过其他云服务商做的事:

1. 创建虚拟机时,一个不显眼的位置有一个每天定时自动关机的选项,而且每次创建新虚拟机时这个选项默认都是启用的。

2. 没有提前通知,Azure Patch Management 突然就把机器立即重启了。

只能说他们可能觉得把云服务器关机了没什么大不了的吧。
新手常犯的一个错误是以为 TCP 可以用于传输多个小字节串,以及它们之间的边界,类似这样:
[字节, 字节, 消息边界, 字节, 字节, 字节, 字节, 消息边界]
以为整个序列要么完整传输到另一端,要么某个前缀加上 RST 会被传输到另一端。实际上,TCP 没有消息边界的概念,发送方先发送 2 字节,再发送 4 字节,接收方完全有可能先看到前 3 个字节,再看到后 3 个字节(只保证总共 6 个字节连起来是按顺序正确传输的)。

但是,很多人可能都不太了解的另一种错误是,以为 TCP 可以用于传输任意长的连续字节串,加上 FIN 作为结束标志:
[字节, 字节, 字节, 字节, FIN]
以为整个序列要么完整传输到另一端,要么某个前缀加上 RST 会被传输到另一端。于是不设计发送消息长度或结束标志的机制,而是发送方一直发载荷,发完了就 shutdown,以此表示载荷结束了。接收方一直收,直到看到 EOF。

按我的理解,只考虑 TCP 的语义时,这个想法其实是没问题的,然而操作系统会打破这个假设。如果发送方的进程被信号杀死,操作系统会自作主张地给这个进程的所有 TCP 流发一个 FIN(而不是 RST)。上面说的错误的设计会导致当发送方进程被杀死时,接收方收到不完整的载荷,却以为是完整的。一个很坑的例子是 @zzh1996 提到 HTTP 协议规定服务器可以不返回 Content-Length 也不用 chunked,这种情况下以 FIN 作为载荷结束的信号,可能导致客户端只下载到半个文件就以为下载成功了。

所以结论是,如果用 TCP 传输一串字节,实际上可能在传输了任何一个前缀后,突然传输一个 FIN 或 RST。没有手段可以可靠地分辨收到的是完整内容还是某个前缀,FIN 和 RST 在这一点上是没区别的,在我看来这是操作系统设计的一个错误。