文章

日常疑难杂症(一)

HACKs are acceptable...

日常疑难杂症(一)

前言

本文收录了一些自己遇到的日常(简单)疑难杂症及对应处理,暂时命名为 1,后续如果收录的过多会考虑出 2 等;按每 10 条一则吧。

本文收录的大多数问题可能都比较蠢,但是 debug 确实还是挺有意思的。

与 Python/深度学习相关的 HACK 被单独收录在了Python开发疑难杂症汇总,方便查阅。

【Web 开发】视口到底有多大?

描述

该问题出现在一个被设计为沉浸式单页应用的移动端页面上。旧方案下页面采用 height: 100vh; overflow: hidden; 布局,旨在完全占满屏幕并严格禁止滚动。页面内容包含由 JS 动态生成的持续下落动画元素,在设计上离开屏幕时该元素被移除。

错误现象: 在移动端浏览器中,JS 生成的动画元素溢出了屏幕,页面右侧出现了意外的滚动条。这表明 overflow: hidden 声明失效,JS 生成的动画元素被视为可滚动内容。

此外,此问题在桌面设备(Windows)上无法复现。这是因为桌面模拟器仅能调整视口尺寸,无法真实模拟移动端浏览器 UI(地址栏、工具栏)的动态显隐行为和其对大视口单位 (100vh) 的精确影响。该问题也长期被 Chromium 等官方项目视为 vh 单位定义的预期行为,而非 Bug。标准化的 svh, lvh, dvh 单位直到后来才出现,旨在解决此痛点,但在本项目中效果不佳。

处理

为根除此问题,采用了overflow: clip,来替代原有的 overflow: hidden,通过更严格的裁剪行为彻底禁止任何滚动并更有效地处理溢出内容。通过这一替换,无需依赖 dvh 等现代单位或复杂的 JS 视口高度计算,直接、并非优雅地解决了由视口单位与动态 UI 交互引发的布局溢出问题。

【域名/自定页面】由自定义域名配置引发的依赖崩溃

描述

自己有了域名,将 GitHub Pages 上的 Jekyll 博客从默认子目录迁移至独立子域名时,构建流程意外中断,导致站点无法部署。

错误现象: GitHub Actions 工作流在执行 bundle install 步骤时失败,核心错误是尝试 Gem 安装 sass-embedded (1.93.3) 时,构建原生扩展失败。

核心错误日志片段:

1
2
3
4
5
6
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
...
rake aborted!
NameError: uninitialized constant JSON::Fragment
...
An error occurred while installing sass-embedded (1.93.3), and Bundler cannot continue.

原因分析:

  1. 旧环境的容忍度: 在使用默认 GitHub Pages 部署或未更新依赖时,构建环境可能使用的是旧版、预编译好的 Sass 依赖,或官方支持的 Jekyll/Sass 版本,从而避免了原生扩展构建。
  2. 新配置的触发: 更改 _config.yml 中的 url/baseurl 或 GitHub Pages 设置,强制触发了 GitHub Actions 重新运行完整的依赖解析和安装(即 bundle install)。
  3. 冲突暴露: 依赖解析器拉取了最新版本的 sass-embedded (1.93.3)。该版本在尝试构建其所需的原生扩展时,其 Rakefile 代码引用了 JSON::Fragment 这一常量。
  4. 版本不兼容: 构建环境使用的 Ruby 版本为 3.1.6,在该版本的标准库中,JSON::Fragment 未定义或无法被正确加载,从而导致 NameError 和 Gem 安装失败。

处理

升级 GitHub Actions 中的 Ruby 版本。

  1. 定位到项目仓库中的 GitHub Actions Workflow 文件(通常是 .github/workflows/jekyll.yml)。

  2. 修改设置 Ruby 版本的步骤,将其升级到已知兼容且更新的稳定版本:

    1
    2
    3
    4
    5
    
    - name: Set up Ruby
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: "3.3" # 将 Ruby 版本从 3.1 升级到 3.3
        bundler-cache: true
    

在 Ruby 3.3 环境中,sass-embedded 成功安装,不再报告 JSON::Fragment 错误。站点构建和部署成功完成,article.akutazehy.xyz 恢复正常访问。

【Windows】由 Windows MPO 机制引发的浏览器画面撕裂

描述

在 Windows 11 环境下,使用 Chromium 系浏览器(Chrome / Edge)进行网页滚动或播放 1080p 视频时,出现明显的卡顿、撕裂、闪烁甚至短暂黑屏现象;问题在多任务切换、窗口化 VRR / G-Sync 场景下更易触发。

原因分析:

多平面叠加 (MPO) 是 Windows 的一项功能,旨在通过对多个显示层(例如视频、桌面和应用程序窗口)使用硬件加速合成来提升图形性能。然而,它被频繁汇报会导致一些问题,例如画面卡顿、闪烁、黑屏、GPU 驱动程序崩溃以及浏览器延迟——尤其是在 AMD 和 NVIDIA GPU 上。在某些硬件配置下(尤其是 AMD RX 5000/6000/7000 和 NVIDIA RTX 2000/3000/4000 系列),由于对叠加平面处理不当,MPO 可能会导致系统不稳定,尤其是在上下文切换或低帧率场景下。

处理

禁用 Windows 的 Multiplane Overlay,使显示管线回退到稳定的 DWM 合成模式:

在注册表路径HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Dwm中,创建一个名为OverlayTestModeDWORD值,将其值设置为00000005并重启电脑。

系统不再使用存在缺陷的 Overlay 显示路径,浏览器帧统一经 DWM 合成并受 VSync 约束,画面撕裂与闪烁问题消失或显著缓解,显示行为恢复稳定。

【Windows/Docker】Docker 占用 C 盘

参见知乎的这一则教程,或更原始的StackOverflow的回答

背景:

在 Windows 系统中安装 Docker Desktop 时,是无法选择安装的位置的,程序默认将 Docker 安装到了 C 盘。在使用 Docker 的过程中,我们会下载镜像文件,而一个镜像文件动辄 10 几 G,都会被放到 C 盘里存储 Docker 数据的磁盘映像文件.vhdx中。由于 vhdx 文件的特性,即使在 Docker 中删除掉不用的镜像文件,vhdx 文件也不会释放存储空间,这样电脑的 C 盘很快就会被占满。

Windows 的 Docker Desktop 基于 WSL2 来运行,所有的 image、container 数据都会被放到 WSL2 的虚拟磁盘文件(vhdx)中。而 WSL2 的 vhdx 具有“动态”特性,即当磁盘文件创建时,初始化一个最大的上限容量(默认是 1T),当里面数据增加时,vhdx 所占的空间随之增加,直到上限,但当里面的数据被移除时,vhdx 所占的空间并不会随之减小。这就是为什么即使在 Docker 中删除了镜像文件,也无法释放电脑的存储空间。

  1. 退出 Docker;
  2. Docker Desktop 的数据文件,默认存放在C:\Users\<Username>\AppData\Local\Docker,使用剪贴-粘贴将其转移到一个其他目录中;
  3. 打开 cmd,执行mklink /J "C:\Users\<Username>\AppData\Local\Docker" "<path_to_new_location>",其中mklink [[/d] | [/h] | [/j]] <link> <target>中的<link>不能已存在(即执行前不应该存在C:\Users\<Username>\AppData\Local\Docker这个文件夹);
  4. 重启 Docker。

压缩 vhdx 文件

  1. 退出 Docker;
  2. 打开 cmd,执行wsl --shutdown,来关闭所有正在 wsl 上运行的服务,并通过wsl -l -v来确认所有的服务已关闭。
  3. 用管理员模式打开命令行窗口,执行diskpart,进入 diskpart 程序;
  4. 在 diskpart 里面输入DISKPART> select vdisk file=<vhdx path>
  5. 输入DISKPART> compact vdisk,压缩 vhdx 文件;
  6. 输入DISKPART> exit,退出 diskpart 程序。
  7. 重启 Docker。

【Windows】安装MSI文件出现”错误代码2502、2503”

参考

描述

在 Windows 10/11 环境下,尝试通过双击运行 .msi 安装包时,安装向导刚启动便立即报错退出,提示”错误代码 2502”或”错误代码 2503”。

错误现象:

  • 双击 MSI 文件后,安装界面闪退或停留在进度条初始阶段;
  • 弹窗提示类似:安装程序遇到错误,代码 2503安装程序遇到错误,代码 2502
  • 右键菜单中没有”以管理员身份运行”选项,无法通过常规方式提权;
  • 问题多发生于第三方软件、企业内网插件、或老旧系统集成包的安装场景。

原因分析

  1. 权限继承断裂C:\Windows\Temp 是 Windows Installer 服务执行解压、缓存、校验等操作的临时工作目录。若当前用户对该文件夹缺乏”完全控制”权限,Installer 无法写入临时文件,进而抛出 2502/2503 错误。
  2. UAC 与 MSI 的”历史遗留问题”:不同于 .exe 安装程序,MSI 文件在资源管理器中默认不暴露”以管理员身份运行”入口,导致用户难以主动提权。
  3. 系统策略限制:部分企业环境或精简版系统可能通过组策略禁用了 Installer 的自动提权行为,进一步加剧了权限冲突。

注意:此处的 Temp 文件夹特指 C:\Windows\Temp并非用户目录下的 AppData\Local\Temp。两者路径不同、权限模型独立,切勿混淆。

处理

一些可以尝试的处理如下:

临时方案:通过任务管理器提权

  1. Ctrl + Shift + Esc 打开任务管理器;
  2. 点击 文件运行新任务
  3. 勾选 “以系统管理权限创建此任务”
  4. 浏览或粘贴 MSI 文件完整路径(如 C:\Downloads\plugin.msi),回车执行。

临时方案:使用管理员 CMD + msiexec 命令

  1. 搜索 cmd → 右键 “以管理员身份运行”
  2. 输入以下命令(注意空格与引号):

    msiexec /package "C:\Path\To\Your\Installer.msi"
    

    小技巧:可直接将 MSI 文件拖拽进 CMD 窗口,自动填充完整路径。

  3. 回车后,安装程序将以完整系统权限启动。

这两种临时处理通常可以成功安装,但下次仍需类似操作,比较繁琐。

一劳永逸的修复方案:

步骤1:手动修复 C:\Windows\Temp 权限(需管理员)

  1. 以管理员身份打开文件资源管理器,导航至 C:\Windows\Temp
  2. 右键 Temp 文件夹 → 属性安全编辑
  3. 选中当前登录用户(或 Users 组),勾选 “完全控制”“修改” 权限;
  4. 应用并确认,重试安装。

若提示”拒绝访问”无法修改权限,可尝试先取得文件夹所有权(高级 → 所有者 → 更改为当前用户),再重复上述步骤。

步骤2:组策略永久启用”提升权限安装”

  1. Win + R 输入 gpedit.msc 打开本地组策略编辑器;
  2. 依次展开:
    计算机配置管理模板Windows 组件Windows Installer
    → 启用 “始终以提升的权限进行安装”
  3. 同样路径在 用户配置 下再操作一遍;
  4. gpupdate /force 刷新策略,或重启生效。

家庭版 Windows 默认不包含 gpedit.msc,可考虑使用方案三作为替代,或通过脚本启用组策略组件。

本文由作者按照 CC BY 4.0 进行授权