终端原理及操作
本文对 shell 中的概念及命令进行总结, 也涵盖一些终端工具的使用, 涉及到 Linux 及 Mac 系统.
常见概念理解
terminal
: 一个程序,Mac
自带terminal
, 也有第三方软件比如xterm
,iterm
,kvt
等,terminal
是shell
的 UI,shell
运行在terminal
中shell
: 命令行解释器. 根据字面意义来看就是机器外面的一层壳, 用于在机器与人交互过程中传递信息. 不限于操作系统, 编程语言, 操作方式和表现形式. 具体表现是用户输入一条命令后 shell 就立刻进行执行并返回结果. CLI(Command Line Interface
) 与 GUI(Graphic User Interface
) 都是shell
, 只不过是不同的表现形式而已.interactive
与non-interactive
: 如果打开 Mac 上的iterm
, 输入bash
代码, 按下回车后有返回任何信息就被称为interactive
; 如果输入了若干行的shell
脚本, 那么这些shell
代码就运行在non-interactive shell
中login
与non-login
:login shell
指登录系统后获得的顶层shell
, 比如最常用的ssh
登录, 登陆完后会获得一个login shell
; 如果是在 Mac 上直接打开iterm
进入了shell
则是non-login shell
shell
类型bash
: 全称:Bourne-Again Shell
, 是最常见的shell
.Mac
中的terminal
默认就是bash
zsh
:Mac
中最常用的shell
, 一大半的原因是因为on-my-zsh
这个配置集.zsh
兼容bash
, 还有自动补全的功能.zsh
的配置文件为~/.zshrc
cmd
:Windows
下的默认shell
, 全称为command interpreter
Jshell
:Java
的第三方解释器 (只要一门编程语言有解释器, 就可以作为一个shell
,PHP
也有PHP Shell
)
Linux 发行版
: GNU/Linux 是基于 GPL 开源许可协议的操作系统内核, 但仅仅有内核还不是一个完整的操作系统, 要想可以使用还需要集成各种应用软件. Linux 发行版就是指预先集成好的 Linux 操作系统及各种应用软件, 一般情况下用户直接安装就可以使用, 不需要再重新编译. 我们平常所说的安装个 Linux 操作系统指的都是安装一个 Linux 的发行版.RHEL
:Red Hat Enterprise Linux
, 是Redhat
公司推出的企业级Linux
发行版, 属于开源操作系统; 但是收费!Fedora
: 是Redhat
公司推出的实验性Linux
发行版, 新特性都会首先出现在Fedora
上, 稳定后放在RHEL
中.CentOS
: 直接将RHEL
的源码拿过来, 去掉相关的版权图标信息, 而后发型, 其版本号与RHEL
基本相同. 法律上是完全没问题的, 因为发布出来的CentOS
同样也遵守了 GPL. 除了一些Redhat
的商业应用软件,CentOS
追求的是与RHEL
100% 兼容.CentOS
作为从 RHEL 源码直接编译的发行版, 其作为服务器的高效率及稳定性等方面都是经过实践验证的, 所以如果自己有丰富的服务器运维经验, 那你可以选择CentOS
. 但如果没有专业的运维团队, 又需要大规模部署, 那还是选择RHEL
比较明智,Redhat
团队会为你提供专业的, 标准化的解决方案和专业的技术支持.Arch Linux
: 巨大的定制潜力,Antergos
提供了一种更加友好的Linux
体验; 不适合容易放弃的人Ubuntu
: 界面漂亮, 非常适合新手,LTS
版本的安全性和稳定性; 不适合服务器端 (需要较多的内存空间), 对非LTS
版本短暂的支持Ubuntu Studio
: 昂贵生产软件的绝佳替代品, 允许访问主Ubuntu
中的包, 支持音频插件; 由于功能强大, 所以操作系统不够精简Debian
: 最适合服务器的操作系统, 稳定得无与伦比, 内存占用小, 常年不需要重启; 由于其发展路线, 帮助文档略少, 技术资料也略少.Elementary OS
: 设计巧妙, 看起来很棒; 预装的应用程序并不多Linux Mint
: 非常适合从Windows
/Mac
切换过来的用户, 良好的媒体支持, 开箱即用, 令人印象深刻的定制选项; 高级玩家可能不会喜欢Tails
: 强调安全和隐私, 易于使用的操作界面; 功能比较基本openSUSE
: 非常精美, 安全, 允许你创建自己的操作系统版本; 默认的软件选择略显臃肿
GNOME
: Linux 系统就是一个纯命令行的操作系统,GNOME
为Linux
提供了桌面操作环境.GNOME
是由GNU Network Object Model Environment
的第一个字母所组成,GNOME
属于GNU
计划中的一部份.
Linux
的图形显示层次是: Linux 本身
-> X 服务器
<- [通过 X 协议交谈] -> 窗口管理器 (综合桌面环境)
-> X 应用程序
.
KDE
: 与GNOME
并列的两种最流行的桌面操作环境, 全称是K Desktop Environment
. 其他的一些比较流行的桌面操作环境有:XFCE
CINNAMON
UNITY
MATE
DEEPIN
PANTHEON
BUDGIE
MANOKWARI
GNU
:GNU
计划开始于 1984 年, 专注于发展类似 UNIX 且完全免费的操作系统.
common environment variables
echo $SHELL
: 查看当前使用的shell
类型 (2019.12.10 目前使用zsh
)echo $TERM
: 查看当前使用的终端类型echo $PATH
: 查看当前系统的路径顺序exprot PATH="/usr/local/sbin:$PATH"
: 将/usr/local/sbin
加入到系统环境中并使之成为第一顺位echo 'export PATH="/usr/local/sbin:$PATH"'>> ~/.zshrc
: 将字符export PATH="/usr/local/sbin:$PATH"
输出到~/.zshrc
文件的末尾echo $PATH
: 输出当前系统的路径读取顺序echo ${(t)fpath}
: 输出fpath
的类型echo ${(t)FPATH}
: 输出FPATH
的类型PS4='+%x:%I>' zsh -i -x -c '' |& grep ***
: 检查别名的定义位置, 用于查找alias
的详细位置
快捷键
C-c
: 终止正在执行的命令C-p/n
: 浏览已执行的历史记录C-f
: 向后移动一个字符C-b
: 向前移动一个字符C-a
: 光标移动到行首C-e
: 光标移到行尾C-z
: 将当前进程最小化C-l
: 清除整个屏幕C-u
: 从光标位置删除到行首 (bash); 删除当前行 (zsh)C-k
: 从光标位置删除到行尾C-y
: 粘贴上一次删除的字符串C-h
: 删除光标前一个字符C-d
: 删除光标后一个字符, 在删除完光标后会删除当前 shell 会话C-i
: 与 tab 作用相同C-_
: undoC-x C-u
: undo, same asc-_
C-t
: 交换光标前的两个字符的位置esc-t
: 交换光标前的两个词的位置alt-t
: 交换光标下的当前单词与前一个单词的位置alt-backspace
: 删除前一个单词alt-.
: 使用上一次的参数alt-u
: 使当前光标至结尾的单词大写C-w
: 移除光标前一个单词C-x-e
: 在编辑器 (vi) 中编辑当前命令行文本C-q
: 将当前命令暂时隐藏, 等待下一个命令执行完毕后再弹出↑/↓
: 浏览已执行的历史记录C-r
: 搜索之前打开过的命令C-s
: 向后搜索历史命令C-xx
: 在行首与当前光标处切换Esc-d
/alt-d
: 删除光标所在字符Esc-f
/alt-f
: 光标右移一个单词Esc-b
/alt-b
: 光标左移一个单词⌘ E
: 向下滚动一行⌘ Y
: 向上滚动一行双击 Tab
: 列出所有的补全列表并直接进入选择模式, 补全项可以使用 ctrl+n/p/f/b 上下左右切换上下键
: 显示历史的命令, 如果在特定前缀命令下只会显示同样的命令, 比如输入ls
情况下只会查找用过的ls
命令
纯内置命令 (不包含 gnu coreutils 实现的)
set -o noglob
/set -f
: 关闭扩展set +o noglob
/set +f
: 打开扩展
pushd <directory>
: 与cd
类似, 会进入某目录, 但是会将此次的进入目录放入堆栈中, 使用popd
可以进入堆栈的上一目录pushd +3
: 从栈顶算起的 3 号目录 (从 0 开始), 移动到栈顶popd
: 进入堆栈的上一目录popd -3
: 删除从栈底算起的 3 号目录 (从 0 开始)
pwd
: 列出当前所在的目录
rmdir [路径]
: 删除一个文件夹 (无法删除含有文件的文件夹)
zsh_stats
: 查看当前使用频率最高的 20 条命令
dirs
: 查看堆栈内容-c
: 清空目录栈.-l
: 用户主目录不显示波浪号前缀, 而打印完整的目录.-p
: 每行一个条目打印目录栈, 默认是打印在一行.-v
: 每行一个条目, 每个条目之前显示位置编号 (从 0 开始).+N
: N 为整数, 表示显示堆顶算起的第 N 个目录, 从零开始.-N
: N 为整数, 表示显示堆底算起的第 N 个目录, 从零开始.
bash$ pwd # 当前处在主目录, 堆栈为空 /home/me # 进入 /home/me/foo $ pushd ~/foo # 当前堆栈为 /home/me/foo /home/me # 进入 /etc $ pushd /etc # 当前堆栈为 /etc /home/me/foo /home/me # 进入 /home/me/foo $ popd # 当前堆栈为 /home/me/foo /home/me # 进入 /home/me $ popd # 当前堆栈为 /home/me # 目录不变, 当前堆栈为空 $ popd
./test.sh
: 执行当前目录下的test.sh
文件, 必须使用./
, 如果直接使用test.sh
的话系统会在PATH
中查找有没有test.sh
, 通常是不在的, 因此会报错, 使用./test.sh
表示就在当前目录找test.sh
, 这样就能顺利找到了/bin/sh test.sh
: 与上面的运行方式类似, 不过指定了解释器
which python
: 输出当前使用的python
路径where python
: 输出当前环境下所有可用的python
路径
type echo
: 查看 echo 是否是 shell 内置命令, 如果不是内置则显示其路径type -a <command>
: 查找某个命令被定义在的位置type -a echo
: 查看 echo 的所有路径位置 (如果是内置命令也会显示)type -t if
: 显示某个命令的类型,if
的类型是keyword
alias python='/usr/local/bin/python3'
: 设置应用的别名 (如果需要取消设置需使用unalias
vim
, 如果想要在.zshrc
中设置需将'
改为"
)alias
: 列出系统所有已设置的别名
history
: 显示会话开始后的所有历史命令history -c
: 清理所有历史命令history 10
: 显示最近 10 个历史命令
compgen -c
: 显示当前终端所有可调用命令
set
/env
: 显示所有环境变量
!!
: run previous command(i.e.sudo !!
)!vi
: run previous command that begins with vi!vi:p
: print previously run command that begins with vi!n
: execute nth command in history!$
: last argument of last command!^
: first argument of last command^abc^xyz
: replace first occurance of abc with xyz in last command and execute it
系统环境路径
在 /etc/paths
中规定了系统路径查找顺序
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
Homebrew
安装的软件都会在 /usr/local/bin
中有一个快捷方式 (具体的文件在 /usr/local/Cellars
中), 因此要将系统环境路径设置为 /usr/local/bin
为第一个检查, 这样在键入 vim
命令时 Homebrew
安装的 vim
就会被先检测到, 内置的 vim
不会被启动
可在终端使用 echo $path
检查当前系统的路径读取顺序.
在 .zshrc
中追加路径可加入 export PATH="/usr/local/sbin:$PATH"
, 这样会将 /usr/local/sbin
路径加入到路径列表并成为第一顺位.
源码编译安装
尽管已经有些包管理软件, 但是仍然不可避免地要编译安装一些源码, 本例以 CentOS 编译安装 Python3.8.3 为例
- 编译环境准备bash
yum groupinstall 'Development Tools' yum install -y ncurses-libs zlib-devel mysql-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel \ db4-devel libpcap-devel xz-devel
删除系统中已有的 python3
在
/usr/bin
与/usr/local/bin
中查找 python3 与pip3
的相关文件, 然后删除. 这一步是为了后面我们将编译出的文件链接到此两个文件夹中- 下载 Python3.8.3 源码到桌面并解压bash
cd /home/hanley/Desktop/https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz tar -xvf Python-3.8.3.tgz cd Python-3.8.3.tgz
配置编译选项
bash./configure --prefix=/usr/local/python3.8.3 --enable-optimizations
解释下这些选项的含义:
--prefix
选项是配置安装的路径, 如果不配置该选项, 安装后可执行文件默认放在/usr/local/bin
, 库文件默认放在/usr/local/lib
, 配置文件默认放在/usr/local/etc
, 其它的资源文件放在/usr/local/share
, 比较凌乱.--enable-optimizations
是优化选项 (LTO
,PGO
等) 加上这个flag
编译后, 性能有10%
左右的优化, 但是这会明显的增加编译时间, 老久了.
./configure
命令执行完毕之后创建一个文件Makefile
, 供下面的make
命令使用, 执行make install
之后就会把程序安装到我们指定的文件夹中去.- 进行编译, 编译结果会放到 [第 4 步](# 第四步) 配置的文件夹中bash
make && make install
进入编译结果文件夹, 将编译出的结果软链接到
/usr/bin
中bashcd /usr/local/Python3.8.3/bin ln -s python3.8 /usr/bin/python ln -s python3.8 /usr/bin/python3 ln -s python3.8 /usr/bin/python3.8 ln -s pip3.8 /usr/bin/pip ln -s pip3.8 /usr/bin/pip3 ln -s pip3.8 /usr/bin/pip3.8
因为终端寻找命令是根据我们定义的
PATH
的顺序来查找的, 我们的编译结果文件夹/usr/local/Python3.8.3
并不在我们的PATH
中, 因此我们要将其中的结果软链接到已经在PATH
的文件夹中同时, 如果不想做软链接, 也可以直接将编译结果文件夹加入到
PATH
中bashvim /etc/profile # 编辑 etc/profile 文件 export PATH=/usr/local/Python3.8.3/bin:$PATH # 在文件末尾直接加入我们的编译结果文件夹 source etc/profile # 更新配置
不过这样的话我们每编译一次软件可能就要编辑一次
PATH
, 而且也会导致PATH
过多, 因此更方便的方法还是使用软链接的方式
标准输入与参数区别
有一些命令不接受标准输入, 这些命令不能用于管道符之后, 比如 where connect.sh | rm
是错误的, 这个时候我们只能使用参数传入该命令: rm "$(where connect.sh)"
而有些命令既接受标准输入, 又接受命令行参数. 比如 cat
如果命令能够让终端阻塞, 说明该命令接收标准输入, 反之就是不接受, 比如你只运行 cat 命令不加任何参数, 终端就会阻塞, 等待你输入字符串并回显相同的字符串.
后台运行程序
可以在命令之后加一个 & 符号, 这样命令行不会阻塞, 可以响应你后续输入的命令, 但是如果你退出服务器的登录, 就不能访问该网页了. 如果你想在退出服务器之后仍然能够访问 web 服务, 应该这样写命令 (cmd &)
$ (python manager.py runserver 0.0.0.0 &)
Listening on 0.0.0.0:8080...
$ logout
单引号与双引号的区别
不同的 shell 行为会有细微区别, 但有一点是确定的, 对于 $
, (
, )
这几个符号, 单引号包围的字符串不会做任何转义, 双引号包围的字符串会转义.
shell 的行为可以测试, 使用 set -x
命令, 会开启 shell 的命令回显, 你可以通过回显观察 shell 到底在执行什么命令:
可见 echo $(cmd)
和 echo "$(cmd)"
, 结果差不多, 但是仍然有区别. 注意观察, 双引号转义完成的结果会自动增加单引号, 而前者不会.
也就是说, 如果 $ 读取出的参数字符串包含空格, 应该用双引号括起来, 否则就会出错.
常见问题解决
mac 设置允许安装任何来源的软件
sudo spctl --master-disable
defaults write com.apple.LaunchServices LSQuarantine -bool false
切换 shell
cat /etc/shells
: 常看当前系统支持的 shell 类型chsh -s /bin/zsh
: 将zsh
设置成默认的shell
source ~/.zshrc
: 重载zsh
的配置文件. ~/.zshrc
: 同source ~/.zshrc
,.
是source
的缩写形式exec $SHELL -l
: 重新启动 SHELL, 与 source 不同的是不会对 PATH 进行重新写入
延伸
本博客文章采用 CC 4.0 协议,转载需注明出处和作者。