开发

为终端加上 ASCII 横幅:bash、zsh、fish、PowerShell 和 SSH 登录

用带引号的 heredoc 或文件保留反斜杠,只在交互式 shell 中打印,scp 才不会出问题。

最后更新:

每次打开终端都看到写着自己名字或机器名的横幅,既有趣,又能一眼看出正在操作哪台电脑。本指南介绍如何把在 lab.ascii 制作的横幅放进 shell 的启动文件。

示例使用 Small 字体的“DEV”。它包含反斜杠(\),一旦被破坏马上就能看出来。

 ___  _____   __
|   \| __\ \ / /
| |) | _| \ V /
|___/|___| \_/

先了解两件事

保留反斜杠

如果用 echo "..." 打印横幅,shell 会把 \ 和 $ 当作特殊字符,字符画的一部分可能会消失或改变。请改用下面任一方法:

  • 带引号的 heredoc:像 cat <<'EOF' 这样给结束标记加上引号,shell 就会按原样打印其中的内容。
  • 文件:用 TXT 按钮保存结果,再用 cat 打印。这样任何字符都不需要转义。

只在交互式 shell 中打印

scp、rsync 和 sftp 会在远程机器上启动 shell,而这个 shell 可能会读取你的启动文件。如果此时打印横幅,文件传输可能会失败。请只在交互式 shell(也就是人打开的 shell)中打印横幅。

bash:~/.bashrc

在 ~/.bashrc 末尾加上:

if [[ $- == *i* ]]; then
cat <<'EOF'
 ___  _____   __
|   \| __\ \ / /
| |) | _| \ V /
|___/|___| \_/
EOF
fi
  • 如果 $- 中包含 i,说明是交互式 shell。
  • 结尾的 EOF 必须从行首开始。前面有空格的话,bash 无法识别。

如果你把 TXT 文件保存为 ~/.banner.txt,一行就够了:

[[ $- == *i* && -r ~/.banner.txt ]] && cat ~/.banner.txt

macOS 的默认 shell 是 zsh,在 Mac 上请使用下面的 zsh 部分。

zsh:~/.zshrc

zsh 只在交互式 shell 中读取 ~/.zshrc,所以不需要额外判断。同样的 heredoc 就能用:

cat <<'EOF'
 ___  _____   __
|   \| __\ \ / /
| |) | _| \ V /
|___/|___| \_/
EOF

如果你使用 Powerlevel10k 的 instant prompt,启动时可能会出现关于控制台输出的警告。请把横幅代码移到 ~/.zshrc 开头 instant prompt 代码块的上方。

fish:fish_greeting

fish 启动时会运行 fish_greeting 函数来显示问候语。自己定义这个函数,横幅就会取代默认消息。把下面的内容写进 ~/.config/fish/config.fish:

function fish_greeting
    cat ~/.banner.txt
end

fish 的单引号字符串会把 \\ 变成一个 \,所以打印文件比把横幅粘贴进字符串更安全。

加上颜色

在横幅前输出 ANSI 颜色代码,在后面输出重置代码。在 bash 或 zsh 中:

printf '\033[36m'   # cyan
cat ~/.banner.txt
printf '\033[0m'    # back to normal
代码 颜色
\033[31m 红
\033[32m 绿
\033[33m 黄
\033[35m 品红
\033[36m 青
\033[1m 粗体

如果忘了最后的 \033[0m,之后输入的所有文字都会一直带着颜色。

PowerShell:$PROFILE

PowerShell 启动时会运行 $PROFILE 所指的文件。如果文件还不存在,先创建它并用记事本打开:

if (!(Test-Path $PROFILE)) { New-Item -Path $PROFILE -ItemType File -Force }
notepad $PROFILE

加入以下内容并保存:

$banner = @'
 ___  _____   __
|   \| __\ \ / /
| |) | _| \ V /
|___/|___| \_/
'@
Write-Host $banner -ForegroundColor Cyan
  • @' 和 '@ 之间的内容不会被改动。结尾的 '@ 必须从行首开始。
  • 如果新窗口提示“此系统上禁止运行脚本”,请为当前用户修改执行策略:Set-ExecutionPolicy -Scope CurrentUser RemoteSigned。
  • 包含 █ ═ 等方块字符或非拉丁文字的横幅,在 Windows PowerShell 5.1 中可能会乱。请在记事本中把配置文件保存为 UTF-8(带 BOM),或使用 PowerShell 7。

SSH 登录画面:/etc/motd

在 Linux 服务器上,/etc/motd 中的文字会在每次 SSH 登录时显示给所有连接的人。

sudo nano /etc/motd

粘贴横幅并保存,下次登录时就会显示。把服务器名放进横幅,就不容易把生产环境和测试环境搞混。你无法知道每个人使用什么终端,所以请选择 Standard、Slant、Small 等 ASCII 字体,而不是方块字符。Ubuntu 还会显示 /etc/update-motd.d/ 中脚本生成的消息。

在你自己的 CLI 工具中

用 Python 或 Node.js 编写的工具也遵循同样的规则:输出交给文件或其他程序时,不要打印横幅。

import sys

BANNER = r"""
 ___  _____   __
|   \| __\ \ / /
| |) | _| \ V /
|___/|___| \_/
"""

if sys.stdout.isatty():
    print(BANNER)
const banner = String.raw`
 ___  _____   __
|   \| __\ \ / /
| |) | _| \ V /
|___/|___| \_/
`;

if (process.stdout.isTTY) console.log(banner);

字符串转义的更多细节,请参见 README 横幅指南。

哪种字体最合适?

终端通常是 80 列宽,很多人还会把窗口一分为二,所以 60 列以内的横幅几乎哪里都放得下。名字较长时,请选择 Small、Small Slant 等较窄的字体。可以在如何选择 FIGlet 字体中比较宽度。

安装 figlet 程序后,可以用 figlet -f slant "$(hostname)" 之类的命令在启动时绘制横幅。不过每台机器都需要安装,未随附的字体还得另外下载。直接粘贴做好的横幅则完全不需要安装。