分类 技术 下的文章

问题

我试着在Ubuntu中安装Emerald图标主题,而这个主题被打包成了.7z归档包。和以往一样,我试着通过在GUI中右击并选择“提取到这里”来将它解压缩。但是Ubuntu 15.04却并没有解压文件,取而代之的,却是丢给了我一个下面这样的错误信息:

Could not open this file

无法打开该文件

There is no command installed for 7-zip archive files. Do you want to search for a command to open this file?

没有安装用于7-zip归档文件的命令。你是否想要搜索用于来打开该文件的命令?

错误信息看上去是这样的:

原因

发生该错误的原因从错误信息本身来看就十分明了。7Z,称之为7-zip更好,该程序没有安装,因此7Z压缩文件就无法解压缩。这也暗示着Ubuntu默认不支持7-zip文件。

解决方案:在Ubuntu中安装 7zip

要解决该问题也十分简单,在Ubuntu中安装7-Zip包即可。现在,你也许想知道如何在Ubuntu中安装 7Zip吧?好吧,在前面的错误对话框中,如果你右击“Search Command”搜索命令,它会查找可用的 p7zip 包。只要点击“Install”安装,如下图:

可选方案:在终端中安装 7Zip

如果偏好使用终端,你可以使用以下命令在终端中安装 7zip:

sudo apt-get install p7zip-full

注意:在Ubuntu中,你会发现有3个7zip包:p7zip,p7zip-full 和 p7zip-rar。p7zip和p7zip-full的区别在于,p7zip是一个更轻量化的版本,仅仅提供了对 .7z 和 .7za 文件的支持,而完整版则提供了对更多(用于音频文件等的) 7z 压缩算法的支持。对于 p7zip-rar,它除了对 7z 文件的支持外,也提供了对 .rar 文件的支持。

事实上,相同的错误也会发生在Ubuntu中的RAR文件身上。解决方案也一样,安装正确的程序即可。

希望这篇快文帮助你解决了Ubuntu 14.04中如何打开 7zip的谜团。如有任何问题或建议,我们将无任欢迎。


via: http://itsfoss.com/fix-there-is-no-command-installed-for-7-zip-archive-files/

作者:Abhishek 译者:GOLinux 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

NGINX 是什么?

NGINX (发音为 “engine X”) 是一种流行的 HTTP 和反向代理服务器。作为一个 HTTP 服务器,NGINX 可以使用较少的内存非常高效可靠地提供静态内容。作为反向代理,它可以用作多个后端服务器或类似缓存和负载平衡这样的其它应用的单一访问控制点。NGINX 是一个自由开源的产品,并有一个具备更全的功能的叫做 NGINX Plus 的商业版。

NGINX 也可以用作邮件代理和通用的 TCP 代理,但本文并不直接讨论 NGINX 的那些用例的监控。

NGINX 主要指标

通过监控 NGINX 可以 捕获到两类问题:NGINX 本身的资源问题,和出现在你的基础网络设施的其它问题。大多数 NGINX 用户会用到以下指标的监控,包括每秒请求数,它提供了一个由所有最终用户活动组成的上层视图;服务器错误率 ,这表明你的服务器已经多长没有处理看似有效的请求;还有请求处理时间,这说明你的服务器处理客户端请求的总共时长(并且可以看出性能降低或当前环境的其他问题)。

更一般地,至少有三个主要的指标类别来监视:

  • 基本活动指标
  • 错误指标
  • 性能指标

下面我们将分析在每个类别中最重要的 NGINX 指标,以及用一个相当普遍但是值得特别提到的案例来说明:使用 NGINX Plus 作反向代理。我们还将介绍如何使用图形工具或可选择的监控工具来监控所有的指标。

本文引用指标术语来自我们的“监控 101 系列”,,它提供了一个指标收集和警告框架。

基本活跃指标

无论你在怎样的情况下使用 NGINX,毫无疑问你要监视服务器接收多少客户端请求和如何处理这些请求。

NGINX Plus 上像开源 NGINX 一样可以报告基本活跃指标,但它也提供了略有不同的辅助模块。我们首先讨论开源的 NGINX,再来说明 NGINX Plus 提供的其他指标的功能。

NGINX

下图显示了一个客户端连接的过程,以及开源版本的 NGINX 如何在连接过程中收集指标。

connection, request states

Accepts(接受)、Handled(已处理)、Requests(请求数)是一直在增加的计数器。Active(活跃)、Waiting(等待)、Reading(读)、Writing(写)随着请求量而增减。

名称描述指标类型
Accepts(接受)NGINX 所接受的客户端连接数资源: 功能
Handled(已处理)成功的客户端连接数资源: 功能
Active(活跃)当前活跃的客户端连接数资源: 功能
Dropped(已丢弃,计算得出)丢弃的连接数(接受 - 已处理)工作:错误*
Requests(请求数)客户端请求数工作:吞吐量

*严格的来说,丢弃的连接是 一个资源饱和指标,但是因为饱和会导致 NGINX 停止服务(而不是延后该请求),所以,“已丢弃”视作 一个工作指标 比较合适。

NGINX worker 进程接受 OS 的连接请求时 Accepts 计数器增加,而Handled 是当实际的请求得到连接时(通过建立一个新的连接或重新使用一个空闲的)。这两个计数器的值通常都是相同的,如果它们有差别则表明连接被Dropped,往往这是由于资源限制,比如已经达到 NGINX 的worker\_connections的限制。

一旦 NGINX 成功处理一个连接时,连接会移动到Active状态,在这里对客户端请求进行处理:

Active状态

  • Waiting: 活跃的连接也可以处于 Waiting 子状态,如果有在此刻没有活跃请求的话。新连接可以绕过这个状态并直接变为到 Reading 状态,最常见的是在使用“accept filter(接受过滤器)” 和 “deferred accept(延迟接受)”时,在这种情况下,NGINX 不会接收 worker 进程的通知,直到它具有足够的数据才开始响应。如果连接设置为 keep-alive ,那么它在发送响应后将处于等待状态。
  • Reading: 当接收到请求时,连接离开 Waiting 状态,并且该请求本身使 Reading 状态计数增加。在这种状态下 NGINX 会读取客户端请求首部。请求首部是比较小的,因此这通常是一个快速的操作。
  • Writing: 请求被读取之后,其使 Writing 状态计数增加,并保持在该状态,直到响应返回给客户端。这意味着,该请求在 Writing 状态时, 一方面 NGINX 等待来自上游系统的结果(系统放在 NGINX “后面”),另外一方面,NGINX 也在同时响应。请求往往会在 Writing 状态花费大量的时间。

通常,一个连接在同一时间只接受一个请求。在这种情况下,Active 连接的数目 == Waiting 的连接 + Reading 请求 + Writing 。然而,较新的 SPDY 和 HTTP/2 协议允许多个并发请求/响应复用一个连接,所以 Active 可小于 Waiting 的连接、 Reading 请求、Writing 请求的总和。 (在撰写本文时,NGINX 不支持 HTTP/2,但预计到2015年期间将会支持。)

NGINX Plus

正如上面提到的,所有开源 NGINX 的指标在 NGINX Plus 中是可用的,但另外也提供其他的指标。本节仅说明了 NGINX Plus 可用的指标。

connection, request states

Accepted (已接受)、Dropped,总数是不断增加的计数器。Active、 Idle(空闲)和处于 Current(当前)处理阶段的各种状态下的连接或请​​求的当前数量随着请求量而增减。

名称描述指标类型
Accepted(已接受)NGINX 所接受的客户端连接数资源: 功能
Dropped(已丢弃)丢弃的连接数(接受 - 已处理)工作:错误*
Active(活跃)当前活跃的客户端连接数资源: 功能
Idle(空闲)没有当前请求的客户端连接资源: 功能
Total(全部请求数)客户端请求数工作:吞吐量

*严格的来说,丢弃的连接是 一个资源饱和指标,但是因为饱和会导致 NGINX 停止服务(而不是延后该请求),所以,“已丢弃”视作 一个工作指标 比较合适。

当 NGINX Plus worker 进程接受 OS 的连接请求时 Accepted 计数器递增。如果 worker 进程为请求建立连接失败(通过建立一个新的连接或重新使用一个空闲),则该连接被丢弃, Dropped 计数增加。通常连接被丢弃是因为资源限制,如 NGINX Plus 的worker\_connections的限制已经达到。

ActiveIdle如上所述的开源 NGINX 的“active” 和 “waiting”状态是相同的,但是有一点关键的不同:在开源 NGINX 上,“waiting”状态包括在“active”中,而在 NGINX Plus 上“idle”的连接被排除在“active” 计数外。Current 和开源 NGINX 是一样的也是由“reading + writing” 状态组成。

Total 为客户端请求的累积计数。请注意,单个客户端连接可涉及多个请求,所以这个数字可能会比连接的累计次数明显大。事实上,(total / accepted)是每个连接的平均请求数量。

开源 和 Plus 之间指标的不同

NGINX (开源)NGINX Plus
acceptsaccepted
dropped 通过计算得来dropped 直接得到
reading + writingcurrent
waitingidle
active (包括 “waiting”状态)active (排除 “idle” 状态)
requeststotal

提醒指标: 丢弃连接

被丢弃的连接数目等于 Accepts 和 Handled 之差(NGINX 中),或是可直接得到的标准指标(NGINX Plus 中)。在正常情况下,丢弃连接数应该是零。如果在每个单位时间内丢弃连接的速度开始上升,那么应该看看是否资源饱和了。

Dropped connections

提醒指标: 每秒请求数

按固定时间间隔采样你的请求数据(开源 NGINX 的requests或者 NGINX Plus 中total) 会提供给你单位时间内(通常是分钟或秒)所接受的请求数量。监测这个指标可以查看进入的 Web 流量尖峰,无论是合法的还是恶意的,或者突然的下降,这通常都代表着出现了问题。每秒请求数若发生急剧变化可以提醒你的环境出现问题了,即使它不能告诉你确切问题的位置所在。请注意,所有的请求都同样计数,无论 URL 是什么。

Requests per second

收集活跃指标

开源的 NGINX 提供了一个简单状态页面来显示基本的服务器指标。该状态信息以标准格式显示,实际上任何图形或监控工具可以被配置去解析这些相关数据,以用于分析、可视化、或提醒。NGINX Plus 提供一个 JSON 接口来供给更多的数据。阅读相关文章“NGINX 指标收集”来启用指标收集的功能。

错误指标

名称描述指标类型可用于
4xx 代码客户端错误计数工作:错误NGINX 日志, NGINX Plus
5xx 代码服务器端错误计数工作:错误NGINX 日志, NGINX Plus

NGINX 错误指标告诉你服务器是否经常返回错误而不是正常工作。客户端错误返回4XX状态码,服务器端错误返回5XX状态码。

提醒指标: 服务器错误率

服务器错误率等于在单位时间(通常为一到五分钟)内5xx错误状态代码的总数除以状态码(1XX,2XX,3XX,4XX,5XX)的总数。如果你的错误率随着时间的推移开始攀升,调查可能的原因。如果突然增加,可能需要采取紧急行动,因为客户端可能收到错误信息。

Server error rate

关于客户端错误的注意事项:虽然监控4XX是很有用的,但从该指标中你仅可以捕捉有限的信息,因为它只是衡量客户的行为而不捕捉任何特殊的 URL。换句话说,4xx出现的变化可能是一个信号,例如网络扫描器正在寻找你的网站漏洞时。

收集错误度量

虽然开源 NGINX 不能马上得到用于监测的错误率,但至少有两种方法可以得到:

  • 使用商业支持的 NGINX Plus 提供的扩展状态模块
  • 配置 NGINX 的日志模块将响应码写入访问日志

关于这两种方法,请阅读相关文章“NGINX 指标收集”。

性能指标

名称描述指标类型可用于
request time (请求处理时间)处理每个请求的时间,单位为秒工作:性能NGINX 日志

提醒指标: 请求处理时间

请求处理时间指标记录了 NGINX 处理每个请求的时间,从读到客户端的第一个请求字节到完成请求。较长的响应时间说明问题在上游。

收集处理时间指标

NGINX 和 NGINX Plus 用户可以通过添加 $request\_time 变量到访问日志格式中来捕​​捉处理时间数据。关于配置日志监控的更多细节在NGINX指标收集

反向代理指标

名称描述指标类型可用于
上游服务器的活跃链接当前活跃的客户端连接资源:功能NGINX Plus
上游服务器的 5xx 错误代码服务器错误工作:错误NGINX Plus
每个上游组的可用服务器服务器传递健康检查资源:可用性NGINX Plus

反向代理是 NGINX 最常见的使用方法之一。商业支持的 NGINX Plus 显示了大量有关后端(或“上游 upstream”)的服务器指标,这些与反向代理设置相关的。本节重点介绍了几个 NGINX Plus 用户可用的关键上游指标。

NGINX Plus 首先将它的上游指标按组分开,然后是针对单个服务器的。因此,例如,你的反向代理将请求分配到五个上游的 Web 服务器上,你可以一眼看出是否有单个服务器压力过大,也可以看出上游组中服务器的健康状况,以确保良好的响应时间。

活跃指标

每上游服务器的活跃连接的数量可以帮助你确认反向代理是否正确的分配工作到你的整个服务器组上。如果你正在使用 NGINX 作为负载均衡器,任何一台服务器处理的连接数的明显偏差都可能表明服务器正在努力消化请求,或者是你配置使用的负载均衡的方法(例如round-robin 或 IP hashing)不是最适合你流量模式的。

错误指标

错误指标,上面所说的高于5XX(服务器错误)状态码,是监控指标中有价值的一个,尤其是响应码部分。 NGINX Plus 允许你轻松地提取每个上游服务器的 5xx 错误代码的数量,以及响应的总数量,以此来确定某个特定服务器的错误率。

可用性指标

对于 web 服务器的运行状况,还有另一种角度,NGINX 可以通过每个组中当前可用服务器的总量很方便监控你的上游组的健康。在一个大的反向代理上,你可能不会非常关心其中一个服务器的当前状态,就像你只要有可用的服务器组能够处理当前的负载就行了。但监视上游组内的所有工作的服务器总量可为判断 Web 服务器的健康状况提供一个更高层面的视角。

收集上游指标

NGINX Plus 上游指标显示在内部 NGINX Plus 的监控仪表盘上,并且也可通过一个JSON 接口来服务于各种外部监控平台。在我们的相关文章“NGINX指标收集”中有个例子。

结论

在这篇文章中,我们已经谈到了一些有用的指标,你可以使用表格来监控 NGINX 服务器。如果你是刚开始使用 NGINX,监控下面提供的大部分或全部指标,可以让你很好的了解你的网络基础设施的健康和活跃程度:

最终,你会学到更多,更专业的衡量指标,尤其是关于你自己基础设施和使用情况的。当然,监控哪一项指标将取决于你可用的工具。参见相关的文章来逐步指导你的指标收集,不管你使用 NGINX 还是 NGINX Plus。

在 Datadog 中,我们已经集成了 NGINX 和 NGINX Plus,这样你就可以以最少的设置来收集和监控所有 Web 服务器的指标。 在本文中了解如何用 NGINX Datadog来监控,并开始免费试用 Datadog吧。

诚谢

在文章发表之前非常感谢 NGINX 团队审阅这篇,并提供重要的反馈和说明。


via: https://www.datadoghq.com/blog/how-to-monitor-nginx/

作者:K Young 译者:strugglingyouth 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

今天,我们将学习如何快速地对docker容器进行快捷备份、恢复和迁移。Docker是一个开源平台,用于自动化部署应用,以通过快捷的途径在称之为容器的轻量级软件层下打包、发布和运行这些应用。它使得应用平台独立,因为它扮演了Linux上一个额外的操作系统级虚拟化的自动化抽象层。它通过其组件cgroups和命名空间利用Linux内核的资源分离特性,达到避免虚拟机开销的目的。它使得用于部署和扩展web应用、数据库和后端服务的大规模构建组件无需依赖于特定的堆栈或供应者。

所谓的容器,就是那些创建自Docker镜像的软件层,它包含了独立的Linux文件系统和开箱即用的应用程序。如果我们有一个在机器中运行着的Docker容器,并且想要备份这些容器以便今后使用,或者想要迁移这些容器,那么,本教程将帮助你掌握在Linux操作系统中备份、恢复和迁移Docker容器的方法。

我们怎样才能在Linux中备份、恢复和迁移Docker容器呢?这里为您提供了一些便捷的步骤。

1. 备份容器

首先,为了备份Docker中的容器,我们会想看看我们想要备份的容器列表。要达成该目的,我们需要在我们运行着Docker引擎,并已创建了容器的Linux机器中运行 docker ps 命令。

# docker ps

Docker Containers List

在此之后,我们要选择我们想要备份的容器,然后去创建该容器的快照。我们可以使用 docker commit 命令来创建快照。

# docker commit -p 30b8f18f20b4 container-backup

Docker Commit

该命令会生成一个作为Docker镜像的容器快照,我们可以通过运行 docker images 命令来查看Docker镜像,如下。

# docker images

Docker Images

正如我们所看见的,上面做的快照已经作为Docker镜像保存了。现在,为了备份该快照,我们有两个选择,一个是我们可以登录进Docker注册中心,并推送该镜像;另一个是我们可以将Docker镜像打包成tar包备份,以供今后使用。

如果我们想要在Docker注册中心上传或备份镜像,我们只需要运行 docker login 命令来登录进Docker注册中心,然后推送所需的镜像即可。

# docker login

Docker Login

# docker tag a25ddfec4d2a arunpyasi/container-backup:test
# docker push arunpyasi/container-backup

Docker Push

如果我们不想备份到docker注册中心,而是想要将此镜像保存在本地机器中,以供日后使用,那么我们可以将其作为tar包备份。要完成该操作,我们需要运行以下 docker save 命令。

# docker save -o ~/container-backup.tar container-backup

taking tarball backup

要验证tar包是否已经生成,我们只需要在保存tar包的目录中运行 ls 命令即可。

2. 恢复容器

接下来,在我们成功备份了我们的Docker容器后,我们现在来恢复这些制作了Docker镜像快照的容器。如果我们已经在注册中心推送了这些Docker镜像,那么我们仅仅需要把那个Docker镜像拖回并直接运行即可。

# docker pull arunpyasi/container-backup:test

Docker Pull

但是,如果我们将这些Docker镜像作为tar包文件备份到了本地,那么我们只要使用 docker load 命令,后面加上tar包的备份路径,就可以加载该Docker镜像了。

# docker load -i ~/container-backup.tar

现在,为了确保这些Docker镜像已经加载成功,我们来运行 docker images 命令。

# docker images

在镜像被加载后,我们将用加载的镜像去运行Docker容器。

# docker run -d -p 80:80 container-backup

Restoring Docker Tarball

3. 迁移Docker容器

迁移容器同时涉及到了上面两个操作,备份和恢复。我们可以将任何一个Docker容器从一台机器迁移到另一台机器。在迁移过程中,首先我们将把容器备份为Docker镜像快照。然后,该Docker镜像或者是被推送到了Docker注册中心,或者被作为tar包文件保存到了本地。如果我们将镜像推送到了Docker注册中心,我们简单地从任何我们想要的机器上使用 docker run 命令来恢复并运行该容器。但是,如果我们将镜像打包成tar包备份到了本地,我们只需要拷贝或移动该镜像到我们想要的机器上,加载该镜像并运行需要的容器即可。

尾声

最后,我们已经学习了如何快速地备份、恢复和迁移Docker容器,本教程适用于各个可以成功运行Docker的操作系统平台。真的,Docker是一个相当简单易用,然而功能却十分强大的工具。它的命令相当易记,这些命令都非常短,带有许多简单而强大的标记和参数。上面的方法让我们备份容器时很是安逸,使得我们可以在日后很轻松地恢复它们。这会帮助我们恢复我们的容器和镜像,即便主机系统崩溃,甚至意外地被清除。如果你还有很多问题、建议、反馈,请在下面的评论框中写出来吧,可以帮助我们改进或更新我们的内容。谢谢大家!享受吧 :-)


via: http://linoxide.com/linux-how-to/backup-restore-migrate-containers-docker/

作者:Arun Pyasi 译者:GOLinux 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

用正则表达式验证邮件地址似乎是一件简单的事情,但是如果要完美的验证一个合规的邮件地址,其实也许很复杂。

邮件地址的规范来自于 RFC 5322 。有一个网站 emailregex.com 专门列出各种编程语言下的验证邮件地址的正则表达式,其中很多正则表达式都是我听说过而从未见过的复杂——我想说,做这个网站的程序员是被邮件验证这件事伤害了多深啊!

其实,在产品环境中,一般来说并不需要这么复杂的正则表达式来做到99.99%正确。一般来说,从执行效率和测试覆盖率来说,只需要一个简单的版本即可:

/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i

那么下面我们来看看这些更严谨、更复杂的正则表达式吧:

验证邮件地址的通用正则表达式(符合 RFC 5322 标准)

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

由于各种语言对正则表达式的支持不同、语法差异和覆盖率不同,所以,不同语言里面的正则表达式也不同:

Python

这个是个简单的版本:

r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"

Javascript

这个有点复杂了:

/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i

Swift

[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}

PHP

PHP 的这个版本就更复杂了,覆盖率就更大一些:

/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\]))$/iD

Perl / Ruby

对与 PHP 的版本,Perl 和 Ruby 表示不服,可以更严谨:

(?:(?:
)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[\t]))*"(?:(?:
)?[ \t])*))*@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)*\<(?:(?:
)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[\t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*(?:,@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[\t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*)*:(?:(?:
)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*))*@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*\>(?:(?:
)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)*:(?:(?:
)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\]\000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*))*@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)*\<(?:(?:
)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*(?:,@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\]\000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*)*:(?:(?:
)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*))*@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*\>(?:(?:
)?[ \t])*)(?:,\s*(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*))*@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)*\<(?:(?:
)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*(?:,@(?:(?:
)?[\t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*)*:(?:(?:
)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:
)?[ \t]))*"(?:(?:
)?[ \t])*))*@(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*)(?:\.(?:(?:
)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
)?[ \t])*))*\>(?:(?:
)?[ \t])*))*)?;\s

Perl 5.10 及以后版本

上面的版本,嗯,我可以说是天书吗?反正我是没有解读的想法了。当然,新版本的 Perl 语言还有一个更易读的版本(你是说真的么?)

/(?(DEFINE)
(?<address> (?&mailbox) | (?&group))
(?<mailbox> (?&name_addr) | (?&addr_spec))
(?<name_addr> (?&display_name)? (?&angle_addr))
(?<angle_addr> (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
(?<group> (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ;
(?&CFWS)?)
(?<display_name> (?&phrase))
(?<mailbox_list> (?&mailbox) (?: , (?&mailbox))*)

(?<addr_spec> (?&local_part) \@ (?&domain))
(?<local_part> (?&dot_atom) | (?&quoted_string))
(?<domain> (?&dot_atom) | (?&domain_literal))
(?<domain_literal> (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
\] (?&CFWS)?)
(?<dcontent> (?&dtext) | (?&quoted_pair))
(?<dtext> (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

(?<atext> (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
(?<atom> (?&CFWS)? (?&atext)+ (?&CFWS)?)
(?<dot_atom> (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
(?<dot_atom_text> (?&atext)+ (?: \. (?&atext)+)*)

(?<text> [\x01-\x09\x0b\x0c\x0e-\x7f])
(?<quoted_pair> \\ (?&text))

(?<qtext> (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
(?<qcontent> (?&qtext) | (?&quoted_pair))
(?<quoted_string> (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
(?&FWS)? (?&DQUOTE) (?&CFWS)?)

(?<word> (?&atom) | (?&quoted_string))
(?<phrase> (?&word)+)

# Folding white space
(?<FWS> (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
(?<ctext> (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
(?<ccontent> (?&ctext) | (?&quoted_pair) | (?&comment))
(?<comment> \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
(?<CFWS> (?: (?&FWS)? (?&comment))*
(?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

# No whitespace control
(?<NO_WS_CTL> [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

(?<ALPHA> [A-Za-z])
(?<DIGIT> [0-9])
(?<CRLF> \x0d \x0a)
(?<DQUOTE> ")
(?<WSP> [\x20\x09])
)

(?&address)/x

Ruby (简单版)

Ruby 表示,其实人家还有个简单版本:

/\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i

.NET

这样的版本谁没有啊——.NET 说:

^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

grep 命令

用 grep 命令在文件中查找邮件地址,我想你不会写个若干行的正则表达式吧,意思一下就行了:

$ grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" filename.txt

SQL Server

在 SQL Server 中也是可以用正则表达式的,不过这个代码片段应该是来自某个产品环境中的,所以,还体贴的照顾了那些把邮件地址写错的人:

 select email 
 from table_name where 
 patindex ('%[ &'',":;!+=\/()<>]%', email) > 0 -- Invalid characters
 or patindex ('[@.-_]%', email) > 0 -- Valid but cannot be starting character
 or patindex ('%[@.-_]', email) > 0 -- Valid but cannot be ending character
 or email not like '%@%.%' -- Must contain at least one @ and one .
 or email like '%..%' -- Cannot have two periods in a row
 or email like '%@%@%' -- Cannot have two @ anywhere
 or email like '%.@%' or email like '%@.%' -- Cannot have @ and . next to each other
 or email like '%.cm' or email like '%.co' -- Camaroon or Colombia? Typos. 
 or email like '%.or' or email like '%.ne' -- Missing last letter

Oracle PL/SQL

这个是不是有点偷懒?尤其是在那些“复杂”的正则表达式之后:

SELECT email 
FROM table_name
WHERE REGEXP_LIKE (email, '[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,4}');

MySQL

好吧,看来最后也一样懒:

SELECT * FROM `users` WHERE `email` NOT REGEXP '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$';

那么,你有没有关于验证邮件地址的正则表达式分享给大家?

在我们之前的文章中,我们介绍了什么是 LVM 以及能用 LVM 做什么,今天我们会给你介绍一些 LVM 的主要管理工具,使得你在设置和扩展安装时更游刃有余。

正如之前所述,LVM 是介于你的操作系统和物理硬盘驱动器之间的抽象层。这意味着你的物理硬盘驱动器和分区不再依赖于他们所在的硬盘驱动和分区。而是你的操作系统所见的硬盘驱动和分区可以是由任意数目的独立硬盘汇集而成的或是一个软件磁盘阵列。

要管理 LVM,这里有很多可用的 GUI 工具,但要真正理解 LVM 配置发生的事情,最好要知道一些命令行工具。这当你在一个服务器或不提供 GUI 工具的发行版上管理 LVM 时尤为有用。

LVM 的大部分命令和彼此都非常相似。每个可用的命令都由以下其中之一开头:

  • Physical Volume (物理卷) = pv
  • Volume Group (卷组)= vg
  • Logical Volume (逻辑卷)= lv

物理卷命令用于在卷组中添加或删除硬盘驱动。卷组命令用于为你的逻辑卷操作更改显示的物理分区抽象集。逻辑卷命令会以分区形式显示卷组,使得你的操作系统能使用指定的空间。

可下载的 LVM 备忘单

为了帮助你理解每个前缀可用的命令,我们制作了一个备忘单。我们会在该文章中介绍一些命令,但仍有很多你可用但没有介绍到的命令。

该列表中的所有命令都要以 root 身份运行,因为你更改的是会影响整个机器系统级设置。

如何查看当前 LVM 信息

你首先需要做的事情是检查你的 LVM 设置。s 和 display 命令可以和物理卷(pv)、卷组(vg)以及逻辑卷(lv)一起使用,是一个找出当前设置的好起点。

display 命令会格式化输出信息,因此比 s 命令更易于理解。对每个命令你会看到名称和 pv/vg 的路径,它还会给出空闲和已使用空间的信息。

最重要的信息是 PV 名称和 VG 名称。用这两部分信息我们可以继续进行 LVM 设置。

创建一个逻辑卷

逻辑卷是你的操作系统在 LVM 中使用的分区。创建一个逻辑卷,首先需要拥有一个物理卷和卷组。下面是创建一个新的逻辑卷所需要的全部命令。

创建物理卷

我们会从一个全新的没有任何分区和信息的硬盘开始。首先找出你将要使用的磁盘。(/dev/sda, sdb, 等)

注意:记住所有的命令都要以 root 身份运行或者在命令前面添加 'sudo' 。
fdisk -l

如果之前你的硬盘从未格式化或分区过,在 fdisk 的输出中你很可能看到类似下面的信息。这完全正常,因为我们会在下面的步骤中创建需要的分区。

我们的新磁盘位置是 /dev/sdb,让我们用 fdisk 命令在磁盘上创建一个新的分区。

这里有大量能创建新分区的 GUI 工具,包括 Gparted,但由于我们已经打开了终端,我们将使用 fdisk 命令创建需要的分区。

在终端中输入以下命令:

fdisk /dev/sdb

这会使你进入到一个特殊的 fdisk 提示符中。

以指定的顺序输入命令创建一个使用新硬盘 100% 空间的主分区并为 LVM 做好了准备。如果你需要更改分区的大小或想要多个分区,我建议使用 GParted 或自己了解一下关于 fdisk 命令的使用。

警告:下面的步骤会格式化你的硬盘驱动。确保在进行下面步骤之前你的硬盘驱动中没有任何有用的信息。

  • n = 创建新分区
  • p = 创建主分区
  • 1 = 成为磁盘上的首个分区

输入 enter 键两次以接受默认的第一个和最后一个柱面。

用下面的命令准备 LVM 所使用的分区。

  • t = 更改分区类型
  • 8e = 更改为 LVM 分区类型

核实并将信息写入硬盘。

  • p = 查看分区设置使得在写入更改到磁盘之前可以回看
  • w = 写入更改到磁盘

运行这些命令之后,会退出 fdisk 提示符并返回到终端的 bash 提示符中。

输入 pvcreate /dev/sdb1 在刚创建的分区上新建一个 LVM 物理卷。

你也许会问为什么我们不用一个文件系统格式化分区,不用担心,该步骤在后面。

创建卷组

现在我们有了一个指定的分区和创建好的物理卷,我们需要创建一个卷组。很幸运这只需要一个命令。

vgcreate vgpool /dev/sdb1

vgpool 是新创建的卷组的名称。你可以使用任何你喜欢的名称,但建议标签以 vg 开头,以便后面你使用它时能意识到这是一个卷组。

创建逻辑卷

创建 LVM 将使用的逻辑卷:

lvcreate -L 3G -n lvstuff vgpool

-L 命令指定逻辑卷的大小,在该情况中是 3 GB,-n 命令指定卷的名称。 指定 vgpool 以便 lvcreate 命令知道从什么卷获取空间。

格式化并挂载逻辑卷

最后一步是用一个文件系统格式化新的逻辑卷。如果你需要选择一个 Linux 文件系统的帮助,请阅读 如果根据需要选取最合适的文件系统

mkfs -t ext3 /dev/vgpool/lvstuff

创建挂载点并将卷挂载到你可以使用的地方。

mkdir /mnt/stuff
mount -t ext3 /dev/vgpool/lvstuff /mnt/stuff

重新设置逻辑卷大小

逻辑卷的一个好处是你能使你的存储物理地变大或变小,而不需要移动所有东西到一个更大的硬盘。另外,你可以添加新的硬盘并同时扩展你的卷组。或者如果你有一个不使用的硬盘,你可以从卷组中移除它使得逻辑卷变小。

这里有三个用于使物理卷、卷组和逻辑卷变大或变小的基础工具。

注意:这些命令中的每个都要以 pv、vg 或 lv 开头,取决于你的工作对象。

  • resize – 能压缩或扩展物理卷和逻辑卷,但卷组不能
  • extend – 能使卷组和逻辑卷变大但不能变小
  • reduce – 能使卷组和逻辑卷变小但不能变大

让我们来看一个如何向刚创建的逻辑卷 "lvstuff" 添加新硬盘驱动的例子。

安装并格式化新硬盘驱动

按照上面创建新分区并更改分区类型为 LVM(8e) 的步骤安装一个新硬盘驱动。然后用 pvcreate 命令创建一个 LVM 能识别的物理卷。

添加新硬盘到卷组

要添加新的硬盘到一个卷组,你只需要知道你的新分区,在我们的例子中是 /dev/sdc1,以及想要添加到的卷组的名称。

这会添加新物理卷到已存在的卷组中。

vgextend vgpool /dev/sdc1

扩展逻辑卷

调整逻辑卷的大小,我们需要指出的是通过大小而不是设备来扩展。在我们的例子中,我们会添加一个 8GB 的硬盘驱动到我们的 3GB vgpool。我们可以用 lvextend 或 lvresize 命令使该空间可用。

lvextend -L8G /dev/vgpool/lvstuff

当这个命令工作的时候你会发现它实际上重新设置逻辑卷大小为 8GB 而不是我们期望的将 8GB 添加到已存在的卷上。要添加剩余的可用 3GB 你需要用下面的命令。

lvextend -L+3G /dev/vgpool/lvstuff

现在我们的逻辑卷已经是 11GB 大小了。

扩展文件系统

逻辑卷是 11GB 大小但是上面的文件系统仍然只有 3GB。要使文件系统使用整个的 11GB 可用空间你需要用 resize2fs 命令。你只需要指定 resize2fs 到 11GB 逻辑卷它就会帮你完成其余的工作。

resize2fs /dev/vgpool/lvstuff

注意:如果你使用除 ext3/4 之外的文件系统,请查看调整你的文件系统大小的工具。

压缩逻辑卷

如果你想从卷组中移除一个硬盘驱动你可以按照上面的步骤反向操作,并用 lvreduce 或 vgreduce 命令代替。

  1. 调整文件系统大小 (调整之前确保已经移动文件到硬盘驱动安全的地方)
  2. 减小逻辑卷 (除了 + 可以扩展大小,你也可以用 - 压缩大小)
  3. 用 vgreduce 从卷组中移除硬盘

备份逻辑卷

快照是一些新的高级文件系统提供的功能,但是 ext3/4 文件系统并没有快照的功能。LVM 快照最棒的是你的文件系统永不掉线,你可以拥有你想要的任何大小而不需要额外的硬盘空间。

LVM 获取快照的时候,会有一张和逻辑卷完全相同的“照片”,该“照片”可以用于在不同的硬盘上进行备份。生成一个备份的时候,任何需要添加到逻辑卷的新信息会如往常一样写入磁盘,但会跟踪更改使得原始快照永远不会损毁。

要创建一个快照,我们需要创建拥有足够空闲空间的逻辑卷,用于保存我们备份的时候会写入该逻辑卷的任何新信息。如果驱动并不是经常写入,你可以使用很小的一个存储空间。备份完成的时候我们只需要移除临时逻辑卷,原始逻辑卷会和往常一样。

创建新快照

创建 lvstuff 的快照,用带 -s 标记的 lvcreate 命令。

lvcreate -L512M -s -n lvstuffbackup /dev/vgpool/lvstuff

这里我们创建了一个只有 512MB 的逻辑卷,因为该硬盘实际上并不会使用。512MB 的空间会保存备份时产生的任何新数据。

挂载新快照

和之前一样,我们需要创建一个挂载点并挂载新快照,然后才能从中复制文件。

mkdir /mnt/lvstuffbackup
mount /dev/vgpool/lvstuffbackup /mnt/lvstuffbackup

复制快照和删除逻辑卷

你剩下需要做的是从 /mnt/lvstuffbackup/ 中复制所有文件到一个外部的硬盘或者打包所有文件到一个文件。

注意:tar -c 会创建一个归档文件,-f 要指出归档文件的名称和路径。要获取 tar 命令的帮助信息,可以在终端中输入 man tar。

tar -cf /home/rothgar/Backup/lvstuff-ss /mnt/lvstuffbackup/

记住备份时候写到 lvstuff 的所有文件都会在我们之前创建的临时逻辑卷中被跟踪。确保备份的时候你有足够的空闲空间。

备份完成后,卸载卷并移除临时快照。

umount /mnt/lvstuffbackup
lvremove /dev/vgpool/lvstuffbackup/

删除逻辑卷

要删除一个逻辑卷,你首先需要确保卷已经卸载,然后你可以用 lvremove 命令删除它。逻辑卷删除后你可以移除卷组,卷组删除后你可以删除物理卷。

这是所有移除我们创建的卷和组的命令。

umount /mnt/lvstuff
lvremove /dev/vgpool/lvstuff
vgremove vgpool
pvremove /dev/sdb1 /dev/sdc1

这些已经囊括了关于 LVM 你需要了解的大部分知识。如果你有任何关于这些讨论的经验,请在下面的评论框中和大家分享。


via: http://www.howtogeek.com/howto/40702/how-to-manage-and-use-lvm-logical-volume-management-in-ubuntu/

译者:ictlyh 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

逻辑分区管理(LVM)是每一个主流Linux发行版都含有的磁盘管理选项。无论是你需要设置存储池,还是只想动态创建分区,那么LVM就是你正在寻找的。

什么是 LVM?

逻辑分区管理是一个存在于磁盘/分区和操作系统之间的一个抽象层。在传统的磁盘管理中,你的操作系统寻找有哪些磁盘可用(/dev/sda、/dev/sdb等等),并且这些磁盘有哪些可用的分区(如/dev/sda1、/dev/sda2等等)。

在LVM下,磁盘和分区可以抽象成一个含有多个磁盘和分区的设备。你的操作系统将不会知道这些区别,因为LVM只会给操作系统展示你设置的卷组(磁盘)和逻辑卷(分区)

因为卷组和逻辑卷并不物理地对应到影片,因此可以很容易地动态调整和创建新的磁盘和分区。除此之外,LVM带来了你的文件系统所不具备的功能。比如,ext3不支持实时快照,但是如果你正在使用LVM你可以不卸载磁盘的情况下做一个逻辑卷的快照。

你什么时候该使用LVM?

在使用LVM之前首先得考虑的一件事是你要用你的磁盘和分区来做什么。注意,一些发行版如Fedora已经默认安装了LVM。

如果你使用的是一台只有一块磁盘的Ubuntu笔记本电脑,并且你不需要像实时快照这样的扩展功能,那么你或许不需要LVM。如果你想要轻松地扩展或者想要将多块磁盘组成一个存储池,那么LVM或许正是你所寻找的。

在Ubuntu中设置LVM

使用LVM首先要了解的一件事是,没有一个简单的方法可以将已有的传统分区转换成逻辑卷。可以将数据移到一个使用LVM的新分区下,但是这并不会在本篇中提到;在这里,我们将全新安装一台Ubuntu 10.10来设置LVM。(LCTT 译注:本文针对的是较老的版本,新的版本已经不需如此麻烦了)

要使用LVM安装Ubuntu你需要使用另外的安装CD。从下面的链接中下载并烧录到CD中或者使用unetbootin创建一个USB盘

从安装盘启动你的电脑,并在磁盘选择界面选择整个磁盘并设置LVM。

注意:这会格式化你的整个磁盘,因此如果正在尝试双启动或者其他的安装选择,选择手动。

选择你想用的主磁盘,最典型的是使用你最大的磁盘,接着进入下一步。

你马上会将改变写入磁盘所以确保此时你选择的是正确的磁盘接着才写入设置。

选择第一个逻辑卷的大小并继续。

确认你的磁盘分区并继续安装。

最后一步将GRUB的bootloader写到磁盘中。重点注意的是GRUB不能作为一个LVM分区因为计算机BIOS不能直接从逻辑卷中读取数据。Ubuntu将自动创建一个255MB的ext2分区用于bootloder。

安装完成之后。重启电脑并如往常一样进入Ubuntu。使用这种方式安装之后应该就感受不到LVM和传统磁盘管理之间的区别了。

要使用LVM的全部功能,静待我们的下篇关于管理LVM的文章。


via: http://www.howtogeek.com/howto/36568/what-is-logical-volume-management-and-how-do-you-enable-it-in-ubuntu/

作者:How-To Geek 译者:geekpi 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出