博客更新日志
展示最近的 5 次更新, 查看全部更新日志请点击阅读全文
26-5-20
新增了Steam 在 niri (xwayland-satellite) 下的崩溃修复指南
26-4-17
更新了修复 libinput 鼠标点击抖动限制
更新了我的 Arch + Niri 全安裝及配置
加载过慢请开启缓存 浏览器默认开启
展示最近的 5 次更新, 查看全部更新日志请点击阅读全文
新增了Steam 在 niri (xwayland-satellite) 下的崩溃修复指南
更新了修复 libinput 鼠标点击抖动限制
更新了我的 Arch + Niri 全安裝及配置
记录一下 Steam 在 niri + xwayland-satellite + NVIDIA 环境下从无法启动到恢复正常运行的完整修复过程, 包括 GDK 补丁、NVIDIA 驱动版本对齐、以及 Proton 游戏闪退排查等内容
| 项目 | 值 |
|---|---|
| 操作系统 | Arch Linux (rolling) |
| 合成器 | niri (scrollable-tiling Wayland compositor) |
| X11 兼容层 | xwayland-satellite |
| glibc 版本 | 2.43 |
| 显示服务 | :0 (通过 xwayland-satellite 提供的 X11 DISPLAY) |
Steam 启动后立即崩溃(SIGSEGV),从 GDB 回溯和 Breakpad minidump 分析发现多个崩溃点
| # | 问题 | 类型 |
|---|---|---|
| 1 | GDK Xinerama 崩溃 | SIGSEGV |
| 2 | GDK XRANDR 崩溃 | SIGSEGV |
| 3 | JIT/CEF NULL 字符串崩溃 | SIGSEGV |
| 4 | nvidia_drm.modeset 未启用 | 配置错误 |
| 5 | 32 位 NVIDIA 驱动版本不匹配 | 配置错误 |
症状: Steam 首次启动时立即段错误
根源: xwayland-satellite 不支持 XINERAMA 扩展。GDK 检查 Xinerama 时向 NULL 指针写入标志位
修复: NOP 掉 Steam 捆绑的 GDK 二进制文件中写入 movl $0x1,0x22c(%eax) 的指令
# 备份原始文件
cp /home/lumorian/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0.2400.10 \
/home/lumorian/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0.backup
# 文件偏移 0x627cc: 将 c7 80 2c 02 00 00 01 00 00 00 替换为 10 个 NOP
python3 -c "
data = bytearray(open('libgdk-x11-2.0.so.0.2400.10', 'rb').read())
data[0x627cc:0x627d6] = b'\x90' * 10
open('libgdk-x11-2.0.so.0.2400.10', 'wb').write(data)
"
症状: 修复 Xinerama 崩溃后 Steam 仍然崩溃, 错误信息包含 XRRGetOutputInfo Workaround: initialized with override: 0 real: (nil)
根源: xwayland-satellite 的 XRANDR 支持不完整, XRRGetOutputInfo() 返回 NULL
修复: NOP 掉跳转到 XRANDR 路径的条件跳转指令, 同时预加载系统 libXrandr
# 文件偏移 0x62737: 将 0f 85 0b 01 00 00 (jne) 替换为 6 个 NOP
python3 -c "
data = bytearray(open('libgdk-x11-2.0.so.0.2400.10', 'rb').read())
data[0x62737:0x6273d] = b'\x90' * 6
open('libgdk-x11-2.0.so.0.2400.10', 'wb').write(data)
"
启动时预加载系统 libXrandr
export LD_PRELOAD="/usr/lib32/libXrandr.so.2"
症状: 修复 GDK 崩溃后 Steam 进程存活时间更长但仍然崩溃, 回溯指向 JIT 编译的代码中 strlen(NULL) 调用
根源: glibc 2.43 的 strlen(), strcmp(), strstr(), strchr() 使用 IFUNC 机制选择 SSE2/AVX2 优化版本, 不处理 NULL 输入
修复: 创建 LD_PRELOAD 库拦截不安全的字符串函数
// nullsafe.c — NULL 安全字符串拦截器
#define _GNU_SOURCE
#include <stddef.h>
#include <dlfcn.h>
extern void *dlsym(void *, const char *);
#define RTLD_NEXT ((void *)-1)
__attribute__((used))
size_t strlen(const char *s) {
static size_t (*real_fn)(const char*) = NULL;
if (!real_fn) real_fn = (size_t (*)(const char*))dlsym(RTLD_NEXT, "strlen");
if (!s) return 0;
return real_fn(s);
}
__attribute__((used))
int strcmp(const char *s1, const char *s2) {
static int (*real_fn)(const char*, const char*) = NULL;
if (!real_fn) real_fn = (int (*)(const char*, const char*))dlsym(RTLD_NEXT, "strcmp");
if (!s1 && !s2) return 0;
if (!s1) return -1;
if (!s2) return 1;
return real_fn(s1, s2);
}
__attribute__((used))
char *strstr(const char *haystack, const char *needle) {
static char *(*real_fn)(const char*, const char*) = NULL;
if (!real_fn) real_fn = (char *(*)(const char*, const char*))dlsym(RTLD_NEXT, "strstr");
if (!haystack) return NULL;
if (!needle) return (char*)haystack;
return real_fn(haystack, needle);
}
__attribute__((used))
char *strchr(const char *s, int c) {
static char *(*real_fn)(const char*, int) = NULL;
if (!real_fn) real_fn = (char *(*)(const char*, int))dlsym(RTLD_NEXT, "strchr");
if (!s) return NULL;
return real_fn(s, c);
}
编译 (需要注意: 不能包含 <string.h>, 因为 glibc 2.43 使用 _Generic 宏与函数定义冲突)
gcc -m32 -shared -fPIC -o /tmp/nullsafe.so /tmp/nullsafe.c -ldl -O2 -fno-builtin
# 安装到永久路径
cp /tmp/nullsafe.so /home/lumorian/.local/lib/nullsafe.so
症状: glxinfo 显示 direct rendering: Yes,但 32 位程序无法创建 GLX 直接上下文
根源: GRUB 内核参数 nvidia-drm-modeset=1 格式错误。正确格式应为 nvidia-drm.modeset=1
# 检查当前状态
cat /sys/module/nvidia_drm/parameters/modeset
# 应为 Y, 若为空则未启用
# 修复 GRUB 参数
sudo sed -i 's/nvidia-drm-modeset=1/nvidia-drm.modeset=1/' /etc/default/grub
sudo grub-mkconfig -o /boot/grub/grub.cfg
# 重启生效
症状: nvidia_drm.modeset=Y 后 32 位 GLX 仍然返回 NULL
根源: 32 位 NVIDIA 用户态库被 paru 升级到 580.159.03, 而内核模块和 64 位库为 580.142, 版本不一致
# 检查版本
pacman -Q nvidia-580xx-utils
pacman -Q lib32-nvidia-580xx-utils
# 降级 32 位库
sudo pacman -U /home/lumorian/.cache/paru/clone/lib32-nvidia-580xx-utils/lib32-nvidia-580xx-utils-580.142-1-x86_64.pkg.tar.zst
# 验证
ls -la /usr/lib32/libGLX_nvidia.so.0
在修复完 Steam 本身的崩溃和 GLX 渲染问题后, Steam 商店和库功能正常, 但运行特定 Windows 游戏时仍然闪退
游戏”星空列车与白的旅行”(Steam AppID 1567800)启动后窗口一闪而过, 约 3-5 秒后进程全部退出
游戏文件包含 UnityPlayer.dll, GameAssembly.dll, 确定是 32 位 Unity IL2CPP 游戏, 需通过 Proton 运行
从 Proton 兼容层目录找到 Unity Player 日志:
cat "/mnt/data/SteamLibrary/steamapps/compatdata/1567800/pfx/drive_c/users/steamuser/AppData/LocalLow/Syawase Works/星空列车与白的旅行/Player.log"
日志显示游戏启动正常, D3D11 设备创建成功, Steam API 初始化完成, 然后:
AspectRatioController:wndProc(IntPtr, UInt32, IntPtr, IntPtr)
ApplicationWantsToQuit: False
StartCoroutine -> DelayedQuit
ApplicationWantsToQuit: True
游戏使用了 DenchiSoft 的 UnityAspectRatioController 组件, 它通过 WinAPI (SetWindowLong + WindowProc) 挂钩窗口消息来锁定宽高比。该组件在说明中明确写了仅支持 Windows。在 Proton/Wine 下, WinAPI 窗口钩子的行为与 Windows 不同, 导致组件在初始化时收到意外窗口消息后触发退出
试了以下方案均无效:
DISABLE_GAMESCOPE=1 (排除 gamescope 干扰)-screen-width 1920 -screen-height 1080 -screen-fullscreen 1 (Unity 强制分辨率)-popupwindow (强制窗口模式)PROTON_LOG=1 %command% # 生成 ~/steam-1567800.log
日志发现 nullsafe.so 和 libXrandr.so.2 的 LD_PRELOAD 泄漏到了 Proton 进程环境中:
ERROR: ld.so: object '/home/lumorian/.local/lib/nullsafe.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
nullsafe.so 是 32 位库, 被 Proton 的 32 位 Wine 内部进程加载后干扰了窗口消息的正常处理, 间接导致 AspectRatioController 异常触发退出
在 Steam 启动选项中使用以下命令清除继承的 LD_PRELOAD
LD_PRELOAD= %command%
这个命令仅对该游戏生效, 不会影响 Steam 主进程的稳定性
如果你的 steam-fixed.sh 中设置了全局 LD_PRELOAD, 任何通过 Proton 运行的 Windows 游戏都可能受到干扰。建议每个游戏单独在启动选项添加:
LD_PRELOAD= %command%
killall -9 steam 2>/dev/null; sleep 1
export LANG=C STEAM_RUNTIME=1 DISPLAY=:0
export LD_PRELOAD="/home/lumorian/.local/lib/nullsafe.so /usr/lib32/libXrandr.so.2"
/home/lumorian/.local/share/Steam/steam.sh -no-cef-sandbox
或使用包装脚本 (完整内容如下)
#!/bin/bash
# Steam 启动包装脚本 — 修复 niri/xwayland-satellite 下的崩溃问题
# 用法: ./steam-fixed.sh [额外参数]
# 永久安装 nullsafe.so:
# sudo cp /home/lumorian/.local/lib/nullsafe.so /usr/local/lib/nullsafe.so
# 然后改脚本中的 NULLSAFE_PATH
NULLSAFE_PATH="/home/lumorian/.local/lib/nullsafe.so"
# NULLSAFE_PATH="/usr/local/lib/nullsafe.so" # 如果用 sudo 安装后取消注释
# 杀掉残留进程
killall -9 steam 2>/dev/null
# 导出环境变量
export LANG=C
export STEAM_RUNTIME=1
export DISPLAY=:0
export LD_PRELOAD="${NULLSAFE_PATH} /usr/lib32/libXrandr.so.2"
# 启动 Steam
exec /home/lumorian/.local/share/Steam/steam.sh "$@"
使用方式:
~/temp/steam-fixed.sh -no-cef-sandbox
Proton 游戏需要在 Steam 启动选项中添加:
LD_PRELOAD= %command%
| 检查项 | 结果 |
|---|---|
| Steam 主进程存活 | ✓ |
| 无新的崩溃转储 | ✓ |
| CEF Web 辅助进程运行 | ✓ |
| 32-bit GLX direct context | ✓ |
| nvidia_drm.modeset | Y |
| 星空列车与白的旅行 Proton 运行 | ✓ |
防止 NVIDIA 版本再次不匹配, 锁定 32 位 NVIDIA 包版本
# 编辑 /etc/pacman.conf, 在 [options] 下添加
IgnorePkg = lib32-nvidia-580xx-utils lib32-opencl-nvidia-580xx
| 文件 | 用途 |
|---|---|
/home/lumorian/.local/lib/nullsafe.so |
NULL 安全字符串拦截器 |
/home/lumorian/temp/steam-fixed.sh |
Steam 启动包装脚本 |
/home/lumorian/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0.2400.10 |
补丁后的 GDK 库 |
/home/lumorian/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0.backup |
原始 GDK 库备份 |
/etc/default/grub |
GRUB 配置 (含 nvidia-drm.modeset=1) |
/mnt/data/SteamLibrary/steamapps/compatdata/1567800/pfx/drive_c/users/steamuser/AppData/LocalLow/Syawase Works/星空列车与白的旅行/Player.log |
游戏 Unity Player 日志 |
在 GNU/Linux 中, 无论是 wayland 还是 x11, 都会出现快速点击鼠标时 (例如 DBC), 最高只能识别到约 12 CPS, 而实际 CPS 为 20 CPS 的情况
evtest 能检测到所有点击
libinput debug-events 和 wev 只能检测到部分点击
libinput 1.23+ 版本引入了按键去抖动功能 (button debouncing) 用于防止硬件接触抖动导致的误触, 但这个功能默认会过滤掉间隔小于 25ms 的点击事件, 从而导致 CPS 被限制在 12 左右
虽然可以通过在 ‘/etc/libinput/local-overrides.quirks’ 中配置 ‘ModelDebounceTime=0’ ‘ModuelBouncingKeys=0’, 但几乎不生效
直接通过修改 libinput 源码来禁用按键去抖动
安装编译依赖
sudo pacman -S --noconfirm base-devel git meson ninja libevdev mtdev systemd
克隆 libinput 源码
git clone https://gitlab.freedesktop.org/libinput/libinput.git && cd libinput
签出对应版本
git tag -l | grep 1.31.1 && git checkout 1.31.1
修改 src/libinput-plugin-button-debounce.c, 这里先备份
cp src/libinput-plugin-button-debounce.c src/libinput-plugin-button-debounce.c.bak
修改插件初始化函数
sed -i '855,864c\void\nlibinput_debounce_plugin(struct libinput *libinput)\n{\n\t/* Button debounce disabled permanently - no CPS limit! */\n\treturn;\n}' src/libinput-plugin-button-debounce.c
编译
meson setup builddir -Ddocumentation=false -Dtests=false && cd builddir && meson compile
安装
sudo meson install
编译默认安装到 /usr/local/lib, 由于我是 Archlinux, 默认从 /usr/lib/ 加载, 所以我们把安装好的复制过去
备份原库
sudo cp /usr/lib/libinput.so.10.13.0 /usr/lib/libinput.so.10.13.0.backup
复制新库
sudo cp /usr/local/lib/libinput.so.10.13.0 /usr/lib/
执行完上一步后系统应该会直接重新加载不需要手动重启, 现在直接打开浏览器 CPS 测试网站或者在游戏中开启 CPS 显示验证即可
防止系统更新覆盖修改好的 libinput, 这边手动将其添加到 pacman 的 IgnorePkg
sudo nano /etc/pacman.conf
IgnorePkg = libinput
本项目所有代码均为 AI 生成
daysmatter 是一款纯Python编写、基于curses的交互式终端倒计时工具,无需图形界面,即可在终端中优雅管理生日、纪念日、节日等重要日期。
工具自动计算倒计时/已过天数,支持年度重复事件、彩色高亮、可视化进度条、全屏展示模式,完美适配中文宽字符,数据本地存储无联网,轻量开箱即用。


curses 库(Linux/macOS 原生支持)wget https://git.lumorian.org/Lumorian/daysmatter/raw/branch/main/daysmatter.py
python3 daysmatter.py
适合终端常驻、桌面展示:
python3 daysmatter.py -F
↑ / ↓:选择事件A:添加新事件E:编辑选中事件D:删除选中事件F:切换到全屏展示模式Q:退出程序Q:返回主界面/退出所有事件数据本地存储,无任何网络请求:
~/.config/daysmatter/events.json有这样一种时兴的 “产物” – 天才少年, 再加上各种短视频平台的宣传, 贴上 “百万年薪” 标签. 这种混淆普通人对成功概念的理解的产物变得普遍流行并非偶然. 从这种混淆中得利的大公司推动了这种混淆, 最明了的方式就是完全拒绝这一 “产物”
这一 “产物” 本身具有一种不难察觉的偏见: 它暗示人们应认为低的薪资是可耻、失败的, 只有拥有百万年薪才能让人生过上幸福的生活, 才是成功. 由于这种转变正是那些大公司所求之不得的, 于是这种由 “天才少年” 这一产物所带来的偏见迎合了它们.
根据现在供职于XX市第二中学南校区的李教授的观点, 对 “天才少年” 这一产物的广泛使用变得流行是应当的. 从李教授多次演讲中我们可以提炼出以下论点: (1) 未达到百万年薪或以上的人, 未来的出路只有卖菜、搬砖等粗活累活; (2) 收税人大于纳税人, 纳税人低人一等; (3) 不愿成为 “天才少年” “百万年薪” 就是害怕、懒惰、不上进; (4) 认为想过普通生活是可笑的.
它是一种幻境. 人们之所以会误认为 “天才少年” 是一种合乎逻辑的分类, 原因仅仅在于这一产物的广泛使用对于人们理解何为美好生活时产生了误导.
例如, 您可能会看见这样的宣传: “华为百万年薪招聘天才少年”, “天才少年发明打破国外技术封锁”, 这些宣传不断暗示我们都应如此. 您也会见到这样的论断, “天才少年” 是为鼓励人们仍需努力, 为人们提供榜样向他们看齐. 但事实上只适用那些天生就是天才的人, 普通人听多了只会感到厌烦. 让我们回到小时候, 你的父母是否时常将一种叫 “邻家小孩” 的生物挂在嘴边, 将它与你进行对比, 当时你的内心是如何看待这些 “邻家小孩” 的呢?
不难发现, “天才少年” 与 “邻家小孩” 的本质其实是一致的. 唯一的区别在于 “邻家小孩” 可能是你 “独享” 的, 而 “天才少年” 则是大家 “共有” 的. 当长辈们在晚辈面前讨论 “天才少年”, “邻家小孩” 时, 他们通常想要真正表达的是他们在生活或工作中的不如意无处释放, 只能通过像 “天才少年” 这种能切中他们要害的产物丢向晚辈来为自己带来一丝微不足道的高潮快感和莫名奇妙的自豪感.
接了个给 hexo-butterfly 增加播放本地音乐的小单, 记录一下实现过程, 网上大多为添加第三方源或只是在单页面添加播放器
npm install --save hexo-tag-aplayer
source 路径, 例如path-to-your-blog/
└─ source/
└─ music/
├─ song1.mp3
├─ song2.mp3
├─ song3.mp3
└─ cover/
├─ song1.jpg
├─ song2.jpg
├─ song3.jpg
└─ lrs/
├─ song1.lrs
├─ song2.lrs
├─ song3.lrs
配置主题的 additional-js.pug 文件 (不选择配置 _config.yml 里的 inject 是因为各种神秘版本神秘兼容已经把我搞晕)
nano themes/butterfly/layout/includes/additional-js.pug
最后一行添加
div(id="global-aplayer")
link(rel="stylesheet", href="https://cdn.bootcdn.net/ajax/libs/aplayer/1.10.1/APlayer.min.css")
script(src="https://cdn.bootcdn.net/ajax/libs/aplayer/1.10.1/APlayer.min.js")
script.
window.onload = function() {
if (typeof APlayer !== 'undefined') {
const ap = new APlayer({
container: document.getElementById('global-aplayer'),
fixed: true,
autoplay: false,
theme: '#F57C00',
loop: 'all',
volume: 0.7,
mutex: true,
listFolded: true,
listMaxHeight: 300,
lrcType: 1, // 这里填 1 没用的可以试一下填 3
preload: auto,
audio: [
{
name: "song1",
artist: "artist1",
url: "/music/song1.mp3",
cover: "/cover/song1.jpg",
lrc: "/lrs/song1.lrc"
},
{
name: "song2",
artist: "artist2",
url: "/music/song2.mp3",
cover: "/cover/song2.jpg",
lrc: "/lrs/song2.lrc"
}
{
name: "song3",
artist: "artist3",
url: "/music/song3.mp3",
cover: "/cover/song3.jpg",
lrc: "/lrs/song3.lrc"
}
]
});
const apFixed = document.querySelector('.aplayer-fixed');
if (apFixed) {
apFixed.style.zIndex = '99999';
apFixed.style.bottom = '20px';
apFixed.style.right = '20px';
apFixed.style.width = '360px';
}
}
};
nano ./_config.yml
# or
nano ./_config_butterfly.yml
找到 inject 部分, 清空先前的配置避免冲突
inject:
head:
bottom:
hexo clean && npm run server
大功告成~~~~
第一版, 2022 年 9 月 16 日
版权所有 © 2022 Peaksol, Lumorian
任何人皆可复制和分发本协议的完整副本, 但不允许修改之.
通用餐饮代购协议是一份适用于餐饮代购环节中代理商为最终消费者提供的服务的协议.
就多数代购行为而言, 最终消费者多对代理商进行利益上的剥削; 相反, 通用餐饮代购协议力图保障代理商与最终消费者的共同利益.
通过使用代理商所提供的餐饮代购服务, 最终消费者接受并同意受到通用餐饮代购协议第一版的约束. 从合同解释的角度来看, 最终消费者获得来自代理商的餐饮代购服务的使用权的对价是接受本协议的条款, 代理商授予最终消费者此权利的对价是可以通过提供其根据本协议提供的服务而获得利益.
以下是对代理商所供服务的使用的条款和条件细则.
a) “本协议” 指通用餐饮代购协议第一版.
b) “食品经营商” 指支持使用电话或短信订购其外卖餐饮的个人或团体.
c) “代理商” 指提供餐饮代购服务的个人.
d) “最终消费者” 指使用代理商所提供的服务的个人.
e) “订单” 指通过代理商在特定食品经验商处订购的单份餐饮. 订单创建者可以是最终消费者或代理商本人.
f) “取件” 过程指订单在从食品经营运输至订单创建者的全过程中, 除食品经营商运输过程以外的所有运输过程.
a) 只有最终消费者接受本协议,且代理商同意为最终消费者提供服务,最终消费者才可使用代理商提供的服务。
b) 代理商为最终消费者提供的服务包括本协议第 2 条和第 3 条所述的服务。
c) 最终消费者有权随时停止接受本协议,代理商亦有权随时停止在本协议下提供其服务。但此类停止不影响截至该类停止发生之时仍未结束的服务,除非最终消费者明确表明结束该服务。
a) 最终消费者可免费在代理商处创建订单,订单应指明食品经营商名称,联系方式和预订餐饮。同一服务时段内,最终消费者不得创建多份订单。
b) 同一服务时段内,在代理商将订单提交至食品经营商前,最终消费者有权修改订单内容或取消订单;代理商将订单提交至食品经营商后,最终消费者不得再修改订单内容或取消订单。
c) 代理商仅负责签订单提交至食品经营商,且不承担食品经营商提出的任何费用,包括但不限于餐饮费,运输费。食品经营商对订单提出的任何费用由最终消费者承担。
a) 同一服务时段内,在代理商向某一食品经营商提交指向该食品经营商的所有订单时,若:
b) 代理商对 3a3 情况下的订单提供的免费代取件服务是可用的,如果:
c) 代理商对 3a2 和 3a3 情况下的订单提供的有偿代取件服务是可用的,如果:
d) 订单在代取件过程中出现的损失,须由为订单进行代取件的个人或集体进行承担。订单创建者可与为订单进行代取件的个人或集体就损失赔偿的具体事宜进行协商。
a) 代理商不对食品经营商嗯餐饮提供任何种类的品质担保。若食品经营商提供的餐饮未达到最终消费者的预期品质,代理商不对此承担任何责任。
b) 代理商不对最终消费者因食用食品经营商的餐饮而遭受的任何直接或间接的伤害和损失承担任何责任,即使代理商受到明示或暗示应对此负责。
条款和条件至此结束
这天我在我的 Arch 上玩 Galgame 的时候发现游戏能正常启动 (有声音) 但窗口不显示的情况, 简单查询发现是 Niri 对 XWayland 存在兼容性问题, 导致窗口无法正常显示 / 渲染, 下面简单说一下如何修复
gamescope 是独立的 Wayland 合成器, 可以绕过 Niri 的 XWayland 兼容性问题
sudo pacman -Syyu
sudo pacman -S gamescope
给游戏启动命令添加启动选项
# 全屏, 自适应分辨率
gamescope -f -- <command>
# 指定分辨率 + 全屏
gamescope -w 1920 -h 1080 -f -- <command>
如果是 Steam 上的 Galgame 的话同样也是给游戏添加启动参数, 将上面的命令 <command> 替换成 %command% 填入即可
我第一次在 GNU/Linux 中使用 tailscale 的 taildrop 时发现怎么都找不到发送过来的文件, 一直以为只是藏在了某个隐蔽的路径下, 直到翻看了官方文档才知道原来 GNU/Linux 端不会自动保存, 需要用户手动设置保存路径 (气笑了)
收文件
# 把接收文的目录设置为当前目录(. 表示当前)
sudo tailscale file get .
# 或保存到指定的某个目录
sudo tailscale file get ~/Downloads
发文件
tailscale file cp <files> <name-or-ip>:
补充一下 tailscale 的官方文档, 点击这里查看
环境 Golang,gcc
下载 MinGW-w64, 将压缩包解压, 注意路径不要含有中文或空格, 随后添加到系统环境变量 (重启终端)
#验证
gcc --version
下载 Golang
# 验证
go version
克隆 chatlog 源码 (此为二次开发版)
git clone https://github.com/teest114514/chatlog_alpha
开始编译
cd chatlog_alpha
# 为 Go 配置镜像加速 (临时生效)
$env:GOPROXY = "https://goproxy.cn,direct"
# 验证, 输出 https://goproxy.cn,direct 则说明成功
go env GOPROXY
# 开启 CGO
$env:CGO_ENABLED = 1
if (-not (Test-Path "bin")) { mkdir bin }; go build -o bin/chatlog.exe main.go
注意查看当前支持的微信版本, 截至到本文结束时, wx_key 支持全部 4.x 版本, 最高稳定支持 4.1.5.11 版本. 最新版能用但有点开盲盒的感觉所以个人还是推荐优先使用目前稳定支持的版本