Linux shell:扫盲

控制台和终端

疑问来自内核调试,无论我如何调整 printk 的日志级别,都不能在我的命令行界面中看到调试信息。对这个反常现象的追究,让我认识到了控制台和终端的区别。

控制台 (Console)​

控制台 是内核的亲儿子。本质计算机的​​物理管理接口​​,直接连接系统主板(如服务器前面板的 VGA + 键盘接口)。现代 Linux 将其虚拟化为虚拟控制台(Virtual Console)​​。分为:

  • 物理控制台:比如嵌入式 Linux 通常将一个串口作为控制台,称为串口控制台
  • 虚拟控制台:由 Linux 内核直接管理,系统启动时自动创建 (tty1~tty6)。通过 Ctrl+Alt+F1Ctrl+Alt+F6 切换,虚拟控制台的输入/输出设备是直连硬件的(比如键盘接口和视频接口)。

控制台才可以接收所有内核消息​​(如启动日志、内核崩溃信息 Oops),终端则不可以。这就是我在命令行中看不到内核调试信息的原因,我的命令行实际上是一个模拟终端。当我切换到虚拟控制台 (Ctrl+Alt+F1)后,才看到实时显示的内核调试信息。

终端 (Terminal)​

终端 是用户的助手。为用户提供​​命令行交互环境的软件抽象,早期是物理设备(如 VT100 终端),现代由软件模拟(如 xterm、GNOME Terminal)。分为:

  • 物理终端:真实的物理设备,比如 VT100 终端,它通过一根串口线与大型机相连,目前已淘汰。
  • 模拟终端:在图形用户界面(GUI)环境下运行的应用程序(比如:/dev/pts/2 ),提供了类似传统终端的功能。
  • 网络终端:通过 SSH/Telnet 远程访问

模拟终端和网络终端都是通过 ​​伪终端 (Pseudo Terminal)​​ 实现的,所以我通过 ssh 登陆的终端类型为 pts/0,其中 p 就是 Pseudo。

总结

特性 控制台 (Console) 终端 (Terminal)
物理起源 计算机本机的物理控制面板(直接连接硬件) 远程输入输出设备(如电传打字机 VT100)
现代实现 内核直接管理的虚拟设备 (/dev/ttyN) 软件模拟的交互环境(终端模拟器、SSH)
数量限制 有限(通常 6 个:tty1~tty6) 理论上无限(通过伪终端 PTS 动态创建)
访问方式 物理键盘 + 显示器(如 Ctrl+Alt+F1) 通过网络或 GUI 终端程序访问
系统级作用 内核消息输出、单用户模式修复 用户交互、程序运行
依赖图形界面 完全独立(甚至在图形崩溃时仍可用) 可能依赖网络/GUI(如 Gnome Terminal)
设备路径 /dev/ttyN(N=1~6) /dev/pts/<ID>(动态分配)

登陆 Shell 和普通 Shell

定义

  1. 登陆 shell (Login Shell):登陆 系统时启动的第一个 shell 。一般通过以下途径启动:
    • 系统登陆界面
    • 通过 ssh 远程登陆 (也要先登陆)
    • 在命令行中显示指定 --login 选项 启动 shell,比如:bash --login
  2. 普通 shell (Non-Login Shell):登陆系统后,在一个会话中再启动的 shell。一般通过以下途径启动:
    • 图形界面中的终端模拟器
    • 在现有 shell 中直接启动新的子 shell,比如通过 bash 命令
    • 运行 shell 脚本

为什么要区分不同 shell

因为不同的 shell 加载的配置文件不同 ,登陆 shell 进行耗时的全面初始化,普通 shell 在此基础上只需设置自己的交互配置,在登陆 shell 的基础上进行个性化定制

  1. 登陆 shell 加载的配置:先加载 系统级 登陆配置文件,然后加载 用户级 登陆配置文件。
    • /etc/profile :系统级登陆 配置文件,作用于所有用户。
      • 如果使用 bash 作为默认 shell,它会依次加载:/etc/profile/etc/bash.bashrc
      • 应避免直接修改 /etc/profile/etc/bash.bashrc,自定义配置放入 /etc/profile.d/custom.sh
    • ~/.profile:用户级登陆 配置文件。
      • 如果使用 bash 作为默认 shell,它会依次加载: ~/.bash_profile~/.bash_login~/.profile
      • 如果使用 bash 作为默认 shell,在 ~/.profile 中会调用 ~/.bashrc
  2. 普通 shell 加载的配置:
    • 使用 bash 作为默认 shell:加载 ~/.bashrc
    • 普通 shell 继承父进程的环境变量,这意味着所有普通 shell 都会继承登陆 shell 加载的配置环境。

登陆 shell 会加载普通 shell 的配置吗?

会。

比如使用 bash 作为默认 shell,在加载用户级登陆配置文件 ~/.profile 中,会调用 ~/.bashrc

bash 复制代码
# 如果 ~/.bashrc 存在且当前 Shell 是 Bash,则加载它
if [ -n "$BASH_VERSION" ] && [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
fi

如何确认是哪种 shell ?

使用命令: echo $0,以 bash 为例,

  • 返回 -bash :输出以 - 开头,是登陆 shell
  • 返回 bash:普通 shell

Ctrl+CCtrl+Z 的区别

以 bash 为例:

  • Ctrl+Z :只是把前台进程暂停(SIGTSTP,送入后台、挂起),并不会关闭文件或释放资源 。用 fg 可以把挂起进程恢复到前台。
  • Ctrl+C :终止前台进程(SIGINT),这样发送 SIGINT 信号可中断并退出。
  • 有些应用可能不支持 Ctrl+C,比如 less ,退出是按 q 键。

其它控制键

  • 查看当前终端的快捷键设置:stty -a (Set Telttype,all)
  • Ctrl+D :发送文件结束符(EOF),关闭输入流
  • Ctrl+\:强制退出并生成 core (SIGQUIT)

Shell 词法结构

逐行 读取输入,并将输入拆分 为一个个的单词(words,这里跟英语中的"单词"含义不同。英语中"单词"是具有独立意义的最小单位,shell 中的"单词"只不可分割的字符序列。比如 last_year,英文中不是一个合法单词,但在 shell 中则是),拆分依据是:

  • 空白字符:空格和制表符
  • 操作符:对 shell 有特殊意义的字符序列

操作符有两类:控制操作符重定向操作符

  • 控制操作符:&&&();;;|||<newline>(换行符)
  • 重定向操作符:<>>|<<>><&>&<<-<>

Shell 引用

某些字符或单词在 shell 中有特殊含义,比如空白字符、操作符或关键字,引用 (quoting) 用来消除它们的特殊含义。引用有三种:

  • 成对的双引号
  • 反斜杠:消除单个字符的特殊含义,换行符除外。出现在换行符前的反斜杠被视为 续行符 (continuation)
  • 成对的单引号:消除单引号包裹的所有字符的特殊含义,单引号本身除外,所以无法在成对的单引号中包含单引号