打造媲美 macOS 的 Linux 开发环境

发布: 2026-06-19   上次更新: 2026-06-24   分类: 效率工具

文章目录

在使用 macOS 作为主力机十多年后,最近想尝试一下 Linux,看一看 2026 年的 Linux 桌面环境是否可以提供媲美 macOS 的开发体验。

macOS 的特点就是流畅,字体渲染细腻,不折腾,作为开发环境很省心,而且对于 Emacs 党来说,macOS 还有一点优势,其在系统层面内置了一套 Emacs 风格的光标移动快捷键,在所有原生文本输入框里都能用,不需要任何额外配置,比如:

快捷键功能
Ctrl+a行首
Ctrl+e行尾
Ctrl+f前移一字符
Ctrl+b后移一字符
Ctrl+p上移一行
Ctrl+n下移一行
Ctrl+d删除光标后一字符
Ctrl+h删除光标前一字符(同 Backspace)
Ctrl+k删除到行尾
Ctrl+t交换光标前两个字符
Ctrl+o在光标处插入换行
Option+f前移一个词
Option+b后移一个词
Option+d删除后一个词

这套快捷键是 macOS 在 AppKit/Cocoa 层实现的,覆盖 Safari、Chrome、Terminal、所有原生 App 的输入框。因此,在尝试 Linux 的过程中,快捷键对标 macOS 是我很重要的一个指标。

有一点需要说明的是,日常开发使用的软件主要是 Emacs、Brave、Zed、Ghostty,这四个软件天然就是跨平台的,所以在 Linux 上也能使用。因此本文主要记录从 macOS 迁移到 Linux 的过程,系统层面的配置和优化。下图是迁移前后的对比:

发行版选择

选择 Linux 的第一件事情就是确定发行版。不同人有不同的选择,由于公司开发时使用 Ubuntu 环境,因此我更偏向 Ubuntu 这一派系。

一开始尝试的是 Ubuntu 26.04,刚装机不久,在使用时就能感到莫名卡顿, ps 一看,无用的服务一大堆,与其尝试定制这个逐渐商业化的系统, 不如直接转向更轻量、更稳重的 Debian。截止到写文章时,已使用 Debian 13(trixie)一周左右(这篇文章就是在 Debian 上完成 😎),即使装了些后台服务,也丝毫没觉得卡顿。

更多发行版的选择可以参考 DistroWatchBest Linux Distros for Development,这里不做赘述。

桌面环境

发行版确定后,第二步就是桌面环境,和 macOS 不一样,Linux 社区内选择非常多,最流行的目前就是两个:

  1. Gnome,这是 Linux 桌面环境的老大哥,很多发行版默认都是 Gnome,其设计理念是『简单、易用、稳定』,适合不想折腾、追求稳定的用户
  2. KDE,这是另一个老牌桌面,设计理念是『功能丰富、可定制性强』。适合追求个性化、想完全掌控系统的用户

对于 Debian 13 来说,这俩桌面环境都完美支持了 Wayland,体验都不错,推荐读者两者都试用一下再做选择。

经过一番试用,两个桌面环境也都有些小问题,比如 Gnome 的 Wayland 下,fcitx5 入法有时会莫名失效,输入法提示框和焦点窗口错位;KDE 的问题对我来说更严重些, xremap 有些问题,导致无法在特定应用中使用 macOS 风格的快捷键。因此在左右权衡后,最终选择了 Gnome,毕竟 macOS 按键风格是我最看重的指标。

安装踩坑:离线镜像也会联网

Debian 提供几种 ISO,选之前先搞清楚两个维度:

  • netinst(网络安装)— ISO 很小(~400MB),安装过程中从网络拉包。需要全程联网,但装出来的系统最干净,只装你选的东西
  • DVD/BD(离线完整镜像)— 包含大量预编译包(3.5G),安装时理论上不需要联网。之所以说是理论上,是因为安装过程中仍然会尝试联网去拉软件包更新,如果不联网就跳过,装完系统后再配置网络和镜像源。

因此推荐制作启动盘时直接下载 DVD/BD 镜像,并且在安装过程中,跳过网络的配置(走到网络配置时,点击『back』即可回到安装流程)和镜像站配置, 避免安装过程中网络问题导致的失败和不必要的等待。装完系统再配置网络和镜像源。

我第一次安装了就配置了网络,用了差不多半小时才装完,期间还好几次因为网络问题失败了,后来干脆重装一次,跳过网络配置, 结果不到十分钟就装好了。网上不少人也踩了这个坑,可以参考:『安装时已选择国内镜像源,为何还走国外服务器』。

固件支持

早期 Debian 官方 ISO — 不含非自由固件(non-free firmware),如果你的网卡、显卡需要私有驱动,装完可能没网、没图形加速。 Debian 12 (bookworm)开始官方把 non-free firmware 合并进了正式 ISO,所以直接下载最新的就可以了。

基础环境

sudo 权限

Debian 默认安装不把普通用户加进 sudoers,需要手动:

1su root
2chmod +w /etc/sudoers
3# 添加一行:your-username ALL=(ALL:ALL) ALL
4chmod -w /etc/sudoers

常用工具

终端、浏览器没有在 apt 官方源里,可以从下面地址进行下载:

其他的常用命令行工具参考下面的脚本,它会检查是否已安装,如果没有就自动安装:

 1#!/usr/bin/env bash
 2function command_exists() {
 3  command -v "$1" &> /dev/null
 4}
 5
 6# https://github.com/sharkdp/fd
 7# https://github.com/burntsushi/ripgrep
 8command_exists fdfind || (sudo apt install -y fd-find && sudo ln -s "$(which fdfind)" /usr/local/bin/fd)
 9command_exists rg || sudo apt install -y ripgrep
10command_exists emacs || sudo apt install -y emacs-pgtk
11command_exists vim ||  sudo apt install -y vim
12command_exists git ||  sudo apt install -y git
13command_exists make ||  sudo apt install -y make
14command_exists sshd ||  sudo apt install -y openssh-server
15command_exists pinentry || sudo apt install -y pinentry-tty
16command_exists g++ || sudo apt install -y build-essential python3-dev
17command_exists pkg-config || sudo apt install -y pkg-config
18command_exists hunspell || sudo apt install -y hunspell hunspell-en-gb hunspell-en-us
19
20[ -d /usr/include/rime ] || sudo apt install -y librime-dev
21
22export UV_NO_MODIFY_PATH=1
23command_exists uv || (curl -LsSf https://astral.sh/uv/install.sh | sh -s -- --no-modify-path)
24command_exists zfetch || (curl -fsSL https://zigcli.liujiacai.net/install.sh | sh -s -- --china)
25command_exists flauth-cli || (curl -fsSL https://jiacai2050.github.io/flauth/install.sh | sh -s -- --china)
26command_exists zed || (curl -f https://zed.dev/install.sh | sh)

很惊喜的是,Debian 的官方源里已经有了 fd 和 ripgrep 这两个现代化的命令行工具,Emacs 也是 30 版本,直接 apt 安装就好,不需要自己编译了。

一开始 Emacs 我用的是 emacs ,但是不时会卡住(弹出提示框:Emacs is Not Responding),后续切到 emacs-pgtk 这个版本就好多了,下面时不同版本的对比:

软件包名适用场景说明
emacs-pgtkWayland 桌面 (强烈推荐)纯生 Wayland 渲染,无 X11 历史包袱
emacs-gtkX11 桌面 / 传统环境基于 GTK+3 的传统 GUI 版本
emacs-nox纯命令行 / 服务器不带任何 GUI 依赖,适合 SSH 远程或服务器

核心挑战:键盘习惯

这是整个迁移里最花精力的部分。在 macOS 上, Cmd+C/V/Z 这套肌肉记忆已经刻进手指了,切到 Linux 之后如果什么都不做,每次复制粘贴都要重新思考用哪个键,极其割裂。

经过一番折腾,最终选择了 xremap,一个支持 Wayland 的键盘重映射工具。

安装

xremap 安装十分简单,直接用 Release 页面下载对应桌面的版本即可,之后,参考 running_without_sudo 进行配置:

1sudo gpasswd -a YOUR_USER input
2echo 'KERNEL=="uinput", GROUP="input", TAG+="uaccess", MODE:="0660", OPTIONS+="static_node=uinput"' | sudo tee /etc/udev/rules.d/99-input.rules

这样就好了,如果是 gnome 桌面,则还需要安装 xremap 这个 gnome shell 插件。

配置方式

为了保证 Linux 和 macOS 按键方式一致,需要进行两步走:

  1. 键位映射,保证和 macOS 一致,如下图所示:
  2. 组合键语义映射,需要保证把以 Ctrl 为主的功能键,映射到 Win 键上

这两步都可以通过 xremap 解决,配置如下:

 1modmap:
 2- name: Global
 3  remap:
 4    # Swap Ctrl and CapsLock
 5    CapsLock: Ctrl_L
 6    Ctrl_L: CapsLock
 7    # Swap Alt and Super(模拟 Mac 的 Cmd/Option 位置)
 8    KEY_LEFTALT: KEY_LEFTMETA
 9    KEY_LEFTMETA: KEY_LEFTALT
10
11keymap:
12  - name: Super shortcuts (global except Emacs/Ghostty/Zed)
13    exact_match: true
14    application:
15      not: [emacs, Emacs, com.mitchellh.ghostty, dev.zed.Zed]
16    remap:
17      Win-c: ctrl-c  # 复制
18      Win-v: ctrl-v  # 粘贴
19      Win-x: ctrl-x  # 剪切
20      Win-z: ctrl-z  # 撤销
21      Win-a: ctrl-a  # 全选
22      Win-s: ctrl-s  # 保存
23      Win-w: ctrl-w  # 关闭标签页
24      Win-t: ctrl-t  # 新建标签页
25      Win-n: ctrl-n  # 新建窗口
26      Win-f: ctrl-f  # 查找
27      Win-l: ctrl-l
28      Win-r: ctrl-r  # 刷新
29      Win-z: ctrl-z  # 撤销
30
31      Ctrl-n: down
32      Ctrl-p: up
33      Ctrl-b: left
34      Ctrl-f: right
35      Ctrl-a: home
36      Ctrl-e: end
37      Ctrl-d: delete
38      Alt-f: ctrl-right   # 向前一个词
39      Alt-b: ctrl-left    # 向后一个词
40      Alt-d: ctrl-delete  # 删除后一个词
41      Alt-left: ctrl-left # 向左移动
42      Alt-right: ctrl-right # 向右移动
43      Alt-Shift-left: ctrl-shift-left # 选中向左移动
44      Alt-Shift-right: ctrl-shift-right # 选中向右移动
45      Alt-backspace: ctrl-backspace  # 删除前一个词

关键细节有两个:

  1. application.not 列表——Emacs、Ghostty、Zed 这些工具有自己的键位体系,需要排除在外,让它们接收原始键值。
  2. exact_match: true 在 xremap 中,按键采用的事模糊匹配,比如已设定 Ctrl-n 映射为 down ,当按下 Ctrl-Shift-n 时,系统会自动将其重映射为 Shift-down 。 若启用精确匹配,则必须专门为 Ctrl-Shift-n 定义一条映射规则。设置为 true 就可以避免这种模糊匹配,保持按键行为的一致性。

这里附上 Ghostty 的相关配置,供大家参考:

theme = light:Primary, dark:Nordfox
gtk-titlebar = false

keybind = super+alt+arrow_right=next_tab
keybind = super+alt+arrow_left=previous_tab
keybind = super+t=new_tab
keybind = super+w=close_tab
keybind = super+1=goto_tab:1
keybind = super+2=goto_tab:2
keybind = super+3=goto_tab:3
keybind = super+4=goto_tab:4
keybind = super+5=goto_tab:5
keybind = super+c=copy_to_clipboard
keybind = super+v=paste_from_clipboard

KDE 兼容问题

上面的配置在 gnome 下运行良好,但在 kde 下,xremap 的表现就不太稳定了,表现是:xremap 把 Win+V 重映射为 Ctrl+V,在 Brave 文本框里不生效,但在地址栏可以。

经过排查,这其实是因为 xremap 模拟按键的速度太快,导致了“修饰键状态同步滞后”。简而言之,物理 Win 键还没来得及在系统底层被标记为“松开”,Ctrl+V 就已经被发出去了。 Brave/Chromium 的 Omnibox(地址栏)对 modifier 容忍度更高, Ctrl+Super+V 也能触发粘贴;而普通文本框(<textarea> 等)对 modifier 做精确匹配, Ctrl+Super+V ≠ Ctrl+V ,所以粘贴动作失效。

解决办法很简单,只需在改键序列中加入 15-20ms 的 throttle_ms 延迟,给系统刷新按键状态留出时间即可。类似配置:

1keymap:
2  - name: Fix KDE Paste
3    remap:
4      # 当按下 Win + V 时
5      Win-v:
6        - throttle_ms: 15       # 先停顿 15 毫秒,让 KDE 彻底释放物理 Win 键的焦点状态
7        - remap_key: Ctrl-v     # 再干净地发送 Ctrl + V

经过一段时间使用,这个方案还是不太好用,偶尔还是会出现粘贴失败的情况。而 Gnome 的合成器 Mutter 在 2014 年的一个 commit 早就解决了这个问题, 两者的差异点可以参考下面的流程图:

 1xremap (uinput)          KWin Window Manager                 Brave Web Textbox
 2
 3      |                         |                                   |
 4      |-- (Release Win, ------> |                                   |
 5      |    Press Ctrl)          |-- 1. [Set & Send Modifiers] ----->|
 6      |                         |      "State updated to: Ctrl"     |
 7      |                         |                                   | 💥 Textbox hasn't finished
 8      |-- (Immediately -------->|                                   |   switching input context.
 9      |    Press Key 'V')       |-- 2. [Send Key Event] ----------->| Race Condition!
10      |                         |      "Key 'V' is pressed"         | Processes 'V' while the physical
11      |                         |                                   | Win state is still clearing ->
12      v                         v                                   v Interpreted as "Win+Ctrl+V" (Ignored)
 1xremap (uinput)          Mutter Window Manager               Brave Web Textbox
 2
 3      |                         |                                   |
 4      |-- (Release Win, ------> | [Internal: update]                |
 5      |    Press Ctrl)          | Intercepts & sets internal state  |
 6      |                         | to 'Ctrl', but pockets the sync   |
 7      |                         | packet. Does NOT notify Brave yet.|
 8      |                         |                                   |
 9      |-- (Immediately -------->| [Internal: handle_event]          |
10      |    Press Key 'V')       |-- 1. [Key First] ---------------> | Perfect Execution!
11      |                         |      "Key 'V' is pressed"         | Browser relies on the clean,
12      |                         |                                   | pre-existing state to resolve V.
13      |                         |                                   | ✅ Successfully triggers PASTE.
14      |                         |                                   |
15      |                         |-- 2. [Modifiers Later] ---------> |
16      |                         |      Calls notify_modifiers()     | Updates the browser's global map
17      |                         |      "State updated to: Ctrl"     | in the background for next inputs.
18      v                         v                                   v

服务管理

xremap 以 systemd user service 运行,常用命令:

1systemctl --user enable --now xremap
2systemctl --user status xremap
3journalctl --user -u xremap -f

systemd 的用户服务做得非常好,开机自启、状态管理、日志查看都很方便。相比 macOS 的 launchctl,Linux 的 systemd user service 更加成熟和易用。

系统快捷键清理

不管是 gnome 还是 kde,默认都占用了大量 Super 组合键,和 xremap 的映射会打架,需要系统性地清理。

Gnome

Activities 触发方式

macOS 上用 Raycast( Cmd+Space ),迁移过来自然想用 Super+Space 对应:

1# 禁用单按 Super 触发 Activities(避免误触)
2gsettings set org.gnome.mutter overlay-key ''
3# 改用 Super+Space
4gsettings set org.gnome.shell.keybindings toggle-overview "['<Super>space']"
5# 清掉输入法切换的默认绑定(Super+Space 默认是切换 input source)
6gsettings set org.gnome.desktop.wm.keybindings switch-input-source "[]"
7gsettings set org.gnome.desktop.wm.keybindings switch-input-source-backward "[]"

其他冲突键位

 1# 工作区切换(会和 Brave 标签切换冲突)
 2gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-left "[]"
 3gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-right "[]"
 4
 5# 锁屏
 6gsettings set org.gnome.settings-daemon.plugins.media-keys screensaver "[]"
 7
 8# Dash-to-Dock 的 Super+数字(会抢占 Emacs 的 Meta+数字)
 9gsettings set org.gnome.shell.extensions.dash-to-dock hot-keys false
10for i in $(seq 1 9); do
11  gsettings set org.gnome.shell.keybindings switch-to-application-$i "[]"
12done
13
14# 杂项
15gsettings set org.gnome.shell.keybindings toggle-message-tray "[]"
16gsettings set org.gnome.desktop.wm.keybindings show-desktop "['']"
17gsettings set org.gnome.shell.keybindings toggle-quick-settings "['']"
18gsettings set org.gnome.mutter.keybindings switch-monitor []

如果你不确定是哪个特定的配置项吞掉了快捷键,可以直接在终端用以下命令全局过滤当前系统中所有绑定了 <Super>n<Alt>n 的 GNOME 设置项:

1gsettings list-recursively | grep -E "(<Super>|<Alt>)[nN]"

KDE

理论上 kde 需要做和 gnome 一样的清理,但不想 gnome 很多快捷键在系统设置里找不到,kde 可能轻松在系统配置了进行操作:

  • 设置里面搜索『shortcuts』,勾选掉所有不需要的 Super 相关的快捷键即可。

剪贴板管理

之前在 macOS 中使用的时 Raycast 自带的剪贴板历史功能,很是方便,支持搜索、图片。在使用 gnome 时,尝试了 copyq、gpaste 后,效果很不是很满意, 体验远不如 raycast。唯一不错的是 fcitx5 自带的剪贴板历史功能,虽然功能简单,不支持搜索、图片,但胜在稳定、快捷键响应迅速,满足日常使用需求。

对于剪贴板搜索,社区已有 PR:clipboard: allow searching the clipboard history by pslldq · Pull Request #1504 · fcitx/fcitx5,希望未来能原生支持。

对于 kde 来说,这个就简单了,原生提供了剪贴板管理,配置下快捷键就好了,体验和 raycast 的无异。

输入法:fcitx5 + Rime

ibus 在 Wayland 下体验不理想,直接换 fcitx5:

1sudo apt purge fcitx* ibus*
2sudo apt install --install-recommends fcitx5 fcitx5-rime fcitx5-config-qt
3
4# 设置默认输入法框架
5im-config -n fcitx5

对于 kde 来说,这样就可以了,但是由于 gnome 默认的输入法是 ibus,切到 fcitx5 后需要多做些配置。

Gnome

首先需要配置以下环境变量,让 Qt/GTK 应用都走 fcitx5:

1sudo tee -a /etc/environment << 'EOF'
2XMODIFIERS=@im=fcitx
3QT_IM_MODULE=fcitx
4GTK_IM_MODULE=fcitx
5SDL_IM_MODULE=fcitx
6EOF

重新登录后生效,再通过 systemd user service 设置开机自启。参考:Setup Fcitx 5

Rime 的词库和配置沿用之前的,迁移成本很低。唯一的坑是 fcitx5 在 Wayland 下启动有竞态问题,有时莫名其妙的输入法就消失了。临时的解决方式是在 systemd service 里加 ExecStartPre 做 socket 轮询,等 Wayland compositor 就绪后再启动。

 1[Unit]
 2Description=Fcitx5 Input Method Engine
 3After=graphical-session.target
 4
 5[Service]
 6ExecStartPre=/bin/bash -c 'until [ -S $XDG_RUNTIME_DIR/wayland-0 ]; do sleep 0.2; done'
 7Type=exec
 8ExecStart=/usr/bin/fcitx5
 9Restart=on-failure
10
11[Install]
12WantedBy=graphical-session.target

另一点问题比较大的是目前 Gnome 桌面不支持 app_options 方式设置输入法状态,导致在特定程序里无法使用英文模式。细节可参考:

字体渲染

macOS 的字体渲染是出了名的好看,Linux 上要接近这个效果需要仔细调 fontconfig。

安装字体

1sudo apt install fonts-noto-cjk fonts-noto-cjk-extra \
2    fonts-jetbrains-mono fonts-inter

fontconfig 配置

配置文件路径: ~/.config/fontconfig/fonts.conf

 1<fontconfig>
 2  <!-- 抗锯齿 -->
 3  <match target="font">
 4    <edit name="antialias" mode="assign"><bool>true</bool></edit>
 5  </match>
 6
 7  <!-- 次像素渲染:横向排列屏幕用 rgb -->
 8  <match target="font">
 9    <edit name="rgba" mode="assign"><const>rgb</const></edit>
10  </match>
11
12  <!-- LCD filter:lcddefault 最接近 macOS -->
13  <match target="font">
14    <edit name="lcdfilter" mode="assign"><const>lcddefault</const></edit>
15  </match>
16
17  <!-- Hinting:hintslight 避免字形变形,最接近 macOS 风格 -->
18  <match target="font">
19    <edit name="hinting" mode="assign"><bool>true</bool></edit>
20    <edit name="hintstyle" mode="assign"><const>hintslight</const></edit>
21  </match>
22
23  <!-- 字体映射 -->
24  <alias>
25    <family>sans-serif</family>
26    <prefer>
27      <family>Inter</family>
28      <family>Noto Sans CJK SC</family>
29    </prefer>
30  </alias>
31
32  <alias>
33    <family>monospace</family>
34    <prefer><family>JetBrains Mono</family></prefer>
35  </alias>
36
37  <alias>
38    <family>serif</family>
39    <prefer><family>Noto Serif CJK SC</family></prefer>
40  </alias>
41</fontconfig>

几个关键选择:

  • Inter 作为无衬线字体:比 Ubuntu/Noto Sans 更接近 macOS 的 SF Pro 风格
  • hintslight :比 hintfull 保留更多字形细节,不会像素化
  • lcddefault :在主流屏幕上彩色边缘控制最好
  • 中文 fallback 到 Noto Sans/Serif CJK SC,避免落到质量参差不齐的系统字体

一些常用命令:

 1# 配置改了不生效时,手动刷新缓存:
 2fc-cache -fv
 3# 查看某个字体族实际解析结果
 4fc-match sans-serif  # 返回 Inter-Regular.otf: "Inter" "Regular"
 5fc-match monospace   # 返回 JetBrainsMono-Regular.ttf: "JetBrains Mono" "Regular"
 6fc-match serif       # 返回 NotoSerifCJK-Regular.ttc: "Noto Serif CJK SC" "Regular"
 7
 8# 查看完整匹配链(包含所有属性)
 9fc-match -v sans-serif | grep -E "family|file|hintstyle|lcdfilter|rgba|antialias"
10# 返回
11# family: "Inter"(w)
12# familylang: "en"(s)
13# antialias: True(w)
14# hintstyle: 1(i)(w)
15# file: "/usr/share/fonts/opentype/inter/Inter-Regular.otf"(s)
16# rgba: 1(i)(w)
17# lcdfilter: 1(i)(w)

性能调优

禁用 tracker-miner

tracker-miner-fs-3 文件索引服务对我来说没用,直接关掉:

1sudo systemctl --global mask tracker-xdg-portal-3.service
2sudo systemctl --global mask tracker-miner-fs-3.service
3killall tracker-miner-fs-3

参考:How to REALLY, COMPLETELY disable Gnome tracker?

休眠策略

笔记本作为开发机,不希望跑着任务突然睡过去:

1# 关掉插电时的自动挂起
2gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'

总结

整体跑下来,日常使用体验已经很平滑了。 Cmd+C/VCmd+Tab 、光标移动这些高频操作的肌肉记忆基本没有断裂感。 字体渲染在 4K 屏幕上达到了满意的效果,Inter + JetBrains Mono 的组合比默认配置好看很多。

最大的收获是对整个系统的掌控感——知道每个配置项在哪、为什么这么设置,这是 macOS 上做不到的。也许,这就是开源的魅力吧!

扩展阅读

评论

欢迎读者通过邮件与我交流,也可以在 MastodonTwitter 上关注我。