diff --git a/README-zh.md b/README-zh.md index 3ac0f3d..eb27bae 100644 --- a/README-zh.md +++ b/README-zh.md @@ -35,7 +35,7 @@ - 这篇文章对刚接触命令行的新手以及具有命令行使用经验的人都有用处。本文致力于做到覆盖面广(尽量包括一切重要的内容),具体(给出最常见的具体的例子)以及简洁(避免一些不必要的东西以及一些偏题的可以在其他地方翻阅到文献的东西)。 每个小技巧在某个特定情境下都是基本的或能够显著地节约时间。 - 本文为 Linux 所写,除了[仅限 MacOS X 系统](#仅限-macos-x-系统)节。其它节中的大部分内容都适用于其它 Unix 系统或 MacOS 系统,甚至 Cygwin。 -- 本文关注于交互式 Bash,尽管很多技巧适用于其他 shell 或 Bash 脚本。 +- 本文关注于交互式 Bash,尽管很多技巧也适用于其他 shell 或 Bash 脚本。 - 本文包括了“标准的”Unix 命令和需要安装特定包的命令,只要它们足够重要。 注意事项: @@ -48,40 +48,42 @@ - 学习 Bash 的基础知识。具体来说,输入 `man bash` 并至少全文浏览一遍; 它很简单并且不长。其他的 shell 可能很好用,但 Bash 功能强大且几乎所有情况下都是可用的 ( *只*学习 zsh,fish 或其他的 shell 的话,在你自己的电脑上会显得很方便,但在很多情况下会限制你,比如当你需要在服务器上工作时)。 -- 学习并掌握至少一个基于文本的编辑器。通常 Vim (`vi`) 会是你最好的选择。 +- 学习并掌握至少一个基于文本的编辑器。通常 Vim (`vi`) 会是你最好的选择,因为在终端里进行随机编辑 Vim 真的毫无敌手,哪怕是 Emacs、某大型 IDE 甚至时下非常流行的编辑器。 - 学会如何使用 `man` 命令去阅读文档。学会使用 `apropos` 去查找文档。了解有些命令并不对应可执行文件,而是Bash内置的,可以使用 `help` 和 `help -d` 命令获取帮助信息。 - 学会使用 `>` 和 `<` 来重定向输出和输入,学会使用 `|` 来重定向管道。明白 `>` 会覆盖了输出文件而 `>>` 是在文件未添加。了解标准输出 stdout 和标准错误 stderr。 -- 学会使用通配符 `*` (或许再算上 `?` 和 `{`...`}`) 和引用以及引用中 `'` 和 `"` 的区别。 +- 学会使用通配符 `*` (或许再算上 `?` 和 `[`...`]`) 和引用以及引用中 `'` 和 `"` 的区别。 - 熟悉 Bash 任务管理工具:`&`,**ctrl-z**,**ctrl-c**,`jobs`,`fg`,`bg`,`kill` 等。 -- 了解 `ssh`,以及基本的无密码认证,`ssh-agent`,`ssh-add` 等。 +- 了解 `ssh`,以及学会通过使用 `ssh-agent`,`ssh-add` 等命令来实现基本的无密码认证。 -- 学会基本的文件管理:`ls` 和 `ls -l` (了解 `ls -l` 中每一列代表的意义),`less`,`head`,`tail` 和 `tail -f` (甚至 `less +F`),`ln` 和 `ln -s` (了解硬链接与软链接的区别),`chown`,`chmod`,`du` (硬盘使用情况概述:`du -hk *`)。 关于文件系统的管理,学习 `df`,`mount`,`fdisk`,`mkfs`,`lsblk`。 +- 学会基本的文件管理:`ls` 和 `ls -l` (了解 `ls -l` 中每一列代表的意义),`less`,`head`,`tail` 和 `tail -f` (甚至 `less +F`),`ln` 和 `ln -s` (了解硬链接与软链接的区别),`chown`,`chmod`,`du` (硬盘使用情况概述:`du -hk *`)。 关于文件系统的管理,学习 `df`,`mount`,`fdisk`,`mkfs`,`lsblk`。知道 inode 是什么(与 `ls -i` 和 `df -i` 等命令相关)。 - 学习基本的网络管理:`ip` 或 `ifconfig`,`dig`。 -- 熟悉正则表达式,以及 `grep`/`egrep` 里不同参数的作用,例如 `-i`,`-o`,`-v`,`-A`,`-B` 和 `-C`。 +- 熟悉正则表达式,以及 `grep`/`egrep` 里不同参数的作用,例如 `-i`,`-o`,`-v`,`-A`,`-B` 和 `-C`,这些参数是值得学习并掌握的。 -- 学会使用 `apt-get`,`yum`,`dnf` 或 `pacman` (取决于你使用的 Linux 发行版)来查找或安装包。确保你的环境中有 `pip` 来安装基于 Python 的命令行工具 (部分程序使用 `pip` 来安装会很简单)。 +- 学会使用 `apt-get`,`yum`,`dnf` 或 `pacman` (取决于你使用的 Linux 发行版)来查找或安装软件包。并确保你的环境中有 `pip` 来安装基于 Python 的命令行工具 (接下来提到的部分程序使用 `pip` 来安装会很方便)。 ## 日常使用 - 在 Bash 中,可以使用 **Tab** 自动补全参数,使用 **ctrl-r** 搜索命令行历史。 -- 在 Bash 中,使用 **ctrl-w** 删除你键入的最后一个单词,使用 **ctrl-u** 删除整行,使用 **alt-b** 和 **alt-f** 按单词移动,使用 **ctrl-k** 从光标处删除到行尾,使用 **ctrl-l** 清屏。键入 `man readline` 查看 Bash 中的默认快捷键,内容很多。例如 **alt-.** 循环地移向前一个参数,以及 **alt-*** 展开通配符。 +- 在 Bash 中,可以使用 **ctrl-w** 删除你键入的最后一个单词,使用 **ctrl-u** 删除整行,使用 **alt-b** 和 **alt-f** 以单词为单位移动光标,使用 **ctrl-a** 将光标移至行首,使用 **ctrl-e** 将光标移至行尾,使用 **ctrl-k** 删除光标至行尾的所有内容,使用 **ctrl-l** 清屏。键入 `man readline` 查看 Bash 中的默认快捷键,内容很多。例如 **alt-.** 循环地移向前一个参数,以及 **alt-*** 展开通配符。 -- 你喜欢的话,可以键入 `set -o vi` 来使用 vi 风格的快捷键。 +- 你喜欢的话,可以键入 `set -o vi` 来使用 vi 风格的快捷键,而 `set -o emacs` 可以把它改回来。 + +- 为了方便地键入长命令,在设置你的编辑器后(例如 `export EDITOR=vim`),键入 **ctrl-x** **ctrl-e** 会打开一个编辑器来编辑当前命令。在 vi 模式下则键入 **escape-v** 实现相同的功能。 - 键入 `history` 查看命令行历史记录。其中有许多缩写,例如 `!$`(最后键入的参数)和 `!!`(最后键入的命令),尽管通常被 **ctrl-r** 和 **alt-.** 取代。 - 回到上一个工作路径:`cd -` -- 如果你输入命令的时候改变了主意,按下 **alt-#** 在行首添加 `#`(将你输入的命令视为注释),并回车。这样做的话,之后你可以很方便的利用命令行历史回到你刚才输入到一半的命令。 +- 如果你输入命令的时候改变了主意,按下 **alt-#** 来在行首添加 `#`,或者依次按下 **ctrl-a**, **#**, **enter**。这样做的话,之后你可以很方便的利用命令行历史回到你刚才输入到一半的命令。 - 使用 `xargs` ( 或 `parallel`)。他们非常给力。注意到你可以控制每行参数个数(`-L`)和最大并行数(`-P`)。如果你不确定它们是否会按你想的那样工作,先使用 `xargs echo` 查看一下。此外,使用 `-I{}` 会很方便。例如: ```bash @@ -91,7 +93,7 @@ - `pstree -p` 有助于展示进程树。 -- 使用 `pgrep` 和 `pkill` 根据名字查找进程或发送信号。 +- 使用 `pgrep` 和 `pkill` 根据名字查找进程或发送信号(`-f` 参数通常有用)。 - 了解你可以发往进程的信号的种类。比如,使用 `kill -STOP [pid]` 停止一个进程。使用 `man 7 signal` 查看详细列表。 @@ -105,7 +107,11 @@ - 使用`alias`来创建常用命令的快捷形式。例如:`alias ll='ls -latr'`使你可以方便地执行`ls -latr`命令。 -- 在 Bash 脚本中,使用 `set -x` 去调试输出,尽可能的使用严格模式,使用 `set -e` 令脚本在发生错误时退出而不是继续运行,使用 `set -o pipefail` 严谨地对待错误(尽管问题可能很微妙)。当牵扯到很多脚本时,使用 `trap`。 +- 在 Bash 脚本中,使用 `set -x` 去调试输出,尽可能的使用严格模式,使用 `set -e` 令脚本在发生错误时退出而不是继续运行,使用 `set -u` 来检查是否使用了未赋值的变量,使用 `set -o pipefail` 严谨地对待错误(尽管问题可能很微妙)。当牵扯到很多脚本时,使用 `trap`。一个好的习惯是在脚本文件开头这样写,这会使它检测一些错误,并在错误发生时中断程序并输出信息: +```bash + set -euo pipefail + trap "echo 'error: Script failed: see failed command above'" ERR +``` - 在 Bash 脚本中,子 shell(使用括号`(...)`)是一种便捷的方式去组织参数。一个常见的例子是临时地移动工作路径,代码如下: ```bash @@ -116,6 +122,8 @@ - 在 Bash 中,注意到其中有许多形式的扩展。检查变量是否存在:`${name:?error message}`。例如,当 Bash 脚本需要一个参数时,可以使用这样的代码 `input_file=${1:?usage: $0 input_file}`。数学表达式:`i=$(( (i + 1) % 5 ))`。序列:`{1..10}`。 截断字符串:`${var%suffix}` 和 `${var#prefix}`。例如,假设 `var=foo.pdf`,那么 `echo ${var%.pdf}.txt` 将输出 `foo.txt`。 +- 使用括号扩展(`{`...`}`)可以减少不必要的重复输入相似文本以及文本组合。 + - 通过使用 `<(some command)` 可以将输出视为文件。例如,对比本地文件 `/etc/hosts` 和一个远程文件: ```sh diff /etc/hosts <(ssh somehost cat /etc/hosts) @@ -144,6 +152,8 @@ - 部分其他的关于 ssh 的选项是安全敏感且应当小心启用的。例如在可信任的网络中:`StrictHostKeyChecking=no`,`ForwardAgent=yes` +- 考虑使用 [`mosh`](https://mosh.mit.edu/) 作为 ssh 的替代品,它使用 UDP 协议。 + - 获取文件的八进制格式权限,使用类似如下的代码: ```sh stat -c '%A %a %n' /etc/timezone @@ -174,7 +184,7 @@ - Excel 或 CSV 文件的处理,[csvkit](https://github.com/onyxfish/csvkit) 提供了 `in2csv`,`csvcut`,`csvjoin`,`csvgrep` 等工具。 -- 关于 Amazon S3,[`s3cmd`](https://github.com/s3tools/s3cmd) 很方便而 [`s4cmd`](https://github.com/bloomreach/s4cmd) 更快。Amazon 官方的 [`aws`](https://github.com/aws/aws-cli) 是其他 AWS 相关工作的基础。 +- 关于 Amazon S3,[`s3cmd`](https://github.com/s3tools/s3cmd) 很方便而 [`s4cmd`](https://github.com/bloomreach/s4cmd) 更快。Amazon 官方的 [`aws`](https://github.com/aws/aws-cli) 以及 [`saws`](https://github.com/donnemartin/saws) 是其他 AWS 相关工作的基础。 - 了解如何使用 `sort` 和 `uniq`,包括 uniq 的 `-u` 参数和 `-d` 参数,详见后文一行代码节。另外可以了解一下 `comm`。 @@ -186,7 +196,7 @@ - 了解语言环境对许多命令行工具的微妙影响,包括排序的顺序和性能。大多数 Linux 的安装过程会将 `LANG` 或其他有关的变量设置为符合本地的设置。意识到当你改变语言环境时,排序的结果可能会改变。明白国际化可能会时 sort 或其他命令运行效率下降*许多倍*。某些情况下(例如集合运算)你可以放心的使用 `export LC_ALL=C` 来忽略掉国际化并使用基于字节的顺序。 -- 了解 `awk` 和 `sed` 关于数据的简单处理的用法。例如,将文本文件中第三列的所有数字求和:`awk '{ x += $3 } END { print x }'`. 这可能比同等作用的 Python 代码块三倍且代码量少三倍。 +- 了解 `awk` 和 `sed` 关于数据的简单处理的用法。例如,将文本文件中第三列的所有数字求和:`awk '{ x += $3 } END { print x }'`. 这可能比同等作用的 Python 代码快三倍且代码量少三倍。 - 替换一个或多个文件中出现的字符串: ```sh @@ -201,7 +211,7 @@ repren --full --preserve-case --from foo --to bar . ``` -- 使用 `shuf` 从一个文件中随机选取行。 +- 使用 `shuf` 从一个文件中随机选取多行。 - 了解 `sort` 的参数。处理数字方面,使用 `-n` 或者 `-h` 来处理可读性数字(例如 `du -h` 的输出)。明白键的工作原理(`-t` 和 `-k`)。例如,注意到你需要 `-k1,1` 来仅按第一个域来排序,而 `-k1` 意味着按整行排序。稳定排序(`sort -s`)在某些情况下很有用。例如,以第二个域为主关键字,第一个域为次关键字进行排序,你可以使用 `sort -k1,1 | sort -s -k2,2`。 @@ -231,6 +241,8 @@ - 使用 `iostat`、`netstat`、`top` (`htop` 更佳)和 `dstat` 去获取硬盘、cpu 和网络的状态。熟练掌握这些工具可以使你快速的对系统的当前状态有一个大概的认识。 +- 使用 `netstat` 和 `ss` 查看网络连接的细节。 + - 若要对系统有一个深度的总体认识,使用 [`glances`](https://github.com/nicolargo/glances)。它在一个终端窗口中向你提供一些系统级的数据。这对于快速的检查各个子系统非常有帮助。 - 若要了解内存状态,运行并理解 `free` 和 `vmstat` 的输出。尤其注意“cached”的值,它指的是 Linux 内核用来作为文件缓存的内存大小,因此它与空闲内存无关。 @@ -259,7 +271,7 @@ - 关于更深层次的系统分析以及性能分析,看看 `stap`([SystemTap](https://sourceware.org/systemtap/wiki)),[`perf`](http://en.wikipedia.org/wiki/Perf_(Linux)),以及[`sysdig`](https://github.com/draios/sysdig)。 -- 查看你当前使用的系统,使用 `uname` 或者 `uname -a` (Unix/kernel 信息) or `lsb_release -a` (Linux 发行版信息)。 +- 查看你当前使用的系统,使用 `uname` , `uname -a` (Unix/kernel 信息) 或者 `lsb_release -a` (Linux 发行版信息)。 - 无论什么东西工作得很欢乐时试试 `dmesg`(可能是硬件或驱动问题)。 @@ -340,7 +352,7 @@ - `factor`:分解因数 -- `gpg`:加密并签名文件 +- [`gpg`](https://gnupg.org/):加密并签名文件 - `toe`:terminfo entries 列表 @@ -348,7 +360,7 @@ - `socat`:套接字代理,与 `netcat` 类似 -- `slurm`:网络可视化 +- [`slurm`](https://github.com/mattthias/slurm):网络可视化 - `dd`:文件或设备间传输数据 @@ -360,6 +372,12 @@ - `time`:执行命令,并计算执行时间 +- `lockfile`:使文件只能通过 `rm -f` 移除 + +- `logrotate`: 切换、压缩以及发送日志文件 + +- `watch`:重复运行同一个命令,展示结果并高亮有更改的部分 + - `tac`:反向输出文件 - `shuf`:文件中随机选取几行 @@ -368,7 +386,7 @@ - `pv`:监视通过管道的数据 -- `hd` 和 `bvi`:保存或编辑二进制文件 +- `hd`,`hexdump`,`xxd`,`biew` 和 `bvi`:保存或编辑二进制文件 - `strings`:从二进制文件中抽取文本 @@ -378,8 +396,12 @@ - `split` 和 `csplit`:分割文件 +- `sponge`:在写入前读取所有输入,在读取文件后再向同一文件写入时比较有用,例如 `grep -v something some-file | sponge some-file` + - `units`:将一种计量单位转换为另一种等效的计量单位(参阅 `/usr/share/units/definitions.units`) +- `apg`:随机生成密码 + - `7z`:高比例的文件压缩 - `ldd`:动态库信息 @@ -452,6 +474,8 @@ - 用 `pbcopy` 复制任何命令的输出到桌面应用,用 `pbpaste` 粘贴输入。 +- 在终端中将 Option 键视为 alt 键,Preferences -> Profiles -> Keyboard 勾选上 "Use Option as Meta key"。 + - 用 `open` 或者 `open -a /Applications/Whatever.app` 使用桌面应用打开文件。 - Spotlight: 用 `mdfind` 搜索文件,用 `mdls` 列出元数据(例如照片的 EXIF 信息)。 @@ -462,7 +486,9 @@ ## 更多资源 - [awesome-shell](https://github.com/alebcay/awesome-shell):一份精心组织的命令行工具及资源的列表。 -- [Strict mode](http://redsymbol.net/articles/unofficial-bash-strict-mode/):为了编写更好的脚本文件。 +- [Strict mode](http://redsymbol.net/articles/unofficial-bash-strict-mode/):为了编写更好的脚本文件。. +- [shellcheck](https://github.com/koalaman/shellcheck):一个 shell 脚本分析工具,基本上等同于 bash/sh/zsh 的 lint。 +- [Filenames and Pathnames in Shell](http://www.dwheeler.com/essays/filenames-in-shell.html):在 shell 脚本里正确处理文件名的好工具。 ## 免责声明