Ecrose's Blog

🏠HOME 📑POSTS 👀MESSAGE 🔗LINK 🖇️RSS
https://s1.ax1x.com/2022/05/15/O2DAfS.png

terminal与shell概念及简单美化

2022-05-11 00:45

  • 杂技浅尝
  • 资源

🤯震惊,你随手使用的小小终端竟可能价值千万

Show HN: Warp, a Rust-based terminal | Hacker News

最近 Warp 发布了新闻稿,筹集了 2300 万美元的资金全力用来构建这个终端。

它之前筹集了 600 万美元的种子轮融资,由 GV 领投,Neo 和 BoxGroup 参投。还筹集了 1700 万美元的 A 轮融资,由 Figma 的联合创始人兼首席执行官 Dylan Field 领投。由企业家主导的这一轮投资,其参与者包括 Elad Gil、LinkedIn 前首席执行官 Jeff Weiner 和 Salesforce 的联合创始人兼联合首席执行官 Marc Benioff。

shell与终端、tty

广义的终端(英语:Computer terminal),是指一台电脑或者计算机系统,用来让用户输入数据,及显示其计算结果的机器,简而言之就是人类用户与计算机交互的设备。终端有些是全电子的,也有些是机电的。其又名终端机,它与一部独立的电脑不同,但也是电脑组成的部分。

终端相关名词:

  • CLI: 命令行, 图形界面普及之前使用最为广泛的用户界面。
  • Terminal: 一种用来让用户输入数据到计算, 并回显计算结果的机器, 一个IO交互设备
  • Console: 一种特殊的终端。
  • Terminal Emulator: 终端模拟器, 利用程序模拟终端行为, 例如iterm2
  • TTY: 终端的统称,该名称沿用了历史习惯,电传打字机(teletypewriter)曾经是计算机的终端,它的缩写便是 TTY(TeleTYpewriter)。
  • Shell: 命令行解释器, 执行用户输入的命令并返回结果

最早期的大型机和小型机时代,计算机因为体积过于庞大,只能被安置于特殊的房间内。用户只能通过特殊的设备与这些计算机交互,这些设备就成为早期的终端。

随着个人微型电脑普及,终端设备也一直在发展,其概念也越来越模糊,根据历史我们可以总结:

  • 字符终端: 文本终端, 仅仅接收和显示文本信息的终端。
  • 基于字符的图形终端: 不仅仅可以显示文本信息, 还可以显示图形和图像, 进行复杂的操作。
  • 运行窗口系统的图形终端: 现在我们使用的窗口系统。

上面说的都是硬件终端设备,随着个人电脑普及,逐渐被键盘和显示器所代替。为了方便用户使用命令行操作电脑,人们又开发了一种终端模拟器程序,用于模拟传统终端行为。

一个终端模拟器的工作流程如下:

  • 监听键盘事件,捕捉键盘输入
  • 将键盘输入发送给 tty 驱动
  • 获取tty驱动响应,输出结果(STDOUT/STDERR)
  • 调用图形接口, 比如X11, 将输出回显到显示器上

terminal/终端/模拟终端(图形界面,命令行界面)->pty(ptm,pts,ttys) ->shell(bash, zsh等)

->kernel。

终端这里有好几种,图形终端,命令行终端。

在macos中,图形界面终端名称是console(ttys000),图形界面下打开的终端/命令行窗口名称是ttys000。

在linux中,图形界面终端名称是tty7, 图形界面下的命令行窗口名称是pts/17 (使用tty可以查看到)。 纯粹的命令行界面名称是tty1~tty6.

  • CTRL + ALT + F1 – 锁屏

  • CTRL + ALT + F2 – 桌面环境

  • CTRL + ALT + F3 – TTY3

  • CTRL + ALT + F4 – TTY4

  • CTRL + ALT + F5 – TTY5

  • CTRL + ALT + F6 – TTY6

  • ptm,pts,ttys

    1、 控制台

    • 系统控制台/dev/console

    /dev/console是系统控制台,是与操作系统交互的设备。系统所产生的信息会发送到该设备上。平时我们看到的PC只有一个屏幕和键盘,它其实就是控制台。目前只有在单用户模式下,才允许用户登录控制台/dev/console。(可以在单用户模式下输入tty命令进行确认)。

    某些情况下console和tty0是一致的,就是当前所使用的是虚拟终端,也是激活虚拟终端。所以有些资料中称/dev/console是到/dev/tty0的符号链接,但是这样说现在看来是不对的:根据内核文档,在2.1.71之前,/dev/console根据不同系统设定,符号链接到/dev/tty0或者其他tty*上,在2.1.71版本之后则完全由内核代码内部控制它的映射。

    如果一个终端设备要实现console功能,必须向内核注册一个struct console结构,一般的串口驱动中都会有。如果设备要实现tty功能,必须要内核的tty子系统注册一个struct tty_driver结构,注册函数在drivers/tty/tty_io.c中。一个设备可以同时实现console和tty_driver,一般串口都这么做。

    • 当前控制台: /dev/tty

    这是应用程序中的概念,如果当前进程有控制终端(Controlling Terminal),那么/dev/tty就是当前进程控制台的设备文件。对于你登录的shell,/dev/tty就是你使用的控制台,设备号是(5,0)。不过它并不指任何物理意义上的控制台,/dev/tty会映射到当前设备(使用命令“tty”可以查看它具体对应哪个实际物理控制台设备)。输出到/dev/tty的内容只会显示在当前工作终端上(无论是登录在ttyn中还是pty中)。你如果在控制台界面下(即字符界面下)那么dev/tty就是映射到dev/tty1-6之间的一个(取决于你当前的控制台号),但是如果你现在是在图形界面(Xwindows),那么你会发现现在的/dev/tty映射到的是/dev/pts的伪终端上。/dev/tty有些类似于到实际所使用终端设备的一个联接。

    你可以输入命令 “tty",将显示当前映射终端如:/dev/tty1或者/dev/pts/0等。也可以使用命令“ps -ax”来查看其他进程与哪个控制终端相连。

    在当前终端中输入 echo “tekkaman” > /dev/tty ,都会直接显示在当前的终端中。

    • 虚拟控制台 /dev/ttyn

    /dev/ttyn是进程虚拟控制台,他们共享同一个真实的物理控制台。

    如果在进程里打开一个这样的文件且该文件不是其他进程的控制台时,那该文件就是这个进程的控制台。进程printf数据会输出到这里。在PC上,用户可以使用alt+Fn切换控制台,看起来感觉存在多个屏幕,这种虚拟控制台对应tty1~n,其中 :

    /dev/tty1等代表第一个虚拟控制台

    例如当使用ALT+F2进行切换时,系统的虚拟控制台为/dev/tty2 ,当前控制台(/dev/tty)则指向/dev/tty2

    在UNIX系统中,计算机显示器通常被称为控制台(Console)。它仿真了类型为Linux的一种终端,并且有一些设备特殊文件与之相关联:tty0、tty1、tty2等。当你在控制台上登录时,使用的是tty1。使用Alt+[F1—F6]组合键时,我们就可以切换到tty2、tty3等上面去。

    你可以登录到不同的虚拟控制台上去,因而可以让系统同时有几个不同的会话存在。

    而比较特殊的是/dev/tty0,他代表当前虚拟控制台,是当前所使用虚拟控制台的一个别名。因此不管当前正在使用哪个虚拟控制台(注意:这里是虚拟控制台,不包括伪终端),系统信息都会发送到/dev/tty0上。只有系统或超级用户root可以向/dev/tty0进行写操作。tty0是系统自动打开的,但不用于用户登录。在Framebuffer设备没有启用的系统中,可以使用/dev/tty0访问显卡。

    2、 伪终端pty(pseudo-tty)

    伪终端(Pseudo Terminal)是终端的发展,为满足现在需求(比如网络登陆、xwindow窗口的管理)。它是成对出现的逻辑终端设备(即master和slave设备, 对master的操作会反映到slave上)。它多用于模拟终端程序,是远程登陆(telnet、ssh、xterm等)后创建的控制台设备。

    历史上,有两套伪终端软件接口:

    BSD接口:较简单,master为/dev/pty[p-za-e][0-9a-f] ;slave为 /dev/tty[p-za-e][0-9a-f] ,它们都是配对的出现的。例如/dev/ptyp3和/dev/ttyp3。但由于在编程时要找到一个合适的终端需要逐个尝试,所以逐渐被放弃。

    Unix 98接口:使用一个/dev/ptmx作为master设备,在每次打开操作时会得到一个master设备fd,并在/dev/pts/目录下得到一个slave设备(如 /dev/pts/3和/dev/ptmx),这样就避免了逐个尝试的麻烦。由于可能有好几千个用户登陆,所以/dev/pts/*是动态生成的,不象其他设备文件是构建系统时就已经产生的硬盘节点(如果未使用devfs、udev、mdev等) 。第一个用户登陆,设备文件为/dev/pts/0,第二个为/dev/pts/1,以此类推。它们并不与实际物理设备直接相关。现在大多数系统是通过此接口实现pty。

    我们在X Window下打开的终端或使用telnet 或ssh等方式登录Linux主机,此时均通过pty设备。例如,如果某人在网上使用telnet程序连接到你的计算机上,则telnet程序就可能会打开/dev/ptmx设备获取一个fd。此时一个getty程序就应该运行在对应的/dev/pts/*上。当telnet从远端获取了一个字符时,该字符就会通过ptmx、pts/传递给 getty程序,而getty程序就会通过pts/、ptmx和telnet程序往网络上返回“login:”字符串信息。这样,登录程序与telnet程序就通过“伪终端”进行通信。

    1. telnet<—>/dev/ptmx(master)<—>pts/*(slave)<—>getty

    如果一个程序把 pts/看作是一个串行端口设备,则它对该端口的读/写操作会反映在该逻辑终端设备对的另一个/dev/ptmx上,而/dev/ptmx则是另一个程序用于读写操作的逻辑设备。这样,两个程序就可以通过这种逻辑设备进行互相交流,这很象是逻辑设备对之间的管道操作。对于pts/,任何设计成使用一个串行端口设备的程序都可以使用该逻辑设备。但对于使用/dev/ptmx的程序,则需要专门设计来使用/dev/ptmx逻辑设备。

    通过使用适当的软件,就可以把两个甚至多个伪终端设备连接到同一个物理串行端口上。

    3、 串口终端(/dev/ttySn)

    串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。有段时间串行端口设备通常被称为终端设备,那时它的最大用途就是用来连接终端,所以这些串行端口所对应的设备名称是/dev/tts/0(或/dev/ttyS0)、/dev/tts/1(或/dev

    /ttyS1)等,设备号分别是(4,0)、(4,1)等(对应于win系统下的COM1、COM2等)。若要向一个端口发送数据,可以在命令行上把标准输出重定向到这些特殊文件名上即可。

    例如,在命令行提示符下键入:echo tekkaman> /dev/ttyS1会把“tekkaman”发送到连接在ttyS1(COM2)端口的设备上。

    在2.6以后的内核中,部分三星芯片(例如S3C24x0等)将串口终端设备节点命名为ttySACn。TI的Omap系列芯片从2.6.37开始芯片自带的UART设备开始使用专有的的omap-uart驱动,故设备节点命名为ttyOn,以区别于使用8250驱动时的设备名“ttySn”。

    # 4、 其它类型终端
    

> 还针对很多不同的字符设备存在有很多其它种类的终端设备特殊文件,例如针对ISDN设备的/dev/ttyIn终端设备等。

接下来一个问题。我们知道在终端中有一些常用的快捷键,Ctrl+E可以移动到行尾,Ctrl+W可以删除一个单词,Ctrl+B可以向前移动一个字母,按上键可以出现上一个使用过的 shell 命令。在这 4 种快捷键中,有一个是和其他的实现不一样的,请问是哪一个?

  • answer

    答案是 Ctrl+W。因为 Ctrl+W是TTY 提供的,其余的三个是 shell 提供的

shell关系

终端(Terminal)是对字符输入输出设备的抽象,在Linux中terminal是一种特殊的文件,在/dev目录下。通常情况下,键盘输入会写这个文件,而对应的终端驱动程序会执行诸如回显的工作(可以通过stty改变驱动程序的默认行为),如果没有了terminal,那么就无法响应键盘的输入。shell的本质是一个软件,这个软件中可以通过fork + exec + wait去加载别的可执行程序并运行。如果没有了shell,那么我们输入’ls’的时候,只会回显’ls’字符,并不会执行ls这个程序,所以shell的工作就是解析我们的输入字符,并执行对应的指令。Terminal和shell之间有什么关系呢?当我们去运行shell软件的时候,shell的stdin、stdout和stderr会打开并指向一个特定的terminal文件,这样导致我们通过键盘的输入实际上是写到terminal文件里面,但是shell也可以通过他的stdin从这个terminal文件中读到。

shell中进程的创建

线程结构

进程结构由以下几个部分组成:代码段、堆栈段、数据段。代码段是静态的二进制代码,多个程序可以 共享。

实际上在父进程创建子进程之后,父、子进程除了pid外,几乎所有的部分几乎一样。 父、子进程共享全部数据,但并不是说他们就是对同一块数据进行操作,子进程在读写数据时会通过写

时复制机制将公共的数据重新拷贝一份,之后在拷贝出的数据上进行操作。

如果子进程想要运行自己的代码段,还可以通过调用execv()函数重新加载新的代码段,之后就和父进程 独立开了。

我们在shell中执行程序就是通过shell进程先fork()一个子进程再通过execv()重新加载新的代码段的过程。

进程在执行过程中可能创建多个新的进程。创建进程称为父进程,而新的进程称为子进程。每个新进程可以再创建其他进程,从而形成进程树。

大多数的操作系统(包括 UNIX、Linux 和 Windows)对进程的识别采用的是唯一的进程标识符 (pid),pid 通常是一个整数值。系统内的每个进程都有一个唯一 pid,它可以用作索引,以便访问内核中的进程的各种属性。

一般来说,当一个进程创建子进程时,该子进程需要一定的资源(CPU 时间、内存、文件、I/O 设备等)来完成任务。子进程可以从操作系统那里直接获得资源,也可以只从父进程那里获得资源子集。父进程可能要在子进程之间分配资源或共享资源(如内存或文件)。限制子进程只能使用父进程的资源,可以防止创建过多进程,导致系统超载。

除了提供各种物理和逻辑资源外,父进程也可能向子进程传递初始化数据(或输入)。例如,假设有一个进程,其功能是在终端屏幕上显示文件如 image.jpg 的状态。当该进程被创建时,它会从父进程处得到输入,即文件名称 image.jpg。通过这个名称,它会打开文件,进而写出内容。它也可以得到输出设备名称。另外,有的操作系统会向子进程传递资源。对于这种系统,新进程可得到两个打开文件,即 image.jpg 和终端设备,并且可以在这两者之间进行数据传输。

当进程创建新进程时,可有两种执行可能:

父进程与子进程并发执行。

父进程等待,直到某个或全部子进程执行完。

新进程的地址空间也有两种可能:

子进程是父进程的复制品(它具有与父进程同样的程序和数据)。

子进程加载另一个新程序。

背景知识: 进程有两种创建方式,一种是操作系统创建的一种是父进程创建的。从计算机启动到终端执行程 序的过程为:0号进程 -> 1号内核进程 -> 1号用户进程(init进程) -> getty进程 -> shell进程 -> 命令行 执行进程。所以我们在命令行中通过 ./program执行可执行文件时,所有创建的进程都是shell进程 的子进程,这也就是为什么shell一关闭,在shell中执行的进程都自动被关闭的原因。

nushell

现代化shell,某些操作逻辑类似sql

得到的输出更工整

其它

ripgrep、bat等优秀的rust开发的工具

Rust学习

Rust优点

从语言的内核来看,它重塑了我们对一些基本概念的理解。比如 Rust 清晰地定义了变量在 一个作用域下的生命周期,让开发者在摒弃垃圾回收(GC)这样的内存和性能杀手的前提 下,还能够无需关心手动内存管理,让内存安全和高性能二者兼得。

从语言的外观来看,它使用起来感觉很像 Python/TypeScript 这样的高级语言,表达能力 一流,但性能丝毫不输于 C/C++,从而让表达力和高性能二者兼得。

学习资料

  • 官方教程两本(官网)
  • 国内开源社区出的一份教程,并且提供配套练习(推荐)

Rust语言圣经(Rust Course)

  • Rust社区

RustCn 社区

  • 极客时间相关专栏课

简单美化

zsh主题

适用于所有shell的主题配置 starship(https://starship.rs)

终端复用TMux(快捷键较多)或者Zellij

当然如果真的追求🌹🍐🐯🔥的终端则是 https://github.com/seenaburns/dex-ui

dex-ui

wrap特点

现在主流操作系统都会带有终端模拟器,这足以说明它的重要性。尤其是对于广大开发者来说,终端模拟器是无法离开的存在。远的不说,在过去的二十年里,各种各样的终端模拟器层出不穷,围绕终端模拟器的各种工具也层出不穷。每个开发者为了拥有一个漂亮、方便、功能丰富的终端模拟器,也是煞费苦心。

虽然现在的常用的终端模拟器也有很多好用的,比如 Rust 实现的高性能跨平台现代化终端模拟器 alacritty 。但它们的内核其实还是一个传统的终端模拟器。现代开发者,要使用终端做很多事,从构建代码、执行和部署,与版本控制系统交互到与云端交互等。作为开发者日常离不开的工具,在当下日益增长的开发需求的时代,现在的终端模拟器却没有帮助开发者提升更多工作效率。

截屏2022-05-07 下午10.08.00.png

Warp 的产品形态,也是在朝着脱离终端模拟器这个简单的工具属性方向发展,更像是朝着IDE的方向发展。但它同样是在帮助个人开发者提升开发效率的基础上,增强团队协作功能。目前因为 Warp 刚公开测试,很多功能还在完善中,但可以预料,如果按这个模式走下去,开发者团队的交流规范也迟早因为 Warp 的普及而得到重要影响。可以预言,熟悉 Warp 工作模式的人,将再也回不去传统终端模拟器上。

简化配置

上手体验的过程也可以知道,Warp 基本上没什么配置,基本上所有的功能都是内建快捷键调用,对新手非常友好。

工作流、块展示

速度

虽然能用tmux + percol + oh-my-zsh + fasd实现类似大概功能,但直接由终端实现,更快

更加智能

Warp 的创始人 Zach Lloyd 说过,走过任何一个开发人员的桌面,都会看到一个打开的终端,还有代码编辑器,VS Code 完成了代码编辑器的重新定义,Warp 就去重新定义终端。

Warp 内置的命令自动补全,还有尚且不是很完善的 AI 搜索都是朝着智能化的方向前进的。GitHub Copilot 已经让我非常惊讶其代码自动补全的能力,我相信 Warp 未来在 AI 自动补全方面也会令人耳目一新。

以终端作为入口。

协作

Warp 的创始人在总结其过去 20 年的程序生涯的时候说过现存的终端存在的两个痛点:

  • 难用
  • 只能一个人用

想来和他自身作为 Google Docs 的开发有着非常大的关系。当前的任何桌面程序如果加上了多人协作都是一个非常大的想象空间。那为什么终端不行?

总之Warp十分值得体验。

命令行的艺术

2022-05-12 00:45

荣耀手环等其它手环手表穿戴移动设备更换第三方表盘

2022-03-11 00:45

Ecrose

Ecrose

尽心尽力,自有万里长风。

Related Posts

  • vps服务器自动备份实践
  • Port Knocking 端口敲门✊
  • DALLE 教程
  • mac-mini 折腾
  • 数据备份方案

Categories

  • 杂技浅尝 8
  • 技术 2
  • 数据库 1
  • 杂七杂八 1

Tags

资源 Database 工具使用 数据备份 安全 日常 隐写术

© 2022 Ecrose.

Powered by Hugo Theme - kagome

🌞 light 🌛 dark 🤖️ auto