九款开源或商业的数据中心基础设施管理软件

xcat呢！

学习了，运维道路还挺漫长的！

当一个公司发展壮大时，相应地对计算资源的需求也会与日俱增。无论是普通公司还是服务提供商，包括那些出租服务器的公司，当服务器数量过多时都不得不面对很多问题。

如何盘存服务器和备件？如何维护使数据中心保持健康运作，及时定位并修复潜在的威胁？如何快速找到宕机设备的机架位置？如何准备物理机上线工作？做完这些事情需要花费大量的时间，或者需要 IT 部门有一大帮管理员支持才能办到。

现在有一个更好的方案解决这些问题，使用特定软件来实现数据中心管理自动化，下文将介绍当前市场上已有的一些数据中心管理工具。

![](/data/attachment/album/201701/04/165459qyroddxoeq79za7d.jpg)

### 1、 Opendcim

这是该类目前唯一的自由软件，该软件开源并且按照商业化<ruby> 数据中心基础设施管理 <rt>  Data Center Infrastructure Management </rt></ruby>（DCIM）解决方案的替代方案来设计。该软件可以管理库存、生成数据中心的地图和监控机房温度与电力消耗。

不过，它不支持远程关机、服务器重启、操作系统安装等功能。尽管如此，它仍然被全球很多非商业机构使用。

由于该软件开源，有研发能力的公司可以修改它，使 [opendcim](http://opendcim.org/) 更适合自己的公司。

![openDCIM](/data/attachment/album/201701/04/165509p02ala01zdjdoaba.png)

*openDCIM*

### 2、 NOC-PS

这是一款可以管理物理和虚拟设备的商业软件。它有很多可以用于初始化设备的工具，比如：操作系统和其他软件安装、网络配置，并且集成了 WHMCS 和 Blesta。美中不足的是，如果你希望能够看到数据中心设备地图或者机架位置，那该软件就不是你的最佳选择了。

[NOC-PS](http://noc-ps.com/) 每 100 台服务器每年管理费需要 100€，比较适合中小企业使用。

![NOC-PS](/data/attachment/album/201701/04/165511fo2b3o833k794i3b.png)

*NOC-PS*

### 3、 DCImanager

[DCImanager](https://www.ispsystem.com/software/dcimanager) 是一个专用的解决方案，正如宣传所说的，考虑了 DC 工程师和托管服务提供商的需求。该软件集成了很多有名的计费软件，比如 WHMCS、Hostbill、BILLmanager 等。

该软件的主要功能有：服务器配置、模板化安装操作系统、传感器监控、流量和电力消耗报告、VLAN 管理。除此之外，企业版还可以生成数据中心服务器地图、以及对服务器和备件进行盘点管理。

你可以试用免费版，但是免费版最多支持 5 台物理服务器管理，而收费版每 100 台服务器每年的授权使用费是 120€。

根据版本不同，收费版可适用中小企业或者大企业。

![DCImanager](/data/attachment/album/201701/04/165513hl3p1lj5lm6ieeie.png)

*DCImanager*

### 4、 EasyDCIM

[EasyDCIM](https://www.easydcim.com/) 是一款主要面向服务提供商的收费软件。拥有可以安装操作系统或其他软件的特点，并且能方便地生成机房目录及机架分布图。

该软件本身并不支持对 IP 和 DNS 进行管理。不过可以通过安装模块的方式获得这些功能，这些模块可能付费或者免费（包括 WHMCS 集成模块）。

该软件每 100 台服务器每年的服务费起步价 $999。对于小公司来说这个价格有点贵，不过中型或者大型企业可以尝试使用。

![EasyDCIM](/data/attachment/album/201701/04/165518vp0j6pj1eh4em6z1.png)

*EasyDCIM*

### 5、 Ansible Tower

[Ansible Tower](https://www.ansible.com/) 是红帽出品的企业级计算中心管理软件。该解决方案的核心思想是实现对服务器和不同用户设备的集中式部署。

由于 **Ansible Tower** 能够通过集成软件的方式使用几乎所有的工具程序，并且该软件的数据统计收集模块特别好用。不好的一面则是缺乏和当前比较流行的计费软件的集成，而且价格也不便宜。

每 100 台设备每年的服务器费是 $5000,这个价格估计只有大公司才能接受。

![Ansible Tower](/data/attachment/album/201701/04/165519uouftdoi3uuv24nt.png)

*Ansible Tower*

### 6、 Puppet Enterprise

在商业基础上发展而来并作为 IT 部门的辅助软件。该软件用于在服务器或者用户设备上安装操作系统及其他软件，无论是初步部署或者进一步开发都适用。

不幸的是，盘存和其他更好的交互方案(电缆连接、协议等)仍然处于开发中。

[Puppet Enterprise](https://puppet.com/) 对于小于 10 台服务器的管理免费并且开放全部功能。而收费版则是每台服务器每年 $120。

这个价格适合大公司使用。

![Puppet Enterprise](/data/attachment/album/201701/04/165523vkzom1nke4ow4deo.png)

*Puppet Enterprise*

### 7、 Device 42

该软件主要用于数据中心监控。有一个很棒的盘存工具，自动创建软硬件依赖关系图。通过 [Device 42](http://www.device42.com/) 生成数据中心地图，给不同机架标特定颜色，并可以通过图表方式反映温度、空闲空间情况和机架的其他指标。但是不支持软件安装和计费软件的集成。

每 100 台服务器每年的收费是 $1499，这个价位比较适合大中型企业。

![Device42](/data/attachment/album/201701/04/165525vcw7e44449bwgv8b.png)

*Device42*

### 8、 CenterOS

这是一款适合数据中心管理的操作系统，主要功能是设备盘点。除此之外可以生成数据中心地图及机架方案，并连接了一个评价不错的服务器状态监控系统，方便内部技术管理工作。

该软件还有一个特性就是能够通过简单的几次点击就可以找到某个设备对应的人（可能是设备所有人、技术管理员或者该设备的制造商），当出现紧急问题时这个就特别有用了。

该软件不是开源的，并且价格也只能在咨询后才能知道。

该软件价格的神秘性也决定了软件的目标客户，极有可能这个软件是给大公司用的。

![CenterOS](/data/attachment/album/201701/04/165529tvrb2q62r26t2ybr.png)

*CenterOS*

### 9、 LinMin

这是一款用于初始化物理设备以便后期使用的软件。使用 PXE 安装选定的操作系统，并可随后部署一系列必要的软件安装。

与同类软件不同的是，[LinMin](http://www.linmin.com/) 有一个开发完善的硬盘备份系统，可以迅速在系统崩溃后恢复以及大规模部署相同配置的服务器。

该软件每 100 台服务器一年的收费是 $1999，这价格也只有大中型企业能用了。

![LinMin](/data/attachment/album/201701/04/165531ni0sslgn7rleg7fv.jpg)

*LinMin*

现在来总结下，当前市场上大部分能够自动化管理大量的基础设施的软件，可以分为两类。

第一类，主要用于完成设备的准备工作，以便能够进一步管理。另一类就是设备的盘点管理。找到一个通用的包含所有功能的软件并不容易，你在选择的时候可以放弃一些设备提供商提供的那些功能比较有限的工具。

现在你知道了这些解决方案，那么你可以逐个尝试下。值得注意的是这里列出的开源产品，如果你有好的开发人员，那么可以尝试定制软件来满足你需求。

希望通过这篇回顾能够帮你找到适合的软件让你的工作更轻松。另，祝您的服务器永不出错。

---

作者简介：

![](/data/attachment/album/201701/04/165532p666jtgqrtsq7rvr.jpg)

Nikita Nesmiyanov

我是一名俄罗斯西伯利亚托管软件开发公司的技术专家。我希望能够在新的 Linux 软件工具和托管行业的发展趋势、可能性、发展历史和发展机遇等方面拓展我的知识。

---

via: <http://www.tecmint.com/data-center-server-management-tools/>

作者：[Nikita Nesmiyanov](http://www.tecmint.com/author/nesmiyanov/) 译者：[beyondworld](https://github.com/beyondworld) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Android、Debian 和 Ubuntu “荣膺”2016 安全缺陷最多的产品前三名

Summary: 据 CVE Details 的数据显示，Android、Debian Linux 和 Ubuntu Linux 是 2016 年出现安全缺陷最多的三个产品。

有洞不可怕，可怕的是明知有洞，确不及时补，应该在表格加1列，叫“平均补丁时间”……

改版之后，这个网站变得好黄好暴力

哈哈哈

你是在说 Android 吗?

哈哈，好像是哦

此言大赞！

比windows漏洞少的还真不少，居然就挑着windows来讲，呵呵

我就喜欢用这么多爆出漏洞的Debian Gnu/Linux，总比那种被植入了官马的不告诉你有漏洞的系统好一点点

来自陕西西安的 Chrome Mobile 55.0|Android 6.0 用户

感谢自由软件让我知道了系统原来有这么多漏洞，并给出了修补措施

windows 10 才出来多久？就有这么多，而且ｗｉｎｄｏｗｓ７都出来这么久了，还有这么多漏洞．你能说它比linux或者安卓安全？

没错，所以这个榜单看怎么解读了。

用的多了， 漏洞自然就有更多的人去发现

可不可以少用点反差很大的对比色，这样感觉眼睛累，回复卡片试试用不同程度的灰色或者浅蓝色比较舒服。虽然出来的效果会很“性冷淡”。

还不错

能力越大，责任越大；用得越多，错误越多……

一直觉得这个网站UI做的好差滴

![](/data/attachment/album/201701/05/011411t8lmtjo7vdhnhvvl.jpg)

[据 CVE Details 的数据显示](https://www.cvedetails.com/top-50-products.php?year=2016)，Android、Debian Linux 和 Ubuntu Linux 是 2016 年出现安全缺陷最多的三个产品。[CVE Details](https://www.cvedetails.com/) 是一个收集和存储软件安全缺陷方面的在线数据库。

![](/data/attachment/album/201701/05/003636gsnegppn5ntwesm5.jpg)

*2016 年安全缺陷榜单*

在这一年中， Android 被发现了最多的安全缺陷，多达 523 个，紧随其后的是 Debian Linux 的 319 个和 Ubuntu Linux 的 278 个。令人吃惊的是，曾经多次蝉联第一名“宝座”的安全缺陷大户 Adobe Flash Player 以 266 个缺陷“屈居”第四。

“冠军” [Android 的安全缺陷](https://www.cvedetails.com/product/19997/Google-Android.html?vendor_id=1224)包括了最近大家比较关注的 DoS 缺陷以及内存破坏缺陷，而且，DoS 缺陷数量从 2015 的 56 个跃升至 104 个，而内存破坏缺陷则从 46 个降至 38 个。 Android 中还有 99 个缺陷是关于信息泄露的，而在一年前才发现了 19 个；权限提升缺陷则令人吃惊的从 2015 年的 17 个剧增至 250 个。

![](/data/attachment/album/201701/05/005345j9wucjpc2aijiiu7.jpg)

*Android 的缺陷*

### 微软的缺陷更少一些

让我们来看看微软的产品，在该列表中，排名最高的微软产品是 Windows 10 ，有 172 个缺陷，连前十名都没进去。

如果根据厂商来比较，谷歌的产品缺陷最多，有 695 个，而 Debian 和 Canonical 以 319 和 278 分列二、三名。

![](/data/attachment/album/201701/05/010303dfvng2l62eyil884.jpg)

*厂商缺陷排行榜*

上图中，虽然 Adobe 和微软的安全缺陷总数非常高，但是其实这里包含的安全缺陷很多是重复的——同一个安全缺陷出现在多个产品之中。

当然， 产品的安全缺陷数高也并不意味着该产品就比其它的产品更不安全，许多产品的安全缺陷是私下报告的，并在被公开之前就修复了，所以在大多数情况下使用这些产品是安全的。


在 Ubuntu 中使用 NTP 进行时间同步

Summary: NTP 是通过网络来同步时间的一种 TCP/IP 协议。通常客户端向服务器请求当前的时间，并根据结果来设置其时钟。这个描述是挺简单的，实现这一功能却是极为复杂的，幸运的是，所有的这些复杂性都进行了封装，你是不可见也不需要见到的。

NTP 是通过网络来同步时间的一种 TCP/IP 协议。通常客户端向服务器请求当前的时间，并根据结果来设置其时钟。

这个描述是挺简单的，实现这一功能却是极为复杂的 - 首先要有多层 NTP 服务器，第一层 NTP 服务器连接原子时钟，第二层、第三层服务器则担起负载均衡的责任，以处理因特网传来的所有请求。另外，客户端可能也超乎你想象的复杂 - 它必须排除通讯延迟，调整时间的同时不干扰其它在服务器中运行的进程。幸运的是，所有的这些复杂性都进行了封装，你是不可见也不需要见到的。

![](/data/attachment/album/201701/05/111343e3mf2ahai26iifz9.jpg)

在 Ubuntu 中，是使用 `ntpdate` 和 `ntpd` 来同步时间的。

### timedatectl

在最新的 Ubuntu 版本中，`timedatectl` 替代了老旧的 `ntpdate`。默认情况下，`timedatectl` 在系统启动的时候会立刻同步时间，并在稍后网络连接激活后通过 socket 再次检查一次。

如果已安装了 `ntpdate` / `ntp`，`timedatectl` 会退而让你使用之前的设置。这样确保了两个时间同步服务不会相互冲突，同时在你升级的时候还保留原本的行为和配置。但这也意味着从旧版本的发行版升级时 `ntp`/`ntpdate` 仍会安装，因此会导致新的基于 systemd 的时间服务被禁用。

### timesyncd

在最新的 Ubuntu 版本中，`timesyncd` 替代了 `ntpd` 的客户端的部分。默认情况下 `timesyncd` 会定期检测并同步时间。它还会在本地存储更新的时间，以便在系统重启时做时间单步调整。

通过 `timedatectl` 和 `timesyncd` 设置的当前时间状态和时间配置，可以使用 `timedatectl status` 命令来进行确认。

```
timedatectl status
      Local time: Fri 2016-04-29 06:32:57 UTC
  Universal time: Fri 2016-04-29 06:32:57 UTC
        RTC time: Fri 2016-04-29 07:44:02
       Time zone: Etc/UTC (UTC, +0000)
 Network time on: yes
NTP synchronized: no
 RTC in local TZ: no

```

如果安装了 NTP，并用它替代 `timedatectl` 来同步时间，则 `NTP synchronized` 将被设置为 `yes`。

`timedatectl` 和 `timesyncd` 用来获取时间的 nameserver 可以通过 `/etc/systemd/timesyncd.conf` 来指定，另外在 `/etc/systemd/timesyncd.conf.d/` 下还有灵活的附加配置文件。

### ntpdate

由于 `timedatectl` 的存在，各发行版已经弃用了 `ntpdate`，默认不再进行安装。如果你安装了，它会在系统启动的时候根据 Ubuntu 的 NTP 服务器来设置你电脑的时间。之后每当一个新的网络接口启动时，它就会重新尝试同步时间 —— 在这期间只要其涵盖的时间差不是太大，它就会慢慢偏移时间。该行为可以通过 `-B`/`-b` 开关来进行控制。

```
ntpdate ntp.ubuntu.com

```

### 时间服务器

默认情况下，基于 systemd 的工具都是从 `ntp.ubuntu.com` 请求时间同步的。经典的基于 `ntpd` 的服务基本上都是使用 `[0-3].ubuntu.pool.ntp.org` 池中的 `2.ubuntu.pool.ntp.org`，还有 `ntp.ubuntu.com`，此外需要的话还支持 IPv6。如果想强制使用 IPv6，可以使用 `ipv6.ntp.ubuntu.com`，不过这并非默认配置。

### ntpd

ntp 的守护进程 `ntpd` 会计算你的系统时钟的时间偏移量并且持续的进行调整，所以不会出现时间差距较大的更正，比如说，不会导致不连续的日志。该进程只花费少量的进程资源和内存，但对于现代的服务器来说实在是微不足道的了。

### 安装

要安装 `ntpd`，在终端命令行中输入：

```
sudo apt install ntp

```

### 配置

编辑 `/etc/ntp.conf` —— 增加/移除 `server` 行。默认配置有以下服务器：

```
# Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board
# on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for
# more information.
server 0.ubuntu.pool.ntp.org
server 1.ubuntu.pool.ntp.org
server 2.ubuntu.pool.ntp.org
server 3.ubuntu.pool.ntp.org

```

修改配置文件之后，你需要重新加载 `ntpd`：

```
sudo systemctl reload ntp.service

```

### 查看状态

使用 `ntpq` 来查看更多信息：

```
# sudo ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
+stratum2-2.NTP. 129.70.130.70    2 u    5   64  377   68.461  -44.274 110.334
+ntp2.m-online.n 212.18.1.106     2 u    5   64  377   54.629  -27.318  78.882
*145.253.66.170  .DCFa.           1 u   10   64  377   83.607  -30.159  68.343
+stratum2-3.NTP. 129.70.130.70    2 u    5   64  357   68.795  -68.168 104.612
+europium.canoni 193.79.237.14    2 u   63   64  337   81.534  -67.968  92.792

```

### PPS 支持

从 Ubuntu 16.04 开始，ntp 支持 PPS 规范，给 ntp 提供了本地时间源，以提供更高的精度。查看下边列出的链接来获取更多配置信息。

### 参考资料

* 参考 [Ubuntu Time](https://help.ubuntu.com/community/UbuntuTime) wiki 页来获取更多信息
* [ntp.org，网络时间协议项目主页](http://www.ntp.org/)
* [ntp.org，关于配置 PPS 的 FAQ](http://www.ntp.org/ntpfaq/NTP-s-config-adv.htm#S-CONFIG-ADV-PPS)

---

via: <https://help.ubuntu.com/lts/serverguide/NTP.html>

作者：[Ubuntu](https://help.ubuntu.com/lts/serverguide/NTP.html) 译者：[GHLandy](https://github.com/GHLandy) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 Ubuntu 16.10 的 Unity 8 上运行老式 Xorg 程序

我就说奇怪了，Unity8不加载Intel和AMD的驱动，难怪显示有问题。<br />
而且不优先加载核显驱动，优先加载独立驱动这也太非主流了吧

来自江苏南京的 Internet Explorer 11.0|Windows 7 用户

没兴趣探索，乖乖用centos7

这种心态必须点赞

![](/data/attachment/album/201701/05/145126obztblftt6bqc16h.jpg)

随着 Ubuntu 16.10 的发布，Unity 8 越来越吸引到了更多人的关注。这是因为在这个大家最爱的 Linux 发行版的最新版本中可以体验其带有的试验性桌面。桌面发行版是人们最熟悉的 Unity 环境，但有一点点不同。它不再使用 X11 图形技术，Ubuntu 的开发者选择了另一种截然不同的方式。

原来，Unity 8 用的是 Mir，这是 Ubuntu 为了在 Linux 上提供显示服务而做出的努力。这项技术已经在 Ubuntu phone 和平板上大量使用，但是这次新版是我们在桌面环境上第一次见到 Mir 。

这项技术相当新颖，结果是没多少 Linux 程序能运行在它之上。不是所有，那也是大部分的程序设计在 Xorg 和 X11 之上运行。如果你想要试试在 Unity 8 上运行这些程序，你肯定会为在 Unity 8上确实能够运行之前的 Xorg 程序而高兴。接下来是如何做！

### 登录进 Unity 8

![](/data/attachment/album/201701/05/145153zkitdd5vv8cuuk1v.jpg)

Unity 8 在 Ubuntu 16.10 上是一个可选会话。在使用之前只须牢记一件事情：它不会加载 AMD 的图形驱动，Intel 的同样不会加载。唯一支持的图形驱动是 Nvidia 的开源驱动。要用 Unity 8 的话，只要像往常那样启动 Ubuntu，然后，在登录进去之前，点击用户名上面的 Ubuntu 图标，选择 Unity8 选项。如果万事顺利的话，这个新的、试验性的桌面环境将会加载。

**注意**： Unity 8 非常新而且不稳定，自行承担使用风险。

### 安装 Libertine

Xorg 程序（例如 Firefox 等）确实能在 Unity 8 上使用，在使用之前需要一点小调整。在 Mir 桌面上用终端打开 Libertine ，在 Scopes 窗口中点击终端图标就能完成。一旦打开，输入你的密码。接下来，输入以下的命令：

![](/data/attachment/album/201701/05/145213bcfz9jcc5fiipxfu.jpg)

```
sudo apt install libertine-tools libertine-scope libertine

```

当这些程序完成安装后，点击并拖动 Scopes 窗口以刷新内容。然后，在面板上点击来启动 libertine。

### 新建 Xorg 容器

打开 Libertine，就可以新建一些（应用）容器了。这些容器很特别，因为它们能让基于 X11 的 Linux 程序在 Mir/Unity 8 桌面上的容器之中运行。另外，如果需要支持 32 位应用，勾选“i386 multiarch support”复选框。否则，什么都不要动（或者输入名字和密码），点击“OK”。

![](/data/attachment/album/201701/05/145305e6botbsqqbzoqtob.jpg)

在这之后，这个 Xorg 容器就准备好，可以使用了。在 Libertine 找到它并启动。删除也很容易，右键点击容器，选择“删除”选项。

**注意**：每一个 Xorg 容器有 500 MB的最大内存限制。所以多个容器是有必要的。

### 安装软件

![](/data/attachment/album/201701/05/145349snakfoapr0kksqns.jpg)

在 Libertine 容器中安装软件有两个方法。第一种是允许用户启动容器后选择“输入包名或者 Debian 文件”，这意味着用户可以在软件中心或者终端找到一个软件的名字，然后在 Libertine 中输入它来安装。也可以指定特定的 DEB 文件来安装，可以在Libertine LXC 容器中直接搜索安装包。

**注意**：Unity 8 非常新，一些程序或许不能在 Libertine 里加载或者完全安装。

### 结论

Unity 8 展现了不少的新特性，它现代、时髦，而且比之前任何一个 Unity 迭代版本都快。唯一限制它的就是使用率。事实是大部分用户更乐意选择实用的应用程序，而不是一个别致新颖的桌面环境。某种程度上来说，使用 Libertine 能解决这个问题，但它不会永久有效。早晚有一天，Canonical 都需要自行移植这些程序或者向社区求助来彻底解决这个问题。

---

via: <https://www.maketecheasier.com/use-old-xorg-apps-unity-8/>

作者：[Derrik Diener](https://www.maketecheasier.com/author/derrikdiener/) 译者：[ypingcn](https://github.com/ypingcn) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 Linux 中找出最近或今天被修改的文件

Summary:
Linux 用户在命令行上遇到的常见问题之一是定位具有特定名称的文件，如果你知道确定的文件名则可能会容易得假设你忘记了白天早些时候创建的文件的名称（在你包含了数百个文件的 home 文件夹中），但现在你有急用。
下面用不同的方式只列出所有你今天创建或修改的文件（直接或间接）。

另外一种通过find找出今天修改的文件的方法:<br />
$ find . -maxdepth 1 -mmin -$((`date +%H`*60+`date +%M`))

不直观。

find . -maxdepth 1 -newermt $(date --date='now' '+%Y-%m-%d')

看着好高大！

cxljava [Internet Explorer 8.0|Windows 7]

我试了 ls  -al --time-style=+%D | grep 'date +%D'  过滤的不是当前日期好像是 'date +%D' 本身，怎么破？

不是单引号，是波浪号下面的单撇号。

在本文中，我们将解释两个简单的命令行小技巧，它可以帮你只列出所有的今天的文件。

Linux 用户在命令行上遇到的常见问题之一是[定位具有特定名称的文件](/article-5973-1.html)，如果你知道确定的文件名则可能会容易得多。

不过，假设你忘记了白天早些时候创建的文件的名称（在你包含了数百个文件的 `home` 文件夹中），但现在你有急用。

下面用不同的方式只[列出所有你今天创建或修改的文件](/article-7984-1.html)（直接或间接）。

![](/data/attachment/album/201701/05/212219h1n7v11mogznj003.jpg)

### 1、 使用 ls 命令，只列出你的 home 文件夹中今天的文件。

```
# ls  -al --time-style=+%D | grep 'date +%D'

```

其中：

* `-a` - 列出所有文件，包括隐藏文件
* `-l` - 启用长列表格式
* `--time-style=FORMAT` - 显示指定 FORMAT 的时间
* `+％D` - 以 `％m/％d/％y` （月/日/年）格式显示或使用日期

![Find Recent Files in Linux](/data/attachment/album/201701/06/090717eldbidcicipwd5kf.png)

*在Linux中找出最近的文件*

此外，你使用可以 `-X` 标志来[按字母顺序对结果排序](/article-5372-1.html)：

```
# ls -alX --time-style=+%D | grep 'date +%D'

```

你也可以使用 `-S` 标志来基于大小（由大到小）来排序：

```
# ls -alS --time-style=+%D | grep 'date +%D'

```

### 2、 另外，使用 find 命令会更灵活，并且提供比 `ls` 更多的选项，可以实现相同的目的。

* `-maxdepth` 级别用于指定在搜索操作的起点下（在这个情况下为当前目录）的搜索层级（子目录层级数）。
* `-newerXY`，用于所寻找的文件的时间戳 `X` 比参照文件的时间戳 `Y` 更新一些的文件。 `X` 和 `Y` 表示以下任何字母： - `a` - 参照文件的访问时间 - `B` - 参照文件的创建时间 - `c` - 参照文件的 inode 状态改变时间 - `m` - 参照文件的修改时间 - `t` - 直接指定一个绝对时间

下面的命令意思是只找出 2016-12-06 这一天修改的文件：

```
# find . -maxdepth 1 -newermt "2016-12-06"

```

![Find Today's Files in Linux](/data/attachment/album/201701/05/212244geaw3vy199t7a3a9.png)

*在 Linux 中找出今天的文件*

重要：在上面的 [find 命令](/article-1672-1.html)中使用正确的**日期格式**作为参照时间，一旦你使用了错误的格式，你会得到如下错误：

```
# find . -maxdepth 1 -newermt "12-06-2016"
find: I cannot figure out how to interpret '12-06-2016' as a date or time

```

或者，使用下面的正确格式：

```
# find . -maxdepth 1 -newermt "12/06/2016"
或者
# find . -maxdepth 1 -newermt "12/06/16"

```

![Find Todays Modified Files in Linux](/data/attachment/album/201701/05/212245qkhqbnndihxqhffs.png)

*在 Linux 中找出今天修改的文件*

你可以在我们的下面一系列文章中获得 `ls`和 `find` 命令的更多使用信息。

* [用 15 例子的掌握 Linux ‘ls’ 命令](http://www.tecmint.com/15-basic-ls-command-examples-in-linux/)
* [对 Linux 用户有用的 7 个奇特技巧](http://www.tecmint.com/linux-ls-command-tricks/)
* [用 35 个例子掌握 Linux ‘find’ 命令](http://www.tecmint.com/35-practical-examples-of-linux-find-command/)
* [在 Linux 中使用扩展查找多个文件名的方法](http://www.tecmint.com/linux-find-command-to-search-multiple-filenames-extensions/)

在本文中，我们解释了如何使用 ls 和 find 命令帮助只列出今天的文件。 请使用以下反馈栏向我们发送有关该主题的任何问题或意见。 你也可以提醒我们其他可以用于这个目的的命令。

---

作者简介：Aaron Kili是一名 Linux 和 F.O.S.S 的爱好者，未来的 Linux 系统管理员、网站开发人员，目前是 TecMint 的内容创作者，他喜欢用电脑工作，并乐于分享知识。

---

via: <http://www.tecmint.com/find-recent-modified-files-in-linux/>

作者：[Aaron Kili](http://www.tecmint.com/author/aaronkili/) 译者：[geekpi](https://github.com/geekpi) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


从源代码编译 Vim 8.0

Summary: 从源代码编译 Vim 实际上并不那么困难。

嗯。

从源代码编译 Vim 实际上并不那么困难。

![](/data/attachment/album/201701/05/220017pyxnl20304ng3z9x.jpg)

从源代码编译 Vim 实际上并不那么困难。下面是你所要做的：

1、首先，安装包括 Git 在内的所有必备的库。对于一个 Debian 类的 Linux 发行版，例如 Ubuntu，命令如下：

```
sudo apt-get install libncurses5-dev libgnome2-dev libgnomeui-dev \
    libgtk2.0-dev libatk1.0-dev libbonoboui2-dev \
    libcairo2-dev libx11-dev libxpm-dev libxt-dev python-dev \
    python3-dev ruby-dev lua5.1 lua5.1-dev libperl-dev git

```

在 Ubuntu 16.04 上，lua 开发包的名称是 `liblua5.1-dev` 而非 `lua5.1-dev`。

如果你知道你将使用哪种语言，可随意删去你不需要的包。例如：Python2 `python-dev` 或者是 Ruby `ruby-dev`。这一原则适用于本文的大部分内容。

对于 Fedora 20，将是以下命令:

```
sudo yum install -y ruby ruby-devel lua lua-devel luajit \
    luajit-devel ctags git python python-devel \
    python3 python3-devel tcl-devel \
    perl perl-devel perl-ExtUtils-ParseXS \
    perl-ExtUtils-XSpp perl-ExtUtils-CBuilder \
    perl-ExtUtils-Embed

```

在 Fedora 20 上需要这一步来纠正安装 XSubPP 时出现的问题：

```
### 从 /usr/bin 到 perl 目录做个 xsubpp (perl) 的符号链接
sudo ln -s /usr/bin/xsubpp /usr/share/perl5/ExtUtils/xsubpp

```

2、 如果你已经安装了 vim，删掉它。

```
sudo apt-get remove vim vim-runtime gvim

```

如果是 Ubuntu 12.04.2，你或许也需要同时删除下面这些软件包:

```
sudo apt-get remove vim-tiny vim-common vim-gui-common vim-nox

```

3、 一旦上述内容都被安装好之后，获取 vim 源代码很容易。

注意：如果你使用 python，你的配置目录或许有一个特定的机器名 (例如 `config-3.5m-x86_64-linux-gnu`)。检查 `/usr/lib/python[2/3/3.5]` 目录来找到你的 python 配置目录，据此更改 `python-config-dir` 和/或 `python3-config-dir`的参数。

添加/删除下面的编译参数以适合您的设置。例如，如果您不打算写任何 Lua 脚本，您可以删去 `enable-luainterp`。

同时，如果你使用的不是 vim 8.0，请确认下面 `VIMRUNTIMEDIR` 参数设置正确（例如，如果使用 vim 8.0a, 就用 `/usr/share/vim/vim80a`）。记住，一些 vim 安装是直接安装在 `/usr/share/vim` 下的；调整好参数以适应你的系统:

```
cd ~
git clone https://github.com/vim/vim.git
cd vim
./configure --with-features=huge \
    --enable-multibyte \
    --enable-rubyinterp=yes \
    --enable-pythoninterp=yes \
    --with-python-config-dir=/usr/lib/python2.7/config \
    --enable-python3interp=yes \
    --with-python3-config-dir=/usr/lib/python3.5/config \
    --enable-perlinterp=yes \
    --enable-luainterp=yes \
    --enable-gui=gtk2 --enable-cscope --prefix=/usr
make VIMRUNTIMEDIR=/usr/share/vim/vim80

```

在 Ubuntu 16.04 上，由于同时开启了 Python2 和 Python3，Python 支持将不工作。 阅读 [chirinosky 的回答](http://stackoverflow.com/questions/23023783/vim-compiled-with-python-support-but-cant-see-sys-version) 以获取变通的处理方法。

如果你想将来轻松卸载 vim，可以使用 `checkinstall` 来安装 。

```
sudo apt-get install checkinstall
cd ~/vim
sudo checkinstall

```

否则，可以使用 `make` 来安装。

```
cd ~/vim
sudo make install

```

要让 vim 成为你默认的编辑器，请使用 `update-alternatives`。

```
sudo update-alternatives --install /usr/bin/editor editor /usr/bin/vim 1
sudo update-alternatives --set editor /usr/bin/vim
sudo update-alternatives --install /usr/bin/vi vi /usr/bin/vim 1
sudo update-alternatives --set vi /usr/bin/vim

```

4、 再检查下，通过查看 `vim --version` 输出来确认确实在运行新的 Vim 应用程序版本。

**如果你的 gvim 不工作（在 ubuntu 12.04.1 LTS 上），试着把 `--enable-gui=gtk2` 参数变为 `--enable-gui=gnome2`。**

如果你遇到问题，仔细检查在步骤 3 开始提到的，使用正确的 Python 配置目录配置 `configure`。

这些 `configure` 和 `make` 命令假设你是一个 Debian 发行版，Vim 的运行库文件目录放在 `/usr/share/vim/vim80/`，这不是 vim 的默认路径。 在 `configure` 命令中的 `--prefix=/usr` 也是如此。这些参数或许对一个不是基于 Debian 的 Linux 发行版来说是有所不同的，在这种情况下，试着移除 `configure` 命令中的 `--prefix` 变量和 `make` 命令中的 `VIMRUNTIMEDIR` (换句话说，使用这些参数的默认值)。

如果你遇到麻烦, 这里是一些[其它编译 Vim 的有用的信息](http://vim.wikia.com/wiki/Building_Vim)。

---

via: <https://github.com/Valloric/YouCompleteMe/wiki/Building-Vim-from-source>

作者：[Val Markovic](https://github.com/Valloric) 等人 译者：[zky001](https://github.com/zky001) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Samba 系列（三）：使用 Windows 10 的 RSAT 工具来管理 Samba4 活动目录架构

我还在用samba2.。。。。。。  有人给我讲解下 samba4  都有些什么新特性吗

这一节的Samba4 AD DC 架构系列文章，我们将会讨论如何把 Windows 10 系统的电脑添加到 Samba4 域环境中，以及如何在 Windows 10 系统下管理域环境。

![](/data/attachment/album/201701/05/225257qbvfnlqngq2wlvqo.jpg)

一旦 Windows 10 系统加入到 Samba4 AD DC ，我们就可以在 Windows 10 系统中创建、删除或者禁用域用户和组了，可以创建新的组织单元，创建、编辑和管理域策略，还可以管理 Samba4 域 DNS 服务。

上面所有的功能和其它一些复杂的与域管理相关的工作都可以通过 Windows 环境下的 RSAT 工具来完成—— Microsoft 远程服务器管理工具。

#### 要求

1、 [在 Ubuntu 系统上使用 Samba4 来创建活动目录架构（一）](/article-8065-1.html)

2、 [在 Linux 命令行下管理 Samba4 AD 架构（二）](/article-8070-1.html)

### 第一步：配置域时间同步

1、在使用 Windows 10 系统的 RSAT 工具来管理 Samba4 ADDC 之前，我们需要了解与活动目录相关的一个很重要的服务，该服务要求[精确的时间同步](http://www.tecmint.com/how-to-synchronize-time-with-ntp-server-in-ubuntu-linux-mint-xubuntu-debian/)。

在大多数的 Linux 发行版中，都由 NTP 进程提供时间同步机制。AD 环境默认允许最大的时间差距是 5 分钟。

如果时间差距超过 5 分钟，你将会遇到各种各样的异常报错，最严重的会影响到 AD 用户、域成员服务器或共享访问等。

为了在 Ubuntu 系统中安装网络时间协议进程和 NTP 客户端工具，可执行以下命令：

```
$ sudo apt-get install ntp ntpdate

```

![Install NTP on Ubuntu](/data/attachment/album/201701/05/230141e8r2a4477a94zp67.png)

*在 Ubuntu 系统下安装 NTP 服务*

2、下一步，修改 NTP 配置文件，使用一个离你最近的 NTP 服务地址列表替换默认的 NTP 池服务列表。

NTP 服务器地址列表可以从 NTP 地址库项目官方网站获取：<http://www.pool.ntp.org/en/>。

```
$ sudo nano /etc/ntp.conf

```

在每一行 `pool` 前添加一个 `#` 符号以注释默认的服务器列表，并替换为适合你的 NTP 服务器地址，如下图所示：

```
pool 0.ro.pool.ntp.org iburst
pool 1.ro.pool.ntp.org iburst
pool 2.ro.pool.ntp.org iburst
# Use Ubuntu's ntp server as a fallback.
pool 3.ro.pool.ntp.org

```

![Configure NTP Server in Ubuntu](/data/attachment/album/201701/05/230142ceky5ez9dek4udrn.png)

*在 Ubuntu 系统下配置 NTP 服务*

3、此时，先不要关闭该文件。移动光标到文件顶部，在 `driftfile` 参数后面添加下面一行内容。该设置是为了让客户端查询该服务时使用 AD 的 NTP 签署请求。

```
ntpsigndsocket /var/lib/samba/ntp_signd/

```

![Sync AD with NTP](/data/attachment/album/201701/05/230143e8kixc8a7afcxxtt.png)

*使用 NTP 来同步 AD*

4、最后，移动光标到文件底部并添加如下一行内容，如截图所示，仅允许网络客户端查询该服务器上的时间。

```
restrict default kod nomodify notrap nopeer mssntp

```

![Query Clients to NTP Server](/data/attachment/album/201701/05/230144dlglhukdnh1lffon.png)

*限制 NTP 服务的查询客户端*

5、设置完成之后，保存并关闭 NTP 配置文件，为了让 NTP 服务读取 `ntp_signed` 目录，需要授予 NTP 服务合适的权限。

以下是 Samba NTP socket 的系统路径。之后，重启 NTP 服务以应用更改，并使用 [netstat 命令](http://www.tecmint.com/20-netstat-commands-for-linux-network-management/)与[grep 过滤](http://www.tecmint.com/12-practical-examples-of-linux-grep-command/)相接合来检查 NTP 服务是否正常。

```
$ sudo chown root:ntp /var/lib/samba/ntp_signd/
$ sudo chmod 750 /var/lib/samba/ntp_signd/
$ sudo systemctl restart ntp
$ sudo netstat –tulpn | grep ntp

```

![Grant Permission to NTP](/data/attachment/album/201701/05/230145jcemacqwqgeddcac.png)

*给 NTP 服务授权*

使用 ntpq 命令行工具来监控 NTP 进程，加上 `-p` 参数来显示摘要信息。

```
$ ntpq -p

```

![Monitor NTP Server Pool](/data/attachment/album/201701/05/230147weopy1x0uzu3ciee.png)

*监控 NTP 服务器池*

### 第二步：处理 NTP 时间同步异常问题

6、有时候 NTP 进程在尝试与上游 ntp 服务端同步时间的计算过程中会卡住，导致客户端使用 `ntpdate` 工具手动强制同步时间时报如下错误：

```
# ntpdate -qu adc1
ntpdate[4472]: no server suitable for synchronization found

```

![NTP Time Synchronization Error](/data/attachment/album/201701/05/230148jz2u2p2mi828rnm2.png)

*NTP 时间同步异常*

`ntpdate` 命令加上 `-d` 调试选项：

```
# ntpdate -d adc1.tecmint.lan
Server dropped: Leap not in sync

```

![NTP Server Dropped Leap Not in Sync](/data/attachment/album/201701/05/230149xbjzyjqticltnnyn.png)

*NTP Server Dropped Leap Not in Sync*

7、为了避免出现该问题，使用下面的方法来解决这个问题：在服务器上停止 NTP 服务，使用 `ntpdate` 客户端工具加上 `-b` 参数指定外部 peer 地址来手动强制同步时间，如下图所示：

```
# systemctl stop ntp.service
# ntpdate -b 2.ro.pool.ntp.org  [你的 ntp peer]
# systemctl start ntp.service
# systemctl status ntp.service

```

![Force NTP Time Synchronization](/data/attachment/album/201701/05/230151j7565yyjyzyl2x5j.png)

*强制 NTP 时间同步*

8、当时间正确同步之后，启动服务器上的 NTP 服务，并且在客户端服务器上执行如下命令来验证 NTP 时间同步服务是否可用：

```
# ntpdate -du adc1.tecmint.lan    [你的 AD DC 服务器]

```

![Verify NTP Time Synchronization](/data/attachment/album/201701/05/230151sao5x3jds35joa5s.png)

*验证 NTP 时间同步*

至此， NTP 服务应该已经工作正常了。

### 第三步：把 Windows 10 系统加入域环境

9、从我们的前一篇文章可以看出，[Samba4 活动目录可以使用 samba-tool 工具在命令行下管理](/article-8070-1.html)，可以直接在服务器上的 VTY 控制台或者通过 SSH 工具远程连接到服务器上进行管理。

另外，更直观更灵活的方式是使用已加入域的 Windows 电脑中的微软远程服务器管理工具（RSAT）来管理我们的 Samba4 AD 域控制器。这些工具在当前的大多数 Windows 系统中都可以使用。

把 Windows 10 或是之前版本的微软操作系统加入到 Samba4 AD DC 环境中的过程也是非常容易的。首先，确保你的 Windows 10 电脑已经设置了正确的 Samba4 DNS 服务器的 IP 地址，以查询出准确的域解析结果。

打开“控制面板 -> 网络和 Internet -> 网络和共享中心 -> 网卡设置 -> 属性 -> IPv4 -> 属性 -> 使用下面的 DNS 服务器地址”，并且手动输入 Samba4 AD 服务器的 IP 地址，如下图所示：

![join Windows to Samba4 AD](/data/attachment/album/201701/05/230153sa44zwfwhibhrl92.png)

*把 Windows 10 加入到 Samba4 AD 环境*

![Add DNS and Samba4 AD IP Address](/data/attachment/album/201701/05/230155g1jroovxq1b11vwi.png)

*添加 DNS 和 Samba4 AD 服务器地址*

这里的 `192.168.1.254` 是 Samba4 AD 域控服务器的地址，用于域名解析。相应替换该 IP 地址。

10、下一步，点击 OK 按钮以应用网络设置，打开 CMD 命令行窗口，通过 ping 域名和 Samba4 服务器的 FQDN 地址来测试通过 DNS 解析到域是否连通。

```
ping tecmint.lan
ping adc1.tecmint.lan

```

![Check Network Connectivity Between Windows and Samba4 AD](/data/attachment/album/201701/05/230157p01s58ushq1h1tsu.png)

*检查 Windows 和 Samb4 AD 服务器的网络连通性*

11、如果 Windows 客户端 DNS 查询的结果解析正确，那么，你还需要确认客户端时间是否已跟域环境同步。

打开“控制面板 -> 时钟、语言和区域 -> 设置时间和日期 -> Internet 时间页 -> 更改设置”，输入你同步时间的域名和 Internet 时间服务器字段。

点击立即更新按钮来强制与域同步时间，点击 OK 关闭窗口。

![Synchronize Time with Internet Server](/data/attachment/album/201701/05/230159uki9xqm9elk99ppq.png)

*与 Internet 服务器同步时间*

12、最后，通过打开“系统属性 -> 更改 -> 域成员 -> 输入域名”，点击 OK，输入你的域管理员账号和密码，再次点击 OK。

应该弹出一个新的窗口通知你已经是一个域成员了。点击 OK 关闭弹出窗口，并且重启机器以应用域更改。

下面的截图将说明这些操作步骤。

![Join Windows Domain to Samba4 AD](/data/attachment/album/201701/05/230201zsswddsmgisfmc5n.png)

*把 Windows 域加入到 Samba4 AD 环境*

![Enter Domain Administration Login](/data/attachment/album/201701/05/230203s1fwccwcmw1wwcgz.png)

*输入域管理员账号登录*

![Domain Joined to Samba4 AD Confirmation](/data/attachment/album/201701/05/230204upxryvf1r8nmtjh3.png)

*确认域已加入到 Samba4 AD 环境*

![Restart Windows Server for Changes](/data/attachment/album/201701/05/230204osq8exq9qszgh2st.png)

*重启 Windows 服务器以应用更改*

13、重启之后，单击其它用户并且使用具有管理员权限的 Samba4 域账号登录到 Windows 系统，你已经准备好进入到后边几个步骤了。

![Login to Windows Using Samba4 AD Account](/data/attachment/album/201701/05/230206wktbpxookkbjw2wo.png)

*使用 Samba4 AD 账号登录到 Windows*

### 第四步：使用 RSAT 工具来管理 Samba4 AD DC

14、微软远程服务器管理工具（RSAT）被广泛地用来管理 Samba4 活动目录，你可以根据你的 Windows 系统版本从下面的地址来下载该工具：

1. Windows 10: <https://www.microsoft.com/en-us/download/details.aspx?id=45520>
2. Windows 8.1: <http://www.microsoft.com/en-us/download/details.aspx?id=39296>
3. Windows 8: <http://www.microsoft.com/en-us/download/details.aspx?id=28972>
4. Windows 7: <http://www.microsoft.com/en-us/download/details.aspx?id=7887>

一旦 Windows 10 独立安装包下载完成，运行安装包，等待安装完成并重启机器以应用所有更新。

重启之后，打开“控制面板 -> 程序（卸载程序） -> 启用或关闭 Windows 功能”，勾选所有的远程服务器管理工具。

点击 OK 开始安装，安装完成之后重启系统。

![Administer Samba4 AD from Windows](/data/attachment/album/201701/05/230208iejuz6kh5egj5yuj.png)

*从 Windows 系统下管理 Samba4 AD*

15、要进入 RSAT 工具集，打开“控制面板 -> 系统和安全 -> 管理工具”。

这些工具也可以在开始工菜单的管理工具菜单中找到。另外，你也可以打开 Windows MMC 工具和管理单元，从“文件 -> 添加/删除管理单元”菜单中访问它们。

![Access Remote Server Administration Tools](/data/attachment/album/201701/05/230209iuu8m8dil0z9ubuc.png)

*访问远程服务器管理工具集*

最常用的工具，比如 AD UC ，DNS 和组策略管理工具可以通过从右键菜单发送到功能来新建快捷方式到桌面直接运行。

16、你可以通过 AD UC 和列出域里的电脑（新加入的 Windows 机器应该出现在列表中）来验证 RSAT 功能，创建一个组织单元或组。

在 Samba4 服务器上使用 `wbinf` 命令来检查用户和组是否已经创建成功。

![Active Directory Users and Computers](/data/attachment/album/201701/05/230211k5zin5xiinen7rht.png)

*活动目录用户和计算机*

![Create Organizational Units and New Users](/data/attachment/album/201701/05/230212o6rrhb31z1thgt1u.png)

*创建组织单元和新用户*

![Confirm Samba4 AD Users](/data/attachment/album/201701/05/230213v41occbz4bcpcbcz.png)

*确认 Samba4 AD 用户*

就这些吧！该主题的下一篇文章将包含其它 Samba4 活动目录的重要内容，包括通过 RSAT 工具来管理 Samba4 活动目录，比如，如何管理 DNS 服务器，添加 DNS 记录和创建 DNS 解析查询区，如何管理及应用域策略以及域用户如何创建交互式登录提示信息。

---

作者简介：我是一个电脑迷，开源软件及 Linux 系统爱好者，有近4年的 Linux 桌面和服务器系统及 bash 编程经验。

---

via: <http://www.tecmint.com/manage-samba4-ad-from-windows-via-rsat/>

作者：[Matei Cezar](http://www.tecmint.com/author/cezarmatei/) 译者：[rusking](https://github.com/rusking) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


CentOS 上的 FirewallD 简明指南

Summary: FirewallD 是 iptables 的前端控制器，用于实现持久的网络流量规则。它提供命令行和图形界面，在大多数 Linux 发行版的仓库中都有。

y ouwdadhwa

赞一个

感谢，好文！

教程非常好，感谢

好文章

![](/data/attachment/album/201701/06/211008tqx6x9jqqm2m4q4q.jpg)

[FirewallD](http://www.firewalld.org/) 是 iptables 的前端控制器，用于实现持久的网络流量规则。它提供命令行和图形界面，在大多数 Linux 发行版的仓库中都有。与直接控制 iptables 相比，使用 FirewallD 有两个主要区别：

1. FirewallD 使用区域和服务而不是链式规则。
2. 它动态管理规则集，允许更新规则而不破坏现有会话和连接。

>
> FirewallD 是 iptables 的一个封装，可以让你更容易地管理 iptables 规则 - 它并*不是* iptables 的替代品。虽然 iptables 命令仍可用于 FirewallD，但建议使用 FirewallD 时仅使用 FirewallD 命令。
>
>
>

本指南将向您介绍 FirewallD 的区域和服务的概念，以及一些基本的配置步骤。

### 安装与管理 FirewallD

CentOS 7 和 Fedora 20+ 已经包含了 FirewallD，但是默认没有激活。可以像其它的 systemd 单元那样控制它。

1、 启动服务，并在系统引导时启动该服务：

```
sudo systemctl start firewalld
sudo systemctl enable firewalld

```

要停止并禁用：

```
sudo systemctl stop firewalld
sudo systemctl disable firewalld

```

2、 检查防火墙状态。输出应该是 `running` 或者 `not running`。

```
sudo firewall-cmd --state

```

3、 要查看 FirewallD 守护进程的状态：

```
sudo systemctl status firewalld

```

示例输出

```
firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled)
   Active: active (running) since Wed 2015-09-02 18:03:22 UTC; 1min 12s ago
 Main PID: 11954 (firewalld)
   CGroup: /system.slice/firewalld.service
   └─11954 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

```

4、 重新加载 FirewallD 配置：

```
sudo firewall-cmd --reload

```

### 配置 FirewallD

FirewallD 使用 XML 进行配置。除非是非常特殊的配置，你不必处理它们，而应该使用 `firewall-cmd`。

配置文件位于两个目录中：

* `/usr/lib/FirewallD` 下保存默认配置，如默认区域和公用服务。 避免修改它们，因为每次 firewall 软件包更新时都会覆盖这些文件。
* `/etc/firewalld` 下保存系统配置文件。 这些文件将覆盖默认配置。

#### 配置集

FirewallD 使用两个*配置集*：“运行时”和“持久”。 在系统重新启动或重新启动 FirewallD 时，不会保留运行时的配置更改，而对持久配置集的更改不会应用于正在运行的系统。

默认情况下，`firewall-cmd` 命令适用于运行时配置，但使用 `--permanent` 标志将保存到持久配置中。要添加和激活持久性规则，你可以使用两种方法之一。

1、 将规则同时添加到持久规则集和运行时规则集中。

```
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=http

```

2、 将规则添加到持久规则集中并重新加载 FirewallD。

```
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --reload

```

>
> `reload` 命令会删除所有运行时配置并应用永久配置。因为 firewalld 动态管理规则集，所以它不会破坏现有的连接和会话。
>
>
>

### 防火墙的区域

“区域”是针对给定位置或场景（例如家庭、公共、受信任等）可能具有的各种信任级别的预构建规则集。不同的区域允许不同的网络服务和入站流量类型，而拒绝其他任何流量。 首次启用 FirewallD 后，`public` 将是默认区域。

区域也可以用于不同的网络接口。例如，要分离内部网络和互联网的接口，你可以在 `internal` 区域上允许 DHCP，但在`external` 区域仅允许 HTTP 和 SSH。未明确设置为特定区域的任何接口将添加到默认区域。

要找到默认区域：

```
sudo firewall-cmd --get-default-zone

```

要修改默认区域：

```
sudo firewall-cmd --set-default-zone=internal

```

要查看你网络接口使用的区域：

```
sudo firewall-cmd --get-active-zones

```

示例输出：

```
public
  interfaces: eth0

```

要得到特定区域的所有配置：

```
sudo firewall-cmd --zone=public --list-all

```

示例输出：

```
public (default, active)
  interfaces: ens160
  sources:
  services: dhcpv6-client http ssh
  ports: 12345/tcp
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

```

要得到所有区域的配置：

```
sudo firewall-cmd --list-all-zones

```

示例输出：

```
block
  interfaces:
  sources:
  services:
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

  ...

work
  interfaces:
  sources:
  services: dhcpv6-client ipp-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

```

#### 与服务一起使用

FirewallD 可以根据特定网络服务的预定义规则来允许相关流量。你可以创建自己的自定义系统规则，并将它们添加到任何区域。 默认支持的服务的配置文件位于 `/usr/lib /firewalld/services`，用户创建的服务文件在 `/etc/firewalld/services` 中。

要查看默认的可用服务：

```
sudo firewall-cmd --get-services

```

比如，要启用或禁用 HTTP 服务：

```
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --remove-service=http --permanent

```

#### 允许或者拒绝任意端口/协议

比如：允许或者禁用 12345 端口的 TCP 流量。

```
sudo firewall-cmd --zone=public --add-port=12345/tcp --permanent
sudo firewall-cmd --zone=public --remove-port=12345/tcp --permanent

```

#### 端口转发

下面是**在同一台服务器上**将 80 端口的流量转发到 12345 端口。

```
sudo firewall-cmd --zone="public" --add-forward-port=port=80:proto=tcp:toport=12345

```

要将端口转发到**另外一台服务器上**：

1、 在需要的区域中激活 masquerade。

```
sudo firewall-cmd --zone=public --add-masquerade

```

2、 添加转发规则。例子中是将本地的 80 端口的流量转发到 IP 地址为 ：123.456.78.9 的*远程服务器上的* 8080 端口。

```
sudo firewall-cmd --zone="public" --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=123.456.78.9

```

要删除规则，用 `--remove` 替换 `--add`。比如：

```
sudo firewall-cmd --zone=public --remove-masquerade

```

### 用 FirewallD 构建规则集

例如，以下是如何使用 FirewallD 为你的服务器配置基本规则（如果您正在运行 web 服务器）。

1. 将 `eth0` 的默认区域设置为 `dmz`。 在所提供的默认区域中，dmz（非军事区）是最适合于这个程序的，因为它只允许 SSH 和 ICMP。

```
sudo firewall-cmd --set-default-zone=dmz
sudo firewall-cmd --zone=dmz --add-interface=eth0

```

2、 把 HTTP 和 HTTPS 添加永久的服务规则到 dmz 区域中：

```
sudo firewall-cmd --zone=dmz --add-service=http --permanent
sudo firewall-cmd --zone=dmz --add-service=https --permanent

```

 3、 重新加载 FirewallD 让规则立即生效：

```
sudo firewall-cmd --reload

```

 如果你运行 `firewall-cmd --zone=dmz --list-all`， 会有下面的输出：

```
dmz (default)
  interfaces: eth0
  sources:
  services: http https ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

```

 这告诉我们，`dmz` 区域是我们的**默认**区域，它被用于 `eth0` 接口**中所有网络的**源地址**和**端口**。 允许传入 HTTP（端口 80）、HTTPS（端口 443）和 SSH（端口 22）的流量，并且由于没有 IP 版本控制的限制，这些适用于 IPv4 和 IPv6。 不允许**IP 伪装**以及**端口转发**。 我们没有 ICMP 块**，所以 ICMP 流量是完全允许的。没有<ruby> 丰富 <rp>  （ </rp> <rt>  Rich </rt> <rp>  ） </rp></ruby>**规则**，允许所有出站流量。

### 高级配置

服务和端口适用于基本配置，但对于高级情景可能会限制较多。 <ruby> 丰富 <rp>  （ </rp> <rt>  Rich </rt> <rp>  ） </rp></ruby>规则和<ruby> 直接 <rp>  （ </rp> <rt>  Direct </rt> <rp>  ） </rp></ruby>接口允许你为任何端口、协议、地址和操作向任何区域 添加完全自定义的防火墙规则。

#### 丰富规则

丰富规则的语法有很多，但都完整地记录在 [firewalld.richlanguage(5)](https://jpopelka.fedorapeople.org/firewalld/doc/firewalld.richlanguage.html) 的手册页中（或在终端中 `man firewalld.richlanguage`）。 使用 `--add-rich-rule`、`--list-rich-rules` 、 `--remove-rich-rule` 和 firewall-cmd 命令来管理它们。

这里有一些常见的例子：

允许来自主机 192.168.0.14 的所有 IPv4 流量。

```
sudo firewall-cmd --zone=public --add-rich-rule 'rule family="ipv4" source address=192.168.0.14 accept'

```

拒绝来自主机 192.168.1.10 到 22 端口的 IPv4 的 TCP 流量。

```
sudo firewall-cmd --zone=public --add-rich-rule 'rule family="ipv4" source address="192.168.1.10" port port=22 protocol=tcp reject'

```

允许来自主机 10.1.0.3 到 80 端口的 IPv4 的 TCP 流量，并将流量转发到 6532 端口上。

```
sudo firewall-cmd --zone=public --add-rich-rule 'rule family=ipv4 source address=10.1.0.3 forward-port port=80 protocol=tcp to-port=6532'

```

将主机 172.31.4.2 上 80 端口的 IPv4 流量转发到 8080 端口（需要在区域上激活 masquerade）。

```
sudo firewall-cmd --zone=public --add-rich-rule 'rule family=ipv4 forward-port port=80 protocol=tcp to-port=8080 to-addr=172.31.4.2'

```

列出你目前的丰富规则：

```
sudo firewall-cmd --list-rich-rules

```

### iptables 的直接接口

对于最高级的使用，或对于 iptables 专家，FirewallD 提供了一个<ruby> 直接 <rp>  （ </rp> <rt>  Direct </rt> <rp>  ） </rp></ruby>接口，允许你给它传递原始 iptables 命令。 直接接口规则不是持久的，除非使用 `--permanent`。

要查看添加到 FirewallD 的所有自定义链或规则：

```
firewall-cmd --direct --get-all-chains
firewall-cmd --direct --get-all-rules

```

讨论 iptables 的具体语法已经超出了这篇文章的范围。如果你想学习更多，你可以查看我们的 [iptables 指南](https://www.linode.com/docs/networking/firewalls/control-network-traffic-with-iptables)。

### 更多信息

你可以查阅以下资源以获取有关此主题的更多信息。虽然我们希望我们提供的是有效的，但是请注意，我们不能保证外部材料的准确性或及时性。

* [FirewallD 官方网站](http://www.firewalld.org/)
* [RHEL 7 安全指南：FirewallD 简介](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Using_Firewalls.html#sec-Introduction_to_firewalld)
* [Fedora Wiki：FirewallD](https://fedoraproject.org/wiki/FirewallD)

---

via: <https://www.linode.com/docs/security/firewalls/introduction-to-firewalld-on-centos>

作者：[Linode](https://www.linode.com/docs/security/firewalls/introduction-to-firewalld-on-centos) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


在 Linux 中管理设备

Summary: 探索 /dev 目录可以让您知道如何直接访问到 Linux 中的设备。

探索 /dev 目录可以让您知道如何直接访问到 Linux 中的设备。

探索 `/dev` 目录可以让您知道如何直接访问到 Linux 中的设备。

![](/data/attachment/album/201701/07/110422hj9xt9xsfgvvbefs.jpg)

Linux 目录结构中有很多有趣的功能，这次我会讲到 `/dev` 目录一些迷人之处。在继续阅读这篇文章之前，建议你看看我前面的文章。[Linux 文件系统](/article-6132-1.html)，[一切皆为文件](/article-7669-1.html)，这两篇文章介绍了一些有趣的 Linux 文件系统概念。请先看看 - 我会等你看完再回来。

……

太好了 ！欢迎回来。现在我们可以继续更详尽地探讨 `/dev` 目录。

### 设备文件

设备文件也称为[设备特定文件](https://en.wikipedia.org/wiki/Device_file)。设备文件用来为操作系统和用户提供它们代表的设备接口。所有的 Linux 设备文件均位于 `/dev` 目录下，是根 （`/`） 文件系统的一个组成部分，因为这些设备文件在操作系统启动过程中必须可以使用。

关于这些设备文件，要记住的一件重要的事情，就是它们大多不是设备驱动程序。更准确地描述来说，它们是设备驱动程序的门户。数据从应用程序或操作系统传递到设备文件，然后设备文件将它传递给设备驱动程序，驱动程序再将它发给物理设备。反向的数据通道也可以用，从物理设备通过设备驱动程序，再到设备文件，最后到达应用程序或其他设备。

让我们以一个典型命令的数据流程来直观地看看。

![dboth-dev-dir_0.png](/data/attachment/album/201701/07/110514xkw0x0jk0o31wom1.png)

*图 1：一个典型命令的简单数据流程。*

在上面的图 1 中，显示一个简单命令的简化数据流程。从一个 GUI 终端仿真器，例如 Konsole 或 xterm 中发出 `cat /etc/resolv.conf` 命令，它会从磁盘中读取 `resolv.conf` 文件，磁盘设备驱动程序处理设备的具体功能，例如在硬盘驱动器上定位文件并读取它。数据通过设备文件传递，然后从命令到设备文件，然后到 6 号伪终端的设备驱动，然后在终端会话中显示。

当然， `cat` 命令的输出可以以下面的方式被重定向到一个文件， `cat /etc/resolv.conf > /etc/resolv.bak` ，这样会创建该文件的备份。在这种情况下，图 1 左侧的数据流量将保持不变，而右边的数据流量将通过 `/dev/sda2` 设备文件、硬盘设备驱动程序，然后到硬盘驱动器本身。

这些设备文件使得使用标准流 (STD/IO) 和重定向访问 Linux 或 Unix 计算机上的任何一个设备非常容易。只需将数据流定向到设备文件，即可将数据发送到该设备。

### 设备文件类别

设备文件至少可以按两种方式划分。第一种也是最常用的分类是根据与设备相关联的数据流进行划分。比如，tty (teletype) 和串行设备被认为是基于字符的，因为数据流的传送和处理是以一次一个字符或字节进行的；而块类型设备（如硬盘驱动器）是以块为单位传输数据，通常为 256 个字节的倍数。

您可以在终端上以一个非 root 用户，改变当前工作目录（`PWD`）到 `/dev` ，并显示长目录列表。 这将显示设备文件列表、文件权限及其主、次设备号。 例如，下面的设备文件只是我的 Fedora 24 工作站上 `/dev` 目录中的几个文件。 它们表示磁盘和 tty 设备类型。 注意输出中每行的最左边的字符。 `b` 代表是块类型设备，`c` 代表字符设备。

```
brw-rw----   1 root disk        8,   0 Nov  7 07:06 sda
brw-rw----   1 root disk        8,   1 Nov  7 07:06 sda1
brw-rw----   1 root disk        8,  16 Nov  7 07:06 sdb
brw-rw----   1 root disk        8,  17 Nov  7 07:06 sdb1
brw-rw----   1 root disk        8,  18 Nov  7 07:06 sdb2
crw--w----   1 root tty         4,   0 Nov  7 07:06 tty0
crw--w----   1 root tty         4,   1 Nov  7 07:07 tty1
crw--w----   1 root tty         4,  10 Nov  7 07:06 tty10
crw--w----   1 root tty         4,  11 Nov  7 07:06 tty11
```

识别设备文件更详细和更明确的方法是使用设备主要以及次要号。 磁盘设备主设备号为 8，将它们指定为 SCSI 块设备。请注意，所有 PATA 和 SATA 硬盘驱动器都由 SCSI 子系统管理，因为旧的 ATA 子系统多年前就由于代码质量糟糕而被认为不可维护。造成的结果就是，以前被称为 “hd[a-z]” 的硬盘驱动器现在被称为 “sd[a-z]”。

你大概可以从上面的示例中推出磁盘驱动器次设备号的模式。次设备号 0、 16、 32 等等，直到 240，是整个磁盘的号。所以主/次 8/16 表示整个磁盘 `/dev/sdb` ， 8/17 是第一个分区的设备文件，`/dev/sdb1`。数字 8/34 代表 `/dev/sdc2`。

在上面列表中的 tty 设备文件编号更简单一些，从 tty0 到 tty63 。

Kernel.org 上的 [Linux 下的已分配设备](https://www.kernel.org/doc/Documentation/devices.txt)文件是设备类型和主次编号分配的正式注册表。它可以帮助您了解所有当前定义的设备的主要/次要号码。

### 趣味设备文件

让我们花几分钟时间，执行几个有趣的实验，演示 Linux 设备文件的强大和灵活性。 大多数 Linux 发行版都有 1 到 7 个虚拟控制台，可用于使用 shell 接口登录到本地控制台会话。 可以使用 `Ctrl-Alt-F1`（控制台 1），`Ctrl-Alt-F2`（控制台 2）等键盘组合键来访问。

请按 `Ctrl-Alt-F2` 切换到控制台 2。在某些发行版，登录显示的信息包括了与此控制台关联的 tty 设备，但大多不包括。它应该是 tty2，因为你是在控制台 2 中。

以非 root 用户身份登录。 然后你可以使用 `who am i` 命令 — 是的，就是这个命令，带空格 — 来确定哪个 tty 设备连接到这个控制台。

在我们实际执行此实验之前，看看 `/dev` 中的 tty2 和 tty3 的设备列表。

```
ls -l /dev/tty[23]

```

有大量的 tty 设备，但我们不关心他们中的大多数，只注意 tty2 和 tty3 设备。 作为设备文件，它们没什么特别之处。它们都只是字符类型设备。我们将使用这些设备进行此实验。 tty2 设备连接到虚拟控制台 2，tty3 设备连接到虚拟控制台 3。

按 `Ctrl-Alt-F3` 切换到控制台 3。再次以同一非 root 用户身份登录。 现在在控制台 3 上输入以下命令。

```
echo "Hello world" > /dev/tty2

```

按 `Ctrl-Alt-f2` 键以返回到控制台 2。字符串 “Hello world”（没有引号）将显示在控制台 2。

该实验也可以使用 GUI 桌面上的终端仿真器来执行。 桌面上的终端会话使用 `/dev` 中的伪终端设备，如 `/dev/pts/1`。 使用 Konsole 或 Xterm 打开两个终端会话。 确定它们连接到哪些伪终端，并使用一个向另一个发送消息。

现在继续实验，使用 `cat` 命令，试试在不同的终端上显示 `/etc/fstab` 文件。

另一个有趣的实验是使用 `cat` 命令将文件直接打印到打印机。 假设您的打印机设备是 `/dev/usb/lp0`，并且您的打印机可以直接打印 PDF 文件，以下命令将在您的打印机上打印 `test.pdf` 文件。

```
cat test.pdf > /dev/usb/lp0

```

`/dev` 目录包含一些非常有趣的设备文件，这些文件是硬件的入口，人们通常不认为这是硬盘驱动器或显示器之类的设备。 例如，系统存储器 RAM 不是通常被认为是“设备”的东西，而 `/dev/mem` 是通过其可以实现对存储器的直接访问的入口。 下面的例子有一些有趣的结果。

```
dd if=/dev/mem bs=2048 count=100

```

上面的 `dd` 命令提供比简单地使用 `cat` 命令 dump 所有系统的内存提供了更多的控制。 它提供了指定从 `/dev/mem` 读取多少数据的能力，还允许指定从存储器哪里开始读取数据。虽然读取了一些内存，但内核响应了以下错误，在 `/var/log/messages` 中可以看到。

```
Nov 14 14:37:31 david kernel: usercopy: kernel memory exposure attempt detected from ffff9f78c0010000 (dma-kmalloc-512) (2048 bytes)

```

这个错误意味着内核正在通过保护属于其他进程的内存来完成它的工作，这正是它应该工作的方式。 所以，虽然可以使用 `/dev/mem` 来显示存储在 RAM 内存中的数据，但是访问的大多数内存空间是受保护的并且会导致错误。 只可以访问由内核内存管理器分配给运行 `dd` 命令的 BASH shell 的虚拟内存，而不会导致错误。 抱歉，但你不能窥视不属于你的内存，除非你发现了一个可利用的漏洞。

`/dev` 中还有一些非常有趣的设备文件。 设备文件 `null`，`zero`，`random` 和 `urandom` 不与任何物理设备相关联。

例如，空设备 `/dev/null` 可以用作来自 shell 命令或程序的输出重定向的目标，以便它们不显示在终端上。 我经常在我的 BASH 脚本中使用这个，以防止向用户展示可能会让他们感到困惑的输出。 `/dev/null` 设备可用于产生一个空字符串。 使用如下所示的 `dd` 命令查看 `/dev/null` 设备文件的一些输出。

```
# dd if=/dev/null  bs=512 count=500 | od -c
0+0 records in
0+0 records out
0 bytes copied, 1.5885e-05 s, 0.0 kB/s
0000000

```

注意，因为空字符什么也没有所以确实没有可见的输出。 注意看看字节数。

`/dev/random` 和 `/dev/urandom` 设备也很有趣。 正如它们的名字所暗示的，它们都产生随机输出，不仅仅是数字，而是任何字节组合。 `/dev/urandom` 设备产生的是**确定性**的随机输出，并且非常快。 这意味着输出由算法确定，并使用种子字符串作为起点。 结果，如果原始种子是已知的，则黑客可以再现输出，尽管非常困难，但这是有可能的。 使用命令 `cat /dev/urandom` 可以查看典型的输出，使用 `Ctrl-c` 退出。

`/dev/random` 设备文件生成**非确定性**的随机输出，但它产生的输出更慢一些。 该输出不是由依赖于先前数字的算法确定的，而是由击键动作和鼠标移动而产生的。 这种方法使得复制特定系列的随机数要困难得多。使用 `cat` 命令去查看一些来自 `/dev/random` 设备文件输出。尝试移动鼠标以查看它如何影响输出。

正如其名字所暗示的，`/dev/zero` 设备文件产生一个无止境的零作为输出。 注意，这些是八进制零，而不是ASCII字符零（`0`）。 使用如下所示的 `dd` 查看 `/dev/zero` 设备文件中的一些输出

```
# dd if=/dev/zero  bs=512 count=500 | od -c
0000000  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
500+0 records in
500+0 records out
256000 bytes (256 kB, 250 KiB) copied, 0.00126996 s, 202 MB/s
0764000

```

请注意，此命令的字节数不为零。

### 创建设备文件

在过去，在 `/dev` 中的设备文件都是在安装时创建的，导致一个目录中有几乎所有的设备文件，尽管大多数文件永远不会用到。 在不常发生的情况，例如需要新的设备文件，或意外删除后需要重新创建设备文件，可以使用 `mknod` 程序手动创建设备文件。 前提是你必须知道设备的主要和次要号码。

CentOS 和 RHEL 6、7，以及 Fedora 的所有版本——可以追溯到至少 Fedora 15，使用较新的创建设备文件的方法。 所有设备文件都是在引导时创建的。 这是因为 udev 设备管理器在设备添加和删除发生时会进行检测。这可实现在主机启动和运行时的真正的动态即插即用功能。 它还在引导时执行相同的任务，通过在引导过程的很早的时期检测系统上安装的所有设备。 [Linux.com](https://www.linux.com/) 上有一篇很棒的对 [udev 的描述](https://www.linux.com/news/udev-introduction-device-management-modern-linux-system)。

回到 `/dev` 中的文件列表，注意文件的日期和时间。 所有文件都是在上次启动时创建的。 您可以使用 `uptime` 或者 `last` 命令来验证这一点。在上面我的设备列表中，所有这些文件都是在 11 月 7 日上午 7:06 创建的，这是我最后一次启动系统。

当然， `mknod` 命令仍然可用, 但新的 `MAKEDEV` （是的，所有字母大写，在我看来是违背 Linux 使用小写命令名的原则的) 命令提供了一个创建设备文件的更容易的界面。 在当前版本的 Fedora 或 CentOS 7 中，默认情况下不安装 `MAKEDEV` 命令；它安装在 CentOS 6。您可以使用 YUM 或 DNF 来安装 MAKEDEV 包。

### 结论

有趣的是，我很久没有创建一个设备文件的需要了。 然而，最近我遇到一个有趣的情况，其中一个我常使用的设备文件没有创建，我不得不创建它。 之后该设备再没出过问题。所以丢失设备文件的情况仍然可以发生，知道如何处理它可能很重要。

设备文件有无数种，您遇到的设备文件我可能没有涵盖到。 这些信息在所下面引用的资源中有大量的细节信息可用。 关于这些文件的功能和工具，我希望我已经给您一些基本的了解，下一步您自己可以探索更多。

### 资源

* [一切皆文件](https://opensource.com/life/15/9/everything-is-a-file)， David Both, Opensource.com
* [Linux 文件系统介绍](https://opensource.com/life/16/10/introduction-linux-filesystems)， David Both, Opensource.com
* [文件系统层次结构](http://www.tldp.org/LDP/Linux-Filesystem-Hierarchy/html/dev.html)， The Linux Documentation Project
* [设备文件](https://en.wikipedia.org/wiki/Device_file)， Wikipedia
* [Linux 下已分配设备](https://www.kernel.org/doc/Documentation/devices.txt)， Kernel.org

---

via: <https://opensource.com/article/16/11/managing-devices-linux>

作者：[David Both](https://opensource.com/users/dboth) 译者：[erlinux](http://www.itxdm.me) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译，[Linux中国](https://linux.cn/) 荣誉推出


在 Linux 终端中自定义 Bash 配色和提示内容

我是在 ~./.bashrc 中这样的写的： PS1="\e[;1;31m[\u@\h \W]$\e[0m "，写完后发现 CTRL + ｕ　不好用了，前面总是留一段，清除不干净了，不知道是为什么？

sorry,更正一个错误：~/.bashrc

0m 双引号之间有个空格。不过留个空格挺好。

现今，大多数（如果不是全部的话）现代 Linux 发行版的默认 shell 都是 Bash。然而，你可能已经注意到这样一个现象，在各个发行版中，其终端配色和提示内容都各不相同。

![](/data/attachment/album/201701/09/140539jkj67m8no8nqm336.jpg)

如果你一直都在考虑，或者只是一时好奇，如何定制可以使 Bash 更好用。不管怎样，请继续读下去 —— 本文将告诉你怎么做。

### PS1 Bash 环境变量

命令提示符和终端外观是通过一个叫 `PS1` 的变量来进行管理的。根据 **Bash** 手册页说明，**PS1** 代表了 shell 准备好读取命令时显示的主体的提示字符串。

**PS1** 所允许的内容包括一些反斜杠转义的特殊字符，可以查看手册页中 **PRMPTING** 部分的内容来了解它们的含义。

为了演示，让我们先来显示下我们系统中 `PS1` 的当前内容吧（这或许看上去和你们的有那么点不同）：

```
$ echo $PS1
[\u@\h \W]\$

```

现在，让我们来了解一下怎样自定义 PS1 吧，以满足我们各自的需求。

#### 自定义 PS1 格式

根据手册页 PROMPTING 章节的描述，下面对各个特殊字符的含义作如下说明：

* `\u:` 显示当前用户的 **用户名**。
* `\h:` <ruby> 完全限定域名 <rt>  Fully-Qualified Domain Name </rt></ruby>（FQDN）中第一个点（`.`）之前的**主机名**。
* `\W:` 当前工作目录的**基本名**，如果是位于 `$HOME` （家目录）通常使用波浪符号简化表示（`~`）。
* `\$:` 如果当前用户是 root，显示为 `#`，否则为 `$`。

例如，如果我们想要显示当前命令的历史数量，可以考虑添加 `\!`；如果我们想要显示 FQDN 全称而不是短服务器名，那么可以考虑添加 `\H`。

在下面的例子中，我们同时将这两个特殊字符引入我们当前的环境中，命令如下：

```
PS1="[\u@\H \W \!]\$"

```

当按下回车键后，你将会看到提示内容会变成下面这样。可以对比执行命令修改前和修改后的提示内容：

![Customize Linux Terminal Prompt PS1](/data/attachment/album/201701/09/140546f1h34y8obggomn1i.png)

*自定义 Linux 终端提示符 PS1*

现在，让我们再深入一点，修改命令提示符中的用户名和主机名 —— 同时修改文本和环境背景。

实际上，我们可以对提示符进行 3 个方面的自定义：

| 文本格式 | 前景色（文本） | 背景色 |
| --- | --- | --- |
| 0: 常规文本 | 30: 黑色 | 40: 黑色 |
| 1: 加粗文本 | 31: 红色 | 41: 红色 |
| 4: 下划线文本 | 32: 绿色 | 42: 绿色 |
|  | 33: 黄色 | 43: 黄色 |
|  | 34: 蓝色 | 44: 蓝色 |
|  | 35: 紫色 | 45: 紫色 |
|  | 36: 青色 | 46: 青色 |
|  | 37: 白色 | 47: 白色 |

我们将在开头使用 `\e` 特殊字符，跟着颜色序列，在结尾使用 `m` 来表示结束。

在该序列中，三个值（**背景**，**格式**和**前景**）由分号分隔（如果不赋值，则假定为默认值）。

**建议阅读：** [在 Linux 中学习 Bash shell 脚本](http://www.tecmint.com/category/bash-shell/)。

此外，由于值的范围不同，指定背景，格式，或者前景的先后顺序没有关系。

例如，下面的 `PS1` 将导致提示符为黄色带下划线文本，并且背景为红色：

```
PS1="\e[41;4;33m[\u@\h \W]$ "

```

![Change Linux Terminal Color Prompt PS1](/data/attachment/album/201701/09/140548xfv4urwrtsuctnlw.png)

*修改 Linux 终端提示符配色 PS1*

虽然它看起来那么漂亮，但是这个自定义将只会持续到当前用户会话结束。如果你关闭终端，或者退出本次会话，所有修改都会丢失。

为了让修改永久生效，你必须将下面这行添加到 `~/.bashrc`或者 `~/.bash_profile`，这取决于你的版本。

```
PS1="\e[41;4;33m[\u@\h \W]$ "

```

尽情去玩耍吧，你可以尝试任何色彩，直到找出最适合你的。

（LCTT 译注：原文的这种设置，不但会影响到提示符，也会影响到输入和显示的其它文字，因此应该在 PS1 设置中使用 `\e[0m` 来结束颜色设置。如：`PS1="\e[41;4;33m[\u@\h \W]$\e[0m "`）

### 小结

在本文中，我们讲述了如何来自定义 Bash 提示符的配色和提示内容。如果你对本文还有什么问题或者建议，请在下面评论框中写下来吧。我们期待你们的声音。

---

作者简介：

![](/data/attachment/album/201701/09/140549m3zrdx727slkr67x.jpg) Aaron Kili 是一位 Linux 及 F.O.S.S 的狂热爱好者，一位未来的 Linux 系统管理员，web 开发者，而当前是 TechMint 的原创作者，他热爱计算机工作，并且信奉知识分享。

---

via: <http://www.tecmint.com/customize-bash-colors-terminal-prompt-linux/>

作者：[Aaron Kili](http://www.tecmint.com/author/aaronkili/) 译者：[GOLinux](https://github.com/GOLinux) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


完全指南之在 Ubuntu 操作系统中安装及卸载软件

总结的很详细，学习～～～

很好的文字。还是apt最好!

评论窗口很漂亮。

哈哈，总算有人夸奖了！

多谢译者，也谢谢原作者！网站做得非常漂亮！

:D

新人感觉很受用，谢谢

习惯源码了

![](/data/attachment/album/201701/09/211952posajmlfha6j0wwx.jpg)

>
> 摘要：这篇文章详尽地说明了在 Ubuntu Linux 系统中安装及卸载软件的各种方法。
>
>
>

当你从 Windows 系统[转向 Linux 系统](https://itsfoss.com/reasons-switch-linux-windows-xp/)的时候，刚开始的体验绝对是非比寻常的。在 Ubuntu 系统下就连最基本的事情，比如安装个应用程序都会让（刚从 Windows 世界来的）人感到无比困惑。

但是你也不用太担心。因为 Linux 系统提供了各种各样的方法来完成同样的任务，刚开始你感到困惑那也是正常的。你并不孤单，我们大家都是这么经历过来的。

在这篇初学者指南中，我将会教大家在 Ubuntu 系统里如何以最常用的方式来安装软件，以及如何卸载之前已安装的软件。

关于在 Ubuntu 上应使用哪种方法来安装软件，我也会提出自己的建议。请用心学习。这篇文章写得很长也很详细，你从中绝对能够学到东西。

### 在 Ubuntu 系统中安装和卸载软件

在这篇教程中我使用的是运行着 Unity 桌面环境的 Ubuntu 16.04 版本的系统。除了一些截图外，这篇教程也同样适用于其它版本的 Ubuntu 系统。

### 1.1 使用 Ubuntu 软件中心来安装软件（推荐方式）

在 Ubuntu 系统中查找和安装软件最简单便捷的方法是使用 Ubuntu 软件中心。在 Ubuntu Unity 桌面里，你可以在 Dash 下搜索 Ubuntu 软件中心，然后选中打开即可：

![](/data/attachment/album/201701/09/212118y7wdkoo6ogcg2ngk.png)

你可以把 Ubuntu 软件中心想像成 Google 的 Play 商店或者是苹果的 App 商店。它包含 Ubuntu 系统下所有可用的软件。你可以通过应用程序的名称来搜索应用程序或者是通过浏览各种软件目录来进行查找软件。你还可以根据作者进行查询。这由你自己来选择。

![](/data/attachment/album/201701/09/212201mguqf43fpzhlh400.jpeg)

一旦你找到自己想要的应用程序，选中它。软件中心将打开该应用程序的描述页面。你可以阅读关于这款软件的说明，评分等级和用户的评论。如果你愿意，也可以写一条评论。

一旦你确定想安装这款软件，你可以点击安装按钮来安装已选择的应用程序。在 Ubuntu 系统中，你需要输入 root 账号的密码才能安装该应用程序。

![](/data/attachment/album/201701/09/212319w3smj7u7b3ambu13.jpg)

还有什么比这更简单的吗？我觉得应该没有了吧！

提示：正如我[在 Ubuntu 16.04 系统安装完成后你需要做的事情](https://itsfoss.com/things-to-do-after-installing-ubuntu-16-04/)这篇文章提到的那样，你应该启用 Canonical 合作伙伴仓库。默认情况下，Ubuntu 系统仅提供了那些源自自身软件库（Ubuntu 认证）的软件。

但是还有一个 Canonical 合伙伙伴软件库，它包含一些闭源专属软件，Ubuntu 并不直接管控它。启用该仓库后将让你能够访问更多的软件。[在 Ubuntu 系统下安装 Skype 软件](https://itsfoss.com/install-skype-ubuntu-1404/)就是通过那种方式安装完成的。

在 Unity Dash 中，找到软件或更新工具。

![](/data/attachment/album/201701/09/212621nif9q3hfyzu12fyl.jpeg)

如下图，打开其它软件标签面，勾选 Canonical 合作伙伴选项。

![](/data/attachment/album/201701/09/212644mk8bdksvrt0zgszf.jpeg)

### 1.2 从 Ubuntu 软件中心卸载软件（推荐方式）

我们刚刚演示了如何在 Ubuntu 软件中心安装软件。那么如何使用同样的方法来卸载已安装的软件呢？

在 Ubuntu 软件中心卸载软件跟安装软件的步骤一样简单。

打开软件中心然后点击已安装的软件标签面。它将显示所有已安装的软件。或者，你也可以只搜索应用程序的名称。

要卸载 Ubuntu 系统中的应用程序，点击删除按钮即中。你同样需要输入 root 账号的密码。

![](/data/attachment/album/201701/09/212736xwtwb9q0au9qgg7g.jpeg)

### 2.1 在 Ubuntu 系统中使用 .deb 文件来安装软件

.deb 文件跟 Windows 下的 .exe 文件很相似。这是一种安装软件的简易方式。很多软件开发商都会提供 .deb 格式的安装包。

Google Chrome 浏览器就是这样的。你可以下载从其官网下载 .deb 安装文件

![](/data/attachment/album/201701/09/212821lor1cofo2sro2sjg.png)

一旦你下载完成 .deb 安装文件之后，只需要双击运行即可。它将在 Ubuntu 软件中心打开，你就可以使用前面 1.1 节中同样的方式来安装软件。

或者，你也可以使用轻量级的安装程序 [在 Ubuntu 系统中使用 Gdebi 工具来安装 .deb 安装文件](https://itsfoss.com/gdebi-default-ubuntu-software-center/)。

软件安装完成后，你可以随意删除下载的 .deb 安装包。

提示：在使用 .deb 文件的过程中需要注意的一些问题：

* 确保你是从官网下载的 .deb 安装文件。仅使用官网或者 GitHub 上提供的软件包。
* 确保你下载的 .deb 文件系统类型正确（32 位或是 64 位）。请阅读我们写的快速指南：[如何查看你的 Ubuntu 系统是 32 位的还是 64 位的](https://itsfoss.com/32-bit-64-bit-ubuntu/)。

### 2.2 使用 .deb 文件来删除已安装的软件

卸载 .deb 文件安装的软件跟我们在 1.2 节看到的步骤一样的。只需要打开 Ubuntu 软件中心，搜索应用程序名称，然后单击移除并卸载即可。

或者你也可以使用[新立得包管理器](http://www.nongnu.org/synaptic/)。这也不是必须的，但是如果在 Ubuntu 软件中心找不到已安装的应用程序的情况下，就可以使用这个工具了。新立得软件包管理器会列出你系统里已安装的所有可用的软件。这是一个非常强大和有用的工具。

这个工具很强大非常有用。在 Ubuntu 软件中心被开发出来提供一种更友好的安装软件方式之前，新立得包管理器是 Ubuntu 系统中默认的安装和卸载软件的工具。

你可以单击下面的链接来安装新立得软件包管器（它将会在 Ubuntu 软件中心中打开）。

* [安装新立得包管理器](apt://synaptic)

打开新立得包管理器，然后找到你想卸载的软件。已安装的软件标记为绿色按钮。单击并选择“标记为删除”。然后单击“应用”来删除你所选择的软件。

![](/data/attachment/album/201701/09/212926mjxlh5ls9sjrpsxs.jpeg)

### 3.1 在 Ubuntu 系统中使用 apt 命令来安装软件（推荐方式）

你应该看到过一些网站告诉你使用 `sudo apt-get install` 命令在 Ubuntu 系统下安装软件。

实际上这种命令行方式跟第 1 节中我们看到的安装方式一样。只是你没有使用 Ubuntu 软件中心来安装或卸载软件，而是使用的是命令行接口。别的没什么不同。

使用 `apt-get` 命令来安装软件超级简单。你只需要执行下面的命令：

```
sudo apt-get install package_name

```

上面使用 `sudo` 是为了获取“管理员”或 “root” （Linux 专用术语）账号权限。你可以替换 package\_name 为你想要安装的软件包名。

`apt-get` 命令可以自动补全，你只需要输入一些字符并按 tab 键即可， `apt-get` 命令将会列出所有与该字符相匹配的程序。

### 3.2 在 Ubuntu 系统下使用 apt 命令来卸载软件（推荐方式）

在命令行下，你可以很轻易的卸载 Ubuntu 软件中心安装的软件，以及使用 `apt` 命令或是使用 .deb 安装包安装的各种软件。

你只需要使用下面的命令，替换 package-name 为你想要删除的软件名。

```
sudo apt-get remove package_name

```

同样地，你也可以通过按 tab 键来利用 `apt-get` 命令的自动补全功能。

使用 `apt-get` 命令来安装卸载或卸载并不算什么高深的技能。这实际上非常简便。通过这些简单命令的运用，你可以熟悉 Ubuntu Linux 系统的命令行操作，长期使用对你学习 Linux 系统的帮忙也很大。建议你看下我写的一篇很详细的[apt-get 命令使用指导](https://itsfoss.com/apt-get-linux-guide/)文章来进一步的了解该命令的使用。

* 建议阅读：[Linux 系统下 apt-get 命令初学者完全指南](https://itsfoss.com/apt-get-linux-guide/)

### 4.1 使用 PPA 命令在 Ubuntu 系统下安装应用程序

PPA 是<ruby> <a href="https://help.launchpad.net/Packaging/PPA">  个人软件包归档 </a> <rp>  （ </rp> <rt>  Personal Package Archive </rt> <rp>  ） </rp></ruby>的缩写。这是开发者为 Ubuntu 用户提供软件的另一种方式。

在第 1 节中出现了一个叫做 ‘<ruby> 仓库 <rp>  （ </rp> <rt>  repository </rt> <rp>  ） </rp></ruby>’ 的术语。仓库本质上是一个软件集。 Ubuntu 官方仓库主要用于提供经过 Ubuntu 自己认证过的软件。 Canonical 合作伙伴仓库包含来自合作厂商提供的各种应用软件。

同时，PPA 允许开发者创建自己的 APT 仓库。当用户在系统里添加了一个仓库时（`sources.list` 中增加了该仓库），用户就可以使用开发者自己的仓库里提供的软件了。

现在你也许要问既然我们已经有 Ubuntu 的官方仓库了，还有什么必要使用 PPA 方式呢？

答案是并不是所有的软件都会自动添加到 Ubuntu 的官方仓库中。只有受信任的软件才会添加到其中。假设你开发出一款很棒的 Linux 应用程序，然后你想为用户提供定期的更新，但是在它被添加到 Ubuntu 仓库之前，这需要花费好几个月的时间（如果是在被允许的情况下）。 PPA 的出现就是为了解决这个问题。

除此之外， Ubuntu 官方仓库通常不会把最新版的软件添加进来。这会影响到 Ubuntu 系统的安全性及稳定性。新版本的软件或许会有影响到系统的[回退](https://en.wikipedia.org/wiki/Software_regression)。这就是为什么在新款软件进入到官方仓库前要花费一定的时间，有时候需要等待几个月。

但是，如果你不想等待最新版出现在 Ubuntu 仓库中呢？这个时候 PPA 就对你有帮助了。通过 PPA 方式，你可以获得该应用程序的最新版本。

通常情况下， PPA 通过这三个命令来进行使用。第一个命令添加 PPA 仓库到源列表中。第二个命令更新软件缓存列表，这样你的系统就可以获取到可用的新版本软件了。第三个命令用于从 PPA 安装软件。

我将演示使用 PPA 方式来安装 [Numix 主题](https://itsfoss.com/install-numix-ubuntu/)：

```
sudo add-apt-repository ppa:numix/ppa
sudo apt-get update
sudo apt-get install numix-gtk-theme numix-icon-theme-circle

```

在上面的实例中，我们添加了一个[Numix 项目](https://numixproject.org/)提供的 PPA 。在更新软件信息之后，我们安装了两个 Numix PPA 中可用的应用程序。

如果你想使用带有图形界面的应用程序，你可以使用 [Y-PPA 应用程序](https://itsfoss.com/easily-manage-ppas-ubuntu-1310-ppa-manager/)。通过它你可以很方便地查询 PPA，添加和删除软件。

注意：PPA 的安全性经常受到争议。我的建议是你应该从受信任的源添加 PPA，最好是从官方软件源添加。

### 4.2 卸载使用 PPA 方式安装的应用程序

在之前的文章[在 Ubuntu 系统下移除 PPA](https://itsfoss.com/how-to-remove-or-delete-ppas-quick-tip/) 中我已经写得很详细了。你可以跳转到这篇文章去深入学习卸载 PPA 方式安装的软件。

这里简要提一下，你可以使用下面的两个命令来卸载：

```
sudo apt-get remove numix-gtk-theme numix-icon-theme-circle

sudo add-apt-repository --remove ppa:numix/ppa

```

第一个命令是卸载通过 PPA 方式安装的软件。第二个命令是从 `source.list` 中删除该 PPA。

### 5.1 在 Ubuntu Linux 系统中使用源代码来安装软件（不推荐使用）

我并不建议你使用[软件源代码](https://en.wikipedia.org/wiki/Source_code)来安装该应用程序。这种方法很麻烦，容易出问题而且还非常地不方便。你得费尽周折去解决依赖包的问题。你还得保留源代码文件，以便将来卸载该应用程序。

但是还是有一些用户喜欢通过源代码编译的方式来安装软件，尽管他们自己本身并不会开发软件。实话告诉你，我曾经也经常使用这种方式来安装软件，不过那都是 5 年前的事了，那时候我还是一个实习生，我必须在 Ubuntu 系统下开发一款软件出来。但是，从那之后我更喜欢使用其它方式在 Ubuntu 系统中安装应用程序。我觉得，对于普通的 Linux 桌面用户，最好不要使用源代码的方式来安装软件。

在这一小节中我将简要地列出使用源代码方式来安装软件的几个步骤：

* 下载你想要安装软件的源代码。
* 解压下载的文件。
* 进入到解压目录里并找到 `README` 或者 `INSTALL` 文件。一款开发完善的软件都会包含这样的文件，用于提供安装或卸载软件的指导方法。
* 找到名为 `configure` 的配置文件。如果在当前目录下，使用这个命令来执行该文件：`./configure` 。它将会检查你的系统是否包含所有的必须的软件（在软件术语中叫做‘依赖包’）来安装该应用程序。（LCTT 译注：你可以先使用 `./configure --help` 来查看有哪些编译选项，包括安装的位置、可选的特性和模块等等。）注意并不是所有的软件都包括该配置文件，我觉得那些开发很糟糕的软件就没有这个配置文件。
* 如果配置文件执行结果提示你缺少依赖包，你得先安装它们。
* 一旦你安装完成所有的依赖包后，使用 `make` 命令来编译该应用程序。
* 编译完成后，执行 `sudo make install` 命令来安装该应用程序。

注意有一些软件包会提供一个安装软件的脚本文件，你只需要运行这个文件即可安装完成。但是大多数情况下，你可没那么幸运。

还有，使用这种方式安装的软件并不会像使用 Ubuntu 软件库、 PPA 方式或者 .deb 安装方式那样安装的软件会自动更新。

如果你坚持使用源代码方式来安装软件，我建议你看下这篇很详细的文章[在 Ubuntu 系统中使用源代码安装软件](http://www.howtogeek.com/105413/how-to-compile-and-install-from-source-on-ubuntu/)。

### 5.2 卸载使用源代码方式安装的软件（不推荐使用）

如果你觉得使用源代码安装软件的方式太难了，再想想看，当你卸载使用这种方式安装的软件将会更痛苦。

* 首先，你不能删除用于安装该软件的源代码。
* 其次，你必须确保在安装的时候也有对应的方式来卸载它。一款设计上很糟糕的应用程序就不会提供卸载软件的方法，因此你不得不手动去删除那个软件包安装的所有文件。

正常情况下，你应该切换到源代码的解压目录下，使用下面的命令来卸载那个应用程序：

```
sudo make uninstall

```

但是，这也不能保证你每次都会很顺利地卸载完成。

看到了吧，使用源代码方式来安装软件实在是太麻烦了。这就是为什么我不推荐大家在 Ubuntu 系统中使用源代码来安装软件的原因。

### 其它一些在 Ubuntu 系统中安装软件的方法

另外，还有一些在 Ubuntu 系统下并不常用的安装软件的方法。由于这篇文章已经写得够长了，我就不再深入探讨了。下面我将把它们列出来：

* Ubuntu 新推出的 [Snap 打包](https://itsfoss.com/use-snap-packages-ubuntu-16-04/)方式
* 使用 [dpkg](https://help.ubuntu.com/lts/serverguide/dpkg.html) 命令
* [AppImage](http://appimage.org/) 方式
* [pip](https://pypi.python.org/pypi/pip) : 用于安装基于 Python 语言的应用程序

### 你是如何在 UBUNTU 系统中安装软件的呢？

如果你一直都在使用 Ubuntu 系统，那么你在 Ubuntu Linux 系统下最喜欢使用什么方式来安装软件呢？你觉得这篇文章对你有用吗？请分享你的一些观点，建议和提出相关的问题。

---

作者简介：

![](/data/attachment/album/201701/09/213150jbsjve7jczbl5mc7.jpg) 我叫 Abhishek Prakash ，F.O.S.S 开发者。我的工作是一名专业的软件开发人员。我是一名狂热的 Linux 系统及开源软件爱好者。我使用 Ubuntu 系统，并且相信分享是一种美德。除了 Linux 系统之外，我喜欢经典的侦探神秘小说。我是 Agatha Christie 作品的真爱粉。

---

via: <https://itsfoss.com/remove-install-software-ubuntu/>

作者：[ABHISHEK PRAKASH](https://itsfoss.com/author/abhishek/) 译者：[rusking](https://github.com/rusking) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


LXD 2.0 系列（五）：镜像管理

这是 LXD 2.0 系列介绍文章的第五篇。

1. [LXD 入门](/article-7618-1.html)
2. [安装与配置](/article-7687-1.html)
3. [你的第一个 LXD 容器](/article-7706-1.html)
4. [资源控制](/article-8072-1.html)
5. [镜像管理](/article-8107-1.html)
6. [远程主机及容器迁移](/article-8169-1.html)
7. [LXD 中的 Docker](/article-8235-1.html)
8. [LXD 中的 LXD](/article-8257-1.html)
9. [实时迁移](/article-8263-1.html)
10. [LXD 和 Juju](/article-8273-1.html)
11. [LXD 和 OpenStack](/article-8274-1.html)
12. [调试，及给 LXD 做贡献](/article-8282-1.html)

因为 lxd 容器管理有很多命令，因此这篇文章会很长。 如果你想要快速地浏览这些相同的命令，你可以[尝试下我们的在线演示](https://github.com/lxc/lxd/blob/master/doc/image-handling.md)！

![](/data/attachment/album/201701/10/123549kvzn000etv0ffeat.jpg)

### 容器镜像

如果你以前使用过 LXC，你可能还记得那些 LXC “模板”，基本上都是导出一个容器文件系统以及一点配置的 shell 脚本。

大多数模板是通过在本机上执行一个完整的发行版自举来生成该文件系统。这可能需要相当长的时间，并且无法在所有的发行版上可用，另外可能需要大量的网络带宽。

回到 LXC 1.0，我写了一个“下载”模板，它允许用户下载预先打包的容器镜像，用模板脚本在中央服务器上生成，接着高度压缩、签名并通过 https 分发。我们很多用户从旧版的容器生成方式切换到了使用这种新的、更快更可靠的创建容器的方式。

使用 LXD，我们通过全面的基于镜像的工作流程向前迈进了一步。所有容器都是从镜像创建的，我们在 LXD 中具有高级镜像缓存和预加载支持，以使镜像存储保持最新。

### 与 LXD 镜像交互

在更深入了解镜像格式之前，让我们快速了解下 LXD 可以让你做些什么。

#### 透明地导入镜像

所有的容器都是由镜像创建的。镜像可以来自一台远程服务器并使用它的完整 hash、短 hash 或者别名拉取下来，但是最终每个 LXD 容器都是创建自一个本地镜像。

这有个例子：

```
lxc launch ubuntu:14.04 c1
lxc launch ubuntu:75182b1241be475a64e68a518ce853e800e9b50397d2f152816c24f038c94d6e c2
lxc launch ubuntu:75182b1241be c3

```

所有这些引用相同的远程镜像（在写这篇文章时），在第一次运行这些命令其中之一时，远程镜像将作为缓存镜像导入本地 LXD 镜像存储，接着从其创建容器。

下一次运行其中一个命令时，LXD 将只检查镜像是否仍然是最新的（当不是由指纹引用时），如果是，它将创建容器而不下载任何东西。

现在镜像被缓存在本地镜像存储中，你也可以从那里启动它，甚至不检查它是否是最新的：

```
lxc launch 75182b1241be c4

```

最后，如果你有个名为“myimage”的本地镜像，你可以：

```
lxc launch my-image c5

```

如果你想要改变一些自动缓存或者过期行为，在本系列之前的文章中有[一些命令](/article-7687-1.html)。

#### 手动导入镜像

##### 从镜像服务器中复制

如果你想复制远程的某个镜像到你本地镜像存储，但不立即从它创建一个容器，你可以使用`lxc image copy`命令。它可以让你调整一些镜像标志，比如：

```
lxc image copy ubuntu:14.04 local:

```

这只是简单地复制一个远程镜像到本地存储。

如果您想要通过比记住其指纹更容易的方式来记住你引用的镜像副本，则可以在复制时添加别名：

```
lxc image copy ubuntu:12.04 local: --alias old-ubuntu
lxc launch old-ubuntu c6

```

如果你想要使用源服务器上设置的别名，你可以要求 LXD 复制下来：

```
lxc image copy ubuntu:15.10 local: --copy-aliases
lxc launch 15.10 c7

```

上面的副本都是一次性拷贝，也就是复制远程镜像的当前版本到本地镜像存储中。如果你想要 LXD 保持镜像最新，就像它在缓存中存储的那样，你需要使用 `–auto-update` 标志：

```
lxc image copy images:gentoo/current/amd64 local: --alias gentoo --auto-update

```

##### 导入 tarball

如果某人给你提供了一个单独的 tarball，你可以用下面的命令导入：

```
lxc image import <tarball>

```

如果你想在导入时设置一个别名，你可以这么做：

```
lxc image import <tarball> --alias random-image

```

现在如果你被给了两个 tarball，要识别哪个是含有 LXD 元数据的。通常可以通过 tarball 的名称来识别，如果不行就选择最小的那个，元数据 tarball 包是很小的。 然后将它们一起导入：

```
lxc image import <metadata tarball> <rootfs tarball>

```

##### 从 URL 中导入

`lxc image import` 也可以与指定的 URL 一起使用。如果你的一台 https Web 服务器的某个路径中有 `LXD-Image-URL` 和 `LXD-Image-Hash` 的标头设置，那么 LXD 就会把这个镜像拉到镜像存储中。

可以参照例子这么做：

```
lxc image import https://dl.stgraber.org/lxd --alias busybox-amd64

```

当拉取镜像时，LXD 还会设置一些标头，远程服务器可以检查它们以返回适当的镜像。 它们是 `LXD-Server-Architectures` 和 `LXD-Server-Version`。

这相当于一个简陋的镜像服务器。 它可以通过任何静态 Web 服务器提供一中用户友好的导入镜像的方式。

#### 管理本地镜像存储

现在我们本地已经有一些镜像了，让我们瞧瞧可以做些什么。我们已经介绍了最主要的部分，可以从它们来创建容器，但是你还可以在本地镜像存储上做更多。

##### 列出镜像

要列出所有的镜像，运行 `lxc image list`：

```
stgraber@dakara:~$ lxc image list
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
|     ALIAS     | FINGERPRINT  | PUBLIC |                     DESCRIPTION                      |  ARCH  |   SIZE   |         UPLOAD DATE          |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| alpine-32     | 6d9c131efab3 | yes    | Alpine edge (i386) (20160329_23:52)                  | i686   | 2.50MB   | Mar 30, 2016 at 4:36am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| busybox-amd64 | 74186c79ca2f | no     | Busybox x86_64                                       | x86_64 | 0.79MB   | Mar 30, 2016 at 4:33am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| gentoo        | 1a134c5951e0 | no     | Gentoo current (amd64) (20160329_14:12)              | x86_64 | 232.50MB | Mar 30, 2016 at 4:34am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| my-image      | c9b6e738fae7 | no     | Scientific Linux 6 x86_64 (default) (20160215_02:36) | x86_64 | 625.34MB | Mar 2, 2016 at 4:56am (UTC)  |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| old-ubuntu    | 4d558b08f22f | no     | ubuntu 12.04 LTS amd64 (release) (20160315)          | x86_64 | 155.09MB | Mar 30, 2016 at 4:30am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| w (11 more)   | d3703a994910 | no     | ubuntu 15.10 amd64 (release) (20160315)              | x86_64 | 153.35MB | Mar 30, 2016 at 4:31am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
|               | 75182b1241be | no     | ubuntu 14.04 LTS amd64 (release) (20160314)          | x86_64 | 118.17MB | Mar 30, 2016 at 4:27am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+

```

你可以通过别名或者指纹来过滤：

```
stgraber@dakara:~$ lxc image list amd64
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+
|     ALIAS     | FINGERPRINT  | PUBLIC |               DESCRIPTION               |  ARCH  |   SIZE   |          UPLOAD DATE         |
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+
| busybox-amd64 | 74186c79ca2f | no     | Busybox x86_64                          | x86_64 | 0.79MB   | Mar 30, 2016 at 4:33am (UTC) |
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+
| w (11 more)   | d3703a994910 | no     | ubuntu 15.10 amd64 (release) (20160315) | x86_64 | 153.35MB | Mar 30, 2016 at 4:31am (UTC) |
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+

```

或者指定一个镜像属性中的键值对来过滤：

```
stgraber@dakara:~$ lxc image list os=ubuntu
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
|    ALIAS    | FINGERPRINT  | PUBLIC |                  DESCRIPTION                |  ARCH  |   SIZE   |          UPLOAD DATE         |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
| old-ubuntu  | 4d558b08f22f | no     | ubuntu 12.04 LTS amd64 (release) (20160315) | x86_64 | 155.09MB | Mar 30, 2016 at 4:30am (UTC) |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
| w (11 more) | d3703a994910 | no     | ubuntu 15.10 amd64 (release) (20160315)     | x86_64 | 153.35MB | Mar 30, 2016 at 4:31am (UTC) |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
|             | 75182b1241be | no     | ubuntu 14.04 LTS amd64 (release) (20160314) | x86_64 | 118.17MB | Mar 30, 2016 at 4:27am (UTC) |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+

```

要了解镜像的所有信息，你可以使用`lxc image info`：

```
stgraber@castiana:~$ lxc image info ubuntu
Fingerprint: e8a33ec326ae7dd02331bd72f5d22181ba25401480b8e733c247da5950a7d084
Size: 139.43MB
Architecture: i686
Public: no
Timestamps:
 Created: 2016/03/15 00:00 UTC
 Uploaded: 2016/03/16 05:50 UTC
 Expires: 2017/04/26 00:00 UTC
Properties:
 version: 12.04
 aliases: 12.04,p,precise
 architecture: i386
 description: ubuntu 12.04 LTS i386 (release) (20160315)
 label: release
 os: ubuntu
 release: precise
 serial: 20160315
Aliases:
 - ubuntu
Auto update: enabled
Source:
 Server: https://cloud-images.ubuntu.com/releases
 Protocol: simplestreams
 Alias: precise/i386

```

##### 编辑镜像

编辑镜像的属性和标志的简单方法是使用：

```
lxc image edit <alias or fingerprint>

```

这会打开默认文本编辑器，内容像这样：

```
autoupdate: true
properties:
 aliases: 14.04,default,lts,t,trusty
 architecture: amd64
 description: ubuntu 14.04 LTS amd64 (release) (20160314)
 label: release
 os: ubuntu
 release: trusty
 serial: "20160314"
 version: "14.04"
public: false

```

你可以修改任何属性，打开或者关闭自动更新，或者标记一个镜像是公共的（后面详述）。

##### 删除镜像

删除镜像只需要运行：

```
lxc image delete <alias or fingerprint>

```

注意你不必移除缓存对象，它们会在过期后被 LXD 自动移除（默认上，在最后一次使用的 10 天后）。

##### 导出镜像

如果你想得到目前镜像的 tarball，你可以使用`lxc image export`，像这样：

```
stgraber@dakara:~$ lxc image export old-ubuntu .
Output is in .
stgraber@dakara:~$ ls -lh *.tar.xz
-rw------- 1 stgraber domain admins 656 Mar 30 00:55 meta-ubuntu-12.04-server-cloudimg-amd64-lxd.tar.xz
-rw------- 1 stgraber domain admins 156M Mar 30 00:55 ubuntu-12.04-server-cloudimg-amd64-lxd.tar.xz

```

#### 镜像格式

LXD 现在支持两种镜像布局，unified 或者 split。这两者都是有效的 LXD 格式，虽然后者在与其他容器或虚拟机一起运行时更容易重用其文件系统。

LXD 专注于系统容器，不支持任何应用程序容器的“标准”镜像格式，我们也不打算这么做。

我们的镜像很简单，它们是由容器文件系统，以及包含了镜像制作时间、到期时间、什么架构，以及可选的一堆文件模板的元数据文件组成。

有关[镜像格式](https://github.com/lxc/lxd/blob/master/doc/image-handling.md)的最新详细信息，请参阅此文档。

##### unified 镜像（一个 tarball）

unified 镜像格式是 LXD 在生成镜像时使用的格式。它们是一个单独的大型 tarball，包含 `rootfs` 目录下的容器文件系统，在 tarball 根目录下有 `metadata.yaml` 文件，任何模板都放到 `templates` 目录。

tarball 可以用任何方式压缩（或者不压缩）。镜像散列是压缩后的 tarball 的 sha256 。

##### Split 镜像（两个 tarball）

这种格式最常用于滚动更新镜像并已经有了一个压缩文件系统 tarball 时。

它们由两个不同的 tarball 组成，第一个只包含 LXD 使用的元数据， `metadata.yaml` 文件在根目录，任何模板都在 `templates` 目录。

第二个 tarball 只包含直接位于其根目录下的容器文件系统。大多数发行版已经有这样的 tarball，因为它们常用于引导新机器。 此镜像格式允许不经修改就重用。

两个 tarball 都可以压缩（或者不压缩），它们可以使用不同的压缩算法。 镜像散列是元数据的 tarball 和 rootfs 的 tarball 结合的 sha256。

##### 镜像元数据

典型的 `metadata.yaml` 文件看起来像这样：

```
architecture: "i686"
creation_date: 1458040200
properties:
 architecture: "i686"
 description: "Ubuntu 12.04 LTS server (20160315)"
 os: "ubuntu"
 release: "precise"
templates:
 /var/lib/cloud/seed/nocloud-net/meta-data:
  when:
   - start
  template: cloud-init-meta.tpl
 /var/lib/cloud/seed/nocloud-net/user-data:
  when:
   - start
  template: cloud-init-user.tpl
  properties:
   default: |
    #cloud-config
    {}
 /var/lib/cloud/seed/nocloud-net/vendor-data:
  when:
   - start
  template: cloud-init-vendor.tpl
  properties:
   default: |
    #cloud-config
    {}
 /etc/init/console.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty1.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty2.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty3.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty4.override:
  when:
   - create
  template: upstart-override.tpl

```

##### 属性

两个唯一的必填字段是 `creation date`（UNIX 纪元时间）和 `architecture`。 其他都可以保持未设置，镜像就可以正常地导入。

额外的属性主要是帮助用户弄清楚镜像是什么。 例如 `description` 属性是在 `lxc image list` 中可见的。 用户可以使用其它属性的键/值对来搜索特定镜像。

相反，这些属性用户可以通过 `lxc image edit`来编辑，`creation date` 和 `architecture` 字段是不可变的。

##### 模板

模板机制允许在容器生命周期中的某一点生成或重新生成容器中的一些文件。

我们使用 [pongo2 模板引擎](https://github.com/flosch/pongo2)来做这些，我们将所有我们知道的容器信息都导出到模板。 这样，你可以使用用户定义的容器属性或常规 LXD 属性来自定义镜像，从而更改某些特定文件的内容。

正如你在上面的例子中看到的，我们使用在 Ubuntu 中使用它们来进行 `cloud-init` 并关闭一些 init 脚本。

### 创建你的镜像

LXD 专注于运行完整的 Linux 系统，这意味着我们期望大多数用户只使用干净的发行版镜像，而不是只用自己的镜像。

但是有一些情况下，你有自己的镜像是有必要的。 例如生产服务器上的预配置镜像，或者构建那些我们没有构建的发行版或者架构的镜像。

#### 将容器变成镜像

目前使用 LXD 构造镜像最简单的方法是将容器变成镜像。

可以这么做：

```
lxc launch ubuntu:14.04 my-container
lxc exec my-container bash
<do whatever change you want>
lxc publish my-container --alias my-new-image

```

你甚至可以将一个容器过去的快照变成镜像：

```
lxc publish my-container/some-snapshot --alias some-image

```

#### 手动构建镜像

构建你自己的镜像也很简单。

1. 生成容器文件系统。这完全取决于你使用的发行版。对于 Ubuntu 和 Debian，它将用于启动。
2. 配置容器中该发行版正常工作所需的任何东西（如果需要任何东西）。
3. 制作该容器文件系统的 tarball，可选择压缩它。
4. 根据上面描述的内容写一个新的 `metadata.yaml` 文件。
5. 创建另一个包含 `metadata.yaml` 文件的 tarball。
6. 用下面的命令导入这两个 tarball 作为 LXD 镜像：`lxc image import <metadata tarball> <rootfs tarball> --alias some-name`

在一切都正常工作前你可能需要经历几次这样的工作，调整这里或那里，可能会添加一些模板和属性。

### 发布你的镜像

所有 LXD 守护程序都充当镜像服务器。除非另有说明，否则加载到镜像存储中的所有镜像都会被标记为私有，因此只有受信任的客户端可以检索这些镜像，但是如果要创建公共镜像服务器，你需要做的是将一些镜像标记为公开，并确保你的 LXD 守护进程监听网络。

#### 只运行 LXD 公共服务器

最简单的共享镜像的方式是运行一个公共的 LXD 守护进程。

你只要运行：

```
lxc config set core.https_address "[::]:8443"

```

远程用户就可以添加你的服务器作为公共服务器：

```
lxc remote add <some name> <IP or DNS> --public

```

他们就可以像使用任何默认的镜像服务器一样使用它们。 由于远程服务器添加了 `-public` 选项，因此不需要身份验证，并且客户端仅限于使用已标记为 `public` 的镜像。

要将镜像设置成公共的，只需使用 `lxc image edit` 编辑它们，并将 `public` 标志设置为 `true`。

#### 使用一台静态 web 服务器

如上所述，`lxc image import` 支持从静态 https 服务器下载。 基本要求是：

* 服务器必须支持具有有效证书的 HTTPS、TLS 1.2 和 EC 算法。
* 当访问 `lxc image import` 提供的 URL 时，服务器必须返回一个包含 `LXD-Image-Hash` 和 `LXD-Image-URL` 的 HTTP 标头。

如果你想使它动态化，你可以让你的服务器查找 LXD 在请求镜像时发送的 `LXD-Server-Architectures` 和 `LXD-Server-Version` 的 HTTP 标头，这可以让你返回符合该服务器架构的正确镜像。

#### 构建一个简单流服务器

`ubuntu:` 和 `ubuntu-daily:` 远端服务器不使用 LXD 协议（`images:` 使用），而是使用称为简单流（simplestreams）的不同协议。

简单流基本上是一个镜像服务器的描述格式，使用 JSON 来描述产品以及相关产品的文件列表。

它被各种工具，如 OpenStack、Juju、MAAS 等用来查找、下载或者做镜像系统，LXD 将它作为用于镜像检索的原生协议。

虽然这的确不是提供 LXD 镜像的最简单的方法，但是如果你的镜像也被其它一些工具使用，那这也许值得考虑一下。

关于简单流的更多信息可以在[这里](https://launchpad.net/simplestreams)找到。

### 总结

我希望这篇关于如何使用 LXD 管理镜像以及构建和发布镜像文章让你有所了解。对于以前的 LXC 而言，可以在一组全球分布式系统上得到完全相同的镜像是一个很大的进步，并且引导了更多可复制性的发展方向。

### 额外信息

LXD 的主站在： <https://linuxcontainers.org/lxd>

LXD 的 GitHub 仓库： <https://github.com/lxc/lxd>

LXD 的邮件列表： <https://lists.linuxcontainers.org>

LXD 的 IRC 频道： #lxcontainers on irc.freenode.net

如果你不想或者不能在你的机器上安装 LXD ，你可以在 web 上[试试在线版的 LXD](https://linuxcontainers.org/lxd/try-it) 。

---

作者简介：我是 Stéphane Graber。我是 LXC 和 LXD 项目的领导者，目前在加拿大魁北克蒙特利尔的家所在的Canonical 有限公司担任 LXD 的技术主管。

---

via: <https://www.stgraber.org/2016/03/30/lxd-2-0-image-management-512/>

作者：[Stéphane Graber](https://www.stgraber.org/author/stgraber/) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织翻译，[Linux中国](https://linux.cn/) 荣誉推出

原文：<https://www.stgraber.org/2016/03/30/lxd-2-0-image-management-512/>


Linux 笔记本电脑选购指南

咯咯哒

可选择有点少

总之，玩linux一定不要选什么双显卡的笔记本，都是坑爹货，特别N卡，坑B中的战斗机

为了不给自己找烦恼，一定要用liveUSB测试，包括显卡、wifi等等。

如果无法实地测试，那么也要看看国外其他linuxer怎么评价的，看看有没有坑（例如奇葩的联想锁boot），或者无法驱动的情况。

以前（2010年左右），a就是坑（ati+amd），能避开就避开，intel+nvidia是首选。现在双卡交火，估计仍然很悬吧……

deepin 用户路过。。。。 开箱即用 哈哈

我就喜欢12寸的能触控的能很好支持Debian Gnu/Linux的笔记本电脑。哈哈哈哈。12寸是个心理尺寸，你们信不信，反正我自己信！！！

人傻怪电脑

不止显卡问题，linux的驱动问题是你这个“聪明人”能解决的？

买了华硕电脑，结果感觉坑了。对Linux支持不好

还要注意无线网卡，Broadcom是坑货

来自117.182.148.8的 Chrome 55.0|GNU/Linux 用户

现在A卡的开源驱动挺好的了。我的两台笔记本都是A卡。

点开dell xps 13的亚马逊链接或者在官网查看都是内置的windows10和office软件，这两样最少1k上去了。

dell xps 13貌似内置的不是linux。

太天真了，你以为预装Linux就不用给钱了？厂商同样会收取一定的费用，只不过不是操作系统的授权费而已，建议直接选没有预装操作系统的电脑！

一般来说不会有没有操作系统的电脑，至少也会装个dos的（不能当dos就不是操作系统是不）。以前看人家说是有规定的

我买的也是华硕，但是感觉对linux支持挺好的。我用的mint/fedora/deepin/opensuse都可以直接驱动。但是，还是觉得华硕笔记本不好，还不如公司给配的TP E系列笔电

一般来说确实没有不预装系统的设备，但凡事总有例外，还有一种办法，就是去美国买预装Windows的设备，完了可以找厂商要求退操作系统的钱。

xps13 的linux用户路过，  写代码确实很顺溜。

不买双显卡的笔电，任何笔记本装linux 问题都不大。

大写的服

那什么RTL开头的也是

xps开发者版本，有ubuntu选项，便宜些

普通用户随便买个集显的就行了。独显确实麻烦些。

我个人还是建议购买Dell或ThinkPad的Intel核显笔记本，一般兼容上问题不大。

ddddddddd

众所周知，如果你去电脑城[购买一个新的笔记本电脑](http://amzn.to/2fPxTms)，你所见到的尽是预安装了 Windows 或是 Mac 系统的笔记本电脑。无论怎样，你都会被迫支付一笔额外的费用—— 微软系统的许可费用或是苹果电脑背后的商标使用权费用。

当然，你也可以选择购买一款笔记本电脑，然后安装自己喜欢的操作系统。然而，最困难的可能是需要找到一款硬件跟你想安装的操作系统兼容性良好的笔记本电脑。

![](/data/attachment/album/201701/10/222416ccarzxm8bb81qeze.jpg)

在此之上，我们还需要考虑硬件驱动程序的可用性。那么，你应该怎么办呢？答案很简单：[购买一款预安装了 Linux 系统的笔记本电脑](http://amzn.to/2fPxTms)。

幸运的是，正好有几家值得依赖的公司提供质量好、有名气，并且预安装了 Linux 系统的笔记本电脑，这样你就不用再担心驱动程序的可用性了。

也就是说，在这篇文章中，我们将根据用户对笔记本电脑的用途列出 3 款可供用户选择的高性价比机器。

### 普通用户使用的 Linux 笔记本电脑

如果你正在寻找一款能够满足日常工作及娱乐需求的 Linux 笔记本电脑，它能够正常运行办公软件，有诸如 Firefox或是 Chrome 这样的 Web 浏览器，有局域网 / Wifi 连接功能，那么你可以考虑选择 [System76](https://system76.com/laptops) 公司生产的 Linux 笔记本电脑，它可以根据用户的定制化需求选择处理器类型，内存及磁盘大小，以及其它配件。

除此之外， System76 公司为他们所有的 Ubuntu 系统的笔记本电脑提供终身技术支持。如果你觉得这听起来不错，并且也比较感兴趣，你可以考虑下 [Lemur](https://system76.com/laptops/lemur) 或者 [Gazelle](https://system76.com/laptops/gazelle) 这两款笔记本电脑。

![Lemur Laptop for Linux](/data/attachment/album/201701/10/222438wvbr5h65br2hr363.png)

*Lemur Linux 笔记本电脑*

![Gazelle Laptop for Linux](/data/attachment/album/201701/10/222439vy570zlu6e0dnn71.png)

*Gazelle Linux 笔记本电脑*

### 开发者使用的 Linux 笔记本电脑

如果你想找一款坚固可靠，外观精美，并且性能强悍的笔记本电脑用于开发工作，你可以考虑一下 [Dell 的 XPS 13 笔记本电脑](http://amzn.to/2fBLMGj)。

这款 13 英寸的精美笔记本电脑，配置全高清 HD 显示器，触摸板，售价范围视其配置情况而定，CPU 代号/型号：Intel 的第 7 代处理器 i5 和 i7，固态硬盘大小：128 至 512 GB，内存大小：8 至 16 GB。

![Dells XPS Laptop for Linux](/data/attachment/album/201701/10/222442vj8p8b5niwunu7p2.png)

*Dell XPS Linux 笔记本电脑*

这些都是你应该考虑在内的重要因素，Dell 已经做得很到位了。不幸的是，Dell ProSupport 为该型号的笔记本电脑仅提供 Ubuntu 16.04 LTS 系统的技术支持（在写本篇文章的时候 - 2016 年 12 月）。

### 系统管理员使用的 Linux 笔记本电脑

虽然系统管理员可以顺利搞定在裸机上安装 Linux 系统的工作，但是使用 System76 的产品，你可以避免寻找各种驱动并解决兼容性问题上的麻烦。

之后，你可以根据自己的需求来配置电脑特性，你可以提高笔记本电脑的性能，增加内存到 32 GB 以确保你可以运行虚拟化环境并进行各种系统管理相关的任务。

如果你对此比较感兴趣，你可以考虑购买 [Kudu](https://system76.com/laptops/kudu) 或者是 [Oryx Pro](https://system76.com/laptops/oryx) 笔记本电脑。

![Kudu Linux Laptop](/data/attachment/album/201701/10/222444qmlufa6mfhjnu7h7.png)

*Kudu Linux 笔记本电脑*

![Oryx Pro Linux Laptop](/data/attachment/album/201701/10/222446cwwom9d78amd7e71.png)

*Oryx Pro 笔记本电脑*

### 总结

在这篇文章中，我们探讨了对于普通用户、开发者及系统管理员来说，为什么购买一款预安装了 Linux 系统的笔记本是一个不错的选择。一旦你决定好，你就可以轻松自如的考虑下应该如何消费这笔省下来的钱了。

你觉得在购买一款 Linux 系统的笔记本电脑时还应该注意些什么？请在下面的评论区与大家分享。

像往常一样，如果你对这篇文章有什么意见和看法，请随时提出来。我们很期待看到你的回复。

---

作者简介：

![](/data/attachment/album/201701/10/222449v4znozobjlbamu4b.png)

Gabriel Cánepa 来自 Argentina，San Luis，Villa Mercedes ，他是一名 GNU/Linux 系统管理员和网站开发工程师。目前在一家世界领先的消费品公司工作，在日常工作中，他非常善于使用 FOSS 工具来提高公司在各个领域的生产率。

---

via: <http://www.tecmint.com/buy-linux-laptops/>

作者：[Gabriel Cánepa](http://www.tecmint.com/author/gacanepa/) 译者：[rusking](https://github.com/rusking) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


初识 HTTP/2（一）

baidu搜不到linux中国？

不能啊，你搜“Linux”，第一就是哦。

刚开始以为前端就是css3+标签+js....然后发现了各种框架, 各种算法, 各种协议, 各种操作系统....根本学不完啊魂淡

前端难着呢，学不完的东西，老厉害了

![](/data/attachment/album/201701/11/000745jioszzor7jfxls7z.jpg)

>
> 用披萨来说明当你订单数很大的时候 HTTP/2 是怎么打败 HTTP/1.1 的。
>
>
>

在建立网站和应用的方式上 HTTP/2 有些令人惊叹的改变，在 HTTP/2 发布后的一年半，几乎 [10% 的网站使用了 HTTP/2](https://w3techs.com/technologies/details/ce-http2/all/all)。它绝对值得采用，但是这篇文章应该首先推给使用 HTTP/2 的前端开发者。这个连载的文章是指导前端开发者怎么转换到 HTTP/2。

本文涵盖了 HTTP/2 对 HTTP/1.1 来说有什么提高的内容，并且向前端开发者介绍了 HTTP/2。

### 再次让我想起什么是 HTTP ...

超文本传输协议，也就是 HTTP，这个协议决定了 web 内容怎么传输。HTTP/1.1 在 1999 年被标准化，那时候的 web 和现在有很大的不同，表格霸占了整个网络。样式通常被内联在元素中，如果网站管理员更加的细致，他们会在头部写个 `<style>`标签。 JavaScript 也被丢在文档里面，那时候完整的网站通常也不会超过几页。

HTTP/1.1 预计这种情况会持续一段时间，所以它并没有太过关注在让一个站点可以加载大量的资源方面，因为那时候的开发者并不需要这个。因此它使用了一个非常简单的方式来处理资源，你访问一个资源然后服务器去寻找它，并且返回你访问的资源，或者告诉你这个资源不存在。这种被叫作"线头堵塞"方式非常高效，但是当你需要多个资源的时候，这个进程会依次寻找每个资源。这意味着在你访问第二个资源之前，服务器必须找到你访问的第一个资源并且载入它，或者告诉你没找到。

### 大型站点的发展

在 1999 年之后的几年里，随着 php 和其他像 Rails 这样的动态语言的崛起，站点变得越来越复杂。css 文件也随着向响应式开发的转变而变的越来越大，因此像 Sass 这样的可以创造一个简单的工作环境的 CSS 编译器就应运而生。 JavaScript 也在 web 上有了更大的作用，它允许开发者编写复杂的应用，这曾经只是 C++ 开发人员的工作。随着 Retina 和高清显示屏的兴起，也让图片变得更高清。随着这些改变，文件大小呈现指数式的增长，使得本来是等待几个字节的资源变成了加载几千字节，甚至在某些情况下有几兆。当你开始载入页面的其它东西前，必须先载入数百 K 的东西，你只能乐观的假设你的用户有很快的网络接入。

想象 HTTP/1.1 是个过去的那种柜台购买式的街旁披萨店。你能自己过去并且预定一个雪碧和 2 片 Angry Hawaiian ，然后等待 3 分钟。他们可以很容易地处理这些，实际上这是一个蓬勃发展的商业模式-定单简单、处理迅速。

![](/data/attachment/album/201701/11/000828grppttiitit5pl6k.png)

然而，一旦你决定在同样的披萨店主办一场小区域的季度颁奖典礼，事情就变的更复杂了。每个人都预定不同的东西，快速而杂乱无章让等待时间直线上升。

![](/data/attachment/album/201701/11/000829bcyrpckr0d0646ap.png)

### 哪里是 HTTP/2 的舞台

HTTP/2 对前端开发者主要的承诺就是复用。意思就是资源请求能发生在同一时间，并且服务器能马上响应这些资源。在请求之间没有等待，因为它们发生在同一时间。

使用同样的比喻，HTTP/2 允许披萨店在餐馆他们自己区域举办派对。派一个服务员接受订单，并把所有已经准备好的订单交付。当其他人的比萨在制作的时候，你也不需要花 30 分钟去等待你的雪碧，它们在第一批交付的东西之中。这方式使得管理大量订单更加简单，并且防止人们等他们的订单时间太长。

复用带给我们的 web 开发的大变化是改变了文件的加载方式。帮助绕过资源加载的 HTTP/1.1 瓶颈的方式是通过连接和压缩需要被加载的文件。所有任务运行器都默认采取这样的操作方式，或者需要作一点小设置就行。和过去一样，开发人员可以将图像放在<ruby> 精灵拼图 <rp>  （ </rp> <rt>  sprite sheets </rt> <rp>  ） </rp></ruby>中，这会减少了对服务器的请求数。

### 改进 HTTP/1.1

将文件连接起来是个处理 HTTP1.1 的请求限制问题的非常聪明的方式，但是连接文件的主要问题是它要求用户第一次访问整个网站时下载所有的资源。一旦它们载入后，浏览器就会缓存所有的资源。这能提高用户每次访问网页时的速度，但是前期负载很重，对[跳出率不利](https://blog.kissmetrics.com/speed-is-a-killer/)。此外，他们可能为所不访问的页面加载资源。期望用户访问每个页面以查看每个样式，并与每个脚本进行交互是不现实的。此外，在加拿大和欧洲以及几乎每个美国移动提供商的地方，有每月的带宽上限。不是加载额外的 54 千字节的内容就会超过每月的流量限制，而是让我们假设用户想保留这些额外的流量看 Taylor Swift 的 gif。

使用 HTTP/2 和多路复用，您可以开发一些最高效的网站，但它需要一些重新思考、甚至撤销之前的最佳做法。重复一次，我的目的是加快 HTTP/2 的会话，使用我们新的工具，我们可以发现这些新的最佳的做法。

在我的下一篇文章，[我将探索建设基于 HTTP/2 的网站的一些最好方式](https://www.viget.com/articles/getting-started-with-http-2-part-2)。

---

via: <https://www.viget.com/articles/getting-started-with-http-2-part-1?imm_mid=0eb24a&cmp=em-web-na-na-newsltr_20161130>

作者：[Ben](https://www.viget.com/about/team/btinsley) 译者：[hkurj](https://github.com/hkurj) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译，[Linux中国](https://linux.cn/) 荣誉推出


Ansible 起步指南

这是一篇关于 Ansible 的速成课程，你可以用作小项目的模板，或者帮你深入了解这个神奇的工具。阅读了本指南之后，你将对自动化服务器配置、部署等有足够的了解。

![](/data/attachment/album/201701/12/010309ihntexy6ei5pezy9.jpg)

### Ansible 是什么，为什么你该了解？

Ansible 简单的说是一个<ruby> 配置管理系统 <rp>  （ </rp> <rt>  configuration management system </rt> <rp>  ） </rp></ruby>。你只需要可以使用 ssh 访问你的服务器或设备就行。它也不同于其他工具，因为它使用推送的方式，而不是像 puppet 或 chef 那样使用拉取的方式。你可以将代码部署到任意数量的服务器上，配置网络设备或在基础架构中自动执行任何操作。

### 前置要求

假设你使用 Mac 或 Linux 作为你的工作站，Ubuntu Trusty 作为你的服务器，并有一些安装软件包的经验。此外，你的计算机上将需要以下软件。所以，如果你还没有它们，请先安装：

* [Virtualbox](https://www.virtualbox.org/)
* [Vagrant](https://www.vagrantup.com/downloads.html)
* Mac 用户：[Homebrew](http://brew.sh/)

### 情景

我们将模拟 2 个连接到 MySQL 数据库的 Web 应用程序服务器。Web 应用程序使用 Rails 5 和 Puma。

### 准备

#### Vagrantfile

为这个项目创建一个文件夹，并将下面的内容保存到名为 `Vagrantfile` 的文件。

```
VMs = [
    [ "web1", "10.1.1.11"],
    [ "web2", "10.1.1.12"],
    [ "dbserver", "10.1.1.21"],
  ]

Vagrant.configure(2) do |config|
  VMs.each { |vm|
    config.vm.define vm[0] do |box|
      box.vm.box = "ubuntu/trusty64"
      box.vm.network "private_network", ip: vm[1]
      box.vm.hostname = vm[0]
      box.vm.provider "virtualbox" do |vb|
         vb.memory = "512"
      end
    end
  }
end

```

#### 配置你的虚拟网络

我们希望我们的虚拟机能互相交互，但不要让流量流出到真实的网络，所以我们将在 Virtualbox 中创建一个仅主机（HOST-Only）的网络适配器。

1. 打开 Virtualbox
2. 转到 Preferences
3. 转到 Network
4. 单击 Host-Only
5. 单击添加网络
6. 单击 Adapter
7. 将 IPv4 设置为 `10.1.1.1`，IPv4 网络掩码：`255.255.255.0`
8. 单击 “OK”

#### 测试虚拟机及虚拟网络

在终端中，在存放 `Vagrantfile` 的项目目录中，输入下面的命令：

```
vagrant up

```

它会创建你的虚拟机，因此会花费一会时间。输入下面的命令并验证输出内容以检查是否已经工作：

```
$ vagrant status
Current machine states:

web1                      running (virtualbox)
web2                      running (virtualbox)
master                    running (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

```

现在使用 `vagrant` 的用户名和密码 ，按 `Vagrantfile` 中的 IP 登录其中一台虚拟机，这将验证虚拟机并将它们的密钥添加到你的已知主机（`known_hosts`）文件中。

```
ssh vagrant@10.1.1.11 # password is `vagrant`
ssh vagrant@10.1.1.12
ssh vagrant@10.1.1.21

```

恭喜你！现在你已经有可以实验的服务器了。下面的剩下的部分！

### 安装 Ansible

对于 Mac 用户:

```
$ brew install ansible

```

对于 Ubuntu 用户:

```
$ sudo apt install ansible

```

确保你使用了ansible 最近的版本 2.1 或者更高的版本：

```
$ ansible --version
ansible 2.1.1.0

```

### 清单

Ansible 使用清单文件来了解要使用的服务器，以及如何将它们分组以并行执行任务。让我们为这个项目创建我们的清单文件 `inventory`，并将它放在与 `Vagrantfile` 相同的文件夹中：

```
[all:children]
webs
db

[all:vars]
ansible_user=vagrant
ansible_ssh_pass=vagrant

[webs]
web1 ansible_host=10.1.1.11
web2 ansible_host=10.1.1.12

[db]
dbserver ansible_host=10.1.1.21

```

* `[all：children]` 定义一个组的组（`all`）
* `[all：vars]` 定义属于组 `all` 的变量
* `[webs]` 定义一个组，就像 `[db]` 一样
* 文件的其余部分只是主机的声明，带有它们的名称和 IP
* 空行表示声明结束

现在我们有了一个清单，我们可以从命令行开始使用 ansible，指定一个主机或一个组来执行命令。以下是检查与服务器的连接的命令示例：

```
$ ansible -i inventory all -m ping

```

* `-i` 指定清单文件
* `all` 指定要操作的服务器或服务器组
* `-m' 指定一个 ansible 模块，在这种情况下为`ping`

下面是命令输出：

```
dbserver | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
web1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
web2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

```

服务器以不同的顺序响应，这只取决于谁先响应，但是这个没有关系，因为 ansible 独立保持每台服务器的状态。

你也可以使用另外一个选项来运行任何命令：

* `-a <command>`

```
$ ansible -i inventory all -a uptime
web1 | SUCCESS | rc=0 >>
 21:43:27 up 25 min,  1 user,  load average: 0.00, 0.01, 0.05

dbserver | SUCCESS | rc=0 >>
 21:43:27 up 24 min,  1 user,  load average: 0.00, 0.01, 0.05

web2 | SUCCESS | rc=0 >>
 21:43:27 up 25 min,  1 user,  load average: 0.00, 0.01, 0.05

```

这是只有一台服务器的另外一个例子：

```
$ ansible -i inventory dbserver -a "df -h /"
dbserver | SUCCESS | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        40G  1.4G   37G   4% /

```

### 剧本

剧本（playbook）只是个 YAML 文件，它将清单文件中的服务器组与命令关联。在 ansible 中的对于关键字是 `tasks`，它可以是一个预期的状态、shell 命令或许多其它的选项。有关 ansible 可做的所有事情列表，可以查看[所有模块的列表](http://docs.ansible.com/ansible/list_of_all_modules.html)。

下面是一个运行 shell 命令的剧本示例，将其保存为 `playbook1.yml`：

```
---
- hosts: all
  tasks:
    - shell: uptime

```

* `---` 是 YAML 文件的开始
* `- hosts`：指定要使用的组
* `tasks`：标记任务列表的开始
* `- shell`：指定第一个任务使用 [shell](http://docs.ansible.com/ansible/shell_module.html) 模块
* **记住：YAML 需要缩进结构，确保你始终遵循剧本中的正确结构**

用下面的命令运行它：

```
$ ansible-playbook -i inventory playbook1.yml

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [web1]
ok: [web2]
ok: [dbmaster]

TASK [command] *****************************************************************
changed: [web1]
changed: [web2]
changed: [dbmaster]

PLAY RECAP *********************************************************************
dbmaster                   : ok=2    changed=1    unreachable=0    failed=0
web1                       : ok=2    changed=1    unreachable=0    failed=0
web2                       : ok=2    changed=1    unreachable=0    failed=0

```

正如你所见，ansible 运行了 2 个任务，而不是只有剧本中的一个。`TASK [setup]` 是一个隐式任务，它会首先运行以捕获服务器的信息，如主机名、IP、发行版和更多详细信息，然后可以使用这些信息运行条件任务。

还有最后的 `PLAY RECAP`，其中 ansible 显示了运行了多少个任务以及每个对应的状态。在我们的例子中，因为我们运行了一个 shell 命令，ansible 不知道结果的状态，它被认为是 `changed`。

#### 安装软件

我们将使用 [apt](http://docs.ansible.com/ansible/apt_module.html) 在我们的服务器上安装软件，因为我们需要 root 权限，所以我们必须使用 `become` 语句，将这个内容保存在 `playbook2.yml` 中并运行它（`ansible-playbook playbook2.yml`）：

```
---
- hosts: webs
  become_user: root
  become: true
  tasks:
    - apt: name=git state=present

```

有一些语句可以应用于 ansible 中所有模块；一个是 `name` 语句，可以让我们输出关于正在执行的任务的更具描述性的文本。要使用它，保持任务内容一样，但是添加 `name ：描述性文本` 作为第一行，所以我们以前的文本将改成：

```
---
- hosts: webs
  become_user: root
  become: true
  tasks:
    - name: This task will make sure git is present on the system
      apt: name=git state=present

```

#### 使用 `with_items`

当你要处理一个列表时，比如要安装的项目和软件包、要创建的文件，可以用 ansible 提供的 `with_items`。下面是我们如何在 `playbook3.yml` 中使用它，同时添加一些我们已经知道的其他语句：

```
---
- hosts: all
  become_user: root
  become: true
  tasks:
    - name: Installing dependencies
      apt: name={{item}} state=present
      with_items:
        - git
        - mysql-client
        - libmysqlclient-dev
        - build-essential
        - python-software-properties

```

#### 使用 `template` 和 `vars`

`vars` 是一个定义变量语句，可以在 `task` 语句或 `template` 文件中使用。 [Jinja2](http://jinja.pocoo.org/docs/dev/) 是 Ansible 中使用的模板引擎，但是关于它你不需要学习很多。在你的剧本中定义变量，如下所示：

```
---
- hosts: all
  vars:
    - secret_key: VqnzCLdCV9a3jK
    - path_to_vault: /opt/very/deep/path
  tasks:
    - name: Setting a configuration file using template
      template: src=myconfig.j2 dest={{path_to_vault}}/app.conf

```

正如你看到的，我可以使用 `{{path_to_vault}}` 作为剧本的一部分，但也因为我使用了 `template`语句，我可以使用 `myconfig.j2` 中的任何变量，该文件必须存在一个名为 `templates` 的子文件夹中。你项目树应该如下所示：

```
├── Vagrantfile
├── inventory
├── playbook1.yml
├── playbook2.yml
└── templates
    └── myconfig.j2

```

当 ansible 找到一个 `template` 语句后它会在 `templates` 文件夹内查找，并将把被 `{{` 和 `}}` 括起来的变量展开来。

示例模板：

```
this is just an example vault_dir: {{path_to_vault}} secret_password: {{secret_key}}

```

即使你不扩展变量你也可以使用 `template`。考虑到将来会添加所以我先做了。比如创建一个 `hosts.j2` 模板并加入主机名和 IP。

```
10.1.1.11 web1
10.1.1.12 web2
10.1.1.21 dbserver

```

这里要用像这样的语句：

```
  -  name: Installing the hosts file in all servers
     template: src=hosts.j2 dest=/etc/hosts mode=644

```

#### shell 命令

你应该尽量使用模块，因为 Ansible 可以跟踪任务的状态，并避免不必要的重复，但有时 shell 命令是不可避免的。 对于这些情况，Ansible 提供两个选项：

* [command](http://docs.ansible.com/ansible/command_module.html)：直接运行一个命令，没有环境变量或重定向（`|`，`<`，`>` 等）
* [shell](http://docs.ansible.com/ansible/shell_module.html)：运行 `/bin/sh` 并展开变量和支持重定向

#### 其他有用的模块

* [apt\_repository](http://docs.ansible.com/ansible/apt_repository_module.html) - 在 Debian 系的发行版中添加/删除包仓库
* [yum\_repository](https://docs.ansible.com/ansible/yum_repository_module.html) - 在 RedHat 系的发行版中添加/删除包仓库
* [service](http://docs.ansible.com/ansible/service_module.html) - 启动/停止/重新启动/启用/禁用服务
* [git](http://docs.ansible.com/ansible/git_module.html) - 从 git 服务器部署代码
* [unarchive](http://docs.ansible.com/ansible/unarchive_module.html) - 从 Web 或本地源解开软件包

#### 只在一台服务器中运行任务

Rails 使用 [migrations](http://edgeguides.rubyonrails.org/active_record_migrations.html) 来逐步更改数据库，但由于你有多个应用程序服务器，因此这些迁移任务不能被分配为组任务，而我们只需要一个服务器来运行迁移。在这种情况下，当使用 `run_once` 时，`run_once` 将分派任务到一个服务器，并直到这个任务完成继续下一个任务。你只需要在你的任务中设置 `run_once：true`。

```
    - name: 'Run db:migrate'
      shell: cd {{appdir}};rails db:migrate
      run_once: true

```

#### 会失败的任务

通过指定 `ignore_errors：true`，你可以运行可能会失败的任务，但不会影响剧本中剩余的任务完成。这是非常有用的，例如，当删除最初并不存在的日志文件时。

```
    - name: 'Delete logs'
      shell: rm -f /var/log/nginx/errors.log
      ignore_errors: true

```

### 放到一起

现在用我们先前学到的，这里是每个文件的最终版：

`Vagrantfile`：

```
VMs = [
    [ "web1", "10.1.1.11"],
    [ "web2", "10.1.1.12"],
    [ "dbserver", "10.1.1.21"],
  ]

Vagrant.configure(2) do |config|
  VMs.each { |vm|
    config.vm.define vm[0] do |box|
      box.vm.box = "ubuntu/trusty64"
      box.vm.network "private_network", ip: vm[1]
      box.vm.hostname = vm[0]
      box.vm.provider "virtualbox" do |vb|
         vb.memory = "512"
      end
    end
  }
end

```

`inventory`：

```
[all:children]
webs
db

[all:vars]
ansible_user=vagrant
ansible_ssh_pass=vagrant

[webs]
web1 ansible_host=10.1.1.11
web2 ansible_host=10.1.1.12

[db]
dbserver ansible_host=10.1.1.21

```

`templates/hosts.j2`:

```
10.1.1.11 web1
10.1.1.12 web2
10.1.1.21 dbserver

```

`templates/my.cnf.j2`：

```
[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
server-id   = 1
user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address        = 0.0.0.0
key_buffer      = 16M
max_allowed_packet  = 16M
thread_stack        = 192K
thread_cache_size       = 8
myisam-recover         = BACKUP
query_cache_limit   = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error.log
expire_logs_days    = 10
max_binlog_size         = 100M

[mysqldump]
quick
quote-names
max_allowed_packet  = 16M

[mysql]

[isamchk]
key_buffer      = 16M

!includedir /etc/mysql/conf.d/

```

`final-playbook.yml`：

```
- hosts: all
  become_user: root
  become: true
  tasks:
    - name: 'Install common software on all servers'
      apt: name={{item}} state=present
      with_items:
        - git
        - mysql-client
        - libmysqlclient-dev
        - build-essential
        - python-software-properties
    - name: 'Install hosts file'
      template: src=hosts.j2 dest=/etc/hosts mode=644

- hosts: db
  become_user: root
  become: true
  tasks:
    - name: 'Software for DB server'
      apt: name={{item}} state=present
      with_items:
        - mysql-server
        - percona-xtrabackup
        - mytop
        - mysql-utilities
    - name: 'MySQL config file'
      template: src=my.cnf.j2 dest=/etc/mysql/my.cnf
    - name: 'Restart MySQL'
      service: name=mysql state=restarted
    - name: 'Grant access to web app servers'
      shell: echo 'GRANT ALL PRIVILEGES ON *.* TO "root"@"%" WITH GRANT OPTION;FLUSH PRIVILEGES;'|mysql -u root mysql

- hosts: webs
  vars:
    - appdir: /opt/dummyapp
  become_user: root
  become: true
  tasks:
    - name: 'Add ruby-ng repo'
      apt_repository: repo='ppa:brightbox/ruby-ng'
    - name: 'Install rails software'
      apt: name={{item}} state=present
      with_items:
        - ruby-dev
        - ruby-all-dev
        - ruby2.2
        - ruby2.2-dev
        - ruby-switch
        - libcurl4-openssl-dev
        - libssl-dev
        - zlib1g-dev
        - nodejs
    - name: 'Set ruby to 2.2'
      shell: ruby-switch --set ruby2.2
    - name: 'Install gems'
      shell: gem install bundler rails
    - name: 'Kill puma if running'
      shell: file /run/puma.pid >/dev/null && kill `cat /run/puma.pid` 2>/dev/null
      ignore_errors: True
    - name: 'Clone app repo'
      git:
           repo=https://github.com/c0d5x/rails_dummyapp.git
           dest={{appdir}}
           version=staging
           force=yes
    - name: 'Run bundler'
      shell: cd {{appdir}};bundler
    - name: 'Run db:setup'
      shell: cd {{appdir}};rails db:setup
      run_once: true
    - name: 'Run db:migrate'
      shell: cd {{appdir}};rails db:migrate
      run_once: true
    - name: 'Run rails server'
      shell: cd {{appdir}};rails server -b 0.0.0.0 -p 80 --pid /run/puma.pid -d

```

### 放在你的环境中

将这些文件放在相同的目录，运行下面的命令打开你的开发环境：

```
vagrant up
ansible-playbook -i inventory final-playbook.yml

```

### 部署新的代码

确保修改了代码并推送到了仓库中。接下来，确保你 git 语句中使用了正确的分支：

```
    - name: 'Clone app repo'
      git:
           repo=https://github.com/c0d5x/rails_dummyapp.git
           dest={{appdir}}
           version=staging
           force=yes

```

作为一个例子，你可以修改 `version` 字段为 `master`，再次运行剧本：

```
ansible-playbook -i inventory final-playbook.yml

```

检查所有的 web 服务器上的页面是否已更改：`http://10.1.1.11` 或 `http://10.1.1.12`。将其更改为 `version = staging` 并重新运行剧本并再次检查页面。

你还可以创建只包含与部署相关的任务的替代剧本，以便其运行更快。

### 接下来是什么 ？！

这只是可以做的很小一部分。我们没有接触<ruby> 角色 <rp>  （ </rp> <rt>  role </rt> <rp>  ） </rp></ruby>、<ruby> 过滤器 <rp>  （ </rp> <rt>  filter </rt> <rp>  ） </rp></ruby>、调试等许多其他很棒的功能，但我希望它给了你一个良好的开始！所以，请继续学习并使用它。如果你有任何问题，你可以在 [twitter](https://twitter.com/c0d5x) 或评论栏联系我，让我知道你还想知道哪些关于 ansible 的东西！

---

via: <https://gorillalogic.com/blog/getting-started-with-ansible/?utm_source=webopsweekly&utm_medium=email>

作者：[JOSE HIDALGO](https://gorillalogic.com/author/josehidalgo/) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 Docker 中设置 Go 并部署应用

嗨，在本教程中，我们将学习如何使用 docker 部署 golang web 应用程序。 你可能已经知道，由于 golang 的高性能和可靠性，docker 是完全是用 golang 写的。在我们详细介绍之前，请确保你已经安装了 docker 以及 golang 并对它们有基本了解。

![](/data/attachment/album/201701/12/094625moon9fmlccxosoka.jpg)

### 关于 docker

Docker 是一个开源程序，它可以将应用及其完整的依赖包捆绑到一起，并打包为容器，与宿主机共享相同的 Linux 内核。另一方面，像 VMware 这样的基于 hypervisor 的虚拟化操作系统容器提供了高级别的隔离和安全性，这是由于客户机和主机之间的通信是通过 hypervisor 来实现的，它们不共享内核空间。但是硬件仿真也导致了性能的开销，所以容器虚拟化诞生了，以提供一个轻量级的虚拟环境，它将一组进程和资源与主机以及其它容器分组及隔离，因此，容器内部的进程无法看到容器外部的进程或资源。

### 用 Go 语言创建一个 “Hello World” web 应用

首先我们为 Go 应用创建一个目录，它会在浏览器中显示 “Hello World”。创建一个 `web-app` 目录并使它成为当前目录。进入 `web-app` 应用目录并编辑一个名为 `main.go` 的文件。

```
root@demohost:~# mkdir web-app
root@demohost:~# cd web-app/
root@demohost:~/web-app# vim.tiny main.go

package main
import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello %s", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/World", handler)
    http.ListenAndServe(":8080", nil)
}

```

使用下面的命令运行上面的 “Hello World” Go 程序。在浏览器中输入 `http://127.0.0.1:8080/World` 测试，你会在浏览器中看到 “Hello World”。

```
root@demohost:~/web-app# PORT=8080 go run main.go

```

下一步是将上面的应用在 docker 中容器化。因此我们会创建一个 dockerfile 文件，它会告诉 docker 如何容器化我们的 web 应用。

```
root@demohost:~/web-app# vim.tiny Dockerfile

# 得到最新的 golang docker 镜像
FROM golang:latest

# 在容器内部创建一个目录来存储我们的 web 应用，接着使它成为工作目录。
RUN mkdir -p /go/src/web-app
WORKDIR /go/src/web-app

# 复制 web-app 目录到容器中
COPY . /go/src/web-app

# 下载并安装第三方依赖到容器中
RUN go-wrapper download
RUN go-wrapper install

# 设置 PORT 环境变量
ENV PORT 8080

# 给主机暴露 8080 端口，这样外部网络可以访问你的应用
EXPOSE 8080

# 告诉 Docker 启动容器运行的命令
CMD ["go-wrapper", "run"]

```

### 构建/运行容器

使用下面的命令构建你的 Go web-app，你会在成功构建后获得确认。

```
root@demohost:~/web-app# docker build --rm -t web-app .
Sending build context to Docker daemon 3.584 kB
Step 1 : FROM golang:latest
latest: Pulling from library/golang
386a066cd84a: Already exists
75ea84187083: Pull complete
88b459c9f665: Pull complete
a31e17eb9485: Pull complete
1b272d7ab8a4: Pull complete
eca636a985c1: Pull complete
08158782d330: Pull complete
Digest: sha256:02718aef869a8b00d4a36883c82782b47fc01e774d0ac1afd434934d8ccfee8c
Status: Downloaded newer image for golang:latest
---> 9752d71739d2
Step 2 : RUN mkdir -p /go/src/web-app
---> Running in 9aef92fff9e8
---> 49936ff4f50c
Removing intermediate container 9aef92fff9e8
Step 3 : WORKDIR /go/src/web-app
---> Running in 58440a93534c
---> 0703574296dd
Removing intermediate container 58440a93534c
Step 4 : COPY . /go/src/web-app
---> 82be55bc8e9f
Removing intermediate container cae309ac7757
Step 5 : RUN go-wrapper download
---> Running in 6168e4e96ab1
+ exec go get -v -d
---> 59664b190fee
Removing intermediate container 6168e4e96ab1
Step 6 : RUN go-wrapper install
---> Running in e56f093b6f03
+ exec go install -v
web-app
---> 584cd410fdcd
Removing intermediate container e56f093b6f03
Step 7 : ENV PORT 8080
---> Running in 298e2a415819
---> c87fd2b43977
Removing intermediate container 298e2a415819
Step 8 : EXPOSE 8080
---> Running in 4f639a3790a7
---> 291167229d6f
Removing intermediate container 4f639a3790a7
Step 9 : CMD go-wrapper run
---> Running in 6cb6bc28e406
---> b32ca91bdfe0
Removing intermediate container 6cb6bc28e406
Successfully built b32ca91bdfe0

```

现在可以运行我们的 web-app 了，可以执行下面的命令。

```
root@demohost:~/web-app# docker run -p 8080:8080 --name="test" -d web-app
7644606b9af28a3ef1befd926f216f3058f500ffad44522c1d4756c576cfa85b

```

进入 `http://localhost:8080/World` 浏览你的 web 应用。你已经成功容器化了一个可重复的/确定性的 Go web 应用。使用下面的命令来启动、停止并检查容器的状态。

```
### 列出所有容器
root@demohost:~/ docker ps -a

### 使用 id 启动容器
root@demohost:~/ docker start CONTAINER_ID_OF_WEB_APP

### 使用 id 停止容器
root@demohost:~/ docker stop CONTAINER_ID_OF_WEB_APP

```

### 重新构建镜像

假设你正在开发 web 应用程序并在更改代码。现在要在更新代码后查看结果，你需要重新生成 docker 镜像、停止旧镜像并运行新镜像，并且每次更改代码时都要这样做。为了使这个过程自动化，我们将使用 docker 卷在主机和容器之间共享一个目录。这意味着你不必为在容器内进行更改而重新构建镜像。容器如何检测你是否对 web 程序的源码进行了更改？答案是有一个名为 “Gin” 的好工具 <https://github.com/codegangsta/gin>，它能检测是否对源码进行了任何更改，然后重建镜像/二进制文件并在容器内运行更新过代码的进程。

要使这个过程自动化，我们将编辑 Dockerfile 并安装 Gin 将其作为入口命令来执行。我们将开放 `3030` 端口（Gin 代理），而不是 `8080`。 Gin 代理将转发流量到 web 程序的 `8080` 端口。

```
root@demohost:~/web-app# vim.tiny Dockerfile

# 得到最新的 golang docker 镜像
FROM golang:latest

# 在容器内部创建一个目录来存储我们的 web 应用，接着使它称为工作目录。
RUN mkdir -p /go/src/web-app
WORKDIR /go/src/web-app

# 复制 web 程序到容器中
COPY . /go/src/web-app

# 下载并安装第三方依赖到容器中
RUN go get github.com/codegangsta/gin
RUN go-wrapper download
RUN go-wrapper install

# 设置 PORT 环境变量
ENV PORT 8080

# 给主机暴露 8080 端口，这样外部网络可以访问你的应用
EXPOSE 3030

# 启动容器时运行 Gin
CMD gin run

# 告诉 Docker 启动容器运行的命令
CMD ["go-wrapper", "run"]

```

现在构建镜像并启动容器：

```
root@demohost:~/web-app# docker build --rm -t web-app .

```

我们会在当前 web 程序的根目录下运行 docker，并通过暴露的 `3030` 端口链接 CWD （当前工作目录）到容器中的应用目录下。

```
root@demohost:~/web-app# docker run -p 3030:3030 -v `pwd`:/go/src/web-app --name="test" -d web-app

```

打开 `http://localhost:3030/World`， 你就能看到你的 web 程序了。现在如果你改变了任何代码，会在浏览器刷新后反映在你的浏览器中。

### 总结

就是这样，我们的 Go web 应用已经运行在 Ubuntu 16.04 Docker 容器中运行了！你可以通过使用 Go 框架来快速开发 API、网络应用和后端服务，从而扩展当前的网络应用。

---

via: <http://linoxide.com/containers/setup-go-docker-deploy-application/>

作者：[Dwijadas Dey](http://linoxide.com/author/dwijadasd/) 译者：[geekpi](https://github.com/geekpi) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


5 个找出“二进制命令”描述和系统中位置的方法

Summary: 在数千个 Linux 系统上的命令/程序中，知道给定命令的类型和目的以及其在系统上的位置（绝对路径）对于新手来说可能是一个挑战。

在数千个 [Linux 系统上的命令/程序](http://www.tecmint.com/category/top-tools/)中，知道给定命令的类型和目的以及其在系统上的位置（绝对路径）对于新手来说可能是一个挑战。

知道命令/程序的一些细节不仅有助于 [Linux 用户掌握大量命令](http://www.tecmint.com/tag/linux-tricks/)，还能使用户理解命令行或脚本在系统上的操作。

因此，在本文中我们将向你解释五个有用的命令，用于显示给定命令的简短描述和位置。

![](/data/attachment/album/201701/12/221954uknr2kkhpkzvdmpf.jpg)

要在系统上发现新命令，请查看 `PATH` 环境变量中的所有目录。这些目录存储系统上安装的所有命令/程序。

一旦你找到一个有趣的命令，在继续阅读更多关于它的手册页之前，请尝试如下收集一些简要的信息。

假设你输出了 `PATH` 的值，然后进到其中的一个目录 `/usr/local/bin`，注意到一个名为 [`fswatch`（监视文件修改更改）](http://www.tecmint.com/fswatch-monitors-files-and-directory-changes-modifications-in-linux/)的新命令：

```
$ echo $PATH
$ cd /usr/local/bin

```

![Find New Commands in Linux](/data/attachment/album/201701/12/222052bnt8brf81atf6spr.png)

*在 Linux 中找出新命令*

现在让我们在 Linux 中用不同的方法找出 `fswatch` 命令的描述和位置。

### 1、 whatis 命令

`whatis` 用于显示你作为参数输入的命令名的单行描述（例如下面命令中的 `fswatch`）。

如果描述太长，一些部分在默认情况下会被省略，使用 `-l` 标志来显示完整的描述。

```
$ whatis fswatch
$ whatis -l fswatch

```

![Linux whatis Command Example](/data/attachment/album/201701/12/222053hwk6knk033tquwcw.png)

*Linux whatis 命令示例*

### 2、 apropos 命令

`apropos` 会搜索手册页名称和关键字描述（以命令名作为正则表达式搜索）。

使用 `-l` 标志来显示完整的描述。

```
$ apropos fswatch
$ apropos -l fswatch

```

![Linux apropos Command Example](/data/attachment/album/201701/12/222053ifio6euumiazafjf.png)

*Linux apropos 命令示例*

默认上，`apropos` 会如示例那样输出所有匹配的行。你可以使用 `-e` 选项来精确匹配：

```
$ apropos fmt
$ apropos -e fmt

```

![Linux apropos Command Show by Keyword](/data/attachment/album/201701/12/222054jd4nlzfcml4tfclf.png)

*Linux apropos 命令根据关键词显示*

### 3、 type 命令

`type` 命令会输出给定命令的完整路径名，此外，如果输入的命令名不是做为独立存储在磁盘的文件的程序，`type` 还会告诉你命令分类：

* shell 内置命令
* shell 关键字或保留字
* 别名

```
$ type fswatch

```

![Linux type Command Example](/data/attachment/album/201701/12/222054sqy2zsqgc4q0ngee.png)

*Linux type 命令示例*

当命令是另外一个命令的别名时，`type` 会显示运行别名时所执行的命令。使用 `alias` 命令可以查看你系统上创建的所有别名：

```
$ alias
$ type l
$ type ll

```

![Show All Aliases in Linux](/data/attachment/album/201701/12/222055hpz1nffnpo7nxknw.png)

*显示 Linux 中所有别名*

### 4、 which 命令

`which` 可以帮助命令定位命令，它会打印出命令的绝对路径：

```
$ which fswatch

```

![Find Linux Command Location](/data/attachment/album/201701/12/222055zgx0yinnfigbfg33.png)

*找出 Linux 命令位置*

一些二进制文件存在于 `PATH` 环境变量中的多个目录，使用 `-a` 标志来找出所有匹配的路径名。

### 5、 whereis 命令

`whereis` 定位指定命令名的二进制、源和帮助页文件，如下所示：

```
$ whereis fswatch
$ whereis mkdir
$ whereis rm

```

![Linux whereis Command Example](/data/attachment/album/201701/12/222056pxnvnbyk7hy8mtv7.png)

*Linux whereis 命令示例*

虽然上面的命令对于查找关于命令/程序的一些快速信息很重要，但是该命令的手册总是可以提供完整的文档，它还包括其他相关程序的列表：

```
$ man fswatch

```

在本文中，我们回顾了五个简单的命令，用于显示命令的简短的手册描述和位置。 你可以在反馈栏中对此文章做出贡献或提出问题。

---

作者简介：

![](/data/attachment/album/201701/12/222058qf99svaeb76vbyzg.jpg)

Aaron Kili 是 Linux 和 F.O.S.S 爱好者，将来的 Linux SysAdmin、web 开发人员，目前是 TecMint 的内容创作者，他喜欢用电脑工作，并坚信分享知识。

---

via: <http://www.tecmint.com/find-linux-command-description-and-location/>

作者：[Aaron Kili](http://www.tecmint.com/author/aaronkili/) 译者：[geekpi](https://github.com/geekpi) 校对：[jasminepeng](https://github.com/jasminepeng)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出