在使用 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 上完成 😎),即使装了些后台服务,也丝毫没觉得卡顿。
更多发行版的选择可以参考 DistroWatch、 Best Linux Distros for Development,这里不做赘述。
桌面环境
发行版确定后,第二步就是桌面环境,和 macOS 不一样,Linux 社区内选择非常多,最流行的目前就是两个:
- Gnome,这是 Linux 桌面环境的老大哥,很多发行版默认都是 Gnome,其设计理念是『简单、易用、稳定』,适合不想折腾、追求稳定的用户
- 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 官方源里,可以从下面地址进行下载:
- clayrisser/debian-ghostty: 👻🌀 debian packaging for ghostty
- https://github.com/brave/brave-browser/releases
其他的常用命令行工具参考下面的脚本,它会检查是否已安装,如果没有就自动安装:
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-pgtk | Wayland 桌面 (强烈推荐) | 纯生 Wayland 渲染,无 X11 历史包袱 |
| emacs-gtk | X11 桌面 / 传统环境 | 基于 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 按键方式一致,需要进行两步走:
- 键位映射,保证和 macOS 一致,如下图所示:
- 组合键语义映射,需要保证把以 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 # 删除前一个词关键细节有两个:
application.not列表——Emacs、Ghostty、Zed 这些工具有自己的键位体系,需要排除在外,让它们接收原始键值。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_clipboardKDE 兼容问题
上面的配置在 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 -fsystemd 的用户服务做得非常好,开机自启、状态管理、日志查看都很方便。相比 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-interfontconfig 配置
配置文件路径: ~/.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休眠策略
笔记本作为开发机,不希望跑着任务突然睡过去:
1# 关掉插电时的自动挂起
2gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'总结
整体跑下来,日常使用体验已经很平滑了。 Cmd+C/V 、 Cmd+Tab 、光标移动这些高频操作的肌肉记忆基本没有断裂感。
字体渲染在 4K 屏幕上达到了满意的效果,Inter + JetBrains Mono 的组合比默认配置好看很多。
最大的收获是对整个系统的掌控感——知道每个配置项在哪、为什么这么设置,这是 macOS 上做不到的。也许,这就是开源的魅力吧!