虽然过去也或多或少有过一些使用命令行的经历,但真正适应使用命令行工作还是在最近。我发现同事们更习惯使用命令行来完成 Git 操作,文件操作,服务器操作,代码编译,单元测试,甚至是调试。从时间上来看,结省了不少启动程序、寻找界面,打开工程等操作的时间;不过,也花费了一些输入和纠正命令的时间。

Windows_PowerShell_1.0_PD

(上图所示为 “Windows PowerShell 1.0 PD”,获取自 Wikipedia,来自 Ghettoblaster)

我想说的命令行,并不是指某一个命令行程序,比如 Windows Command Prompt,PowerShell 或是 Linux Shell,而想指代的是使用命令行开展日常工作、完成开发任务的一种方式。它具体表现为,向一个终端控制台输入一系列指令和对应的参数,来执行一个操作;而不是通过一个可视化窗口,点击数次鼠标。对于命令行,显然,一开始我是拒绝的。回想起来,这种拒绝可能来自多方面:可能由于对一个黑乎乎的窗口的天然恐惧,也有可能是因为感觉命令的威力实在太大,深怕自己一个命令下去会导致不可控的后果,又或许由于不熟悉命令经常输错调用参数格式而倍感挫败,还可能是害怕当出现问题时,进退唯谷了不知如何是好。总之,一直对命令行有一种敬而远之的情结。

我非常愿意分享一下我的“心路历程”,写下这篇文章,以供有同样情况的朋友们借鉴了解。

 

命令行的好处

命令行的缺点就不用多说了,比如不够直观,命令难以记忆等,都是天然的、难能改掉的,如果想用命令行,那只好面对并习惯它们。

说一下我感受到的好处:

  • 众操作系统必备,响应快速,直接上手(很大的好处了,不用安装任何第三方软件即可使用) 直观简洁,清爽干净,统一的交互方式(界面单一,颜色对比明显) 能以最直接的方式,类似函数调用式地使用程序,非常适合开发人员的思维 编写命令脚本,自定义、批量地完成工作 还可以轻松地编写与命令行交互的应用程序,从而完成更多扩展

从开发人员的角度来考虑,一些数据输入输出较简单的程序使用命令行可以大大减少制作用户界面的精力,而制作用户界面本身就是一个具有挑战性的工作。

总之,命令行是与计算机最基本的交互方式,从最早的与计算机交互的方式,一直沿用之今,早已说明了它的用处。对它与 GUI 的关系,我的认识虽然很肤浅,但至少也能感受到,目前 GUI 还不能完全地替代命令行。在接下来很长的时间内,它还将与富交互 GUI 并存,继续是少数人与计算机交互的最佳方式。

 

命令行并不高大上,甚至是低效的

在命令行的使用上,Unix 服务器管理员和基于 OS/X 的开发人员通常有更多的话要说。而针对 Windows 技术人员和开发人员,则相对要少很多。而正因为此,在一些社区广泛存在着 Unix 系的技术人员对日常工作在 Windows 体系中人员的一种或有或无的鄙夷。我觉得这种做法是甚为可笑的,有点像使用 104 键盘的人嘲笑使用 87 键盘的人不能高效地地输入数字一样。

那么,命令行代表高大上吗?会不会用命令行能够代表一个人的技术水平的高低吗?完全不是。实际上,当命令行成为你的日常工作的一部分的时候,代表它很重复化(因为工作中,总是有如此多的重复),就那几个常用的命令。我敢说,一个普通的工程师,在一天的开发工作中,使用频率超过 5 次以上的命令不会超过 10 个。因此我们可以这么想:我们要使用的这些命令,其提供者并没有提供好用的界面,或者与现有主要工作界面没能提供很好的集成,才导致我们逼不得已要使用这些蹩脚的命令的。故而,命令行仍然只能算是一种使用这些命令的一种方式,并没有值得值得骄傲的。

过去很长的时间内,我都知道命令行的存在,并且在部署一些 Linux 环境时无可避免地使用了大量的命令行来完成工作,在管理多台 Windows 服务器的时候,我也会使用 PowerShell 来帮忙。但我一直无法适应在 IDE 里写代码的同时,还需要开一个命令行,来辅助完成一些工作。尽管目前我已经适应了这样的工作方式,我仍然认为这些在日常开发工作中所用到的那些最常用的命令行是低效的。大量人士都认可“Visual Studio 是世界上最好的 IDE”这一说法,Visual Studio 的强大之处便在于,它将大量的相关工具,集成在了一起,看起来像是一个软件一样。因此在 Visual Studio 里工作,绝大多数工作并不需要命令行来完成。

当我向同事展示集成在 Visual Studio 2013 中的 Git 比较和合并工具之后,大家惊异的神情令我记忆尤新。这充分说明了,人们对 GUI 的认可和追求从来没有缺少过。

甚至,在一些场合,命令行是非常低效的。比如交互式调试,文字编辑,多层级数据结构的处理,就更不用提图形图表处理这类几乎不能完成的工作了。

总体来看,我认为命令行在一些场合非常好用,它是一种有效的工具;但它绝不能够作为技术水平高的一个体现。就像王垠在 怎样尊重一个程序员 这篇文章中写道“我们不应该因为自己知道很多表面知识,就自以为比掌握了精髓知识的人还要强。不应该因为别人不知道某些表面知识,就以为自己高人一等。”命令行就是这种“表面知识”,因为做开发人员肯定了解,CLI 只是界面的一种表现形式,而已。

 

使用命令行

上面谈了这么多,无非是想说,命令行有用,但并没有什么可供显摆的。最近我也在考虑,作为一个开发者,我们为什么要使用命令行呢?很简单,因为它有用。事实是,就算不提服务器管理这种批量性比较严重的工作,即便是在日常开发工作中,还是有很好用的工具,并没有提供足够好用的 GUI,或者根本没有提供 GUI,我们需要面对它。比如,git、openssl、npm 以及各种语言的编译器等。

我们经常需要用到这些工具。多用几遍就很容易发现,不管是什么操作系统上,命令行之间是有大量的相似点的。当熟悉了命令行的工作方式之后,就很容易适应各种命令行,即使不记得它们,看一下 usage 再试几次很快就记住了。

命令行程序的规律通常就是:

  • command arguments,即,在命令名和参数列表中包含有一个空格 多个参数之间用空格隔开 如果指定参数名、参数值键值对,则需要用短横线开头表示参数名,在后面一个空格之后再加上它的值,如 openssl* req -new -key nginx.key -out nginx.csr*

实际上,最终一个命令的调用方式,与操作系统提倡的风格有关系,但最终决定到要运行的程序。比如,在 Windows 中官方不少程序都是使用斜线开头表示参数名,而大量开源的程序中,不少程序使用双短横线表示参数名,单短横线表示参数名的缩写形式。

而基本上所有命令行可以适用的经验是:命令名就是程序的名字,参数就是它可以被调用的方式。如果命令或文件名只记得一部分,可以使 Tab 键补全,如果有多个匹配,则继续按 Tab。如果不会用的时候,尝试在它的命令名后面随便输入一些应该不可能支持的参数,绝大多数设计良好的命令行程序就会输入有用的帮助信息,告诉你怎么使用它。几乎所有命令行程序都是这个样子。就像在 Windows 上学会了鼠标键盘操作,在 Linux 和 Mac 下也一样用,是一个道理。甚至窗口的开关、最小化操作、上下文菜单等概念都是通用的。

偶尔会进入一些交互式命令行,也就是使用命令行程序进入了它内部的一个命令行,这时它的命令格式可能与通常的形式有些差异,这可能需要参考具体的文档了。典型的例子有,mysql 命令行,nodejs,Ruby 和 F# 命令行等。

接受命令行,多加练习之后我们很快发现,命令行很有用,而且它并不难用。考虑一下以前我排斥命令行的那些理由,当我们熟悉使用命令行之后,不再觉得它是一个令人恐惧的东西,就算是一时间没能正确地使用,不管是调用格式不正确还是导致了错误,也不至于恐慌怕不好收拾。打消了这些顾虑,这才非常自然地接受它作为日常工作的一种常用技能了。

另外,任何一件事量变都能带来质量,使用命令行也是。当使用久了,我们会以一种交互式的思维来思考问题,这对于解决问题时的逻辑分析能力的锻炼是有一定好处的;命令行的使用还迫使我们接触了平常 GUI 所不能接触,或者不常接触到的一部分,因此也让我们了解了更多技术细节,促使我们更自然地去了解、猜测程序运行的原理和步骤。

 

选用合适的命令行终端软件

本来,没有意识到这会是一个话题。直到,这两年用 PowerShell 越来越多才发现,在不同的命令行终端中生存的幸福感还是大有差异的。简单来讲,在 Windows 中,用 PowerShell 代替系统默认的命令提示符就好了。系统默认提示符(即 cmd.exe)中支持的批处理语法年代太久远了,虽然曾经也是生产率扛扛的,但它的语法怪异,不能与很方便地与 .NET 集成,这些就大大逊色于 PowerShell 了。

PowerShell 有太多值得说的东西,但请参考其他文章,并且这里有个专门介绍 PowerShell 脚本编写的网站

另外,在 Windows 上,还有一些好用的命令行值得推荐:

  • git bash 命令行,除了 git 命令之外,还自带了常用的 linux 中的命令,如 ls、rm 等 Console 2 是一个开源的命令行终端实现,提供了大量的自定义能力,并能设置半透明的窗体,支持多个不同的控制台标签 ConEmu 则是另一个开源的命令行终端,目前开发工作仍很活跃,具有多屏功能等强大特性 Babun 则从另外一个思路提供了扩展性,它内置提供 Cygwin 及一系列 linux 风格的命令,并提供了内置的包管理器,甚至是一些开发人员工具,如 python 等

我们来瞧瞧微软的 Scott Hanselman 同学,他简直是一个命令行终端控。

 

几个十分常用的命令

到这里就该结束了,列几个常用的命令,一来可以做个记录,二来对于想现在多试试命令行却仍没有自信的朋友们一个起点。

命令 用途
ls 列出当前目录中的子目录及文件
cd 转到指定路径
mkdir 创建目录
rm 删除文件
rmdir 删除目录
cp 复制文件或目录
mv 移动文件或目录
pwd 显示当前目录所在
date 显示当前时间
history 显示执行过的命令
ps 显示当前系统中运行的进程列表
help 获取帮助
Tab 键 补全命令或文件名
Ctrl + C 键 终止当前正在执行的任务
shutdown 关机、重启
chmod 修改目录或文件的读写属性(非 Windows 命令)
vi/vim 编辑指定的文件(非 Windows 命令)
find 查找文件(在 PowerShell 中是在文件夹中搜索字符串)

 

再来几个常用的开发命令:

命令 用途
git init/clone 在当前目录初始化空的 Git 仓库;克隆远程的 Git 仓库
git pull 从远程拉取最新代码
dnu restore/build 还原安装 .NET 包;编译 .NET 工程
npm init/install 在当前目录初始化空的 node.js 项目;还原安装缺少的 npm 包
bower install 安装指定的 bower 组件

 

愿命令行能够提高你的工作效率。