Mac + iTerm2 运维终端配置:黑底主题 / SSH 自动角标 / zsh 增强一键还原
使用场景:Mac 上用 iTerm2,日常 SSH 到 Linux 服务器,在 tmux 里敲命令、跑 Claude Code。
配置原则:不替换、不 alias 任何原生命令 ,
ls、cat、grep、cd全是系统原样,手感零变化,只做纯增强。全部配置文件化,换新设备把目录拷过去跑一个脚本即可完整还原。
一、最终效果
- 纯黑背景 + 经典终端绿 (#00FF00)配色,深蓝、暗红都调亮过,黑底下
ls、vim、tmux 状态栏清晰可读 - SSH 自动角标 :敲任何带
ssh字样的命令或 alias,iTerm2 自动在屏幕右上角显示登录目标(如root@web01.example.com),tab 标题同步;退出登录自动清空。多 tab 长时间无操作,扫一眼就知道每个 tab 连的哪台机器 - 历史记录 20 万条:带时间戳、多 tab 实时共享、敲完立即落盘(终端崩溃不丢)、行首加空格不入历史(敲带密码的命令用)
- Ctrl+R 模糊搜索历史(fzf):敲几个碎片关键词就能捞出几个月前那条长命令
- 灰色自动建议 :输入时灰色提示历史匹配命令,按
→接受,不按完全无感 - 语法高亮:命令打对变绿、打错变红,回车前就知道对不对
- Starship 提示符 :SSH 时显示绿色主机名、root 时红色警示、命令超 3 秒显示耗时、失败显示红色退出码(不用再手动
echo $?) - 无限回滚、tmux 鼠标支持、Option 作 Meta 键(Option+B/F 按词跳光标、Claude Code 里 Option+Enter 换行)、静音铃声
二、文件结构
一个目录 5 个文件(我放在服务器 /root/mac/,也可以放 git 仓库):
mac/
├── mac-terminal-setup.sh # 一键安装脚本(幂等,可重复执行)
├── iterm2-ops-profile.json # iTerm2 主题(Dynamic Profile,自动热加载)
├── iterm2-badge.zsh # SSH 自动角标脚本
├── zshrc-ops.zsh # zsh 增强配置
└── starship.toml # 提示符配置
注:文中
duanshuaixing是我的专属命名,方便多设备识别,你可以全局替换成自己的名字。
三、安装步骤
bash
# 1. 把目录拷到 Mac(从服务器拉,或从 git 仓库 clone)
scp -rp root@你的服务器:/root/mac ~/iterm2-config
# 2. 跑安装脚本(需要已安装 Homebrew:https://brew.sh)
bash ~/iterm2-config/mac/mac-terminal-setup.sh
# 3. 新开一个 iTerm2 tab(或 source ~/.zshrc)即可看到效果
# 4. 设默认 Profile:先完全退出 iTerm2(Cmd+Q),在 Terminal.app 里执行:
defaults write com.googlecode.iterm2 "Default Bookmark Guid" "duanshuaixing-ops-dark-base"
# 再打开 iTerm2,新 tab 默认就是黑底新主题
第 4 步必须在 iTerm2 完全退出后执行,否则 iTerm2 退出时会用内存里的旧值覆盖回去。
Dynamic Profile 目录(~/Library/Application Support/iTerm2/DynamicProfiles/)是 iTerm2 实时监控的,文件放进去几秒内自动加载,不用重启。
四、配置文件全文
4.1 mac-terminal-setup.sh ------ 一键安装脚本
bash
#!/bin/bash
# ============================================================
# duanshuaixing: Mac 终端一键配置脚本
# 用法:把 /root/mac 整个目录 scp 到 Mac 后,在该目录里执行 bash mac-terminal-setup.sh
# 幂等设计,重复执行安全,换新设备跑一遍即可完整还原
# ============================================================
set -euo pipefail
cd "$(dirname "$0")"
export HOMEBREW_NO_AUTO_UPDATE=1 # 跳过 brew 自更新,国内网络下能省很久
if ! command -v brew >/dev/null 2>&1; then
echo "未检测到 Homebrew,请先安装: https://brew.sh"
exit 1
fi
echo "==> 安装字体和工具(已装的会自动跳过)..."
brew install --quiet starship fzf zsh-autosuggestions zsh-syntax-highlighting || true
brew install --quiet --cask font-jetbrains-mono-nerd-font || true
echo "==> 安装 iTerm2 Dynamic Profile(自动热加载)..."
mkdir -p "$HOME/Library/Application Support/iTerm2/DynamicProfiles"
cp iterm2-ops-profile.json "$HOME/Library/Application Support/iTerm2/DynamicProfiles/"
echo "==> 安装 zsh 配置..."
cp iterm2-badge.zsh "$HOME/.iterm2-badge.zsh"
cp zshrc-ops.zsh "$HOME/.zshrc-ops"
mkdir -p "$HOME/.config"
cp starship.toml "$HOME/.config/starship.toml"
if ! grep -q 'source ~/.zshrc-ops' "$HOME/.zshrc" 2>/dev/null; then
echo 'source ~/.zshrc-ops' >> "$HOME/.zshrc"
echo "==> 已在 ~/.zshrc 末尾追加 source ~/.zshrc-ops"
fi
echo ""
echo "完成!最后两步手动操作:"
echo "1. 新开一个 iTerm2 tab(或执行 source ~/.zshrc)"
echo "2. 设默认 Profile:完全退出 iTerm2 (Cmd+Q) 后在 Terminal.app 执行:"
echo ' defaults write com.googlecode.iterm2 "Default Bookmark Guid" "duanshuaixing-ops-dark-base"'
4.2 iterm2-ops-profile.json ------ iTerm2 黑底主题
放到 ~/Library/Application Support/iTerm2/DynamicProfiles/ 自动生效。
关键设计:
Unlimited Scrollback:无限回滚,排查日志不怕翻不到Mouse Reporting:tmux 里鼠标滚轮翻屏、点击切 pane(配合 tmux 的set -g mouse on)Option Key Sends: 2(Esc+):Option+B/F 按词跳光标;Claude Code 里 Option+Enter 换行Send Code When Idle: false:保活交给 SSH 层做(见后文 FAQ)- 字体 JetBrains Mono Nerd Font 14 号:
0/O、1/l分明,图标正常渲染
json
{
"Profiles": [
{
"Name": "duanshuaixing-ops-dark",
"Guid": "duanshuaixing-ops-dark-base",
"Description": "duanshuaixing 运维专属:纯黑背景,SSH/tmux 友好,角标由 zsh 自动更新",
"Custom Directory": "No",
"Command": "",
"Custom Command": "No",
"Columns": 140,
"Rows": 40,
"Normal Font": "JetBrainsMonoNFM-Regular 14",
"Use Bold Font": true,
"Use Bright Bold": true,
"Use Italic Font": true,
"Horizontal Spacing": 1,
"Vertical Spacing": 1.05,
"Use Non-ASCII Font": false,
"Ambiguous Double Width": false,
"Unicode Version": 9,
"Character Encoding": 4,
"Terminal Type": "xterm-256color",
"Mouse Reporting": true,
"Mouse Reporting allow mouse wheel": true,
"Option Key Sends": 2,
"Right Option Key Sends": 0,
"Scrollback Lines": 0,
"Unlimited Scrollback": true,
"Scrollback in Alternate Screen": false,
"Silence Bell": true,
"BM Growl": false,
"Visual Bell": true,
"Flashing Bell": false,
"Blinking Cursor": false,
"Cursor Type": 2,
"Close Sessions On End": true,
"Prompt Before Closing 2": 0,
"Send Code When Idle": false,
"Allow Title Setting": true,
"Badge Text": "",
"Badge Color": {
"Red Component": 0.0, "Green Component": 1.0, "Blue Component": 0.0,
"Alpha Component": 0.65, "Color Space": "sRGB"
},
"Badge Font": "Menlo-Bold",
"Badge Max Width": 0.45,
"Badge Max Height": 0.2,
"Minimum Contrast": 0.2,
"Transparency": 0,
"Blur": false,
"Foreground Color": {
"Red Component": 0.878, "Green Component": 0.878, "Blue Component": 0.878
},
"Background Color": {
"Red Component": 0.0, "Green Component": 0.0, "Blue Component": 0.0
},
"Bold Color": {
"Red Component": 1.0, "Green Component": 1.0, "Blue Component": 1.0
},
"Cursor Color": {
"Red Component": 0.0, "Green Component": 1.0, "Blue Component": 0.0
},
"Cursor Text Color": {
"Red Component": 0.0, "Green Component": 0.0, "Blue Component": 0.0
},
"Selection Color": {
"Red Component": 0.22, "Green Component": 0.32, "Blue Component": 0.47
},
"Selected Text Color": {
"Red Component": 1.0, "Green Component": 1.0, "Blue Component": 1.0
},
"Link Color": {
"Red Component": 0.4, "Green Component": 0.7, "Blue Component": 1.0
},
"Ansi 0 Color": { "Red Component": 0.20, "Green Component": 0.20, "Blue Component": 0.20 },
"Ansi 1 Color": { "Red Component": 0.90, "Green Component": 0.31, "Blue Component": 0.31 },
"Ansi 2 Color": { "Red Component": 0.0, "Green Component": 0.80, "Blue Component": 0.0 },
"Ansi 3 Color": { "Red Component": 0.90, "Green Component": 0.75, "Blue Component": 0.35 },
"Ansi 4 Color": { "Red Component": 0.38, "Green Component": 0.62, "Blue Component": 0.94 },
"Ansi 5 Color": { "Red Component": 0.78, "Green Component": 0.47, "Blue Component": 0.87 },
"Ansi 6 Color": { "Red Component": 0.30, "Green Component": 0.78, "Blue Component": 0.78 },
"Ansi 7 Color": { "Red Component": 0.80, "Green Component": 0.80, "Blue Component": 0.80 },
"Ansi 8 Color": { "Red Component": 0.45, "Green Component": 0.45, "Blue Component": 0.45 },
"Ansi 9 Color": { "Red Component": 1.00, "Green Component": 0.45, "Blue Component": 0.45 },
"Ansi 10 Color": { "Red Component": 0.0, "Green Component": 1.0, "Blue Component": 0.0 },
"Ansi 11 Color": { "Red Component": 1.00, "Green Component": 0.88, "Blue Component": 0.45 },
"Ansi 12 Color": { "Red Component": 0.50, "Green Component": 0.74, "Blue Component": 1.00 },
"Ansi 13 Color": { "Red Component": 0.90, "Green Component": 0.60, "Blue Component": 1.00 },
"Ansi 14 Color": { "Red Component": 0.45, "Green Component": 0.92, "Blue Component": 0.92 },
"Ansi 15 Color": { "Red Component": 1.00, "Green Component": 1.00, "Blue Component": 1.00 }
}
]
}
4.3 iterm2-badge.zsh ------ SSH 自动角标
不用给每台机器建 Profile:只要命令行里带 ssh 字样(alias 也算),角标自动显示登录目标。有一百个 ssh alias 也零维护。
bash
# ============================================================
# duanshuaixing: iTerm2 自动登录角标
# 放到 Mac 的 ~/.zshrc 末尾(或 source 本文件)
#
# 效果:敲任何带 "ssh" 字样的命令/alias 时,iTerm2 在屏幕右上角
# 显示登录目标,tab 标题同步;退出登录后自动清空。
# zhipu-ssh-claude -> 显示 zhipu-ssh-claude
# ssh root@web01.example.com -> 显示 root@web01.example.com
# ssh -p 2222 root@10.1.1.5 -> 显示 root@10.1.1.5
# ============================================================
autoload -Uz add-zsh-hook
# 设置 iTerm2 屏幕角标(OSC 1337,内容需 base64;传空串即清除)
_dsx_badge() {
printf "\e]1337;SetBadgeFormat=%s\a" "$(printf '%s' "$1" | base64)"
}
_dsx_preexec() {
[[ "$1" != *ssh* ]] && return
local -a words
words=(${(z)1})
local name=$words[1]
# 裸 ssh 命令:取真正的登录目标,而不是 "ssh" 本身
if [[ $name == ssh ]]; then
local w
# 优先找 user@host 形式的参数
for w in ${words[2,-1]}; do
[[ $w == *@* ]] && { name=$w; break }
done
# 没有 @ 的话(用了 ssh config 别名),取第一个非选项参数
if [[ $name == ssh ]]; then
for w in ${words[2,-1]}; do
[[ $w == -* ]] && continue
name=$w; break
done
fi
fi
_dsx_badge "$name"
printf "\e]0;%s\a" "$name"
}
_dsx_precmd() {
_dsx_badge ""
printf "\e]0;%s\a" ""
}
add-zsh-hook preexec _dsx_preexec
add-zsh-hook precmd _dsx_precmd
4.4 zshrc-ops.zsh ------ zsh 增强配置
bash
# ============================================================
# duanshuaixing: Mac 终端运维配置(zsh 部分)
# 由 mac-terminal-setup.sh 安装为 ~/.zshrc-ops,并在 ~/.zshrc 中 source
#
# 原则:不替换、不 alias 任何原生命令,手感和裸终端完全一致,
# 只做纯增强:历史记录、输入提示、提示符显示。
# ============================================================
# ---------- 历史记录:运维的命令历史就是资产 ----------
HISTFILE=~/.zsh_history
HISTSIZE=200000 # 内存里保留 20 万条
SAVEHIST=200000 # 文件里保留 20 万条
setopt EXTENDED_HISTORY # 记录每条命令的时间戳和耗时
setopt INC_APPEND_HISTORY # 敲完立即写入,不等退出(防终端崩溃丢历史)
setopt SHARE_HISTORY # 多个 tab 之间历史实时共享
setopt HIST_IGNORE_ALL_DUPS # 重复命令只留最新一条
setopt HIST_IGNORE_SPACE # 行首加空格的命令不入历史(带密码的命令用)
# ---------- 补全(zsh 自带能力,只调行为不加东西)----------
autoload -Uz compinit && compinit
zstyle ':completion:*' menu select # Tab 两次出菜单,方向键选
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' # 补全忽略大小写
# ---------- 输入增强 ----------
BREW_PREFIX=$(brew --prefix)
# 自动建议:输入时灰色显示历史里匹配的命令,按 → 接受整条;不按就完全无感
source $BREW_PREFIX/share/zsh-autosuggestions/zsh-autosuggestions.zsh
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=240'
# fzf:把 Ctrl+R 升级为全屏模糊搜索历史(唯一改变原有按键行为的一项,
# 不习惯的话注释掉下面两行,Ctrl+R 立刻恢复 zsh 原生搜索)
source <(fzf --zsh)
export FZF_DEFAULT_OPTS='--height 40% --reverse --color=bg:#000000,fg:#e0e0e0,hl:#00ff00,prompt:#00ff00'
# Starship 提示符(只改提示符外观,不碰命令)
eval "$(starship init zsh)"
# ---------- iTerm2 SSH 角标 ----------
[[ -f ~/.iterm2-badge.zsh ]] && source ~/.iterm2-badge.zsh
# ---------- 语法高亮:命令存在=绿色,敲错=红色,回车前就知道对不对 ----------
# 官方要求必须放在 zshrc 最后加载
source $BREW_PREFIX/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
4.5 starship.toml ------ 提示符配置
toml
# duanshuaixing: Starship 提示符配置(黑底运维版)
# 安装位置:~/.config/starship.toml
# 单行提示符,只显示运维真正需要的信息,不堆图标
add_newline = false
command_timeout = 1000
format = """$username$hostname$directory$git_branch$git_status$cmd_duration$status$character"""
[username]
show_always = false # 普通用户不显示;root 或 su 到别的用户时才显示
style_user = "bold yellow"
style_root = "bold red"
format = "[$user]($style)@"
[hostname]
ssh_only = true # 只在 SSH 会话里显示主机名,本地保持干净
style = "bold green"
format = "[$hostname]($style) "
[directory]
truncation_length = 4 # 最多显示 4 级目录
truncate_to_repo = false
style = "bold cyan"
format = "[$path]($style) "
[git_branch]
style = "purple"
format = "[$branch]($style)"
[git_status]
style = "red"
format = "[$all_status$ahead_behind]($style) "
[cmd_duration]
min_time = 3000 # 上一条命令超过 3 秒才显示耗时
style = "yellow"
format = "[$duration]($style) "
[status]
disabled = false # 上一条命令失败时显示红色退出码,排障必备
style = "bold red"
format = "[✗$status]($style) "
[character]
success_symbol = "[❯](bold green)"
error_symbol = "[❯](bold red)"
五、配套的 SSH / tmux 设置(服务器侧)
1. SSH 保活 (防止长时间挂着 tmux / Claude Code 被断连),Mac 的 ~/.ssh/config:
Host *
ServerAliveInterval 30
ServerAliveCountMax 4
2. 远程复制直达 Mac 剪贴板(OSC52,运维刚需):
-
iTerm2:
Settings → General → Selection → 勾选 "Applications in terminal may access clipboard" -
服务器
~/.tmux.conf加:set -g mouse on
set -g set-clipboard on
这样在远程 tmux 里选中复制的内容直接进 Mac 剪贴板,不用鼠标跨 pane 拖选。
六、FAQ
Q: 脚本卡在 Auto-updating Homebrew...?
brew 安装前的自动自更新,国内网络可能等很久。脚本里已加 HOMEBREW_NO_AUTO_UPDATE=1 跳过;手动装包时也可以 HOMEBREW_NO_AUTO_UPDATE=1 brew install xxx。
Q: 角标为什么看起来比输入的文字"暗"?
角标是印在背景上的半透明水印(透明度 65%),不占行、不遮挡输出,和命令行文字不是一个东西。想更醒目就把 JSON 里 Badge Color 的 Alpha Component 往 1.0 调(太高会盖住文字,0.65 是可读性和醒目度的平衡点)。
Q: 不习惯 fzf 的 Ctrl+R?
注释掉 zshrc-ops.zsh 里 source <(fzf --zsh) 那两行,Ctrl+R 立刻恢复 zsh 原生搜索。
Q: defaults write 设默认 Profile 不生效?
必须在 iTerm2 完全退出(Cmd+Q) 后执行(比如在 Terminal.app 里),否则 iTerm2 退出时会用内存里的旧值覆盖回去。
Q: ssh alias 名字里不含 "ssh" 怎么办?
角标脚本靠 [[ "$1" == *ssh* ]] 匹配。要么 alias 命名带上 ssh(如 prod-ssh-db),要么把匹配条件加宽,如 [[ "$1" == *ssh* || "$1" == jump* ]]。
Q: 这套配置对服务器端生效吗?
不。历史增强、语法高亮、Starship 都装在 Mac 本地,SSH 进服务器后远端 shell 是服务器自己的配置。角标和主题是 iTerm2 层面的,全程有效。
七、换新设备还原清单
bash
# 1. 装 Homebrew(如果是全新机器): https://brew.sh
# 2. 拷目录、跑脚本
scp -rp 旧机器或服务器:/path/to/mac ~/iterm2-config
bash ~/iterm2-config/mac/mac-terminal-setup.sh
# 3. Cmd+Q 退出 iTerm2 后设默认 Profile
defaults write com.googlecode.iterm2 "Default Bookmark Guid" "duanshuaixing-ops-dark-base"
# 4. ~/.ssh/config 加保活配置(见第五节)