命令行是你的至交好友

命令行既可以成为你的至交好友,又可能成为你最大的敌人。它关键取决于你怎样用它,以及用它来做什么。如果你还是像大部分人一样畏惧使用命令行界面,那么这篇文章定会让你受益匪浅。

命令行界面?

是的,它是在黑色屏幕上的白色(或者绿色)的显示区域,是神秘的文字流和奇怪的命令执行的地方。我知道很多大师级的程序员从来不使用命令行界面;然而,我也知道一些初级用户用命令行来做所有的事而不是用图形界面。他们控制应用程序去浏览网页和文件系统,查收邮件,查看图片和编辑文字。他们甚至看youtyube视频和查看PDF文件都不使用图形界面!

最好的工作流程是取决于个人的。有些人倾向于图形界面,其他人则钟爱于命令行。

术语

刚刚接触Unix或者Linux的人在面对诸如终端,控制台和shell时是比较困惑的。

命令行是你的至交好友

从用户的角度来看,它们之间似乎是没有太大区别的,但事实上,用户是使用控制台来连接终端来查看运行在计算机上的脚本。

在过去的时候,这三者是独立的硬件。控制台无非是一个显示器和一个键盘;它没有计算能力。它通过一个串行接口去连接终端,应用最广泛的是RS-232接口。

终端就像大型主机的界面。它一般具有计算、网络通信或进行其他特殊连接,如与大型主机连接的能力。终端也提供了对系统的管理者权限,这也是它为什么总是被关在小黑屋的原因。被雇用者使用连接到这些终端的控制台进行工作,但是却无法获得大型主机的管理者权限。控制台与终端最终合并为一个单独的设备,最好的例子的就是现代linux发行版中仿真的虚拟机终端。

命令行是你的至交好友

shell就是一个可以读取用户输入,然后在屏幕输出结果的程序。一个shell可以是基于字符的(像CLI),或者是基于图形的(像Windows的GUI)。今天,shell已经不仅仅是用户与系统的接口,他还肩负着管理进程,窗口,应用程序,命令,以及系统的其他方面。

shell解释执行命令行中输入的命令,用户也可以将命令组合起来写成一个脚本。现代的shell拥有自己的脚本语言,这提供了执行复杂任务的能力。

大多数现代的Linux发行版,如同Mac OSX一样,使用一个shell,BASH(译注:默认的,想用什么自己换)。Solaris和OpenIndiana默认使用Korn Shell,一个BASH的变种。请注意这篇指南主要讲的是BASH。

让我们说说 BASH

BASH 代表 Bourne Again Shell。它被作为 Bourne Shell 的新版本于1989年发布,之后成为了 Unix 系统的默认 shell。它由斯蒂芬·伯恩(Stephen Bourne)编写,用以取代 Thompson Shell。老版的 Bourne Shell 至今仍工作在一些 Unix 系统中。通常你可以用 /bin/sh 找到它。总之,尽管 Bourne Shell 在新的 Linux 发行版中 已经为 BASH 取代,/bin/sh 和 /bin/bash 都能被 BASH 运行。

BASH的提示符

你永远都会碰到BASH的提示符。它是一个贯穿BASH及其历史的东西。如果篇幅允许,我们可以用所有篇幅讲讲如何按自己的希望配置BASH的提示符。但是,我们只会在这个指南中提到一些基本的东西。

我的BASH提示符就像上面那个样子。 第一个词csaba是我的用户名,后接@和我的主机名称,最后是当前的文件夹。~这个字符代表了用户文件夹,对于我来说是/home/csaba。整行以$结尾,在$后面输入的东西是我想shell执行的命令。

当然,这仅仅是一个简单的例子。你可以放更多的东西进提示符中。来看看更多的例子吧。

PS1,PS2,PS3和PS4是BASH的特殊变量,它们控制着不同类型的提示符(例如PS2是一般使用于命令行里较长命令的换行提示信息)。我们在这篇指南中只用到PS1。你可以用下面的命令查看你的PS1变量。

输入命令echo $PS1,然后你就看见了我的PS1变量。在BASH中,我们将$到变量名称前就可以得到这个变量的内容。这个echo命令仅仅会输出它接到的参数。我们给echo的参数是变量的值,所以它会输出这个变量的值。

输出代表着一种格式。

\[\033[01;32m\]

表示绿色,\u表示当前用户的用户名。\h表示主机名,

\[\033[01;34m\]

表示蓝色,\w是当前目录,

\[\033[00m\]

是将文字后续输入的文字置为高亮灰色。通过下面的屏幕截图你能够更好地理解结果。

命令行是你的至交好友

以“\”开头的特殊字符具有特别的意义。反之“\”标识后面的字符是一个转义字符(比如颜色代码)。下面的内容是从BASH官方手册中引用的,你可以在BASH命令中使用的特殊字符的完整列表:

  • \a- ASCII响铃字符(07)
  • \d– 以“Weekday Month Date”格式显示日期
  • \D{format}– format被传递给strftime(3)并把相应的结果插入到提示字符串中; 如果format为空则代表本地时间. 必须有在括号
  • \e– ASCII转义字符(033)
  • \h– 到第一个 `.’前代表主机名称
  • \H– 主机名称
  • \j– 当前被Shell管理工作数
  • \l– Shell终端设置名称的基本名
  • \n– 新行
  • \r– 回车
  • \s– Shell的名称
  • \T– 12小时制当前时间,格式为 HH:MM:SS
  • \t– 24小时制当前时间,格式为 HH:MM:SS
  • \@– 12小时制当前时间,格式为am/pm
  • \A– 24小时制当前时间,格式为 HH:MM
  • \u– 当前用户的名称
  • \v– BASH版本
  • \V– BASH发行备注,版本号+补丁
  • \w– 当前工作目录,其中$HOME被缩写成”~”(使用PROMPT_DIRTRIM的值)
  • \W– 当前工作目录的basename,$HOME被缩写成”~”
  • \!– 命令的使用次数
  • \#– 命令号
  • \$– 命令提示符,如果UID是0则显示为#,否则为$
  • \nnn– 8进制数据nnn代表的字符
  • \\– 反斜杠
  • 0B127790-9488-417A-834A-DD83859A159A

操作目录和文件

在命令行环境中,每个人都要做的一件事就是操作文件系统,创建,删除,复制和移动文件系统对象,并且执行命令。这对你来说可能已经是家常便饭,然而,还是让我们来看一眼:

逐句解释:

  1. 在/home/csaba/tmp下创建一个名为NetTuts的目录
  2. 将刚刚创建的目录切换为当前目录
  3. 在当前目录下创建一个名为“AnotherDir”的目录
  4. 在当前目录下创建一个名为“SecondDir”的目录
  5. 使用touch命令在“SecondDir”目录下创建两个空文件
  6. 切换当前目录到SecondDir.
  7. 使用pushd命令切换目录到~/tmp/NetTuts来把当前目录存储到堆栈之中
  8. 列出目录~/tmp/NetTuts下的所有文件
  9. 使用popd命令来返回前一个目录,这样会从堆栈中获取并且移除最顶层的目录
  10. 再一次列出内容会看到我们上几步所创建的两个文件

当然,对于命令行你们可以有个万能文件管理器,称之为Midnight Commander。要开始用的时候只需要执行它的命令就行。它也内置了文本编辑器(高亮代码的那段)适合大部分语言,而且有智能缩进和其他的一些特性。它不完全是一个被夸大的编辑器,事实上,它是一个相当简单的工具,特别适合简单和快速编辑。你可以随意的选择任何文件然后按F4,或者你可以在编辑模式下直接打开一个文件。

输入/输出

每个命令必须和命令行环境交互。命令需要输入和提供输出。

标准输入是命令读取信息的来源。键盘是默认标准输入,标准输入经常被称为“stdin”。

标准输出是命令的输出会被发送到的地方。默认是当前控制台,标准输出通常被称为“stdout”。

标准错误是命令输出错误的地方。默认当前控制台,常被称为”stderr”。

到目前为止,我们可以定义简单的状态,来表示一个命令从键盘上读取并输出它的结果(包括好的和坏的)到屏幕上.

在Unix(或类unix系统)中, 所有的东西都会被抽象成文件,你的键盘是文件,你的鼠标是文件,你的屏幕是文件,程序是文件, 文本是文件,等等

文件描述符是一个整形数字用于操作系统引用打开的文件, 所有的unix系统至少包含三个文件描述符.

  • 描述符 no. 0 – 标准输入
  • 描述符 no. 1 – 标准输出
  • 描述符 no. 2 – 标准错误输出

重定向

Unix系统有一个非常强大的特性:因为所有资源都是文件,你可以将所有资源引用和将其从一个位置重定向到另一个位置。重定向的操作符<表示标准输入(stdin),>表示标准输出(stdout)。所以,如果你需要一个命令从键盘中读取信息,你可以进行如下操作:

但当要你的命令从一个文件中读取内容你要怎么做呢?你只要重定向这个文件到它的标准输入(stdin),如下:

如果你要你的命令执行结果输出到一个文件,你可以使用>操作符。例如我们已经知道如何将一个目录中的文件列出:

你可以把使用如下命令将结果发送到一个文件:

ThirdFile的内容如下:

比方说,我们要导航到上级目录,列出它所有的文件,并且使用一个命令将这个列表添加至一个已经存在的文件中。操作符>重定向输出到一个文件并且覆盖该文件;所以我们不能使用它。不过,我们可以使用>>(两个>)来添加新数据到一个已经存在的文件。

于是我们的文件内容就是这样了:

输入/输出重定向

我们可以综合我们的知识,以不同的方向重定向标准错误(stderr),标准输入(stdin)和标准输出(stdout)。实际上,以下的命令功能相同:

在第二个命令中,在重定向之前我们指定标准输出的来源。请注意1与>之间没有空格。实际上,如果两者之间有空格,则1会作为ls命令的一个参数,并且>会自动重定向标准输出。以下两个表达功能相同,但和上面的那个功能不同。

当然,这些结果会出错:”ls:不能访问1:没有那个文件或目录” ——除非你真的有一个名字为1的目录。这会让我们惊讶下一步我们得到的:重定向错误。

如你所见,第一个命令在控制台输出标准输出并重定向标准输出到一个文件。第一个命令的结果是一个空文件和屏幕上的一条信息。然而,第二条命令重定向错误到我们的文件。其结果是如果在标准输出上有任何输出,则它们会显示在屏幕上,并且错误信息会输入到这个文件。

一个实际的I/0重导例子

当你需要在命令行寻找一些文件时,你基本上只有两个选择。第一个就是选择用本地命令。这些命令常常是伴随着安装各种Linux版本而已经安装好的,当然不是每一个版本都安装了。更新文件数据库命令索引你的文件和定位,然后使用那个数据库去发现你的文件。实际上他不是做一个实时的搜索,它只是简单的在数据库做索引。这就是为什么这个应用程序常常定期的做每日更新文件数据库。

我们来用这个命令演示一个实时搜索,它比本地命令搜索的更精确,但是很显然更慢一些。现在让我们用这个命令来演示一段:

我打印这两个ls命令是为了让你很方便的看明白目录结构,第三个是find命令。它有着复杂的参数系统,在此我就不一一列举了,但是以上的例子展示了find命令最常见的使用。第一个参数.是一个我们想去搜索的目录。

小贴士:参考当前目录……参考上目录

find命令的第二个参数是-name,紧接着是文件的名字。在-name参数中我们可以用?和*来扩大我们的搜索范围:

?代表一个单个字母,而*指的是任意的字母数量。

接下来,我们将创建一个目录同时使它被我们的用户所不能读。我们还没有讲解到权限,但是不用着急,很快我们将涉及那部分。现在试试下面的例子:

在这个例子中,我希望你对这目录没有权限以便我可以展示一下find输出的内容。它试着进入到所有的目录中然后搜索所有匹配的文件。当它不能进入一个目录,它会输出一条信息。当你看到一两条这样的信息提示是很正常的哈,但是作为一个普通用户去试着搜索root目录下面的文件时。你将会获取数百条错误信息提示而且可能只有一两条搜索结果。你不想错过搜索结果;于是乎你想要除去错误的信息提示。

我们重定向标准错误输出到/dev/null里面。这样做再好不过了。无论你向/dev/null扔进去什么东西,它都可以很简单的使他消失。通常的做法是当你不想看见这些错误提示信息,你可以把信息发到那里。假如你更喜欢把结果存入一个文件中的话,你可以把错误提示信息传送到/dev/null,然后可以用多道重定向:

正如你看见的,这个命令在屏幕上面什么也没有输出,因为错误信息和标准输出被传送到了不同的文件中。但是如果我们想在同一个文件中看到两种信息的输出,怎么办呢?没问题,你可以把标准错误输出传送到标准输出然后把标准输出传送到文件中:

重定向被解释执行是从右到左的。首先开始执行的是 2>&1,这里的意思是重定向标准错误输出到标准输出。然后是1>./SecondDir/ThirdFile,这里的意思是重定向标准输出(此时已经有错误信息在文件里面了)到指定的文件。

再来谈一下用户权限

本文中所谈及的所有权限问题都仅限于 *nix 操作系统。我对最新的 Windows 版本并不熟悉,但微软在其文件系统中使用了一种不同的权限概念。

用户和组

同一台电脑中可以又数个不同的用户。事实上,很多应用注册自己的特殊用户,并在一个受限的环境里运行程序。每个用户以名称和/或 ID(UID) 区分。

你可以在 /etc/passwd 文件中找到现有用户的列表。

组的列表存放在 /etc/group 文件中。一个组拥有一个名字和一个 ID (GID),并拥有另个或数个用户。每个用户通常还拥有一个与之对应的组,名称相同。

拥有者

文件有其拥有者,默认情况,创建那个文件的用户就是它的拥有者。文件夹仅仅是一些特殊的文件,它们跟普通文件遵从一样的规则。

在ls -al命令中,每一个文件的拥有者会像“用户 组”(在这个例子中是“csaba csaba”)输出。我们可以用下面的方法改变AnotherDir这个文件夹的拥有者:

chown命令用途是改变拥有者(CHange OWNer)。它有一个简单的用法:chown 用户:组 文件路径。一个用户只能将“组”这个位置改成一个他所在的组。一个普通用户不能更改他无权读取的文件的拥有者。当然,拥有管理员权限的用户,如“root”,可以把任意文件的拥有者改成任意用户和组。

这里有三种关于文件的权限:

  • r – 读取
  • w – 写入
  • x – 执行

请注意: 如果一个文件夹内的文件可以被列出,这个文件夹本身拥有可执行的权限(x)。

看看前面的例子,每一个文件系统的对象的权限在输出的开头(那些rwx字符)。每个标志位可以是”被设置“(那些有字母的位置),或者是“未设置”(用一个”-“标识,代表没有这个权限)。

这三种权限被包含于三个组, 即每个组都有这三种权限:

  • 用户 – 对拥有者的权限
  • 组 – 对这个文件所在组的成员的权限
  • 其他人 – 对其他想要读取这个文件或文件夹的用户的权限

这个叫做ThirdDir的文件夹没有任何标志位,所以它的拥有者也不能读取它:

但是拥有者拥有改变它的权限的权力:

chmod命令可以更改一个文件系统对象的权限,,它的用法是:chmod +/-权限 文件路径。使用+意味着你将给这个文件一个权限,-意味着去掉一个权限。你可以使用任意权限的组合。上个例子,我们给ThirdDir加上读取,写入,和可执行的权限。

请注意: 用这个方式添加的读写和可执行权限,会作用于拥有者,组,和其他人。但是写入权限只会作用于当前的用户。

第二个例子中,我们选择性的加上读取的权限,去掉了写入的权限,没有改动可执行权限。

但是有时,你需要使用二进制的表示。chmod命令允许你使用10进制表示的二进制数据来更改权限。

  • rwx: 每一个bit都设置成1: 111. 十进制的7.
  • rw-: 由110代表. 十进制 6.
  • r-x: 由101代表. 十进制 5.
  • r–: 100. 十进制 4.
  • -wx: 011. 十进制 3.
  • -w-: 010. 十进制 2.
  • –x: 001. 十进制 1.
  • —: 000. 十进制 0.

chmod命令可以接受一个由0-7数字组成的字符串。每个数字由:用户,组,其他人,的顺序表示了特定的权限。

这个命令设置了读取,写入,可执行给拥有者,读取,写入,不可执行给组,读取,可执行,还有不可写入给其他人。

Cat,Sed,Pipe

下页是一些非常有用的命令。

Cat

这个命令使用你能读出文件的内容。只要简单地提供一个文件名作为参数,之后它会输出这个文件的内容到标准输出(stdout)。

Grep

Grep查找一个模式并输出相匹配的行。你可以通过第三个参数指定要查找的文件:

加入–color选项,可以在结果行高亮匹配的内容。

Pipe 管道

管道使用 | 这个字符表示; 它接受一个命令的输出并将其传给|后的命令. 这听起来好像挺简单的.但确是复杂的, 那一个符号| 实现起来却用了几万行代码,  你可以这样用:

这实际上运行cat命令, 而不是输出结果发送到标准输出, 管道将标准输出作为标准输入传给grep命令.grep命令读取输入的数据, 并搜索字条串”Another”, 结果和我们先前的例子一样

The History of UNIX(unix的历史):  这是一个很有年代的视频,来自AT&T, 这是一个非常不错的视频.如果你只对PIPES感觉趣, 可以快进到4:56 

Sed

sed 命令可以让你在输出中执行一些正则表达式操作。 sed可以用在标准输出或者管道命令中,它会输出结果到标准输出。

这个例子添加了sed命令。有了sed的帮助,我们可以在标准输出中将“AnotherFile” 替换为“MyFile”,是不是很酷?

sed命令有很多选项,使用-e 参数指定要执行的正则表达式。如果你对正则表达式不熟悉的话,查看下面的手册: Introducing “Regular Expressions: Up and Running” or Regular Expressions Cheat Sheets.

定义你自己的命令行

假设你需要经常执行下面的连接ssh的命令:

你可以通过创建一个自定义的命令saysshcon来缩短这个命令。你可以使用alias来自定义命令。Alias语法类似这样的形式:alias shorthand=’original_command’。

但是alias是临时的,当你退出登录之后就会失效。一个可能的解决办法是编辑你的.bashrc文件。

.bashrc和.bash.profile文件

.bashrc文件一般位于你的用户目录。这个文件可以让你指定任何你想在新开一个控制台或者登录一个shell时想要执行的命令。让我们把上面提到的sshcon加到里面。

把你的代码加到文件末尾,按F2保存文件,然后按ESC两次关闭文件。按CTRL+D退出shell,然后打开另一个shell,试试新添加的alias。

一些操作系统, 像Solaris, 可能没有~/.bashrc文件。遇到这种情况,你可以编辑~/.bash_profile来实现这个操作。事实上,任何系统上都有~/.bash_profile。

隐藏文件: 以一个点 (.) 开头的文件表明这个文件是隐藏文件。

 

些许网络命令

让我们来玩些许网络命令。

Ping

ping命令是一种用来检测一个服务器在线并可访问的一种简单方法。

它的语言简单:ping IP_address_or_name。如果服务器可访问,你会看到详细回复列表。如果不可访问,会出现一个描述出错信息的问题。

Traceroute

traceroute命令可以得出从你电脑到目标设备的路由。

路由表

*nix和Windows系统都有路由命令。尽管它们在语法上不同,但是基本的功能都是一样的。这个命令允许我们查看系统当前路由表,并在必要时添加或删除静态路由。

第一列是网络连接或通讯的目的地址。“default”指的是没有找到匹配的项或发送到本地的路由。Loopback是本地虚拟设备,它的IP地址是127.0.0.1。这个IP地址在所有操作系统中都存在并总是指向本地机器(没有其它地址像127.0.0.1一样的功能)

第二列是连接用以到达目的所使用的网关。第一行显示的是我的默认网关192.168.111.1。第二行是环回到达本地;第三行到达*,不需要网关用来访问我们自身的网络。

第三个有趣的是最后一列:”Iface“。它指定用以同特定目的通信的接口。在我们的例子中,环回通信通过环回接口lo。其它的所有连接通过接口eno1。

小贴士:如果你找不到route命令,可以试一下netstat -nr。它会产生相似的输出。

网络配置

如果你想要瞅一眼网络配置,只需在命令行中键入 ifconfig。

这里又很多信息。首先,我们拥有两部分,每个网络适配器一个。系统中,我的有线网卡名为 eno1。你可以看到如 e1000g0,eth0,en0 或是其它的名字。无线网络设备则通常(但并非绝对)以“w“开头。

在名字的同一行中,则是接口的当前状态。这里,接口状态为 UP、broadcast、running等。 第二行则是 IPv4 IP 地址、子网掩码和网关地址。第三行与第二行相似,但对象是 IPv6。第四行以 “ether” 开始,是网卡的 MAC 地址,后面的数行则显示的是数据传输的统计信息。

当前网络连接

另一个非常有用的命令是netstat。它可以列出系统所有的网络连接,以及相应的IP,接口,和系统所监听的端口。以上是我的系统中,netstat命令所输出的一部分。我去除了不相关的信息以使得其简洁些。

每一行表示一个处于特定状态的连接,在这个例子中,你可以看到这些连接处于监听状态(看第一行,端口22,我的ssh服务端),已连接状态,等待状态等等。

最后的交代

于是,你拥有了一些最常用的CLI命令!当然,这些命令的能力远超我在本教程中的介绍。希望我的文章能够为你揭开 CLI 神秘面纱的一角。感谢阅读!

3 收藏 1 评论

相关文章

可能感兴趣的话题



直接登录
最新评论
跳到底部
返回顶部