Linux-工具秘籍-二-

96 阅读1小时+

Linux 工具秘籍(二)

原文:zh.annas-archive.org/md5/CA17A1452E9A171FA85666D109FEB63D

译者:飞龙

协议:CC BY-NC-SA 4.0

第五章:权限、访问和安全

在本章中,我们将涵盖:

  • 创建和管理用户账户 - useradd

  • 使用密码

  • 处理文件权限

  • 使用防火墙和路由器设置

  • 使用安全 Linux SELinux

  • 使用 sudo 保护系统

  • /tmp 目录

介绍

这一章将作为对 Linux 文件权限的简要回顾,并介绍密码系统处理机器访问的方式。它还将展示如何使用防火墙和路由器中的安全功能,并提到 SELinux 和 sudo。

创建和管理用户账户 - useradd

在这一节中,我们将向您展示如何使用useradd程序添加用户账户。

准备工作

这些命令不应该对你的系统造成破坏;然而,你需要以 root 用户身份执行。

注意

在大多数 Linux 发行版中,有两个版本的这个命令,useraddadduser。它们并不总是做同样的事情,所以请查阅你的man页面(和/或file命令)以确保你运行的是正确的命令。在 Fedora 中,adduseruseradd的符号链接,因此它们是等效的。

如何做...

在这里,我们将运行useradd命令来添加一个用户,然后使用passwd命令来设置密码。在下一节中将更多讨论passwd

  1. 首先,我们将更改/etc/passwd,所以让我们先备份一份。运行以下命令:cp /etc/passwd /tmp/passwd.orig

  2. 现在让我们创建一个名为test1的用户:

useradd test1

  1. 它应该悄无声息地返回到命令行。现在让我们试一下:
su  -  test1

  1. 你应该看到提示发生了变化。运行whoami,它应该会显示test1。确保每次使用su时都运行这个命令。现在让我们更改密码:
run 
passwd

  1. 它会说类似于Changing password for user test1。但然后它会提示输入当前密码。这是什么意思?它想要什么密码?

  2. 我真的不知道答案,而且man页面也没用。它们总是跳过这一步,这相当奇怪。有一些使用加密功能和其他复杂程序的方法。然而,以下是我的方法:

  3. 按下Ctrl + C退出passwd命令,并运行exit返回到 root 账户。现在编辑/etc/passwd并转到底部一行。1003下面的内容在你的系统上可能会有所不同,但你应该看到类似于这样的一行:

test1:x:1003:1003::/home/test1:/bin/bash

  1. 删除x,这样这一行看起来就像这样:
test1::1003:1003::/home/test1:/bin/bash

  1. 保存文件并退出。如果出现权限错误,请记住你必须以 root 用户身份执行此过程。

  2. 现在运行su再次成为test1用户:

su – test1

  1. 运行passwd

  2. 嘿,很酷,这次没有要求输入当前密码。所以现在可以创建一个密码,因为我们真的不想在系统上留下一个开放的账户。如果你打算保留这个账户,我建议你把这个密码写下来,或者更好地把它放到一个加密文件中的安全位置。

  3. 两次输入相同的新密码后,你应该会收到类似的消息:

passwd: all authentication tokens updated successfully

现在我们有了一个新用户。请注意,一般来说,这个用户可以在命令行上执行大部分他有适当权限的活动。然而,根据 Linux 发行版的不同,用户可能无法访问所有资源(例如声音系统)。

这是我在我的 Fedora 17 系统上使用useradd --help命令得到的截图:

如何做...

还有更多...

useradd命令不仅可以创建新账户,还可以做很多其他事情。你可以更改现有账户的工作方式,或者设置过期时间。你甚至可以给用户系统权限,使他几乎拥有 root 用户一样的权限。请参阅 man 页面或使用--help选项获取更多信息。

使用密码

我在前面的步骤中提到了passwd命令。它用于更新用户的身份验证令牌。你需要以 root 用户身份执行此示例。我们将使用上一节中创建的test1用户。

如何做...

让我们稍微使用一下passwd命令:

  1. 从用户帐户登录到test1,以确保仍然按预期工作:
su - test1

  1. 在提示时输入密码。这应该可以正常工作,没有错误。

  2. 现在让我们锁定此帐户。退出到根目录并运行:

passwd -l test1

  1. 从用户帐户运行su - test1并再次输入密码。它应该失败。

  2. 返回到根目录,并使用命令passwd -u test1解锁帐户。再次登录以确保它有效。

  3. 现在让我们使帐户过期。这将强制用户创建新密码。作为 root 运行以下命令:

passwd -e test1

  1. 现在作为访客用户,使用命令su - test1登录test1。输入密码。

  2. 您将被要求创建新密码。在这里要小心,因为您必须再次输入旧(当前)密码,然后两次输入新密码。是的,似乎很奇怪,我们必须再次输入旧密码,因为我们刚刚这样做了。

  3. 请注意,您可以通过运行passwd -d test1删除用户帐户的密码。这比直接编辑/etc/passwd文件更容易,就像我们在上一节中所做的那样。

还有更多…

您可以在用户帐户上设置很多其他内容。这些包括帐户保持活动的时间以及何时开始警告用户更改其密码。有关更多信息,请参阅 man 页面。

注意

关于密码的一些话

在过去,我们会选择一个相对简单的密码并永远保留它。我们不需要一直更改它,并且可以将其用于一切,因此不需要将其写下来。不幸的是,现在情况已经改变。密码通常需要是大写字母,数字,甚至特殊字符的组合。它们的长度也必须更长。您不能总是将它们用于一切,因为一个系统上的密码规则可能与另一个系统上的规则不同。出于这些原因,我建议在合理的情况下为每个帐户使用不同的密码,并将其记录在安全的地方。您很可能需要定期更改此密码。

处理文件权限

由于 Linux 被设计为多用户操作系统,每个文件都有与之关联的文件权限和所有权。这是为了防止一个用户覆盖另一个用户的文件(无论是有意还是无意)。根用户可以(通常)访问系统中的每个文件。

做好准备

以下是基本文件系统权限的快速回顾。在本例中,假定umask设置为0022。运行umask以确保。

观察我的备份脚本 b 的以下ls -la列表:

-rwxr-xr-x. 1 guest1 root 559 Mar 28 12:43 b

从左边开始,第一个位置表示这是什么类型的文件。如所示的-表示这是一个常规文件。d表示目录,l表示链接。接下来的三组三个字母是文件权限,可以用符号模式或数字模式引用。我们将使用数字(八进制)模式。

前三组rwx是此文件所有者(guest1)的设置。接下来的三个r-x是组(root)的设置。第三组是所有其他人的设置。r表示文件可读,w表示可写,x表示可执行。

chmod命令接受一个到四个八进制数字。如果缺少一个数字,则假定为前导零。第一个数字设置用户 ID,组 ID 或粘性位。第二个数字选择此用户的权限,第三个数字选择其他用户的权限。

现在让我们更改临时文件的一些权限,看看会发生什么。

如何做…

让我们处理一些文件权限:

  1. 让我们使用以下命令切换到/tmp目录:
 cd  /tmp

  1. 如果文件f1存在,请使用以下命令删除它:
rmf1

  1. 使用访客帐户(在我的情况下是jklewis)使用以下命令创建临时文件:
ls>f1

  1. 现在运行以下命令:
ls -al f1

  1. 它应该显示类似以下输出:
-rw-rw-r--. 1 jklewisjklewis 131 Mar 29 10:35 f1

  1. 这些是基于umask命令的默认权限。这表明所有者和组具有读取和写入权限,其他用户只有读取权限。

  2. 那么我们如何更改这些?通过使用chmod命令。假设这是一个脚本,我们想要使其可执行。运行以下命令:

chmod 775  f1

  1. 现在运行ls -la f1;它现在应该看起来像以下输出:
-rwxrwxr-x. 1 jklewisjklewis 131 Mar 29 10:35 f1

  1. 这些x表示每个用户都可以运行该文件。我们再做一个。运行chmod 000 f1,然后运行ls -la f1,它将显示以下输出:
----------. 1 jklewisjklewis 131 Mar 29 10:35 f1

哇!现在没有人能够对这个文件做任何事情了,对吧?嗯,不,文件的所有者仍然可以更改权限。说到所有权,chown命令用于更改该字段。通常以 root 用户身份运行。

还有更多...

我没有提到setuidsetgidsticky位。请参考chmod手册页了解这些设置的信息。受限删除位在* /tmp 目录*部分中提到。

使用防火墙和路由器设置

防火墙用于防止未经授权的网络访问到一台或多台机器,同时仍然允许正常(或合法)的流量通过。iptables命令用于设置、配置和查看内核中 IPv4 规则的表。它有点复杂,因此这只是一个简单的概述。

iptables使用一个或多个表。每个表都有一些预定义的链,并且还可以包含用户创建的链。链是规则的列表,规则指定匹配的数据包应该执行什么操作。这种“匹配”称为目标

当数据包不匹配时,将查看链中的下一个规则。如果匹配,可以为数据包指定以下内容之一:

  • ACCEPT:它允许数据包通过

  • DROP:它拒绝了数据包

  • QUEUE:它将数据包传递到用户空间

  • RETURN:它停止此链的运行,并在调用链中的下一个规则处继续

如何做到...

以下是一些iptable命令。不要在您的系统上运行这些命令;这只是一个示例:

  1. 要删除所有现有规则,请使用以下命令:
iptables -F

  1. 要阻止特定的 IP 地址,请使用以下命令:
iptables  -A INPUT -s 192.168.1.115  -j DROP

  1. 要允许环回访问,请使用以下命令:
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

现在让我们谈谈路由器。大多数路由器都内置了防火墙,可以通过 Web 浏览器进行管理。虽然它不能取代iptables,但通常更容易配置,并且可以在整个网络中工作。

典型家用路由器的网页通常具有192.168.1.1地址。现在在浏览器中尝试一下。

这是我在安全页面上的路由器的屏幕截图:

如何做...

您可能需要输入 ID 和密码。如果您尚未更改它们,请参考路由器文档中的默认值。转到安全(或等效)选项卡以访问这些功能。

还有更多...

iptables还有很多内容,足以填满一本整书。有关更多信息,请参考手册页或防火墙书籍。还有一些关于这个主题的很好的网站。

使用安全 Linux - SELinux

本节将作为安全增强型 LinuxSELinux)的概述。在使用文件权限部分,我们讨论了标准 Linux 如何为系统提供保护。这种方法称为自主访问控制DAC),并且有一些限制。例如,典型用户可以无意或有意地打开他的文件,以便其他用户读取或写入。这可能允许未经授权的访问敏感信息。为了提供更多安全性,SELinux 使用MAC强制访问控制)。MAC 使用覆盖系统中所有进程和文件的安全策略。SELinux 中的所有文件都具有包含安全相关信息的标签。

例如,以下是 DAC 下文件的正常列表:

ls -la ifcfg-eth0
-rw-r--r--. 1 root root 73 Apr 22  2011 ifcfg-eth0

相同的文件,但使用ls的 Z(安全上下文)选项:

ls -Z ifcfg-eth0
-rw-r--r--. root root unconfined_u:object_r:default_t:s0ifcfg-eth0

unconfined_u是用户,object_r是角色,default_t是类型,s0是级别。这些信息用于进行访问控制决策。请注意,首先检查正常的 DAC 规则,如果它们不允许操作,则不使用 SELinux 规则。

准备工作

我们只会以 root 身份运行一些命令并查看一些设置。我们不会对配置进行任何更改。本示例将假定您已经在 Enforcing 模式下运行 SELinux。要确定是否如此,请运行sestatus命令。输出应类似于以下屏幕截图

准备工作

如何做...

好的,让我们运行一些 SELinux 命令。

  1. 运行getenforce;它应该报告 enforcing。

  2. 现在让我们查看映射列表:

semanage login -l

  1. 要查看进程的 SELinux 上下文,请运行以下命令:
ps –eZ

  1. 要查看用户的上下文,请运行以下命令:
id –Z

  1. 当发生错误时,使用sealert命令查看完整的 SELinux 消息。检查您的/var/log/messages文件,看看是否生成了任何警报,如果有,可以运行sealert -l查看详细信息。

  2. 要获取带有描述的 SELinux 布尔值的详细列表,请运行以下命令:

semanage boolean –l

  1. 要查看列表但不包括描述,请运行以下命令:
getsebool –a

  1. 要检查文件和目录是否具有正确的 SELinux 上下文,请运行以下命令:
matchpathcon

还有更多...

正如我提到的,SELinux 通常默认安装在大多数发行版中。在某些情况下,您甚至可能没有意识到它的存在。但是,有时它会妨碍您。例如,如果您尝试安装服务,比如vsftpd,可能会失败,因为它会违反 SELinux 策略。通常会弹出一个相当不错的错误消息。该消息甚至可能告诉您如何解决问题,但是在实践中,我发现它不起作用。您执行它给出的操作,似乎没有错误,但是访问仍然被拒绝。在这些情况下,我使用setenforce命令将 SELinux 置于 Permissive 模式,然后继续我的活动:

setenforce 0

请注意,这只在下次重启之前有效。

有关 SELinux 的更多信息,请参阅 Fedora 网站上的一份相当出色的指南。

使用 sudo 来保护系统

有时,特别是作为系统管理员,您可能希望给用户更多对计算机的访问权限,但实际上不是 root 权限。这可以通过修改/etc/sudoers文件并让用户调用sudo命令来实现。

准备工作...

以下步骤不应损害您的系统。我们将使用上面创建的用户帐户执行这些步骤。您需要成为 root 用户才能执行此部分。

如何做...

在这里,我们将使用/etc/sudoers文件:

  1. 备份你的/etc/sudoers 文件
cp /etc/sudoers /tmp/sudoers.orig

  1. 您不直接编辑此文件,而是使用visudo命令。如果需要,任何文本编辑器都可以使用。如果需要,设置变量然后运行命令:
visudo

  1. 这个命令会创建一个sudoers文件的临时副本并对其进行编辑。如果一切顺利,完成后会将临时文件复制到原始文件上。所以,让我们来看看这个文件。

  2. 阅读别名部分。它们被分成组,用于诸如网络、软件、服务、locate等的事物。现在让我们跳进来看看这是如何工作的。

  3. 但首先让我们尝试一些东西。以 guest 用户身份打开另一个会话。我将使用我的jklewis帐户。

  4. jklewis帐户下键入以下命令:

cd /tmp

  1. 使用以下命令创建一个文件:
ls>f1

  1. 现在尝试将该文件复制到/usr/bin
cp f1 /usr/bin

  1. 您应该收到一个错误。这当然是正确的,普通用户通常不能写入/usr/bin目录。现在返回到您的visudo会话。

  2. 您将需要您机器的主机名。在本示例中,我们将使用数字 IP。如果需要,您可以从ifconfig命令中获取它。

  3. 就在提到关闭命令的行之后,我们将为我们的访客用户添加一行。语法是用户名、主机名、命令和选项,因此添加以下行:

jklewis  192.168.1.115=(ALL)  ALL

  1. 保存文件并关闭visudo会话。现在再次尝试此命令。仍然在/tmp目录中运行cpf1 /usr/bin。它应该仍然显示错误消息。现在尝试以下命令:
sudo cp f1 /usr/bin

  1. 啊,它要求输入密码,对吧?是的,它要求用户的密码,而不是 root 的密码。这可能很容易混淆(至少对我来说是这样)。记住的最好方法是,你可能不应该知道 root 密码是什么。输入你的密码。

  2. 如果这是该用户第一次使用sudo,可能会弹出一个有趣的通知。阅读并理解它,以避免系统管理员的愤怒。

  3. 在所有这些之后,这次命令应该可以无错误地进行。很酷,对吧?由于我们在sudoers文件中添加的行中使用了ALL,它实际上已经给予了这个用户完全访问权限。请注意,有些事情仍然不会工作得一样,例如重定向。

  4. 好吧,我们可能真的不希望这个jklewis混蛋搞乱我们的系统,所以让我们稍微微调一下。再次运行visudo

  5. 向下滚动或搜索进程。通过删除#标记取消注释# Cmnd_Alias PROCESSES行。

  6. 再次向下滚动到我们之前添加的jklewis行。将其更改为:

jklewis  192.168.1.115=(ALL) PROCESSES

  1. 现在我们需要一个要终止的进程。以 root 身份启动一个vi会话。类似vi mybook的东西会起作用。

  2. 在您的用户会话中运行psauxw | grep”vi mybook”并记住进程号(PID)。

  3. 还在您的用户会话中运行kill -9上面的 PID。它会出错。现在再次运行,但使用以下命令:

sudo kill -9 <pid>

  1. 应该终止vi进程。

提示

如果屏幕保持蓝色或其他颜色,只需运行ls 命令。那应该解决问题。

以下是我的/etc/sudoers文件的屏幕截图:

如何做...

还有更多...

您可以从sudoers文件中看到,可以对其进行很多微调。用户可以被赋予非常少的额外权限,或者非常多的权限。有关更多信息,请运行man sudoers

这是我对sudo的两分钱。有许多计算机用户可以信任以 root 身份运行而不会损害系统。但也有例外。如果您设置了sudo,您可能会花很多时间尝试使其完美,只能发现您总是不得不添加更多内容。您的用户会因为无法进行更改而感到沮丧。然后,当您认为最终已经完美无缺时,有人使用sudo,仍然会搞砸并严重搞砸。根据我的经验,如果用户犯了这个错误一次,他会一次又一次地犯。

/tmp目录

/tmp目录在某种程度上是特殊的,因为默认情况下允许所有用户向其中写入文件。这是我系统上/tmp的列表:

drwxrwxrwt.  10 root    root      4096 Mar 31 03:48 tmp

您可以看到这是对所有人开放的。权限中的t表示目录上设置了受限删除位。那么这实际上意味着什么呢?对于目录,它防止普通用户删除或重命名他们没有适当权限的目录中的文件。

作为普通用户,当写入/tmp时仍然需要小心,因为有一些限制。

如何做...

让我们尝试一些事情,以了解/tmp的工作原理:

  1. 运行以下命令:
cd /tmp

  1. 如果有任何早期部分留下的临时.txt文件,请清理它们;rm *.txt文件应该可以做到。

  2. 现在运行以下命令:

ls>root1.txt

  1. 在另一个会话中,作为一个访客用户(我将使用jklewis),运行以下命令:
cd /tmp

  1. 运行以下命令:
ls>jklewis.txt

  1. 这应该可以无错误地工作。现在尝试:
 ls>root1.txt

  1. 您应该收到权限被拒绝的错误。为什么?因为即使普通用户都可以写入/tmp目录,但仍必须遵循正常文件系统(DAC)权限。

还有更多...

基于上述原因,我建议除了真正临时的文件之外,不要在/tmp目录中使用任何东西。此外,大多数发行版会定期清理/tmp,因此任何不属于 root 用户的文件都将被删除。在生成临时文件时请记住所有这些,特别是在编写脚本时(更多内容请参见第八章,“脚本处理”)。

第六章:进程

在本章中,我们将涵盖以下主题:

  • 理解进程

  • 使用 ps 检查进程

  • 使用 top 检查进程

  • 使用 nice 更改优先级

  • 使用/proc 文件系统观察进程

介绍

在 Linux 中运行的所有程序都是进程。在本章中,您将学习如何使用 ps 和 top 查看它们的状态,如何设置它们运行的优先级,以及如何使用/proc 文件系统查看进程的内部。

理解进程

每个进程都有一个称为进程标识符PID)的唯一标识符。此外,每个进程都有一个父进程标识符PPID)。有一个例外,即init(或systemd)。init进程启动所有其他进程,并具有 PID 为 1。该进程很特殊,因为它无法被终止(任何尝试这样做通常都是致命的)。

与文件类似,进程也具有访问权限。这些被称为真实用户和组 ID。这通过不允许非特权用户访问关键操作系统任务来提供一定程度的保护。内存、打开的文件和其他资源由进程拥有,并与其他进程(在大多数情况下)分开。

从用户的角度来看,进程通常是从命令行或桌面启动的。例如,使用vi编辑文件。用户启动会话并与编辑器进行交互。他可以保存文件或编辑其他文件。只要会话处于活动状态,就会有一个 PID 与之关联。当用户终止vi时,PID 和所有相关资源也将终止。该 PID 将被回收并稍后由操作系统再次使用。以这种方式运行的程序称为前台进程。

进程也可以在后台运行。例如,在第四章中,网络和互联网,我们使用firefox &命令运行浏览器。&符号将进程放入后台,释放该终端以进行更多的输入/输出。请注意,应用程序(例如此示例中的 Firefox)发出的消息仍将输出到该终端。在调试时,这真的很有帮助。还要注意,后台运行的进程往往以比前台任务更低的优先级运行(稍后会详细介绍优先级)。在旧时代,后台进程通常也被称为作业。

每个进程都有一些特殊的文件句柄:

  • 标准输入stdin):进程从此处获取其正常输入(句柄 0)

  • 标准输出stdout):进程将其正常输出写入此处(句柄 1)

  • 标准错误stderr):进程将其错误输出写入此处(句柄 2)

以下是显示标准句柄的屏幕截图:

理解进程

由进程打开的其他文件从句柄 3 开始。有一些进程被赋予特殊名称。例如,Linux 系统上的许多进程在后台运行,并且在大多数情况下,从不打算从命令行运行。这些被称为服务或守护进程。超文本传输协议守护进程HTTPD)Web 进程是服务的一个很好的例子。

通常,服务会等待事件发生,执行一个或多个操作,然后再次等待。如果服务记录任何活动,通常会记录到/var/log/<service-name>目录。

注意

如果启动后台作业的终端被终止,后台作业也将结束。一些 Linux 发行版将尝试警告用户此条件。

如何做…

以下是可以用来查看进程的命令的简要列表:

  • 要查看当前在系统上运行的进程的快照:
ps auxw

  • 要实时查看进程,请运行:
top

  • 要查看所有类型的进程目录:
ls /proc

还有更多...

一个进程可以衍生出其他进程。它也可以衍生出线程。线程继承父进程的所有句柄和资源。通常在编程中用于同时执行一个小任务,而主任务正在运行,并且快速返回。

资源有限制吗?是的。ulimit命令用于查看和设置进程的硬限制和软限制。通常用户不需要它;但是,如果您好奇,可以在您的系统上运行ulimit -a。您应该看到类似以下截图的输出:

更多内容...

有关ulimit的更多信息,请参阅 man 页面。

使用 ps 检查进程

ps程序允许用户查看系统上运行的进程的快照。通过使用适当的参数,输出可以更改以包含更多或更少的信息。在本节中,我们将以 root 身份运行,并使用 BSD 风格的ps。选项可以分组,不使用破折号。

如何做...

执行以下步骤来运行ps

  1. 只运行ps而不带任何参数会得到以下类似的输出:
 Big4 /temp/linuxbook/chap6 # ps
 PID TTY          TIME CMD
 5197 pts/25   00:00:00 su
 5218 pts/25   00:00:00 bash
 17789 pts/25   00:00:00 ps

  1. 由于这并不是非常具有信息性,让我们显示每个具有 TTY 的进程:
ps a

  1. 现在,包括那些没有 TTY 的进程:
ps ax

  1. 以更加用户友好的格式显示输出:ps aux。注意标题的变化。

  2. 如果在您的系统上行被截断了,可以使用以下命令添加宽选项:

ps auxw

  1. 输出确实很多。以下是一些处理它的想法:
ps auxw | more

  1. 您也可以将输出重定向到文件:ps auxw > ps-output.txt,然后使用morevi查看它。

  2. 您也可以使用grep来查找特定的进程 ID。在另一个终端中,运行以下命令:

vi file1.txt

  1. 现在回到您的原始终端,运行以下命令:
ps auxw | grep file1.txt

  1. 您应该看到一行包含文本vi file1.txt。这就是您要找的 PID,也是ps的最常见用途之一。

  2. 您还可以显示进程的树状视图:

pstree

工作原理...

ps命令从/proc文件系统获取信息。每个运行的进程都有一个相关的条目。我们将在本章后面更详细地讨论/proc

还有更多...

BSD 风格的标题将类似于以下内容:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

每个术语的定义如下:

  • USER:它是进程的所有者

  • PID:它是进程标识符

  • %CPU:它给出了 CPU 时间除以进程运行时间的比例

  • %MEM:它给出了进程内存与物理内存的比例

  • VSZ:它包含了进程的虚拟内存大小

  • RSS:它包含了实际内存驻留集大小

  • TTY:它表示与该进程关联的终端

  • STAT:它表示进程的状态

  • START:它给出了进程启动的时间

  • TIME:它给出了总 CPU 时间

  • COMMAND:它是命令的名称

ps命令还有很多其他选项。您可以查看线程,获取安全(SELinux)信息,通过用户名紧缩显示内容,并更改输出格式。您甚至可以修改一些环境变量以改变ps的工作方式。请参阅 man 页面以获取更多信息。

以下截图展示了在我的 Fedora 17 系统上ps - auxw的样子:

更多内容...

使用 top 检查进程

top程序类似于ps,只是它实时显示系统的状态。您可以使用命令行开关和/或其交互式界面来控制其操作。它还可以使用配置文件。您可以通过top做很多事情。以下是一些可能的示例。

准备就绪

不需要特殊设置。这些命令将以 root 身份运行。

要获取top的帮助,可以运行以下命令行:

 top -h or -v

这些是等效的,并显示库版本和用法。

top的一般语法如下:

 top -bcHisS -d delay -n iterations -p pid [,pid...]

以下是在 Fedora 17 上运行top的截图:

准备就绪

如何做...

以下是使用命令行开关的一些示例:

  1. 每 2 秒更新一次屏幕:
top -d 2

  1. 每半秒更新一次屏幕:
top -d 0.5

  1. 要更新 10 次然后退出:
top -n 10

  1. 要同时执行两者:
top -d 0.5 -n 10

  1. 要立即更新屏幕,请按空格键或Enter

  2. 要监视特定的 PID,请使用-p选项。这将显示init(或systemd)进程:

top -p 1

  1. 让我们监视一些进程。首先运行ps auxw,并记住四个进程的 PID。

  2. 然后运行top,用之前获得的 PID 替换:

top -p pid1,pid2,pid3,pid4

  1. 要省略显示空闲进程,请运行以下命令:
top -i

  1. 要显示线程,请运行top -H。要仅监视特定用户的进程,语法是top -u <username>。尝试使用 root:
top -u root

  1. 你可以以批处理模式运行top。例如,要将输出保存到文件中:
top -b -n 10 > top1.txt

以下是使用交互命令的一些示例。启动top并跟随操作:

  1. 要仅显示特定用户(此示例中为 root)拥有的进程,请按U,然后输入root

  2. 要更改延迟时间,请按D,然后按1输入时间。

  3. 要显示多核机器上的所有 CPU,请按1(再次按1切换回来)。

  4. 要切换显示命令行与程序名称,请按C

  5. 要更改进程的 nice 设置,请按R,然后输入所需的优先级。

  6. 要激活安全模式,请按S(之后查看安全模式的解释)。

  7. 要向进程发送信号,请按K,然后输入要发送的信号。在执行此操作之前,请确保您有正确的 PID 和信号。

  8. 要写入配置文件,请按W。这将在用户的主目录中创建文件.toprc,并在下次启动top时使用其中的设置。

  9. 要显示帮助屏幕,请按H

  10. 要退出 top,请按Q

它是如何工作的...

以下是前一张截图中显示的前五行的描述:

  • top:它包含了当天的时间、机器的运行时间、用户数量和平均负载

  • Tasks:它给出了总任务数、当前运行、睡眠、停止和僵尸的数量

  • Cpu(s):不同类型的 CPU 状态如下:

  • us:它代表用户时间

  • sy:它代表系统时间

  • ni:它代表了 nice 时间

  • id:它代表空闲时间

  • wa:它代表了 I/O 等待时间

  • hi:它给出了用于服务硬件中断的时间

  • si:它给出了用于服务软件中断的时间

  • st:它代表被窃取的 CPU 时间

  • Mem:它给出了机器上的总内存;已使用的、空闲的和缓冲区的大小(以 KB 为单位)

  • Swap:它给出了总交换空间;已使用的、空闲的和缓存的大小(以 KB 为单位)

以下是标准标题的定义。请注意,这些可能会根据命令行选项或交互命令而更改:

  • PID:它定义了进程标识符

  • USER:它保存了此任务的所有者的用户名

  • PR:它保存了这个任务的优先级

  • NI:它包括 nice 值(下一节将更多介绍优先级)

  • VIRT:它展示了此任务使用的虚拟内存总量

  • RES:它给出了此任务使用的物理内存

  • SHR:它给出了此任务使用的共享内存

  • S:它代表进程状态,可能是以下之一:

  • S:它代表睡眠状态

  • D:它表示不可中断的睡眠状态

  • R:它表示进程正在运行(或准备运行)

  • T:它表示进程已被跟踪或停止

  • Z:它表示僵尸状态

  • %CPU:它给出了自上次更新以来经过的 CPU 时间的份额,以百分比表示

  • %MEM:它保存了当前使用的可用物理内存的份额,以百分比表示

  • TIME+:它给出了此任务自开始运行以来使用的总 CPU 时间

  • COMMAND:这是用来启动此任务的命令

还有更多...

除了用户配置文件外,还可以有一个全局文件。它的名字是/etc/toprc,包括以下两行:

S # Line 1: secure mode switch
2.0 # Line 2: delay in seconds

此文件是由 root 用户手动创建的。如果此文件存在,则会激活安全模式并更改top的操作方式:

  • 显示了帮助屏幕的不同版本

  • 用户无法终止任务

  • 用户无法重新设置任务

  • 用户无法更改top的延迟间隔

如果top似乎不按预期工作,请检查用户和 root 的配置文件是否存在。您可以使用top做很多其他事情。您可以更改字段的排列和排序方式。您可以更改颜色和突出显示。还有一个多窗口选项。有关更多信息,请参阅top的 man 页面。

以下是我在我的 Fedora 17 系统上的top的屏幕截图:

还有更多...

使用 nice 更改优先级

nice命令允许您调整进程运行的优先级。现代操作系统通常会很好地进行任务调度。但是,某个特定进程可能偶尔需要进行一些调整。在这里,我们将展示如何使用nice

优先级称为 niceness 级别。进程可以具有的 niceness 范围从 19(最不利)到最大值-20(最有利)(如果这对您来说似乎是反向的,对我来说也是)。

最有利 ________________________ 最不利

20 __________________________________19

最高优先级 ________________________ 最低优先级

您可能还记得上一节关于top的 NI 列。这是 niceness 设置,在 Fedora 上,有几个服务以最有利的-20 设置运行。

请注意,更改进程的 niceness 设置并不保证操作系统会遵守它。这只是对调度程序的建议。

还要注意,给 nice 的命令不能是内置命令。

nice的语法如下:

 nice [Option]... [Command [Arg] ...]

如何做...

现在,让我们运行一些nice命令:

  1. 要查看当前的 niceness 值,请单独运行 nice:
nice 

  1. 现在在自身上运行 nice:
nice nice

  1. 看到输出为 10 吗?如果没有给出默认调整,那就是默认值。

  2. 现在将其设置为最大值:

nice -n -20 nice

  1. 对于最小值:
nice -n 19 nice

  1. 现在让我们尝试其他事情。在另一个终端中,运行以下命令:
nice -n 15 vi testfile.txt

  1. 然后找到它的 PID:
ps auxw | grep testfile.txt

  1. 现在在先前的 PID 上运行top
top -p <pid>

  1. niceness 列(NI)应显示 15 的 niceness。

以下是显示在 Fedora 17 上运行nice的屏幕截图:

如何做...

还有更多...

与大多数其他 Linux 程序不同,nice没有更多内容。如果您尝试将其设置为高于 20 的最大值,它仍将使用 20,如果您尝试将其设置为低于-19 的最小值,它将使用-19。此外,top程序允许您动态调整进程的 niceness 级别。

使用/proc 文件系统观察进程

/proc文件系统是 Linux 存储与当前运行的进程相关数据的地方。在大多数情况下,普通用户可能永远不需要(希望永远不需要)了解这些信息。但是,在调试期间或者只是想了解一些 Linux 内部情况时,这些信息可能会非常有帮助。

如何做...

以下步骤解释了如何查看/proc中包含的信息:

  1. 让我们尝试在/proc中作为 root 运行一个实验:
file uptime

  1. 它显示uptime: empty,对吧?因此,如果我们 cat 它,理想情况下应该没有输出,对吧?试试看:
cat uptime

  1. 哇,那是怎么发生的?/proc中的文件很特殊,因为信息是实时从中读取的。让我们尝试一些更多的内容,并运行以下命令:
cat interrupts

  1. 现在运行cat versioncat meminfo

  2. 在另一个会话中,运行以下命令:

vi test5.txt

  1. 让我们找到它的 PID:
ps auxw | grep “vi test5.txt”

  1. 更改到/proc中的目录:cd /proc/<pid-from-above>

  2. 现在将目录更改为文件描述符FD)目录:

cd fd

  1. 运行ls -la命令。您应该看到类似以下输出:
Big2 /proc/20879/fd # ls –la.
 total 0
 dr-x------. 2 root root  0 Apr 11 16:27 .
 dr-xr-xr-x. 8 root root  0 Apr 11 16:27 ..
 lrwx------. 1 root root 64 Apr 11 16:27 0 -> /dev/pts/10
 lrwx------. 1 root root 64 Apr 11 16:27 1 -> /dev/pts/10
 lrwx------. 1 root root 64 Apr 11 16:27 2 -> /dev/pts/10
 lrwx------. 1 root root 64 Apr 11 16:27 4 -> /tmp/.test5.txt.swp

您可以看到这确实是我们的vi编辑test5.txt文件的会话。请注意,显示的文件是由vi创建并在执行期间保持打开的临时文件。

还有更多...

以下截图显示了 Fedora 17 系统中/proc目录的列表:

还有更多...

那么这一切意味着什么呢?这些数字是,正如你可能已经猜到的,进程 ID。每个进程都会在这里有一个数字,实际上是包含了关于该进程的几乎所有你想知道的东西的目录。

以下是其中一些文件的用途。我没有列出每一个,但涵盖了我认为最有趣的那些:

  • buddyinfo: 它包含有关节点和内存的数据

  • cgroups: 它包含了有关 CPU 组的数据

  • cmdline: 它是启动进程时给出的命令行

  • consoles: 它提供了有关控制台的信息

  • cpuinfo: 它包含了你的系统中 CPU 的非常详细的列表

  • crypto: 它包含了系统中可用的加密例程的信息

  • devices: 它包含了设备的列表

  • diskstats: 它包含了磁盘统计信息的列表

  • dma: 它包含了 DMA 的列表

  • filesystems: 它提供了可用文件系统的列表

  • interrupts: 它包含了系统正在使用的中断的非常详细的列表

  • iomem: 它提供了 I/O 内存信息

  • ioports: 它提供了 I/O 端口的信息

  • kallsyms: 它包含了操作系统符号的列表

  • kcore: 它代表了这台机器的内存映像

  • meminfo: 它包含了系统内存使用情况的非常详细的列表

  • modules: 它包含了系统使用的模块的列表

  • mounts: 它包含了系统中已挂载的文件系统(真实和虚拟)的列表

  • partitions: 它包含了分区的列表

  • slabinfo: 它包含了一个 slab 内存对象的列表

  • softirqs: 这是另一个 IRQ 列表

  • uptime: 它提供了机器已经运行的时间(参见uptime命令)

  • version: 这是内核版本(参见uname命令)

  • vmstat: 它提供了虚拟内存统计信息

  • zoneinfo: 这是另一个相当详细的内存列表

除了少数例外,你可以使用 cat 命令查看大多数这些文件中的重要内部数据。注意,不要 cat(或对)kcore文件做任何操作。不要尝试编辑这些文件。另外,如果你 cat 一个文件,但似乎什么也没发生,按下CtrlC键应该让你退出。

使用 C 语言编写的程序可以利用/proc中的信息做一些非常酷的事情。例如,我开发了一段代码,可以让程序确定它是正常运行到屏幕上,还是被重定向到文件中。程序可以根据情况采取适当的行动,例如,如果正常运行,则清除屏幕,如果被重定向到文件,则不清除。这样,控制代码就不会嵌入到文件中。我还有另一段 C 代码,可以确定程序当前打开的任何文件的完整路径和文件名。

以下是top的另一个截图:

还有更多...

这是通过运行top然后按下Z键创建的。你可以对top进行相当多的自定义。查看 man 页面以获取更多信息。

第七章:磁盘和分区

在本章中,我们将涵盖以下主题:

  • 使用fdisk

  • 使用mkfs格式化驱动器

  • 使用fsck检查文件系统

  • 逻辑卷管理(LVM)

介绍

在安装机器时,您可以采用默认设置或根据需要设置磁盘。以下是对分区和文件系统的简要回顾。典型的 Linux 系统通常至少有三个单独的分区。它们被标记为//bootswap/(发音为root)是目录结构的父目录。/boot是系统内核和映射文件所在的地方。当内存的部分需要移动到硬盘上时,将使用swap分区。这被称为因过度承诺而将内存部分交换出到磁盘上。

以下通常位于单独的分区上:

  • /:它是父目录

  • /boot:引导和映射文件位于此处

  • (交换):它表示交换空间

以下传统上位于单独的分区上,但不一定要这样:

  • /home

  • /tmp

  • /etc

  • /var

以下是 Linux 系统上通常存在的文件系统和目录及其一般用途的部分列表。这是来自 Fedora 17 64 位的信息:

  • /:它是父目录。

  • /boot:引导、映射文件和系统内核都在其中。

  • (交换):它代表交换空间。

  • /root:这是超级用户的主目录。

  • /home:用户目录放在这里(例如,/home/guest1,在本书中一直在使用)。

  • /tmp:这是一个具有文件删除位设置的目录。用户和各种其他程序可以将临时文件放在这里。由 root 运行的cron作业会定期清理/tmp(通常一周一次)。

  • /usr:它包括操作系统(OS)的父用户目录。

  • /usr/bin:它包含操作系统的可执行程序。

  • /usr/etc:它包含操作系统的配置文件。

  • /usr/games:它包括发行版提供的游戏。

  • /usr/include:它包括用于编程语言如 C 的文件。

  • /usr/lib:它包含操作系统的库文件。

  • /usr/lib64:它包括 64 位版本的操作系统库文件。

  • /usr/local:系统管理员可以将用户程序放在这里供其使用。

  • /usr/sbin:它包含系统使用的操作系统可执行程序。

  • /usr/share:它包括操作系统的共享程序和文件。

  • /usr/src:操作系统的内核源代码、包含和制作文件都放在这里

  • /dev:它代表设备目录。例如,/dev/sda设备指向第一个 SCSI 硬盘。

  • /lib:它是指向/usr/lib的符号链接。

  • /lib64:它是指向/usr/lib64的符号链接。

  • /mnt:它用作挂载点。

  • /opt:它代表可选文件。

  • /var/logs:它包括操作系统的日志。

  • /var/spool:它包含打印机文件。

  • /var/run:操作系统在此处保存运行中的程序的数据。

  • /run:它是指向/var/run的符号链接。

  • lost+found:这是操作系统用来跟踪文件系统数据的地方。

  • /etc:它的发音是etcetera,代表其他所有东西。配置文件通常位于此处。

不同类型的虚拟文件系统如下:

  • /proc:操作系统在此处跟踪进程。有关更多信息,请参阅上一章。

  • /sys:操作系统在此目录中跟踪其他进程。

以下是以下列表中定义的一些其他有用术语:

  • 设备:它指的是整个磁盘。例如,第一个 SCSI 磁盘通常被命名为/dev/sda

  • 分区:它是设备名称后跟一个数字。第一个 SCSI 分区将是/dev/sda1

  • 文件系统:它定义了正在使用的文件系统类型。一些示例是ext2ext3ext4vfatxfs

  • 挂载点:它是指向分区的目录。/etc/fstab文件包含一个表,显示挂载点和它们关联的分区。这个文件是由系统安装程序(如 Anaconda)创建的,可以由超级用户手动编辑以添加或删除设备和挂载。

引导分区是操作系统内核和其他启动文件所在的位置。以下是在/boot中找到的文件的描述:

  • vmlinuz:它代表内核的符号链接。例如,在 Fedora 14 上,它指向vmlinuz-2.6.35.6-45.fc14.x86_64

  • initramfs:它代表初始 RAM 磁盘。在 Fedora 14 上,它被命名为initramfs-2.6.35.6-45.fc14.x86_64.img

  • config:此文件用于配置内核。我们将在第十章内核中看到更多内容。在 Fedora 14 上,它被命名为config-2.6.35.6-45.fc14.x86_64

  • map:这是系统映射文件,其中包含对各种内核例程的入口点。在 Fedora 14 上,它被命名为System.map-2.6.35.6-45.fc14.x86_64

初始 RAM 磁盘需要更多解释。该文件包含加载和运行内核所需的所有设备驱动程序。例如,内核需要访问硬盘才能启动。如果它需要特殊驱动程序(即,如果仅靠 BIOS 无法访问),则必须位于initramfs文件中,否则将无法完成该过程。initramfs文件是在系统安装期间创建的,并且可以由经验丰富的人修改。这通常在测试和/或使用新硬件时完成。这是一个压缩的GZIP文件,在启动时会被解压并放置在 RAM(内存)磁盘上。

以下是我 Fedora 17 系统上/boot和文件命令的快照:

介绍

df程序用于报告文件系统磁盘空间使用统计信息。以下输出是我 Fedora 14 系统上的df -h列表。-h参数将输出放入更易读的形式(在大型磁盘上很有用):

Big4 ~ # df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              97G   48G   45G  52% /
tmpfs                 5.9G  780K  5.9G   1% /dev/shm
/dev/sda1             485M   51M  409M  12% /boot
/dev/sda2             385G  124G  242G  34% /data
/dev/sda5              49G  8.3G   38G  19% /lewis
/dev/sdf1             932G  243G  690G  27% /megadrive
/dev/sdg1             7.3G  3.1G  4.3G  42% /usb

第一列显示文件系统的分区。第二列显示分区的大小。第三列是已使用的量,后面是仍可用的量。Use%是使用的百分比,最后一列是挂载点。

此输出告诉您有关我如何设置此系统的许多信息。我没有为/home/tmp/etc/var创建单独的分区。它们都在/下的同一分区中。我有所需的/boot分区,我将其大小设置得比默认值大,因为我经常构建新内核。还有一个单独的/data/lewis分区。所有提到的分区都在/dev/sda设备上。那么/dev/sdf1/dev/sdg1是什么设备和分区?第一个是 Iomega 外部 USB 驱动器,第二个是 8GB 的通用串行总线USB)存储设备。这些用于备份,以防主要驱动器出现故障。

fsck程序用于检查和可选修复损坏的文件系统。它可以并行检查多个文件系统以加快处理速度。如果未给出参数,则fsck默认为检查/etc/fstab文件中的文件系统。

在使用分区时,必须记住目录挂载在哪里。例如,假设/上的空间变得紧张,因此您决定删除位于/tmp目录中的一些大文件。您首先需要确保/tmp确实挂载在/上,而不是在自己的分区上。很容易犯这个错误,所以要记住。如果您是许多设置不同的机器的系统管理员,这将更加成问题。

使用 fdisk

fdisk程序用于操作磁盘分区表。您可以使用此实用程序创建、修改和删除分区。

做好准备

只要不使用写入磁盘的操作,您可以按照这些命令进行操作。但是,为了安全起见,您可能希望使用 USB 存储设备或其他您不在乎的驱动器或系统。

交互式版本的fdisk的语法是fdisk <device-name>。我将使用一个 4GB 的 USB 存储设备,/dev/sdb作为这个例子。请记住,fdisk适用于整个设备,因此在启动命令时不使用分区号。我们将以 root 用户身份执行这些操作。

以下是 Fedora 18 上fdisk的屏幕截图:

准备就绪

如何做...

执行以下步骤来运行fdisk

  1. 通过在设备上运行fdisk来启动命令:
fdisk /dev/sdb

  1. 显示帮助菜单:输入 an m。它会显示可以在此设备上执行的操作列表。

  2. 显示分区表:输入 a p。将显示此设备上的分区列表。

  3. 在我的 USB 存储设备的情况下,只有一个分区。所以让我们删除它:

enter a d

  1. 由于只有一个分区,默认情况下已删除。现在让我们添加一个:
enter an n
  1. 由于这是第一个分区,按a p键选择主分区。

  2. 现在运行输入 a 1并采用默认的起始扇区。

  3. 现在我们必须输入一个大小。这可以通过扇区号或大小来完成。让我们使用大小,将其设置为 1GB:

enter +1G

  1. 再次运行输入 a p以查看我们有什么。您应该看到类似以下输出:
 Command (m for help): p
 Disk /dev/sdb: 4009 MB, 4009754624 bytes, 7831552 sectors
 Units = sectors of 1 * 512 = 512 bytes
 Sector size (logical/physical): 512 bytes / 512 bytes
 I/O size (minimum/optimal): 512 bytes / 512 bytes
 Disk identifier: 0xc3072e18
 Device Boot      Start         End      Blocks   Id  System
 /dev/sdb1            2048     2099199     1048576   83  Linux
 Command (m for help):

  1. 看起来不错。现在让我们添加另一个,然后采用默认设置:
enter n, then p, then 2, and the default first sector

  1. 这次让我们使用 2GB 的大小:
enter +2G

  1. 查看它的样子:
enter a p

  1. 现在表格应该显示两个分区。在这一点上,您可以继续创建更多分区,或者保存表格。如果您有所需的磁盘空间,随时可以稍后创建更多分区。

  2. 在这个例子中,我们将不保存更改而退出:

enter a q

  1. 为了确保没有出错,运行fdisk /dev/sdb -l来获取列表。它应该显示与我们开始时相同的内容。

还有更多...

您可能已经注意到fdisk帮助屏幕上提供了其他一些操作。您可以更改显示单位的方式,列出已知的分区类型,以及其他一些内容。有关更多信息,请参阅fdisk man页面。

使用 mkfs 格式化驱动器

mkfs命令在设备上构建文件系统(类似于格式化驱动器)。它确定文件系统类型并调用适当的mkfs.<type>程序。例如,如果您要运行mkfs -t ext4 /dev/sdb5,它实际上会运行mkfs.ext4程序。mkfs选项如下:

  • -t:指定所需的文件系统类型

  • -V:生成详细输出

  • -V:如果作为唯一参数使用,它会显示版本信息

  • -h:显示帮助屏幕

请注意,没有传递其他参数给文件系统的特定程序。还要注意,在某些情况下,需要提供大小值。

准备就绪

mkfs程序将销毁当前驻留在分区中的任何数据。因此,在继续此命令之前,请确保已备份所需的数据。一旦执行了此操作,就无法撤消。如果您想按照这些步骤操作,您应该先在一个您不在乎的 USB 存储设备或其他设备上练习。

在继续之前,请确保卸载分区。

如何做...

执行以下步骤来在 Linux 中格式化分区:

  1. 在这个例子中,我插入了一个 USB 存储设备(我不在乎的一个)。为了确保我们有正确的设备,请运行dmesg并查看最后一行:
dmesg | tail -20

  1. 在我的系统上,它显示设备是/dev/sdh1(根据您的设备进行替换)。它没有挂载,所以我准备好继续。但是,如果您的设备是自动挂载的,您应该能够通过运行以下命令卸载它:
umount /dev/sdh1

  1. 请注意,以下命令将销毁设备上的任何数据。因此,在继续之前,请确保已备份要保留的任何数据!

  2. 运行命令mkfs -V -t vfat /dev/sdh1。我的系统上显示以下输出:

Big2 /temp # mkfs -V -t vfat /dev/sdh1
mkfs (util-linux 2.21.2)
mkfs.vfat /dev/sdh1
mkfs.vfat 3.0.12 (29 Oct 2011)

  1. 现在挂载设备:mount /dev/sdh1 /usb2(根据需要替换您的设备和挂载点)。

  2. 运行ls -la /usb2。它应该看起来像以下输出:

Big2 /temp # ls -la /usb2
total 8
drwxr-xr-x.  2 root root 4096 Dec 31  1969 .
dr-xr-xr-x. 25 root root 4096 Jun  7 10:04 ..

这基本上就是mkfs的全部内容。在使用此命令时要非常小心,并在继续之前仔细检查一切。

使用 fsck 检查文件系统

为了检查和修复 Linux 文件系统,使用fsck程序。实际上,fsck只是文件系统特定检查器的前端(类似于mkfs)。

fsck程序可以并行运行在不同的文件系统上以加快处理速度。请注意,此功能可以在资源较低的机器上禁用。

一般来说,fsck的语法如下:

 fsck [-lsAVRTMNP] [-C [fd]] [-t fstype] [filesys...]  [--] [fs-specific-options]

准备工作

如果不正确使用fsck程序,可能会损坏当前驻留在分区上的数据。因此,在执行此命令之前,请确保已经备份了所有所需的数据。一旦执行了此操作,就无法撤销。如果您想要按照这些步骤操作,可以先在一个您不在乎的 USB 存储设备上练习。

在运行命令之前,设备必须被卸载。

如何操作...

执行以下步骤来检查和运行分区:

  1. 在此示例中,我插入了一个我不太在乎的 USB 存储设备。为了确保我们有正确的设备,请运行dmesg并查看最后一行:
dmesg | tail -20

  1. 在我的系统上,它显示设备是/dev/sdh1(相应地替换您的设备)。它没有挂载,所以我准备好继续。但是,如果您的设备是自动挂载的,您应该能够通过运行umount /dev/sdh1来卸载它。

  2. 现在我们可以运行fsck程序。我首先想看看它将采取什么行动,因此将使用-N选项。运行fsck -N /dev/sdh1。在我的系统上显示以下输出:

Big2 /home/guest1 # fsck -N /dev/sdh1
fsck from util-linux 2.21.2
[/sbin/fsck.vfat (1) -- /dev/sdh1] fsck.vfat /dev/sdh1

  1. 看起来不错,所以让我们包括一个进度条并真正运行它:fsck -C /dev/sdh1。在我的系统上获得以下结果:
Big2 /home/guest1 # fsck -C /dev/sdh1
fsck from util-linux 2.21.2
dosfsck 3.0.12, 29 Oct 2011, FAT32, LFN
/dev/sdh1: 1743 files, 234381/977025 clusters

由于这个 USB 存储设备没有问题,输出并不是很令人兴奋。我过去曾看到一些非常严重的错误,如果这种情况发生在您身上,我建议尽快将数据从驱动器上取出,然后使用mkfs重新格式化驱动器,或者为了安全起见,获取一个新的驱动器。

还有更多...

以下是fdisk的简要选项列表以及它们的功能:

  • -l:它将在检查之前锁定设备,一次只能用于一个设备。

  • -s:它将串行化文件检查操作。在交互模式下检查多个文件系统时很有用。

  • -A:它使用/etc/fstab文件中的条目一次性检查所有文件系统。通常,首先检查根文件系统,然后根据passno值检查其他文件系统。有关可用选项的更多信息,请参阅fstabman页面。

  • -C:它将显示一个进度条。

  • -M:指定不检查已挂载的文件系统。

  • -N:它将显示将在此设备上执行的操作,但实际上不会执行。

  • -P:它将并行检查根文件系统和其他系统。绝对不要使用此选项。

  • -R:它将在检查其他系统时跳过根文件系统。

  • -V:它将启用详细输出,因此建议使用。

以下是通常由特定文件系统程序支持的选项列表:

  • -a:它将自动修复文件系统,无需任何问题。请非常小心使用此选项,因为我曾在多次情况下看到它出现严重错误。

  • -n:此选项应告诉特定的检查器不执行任何修复。它不可靠,因此不建议使用。

  • -r:它将以交互方式修复文件系统。如果并行运行fsck,不要使用此选项。

  • -y:它告诉某些特定的检查器自动进行修复。

理论上,像ext3ext4这样的日志文件系统不应需要大量的检查或修复。如果在您的系统上不是这种情况,我会怀疑是硬件或者硬件 CMOS 级别的问题。确保系统中的所有内容都刷新到正确的版本。

注意

为了修复文件系统,它必须没有挂载。此外,检查已挂载的文件系统有时可能会产生虚假的错误消息。

逻辑卷管理(LVM)

Linux 的 LVM 允许将磁盘或磁盘阵列管理为一个大的存储池。一个 LVM 由一个或多个物理卷以及一个或多个逻辑卷组成。

例如,/root/home等目录位于一个逻辑卷中。有一些命令用于管理 LVM。有些操作在物理卷上进行,有些在逻辑卷上进行,有些在两者上都进行。

以下列表可用作 LVM 命令的快速参考指南:

  • pvcreate:它初始化磁盘或分区

  • pvchange:它改变一个或多个物理卷的分配权限

  • pvck:它检查物理卷的元数据

  • pvdisplay:它显示物理卷的属性

  • pvmove:它移动物理区段

  • pvremove:它移除一个物理卷

  • pvresize:它调整磁盘或分区的大小

  • pvs:它报告有关物理卷的信息

  • pvscan:它扫描所有磁盘以查找物理卷

  • vgcfgbackup:它备份卷组描述符区域

  • vgcfgrestore:它恢复卷组描述符区域

  • vgchange:它改变卷组的属性

  • vgck:它检查卷组的元数据

  • vgconvert:它转换卷组的元数据格式

  • vgcreate:它创建一个卷组

  • vgdisplay:它显示卷组的属性

  • vgexport:它使卷组对系统不可见

  • vgextend:它向卷组添加物理卷

  • vgimport:它使导出的卷组对系统可见

  • vgimportclone:它导入并重命名重复的卷组

  • vgmerge:它合并两个卷组

  • vgmknodes:它重新创建卷组目录和逻辑卷特殊文件

  • vgreduce:它从卷组中删除未使用的物理卷

  • vgremove:它移除一个卷组

  • vgrename:它重命名一个卷组

  • vgs:它报告有关卷组的信息

  • vgscan:它扫描所有磁盘以查找卷组并重建缓存

  • vgsplit:它将卷组分割成两个

  • lvchange:它改变逻辑卷的属性

  • lvconvert:它将逻辑卷从线性转换为镜像或快照

  • lvcreate:它在现有卷组中创建逻辑卷

  • lvdisplay:它显示逻辑卷的属性

  • lvextend:它扩展逻辑卷的大小

  • lvmdiskscan:它扫描所有对 lvm2 可见的设备

  • lvmdump:它为诊断目的创建 lvm2 信息转储

  • lvreduce:它减小逻辑卷的大小

  • lvremove:它移除一个逻辑卷

  • lvrename:它重命名逻辑卷

  • lvresize:它调整逻辑卷的大小

  • lvs:它报告有关逻辑卷的信息

  • lvscan:它扫描所有磁盘以查找逻辑卷

准备工作

以下命令假定您正在运行一个了解 LVM 的系统。请注意,您不需要实际上将驱动器格式化为 LVM 格式才能尝试这些命令。

如何做...

以下是您可以在系统上尝试的一些非破坏性命令(您需要以 root 用户身份运行这些命令):

  1. 让我们看看系统上的所有物理卷:
pvdisplay

  1. 现在让我们扫描磁盘:
pvscan

  1. 然后,显示卷组的属性:
vgdisplay

  1. 我们报告有关卷组的信息:
vgs

  1. 然后扫描所有卷组的磁盘:
vgscan

  1. 然后需要显示逻辑卷的属性(这个经常使用):
lvdisplay

  1. 扫描所有对 LVM 可见的设备:
lvmdiskscan

  1. 报告有关逻辑卷的信息:
lvs

  1. 扫描所有磁盘以查找逻辑卷:
lvscan

以下是我在我的 Fedora 14 系统上的pvdisplayvgdisplay的屏幕截图:

如何做...

还有更多...

如果您习惯于传统的磁盘驱动器配置方法,LVM 可能需要一段时间才能习惯。我发现 man 页面在这方面非常好,互联网上也有一些很好的文章。

了解不同的文件系统

在撰写本文时,Linux 上有 60 多种不同的文件系统可用。以下是您可能经常遇到的常见文件系统的简要概述:

  • Btrfs:B 树文件系统是由 Oracle 于 2007 年开发的写时复制文件系统。它仍处于开发阶段,被认为是实验性的。Btrfs的意图是允许文件系统随着驱动器变得越来越大而扩展。由于其优势,它被认为是取代ext4的文件系统。

  • ext2:它是在 1993 年引入的。这个文件系统没有日志记录,因此每个周期的写入较少,使其成为闪存驱动器的良好选择。

  • ext3:它与ext2非常相似,但增加了日志记录,这提高了可靠性,特别是在非正常关闭后。

  • ext4:发布于 2008 年,被认为是ext3的后继者。它可以处理高达 1 exbibyte 的卷和高达 16 tebibytes 的文件。这个文件系统使用范围来替代早期版本的 ext 使用的传统块映射方案。它具有增强功能,可以加快文件系统检查(fsck)的速度。

  • FAT:这是文件分配表的缩写,最初由 DOS、OS/2 和 Windows 使用。它主要在内核中提供对外部设备(如 USB 闪存驱动器)的支持。

  • ReiserFS(或Reiser3):这是一个带有日志记录的通用文件系统,最初由 Hans Reiser 设计和编写。当它被创建时,它包含了当时尚未可用的许多功能,包括日志记录、在线增长和限制内部碎片的方案。

  • Reiser4:这是ReiserFS的后继者(由于设计者 Hans Reiser 因谋杀罪被定罪,未来的发展是不确定的)。

第八章:使用脚本

在本章中,我们将涵盖以下主题:

  • 从文件中删除文本

  • 使用脚本参数

  • 在脚本中编写循环

  • 备份您的系统

  • 一次只能为一个用途锁定文件

  • 熟悉 Perl

介绍

知道如何编写脚本将使您能够更有效地运行您的系统。编写脚本很容易;您不需要计算机科学学位或类似的东西。更好的是,您需要创建和运行脚本的一切都已经在您的 Linux 系统上可用。

编程时要记住的主要事情是要像计算机一样思考。尝试理解每个步骤的作用。如果遇到问题,请仔细查看相关的行。计算机会按照您的指示每次执行。

在这些示例中,我们将编写Bash shell 脚本。以指示使用的 shell 为开头的每个脚本是良好的编程实践。这是通过以第一列开始的一行来完成的,例如以下内容:

#!/bin/sh

使用文本编辑器创建脚本。我看到有人试图使用文字处理软件来编写脚本,但我不建议这样做。文字处理软件笨重,似乎总是会在文件中插入不良字符(尽管它们声称不会)。如果您现在还不知道,学习如何使用EMACSvi或其他文本编辑器(参见第三章,“文件和目录”)。您会为此感到高兴的。

为了将脚本作为命令执行,您需要更改文件的权限。例如,如果您已经创建并保存了一个名为mycmd的文本文件,您可以通过运行以下命令使其可执行:

 chmod 755 mycmd

如果您没有进行过太多的脚本编写,为了安全起见,我建议在创建和运行脚本时使用用户帐户。当您感到舒适(或者如果您已经感到舒适),您可以以 root 身份运行。您可能会在某个时候必须这样做,特别是如果您是系统管理员。

以下段落中给出了几个脚本示例。这些应该很好地说明了脚本可以用于什么以及如何编写它们。

从文件中删除文本

脚本可以编写成几乎您能想象到的任何事情。以下是一个这样的例子。

如何做到...

以下是一个可以用于去掉示例中行号的脚本的清单。然后您可以在您的系统上按原样运行它们。

脚本 1 - 去掉行号

 1  #!/bin/sh
 2  # removelines 5/1/2013
 3  if [ "$1" = "" ] ; then
 4   echo "Usage: removenumbers filename > newfile"
 5   echo " This script will remove the line numbers from the beginning of the lines"
 6   echo " in filename. It assumes the number field is 5 characters wide."
 7   echo " Use the redirection operator to save the output to a new file."
 8   exit
 9  fi
 10  cat $1 | cut -c 1-5 --complement

它是如何工作的...

让我们讨论一下前面给出的行是做什么的。

  • 第一行告诉操作系统这个脚本是为哪个 shell 准备的。

  • 第 2 行在第一列有一个#。这被称为注释行。这里我有脚本编写的日期。

  • $1变量是您在命令名称之后给出的第一个参数。如果没有给出参数,它将等于空字符串("")。Usage文本将显示,并且脚本将在第 8 行退出。

  • 如果确实给出了参数,此脚本假定它是一个文件名,因此,处理将继续到第 10 行。

  • 第 10 行使用cat命令来流式传输文件的内容。在这种情况下,流被传输到cut命令。

  • cut命令通常会保留每行的前五个字符并丢弃其余部分。但是,由于我使用了--complement标志,它做的恰恰相反。许多 Linux 命令都有这个选项或类似的选项。

还有更多...

如果您想在您的系统上尝试这个,请执行以下步骤:

  1. 打开一个文本编辑会话,例如vi removelines.txt

  2. 通过按*I.*将vi置于插入模式。

  3. 从书中复制脚本的文本并粘贴到vi中。保存文件并退出:wq

  4. 现在运行以下命令:

cat removelines.txt | cut -c 1-5 --complement > removelines

  1. 然后使其可执行:
chmod 755 removelines

  1. 运行以下命令:
removelines

如果一切顺利,使用屏幕应该会出现。您现在可以在本章的其余示例中使用此脚本。

使用脚本参数

这里我们展示了如何计算和显示给脚本的参数数量。

如何做...

以下是脚本清单:

脚本 2 - 参数

 1  #!/bin/sh
 2  # 5/1/2013
 3  echo Script showing how to count and show the parameters
 4  N=$#
 5  echo Number of parameters: $N
 6  if [ $N -eq 0 ] ; then
 7    echo "Usage: $0 parameters and/or a mask"
 8    exit
 9  fi
 10  for i in $* ; do
 11   echo Parm: $i
 12  done

它是如何工作的...

  • 您已经知道第 1 到 3 行的作用。$#内置变量包含给脚本的参数数量。在第 4 行,我们将变量N设置为该值。

  • 第 5 行显示了N的值。请注意,要访问变量,必须在其前面加上$字符。

  • 在第 6 行,我们测试N以查看是否给出了任何参数。如果没有,我们显示Usage消息,并在第 8 行退出。

  • 第 10 行是一个for循环的示例。注意语法,并不要忘记循环结束时的done命令。请注意,$*是一个内置变量,其中包含给脚本的所有参数的列表。

  • 在第 11 行,我们显示了i变量的值。

还有更多...

  1. 通过按照前一节中的示例进行更改,将其命名为parameters,使其成为您系统上的可执行脚本。

  2. 运行它:parameters(您可能需要在系统上运行. /parameters)。

  3. 您应该看到Usage消息。现在使用以下命令运行它:

parameters 1 34 56

  1. 它应该显示数字 3,然后每个参数一行。

  2. 尝试使用其他数字。还尝试一些通配符字符。

注意

变量需要更多的解释。例如,以下是数字:

i=1
RC=0

您可以按以下方式测试数字:

if [ $i -eq 0 ] ; then           # test for equal
if [ $RC -ne 0 ] ; then       # test for not equal

以下是字符串:

FNAME=Jim
LNAME=Lewis
if [ "$FNAME" = "Jim" ] ; then     # test string equality
if [ "$LNAME" = "Lewis" ] ; then   # test string equality

这是另一种情况,记住它是相反的。使用诸如-eq之类的字母来测试数字,使用=和其他数字运算符来测试字符串。

在脚本中编写一个循环

我们之前的脚本是快速运行完成的命令。这是一个运行直到您决定终止它的脚本的示例。请注意,如果不需要参数,则可能不需要Usage部分(但一定要在注释部分说明脚本的功能)。

此脚本通过每分钟一次 ping 服务提供商来监视网络连接的状态。失败将被记录到文件中。

如何做...

以下是程序清单:

脚本 3 - 循环

 1  #!/bin/sh
 2  #
 3  #  Check network once a minute and log failures to a file
 4  PROVIDER=192.168.1.102
 5  tput clear
 6  while [ 1 ]
 7  do
 8    echo Written by Jim Lewis 2/21/2007
 9    echo Pinging $PROVIDER
 10    ping -c 1 $PROVIDER
 11    rc=$?
 12    if [ $rc -ne 0 ] ; then
 13      echo Cannot ping $PROVIDER
 14      date >> log1.txt
 15      echo Cannot ping $PROVIDER >> log1.txt
 16    fi
 17    sleep 60
 18  done

它是如何工作的...

  • 第 4 行是您的服务提供商的 IP 地址或域名。在本例中,我使用了我的bigtwo机器。请注意,如果将此变量放在您的.bashrc文件中(参见第一章,“使用终端/命令行”),那么如果将来更换服务提供商,您只需要在一个地方进行更改。

  • 第 5 行清除屏幕。

  • 第 6 行可能看起来有点奇怪。是的,这就是所谓的无限循环。但是,脚本仍然可以通过按下CtrlC,通过向其发出 kill 命令,或者通过让它监视一个文件(稍后会详细介绍)来终止。

  • 在第 7 行,记住while语句需要在其后有一个语句。

  • 第 10 行使用了ping命令。-c 1变量告诉它只 ping 一次。

  • 第 11 行保存了上一个命令的错误代码。

  • 如果没有错误,则ping命令返回0。如果存在错误,第 14 行将系统日期附加到log1.txt文件中。

  • 第 15 行然后将文本附加到日志文件中。

  • 第 17 行等待 60 秒,然后循环在第 6 行重新开始。

我从 2007 年 1 月开始运行这个脚本。我已经多次使用log1.txt文件来说服我的服务提供商改进他们的服务。

以下是我在 Fedora 17 系统上运行的脚本的截图:

它是如何工作的...

还有更多...

执行以下步骤来运行此脚本:

  1. 按照前几节的步骤创建文件。您可以根据需要对其进行命名,只要不会与另一个脚本或程序冲突即可。我将其命名为loop1

  2. 在您的系统上打开一个终端。我建议将其设置得比之前的截图小一些。

  3. 您无需以 root 身份运行此脚本。因此,只需键入您给它的名称即可启动它。

  4. 请记住,这个脚本是一个循环;它会一直运行直到你终止它。

  5. 你应该不时查看log1.txt文件,以了解你的互联网连接有多可靠。请注意,如果你的连接经常中断,这个文件可能会变得非常大。

这样的脚本经常被使用,特别是在执行系统管理职责时,用于监视网络资源。

一个警告,谨慎使用ping等服务。例如,不要过多地 ping 你的提供商。一分钟一次就可以了。在开发这样的脚本时,使用本地 ping 地址进行测试,直到你完全掌握它。

系统备份

自动化任务是使脚本真正强大的地方。你可以花一些时间把脚本做得完美,然后让它自己运行。我现在每个 Fedora 系统上至少有十个脚本在运行。

这就是我所谓的穷人备份实用程序。过去,我曾尝试过一些商店购买的程序,但对软件质量感到失望。最糟糕的是需要备份文件,然后发现根本没有!这个脚本由一个cron作业每天晚上 3 点调用。我们将在下一章介绍 cron。

如果你想尝试并使用这个脚本,请确保你理解正在发生什么。备份目录必须首先手动创建,以及filenum1文件。

如所写的这个脚本必须以 root 身份运行。

如何做...

我使用以下脚本来备份我的文件:

脚本 4 - 备份

 1  #!/bin/sh
 2  #   Jim's backup program
 3  # Change to an appropriate directory on your system
 4  cd /lewis/backup
 5  VER="File backup by Jim Lewis 4/25/2011 A"
 6  echo $VER
 7  date >> datelog.txt
 8  T=`cat filenum1`
 9  T=`expr $T + 1`
 10  if [ $T -gt 7 ] ; then
 11   T=1
 12  fi
 13  echo $T > filenum1
 14  TDIR=/temp/linuxbook/chap8/backups$T
 15  echo "Removing files from $TDIR"
 16  cd $TDIR
 17  pwd
 18  rm *.gz
 19  echo "Backing up files to $TDIR"
 20  X=`date "+%m%d-%H"`              # create a timestamp
 21  echo $X
 22  cd /
 23  tar -cvzf "$TDIR/lewis$X.gz" lewis
 24  tar -cvzf "$TDIR/temp$X.gz" temp
 25  tar -cvzf "$TDIR/root$X.gz" root
 26  cd /home
 27  tar -cvzf "$TDIR/guest$X.gz" --exclude=Cache --exclude=.cache --exclude=.evolution --exclude=vmware --exclude=.thumbnails  --exclude=.gconf --exclude=.kde --exclude=.adobe   guest1
 28  echo $VER
 29  cd $TDIR
 30  pwd
 31  ls -lah

它是如何工作的...

  • 第 4 行切换到我的备份目录。你会想在你的系统上更改这个。

  • 第 7 行将当前日期附加到datelog.txt文件中。我不时检查这个文件,确保一切看起来都很好。

  • 第 8 行看起来真的很奇怪;那些反引号是干什么的?filenum1文件包含一个数字,这是下一个要复制备份文件的目录(总共 7 个)。你知道,如果你cat这个文件,它会在屏幕上显示它的内容。嗯,反引号的意思是运行这个命令,但将结果表达式放入一个变量中。这听起来很复杂,但你会很快习惯的。

  • 变量T现在有了下一个要使用的目录的编号。第 9 行使用expr命令来评估表达式,并将1加到T上。

  • 第 10 行检查T是否大于7,如果是,就将它设置回1。是的,我做了七次备份,每周一次。叫我偏执狂吧!

  • 第 13 行将T的新值复制回filenum1以供下次使用。

  • 第 14 行设置了TDIR变量,其中包含我们要复制文件的备份目录。

  • 第 16 行切换到TDIR

  • 第 17 行显示当前工作目录。我在编写这个脚本时加入了这个,习惯了它的存在,所以留了下来。这完全是可选的。

  • 第 18 行删除了先前压缩的备份文件。我强烈建议你在首次尝试这个脚本时注释掉这一行。然后,在确保一切正常之后,你可以把它放回去。

  • 第 20 行设置了一个日期时间戳。同样,反引号操作符被用来将日期的值放入一个变量中(在这种情况下是X)。

  • 第 22 行切换到/

  • 第 23、24 和 25 行备份了/lewis/temp/root目录。

  • 第 26 行切换到/home

  • 第 27 行打包了我的/home/guest1目录。tar的参数告诉它从归档中排除哪些目录。查看tar man页面以获取更多信息。

  • 第 28 行显示脚本版本,第 29 行返回到备份目录,第 30 行显示目录名称,第 31 行显示文件列表。

这个脚本更像是一个示例,而不是一个真正的备份程序,但这是一个很好的起点。我使用的真正的备份程序与此类似,但还将文件复制到外部 USB 驱动器和另一台远程计算机(使用无人值守的scp)。每当我想要创建一个新的 Linux 机器时,我只需将这些文件复制到它并解压缩,配置和源我的.bashrc,然后我就可以运行了。

一次只能使用一个文件的锁定

这对我来说经常发生。有时候您可能想通过运行一个简单的脚本在终端中编辑一个文件。但是,如果文件已经在另一个终端中打开,那么一个会话中进行的更新可能会在另一个会话中被覆盖。以下脚本应该有助于防止这种情况发生。

操作步骤...

以下是防止同一个文件同时被多个终端编辑的简单方法:

脚本 5 - 文件锁定

 1  #!/bin/sh
 2  # todo script 5/1/2013
 3  FN1=/tmp/file.lock
 4  if [ -f $FN1  ] ; then
 5   echo -n "File is being used in tty: "
 6   cat $FN1
 7   exit
 8  fi
 9  echo `tty` > $FN1
 10  # perform your actions(s) here
 11  kw /lewis/todo.txt
 12  rm $FN1

它是如何工作的...

  • 第 3 行将变量FN1设置为锁定文件的名称。

  • 第 4 行检查锁定文件是否存在。如果存在,它会显示锁定文件的内容并退出脚本。

  • 如果锁定文件不存在,我们将到达第 9 行。现在通过将tty命令的输出重定向到文件来创建锁定文件。

  • 在第 11 行,您可以执行任何您想要的操作。在我的情况下,我在这里使用kw,我的文本编辑器编辑/tmp/todo.txt。即使编辑器会话关闭,脚本的处理也会继续。

  • 第 12 行删除锁定文件。

这很简单,而且效果非常好。我使用这个脚本的一个版本来编辑我的几个重要文件。todo脚本可以从系统的任何位置运行,并且todo.txt文件会显示在我的文本编辑器中。如果我在文件仍在被编辑时离开到另一个会话或窗口,然后尝试再次运行todo,它将不允许编辑。它还会告诉我tty是否在原始会话中。这可以帮助我更快地再次找到它,这对我来说非常有用,因为我总是有很多工作区和终端打开。

介绍 Perl

Perl 是一种可以用于文本处理、Web 开发、网络编程、系统管理、GUI 开发等等的编程语言。它被设计成易于使用和高效,您可以在脚本中使用传统的过程化方法或面向对象的方法。Perl 还有一个相当大的第三方附加模块列表,使其具有更多的功能。

准备工作

在本节中,我们将只涵盖 Perl 的基础知识。大多数典型的 Linux 系统都已经安装了它和文档。要查看简要介绍,请在您的系统上运行perldoc perlintro。Perl 介绍应该会立即出现。

要运行 Perl 脚本,可以使用以下 Perl 命令:

perl filename.pl

.pl参数是通常赋予 Perl 脚本的扩展名。您还可以在脚本中放置 Perl 的路径,类似于我们在bash中所做的。首先运行which perl以查看 Perl 的位置,然后将其放在脚本的第一行中:

#!/usr/bin/perl

这是 Fedora 上的正确路径。与bash脚本一样,使用文本编辑器创建它们,并使用chmod 755 filename.pl使其可执行。现在,您只需输入命令的名称即可运行它。

操作步骤...

以下是我在开始学习这种语言时写的一个小 Perl 脚本:

 1  #!/usr/bin/perl
 2  #  t1.pl - Perl practice script 1
 3  use strict;
 4  use warnings;
 5  sub displaymessage
 6  {
 7   my $message = shift;
 8   print "message: $message\n";
 9  }
 10  system("tput clear");
 11  print "Practice script 1 5/4/2013\n";
 12  my $name = "Jim";
 13  print "name: $name\n";
 14  my @numbers = (23, 42, 69, 71);
 15  print "numbers 0: $numbers[0]\n";
 16  print "Last element is: $numbers[$#numbers]\n";
 17  if($numbers[0]==23)
 18  {
 19   print "numbers 0 is equal to 23\n";
 20  }
 21  my $count = 0 ;
 22  foreach (@numbers)
 23  {
 24   print "Element $count is  $_\n";
 25   $count++;
 26  }
 27  print "Opening input.txt ...\n";
 28  open(my $in,  "<",  "input.txt")  or die "Cannot open input.txt for reading: $!";
 29  print "Opening output.txt ...\n";
 30  open(my $out, ">",  "output.txt") or die "Cannot open output.txt for writing: $!";
 31  while (<$in>)
 32  {
 33   print "line $_";
 34   print $out $_;
 35  }
 36  close $in or die "$in: $!";
 37  close $out or die "$out: $!";
 38  displaymessage("Type some keys. Press 'c' to clear the screen and 'q' to quit:");
 39  my $key = 1;
 40  $count = 1;
 41  while($count < 500)
 42  {
 43  # read a key from the keyboard
 44   open(TTY, "+</dev/tty") or die "no tty: $!";
 45   system "stty  cbreak </dev/tty >/dev/tty 2>&1";
 46   $key = getc(TTY);
 47   if($key eq 'c')
 48   {
 49    system("tput clear");
 50   }
 51   if($key eq 'q')
 52   {
 53    print "\nEnding the script\n";
 54    $count = 10000;
 55   }
 56   $count++;
 57  }

它是如何工作的...

  • 第 1 行告诉 shell 要使用哪个解释器。

  • 第 3 行告诉编译器在语法上要非常严格。也始终使用这一行。

  • 第 4 行表示显示所有警告。也始终使用这个。

  • 第 5 到 9 行是一个子例程。第 7 行将子例程的第一个参数放入变量消息中。第 8 行显示它。

  • 第 10 行清除屏幕。

  • 第 11 行告诉我们这个脚本应该是什么。请注意行尾的\n参数。这代表换行,表示将下一个打印输出继续到下一行。

  • 第 12 行将变量名设置为Jim。注意名称前面的$符号。不要忘记它。

  • 第 13 行显示变量。

  • 第 14 行创建一个数字数组。注意@字符。

  • 第 15 行显示数组中的第一个元素。

  • 第 16 行使用特殊的 Perl 语法$#numbers显示最后一个元素。

  • 第 17 行检查元素0是否真的等于23。注意双等号。

  • 第 21 行创建变量count并将其设置为0

  • 第 22 行是另一个特殊的 Perl 约定。foreach命令表示逐个遍历数组中的元素。这是一个非常方便的功能。

  • 第 24 行展示了特殊的$_结构如何显示数组的每个元素。

  • 第 25 行将计数增加1

  • 下面的几行是在 Perl 中处理文件的一种方法。它尝试打开input.txt文件进行读取,output.txt进行写入。input.txt文件必须存在,否则程序将出错并在此停止。input.txt的内容如下:

line 1
line 2
line 3
line 4
line 5

  • 第 30 行打开输出文件。

  • 第 31 到 35 行读取input.txt中的每一行并将其写入output.txt

  • 第 36 和 37 行关闭文件。不要忘记在脚本中执行这一步。

  • 第 38 行使用我们之前创建的子例程显示一条消息。

  • 第 39 行创建并设置key变量。

  • 第 40 行将count变量重新设置为1

  • 第 41 行开始一个while循环。

  • 第 43 到 46 行是在 Perl 中从键盘读取键的一种方法。如果这对你来说看起来很复杂,我完全同意。

其余的行都是不言自明的。当用户按下q退出时,count变量增加到10000。这会导致第 41 行的while循环提前结束,有效地结束脚本。你也可以在这里使用一个循环控制变量。

以下是我系统上运行的上一个脚本的屏幕截图:

它是如何工作的...

还有更多...

尽管这是一个非常琐碎的脚本,但你可以用 Perl 做很多事情。许多年前,当我刚开始接触家用电脑时,有一个基于星际迷航的文本模式游戏可以玩。我得到了这个 BASIC 游戏的副本,最终用 C 语言重写了它。几个月前,我决定再次重写它,这次使用 Perl。它还没有完成,可能是因为我太忙于写这本书,但它正在进行中。

关于 Perl 的好书应该很容易找到。我买了几本,发现它们在我试图更详细地学习它时非常有价值。

有几百个标准的 Linux 实用程序可以独立使用或在脚本中使用。以下是一些最常见的一些命令的简短列表。每当你需要执行任何任务时,请在这里检查,看看你是否可以将其中一些命令纳入你的脚本中。

以下实用程序位于/bin目录中:

  • awkgawk:用于模式扫描和处理语言

  • basename:用于从文件名中剥离目录和后缀

  • bash:GNU 的 Bourne-Again Shell

  • cat:用于连接文件并在标准输出上打印

  • chmod:用于更改文件模式位

  • chown:用于更改文件所有者和组

  • cp:用于复制文件和目录

  • cut:用于从文件的每一行中删除部分

  • date:用于打印或设置系统的日期和时间

  • dmesg:用于打印或控制内核环形缓冲区

  • echo:用于显示一行文本

  • find:用于在目录层次结构中搜索文件

  • grepegrepfgrep:用于打印匹配模式的行

  • hostname:用于显示或设置系统的主机名

  • ls:用于列出目录内容

  • mkdir:用于创建目录

  • mktemp:用于创建临时文件或目录

  • mv:用于移动(重命名)文件

  • pingping6:用于向网络主机发送ICMP ECHO_REQUEST

  • ps:用于报告当前进程的快照

  • pwd:用于打印当前工作目录的名称

  • rm:用于删除文件或目录

  • sed:用于调用流编辑器来过滤和转换文本

  • sleep:表示延迟一定时间

  • sort:用于对文本文件的行进行排序

  • tar:用于将文件组合并可选地压缩到单个存档中

  • touch:用于更改文件时间戳

以下实用程序位于/usr/bin中:

  • diff:用于逐行比较文件

  • dirname:用于从文件名中剥离最后一个组件

  • expr:用于评估表达式

  • file:用于确定文件类型

  • flock:用于从 shell 脚本管理锁

  • stat:用于显示文件或文件系统状态

  • tee:用于从标准输入读取并写入标准输出和文件

  • time:用于计时简单命令或提供资源使用情况

  • tty:用于打印连接到标准输入的终端的文件名

  • uniq:用于报告或省略重复的行

  • unzip:用于列出、测试和提取ZIP存档中的压缩文件

  • who:用于显示谁已登录

  • xargs:用于从标准输入构建和执行命令行

以下命令内置于 shell 中:

  • cd:用于更改目录

  • echo:用于显示一行文本

  • exit:导致 shell 退出(带有可选的返回代码)

  • export:用于设置环境变量

  • kill:用于向进程发送信号或终止进程

  • read:用于从键盘获取字符串并将其放入变量中