文章目录
第三章
3. 网络系统
当谈及到网络系统层面,几乎任何东西都能由Linux来实现,Linux被用来创建各式各样的网络系统和配置,包括防火墙,路由器,名称服务器,网络连接式存储设备等等。
常用命令:
命令名 | 作用 |
---|---|
ping | 发送ICMP ECHO_REQUEST数据包到网络主机 |
traceroute | 打印到一台网络主机的路由数据包 |
netstat | 打印网络连接,路由表,接口统计数据,伪装连接和多路广播成员 |
ftp | 因特网文件传输程序 |
wget | 非交互式网络下载器 |
ssh | OpenSSH SSH客户端(远程登录程序) |
1. 检查和检测网络
- ping
最基本的网络命令是ping,这个ping命令发送一个特殊的网络数据包,叫做ICMP ECHO_REQUEST,到一台指定的主机,大多数接受这个包的网络设备将会回复它,来允许网络连接验证。
[me@linuxbox ~]$ ping linuxcommand.org
- traceroute
这个traceroute程序会显示从本地到指定主机要经过的所有”跳数“的网络流量列表。
[me@linuxbox ~]$ traceroute slashdot.org
traceroute to slashdot.org (216.34.181.45), 30 hops max, 40 byte
packets
1 ipcop.localdomain (192.168.1.1) 1.066 ms 1.366 ms 1.720 ms
2 * * *
3 ge-4-13-ur01.rockville.md.bad.comcast.net (68.87.130.9) 14.622
ms 14.885 ms 15.169 ms
从输出结果中,我们可以看到连接测试系统到slashdot.org网站需要经过由16个路由器。对于那些提供标识信息的路由器,我们能看到它们的主机名,IP地址和性能数据,这个数据包括三次从本地到此路由器的往返时间样本。对于那些没有提供标识信息的路由器,我们会看到几个星号。
- netstat
netstat程序被用来检查各种各样的网络设置的统计数据。通过此命令的许多选项,我们可以看到网络设置中的各种特性。使用"-ie"选项,我们能够查看系统中的网络接口:
[me@linuxbox ~]$ netstat -ie
eth0 Link encap:Ethernet HWaddr 00:1d:09:9b:99:67
inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::21d:9ff:fe9b:9967/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:238488 errors:0 dropped:0 overruns:0 frame:0
TX packets:403217 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100 RX bytes:153098921 (146.0 MB) TX
bytes:261035246 (248.9 MB) Memory:fdfc0000-fdfe0000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
...
当执行日常网络诊断时,要查看的重要信息是每个网络接口第四行开头出现的单词"UP",说明这个网络接口已经生效,还要查看第二行中的inet addr字段出现的有效IP地址。对于使用DHCP的系统,在这个字段中的一个有效IP地址证明了DHCP工作正常。
使用这个"-r"选项会显示内核的网络路由表,这展示了系统是如何配置网络之间发送数据包的。
[me@linuxbox ~]$ netstat -r
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.1.0 * 255.255.255.0 U 0 0 0 eth0
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
第一行显示了目的地192.168.1.0 ,IP地址以0结尾是指网络,而不是独立主机,所以这个目的地意味着局域网中的任何一台主机,下一个字段Gateway是网关的名字或IP地址,用它来连接当前的主机和目的地的网络。若这个字段显示一个星号,则表明不需要网关。
最后一行包含目的地 default。指的是发往任何表上没有列出的目的地网络的流量。 在我们的实例中,我们看到网关被定义为地址 192.168.1.1 的路由器,它应该能 知道怎样来处理目的地流量。
netstat还有许多选项…
2. 网络中传输文件
- ftp
文件传输协议,FTP被广泛地用来从因特网上下载文件。并不是所有的,而只是大多数的网络浏览器支持FTP,他们的URL经常以协议ftp://开头。ftp程序可用来与FTP服务器进行通信,FTP服务器就是存储文件的计算机,这些文件能够通过网络下载和上传。
FTP(它的原始形式)并不是安全的,因为它会以明码形式发送账号的姓名和密码。这意味着这些数据没有加密,任何嗅探网络的人都能看到。由于这个原因,几乎因特网中所有FTP服务器都是匿名的。一个匿名服务器能允许任何人使用注册名"anonymous"和无意义的密码登录系统。
[me@linuxbox ~]$ ftp fileserver
Connected to fileserver.localdomain.
220 (vsFTPd 2.0.1)
Name (fileserver:me): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub/cd\_images/Ubuntu-8.04
250 Directory successfully changed.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-rw-r-- 1 500 500 733079552 Apr 25 03:53 ubuntu-8.04- desktop-i386.iso
226 Directory send OK.
ftp> lcd Desktop
Local directory now /home/me/Desktop
ftp> get ubuntu-8.04-desktop-i386.iso
local: ubuntu-8.04-desktop-i386.iso remote: ubuntu-8.04-desktop-
i386.iso
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for ubuntu-8.04-desktop-
i386.iso (733079552 bytes).
226 File send OK.
733079552 bytes received in 68.56 secs (10441.5 kB/s)
ftp> bye
命令
命令 | 含义 |
---|---|
ftp fileserver | 唤醒ftp程序,让它连接到FTP服务器,fileserver |
anonymous | 登录名,输入登录名后,将出现一个密码提示。一些服务器将会接受空密码, 其它一些则会要求一个邮件地址形式的密码。如果是这种情况,试着输入 “user@example.com”。 |
cd pub/cd_images/Ubuntu-8.04 | 跳转到远端系统中的指定目录,注意在大多数匿名的FTP服务器中,支持公开下载的文件都能在目录pub下找到 |
ls | 列出远端系统中的目录 |
lcd Desktop | 跳转到本地系统中的~/Desktop目录下 |
get ubuntu-8.04-desktop-i386.iso | 将指定文件下载到本地指定目录下 |
bye | 退出远端服务器,结束程序会话。也可以使用quit和exit |
在"ftp>"提示符下,输入"help"会显示所支持命令的列表,使用ftp登录到一台授予了用户足够权限的服务器中,则可以执行很多普通的文件管理任务。
3. lftp - 更好的ftp
lftp工作起来和传统的ftp程序很相似,但是它带有额外的便捷特性,包括协议支持(包括HTTP),如下载失败会自动地重新下载等等。
4. wget
wget是另一个下载文件的命令行程序。wget可以从网络或ftp网站上下载数据,不仅仅是单个文件,多个文件甚至是整个网站都能下载。
下载linuxcommand.org 网站的首页:
[me@linuxbox ~]$ wget http://linuxcommand.org/index.php
这个程序的许多选项允许wget递归地下载,在后台下载文件(你退出后仍在下载),能完成未下载全的文件,这些特性在命令手册上有详尽的说明。
5. 与远程主机安全通信
ssh
SSH(Secure Shell)解决了这两个基本的和远端主机安全交流的问题,首先,它要认证远端主机是否为它所知道的那台主机(这样就阻止了所谓的中间人的攻击),其次,它加密了本地与远程主机之间所有的通讯信息。
SSH由两部分组成,SSH服务器运行在远端主机上,在端口22上监听收到的外部连接,而SSH客户端用在本地系统中,用来和远端服务器通信。
大多数 Linux 发行版自带一个提供 SSH 功能的软件包,叫做 OpenSSH,来自于 BSD 项目。一些发行版 默认包含客户端和服务端两个软件包(例如 Red Hat),而另一些(比方说 Ubuntu)则只提供客户端。 为了能让系统接受远端的连接,它必须安装 OpenSSH-server 软件包,配置,运行它, 并且(如果系统正在运行,或者系统在防火墙之后)它必须允许在 TCP 端口 22 上接收网络连接。
[me@linuxbox ~]$ ssh remote-sys
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle
attack)!
...
如果远端主机不能成功地通过验证,则会提示上面信息。
有两种可能的情形会提示这些信息。第一,某个攻击者企图制造“中间人”袭击。这很少见, 因为每个人都知道 ssh 会针对这种状况发出警告。最有可能的罪魁祸首是远端系统已经改变了; 例如,它的操作系统或者是 SSH 服务器重新安装了。然而,为了安全起见,第一个可能性不应该 被轻易否定。当这条消息出现时,总要与远端系统的管理员查对一下。
当确定了这条消息归结为一个良性的原因之后,那么在客户端更正问题就很安全了。 使用文本编辑器(可能是 vim)从文件~/.ssh/known_hosts 中删除废弃的钥匙, 就解决了问题。在上面的例子里,我们看到这样一句话:
Offending key in /home/me/.ssh/known_hosts:1
这意味着 known_hosts 文件的第一行包含那个冲突的钥匙。从文件中删除这一行,则 ssh 程序 就能够从远端系统接受新的身份验证凭据。
除了能够在远端系统中打开一个 shell 会话,ssh 程序也允许我们在远端系统中执行单个命令。 例如,在名为 remote-sys 的远端主机上,执行 free 命令,并把输出结果显示到本地系统 shell 会话中。
[me@linuxbox ~]$ ssh remote-sys free
me@twin4's password:
total used free shared buffers cached
Mem: 775536 507184 268352 0 110068 154596
-/+ buffers/cache: 242520 533016
Swap: 0 1572856 0 110068 154596
[me@linuxbox ~]$ ssh remote-sys 'ls \*' > dirlist.txt
me@twin4's password:
注意,上面的例子中使用了单引号。这样做是因为我们不想路径名展开操作在本地执行,而希望 它在远端系统中被执行。同样地,如果我们想要把输出结果重定向到远端主机的文件中,我们可以 把重定向操作符和文件名都放到单引号里面。
[me@linuxbox ~]$ ssh remote-sys 'ls * > dirlist.txt'
SSH通道
当你通过SSH协议与远端主机建立连接的时候,其中发生的事就是在本地与远端系统之间建立一条加密通道,通常,这条通道被用来把在本地系统中输入的命令安全地传输到远端系统,同样地,在把执行结果安全地发送回来。除了这个基本功能之外,SSH 协议允许大多数 网络流量类型通过这条加密通道来被传送,在本地与远端系统之间创建一种 VPN(虚拟专用网络)。
6. scp和sftp
OpenSSH软件也包含两个程序,他们可以利用SSH加密通道在网络间复制文件,第一个scp(安全复制)被用来复制文件,与熟悉的cp程序非常相似,最显著的区别就是源或者目标路径名要以远端主机的名字后跟一个冒号字符开头。例如,如果我们想要 从 remote-sys 远端系统的家目录下复制文档 document.txt,到我们本地系统的当前工作目录下, 可以这样操作:
[me@linuxbox ~]$ scp remote-sys:document.txt .
me@remote-sys's password:
document.txt
100% 5581 5.5KB/s 00:00
[me@linuxbox ~]$
和ssh命令一样,如果所需的远端主机账户名与本地系统中的不一致,那你可以把用户名添加到远端主机名的开头:
[me@linuxbox ~]$ scp bob@remote-sys:document.txt .
第二个SSH文件复制程序是sftp,与ftp程序很相似,然而,它不是明码形式来传递数据,它使用加密的SSH通道。sftp 有一个 重要特性强于传统的 ftp 命令,就是 sftp 不需要远端系统中运行 FTP 服务端。它仅仅需要 SSH 服务端。 这意味着任何一台能用 SSH 客户端连接的远端机器,也可当作类似于 FTP 的服务器来使用。 这里是一个样本会话:
[me@linuxbox ~]$ sftp remote-sys
Connecting to remote-sys...
me@remote-sys's password:
sftp> ls
ubuntu-8.04-desktop-i386.iso
sftp> lcd Desktop
sftp> get ubuntu-8.04-desktop-i386.iso
Fetching /home/me/ubuntu-8.04-desktop-i386.iso to ubuntu-8.04-
desktop-i386.iso
/home/me/ubuntu-8.04-desktop-i386.iso 100% 699MB 7.4MB/s 01:35
sftp> bye
4. 查找文件
一个典型的Linux系统包含很多文件,在这一章我们将使用在系统中查找文件的工具。
命令 | 含义 |
---|---|
locate | 通过名字来查找文件 |
find | 在一个目录层次结构中搜索文件 |
xargs | 从标准输入生成和执行命令行 |
touch | 更改文件时间 |
stat | 显示文件或文件系统状态 |
1. locate - 查找文件的简单方法
这个locate程序会执行一次快速的路径名数据库搜索,并且输出每个与给定子字符串相匹配的路径名。比如:
[me@linuxbox ~]$ locate bin/zip
#locate命令将会搜索它的路径名数据库,输出任一个包含字符串"bin/zip"的路径名:
/usr/bin/zip
/usr/bin/zipcloak
/usr/bin/zipgrep
/usr/bin/zipinfo
/usr/bin/zipnote
/usr/bin/zipsplit
#也可以结合grep命令
[me@linuxbox ~]$ locate zip | grep bin
/bin/bunzip2
/bin/bzip2
/bin/bzip2recover
/bin/gunzip
/bin/gzip
/usr/bin/funzip
/usr/bin/gpg-zip
/usr/bin/preunzip
/usr/bin/prezip
/usr/bin/prezip-bin
/usr/bin/unzip
/usr/bin/unzipsfx
/usr/bin/zip
/usr/bin/zipcloak
/usr/bin/zipgrep
/usr/bin/zipinfo
/usr/bin/zipnote
/usr/bin/zipsplit
在现在Linux发行版中两个最常见的变体是slocate和mlocate,尽管它们通常被名为locate的符号链接访问,不同版本的locate命令拥有重叠的选项集合。
locate数据库来自何方
在一些发行版中,仅仅在系统安装之后,locate不能工作,但是如果第二天你再试一下,它就能正常工作了。locate数据库由另一个叫做updatedb的程序创建。通常,这个程序作为一个定时任务(jobs)周期性运转,也就是说,一个任务在特定的时间间隔内被cron守护进程执行。为了克服这个问题,通过切换到超级用户身份,在提示符下运行updatadb命令可以手动运行updatedb更新locate数据库。
2. find - 查找文件的复杂方式
locate程序只能依据文件名来查找文件,而find程序能基于各种各样的属性搜索一个给定目录(以及它的子目录)来查找文件。
在它最简单的使用方式中,find命令接受一个或多个目录名来执行搜索。
[me@linuxbox ~]$ find ~
在最活跃的用户账号中,这将产生一张很大的列表,因为这张表被发送到标准输出,我们可以把这个列表管道到其他程序中,让我们使用wc程序来计算出文件的数量:
[me@linuxbox ~]$ find ~ | wc -l
47068
find 命令能够找到符合特定标准的文件,它通过应用选项,测试条件和操作符来做到这一点。
- Tests
比如说我们想在我们的搜索中得到目录列表,我们可以添加以下测试条件:
[me@linuxbox ~]$ find ~ -type d | wc -l
1695
添加测试条件-type d限制了只搜索目录。
find文件类型
文件类型 | 描述 |
---|---|
b | 块特殊设备文件 |
c | 子符特殊设备文件 |
d | 目录 |
f | 普通文件 |
l | 符号链接 |
我们也可以通过加入一些额外的测试条件,根据文件大小和文件名来搜索:让我们查找所有文件名匹配通配符模式"*.JPG"和文件大小大于1M的普通文件:
[me@linuxbox ~]$ find ~ -type f -name "*.JPG" -size +1M | wc -l
840
find单位大小
字符 | 单位 |
---|---|
b | 512个字节块,如果没有指定单位,则这是默认值 |
c | 字节 |
w | 两个字节的字 |
k | 千字节 |
M | 兆字节 |
G | 千兆字节 |
find命令支持大量不同的测试条件,在需要数值参数的情况下,可以应用以上讨论的+和-符号表示法:
find测试条件
测试条件 | 描述 |
---|---|
cmin n | 匹配内容或属性最后修改时间正好在n分钟之前的文件或目录。指定少于n分钟之前,使用-n。指定多余n分钟之前,使用+n |
-cnewer file | 匹配内容或属性修改时间晚于file的文件或目录 |
-ctime n | 匹配内容或属性最后修改时间晚于file的文件或目录 |
-empty | 匹配空文件或目录 |
-group name | 匹配属于一个组的文件或目录,组可以用组名或组ID表示 |
-iname pattern | 就像-name测试条件,但是不区分大小写 |
-inum n | 匹配inode号是n的文件,这对于找到某个特殊inode的所有硬连接很有帮助 |
-mmin n | 匹配内容被修改于n分钟之前的文件或目录 |
-mtime n | 匹配的文件或目录的内容被修改与n*24小时之前 |
-name pattern | 用指定的通配符模式匹配的文件和目录 |
-newer file | 匹配内容晚于指定的文件和目录。这在编写执行备份的shell脚本的时候很有帮助。每次你制作一个备份,更新文件,然后使用find命令来判断哪些文件自从上一次更新之后被更改了。 |
-nouser | 匹配不属于一个有效用户的文件和目录,这可以用来查找属于被删除的账户的文件或监测攻击行为。 |
-nogroup | 匹配不属于一个有效的组的文件和目录 |
-perm mode | 匹配权限已经设置为指定的mode的文件或目录。mode可以用八进制或符号表示法 |
-samefile name | 类似于-inum测试条件,匹配和文件name享有同样inode号的文件 |
-size n | 匹配大小为n的文件 |
-type c | 匹配文件类型是c的文件 |
-user name | 匹配属于某个用户的文件或目录,这个用户可以通过用户名或用户ID来表示 |
- 操作符
即使拥有了find命令提供的所有测试条件,还需要一个更好的方式来描述测试条件之间的逻辑关系。
find命令的逻辑操作符
操作符 | 描述 |
---|---|
-and | 如果操作符两边的测试条件都为真,则匹配,可以简写为-a,注意若没有使用操作符,则默认使用-and |
-or | 若操作符两边的任一个测试条件为真,则匹配,可以简写为-o |
-not | 若操作符后面的测试条件为假,则匹配,可以简写为一个感叹号(!) |
() | 把测试条件和操作符组合起来形成更大的表达式 |
查找权限不是0600的文件和权限不是0700的目录
[me@linuxbox ~]$ find ~ ( -type f -not -perm 0600 ) -or ( -type d -not -perm 0700 )
从最外层看,我们看到测试条件被分为两组,由一个-or操作符分开:
( expression 1 ) -or ( expression 2 )
find命令扫描文件和目录时会计算每一个对象,看看是否匹配指定的测试条件,我们想要知道它是具有错误权限的文件还是有错误权限的目录。它不可能同时符合两个条件。
对于目录表达式为
-type d -and -not -perms 0700
因为-and是默认使用的操作符,所以它能够被删除。
然而圆括号对于shell有特殊含义,我们必须转义它们来阻止shell解释它们。
预定义的操作
find命令允许基于搜索结果来执行操作。
几个预定义的find命令操作
操作 | 描述 |
---|---|
-delete | 删除当前匹配的文件 |
-ls | 对匹配的文件执行等同的ls-dils命令,并将结果发送到标准输出 |
把匹配文件的全路径名输送到标准输出,如果没有指定其他操作,这是默认操作 | |
-quit | 一旦找到一个匹配,退出 |
我们可以使用find命令来删除符合一定条件的文件,例如,删除扩展名为”.BAK“(这通常用来指定备份文件)的文件:
find ~ -type f -name ‘*.BAK’ -delete
测试/行为 | 只有…的时候,才被执行 |
---|---|
只有-type f -name ‘*.BAK’ 为真的时候 | |
-name ‘*.BAK’ | 只有-type f为真的时候 |
-type f | 总是被执行,因为它是与-and关系中的第一个测试/行为 |
因为测试和行为之间的逻辑关系决定了哪一个会被执行,我们可以看出知道测试和行为的顺序很重要。
用户定义的行为
除了预定义的行为之外,我们也可以调用任意的命令,传统方式是通过-exec行为,这个行为像这样工作:
-exec command();
这里的command就是指一个命令的名字,{}是当前路径名的符号表示,分号是必要的分隔符表明命令的结束。
因为花括号和分号对于shell有特殊含义,所以它们必须被引起来或被转义。
我们也可以交互地执行一个用户定义的行为,通过使用-ok行为来代替-exec,在执行每个指定的命令之前,提示用户:
find ~ -type f -name ‘foo*’ -ok ls -l ‘{}’ ‘;’
在这个例子中,我们搜索以字符串”foo“开头的文件名,并且对每个匹配的文件执行ls -l命令,使用-ok行为会在ls命令执行之前提示用户。
提高效率
当-exec行为被使用的时候,若每次找到一个匹配的文件,它会启动一个新的指定命令的实例。我们可能更愿意将所有的搜索结果结合起来,再运行一个命令实例。
传统的方式是使用命令xargs,另一个方法是,使用find命令命令自己的一个新功能。
通过把末尾的分号改成加号,就激活了find命令的一个功能,把搜索结果结合为一个参数列表,然后用于所期望的命令的一次执行:
find ~ -type f -name ‘foo*’ -exec ls -l ‘{}’ +
这个命令,系统只执行一次ls命令
xargs 从标准输入接受输入,并把输入转换为一个特定命令的参数列表。
find ~ -type f -name ‘foo*’ -print | xargs ls -l
注意:当被放置到命令行中的参数个数相当大时,参数个数是有限制的,有可能创建的命令太长以至于shell不接受,当命令超过系统支持的最大长度时,xargs会执行带有最大参数个数的指定命令,然后重复这个过程直到耗尽标准输入,执行带有–show–limits选项的xargs命令,来查看命令行的最大值。
类 Unix 的系统允许在文件名中嵌入空格(甚至换行符)。这就给一些程序,如为其它 程序构建参数列表的 xargs 程序,造成了问题。一个嵌入的空格会被看作是一个分隔符,生成的 命令会把每个空格分离的单词解释为单独的参数。为了解决这个问题,find 命令和 xarg 程序 允许使用一个可选的 null 字符作为参数分隔符。一个 null 字符被定义在 ASCII 码中,由数字 零来表示(相反的,例如,空格字符在 ASCII 码中由数字32表示)。find 命令提供的 -print0 行为, 则会产生由 null 字符分离的输出,并且 xargs 命令有一个 –null 选项,这个选项会接受由 null 字符 分离的输入。这里有一个例子:
find ~ -iname ‘*.jpg’ -print0 xargs –null ls -l
touch playground/timestamp
这个创建了一个空文件,名为 timestamp,并且把它的修改时间设置为当前时间。我们能够验证 它通过使用另一个方便的命令,stat,是一款加大马力的 ls 命令版本。这个 stat 命令会展示系统对 某个文件及其属性所知道的所有信息:
stat playground/timestamp
如果我们再次 touch 这个文件,然后用 stat 命令检测它,我们会发现所有文件的时间已经更新了。
find选项
选项 | 描述 |
---|---|
-depth | 指示 find 程序先处理目录中的文件,再处理目录自身。当指定-delete 行为时,会自动 应用这个选项。 |
-maxdepth levels | 当执行测试条件和行为的时候,设置 find 程序陷入目录树的最大级别数 |
-mindepth levels | 在应用测试条件和行为之前,设置 find 程序陷入目录数的最小级别数 |
-mount | 指示 find 程序不要搜索挂载到其它文件系统上的目录。 |
-noleaf | 指示 find 程序不要基于自己在搜索 Unix 的文件系统的假设,来优化它的搜索。 在搜索DOS/Windows 文件系统和CD/ROMS的时候,我们需要这个选项 |