服务器开机后在 tty1 自动显示 btop:一块小屏幕救一根 HDMI 线的故事

random-pic-api

背景:我只是想让那块小屏幕别闲着

家里那台服务器是主力 Homelab,24 小时跑着 PVE、几个 LXC、几组 Docker。之前监控全靠 Grafana + Nezha,看得很全,但有个问题:每次我想”扫一眼当前状态”,都得掏手机或者切到电脑上的浏览器。

某天翻出一块以前买摄像头配的 7 寸 HDMI 小屏幕,突然就想:要是把它接到服务器 HDMI 口上,常亮挂一个 btop 不就好了?走过服务器旁边看一眼 CPU/内存/磁盘/网络,比掏手机快多了。

理想很美好,现实一接上就踩坑:

  • 开机后屏幕默认停在 getty@tty1 的登录提示符
  • 要看 btop 得先插键盘、输账号密码、btop 回车
  • 我的服务器放在柜子里,键盘根本不在旁边
  • 偶尔掉电重启,每次都要拖一根键盘线过去,心态爆炸

说白了我要的不是”登录系统”,我要的是一块常亮的监控屏。那 tty1 这个位置就不能留给 getty,而应该直接跑 btop。

记录一下最后的方案,顺便留档给未来的自己。

目标

  • 开机后 tty1 直接显示 btop,不需要登录、不需要键盘
  • 屏幕 24 小时常亮做仪表盘用
  • 不想登录界面?切到 tty2(Ctrl+Alt+F2)照样能登
  • 随时能滚回默认的 getty 登录行为

思路

这套方案其实很朴素:

  1. 停掉默认抢占 tty1 的 getty@tty1 登录服务
  2. 自己写一个 systemd service,把 tty1 指给 btop
  3. 加上 Restart=always,万一 btop 因为终端尺寸变化退出,秒起

核心坑只有一个:tty1 默认是被 getty@.service 模板实例化抢走的,你不屏蔽它,你的服务进程会跟它抢同一个 TTY,结果就是屏幕上闪烁、光标乱跳、btop 一直被挤下去。

下面是具体操作,环境是 Debian 系(Proxmox VE / Ubuntu Server 通用),其他发行版 systemd 逻辑一致,只是包管理命令换一下。


一、让 btop 跑起来

1. 安装 btop

1
2
apt update
apt install -y btop

装完随便 btop 一下确认能跑,确认一下字符是不是乱的。如果乱码,一般是 locale 或者 TERM 没设对,后面 service 里我直接写死 xterm-256color,大概率没问题。

2. 停掉并屏蔽 getty@tty1

1
2
systemctl disable --now getty@tty1.service
systemctl mask getty@tty1.service

两步要一起做:disable --now 是让它停掉并且开机不再起;mask 是彻底屏蔽,防止被依赖关系反向拉起。只 disablemask 会踩坑,一些 target 会把它重新拽回来。

可选清理一下残留配置,避免以后改的时候被老文件误导:

1
rm -rf /etc/systemd/system/getty@tty1.service.d

3. 新增 btop 的 systemd 服务

创建文件 /etc/systemd/system/pve-dashboard-tty1.service,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Unit]
Description=btop on tty1
After=multi-user.target

[Service]
Type=simple
User=root
StandardInput=tty
StandardOutput=tty
StandardError=tty
TTYPath=/dev/tty1
TTYReset=no
TTYVHangup=no
TTYVTDisallocate=no
Environment=TERM=xterm-256color
WorkingDirectory=/root
ExecStart=/usr/bin/btop
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target

几个字段单独说两句,都是踩过坑才写进去的:

  • StandardInput/Output/Error=tty + TTYPath=/dev/tty1:把 btop 的三条流都接到 tty1 上,不然你会看到服务”起来了”,但屏幕上什么都没有
  • TTYReset=noTTYVHangup=noTTYVTDisallocate=no:关掉 systemd 自作主张的 TTY 重置。开了之后每次 service 重启屏幕都会黑一下,体验很割裂
  • Environment=TERM=xterm-256color:不写的话 btop 出来的画面可能没颜色或者字符错位
  • Restart=always + RestartSec=2:给 btop 偶发退出兜底(比如我手贱切过屏幕分辨率)
  • service 名字里带了 pve-dashboard- 前缀,是为了以后 systemctl list-units | grep dashboard 一眼就能找到

4. 启用并启动

1
2
systemctl daemon-reload
systemctl enable --now pve-dashboard-tty1.service

这一下执行完,屏幕上应该已经是 btop 的界面了。如果还停在登录提示符,99% 是第 2 步的 getty 没屏蔽干净,回去 systemctl status getty@tty1.service 看看。

5. 验证

1
systemctl status pve-dashboard-tty1.service --no-pager

能看到 active (running),并且屏幕实时显示 CPU/内存的动态图,就成了。

6. 给自己留个登录口子:tty2

tty1 被 btop 占了之后,想本地登录怎么办?启用 tty2 就好:

1
systemctl enable --now getty@tty2.service

屏幕前按 Ctrl + Alt + F2 切到 tty2 登录,Ctrl + Alt + F1 切回 btop。插上键盘就是传统 Linux 控制台,拔掉键盘就是一块监控屏,两不耽误。


二、回滚:恢复默认的 tty1 登录界面

哪天不想要仪表盘模式了,或者要把机器送去维修,按顺序跑一遍就能恢复。

1. 停掉 btop 服务

1
2
systemctl disable --now pve-dashboard-tty1.service
rm -f /etc/systemd/system/pve-dashboard-tty1.service

2. 解除屏蔽并启用 getty@tty1

1
2
systemctl unmask getty@tty1.service
systemctl enable --now getty@tty1.service

3. 重载 systemd

1
systemctl daemon-reload

4. 验证

1
systemctl status getty@tty1.service --no-pager

能看到 active (running),屏幕回到熟悉的 login: 提示符,整个操作就闭环了。


一些题外话

这事做完之后,我又顺手干了两件相关的小优化,这里一起记一下:

  • 关掉屏幕休眠:控制台默认有 consoleblank 把屏幕黑掉,在 /etc/default/grub 里把 GRUB_CMDLINE_LINUX_DEFAULT 加上 consoleblank=0,然后 update-grub + 重启就好
  • btop 的配色:默认主题在小屏幕上不太醒目,我换成了 gruvbox_dark,远远一眼看过去颜色层次更清楚
  • HDMI 自动亮度:小屏幕自带的 OSD 菜单把亮度调到 30 左右,白天够看、晚上不刺眼

总的来说这套方案非常朴素,一共就改了一个 systemd service 文件,但解决了一个每天都会发生的小痛点:服务器旁边的那块屏幕终于有存在感了

以前它只是一块盖灰用的塑料板,现在走过去瞟一眼就能知道机器是不是在正常呼吸,这种感觉还挺好的。