命令行省时技巧

作者: Janos Gyerik

我记得第一次我的一个朋友向我介绍了 Linux,并向我展示了如何不必完整地输入命令和路径名——我可以开始输入并使用 Tab 键来完成其余部分。这真是太酷了。我认为每个人都喜欢 Tab 补全,因为这几乎是您在 shell 中花费的每一分钟都会用到的东西。随着时间的推移,我发现了更多快捷方式和省时技巧,其中许多技巧我已经像 Tab 补全一样频繁地使用了。

在本文中,我重点介绍了一组适用于常见情况的技巧,这些技巧对我来说意义重大

  • 在 screen 会话中工作:核心功能将助您一臂之力。

  • 编辑命令行:快速移动和快速编辑。

  • 使用 less 查看文件或 man 手册页。

  • 给自己发送电子邮件,其中包含相关的日志片段或事件触发的警报。

在阅读本文时,最好打开一个终端窗口,以便您可以立即尝试使用这些技巧。所有技巧都应在 Linux、UNIX 和类似系统中无需任何配置即可工作。

在 Screen 会话中工作

Screen 之前曾在 Linux 杂志 中介绍过(请参阅“资源”部分),但简单来说,screen 允许您在单个终端应用程序中拥有多个“窗口”。最好的部分是您可以随时分离和重新连接到正在运行的 screen 会话,因此您可以准确地从上次离开的地方继续之前的工作。这在远程服务器上工作时最有用。

幸运的是,您真的不需要掌握 Screen 就能从中受益匪浅。您只需使用以下几个主要功能,即可享受其最有用的好处

  • screen -R projectx:重新连接到名为“projectx”的 screen 会话,或立即创建一个新的会话。

  • Ctrl-a c:创建一个新窗口。

  • Ctrl-a n:切换到下一个窗口。

  • Ctrl-a p:切换到上一个窗口。

  • Ctrl-a 0:切换到第一个窗口;使用 Ctrl-a 1 切换到第二个窗口,依此类推。

  • Ctrl-a w:查看窗口列表。

  • Ctrl-a d:从此 screen 会话分离。

  • screen -ls:查看 screen 会话列表。

注意:在上面的列表中,“Ctrl-a c”表示同时按下 Ctrl 和 a 键,然后按下 c 键。Ctrl-a 称为命令键,所有 screen 命令都以此键序列开头。

让我通过一个实际的例子来展示所有这些:在我的远程托管服务器上调试一个 Django 网站,这通常涉及以下活动

  • 编辑配置文件。

  • 运行一些命令(执行 Django 操作)。

  • 重启网站。

  • 查看网站日志。

当然,我可以逐一完成所有这些事情,但是为每个操作打开多个窗口会更加实用。我可以使用多个真实的终端窗口,但是每次需要进行此类工作时都重新打开它们将是繁琐且缓慢的。Screen 可以使此过程更快更轻松。

启动 Screen

在启动 screen 之前,最好先导航到您希望进行大部分工作的目录。这是因为 screen 中的新窗口都将在此目录中启动。在我的示例中,我首先导航到我的 Django 项目的目录,以便当我打开新的 screen 窗口时,相关文件将就在我面前。

启动 screen 有不同的方法,但我推荐这种方法


screen -R mysite

当您第一次运行此命令时,它会创建一个名为“mysite”的 screen 会话。稍后,您可以使用相同的命令再次重新连接到此会话。(-R 标志代表重新连接。)

创建窗口

现在我进入了 screen,假设我开始编辑 Django 网站的配置


vim mysite/settings.py

假设我做了一些更改,现在我想重启网站。我可以退出 vim 或将其放到后台,以便运行重启网站的命令,但我预计我需要在此处进行进一步的更改。现在只需使用 screen 命令 Ctrl-a c 创建一个新窗口即可,这样更简单。

每次您开始进行与当前活动不同的操作时,都很容易创建另一个窗口。当您需要在命令之间更改目录时,这尤其有用。例如,如果您的脚本文件位于 /some/long/path/scripts 中,而日志文件位于 /other/long/path/logs 中,那么只需为每个目录保留一个单独的窗口,而不是在目录之间跳转。

在本例中,首先我开始查看配置文件。接下来,我想重启网站。然后我想运行一些 Django 命令,然后我想查看日志。所有这些活动都是我在调试会话期间倾向于多次执行的,因此为每个活动创建一个单独的窗口是有意义的。

创建新窗口的成本非常小,您可以不假思索地执行此操作。不要中断您当前的活动;使用 Ctrl-a c 启动另一个窗口并继续操作。

在窗口之间切换

您在 screen 中创建的窗口从零开始编号。您可以通过窗口编号切换到窗口——例如,使用 Ctrl-a 0 跳转到第一个窗口,使用 Ctrl-a 1 跳转到第二个窗口,依此类推。使用 Ctrl-a n 和 Ctrl-a p 分别切换到下一个和上一个窗口也非常方便。

列出您的窗口

如果您开始忘记您在哪个窗口中,请使用 Ctrl-a w 或 Ctrl-a " 检查窗口列表。前者在 screen 的状态行(底部)中显示窗口列表,当前窗口用 * 标记。后者以更用户友好的格式以菜单形式显示窗口列表。

分离和重新连接到会话

screen 最节省时间的功能是重新连接到现有会话。您可以使用 Ctrl-a d 从当前 screen 会话干净地分离。但您真的不需要这样做。您也可以直接关闭终端窗口。

关于 screen 会话的伟大之处在于,无论您以何种方式断开连接,您都可以在以后重新连接。在一天结束时,您可以关闭本地电脑,而无需关闭远程 screen 会话,并在第二天通过运行您用于启动它的相同命令(如本例中的 screen -R mysite)来恢复它。

您可能为不同的目的运行多个 screen 会话。您可以使用以下命令列出所有会话


screen -ls

如果您突然断开与 screen 的连接,有时它可能会认为您仍处于连接状态,这将阻止您使用常用命令 screen -R label 重新连接。在这种情况下,您可以附加一个 -D 标志来强制从任何现有连接分离——例如


screen -R label -D

了解更多关于 Screen 的信息

如果您想了解更多信息,请参阅 man 手册页和“资源”部分中的链接。快捷键的内置速查表也很方便,您可以使用 Ctrl-a ? 查看它。

我还应该提到 Screen 的一个竞争对手:tmux。我在本文中选择 Screen 是因为根据我的经验,它在我无法控制的系统中更常用。您也可以使用 tmux 完成我上面介绍的所有操作。使用您发现自己所处的远程系统中可用的任何一个。

最后,在远程系统上工作时(例如,通过 SSH 会话),您可以最大程度地利用 Screen。在本地工作时,使用带有标签页的终端应用程序可能更实用。那不完全相同,但可能足够接近。

编辑命令行

许多非常实用的快捷方式可以使您在命令行上以不同的方式更快、更高效

  • 从历史记录中查找并重新运行或编辑长而复杂的命令。

  • 编辑速度比仅使用退格键和重新输入文本快得多。

  • 移动速度比仅使用左右箭头键快得多。

在历史记录中查找命令

如果您想重复最近执行的命令,只需按几次向上箭头键直到找到它可能很容易。但是,如果该命令距离现在不止几个步骤,这将变得笨拙。通常,使用 Ctrl-r 快捷键通过片段查找特定命令会更加实用。

要搜索过去的命令,请按 Ctrl-r 并开始输入您记得的任何片段。在您键入时,最近的匹配行将出现在命令行上。这是一个增量搜索,这意味着您可以继续键入或删除字母,并且匹配的命令将动态更改。

让我们用一个例子来尝试一下。假设我昨天运行了这些命令,这意味着它们仍然在我的最近历史记录中,但距离太远,无法简单地使用向上箭头


...
cd ~/dev/git/github/bashoneliners/
. ~/virtualenv/bashoneliners/bin/activate
./run.sh pip install --upgrade django
git push beta master:beta
git push release master:release
git status
...

假设我想再次激活 virtualenv。再次输入它很麻烦,因为即使使用 Tab 补全,我也必须在每个路径段中至少输入几个字符。相反,按 Ctrl-r 并开始输入“activate”会容易得多。

对于稍微复杂的示例,假设我想再次运行 git push 命令,但我不记得确切是哪个命令。所以我按 Ctrl-r 并开始输入“push”。这将匹配最近的命令,但实际上我想要的是之前的命令,而且我不记得要输入更好的片段。解决方案是在当前搜索过程中再次按 Ctrl-r,因为这会跳转到下一个匹配的命令。

这确实非常有用,不仅节省了输入时间,而且通常也节省了思考时间。想象一下那些长单行命令,您通过 sed、awk、Perl 等管道的长序列处理文本文件;或者带有许多标志、过滤器和排除项的 rsync 命令;或者使用“for”和“while”的复杂循环。您可以使用 Ctrl-r 和您记得的片段快速将它们带回您的命令行。

以下是一些其他需要注意的事项

  • 搜索区分大小写。

  • 您可以使用 Ctrl-c 中止搜索。

  • 要在运行之前编辑该行,请按任意箭头键。

如果您养成一些新习惯,此技巧可能会更有用。例如,当引用您经常使用的路径时,请键入绝对路径而不是相对路径。这样,该命令稍后可以从任何目录重用。

快速移动和快速编辑

命令行上的基本编辑涉及使用箭头键移动和使用退格键或 Delete 键删除字符。当需要移动或删除的字符多于几个时,使用这些基本键就太慢了。通过了解一些有趣的快捷方式,您可以更快地完成相同的操作

  • Ctrl-w:向后剪切文本直到空格。

  • Esc-Backspace:向后剪切一个单词。

  • Esc-Delete:向前剪切一个单词。

  • Ctrl-k:从当前位置剪切到行尾。

  • Ctrl-y:粘贴最近剪切的文本。

像这样逐块删除行的一部分不仅更快,而且额外的好处是,以这种方式删除的文本保存在寄存器中,以便您可以在需要时稍后粘贴它。例如,以下命令序列


git init --bare /path/to/repo.git
git remote add origin /path/to/repo.git

请注意,第二个命令在末尾使用了相同的路径。您可以复制并粘贴第一个命令中的路径,而不是两次键入该路径,使用以下按键顺序

  1. 按向上箭头键以调出上一个命令。

  2. 按 Ctrl-w 以剪切路径部分:“/path/to/repo.git”。

  3. 按 Ctrl-c 以取消当前命令。

  4. 键入 git remote add origin,然后按 Ctrl-y 以粘贴路径。

一些编辑快捷方式与移动快捷方式结合使用时更有用

  • Ctrl-a:跳转到行首。

  • Ctrl-e:跳转到行尾。

  • Esc-b:向后跳转一个单词。

  • Esc-f:向前跳转一个单词。

如果您输错了长命令的第一个单词,则跳转到行首非常有用。您可以比使用左箭头键更快地跳转到行首。

当编辑长命令的中间部分(例如,长路径段的中间部分)时,向前和向后跳转非常实用。

整合所有内容

学习这些小技巧的一个好的起点是停止一些旧的低效习惯

  • 不要使用退格键清除命令行。请改用 Ctrl-c。

  • 不要使用退格键删除长参数。请改用 Ctrl-w。

  • 不要使用左右箭头键移动到行首或行尾。请改用 Ctrl-a 和 Ctrl-e 跳转。

  • 不要使用箭头键移动长术语。请改用 Esc-b 和 Esc-f 跳转术语。

  • 不要按向上箭头键 20 次来查找不太近期的上一个命令。请改用 Ctrl-r 直接跳转到它。

  • 不要在同一行上输入任何内容两次。使用 Ctrl-w 复制一次,然后使用 Ctrl-y 多次重用它。

一旦您掌握了它,您将开始看到越来越多的情况,您可以在这些情况下以有趣的方式组合这些快捷方式,并最大限度地减少您的输入。

了解更多关于命令行编辑的信息

如果您想了解更多信息,请参阅 bash 手册页,并搜索“READLINE”、“移动命令”和“更改文本命令”。

使用 less 查看文件或 man 手册页

less 命令是一个非常方便的工具,用于查看文件,并且它是许多现代系统中查看 man 手册页的默认应用程序。它有许多非常实用的快捷方式,可以使您以不同的方式更快、更高效

  • 向前和向后搜索。

  • 快速移动。

  • 放置标记和跳转到标记。

向前和向后搜索

您可以通过键入 / 后跟要搜索的模式来向前搜索某些文本。要向后搜索,请使用 ? 代替 /。搜索模式可以是基本正则表达式。如果您的终端支持,搜索结果将以反转的前景色和背景色突出显示。

您可以按 n 跳转到下一个结果,按 N 跳转到上一个结果。下一个和上一个的方向是相对于搜索本身的方向而言的。也就是说,当使用 / 向前搜索时,按 n 将使您在文件中向前移动,而当使用 ? 向后搜索时,按 n 将使您在文件中向后移动。

如果您使用 vim 编辑器,您应该会感到宾至如归,因为这些快捷方式的工作方式与 vim 中相同。

默认情况下,搜索区分大小写,除非您在启动 less 时指定 -i 标志。读取文件时,您可以通过键入 -i 在区分大小写和不区分大小写模式之间切换。

快速移动

以下是一些快捷方式,可帮助您快速移动

  • g:跳转到文件开头。

  • G:跳转到文件末尾。

  • 空格键:向前移动一个窗口。

  • b:向后移动一个窗口。

  • d:向下移动半个窗口。

  • u:向上移动半个窗口。

使用标记

当您需要反复在同一文件中的两个或多个不同部分之间跳转时,标记非常有用。

例如,假设您正在查看服务器日志,其中文件开头附近包含初始化信息,而中间某处包含一些错误。您需要在两个部分之间切换,同时尝试弄清楚发生了什么,但是反复使用搜索来查找相关部分非常不方便。

一个好的解决方案是在两个位置放置标记,以便您可以直接跳转到它们。标记的工作方式与 vim 编辑器类似:您可以通过按 m 后跟一个小写字母来标记当前位置,并且您可以通过按 ' 后跟相同的字母来跳转到标记。在本例中,我将用 mi 标记初始化部分,用 me 标记错误部分,这样我就可以使用 'i 和 'e 轻松跳转到它们。我选择字母作为位置所代表内容的缩写,这样我可以轻松记住它们。

了解更多快捷方式

如果您对更多快捷方式感兴趣,请参阅 less 命令的 man 手册页。快捷键的内置速查表也很方便,您可以通过按 h 查看它。

给自己发送电子邮件

在远程服务器上工作时,有时将数据传回您的电脑可能会很不方便——例如,当您的电脑是 NAT 后的,并且服务器无法使用 rsyncscp 直接连接到它时。一个快速的替代方案可能是通过电子邮件发送数据。

给自己发送电子邮件的另一个好场景是使用由您等待的事件触发的警报,例如崩溃的服务器重新上线或其他特定的系统事件。

通过电子邮件发送日志片段

假设您找到了导致远程服务崩溃的错误日志,并且您想快速将其复制到您的电脑。进一步假设相关日志跨越多页,因此从终端窗口复制和粘贴会很不方便。假设您可以使用 headtailgrep 命令的组合来提取相关部分。您可以将日志片段保存在文件中,并在本地电脑上运行 rsync 来复制它,或者您可以简单地通过管道将其传递给此命令,通过邮件发送给自己


mailx -s 'error logs' me@example.com

根据您的系统,mailx 命令可能有所不同,但参数可能相同:-s 指定主题(可选),其余参数是目标电子邮件地址,标准输入用作消息正文。

在长时间任务后触发电子邮件警报

当您运行长时间任务(例如复制大文件)时,等待并不断检查它是否完成可能会很烦人。最好安排在复制完成时触发发送给自己的电子邮件——例如


the_long_task; date | mailx -s 'job done' me@example.com

也就是说,当长时间任务完成后,电子邮件命令将运行。在本例中,消息正文将只是 date 命令的输出。在实际情况下,您可能希望使用更令人感兴趣和相关的内容作为消息——例如复制文件的 ls -lh,甚至像这样组合在一起的多个命令


the_long_task; { df -h; tail some.log; } | \
    mailx -s 'job done' me@example.com

通过任何类型的事件触发电子邮件警报

您是否曾经遇到过以下情况之一?

  • 您正在等待崩溃的 serverX 重新上线。

  • 您正在跟踪服务器日志,等待用户测试您的新功能,这将触发日志中的特定条目。

  • 您正在等待另一个团队部署更新的 .jar 文件。

与其盯着屏幕或反复检查您等待的事件是否已经发生,不如使用这种单行命令


while :; do date; CONDITION && break; sleep 300; \
done; MAILME

这本质上是一个无限循环,中间有一个适当的 CONDITION 来退出循环,从而触发电子邮件命令。在循环内部,我打印日期,只是为了让我看到循环正在运行,并且在每个循环周期中休眠五分钟(300 秒),以避免机器过载。

CONDITION 可以是任何 shell 命令,其退出代码将确定循环是否应该退出。对于上面概述的情况,您可以像这样编写 CONDITION

  • ping -c1 serverX:向 serverX 发送单个 ping。如果它响应,ping 将成功退出,结束循环。

  • grep pattern /path/to/log:在日志中搜索预期模式。如果找到该模式,grep 将成功退出,结束循环。

  • find /path/to/jar -newer /path/to/jar.marker:这假设在启动无限循环之前,您创建了一个标记文件,如下所示:touch -r /path/to/jar /path/to/jar.marker,以便保存与您要监控的 .jar 文件完全相同的时间戳的副本。在 jar 文件更新后,find 命令将成功退出。

简而言之,不要等待长时间运行的任务或某些外部事件。设置一个无限循环,并在出现有趣的事情时通过电子邮件提醒自己。

结论

本文中的所有技巧都是标准功能,应在 Linux、UNIX 和类似系统中工作。我在这里仅仅触及了表面,重点介绍了每个领域的最少功能集,这些功能集应为您带来最大的性价比。一旦您习惯使用它们,这些小技巧将使您成为 shell 中的真正忍者,跳来跳去,闪电般快速完成任务,并且输入最少。

资源

输入 man screen

输入 man bash,并搜索“READLINE”、“移动命令”和“更改文本命令”。

输入 man less

Janos Gyerik 关于命令行省时技巧的演讲: https://speakerdeck.com/janosgyerik/time-saving-tricks-on-the-command-line

Adam Lazur 的“使用 Screen 的强大会话”,LJ,2013 年 1 月: https://linuxjournal.cn/article/6340

Kyle Rankin 的“Screen 中的状态消息”,LJ,2011 年 3 月: https://linuxjournal.cn/article/10950

Shawn Powers 的“使用 Screen 传输您的终端”(视频): https://linuxjournal.cn/video/transfer-your-terminal-screen

加载 Disqus 评论