mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-13 22:30:37 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
ec25764ecc
@ -0,0 +1,221 @@
|
||||
如何在 Linux 中从一个 PDF 文件中移除密码
|
||||
======
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2018/04/Remove-Password-From-A-PDF-File-720x340.png)
|
||||
|
||||
今天,我碰巧分享一个受密码保护的 PDF 文件给我的一个朋友。我知道这个 PDF 文件的密码,但是我不想透露密码。作为代替,我只想移除密码并发送文件给他。我开始在因特网上查找一些简单的方法来从 PDF 文件中移除密码保护。在快速 google 搜索后,在 Linux 中,我带来四种方法来从一个 PDF 文件中移除密码。有趣的事是,在几年以前我已经做过这事情但是我忘记了。如果你想知道,如何在 Linux 中从一个 PDF 文件移除密码,继续读!它是不难的。
|
||||
|
||||
### 在Linux中从一个PDF文件中移除密码
|
||||
|
||||
#### 方法 1 – 使用 Qpdf
|
||||
|
||||
**Qpdf** 是一个 PDF 转换软件,它被用于加密和解密 PDF 文件,转换 PDF 文件到其他等效的 PDF 文件。 Qpdf 在大多数 Linux 发行版中的默认存储库中是可用的,所以你可以使用默认的软件包安装它。
|
||||
|
||||
例如,Qpdf 可以被安装在 Arch Linux 和它的衍生版,使用 [pacman][1] ,像下面显示。
|
||||
|
||||
```
|
||||
$ sudo pacman -S qpdf
|
||||
```
|
||||
|
||||
在 Debian、Ubuntu、Linux Mint 上:
|
||||
|
||||
```
|
||||
$ sudo apt-get install qpdf
|
||||
```
|
||||
|
||||
现在,让我们使用 qpdf 从一个 pdf 文件移除密码。
|
||||
|
||||
我有一个受密码保护的 PDF 文件,名为 `secure.pdf`。每当我打开这个文件时,它提示我输入密码来显示它的内容。
|
||||
|
||||
![][3]
|
||||
|
||||
我知道上面 PDF 文件的密码。然而,我不想与任何人共享密码。所以,我将要做的事是简单地移除 PDF 文件的密码,使用 Qpdf 功能带有下面的命令。
|
||||
|
||||
```
|
||||
$ qpdf --password='123456' --decrypt secure.pdf output.pdf
|
||||
```
|
||||
|
||||
相当简单,不是吗?是的,它是!这里,`123456` 是 `secure.pdf` 文件的密码。用你自己的密码替换。
|
||||
|
||||
#### 方法 2 – 使用 Pdftk
|
||||
|
||||
**Pdftk** 是另一个用于操作 PDF 文件的好软件。 Pdftk 可以做几乎所有的 PDF 操作,例如:
|
||||
|
||||
* 加密和解密 PDF 文件。
|
||||
* 合并 PDF 文档。
|
||||
* 整理 PDF 页扫描。
|
||||
* 拆分 PDF 页。
|
||||
* 旋转 PDF 文件或页。
|
||||
* 用 X/FDF 数据 填充 PDF 表单,和/或摧毁表单。
|
||||
* 从 PDF 表单中生成 PDF数据模板。
|
||||
* 应用一个背景水印,或一个前景印记。
|
||||
* 报告 PDF 度量标准、书签和元数据。
|
||||
* 添加/更新 PDF 书签或元数据。
|
||||
* 附加文件到 PDF 页,或 PDF 文档。
|
||||
* 解包 PDF 附件。
|
||||
* 拆解一个 PDF 文件到单页中。
|
||||
* 压缩和解压缩页流。
|
||||
* 修复破损的 PDF 文件。
|
||||
|
||||
Pddftk 在 AUR 中是可用的,所以你可以在 Arch Linux 和它的衍生版上使用任意 AUR 帮助程序安装它。
|
||||
|
||||
使用 [Pacaur][4]:
|
||||
|
||||
```
|
||||
$ pacaur -S pdftk
|
||||
```
|
||||
|
||||
使用 [Packer][5]:
|
||||
|
||||
```
|
||||
$ packer -S pdftk
|
||||
```
|
||||
|
||||
使用 [Trizen][6]:
|
||||
|
||||
```
|
||||
$ trizen -S pdftk
|
||||
```
|
||||
|
||||
使用 [Yay][7]:
|
||||
|
||||
```
|
||||
$ yay -S pdftk
|
||||
```
|
||||
|
||||
使用 [Yaourt][8]:
|
||||
|
||||
```
|
||||
$ yaourt -S pdftk
|
||||
```
|
||||
|
||||
在 Debian、Ubuntu、Linux Mint 上,运行:
|
||||
|
||||
```
|
||||
$ sudo apt-get instal pdftk
|
||||
```
|
||||
|
||||
在 CentOS、Fedora、Red Hat 上:
|
||||
|
||||
首先,安装 EPEL 仓库:
|
||||
|
||||
```
|
||||
$ sudo yum install epel-release
|
||||
```
|
||||
|
||||
或
|
||||
|
||||
```
|
||||
$ sudo dnf install epel-release
|
||||
```
|
||||
|
||||
然后,安装 PDFtk 应用程序,使用命令:
|
||||
|
||||
```
|
||||
$ sudo yum install pdftk
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
$ sudo dnf install pdftk
|
||||
```
|
||||
|
||||
一旦 pdftk 安装,你可以从一个 PDF 文档移除密码,使用命令:
|
||||
|
||||
```
|
||||
$ pdftk secure.pdf input_pw 123456 output output.pdf
|
||||
```
|
||||
|
||||
用你正确的密码替换 `123456`。这个命令解密 `secure.pdf` 文件,并创建一个相同的名为 `output.pdf` 的无密码保护的文件。
|
||||
|
||||
**参阅:**
|
||||
|
||||
- [How To Merge PDF Files In Command Line On Linux][9]
|
||||
- [How To Split or Extract Particular Pages From A PDF File][10]
|
||||
|
||||
#### 方法 3 – 使用 Poppler
|
||||
|
||||
**Poppler** 是一个基于 xpdf-3.0 代码库的 PDF 渲染库。它包含下列用于操作 PDF 文档的命令行功能集。
|
||||
|
||||
* `pdfdetach` – 列出或提取嵌入的文件。
|
||||
* `pdffonts` – 字体分析器。
|
||||
* `pdfimages` – 图片提取器。
|
||||
* `pdfinfo` – 文档信息。
|
||||
* `pdfseparate` – 页提取工具。
|
||||
* `pdfsig` – 核查数字签名。
|
||||
* `pdftocairo` – PDF 到 PNG/JPEG/PDF/PS/EPS/SVG 转换器,使用 Cairo 。
|
||||
* `pdftohtml` – PDF 到 HTML 转换器。
|
||||
* `pdftoppm` – PDF 到 PPM/PNG/JPEG 图片转换器。
|
||||
* `pdftops` – PDF 到 PostScript (PS) 转换器。
|
||||
* `pdftotext` – 文本提取。
|
||||
* `pdfunite` – 文档合并工具。
|
||||
|
||||
因这个指南的目的,我们仅使用 `pdftops` 功能。
|
||||
|
||||
在基于 Arch Linux 的发行版上,安装 Poppler,运行:
|
||||
|
||||
```
|
||||
$ sudo pacman -S poppler
|
||||
```
|
||||
|
||||
在 Debian、Ubuntu、Linux Mint 上:
|
||||
|
||||
```
|
||||
$ sudo apt-get install poppler-utils
|
||||
```
|
||||
|
||||
在 RHEL、CentOS、Fedora 上:
|
||||
|
||||
```
|
||||
$ sudo yum install poppler-utils
|
||||
```
|
||||
|
||||
一旦 Poppler 安装,运行下列命令来解密密码保护的 PDF 文件,并创建一个新的相同的名为 `output.pdf` 的文件。
|
||||
|
||||
```
|
||||
$ pdftops -upw 123456 secure.pdf output.pdf
|
||||
|
||||
```
|
||||
|
||||
再一次,用你的 pdf 密码替换 `123456` 。
|
||||
|
||||
正如你在上面方法中可能注意到,我们仅转换密码保护的名为 `secure.pdf` 的 PDF 文件到另一个相同的名为 `output.pdf` 的 PDF 文件。技术上讲,我们并没有真的从源文件中移除密码,作为代替,我们解密它,并保存它为另一个相同的没有密码保护的 PDF 文件。
|
||||
|
||||
#### 方法 4 – 打印到一个文件
|
||||
|
||||
这是在所有上面方法中的最简单的方法。你可以使用你存在的 PDF 查看器,例如 Atril 文档查看器、Evince 等等,并打印密码保护的 PDF 文件到另一个文件。
|
||||
|
||||
在你的 PDF 查看器应用程序中打开密码保护的文件。转到 “File - > Print” 。并在你选择的某个位置保存 PDF 文件。
|
||||
|
||||
![][2]
|
||||
|
||||
于是,这是全部。希望这是有用的。你知道/使用一些其它方法来从从 PDF 文件中移除密码保护吗?在下面的评价区让我们知道。
|
||||
|
||||
更多好东西来了。敬请期待!
|
||||
|
||||
谢谢!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-remove-password-from-a-pdf-file-in-linux/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.ostechnix.com/author/sk/
|
||||
[1]:https://www.ostechnix.com/getting-started-pacman/
|
||||
[2]:https://www.ostechnix.com/wp-content/uploads/2018/04/Remove-Password-From-A-PDF-File-2.png
|
||||
[3]:http://www.ostechnix.com/wp-content/uploads/2018/04/Remove-Password-From-A-PDF-File-1.png
|
||||
[4]:https://www.ostechnix.com/install-pacaur-arch-linux/
|
||||
[5]:https://www.ostechnix.com/install-packer-arch-linux-2/
|
||||
[6]:https://www.ostechnix.com/trizen-lightweight-aur-package-manager-arch-based-systems/
|
||||
[7]:https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
|
||||
[8]:https://www.ostechnix.com/install-yaourt-arch-linux/
|
||||
[9]: https://www.ostechnix.com/how-to-merge-pdf-files-in-command-line-on-linux/
|
||||
[10]: https://www.ostechnix.com/extract-particular-pages-pdf-file/
|
@ -1,48 +1,48 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxfminions )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: translator: (lxfminions)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: subject: (4 open source Markdown editors)
|
||||
[#]: via: (https://opensource.com/article/18/11/markdown-editors)
|
||||
[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
|
||||
[#]: url: ( )
|
||||
[#]: url: (https://linux.cn/article-10320-1.html)
|
||||
|
||||
4 个 Markdown 开源编辑器
|
||||
======
|
||||
如果你正在寻找一种简便的方法去格式化 Markdown 文本,那么这些编辑器可能会满足你的需求。
|
||||
|
||||
> 如果你正在寻找一种简便的方法去格式化 Markdown 文本,那么这些编辑器可能会满足你的需求。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-docdish-typewriterkeys.png?itok=IeQWevaV)
|
||||
|
||||
|
||||
我在编辑器上使用 [Markdown][1] 写作,包括文章,散文,博客等等。我也不是唯一使用 Markdown 写作的人。不仅仅无数的人在使用 Markdown,而且也产生了许多服务于 Markdown 的工具。
|
||||
我的文章、散文、博客等等基本上都是在文本编辑器上使用 [Markdown][1] 写作的。当然,我不是唯一使用 Markdown 写作的人。不仅仅无数的人在使用 Markdown,而且也产生了许多服务于 Markdown 的工具。
|
||||
|
||||
谁能想到由 John Gruber 和之后的 Aaron Schwartz 创造的一种格式化网页文档的简便的方法如此的受欢迎呢?
|
||||
|
||||
当我在文本编辑器上进行写作时,才理解了为什么 Markdown 编辑器会如此受欢迎-可以快速格式化,可以轻便的将文档转换为其他的格式,可以实时预览。
|
||||
我的大多数协作都是在文本编辑器上进行,我能理解为什么 Markdown 编辑器会如此受欢迎 —— 可以快速格式化,可以轻便的将文档转换为其他的格式,可以实时预览。
|
||||
|
||||
如果你想用 Markdown 和寻找一个 Markdown 编辑器,那么这里有四个开源编辑器可能会让你写作更加轻松。
|
||||
如果你想用 Markdown 和寻找一个专用的 Markdown 编辑器,那么这里有四个开源编辑器可能会让你写作更加轻松。
|
||||
|
||||
### Ghostwriter
|
||||
|
||||
在我使用过的或试过的三个 Markdown 编辑器中,[Ghostwriter][2] 是最好用的。我已经使用或试了很多次。
|
||||
在我使用过的或试过的 Markdown 编辑器中 [Ghostwriter][2] 能排进前三。我已经使用或试了不少。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/markdown-editors_ghostwriter.png)
|
||||
|
||||
作为一个编辑器,Ghostwriter 就像一个画布,你可以手动进行编辑和添加格式。如果你不想这么做或者只想学习 Markdown 或者不知道如何添加,你可以从 Ghostwriter 的格式化菜单中选择你想要的格式。
|
||||
|
||||
一般的,它只有一个基本的格式化列表,字符格式化和缩进。所以你必须手动的添加标题,代码。而且它有一个有趣的任务列表选项,很多人都在用 Markdown 去创造任务列表,这个功能可以让你更加容易去创造和维护。
|
||||
一般的,它只有一个基本的格式:列表、字符格式化和缩进。所以你必须手动的添加标题、代码。而且它有一个有趣的任务列表选项,很多人都在用 Markdown 去创造任务列表,这个功能可以让你更加容易去创造和维护任务列表。
|
||||
|
||||
Ghostwriter 区别于其他的 Markdown 编辑器的是它有更多的导出选项。你可以选择你想使用的 Markdown 编译器,包括 [Sundown][3], [Pandoc][4], or [Discount][5]。只需要双击鼠标,你可以轻松的将你写的内容转换为 HTML5, ODT, EPUB,LaTeX,PDF 或 Word 文档。
|
||||
Ghostwriter 区别于其他的 Markdown 编辑器的是它有更多的导出选项。你可以选择你想使用的 Markdown 编译器,包括 [Sundown][3]、[Pandoc][4] 或 [Discount][5]。只需要点击两次,你可以轻松的将你写的内容转换为 HTML5、ODT、EPUB、LaTeX、PDF 或 Word 文档。
|
||||
|
||||
### Abricotine
|
||||
|
||||
如果喜欢简洁的 Markdown 编辑器,你会爱上[Abricotine][6]。但是不要让它的简单性欺骗了你;Abricotine 包含了很多强大的功能。
|
||||
如果喜欢简洁的 Markdown 编辑器,你会爱上 [Abricotine][6]。但是不要让它的简单性欺骗了你;Abricotine 包含了很多强大的功能。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/markdown-editors_abricotine.png)
|
||||
|
||||
与其他的编辑器一样,你可以手动格式化文档或使用它的格式化菜单或插入菜单。Abricotine 有一个插入 [GitHub Flavored Markdown][7] 表的菜单。它预装了 16 个表样式,你可以在你需要的地方添加行或列。如果这个表看起来有点复杂,你可以使用 Ctrl+Shift+B 去使它看起来更整洁优美。
|
||||
与其他的编辑器一样,你可以手动格式化文档或使用它的格式化菜单或插入菜单。Abricotine 有一个插入 [GitHub 式 Markdown][7] 表格的菜单。它预装了 16 个表样式,你可以在你需要的地方添加行或列。如果这个表看起来有点复杂,你可以使用 `Ctrl+Shift+B` 去使它看起来更整洁优美。
|
||||
|
||||
Abricotine 可以自动显示图片,连接和数学。当然你也可以关闭这些选项。可惜的是,这个编辑器只能导出为 HTML 格式。
|
||||
Abricotine 可以自动显示图片、连接和数学公式。当然你也可以关闭这些选项。可惜的是,这个编辑器只能导出为 HTML 格式。
|
||||
|
||||
### Mark Text
|
||||
|
||||
@ -50,22 +50,23 @@ Abricotine 可以自动显示图片,连接和数学。当然你也可以关闭
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/markdown-editors_marktext.png)
|
||||
|
||||
Mark Text 有点奇怪,它们没有菜单或工具条。你需要点击编辑器左上角的弹出式菜单得到命令和功能。它仅仅让你专注于你的内容。
|
||||
Mark Text 有点奇怪,它没有菜单或工具条。你需要点击编辑器左上角的弹出式菜单得到命令和功能。它就是让你专注于你的内容。
|
||||
|
||||
虽然当你添加内容后,可以在预览区实时看到你所写的内容,但它仍然是一个半所见即所得的编辑器。Mark Text 支持 GitHub Flavored Markdown 格式,所以你可以添加表和语法高亮的代码块。在缺省的预览中,编辑器会显示你文档的所有图片。
|
||||
虽然当你添加内容后,可以在预览区实时看到你所写的内容,但它仍然是一个半所见即所得的编辑器。Mark Text 支持 GitHub 式 Markdown 格式,所以你可以添加表和语法高亮的代码块。在缺省的预览中,编辑器会显示你文档的所有图片。
|
||||
|
||||
与 Ghostwriter 相比,你只能将你的文档保存为 HTML 或 PDF 格式。这个输出看起来也不是很糟糕。
|
||||
|
||||
### Remarkable
|
||||
|
||||
[Remarkable][9] 复杂性位于 Ghostwriter 和 Abricotine 或 Mark Text 之间。它有一个带点现代风格的双栏界面。它有一些有用的特点。
|
||||
[Remarkable][9] 复杂性介乎于 Ghostwriter 和 Abricotine 或 Mark Text 之间。它有一个带点现代风格的双栏界面。它有一些有用的特点。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/markdown-editors_remarkable.png)
|
||||
|
||||
你注意到的第一件事是它受到 [Material Design][10] 启发的界面外观。它不是每一个人都能习惯的,老实说:我花费了很多时间去适应它。一旦你适应了,它使用起来很简单。
|
||||
你可以在工具条和菜单上快速访问格式化功能。你可以使用内置的 11 种样式或你自己创造的去定制预览框的样式。
|
||||
|
||||
Remarkable 的导出选项是有限的-你只能导出为 HTML 或 PDF 格式文件。然而你可以复制整个文档或挑选一部分作为 HTML,粘贴到另一个文档或编辑器中。
|
||||
你可以在工具条和菜单上快速访问格式化功能。你可以使用内置的 11 种 CSS 样式或你自己创造的去定制预览框的样式。
|
||||
|
||||
Remarkable 的导出选项是有限的 —— 你只能导出为 HTML 或 PDF 格式文件。然而你可以复制整个文档或挑选一部分作为 HTML,粘贴到另一个文档或编辑器中。
|
||||
|
||||
你有最喜爱的 Markdown 编辑器吗?为什么不在评论区分享它呢?
|
||||
|
||||
@ -76,7 +77,7 @@ via: https://opensource.com/article/18/11/markdown-editors
|
||||
作者:[Scott Nesbitt][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxfminions](https://github.com/lxfminions)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,461 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: subject: (How to Build a Netboot Server, Part 1)
|
||||
[#]: via: (https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/)
|
||||
[#]: author: (Gregory Bartholomew https://fedoramagazine.org/author/glb/)
|
||||
[#]: url: ( )
|
||||
|
||||
How to Build a Netboot Server, Part 1
|
||||
======
|
||||
|
||||
![](https://fedoramagazine.org/wp-content/uploads/2018/11/build-netboot-816x345.jpg)
|
||||
|
||||
Some computer networks need to maintain identical software installations and configurations on several physical machines. One such environment would be a school computer lab. A [netboot][1] server can be set up to serve an entire operating system over a network so that the client computers can be configured from one central location. This tutorial will show one method of building a netboot server.
|
||||
|
||||
Part 1 of this tutorial will cover creating a netboot server and image. Part 2 will show how to add Kerberos-authenticated home directories to the netboot configuration.
|
||||
|
||||
### Initial Configuration
|
||||
|
||||
Start by downloading one of Fedora Server’s [netinst][2] images, burning it to a CD, and booting the server that will be reformatted from it. We just need a typical “Minimal Install” of Fedora Server for our starting point and we will use the command line to add any additional packages that are needed after the installation is finished.
|
||||
|
||||
![][3]
|
||||
|
||||
> NOTE: For this tutorial we will be using Fedora 28. Other versions may include a slightly different set of packages in their “Minimal Install”. If you start with a different version of Fedora, then you may need to do some troubleshooting if an expected file or command is not available.
|
||||
|
||||
Once you have your minimal installation of Fedora Server up and running, log in as root and set the hostname:
|
||||
|
||||
```
|
||||
$ MY_HOSTNAME=server-01.example.edu
|
||||
$ hostnamectl set-hostname $MY_HOSTNAME
|
||||
```
|
||||
|
||||
> NOTE: Red Hat recommends that both static and transient names match the fully-qualified domain name (FQDN) used for the machine in DNS, such as host.example.com ([Understanding Host Names][4]).
|
||||
>
|
||||
> NOTE: This guide is meant to be copy-and-paste friendly. Any value that you might need to customize will be stated as a MY_* variable that you can tweak before running the remaining commands. Beware that if you log out, the variable assignments will be cleared.
|
||||
>
|
||||
> NOTE: Fedora 28 Server tends to dump a lot of logging output to the console by default. You may want to disable the console logging temporarily by running: sysctl -w kernel.printk=0
|
||||
|
||||
Next, we need a static network address on our server. The following sequence of commands should find and reconfigure your default network connection appropriately:
|
||||
|
||||
```
|
||||
$ MY_DNS1=192.0.2.91
|
||||
$ MY_DNS2=192.0.2.92
|
||||
$ MY_IP=192.0.2.158
|
||||
$ MY_PREFIX=24
|
||||
$ MY_GATEWAY=192.0.2.254
|
||||
$ DEFAULT_DEV=$(ip route show default | awk '{print $5}')
|
||||
$ DEFAULT_CON=$(nmcli d show $DEFAULT_DEV | sed -n '/^GENERAL.CONNECTION:/s!.*:\s*!! p')
|
||||
$ nohup bash << END
|
||||
nmcli con mod "$DEFAULT_CON" connection.id "$DEFAULT_DEV"
|
||||
nmcli con mod "$DEFAULT_DEV" connection.interface-name "$DEFAULT_DEV"
|
||||
nmcli con mod "$DEFAULT_DEV" ipv4.method disabled
|
||||
nmcli con up "$DEFAULT_DEV"
|
||||
nmcli con add con-name br0 ifname br0 type bridge
|
||||
nmcli con mod br0 bridge.stp no
|
||||
nmcli con mod br0 ipv4.dns $MY_DNS1,$MY_DNS2
|
||||
nmcli con mod br0 ipv4.addresses $MY_IP/$MY_PREFIX
|
||||
nmcli con mod br0 ipv4.gateway $MY_GATEWAY
|
||||
nmcli con mod br0 ipv4.method manual
|
||||
nmcli con up br0
|
||||
nmcli con add con-name br0-slave0 ifname "$DEFAULT_DEV" type bridge-slave master br0
|
||||
nmcli con up br0-slave0
|
||||
END
|
||||
```
|
||||
|
||||
> NOTE: The last set of commands above is wrapped in a “nohup” script because it will disable networking temporarily. The nohup command should allow the nmcli commands to finish running even while your ssh connection is down. Beware that it may take 10 or so seconds for the connection to come back up and that you will have to start a new ssh connection if you changed the server’s IP address.
|
||||
>
|
||||
> NOTE: The above network configuration creates a [network bridge][5] on top of the default connection so that we can run a virtual machine instance directly on the server for testing later. If you do not want to test the netboot image directly on the server, you can skip creating the bridge and set the static IP address directly on your default network connection.
|
||||
|
||||
### Install and Configure NFS4
|
||||
|
||||
Start by installing the nfs-utils package:
|
||||
|
||||
```
|
||||
$ dnf install -y nfs-utils
|
||||
```
|
||||
|
||||
Create a top-level [pseudo filesystem][6] for the NFS exports and share it out to your network:
|
||||
|
||||
```
|
||||
$ MY_SUBNET=192.0.2.0
|
||||
$ mkdir /export
|
||||
$ echo "/export -fsid=0,ro,sec=sys,root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports
|
||||
```
|
||||
|
||||
SELinux will interfere with the netboot server’s operation. Configuring exceptions for it is beyond the scope of this tutorial, so we will disable it:
|
||||
|
||||
```
|
||||
$ sed -i '/GRUB_CMDLINE_LINUX/s/"$/ audit=0 selinux=0"/' /etc/default/grub
|
||||
$ grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
|
||||
$ setenforce 0
|
||||
```
|
||||
|
||||
> NOTE: Editing the grub command line should not be necessary, but simply editing /etc/sysconfig/selinux proved ineffective across reboots of Fedora Server 28 during testing, so the “selinux=0” flag has been set here to be doubly sure.
|
||||
|
||||
Now, add an exception for the NFS service to the local firewall and start the NFS service:
|
||||
|
||||
```
|
||||
$ firewall-cmd --add-service nfs
|
||||
$ firewall-cmd --runtime-to-permanent
|
||||
$ systemctl enable nfs-server.service
|
||||
$ systemctl start nfs-server.service
|
||||
```
|
||||
|
||||
### Create the Netboot Image
|
||||
|
||||
Now that our NFS server is up and running, we need to supply it with an operating system image to serve to the client computers. We will start with a very minimal image and add to it after everything is working.
|
||||
|
||||
First, create a new directory where our image will be stored:
|
||||
|
||||
```
|
||||
$ mkdir /fc28
|
||||
```
|
||||
|
||||
Use the “dnf” command to build the image under the new directory with only a few base packages:
|
||||
|
||||
```
|
||||
$ dnf -y --releasever=28 --installroot=/fc28 install fedora-release systemd passwd rootfiles sudo dracut dracut-network nfs-utils vim-minimal dnf
|
||||
```
|
||||
|
||||
It is important that the “kernel” packages were omitted from the above command. Before they are installed, we need to tweak the set of drivers that will be included in the “initramfs” image that is built automatically when the kernel is first installed. In particular, we need to disable “hostonly” mode so that the initramfs image will work on a wider set of hardware platforms and we need to add support for networking and NFS:
|
||||
|
||||
```
|
||||
$ echo 'hostonly=no' > /fc28/etc/dracut.conf.d/hostonly.conf
|
||||
$ echo 'add_dracutmodules+=" network nfs "' > /fc28/etc/dracut.conf.d/netboot.conf
|
||||
```
|
||||
|
||||
Now, install the kernel:
|
||||
|
||||
```
|
||||
$ dnf -y --installroot=/fc28 install kernel
|
||||
```
|
||||
|
||||
Set a rule to prevent the kernel from being updated:
|
||||
|
||||
```
|
||||
$ echo 'exclude=kernel-*' >> /fc28/etc/dnf/dnf.conf
|
||||
```
|
||||
|
||||
Set the locale:
|
||||
|
||||
```
|
||||
$ echo 'LANG="en_US.UTF-8"' > /fc28/etc/locale.conf
|
||||
```
|
||||
|
||||
> NOTE: Some programs (e.g. GNOME Terminal) will not function if the locale is not properly configured.
|
||||
|
||||
Blank root’s passwd:
|
||||
|
||||
```
|
||||
$ sed -i 's/^root:\*/root:/' /fc28/etc/shadow
|
||||
```
|
||||
|
||||
Set the client’s hostname:
|
||||
|
||||
```
|
||||
$ MY_CLIENT_HOSTNAME=client-01.example.edu
|
||||
$ echo $MY_CLIENT_HOSTNAME > /fc28/etc/hostname
|
||||
```
|
||||
|
||||
Disable logging to the console:
|
||||
|
||||
```
|
||||
$ echo 'kernel.printk = 0 4 1 7' > /fc28/etc/sysctl.d/00-printk.conf
|
||||
```
|
||||
|
||||
Define a local “liveuser” in the netboot image:
|
||||
|
||||
```
|
||||
$ echo 'liveuser:x:1000:1000::/home/liveuser:/bin/bash' >> /fc28/etc/passwd
|
||||
$ echo 'liveuser::::::::' >> /fc28/etc/shadow
|
||||
$ echo 'liveuser:x:1000:' >> /fc28/etc/group
|
||||
$ echo 'liveuser:!::' >> /fc28/etc/gshadow
|
||||
```
|
||||
|
||||
Allow “liveuser” to sudo:
|
||||
|
||||
```
|
||||
$ echo 'liveuser ALL=(ALL) NOPASSWD: ALL' > /fc28/etc/sudoers.d/liveuser
|
||||
```
|
||||
|
||||
Enable automatic home directory creation:
|
||||
|
||||
```
|
||||
$ dnf install -y --installroot=/fc28 authselect oddjob-mkhomedir
|
||||
$ echo 'dirs /home' > /fc28/etc/rwtab.d/home
|
||||
$ chroot /fc28 authselect select sssd with-mkhomedir --force
|
||||
$ chroot /fc28 systemctl enable oddjobd.service
|
||||
```
|
||||
|
||||
Since multiple clients will be mounting our image concurrently, we need to configure the image so that it will operate in read-only mode:
|
||||
|
||||
```
|
||||
$ sed -i 's/^READONLY=no$/READONLY=yes/' /fc28/etc/sysconfig/readonly-root
|
||||
```
|
||||
|
||||
Configure logging to go to RAM rather than permanent storage:
|
||||
|
||||
```
|
||||
$ sed -i 's/^#Storage=auto$/Storage=volatile/' /fc28/etc/systemd/journald.conf
|
||||
```
|
||||
|
||||
Configure DNS:
|
||||
|
||||
```
|
||||
$ MY_DNS1=192.0.2.91
|
||||
$ MY_DNS2=192.0.2.92
|
||||
$ cat << END > /fc28/etc/resolv.conf
|
||||
nameserver $MY_DNS1
|
||||
nameserver $MY_DNS2
|
||||
END
|
||||
```
|
||||
|
||||
Work-around a few bugs that exist for read-only root mounts at the time this tutorial is being written ([BZ1542567][7]):
|
||||
|
||||
```
|
||||
$ echo 'dirs /var/lib/gssproxy' > /fc28/etc/rwtab.d/gssproxy
|
||||
$ cat << END > /fc28/etc/rwtab.d/systemd
|
||||
dirs /var/lib/systemd/catalog
|
||||
dirs /var/lib/systemd/coredump
|
||||
END
|
||||
```
|
||||
|
||||
Finally, we can create the NFS filesystem for our image and share it out to our subnet:
|
||||
|
||||
```
|
||||
$ mkdir /export/fc28
|
||||
$ echo '/fc28 /export/fc28 none bind 0 0' >> /etc/fstab
|
||||
$ mount /export/fc28
|
||||
$ echo "/export/fc28 -ro,sec=sys,no_root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports.d/fc28.exports
|
||||
$ exportfs -vr
|
||||
```
|
||||
|
||||
### Create the Boot Loader
|
||||
|
||||
Now that we have an operating system available to netboot, we need a boot loader to kickstart it on the client systems. For this setup, we will be using [iPXE][8].
|
||||
|
||||
> NOTE: This section and the following section — Testing with QEMU — can be done on a separate computer; they do not have to be run on the netboot server.
|
||||
|
||||
Install git and use it to download iPXE:
|
||||
|
||||
```
|
||||
$ dnf install -y git
|
||||
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
|
||||
```
|
||||
|
||||
Now we need to create a special startup script for our bootloader:
|
||||
|
||||
```
|
||||
$ cat << 'END' > $HOME/ipxe/init.ipxe
|
||||
#!ipxe
|
||||
|
||||
prompt --key 0x02 --timeout 2000 Press Ctrl-B for the iPXE command line... && shell ||
|
||||
|
||||
dhcp || exit
|
||||
set prefix file:///linux
|
||||
chain ${prefix}/boot.cfg || exit
|
||||
END
|
||||
```
|
||||
|
||||
Enable the “file” download protocol:
|
||||
|
||||
```
|
||||
$ echo '#define DOWNLOAD_PROTO_FILE' > $HOME/ipxe/src/config/local/general.h
|
||||
```
|
||||
|
||||
Install the C compiler and related tools and libraries:
|
||||
|
||||
```
|
||||
$ dnf groupinstall -y "C Development Tools and Libraries"
|
||||
```
|
||||
|
||||
Build the boot loader:
|
||||
|
||||
```
|
||||
$ cd $HOME/ipxe/src
|
||||
$ make clean
|
||||
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe
|
||||
```
|
||||
|
||||
Make note of where the where the newly-compiled boot loader is. We will need it for the next section:
|
||||
|
||||
```
|
||||
$ IPXE_FILE="$HOME/ipxe/src/bin-x86_64-efi/ipxe.efi"
|
||||
```
|
||||
|
||||
### Testing with QEMU
|
||||
|
||||
This section is optional, but you will need to duplicate the file layout of the [EFI system partition][9] that is shown below on your physical machines to configure them for netbooting.
|
||||
|
||||
> NOTE: You could also copy the files to a TFTP server and reference that server from DHCP if you wanted a fully diskless system.
|
||||
|
||||
In order to test our boot loader with QEMU, we are going to create a small disk image containing only an EFI system partition and our startup files.
|
||||
|
||||
Start by creating the required directory layout for the EFI system partition and copying the boot loader that we created in the previous section to it:
|
||||
|
||||
```
|
||||
$ mkdir -p $HOME/esp/efi/boot
|
||||
$ mkdir $HOME/esp/linux
|
||||
$ cp $IPXE_FILE $HOME/esp/efi/boot/bootx64.efi
|
||||
```
|
||||
|
||||
The below command should identify the kernel version that our netboot image is using and store it in a variable for use in the remaining configuration directives:
|
||||
|
||||
```
|
||||
$ DEFAULT_VER=$(ls -c /fc28/lib/modules | head -n 1)
|
||||
```
|
||||
|
||||
Define the boot configuration that our client computers will be using:
|
||||
|
||||
```
|
||||
$ MY_DNS1=192.0.2.91
|
||||
$ MY_DNS2=192.0.2.92
|
||||
$ MY_NFS4=server-01.example.edu
|
||||
$ cat << END > $HOME/esp/linux/boot.cfg
|
||||
#!ipxe
|
||||
|
||||
kernel --name kernel.efi \${prefix}/vmlinuz-$DEFAULT_VER initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=$MY_DNS1 nameserver=$MY_DNS2 root=nfs4:$MY_NFS4:/fc28 console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
|
||||
initrd --name initrd.img \${prefix}/initramfs-$DEFAULT_VER.img
|
||||
boot || exit
|
||||
END
|
||||
```
|
||||
|
||||
> NOTE: The above boot script shows a minimal example of how to get iPXE to netboot Linux. Much more complex configurations are possible. Most notably, iPXE has support for interactive boot menus which can be configured with a default selection and a timeout. A more advanced iPXE script could, for example, default to booting an operation system from the local disk and only go to the netboot operation if a user pressed a key before a countdown timer reached zero.
|
||||
|
||||
Copy the Linux kernel and its associated initramfs to the EFI system partition:
|
||||
|
||||
```
|
||||
$ cp $(find /fc28/lib/modules -maxdepth 2 -name 'vmlinuz' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/vmlinuz-$DEFAULT_VER
|
||||
$ cp $(find /fc28/boot -name 'init*' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/initramfs-$DEFAULT_VER.img
|
||||
```
|
||||
|
||||
Our resulting directory layout should look like this:
|
||||
|
||||
```
|
||||
esp
|
||||
├── efi
|
||||
│ └── boot
|
||||
│ └── bootx64.efi
|
||||
└── linux
|
||||
├── boot.cfg
|
||||
├── initramfs-4.18.18-200.fc28.x86_64.img
|
||||
└── vmlinuz-4.18.18-200.fc28.x86_64
|
||||
```
|
||||
|
||||
To use our EFI system partition with QEMU, we need to create a small “uefi.img” disk image containing it and then connect that to QEMU as the primary boot drive.
|
||||
|
||||
Begin by installing the necessary tools:
|
||||
|
||||
```
|
||||
$ dnf install -y parted dosfstools
|
||||
```
|
||||
|
||||
Now create the “uefi.img” file and copy the files from the “esp” directory into it:
|
||||
|
||||
```
|
||||
$ ESP_SIZE=$(du -ks $HOME/esp | cut -f 1)
|
||||
$ dd if=/dev/zero of=$HOME/uefi.img count=$((${ESP_SIZE}+5000)) bs=1KiB
|
||||
$ UEFI_DEV=$(losetup --show -f $HOME/uefi.img)
|
||||
$ parted ${UEFI_DEV} -s mklabel gpt mkpart EFI FAT16 1MiB 100% toggle 1 boot
|
||||
$ mkfs -t msdos ${UEFI_DEV}p1
|
||||
$ mkdir -p $HOME/mnt
|
||||
$ mount ${UEFI_DEV}p1 $HOME/mnt
|
||||
$ cp -r $HOME/esp/* $HOME/mnt
|
||||
$ umount $HOME/mnt
|
||||
$ losetup -d ${UEFI_DEV}
|
||||
```
|
||||
|
||||
> NOTE: On a physical computer, you need only copy the files from the “esp” directory to the computer’s existing EFI system partition. You do not need the “uefi.img” file to boot a physical computer.
|
||||
>
|
||||
> NOTE: On a physical computer you can rename the “bootx64.efi” file if a file by that name already exists, but if you do so, you will probably have to edit the computer’s BIOS settings and add the renamed efi file to the boot list.
|
||||
|
||||
Next we need to install the qemu package:
|
||||
|
||||
```
|
||||
$ dnf install -y qemu-system-x86
|
||||
```
|
||||
|
||||
Allow QEMU to access the bridge that we created in the “Initial Configuration” section of this tutorial:
|
||||
|
||||
```
|
||||
$ echo 'allow br0' > /etc/qemu/bridge.conf
|
||||
```
|
||||
|
||||
Create a copy of the “OVMF_VARS.fd” image to store our virtual machine’s persistent BIOS settings:
|
||||
|
||||
```
|
||||
$ cp /usr/share/edk2/ovmf/OVMF_VARS.fd $HOME
|
||||
```
|
||||
|
||||
Now, start the virtual machine:
|
||||
|
||||
```
|
||||
$ qemu-system-x86_64 -machine accel=kvm -nographic -m 1024 -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/ovmf/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=$HOME/OVMF_VARS.fd -drive if=ide,format=raw,file=$HOME/uefi.img -net bridge,br=br0 -net nic,model=virtio
|
||||
```
|
||||
|
||||
If all goes well, you should see results similar to what is shown in the below image:
|
||||
|
||||
![][10]
|
||||
You can use the “shutdown” command to get out of the virtual machine and back to the server:
|
||||
|
||||
```
|
||||
$ sudo shutdown -h now
|
||||
```
|
||||
|
||||
> NOTE: If something goes wrong and the virtual machine hangs, you may need to start a new ssh session to the server and use the “kill” command to terminate the “qemu-system-x86_64” process.
|
||||
|
||||
### Adding to the Image
|
||||
|
||||
Adding to the image should be a simple matter of chroot’ing into the image on the server and running “dnf install <package_name>”.
|
||||
|
||||
There is no limit to what can be installed on the netboot image. A full graphical installation should function perfectly.
|
||||
|
||||
Here is an example of how to bring our minimal netboot image up to a complete graphical installation:
|
||||
|
||||
```
|
||||
$ for i in dev dev/pts dev/shm proc sys run; do mount -o bind /$i /fc28/$i; done
|
||||
$ chroot /fc28 /usr/bin/bash --login
|
||||
$ dnf -y groupinstall "Fedora Workstation"
|
||||
$ dnf -y remove gnome-initial-setup
|
||||
$ systemctl disable sshd.service
|
||||
$ systemctl enable gdm.service
|
||||
$ systemctl set-default graphical.target
|
||||
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
|
||||
$ logout
|
||||
$ for i in run sys proc dev/shm dev/pts dev; do umount /fc28/$i; done
|
||||
```
|
||||
|
||||
Optionally, you may want to enable automatic login for the “liveuser” account:
|
||||
|
||||
```
|
||||
$ sed -i '/daemon/a AutomaticLoginEnable=true' /fc28/etc/gdm/custom.conf
|
||||
$ sed -i '/daemon/a AutomaticLogin=liveuser' /fc28/etc/gdm/custom.conf
|
||||
```
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/
|
||||
|
||||
作者:[Gregory Bartholomew][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/glb/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Network_booting
|
||||
[2]: https://dl.fedoraproject.org/pub/fedora/linux/releases/28/Server/x86_64/iso/
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2018/11/installation-summary-1024x768.png
|
||||
[4]: https://docs.fedoraproject.org/en-US/Fedora/25/html/Networking_Guide/ch-Configure_Host_Names.html#sec_Understanding_Host_Names
|
||||
[5]: https://en.wikipedia.org/wiki/Bridging_(networking)
|
||||
[6]: https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s3-nfs-server-config-exportfs-nfsv4.html
|
||||
[7]: https://bugzilla.redhat.com/show_bug.cgi?id=1542567
|
||||
[8]: https://ipxe.org/
|
||||
[9]: https://en.wikipedia.org/wiki/EFI_system_partition
|
||||
[10]: https://fedoramagazine.org/wp-content/uploads/2018/11/netboot-liveuser-1024x641.png
|
@ -1,222 +0,0 @@
|
||||
robsean Translating
|
||||
|
||||
如何在Linux中从一个PDF文件中移除密码
|
||||
======
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2018/04/Remove-Password-From-A-PDF-File-720x340.png)
|
||||
今天,我碰巧分享一个受密码保护的 PDF 文件给我的一个朋友。我知道这个PDF文件的密码,但是我不想透露密码。作为代替,我只想移除密码并发送文件给他。我开始在因特网上查找一些简单的方法来从 pdf 文件中移除密码保护。在快速 google 搜索后,在 Linux 中,我带来四种方法来从一个 PDF 文件中移除密码 。有趣的事是,在几年以前我已经做到它,并且我也忘记它了。如果你疑惑,如何在 Linux 中从一个 PDF 文件移除密码,继续读!它是不难的。
|
||||
|
||||
### 在Linux中从一个PDF文件中移除密码
|
||||
|
||||
**方法 1 – 使用 Qpdf**
|
||||
|
||||
**Qpdf** 是一个 PDF 转换软件,它被用于加密和解密 PDF 文件,转换 PDF 文件到其他等效的 pdf 文件。 Qpdf 在大多数 Linux 发行版中的默认存储库中是可用的,所以你可以使用默认的软件包安装它。
|
||||
|
||||
例如, Qpdf 可以被安装在 Arch Linux 和它的衍生版,使用 [**pacman**][1] ,像下面显示。
|
||||
```
|
||||
$ sudo pacman -S qpdf
|
||||
|
||||
```
|
||||
|
||||
在 Debian, Ubuntu, Linux Mint 上:
|
||||
```
|
||||
$ sudo apt-get install qpdf
|
||||
|
||||
```
|
||||
|
||||
现在,让我们使用 qpdf 从一个 pdf 文件移除密码。
|
||||
|
||||
我有一个受密码保护的 PDF 文件,名为 **“secure.pdf”**. 每当我打开这个文件时,它提示我输入密码来显示它的内容。
|
||||
|
||||
![][3]
|
||||
|
||||
我知道上面 pdf 文件的密码。然而,我不想与任何人共享密码。所以,我将要做的事是简单地移除 PDF 文件的密码,使用 Qpdf 功能带有下面的命令。
|
||||
```
|
||||
$ qpdf --password='123456' --decrypt secure.pdf output.pdf
|
||||
|
||||
```
|
||||
|
||||
相当简单,不是吗?是的,它是!这里, **123456** 是 **secure.pdf** 文件的密码。用你自己的密码替换。
|
||||
|
||||
**方法 2 – 使用 Pdftk**
|
||||
|
||||
**Pdftk** 是另一个用于操作 pdf 文件的好软件。 Pdftk 可以做几乎所有分类的 pdf 操作,例如;
|
||||
|
||||
* 加密和解密 pdf 文件。
|
||||
* 合并 PDF 文档。
|
||||
* 整理 PDF 页扫描。
|
||||
* 拆分 PDF 页。
|
||||
* 旋转 PDF 文件或页。
|
||||
* 用 X/FDF 数据 填充 PDF 表单,和/或摧毁表单。
|
||||
* 从 PDF 表单中生成 PDF数据模板。
|
||||
* 应用一个背景水印,或一个前景印记。
|
||||
* 报告 PDF 度量标准,书签和元数据。
|
||||
* 添加/更新 PDF 书签或元数据。
|
||||
* 附加文件到 PDF 页,或 PDF 文档。
|
||||
* 解包 PDF 附件。
|
||||
* 破裂一个 PDF 文件到单页中。
|
||||
* 压缩和解压缩页流。
|
||||
* 修复破损的 PDF 文件。
|
||||
|
||||
|
||||
|
||||
Pddftk 在 AUR 中是可用的,所以你可以在 Arch Linux 和它的衍生版上使用任意 AUR 帮助程序安装它。
|
||||
|
||||
使用 [**Pacaur**][4]:
|
||||
```
|
||||
$ pacaur -S pdftk
|
||||
|
||||
```
|
||||
|
||||
使用 [**Packer**][5]:
|
||||
```
|
||||
$ packer -S pdftk
|
||||
|
||||
```
|
||||
|
||||
使用 [**Trizen**][6]:
|
||||
```
|
||||
$ trizen -S pdftk
|
||||
|
||||
```
|
||||
|
||||
使用 [**Yay**][7]:
|
||||
```
|
||||
$ yay -S pdftk
|
||||
|
||||
```
|
||||
|
||||
使用 [**Yaourt**][8]:
|
||||
```
|
||||
$ yaourt -S pdftk
|
||||
|
||||
```
|
||||
|
||||
在 Debian, Ubuntu, Linux Mint 上,运行:
|
||||
```
|
||||
$ sudo apt-get instal pdftk
|
||||
|
||||
```
|
||||
|
||||
在 CentOS, Fedora, Red Hat 上:
|
||||
|
||||
首先,安装 EPEL 仓库:
|
||||
```
|
||||
$ sudo yum install epel-release
|
||||
|
||||
```
|
||||
|
||||
或
|
||||
```
|
||||
$ sudo dnf install epel-release
|
||||
|
||||
```
|
||||
|
||||
然后,安装 PDFtk 应用程序,使用命令:
|
||||
```
|
||||
$ sudo yum install pdftk
|
||||
|
||||
```
|
||||
|
||||
或者
|
||||
```
|
||||
$ sudo dnf install pdftk
|
||||
|
||||
```
|
||||
|
||||
一旦 pdftk 安装,你可以从一个 pdf 文档移除密码,使用命令:
|
||||
```
|
||||
$ pdftk secure.pdf input_pw 123456 output output.pdf
|
||||
|
||||
```
|
||||
|
||||
用你正确的密码替换“123456”。这个命令解密 “secure.pdf” 文件,并创建一个相同的名为 “output.pdf” 的非密码保护的文件。
|
||||
|
||||
**也读:**
|
||||
|
||||
**方法 3 – 使用 Poppler**
|
||||
|
||||
**Poppler** 是一个基于 xpdf-3.0 代码基础的 PDF 渲染库。它包含下列用于操作 PDF 文档的命令行功能集。
|
||||
|
||||
* **pdfdetach** – 列出或提取嵌入的文件。
|
||||
* **pdffonts** – 字体分析器。
|
||||
* **pdfimages** – 图片提取器。
|
||||
* **pdfinfo** – 文档信息。
|
||||
* **pdfseparate** – 页提取工具。
|
||||
* **pdfsig** – 核查数字签名。
|
||||
* **pdftocairo** – PDF 到 PNG/JPEG/PDF/PS/EPS/SVG 转换器,使用 Cairo 。
|
||||
* **pdftohtml** – PDF 到 HTML 转换器。
|
||||
* **pdftoppm** – PDF 到 PPM/PNG/JPEG 图片转换器。
|
||||
* **pdftops** – PDF 到 PostScript (PS) 转换器。
|
||||
* **pdftotext** – text 提取。
|
||||
* **pdfunite** – 文档合并工具。
|
||||
|
||||
|
||||
|
||||
因这个指南的目的,我们仅使用 “pdftops” 功能。
|
||||
|
||||
在基于 Arch Linux 的发行版上,安装 Poppler,运行:
|
||||
```
|
||||
$ sudo pacman -S poppler
|
||||
|
||||
```
|
||||
|
||||
在 Debian, Ubuntu, Linux Mint 上:
|
||||
```
|
||||
$ sudo apt-get install poppler-utils
|
||||
|
||||
```
|
||||
|
||||
在 RHEL, CentOS, Fedora 上:
|
||||
```
|
||||
$ sudo yum install poppler-utils
|
||||
|
||||
```
|
||||
|
||||
一旦 Poppler 安装,运行下列命令来解密密码保护的 pdf 文件,并创建一个新的相同的名为 output.pdf 的文件。
|
||||
```
|
||||
$ pdftops -upw 123456 secure.pdf output.pdf
|
||||
|
||||
```
|
||||
|
||||
再一次,用你的 pdf 密码替换 “123456” 。
|
||||
|
||||
正如你在上面方法中可能注意到,我们仅转换密码保护的名为 “secure.pdf” 的 pdf 文件到另一个相同的名为 “output.pdf” 的 pdf 文件。技术上讲,我们并没有真的重源文件中移除密码,作为代替,我们解密它,并保存它为另一个相同的没有密码保护的 pdf 文件。
|
||||
|
||||
**方法 4 – 打印到一个文件
|
||||
**
|
||||
|
||||
这是在所有上面方法中的最简单的方法。你可以使用你存在的 PDF 查看器,例如 Atril 文档查看器, Evince 等等,并打印密码保护的 pdf 文件到另一个文件。
|
||||
|
||||
在你的 PDF 查看器应用程序中打开密码保护的文件。转到 **File - > Print** 。并在你选择的一些位置保存 pdf 文件。
|
||||
|
||||
![][9]
|
||||
|
||||
于是,这是全部。希望这是有用的。你知道/使用一些其它方法来从从 PDF 文件中移除密码保护And吗?在下面的评价区让我们知道。
|
||||
|
||||
更多好东西来了。敬请期待!
|
||||
|
||||
谢谢!
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-remove-password-from-a-pdf-file-in-linux/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[robsean ](https://github.com/robsean)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.ostechnix.com/author/sk/
|
||||
[1]:https://www.ostechnix.com/getting-started-pacman/
|
||||
[2]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[3]:http://www.ostechnix.com/wp-content/uploads/2018/04/Remove-Password-From-A-PDF-File-1.png
|
||||
[4]:https://www.ostechnix.com/install-pacaur-arch-linux/
|
||||
[5]:https://www.ostechnix.com/install-packer-arch-linux-2/
|
||||
[6]:https://www.ostechnix.com/trizen-lightweight-aur-package-manager-arch-based-systems/
|
||||
[7]:https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
|
||||
[8]:https://www.ostechnix.com/install-yaourt-arch-linux/
|
@ -1,37 +1,38 @@
|
||||
yongshouzhang translating
|
||||
|
||||
HTTP request routing and validation with gorilla/mux
|
||||
使用 gorilla/mux 进行HTTP请求路由和验证
|
||||
======
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr)
|
||||
|
||||
The Go networking library includes the `http.ServeMux` structure type, which supports HTTP request multiplexing (routing): A web server routes an HTTP request for a hosted resource, with a URI such as /sales4today, to a code handler; the handler performs the appropriate logic before sending an HTTP response, typically an HTML page. Here’s a sketch of the architecture:
|
||||
Go 网络库包括 `http.ServeMux` 结构类型,它支持 HTTP 请求多路复用(路由):Web 服务器将托管资源的 HTTP 请求与诸如 sales4today 之类的 URI 路由到代码处理程序; 处理程序在发送 HTTP 响应(通常是 HTML 页面)之前执行适当的逻辑。 这是该体系的草图:
|
||||
|
||||
```
|
||||
+------------+ +--------+ +---------+
|
||||
HTTP request---->| web server |---->| router |---->| handler |
|
||||
HTTP 请求---->| web 服务器 |---->| 路由 |---->| 处理程序|
|
||||
+------------+ +--------+ +---------+
|
||||
```
|
||||
|
||||
In a call to the `ListenAndServe` method to start an HTTP server
|
||||
调用 `ListenAndServe` 方法后启动 HTTP 服务器
|
||||
|
||||
```
|
||||
http.ListenAndServe(":8888", nil) // args: port & router
|
||||
```
|
||||
|
||||
a second argument of `nil` means that the `DefaultServeMux` is used for request routing.
|
||||
|
||||
The `gorilla/mux` package has a `mux.Router` type as an alternative to either the `DefaultServeMux` or a customized request multiplexer. In the `ListenAndServe` call, a `mux.Router` instance would replace `nil` as the second argument. What makes the `mux.Router` so appealing is best shown through a code example:
|
||||
第二个参数 `nil` 意味着 `DefaultServeMux` 用于请求路由。
|
||||
|
||||
`gorilla/mux` 库包含 `mux.Router` 类型,可替代 `DefaultServeMux` 或自定义请求多路复用器。 在 `ListenAndServe` 调用中,`mux.Router` 实例将代替 `nil` 作为第二个参数。 下面的示例代码很好的说明了为什么 `mux.Router`如此吸引人:
|
||||
|
||||
### 1\. A sample crud web app
|
||||
|
||||
The crud web application (see below) supports the four CRUD (Create Read Update Delete) operations, which match four HTTP request methods: POST, GET, PUT, and DELETE, respectively. In the crud app, the hosted resource is a list of cliche pairs, each a cliche and a conflicting cliche such as this pair:
|
||||
crud web 应用程序(见下文)支持四种 CRUD(创建读取更新删除)操作,它们分别对应四种 HTTP 请求方法:POST,GET,PUT 和 DELETE。 在 crud 应用程序中,托管资源是陈词滥调对的列表,每个陈词滥调都是陈词滥调和冲突的陈词滥调,例如这对:
|
||||
```
|
||||
Out of sight, out of mind. Absence makes the heart grow fonder.
|
||||
|
||||
```
|
||||
|
||||
New cliche pairs can be added, and existing ones can be edited or deleted.
|
||||
可以添加新的陈词滥调对,可以编辑或删除现有的陈词滥调对。
|
||||
|
||||
**The crud web app**
|
||||
**crud web 应用程序**
|
||||
```
|
||||
package main
|
||||
|
||||
@ -446,43 +447,45 @@ func populateClichesList() {
|
||||
|
||||
```
|
||||
|
||||
To focus on request routing and validation, the crud app does not use HTML pages as responses to requests. Instead, requests result in plaintext response messages: A list of the cliche pairs is the response to a GET request, confirmation that a new cliche pair has been added to the list is a response to a POST request, and so on. This simplification makes it easy to test the app, in particular, the `gorilla/mux` components, with a command-line utility such as [curl][1].
|
||||
为了专注于请求路由和验证,crud 应用程序不使用 HTML 页面作为请求响应。 相反,请求会产生明文响应消息:陈词滥调对的列表是对 GET 请求的响应,确认新的陈词滥调对已添加到列表中是对 POST 请求的响应,依此类推。 这种简化使得使用命令行实用程序(如 [curl] [1])可以轻松地测试应用程序,尤其是 `gorilla/mux` 组件。
|
||||
|
||||
The `gorilla/mux` package can be installed from [GitHub][2]. The crud app runs indefinitely; hence, it should be terminated with a Control-C or equivalent. The code for the crud app, together with a README and sample curl tests, is available on [my website][3].
|
||||
`gorilla/mux` 包可以从 [GitHub] [2] 安装。 crud app 无限期运行; 因此,应使用 Control-C 或同等命令终止。 crud 应用程序的代码,以及自述文件和简单的 curl 测试,可以在[我的网站] [3]上找到。
|
||||
|
||||
### 2\. Request routing
|
||||
### 2\. 请求路由
|
||||
|
||||
`mux.Router` 扩展了 REST 风格的路由,它赋给 HTTP 方法(例如,GET)和 URL 末尾的 URI 或路径(例如/cliches)相同的权重。 URI 用作 HTTP 动词(方法)的名词。 例如,在HTTP请求中有一个起始行,例如
|
||||
|
||||
The `mux.Router` extends REST-style routing, which gives equal weight to the HTTP method (e.g., GET) and the URI or path at the end of a URL (e.g., /cliches). The URI serves as the noun for the HTTP verb (method). For example, in an HTTP request a startline such as
|
||||
```
|
||||
GET /cliches
|
||||
|
||||
```
|
||||
|
||||
means get all of the cliche pairs, whereas a startline such as
|
||||
意味着得到所有的陈词滥调对,而一个起始线,如
|
||||
|
||||
```
|
||||
POST /cliches
|
||||
|
||||
```
|
||||
|
||||
means create a cliche pair from data in the HTTP body.
|
||||
意味着从HTTP正文中的数据创建一个陈词滥调对。
|
||||
|
||||
In the crud web app, there are five functions that act as request handlers for five variations of an HTTP request:
|
||||
在 crud web 应用程序中,有五个函数充当HTTP请求的五种变体的请求处理程序:
|
||||
```
|
||||
ClichesAll(...) # GET: get all of the cliche pairs
|
||||
ClichesAll(...) # GET: 获取所有的陈词滥调对
|
||||
|
||||
ClichesOne(...) # GET: get a specified cliche pair
|
||||
ClichesOne(...) # GET: 获取指定的陈词滥调对
|
||||
|
||||
ClichesCreate(...) # POST: create a new cliche pair
|
||||
ClichesCreate(...) # POST: 创建新的陈词滥调对
|
||||
|
||||
ClichesEdit(...) # PUT: edit an existing cliche pair
|
||||
ClichesEdit(...) # PUT: 编辑现有的陈词滥调对
|
||||
|
||||
ClichesDelete(...) # DELETE: delete a specified cliche pair
|
||||
ClichesDelete(...) # DELETE: 删除指定的陈词滥调对
|
||||
|
||||
```
|
||||
|
||||
Each function takes two arguments: an `http.ResponseWriter` for sending a response back to the requester, and a pointer to an `http.Request`, which encapsulates information from the underlying HTTP request. The `gorilla/mux` package makes it easy to register these request handlers with the web server, and to perform regex-based validation.
|
||||
每个函数都有两个参数:一个 `http.ResponseWriter` 用于向请求者发送一个响应,一个指向 `http.Request` 的指针,该指针封装了底层 HTTP 请求的信息。 使用 `gorilla/mux` 包可以轻松地将这些请求处理程序注册到Web服务器,并执行基于正则表达式的验证。
|
||||
|
||||
The `startServer` function in the crud app registers the request handlers. Consider this pair of registrations, with `router` as a `mux.Router` instance:
|
||||
crud 应用程序中的 `startServer` 函数注册请求处理程序。 考虑这对注册,`router` 作为 `mux.Router` 实例:
|
||||
```
|
||||
router.HandleFunc("/", ClichesAll).Methods("GET")
|
||||
|
||||
@ -490,13 +493,14 @@ router.HandleFunc("/cliches", ClichesAll).Methods("GET")
|
||||
|
||||
```
|
||||
|
||||
These statements mean that a GET request for either the single slash / or /cliches should be routed to the `ClichesAll` function, which then handles the request. For example, the curl request (with % as the command-line prompt)
|
||||
这些语句意味着对单斜线/ 或 /cliches 的 GET 请求应该路由到 `ClichesAll` 函数,然后处理请求。 例如,curl 请求(使用%作为命令行提示符)
|
||||
|
||||
```
|
||||
% curl --request GET localhost:8888/
|
||||
|
||||
```
|
||||
|
||||
produces this response:
|
||||
会产生如下结果
|
||||
```
|
||||
1: Out of sight, out of mind. Absence makes the heart grow fonder.
|
||||
|
||||
@ -506,9 +510,10 @@ produces this response:
|
||||
|
||||
```
|
||||
|
||||
The three cliche pairs are the initial data in the crud app.
|
||||
三个陈词滥调对是 crud 应用程序中的初始数据。
|
||||
|
||||
In this pair of registration statements
|
||||
|
||||
在这句注册语句中
|
||||
```
|
||||
router.HandleFunc("/cliches", ClichesAll).Methods("GET")
|
||||
|
||||
@ -516,84 +521,85 @@ router.HandleFunc("/cliches", ClichesCreate).Methods("POST")
|
||||
|
||||
```
|
||||
|
||||
the URI is the same (/cliches) but the verbs differ: GET in the first case, and POST in the second. This registration exemplifies REST-style routing because the difference in the verbs alone suffices to dispatch the requests to two different handlers.
|
||||
URI是相同的(/cliches),但动词不同:第一种情况下为 GET 请求,第二种情况下为 POST 请求。 此注册举例说明了 REST 样式的路由,因为仅动词的不同就足以将请求分派给两个不同的处理程序。
|
||||
|
||||
注册中允许多个 HTTP 方法,尽管这会影响 REST 风格路由的精髓:
|
||||
|
||||
More than one HTTP method is allowed in a registration, although this strains the spirit of REST-style routing:
|
||||
```
|
||||
router.HandleFunc("/cliches", DoItAll).Methods("POST", "GET")
|
||||
|
||||
```
|
||||
除了动词和 URI 之外,还可以在功能上路由 HTTP 请求。 例如,注册
|
||||
|
||||
HTTP requests can be routed on features besides the verb and the URI. For example, the registration
|
||||
```
|
||||
router.HandleFunc("/cliches", ClichesCreate).Schemes("https").Methods("POST")
|
||||
|
||||
```
|
||||
|
||||
requires HTTPS access for a POST request to create a new cliche pair. In similar fashion, a registration might require a request to have a specified HTTP header element (e.g., an authentication credential).
|
||||
要求对 POST 请求进行 HTTPS 访问以创建新的陈词滥调对。 以类似的方式,注册可能需要具有指定的 HTTP 头元素(例如,认证凭证)的请求。
|
||||
|
||||
### 3\. Request validation
|
||||
|
||||
The `gorilla/mux` package takes an easy, intuitive approach to request validation through regular expressions. Consider this request handler for a get one operation:
|
||||
`gorilla/mux` 包采用简单,直观的方法通过正则表达式进行请求验证。 考虑此请求处理程序以获取一个操作:
|
||||
```
|
||||
router.HandleFunc("/cliches/{id:[0-9]+}", ClichesOne).Methods("GET")
|
||||
|
||||
```
|
||||
|
||||
This registration rules out HTTP requests such as
|
||||
此注册排除了 HTTP 请求,例如
|
||||
```
|
||||
% curl --request GET localhost:8888/cliches/foo
|
||||
|
||||
```
|
||||
|
||||
because foo is not a decimal numeral. The request results in the familiar 404 (Not Found) status code. Including the regex pattern in this handler registration ensures that the `ClichesOne` function is called to handle a request only if the request URI ends with a decimal integer value:
|
||||
因为 foo 不是十进制数字。 该请求导致熟悉的 404(未找到)状态码。 在此处理程序注册中包含正则表达式模式可确保仅在请求 URI 以十进制整数值结束时才调用 `ClichesOne` 函数来处理请求:
|
||||
|
||||
```
|
||||
% curl --request GET localhost:8888/cliches/3 # ok
|
||||
|
||||
```
|
||||
|
||||
As a second example, consider the request
|
||||
另一个例子,请求如下
|
||||
```
|
||||
% curl --request PUT --data "..." localhost:8888/cliches
|
||||
|
||||
```
|
||||
此请求导致状态代码为 405(错误方法),因为 /cliches URI 在 crud 应用程序中仅在 GET 和 POST 请求中注册。 像 GET 请求一样,PUT 请求必须在 URI 的末尾包含一个数字id:
|
||||
|
||||
This request results in a status code of 405 (Bad Method) because the /cliches URI is registered, in the crud app, only for GET and POST requests. A PUT request, like a GET one request, must include a numeric id at the end of the URI:
|
||||
```
|
||||
router.HandleFunc("/cliches/{id:[0-9]+}", ClichesEdit).Methods("PUT")
|
||||
|
||||
```
|
||||
|
||||
### 4\. Concurrency issues
|
||||
### 4\. 并发问题
|
||||
|
||||
`gorilla/mux` 路由器作为单独的 goroutine 执行对已注册的请求处理程序的每次调用,这意味着并发性被烘焙到包中。 例如,如果有十个同时发出的请求,例如
|
||||
|
||||
The `gorilla/mux` router executes each call to a registered request handler as a separate goroutine, which means that concurrency is baked into the package. For example, if there are ten simultaneous requests such as
|
||||
```
|
||||
% curl --request POST --data "..." localhost:8888/cliches
|
||||
|
||||
```
|
||||
|
||||
then the `mux.Router` launches ten goroutines to execute the `ClichesCreate` handler.
|
||||
然后 `mux.Router` 启动十个 goroutines 来执行 `ClichesCreate` 处理程序。
|
||||
|
||||
Of the five request operations GET all, GET one, POST, PUT, and DELETE, the last three alter the requested resource, the shared `clichesList` that houses the cliche pairs. Accordingly, the crudapp needs to guarantee safe concurrency by coordinating access to the `clichesList`. In different but equivalent terms, the crud app must prevent a race condition on the `clichesList`. In a production environment, a database system might be used to store a resource such as the `clichesList`, and safe concurrency then could be managed through database transactions.
|
||||
GET all,GET one,POST,PUT 和 DELETE 中的五个请求操作中,最后三个改变了所请求的资源,即包含陈词滥调对的共享 `clichesList`。 因此,crudapp 需要通过协调对`clichesList` 的访问来保证安全的并发性。 在不同但等效的术语中,crud app 必须防止 `clichesList` 上的竞争条件。 在生产环境中,可以使用数据库系统来存储诸如 `clichesList` 之类的资源,然后可以通过数据库事务来管理安全并发。
|
||||
|
||||
The crud app takes the recommended Go approach to safe concurrency:
|
||||
crud 应用程序采用推荐的Go方法来实现安全并发:
|
||||
|
||||
* Only a single goroutine, the resource manager started in the crud app `startServer` function, has access to the `clichesList` once the web server starts listening for requests.
|
||||
* The request handlers such as `ClichesCreate` and `ClichesAll` send a (pointer to) a `crudRequest` instance to a Go channel (thread-safe by default), and the resource manager alone reads from this channel. The resource manager then performs the requested operation on the `clichesList`.
|
||||
* 只有一个 goroutine,资源管理器在 crud app`startServer` 函数中启动,一旦 Web 服务器开始侦听请求,就可以访问 `clichesList`。
|
||||
* 诸如 `ClichesCreate` 和 `ClichesAll` 之类的请求处理程序向 Go 通道发送(指向)`crudRequest` 实例(默认情况下是线程安全的),并且资源管理器单独从该通道读取。 然后,资源管理器对 `clichesList` 执行请求的操作。
|
||||
|
||||
安全并发体系结构绘制如下:
|
||||
|
||||
|
||||
The safe-concurrency architecture can be sketched as follows:
|
||||
```
|
||||
crudRequest read/write
|
||||
crudRequest 读/写
|
||||
|
||||
request handlers------------->resource manager------------>clichesList
|
||||
请求处理程序 -------------> 资源托管者 ------------> 陈词滥调列表
|
||||
|
||||
```
|
||||
|
||||
With this architecture, no explicit locking of the `clichesList` is needed because only one goroutine, the resource manager, accesses the `clichesList` once CRUD requests start coming in.
|
||||
在这种架构中,不需要显式锁定 `clichesList`,因为一旦 CRUD 请求开始进入,只有一个 goroutine(资源管理器)访问 `clichesList`。
|
||||
|
||||
为了使 crud 应用程序尽可能保持并发,在一方请求处理程序与另一方的单一资源管理器之间进行有效的分工至关重要。 在这里,为了审查,是 `ClichesCreate` 请求处理程序:
|
||||
|
||||
To keep the crud app as concurrent as possible, it’s essential to have an efficient division of labor between the request handlers, on the one side, and the single resource manager, on the other side. Here, for review, is the `ClichesCreate` request handler:
|
||||
```
|
||||
func ClichesCreate(res http.ResponseWriter, req *http.Request) {
|
||||
|
||||
@ -612,42 +618,40 @@ func ClichesCreate(res http.ResponseWriter, req *http.Request) {
|
||||
}ClichesCreateres httpResponseWriterreqclichecountergetDataFromRequestreqcpclichePaircpClicheclichecpCountercountercr&crudRequestverbPOSTcpcpconfirmcompleteRequestcrres
|
||||
|
||||
```
|
||||
`ClichesCreate` 调用实用函数 `getDataFromRequest`,它从 POST 请求中提取新的陈词滥调和反陈词滥调。 然后 `ClichesCreate` 函数创建一个新的 `ClichePair`,设置两个字段,并创建一个 `crudRequest` 发送给单个资源管理器。 此请求包括一个确认通道,资源管理器使用该通道将信息返回给请求处理程序。 所有设置工作都可以在不涉及资源管理器的情况下完成,因为尚未访问 `clichesList`。
|
||||
|
||||
`ClichesCreate` calls the utility function `getDataFromRequest`, which extracts the new cliche and counter-cliche from the POST request. The `ClichesCreate` function then creates a new `ClichePair`, sets two fields, and creates a `crudRequest` to be sent to the single resource manager. This request includes a confirmation channel, which the resource manager uses to return information back to the request handler. All of the setup work can be done without involving the resource manager because the `clichesList` is not being accessed yet.
|
||||
请求处理程序调用实用程序函数,该函数从 POST 请求中提取新的陈词滥调和反陈词滥调。 然后,该函数创建一个新的,设置两个字段,并创建 ato 发送到单个资源管理器。 此请求包括一个确认通道,资源管理器使用该通道将信息返回给请求处理程序。 所有设置工作都可以在不涉及资源管理器的情况下完成,因为尚未访问它。
|
||||
|
||||
The request handlercalls the utility function, which extracts the new cliche and counter-cliche from the POST request. Thefunction then creates a new, sets two fields, and creates ato be sent to the single resource manager. This request includes a confirmation channel, which the resource manager uses to return information back to the request handler. All of the setup work can be done without involving the resource manager because theis not being accessed yet.
|
||||
|
||||
The `completeRequest` utility function called at the end of the `ClichesCreate` function and the other request handlers
|
||||
`completeRequest` 实用程序函数在 `ClichesCreate` 函数和其他请求处理程序的末尾调用
|
||||
```
|
||||
completeRequest(cr, res, "create") // shown above
|
||||
|
||||
```
|
||||
|
||||
brings the resource manager into play by putting a `crudRequest` into the `crudRequests` channel:
|
||||
通过将 `crudRequest` 放入 `crudRequests` 频道,使资源管理器发挥作用:
|
||||
```
|
||||
func completeRequest(cr *crudRequest, res http.ResponseWriter, logMsg string) {
|
||||
|
||||
crudRequests<-cr // send request to resource manager
|
||||
crudRequests<-cr // 向资源托管者发送请求
|
||||
|
||||
msg := <-cr.confirm // await confirmation string
|
||||
msg := <-cr.confirm // 等待确认
|
||||
|
||||
res.Write([]byte(msg)) // send confirmation back to requester
|
||||
res.Write([]byte(msg)) // 向请求方发送确认
|
||||
|
||||
logIt(logMsg) // print to the standard output
|
||||
logIt(logMsg) // 打印到标准输出
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
For a POST request, the resource manager calls the utility function `addPair`, which changes the `clichesList` resource:
|
||||
对于 POST 请求,资源管理器调用实用程序函数 `addPair`,它会更改 `clichesList` 资源:
|
||||
```
|
||||
func addPair(cp *clichePair) string {
|
||||
|
||||
cp.Id = masterId // assign a unique ID
|
||||
cp.Id = masterId // 分配一个唯一的 ID
|
||||
|
||||
masterId++ // update the ID counter
|
||||
masterId++ // 更新 ID 计数器
|
||||
|
||||
clichesList = append(clichesList, cp) // update the list
|
||||
clichesList = append(clichesList, cp) // 更新列表
|
||||
|
||||
return "\nCreated: " + cp.Cliche + " " + cp.Counter + "\n"
|
||||
|
||||
@ -655,9 +659,9 @@ func addPair(cp *clichePair) string {
|
||||
|
||||
```
|
||||
|
||||
The resource manager calls similar utility functions for the other CRUD operations. It’s worth repeating that the resource manager is the only goroutine to read or write the `clichesList` once the web server starts accepting requests.
|
||||
资源管理器为其他CRUD操作调用类似的实用程序函数。 值得重复的是,一旦 Web 服务器开始接受请求,资源管理器就是唯一可以读取或写入 `clichesList` 的 goroutine。
|
||||
|
||||
For web applications of any type, the `gorilla/mux` package provides request routing, request validation, and related services in a straightforward, intuitive API. The crud web app highlights the package’s main features. Give the package a test drive, and you’ll likely be a buyer.
|
||||
对于任何类型的 Web 应用程序,`gorilla/mux` 包在简单直观的API中提供请求路由,请求验证和相关服务。 crud web 应用程序突出了软件包的主要功能。 给包裹一个测试驱动,你可能会成为买主。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -665,7 +669,7 @@ via: https://opensource.com/article/18/8/http-request-routing-validation-gorilla
|
||||
|
||||
作者:[Marty Kalin][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[yongshouzhang](https://github.com/yongshouzhang)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
@ -0,0 +1,462 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer:
|
||||
[#]: publisher:
|
||||
[#]: subject: (How to Build a Netboot Server, Part 1)
|
||||
|
||||
[#]: via: (https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/)
|
||||
[#]: author: (Gregory Bartholomew https://fedoramagazine.org/author/glb/)
|
||||
|
||||
[#]: url:
|
||||
|
||||
如何构建一台网络引导服务器(第一部分)
|
||||
======
|
||||
|
||||
![](https://fedoramagazine.org/wp-content/uploads/2018/11/build-netboot-816x345.jpg)
|
||||
|
||||
有些计算机网络需要在各个物理机器上维护相同的软件和配置。学校的计算机实验室就是这样的一个环境。一台 [网络引导][1] 服务器能够被配置为基于网络去提供一个完整的操作系统,以便于客户端计算机从一个中央位置获取配置。本教程将向你展示构建一台网络引导服务器的一种方法。
|
||||
|
||||
本教程的第一部分将包括创建一台网络引导服务器和镜像。第二部分将展示如何去添加 Kerberos 验证的 home 目录到网络引导配置中。
|
||||
|
||||
### 初始化配置
|
||||
|
||||
首先去下载 Fedora 服务器的 [netinst][2] 镜像,将它刻录到一张光盘上,然后它将引导服务器去重新格式化。我们只需要一个典型的 Fedora Server 的“最小化安装”来作为我们的开端,安装完成后,我们可以使用命令行去添加我们需要的任何额外的包。
|
||||
|
||||
![][3]
|
||||
|
||||
> 注意:本教程中我们将使用 Fedora 28。其它版本在“最小化安装”中包含的包可能略有不同。如果你使用的是不同的 Fedora 版本,如果一个预期的文件或命令不可用,你可能需要做一些调试。
|
||||
|
||||
最小化安装的 Fedora Server 运行起来之后,以 root 用户登入并设置主机名字:
|
||||
|
||||
```javascript
|
||||
$ MY_HOSTNAME=server-01.example.edu
|
||||
$ hostnamectl set-hostname $MY_HOSTNAME
|
||||
```
|
||||
|
||||
> 注意:Red Hat 建议静态和临时名字应都要与这个机器在 DNS 中的完全合格域名相匹配,比如 host.example.com([了解主机名字][4])。
|
||||
>
|
||||
> 注意:本指南为了你“复制粘贴”友好。需要自定义的任何值都声明为一个 MY_* 变量,在你运行剩余命令之前,你可能需要调整它。如果你注销之后,变量的赋值将被清除。
|
||||
>
|
||||
> 注意:Fedora 28 Server 在默认情况下往往会转储大量的日志到控制台上。你可以通过运行命令:sysctl -w kernel.printk=0 去禁用控制台日志输出。
|
||||
|
||||
接下来,我们需要在我们的服务器上配置一个静态网络地址。运行下面的一系列命令将找到并重新配置你的默认网络连接:
|
||||
|
||||
```javascript
|
||||
$ MY_DNS1=192.0.2.91
|
||||
$ MY_DNS2=192.0.2.92
|
||||
$ MY_IP=192.0.2.158
|
||||
$ MY_PREFIX=24
|
||||
$ MY_GATEWAY=192.0.2.254
|
||||
$ DEFAULT_DEV=$(ip route show default | awk '{print $5}')
|
||||
$ DEFAULT_CON=$(nmcli d show $DEFAULT_DEV | sed -n '/^GENERAL.CONNECTION:/s!.*:\s*!! p')
|
||||
$ nohup bash << END
|
||||
nmcli con mod "$DEFAULT_CON" connection.id "$DEFAULT_DEV"
|
||||
nmcli con mod "$DEFAULT_DEV" connection.interface-name "$DEFAULT_DEV"
|
||||
nmcli con mod "$DEFAULT_DEV" ipv4.method disabled
|
||||
nmcli con up "$DEFAULT_DEV"
|
||||
nmcli con add con-name br0 ifname br0 type bridge
|
||||
nmcli con mod br0 bridge.stp no
|
||||
nmcli con mod br0 ipv4.dns $MY_DNS1,$MY_DNS2
|
||||
nmcli con mod br0 ipv4.addresses $MY_IP/$MY_PREFIX
|
||||
nmcli con mod br0 ipv4.gateway $MY_GATEWAY
|
||||
nmcli con mod br0 ipv4.method manual
|
||||
nmcli con up br0
|
||||
nmcli con add con-name br0-slave0 ifname "$DEFAULT_DEV" type bridge-slave master br0
|
||||
nmcli con up br0-slave0
|
||||
END
|
||||
```
|
||||
|
||||
> 注意:上面最后的一组命令被封装到一个 “nohup” 脚本中,因为它将临时禁用网络。这个 nohup 命令将允许 nmcli 命令去完成运行,直到你的 SSH 连接断开。注意,连接恢复可能需要 10 秒左右的时间,如果你改变了服务器 IP 地址,你将需要重新启动一个新的 SSH 连接。
|
||||
>
|
||||
> 注意:上面的网络配置在默认的连接之上创建了一个 [网桥][5],这样我们在后面的测试中就可以直接运行一个虚拟机实例。如果你不想在这台服务器上去直接测试网络引导镜像,你可以跳过创建网桥的命令,并直接在你的默认网络连接上配置静态 IP 地址。
|
||||
|
||||
### 安装和配置 NFS4
|
||||
|
||||
从安装 nfs-utils 包开始:
|
||||
|
||||
```
|
||||
$ dnf install -y nfs-utils
|
||||
```
|
||||
|
||||
为发布 NFS 去创建一个顶级的 [伪文件系统][6],然后在你的网络上共享它:
|
||||
|
||||
```javascript
|
||||
$ MY_SUBNET=192.0.2.0
|
||||
$ mkdir /export
|
||||
$ echo "/export -fsid=0,ro,sec=sys,root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports
|
||||
```
|
||||
|
||||
SELinux 将干扰网络引导服务器的运行。在本教程中我们将不涉及为它配置例外的部分,因此我们直接禁用它:
|
||||
|
||||
```javascript
|
||||
$ sed -i '/GRUB_CMDLINE_LINUX/s/"$/ audit=0 selinux=0"/' /etc/default/grub
|
||||
$ grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
|
||||
$ setenforce 0
|
||||
```
|
||||
|
||||
> 注意:编辑 grub 命令行应该是不需要的,但在测试过程中发现,简单地编辑 /etc/sysconfig/selinux 被证明重启后是无效的,因此再次确保设置了 “selinux=0” 标志。
|
||||
|
||||
现在,在本地防火墙中为 NFS 服务添加一个例外,然后启动 NFS 服务:
|
||||
|
||||
```javascript
|
||||
$ firewall-cmd --add-service nfs
|
||||
$ firewall-cmd --runtime-to-permanent
|
||||
$ systemctl enable nfs-server.service
|
||||
$ systemctl start nfs-server.service
|
||||
```
|
||||
|
||||
### 创建网络引导镜像
|
||||
|
||||
现在我们的 NFS 服务器已经启动运行了,我们需要为它提供一个操作系统镜像,以便于它提供给客户端计算机。我们将从一个非常小的镜像开始,等一切顺利之后再添加。
|
||||
|
||||
首先,创建一个存放我们镜像的新目录:
|
||||
|
||||
```
|
||||
$ mkdir /fc28
|
||||
```
|
||||
|
||||
使用 “dnf” 命令在新目录下用几个基础包去构建镜像:
|
||||
|
||||
```javascript
|
||||
$ dnf -y --releasever=28 --installroot=/fc28 install fedora-release systemd passwd rootfiles sudo dracut dracut-network nfs-utils vim-minimal dnf
|
||||
```
|
||||
|
||||
在上面的命令中省略了很重要的 “kernel” 包。在它们被安装完成之前,我们需要去调整一下 “initramfs” 镜像中包含的驱动程序集,“kernel” 首次安装时将自动构建这个镜像。尤其是,我们需要禁用 “hostonly” 模式,以便于 initramfs 镜像能够在各种硬件平台上正常工作,并且我们还需要添加对网络和 NFS 的支持:
|
||||
|
||||
```javascript
|
||||
$ echo 'hostonly=no' > /fc28/etc/dracut.conf.d/hostonly.conf
|
||||
$ echo 'add_dracutmodules+=" network nfs "' > /fc28/etc/dracut.conf.d/netboot.conf
|
||||
```
|
||||
|
||||
现在,安装 kernel:
|
||||
|
||||
```javascript
|
||||
$ dnf -y --installroot=/fc28 install kernel
|
||||
```
|
||||
|
||||
设置一个阻止 kernel 被更新的规则:
|
||||
|
||||
```javascript
|
||||
$ echo 'exclude=kernel-*' >> /fc28/etc/dnf/dnf.conf
|
||||
```
|
||||
|
||||
设置 locale:
|
||||
|
||||
```javascript
|
||||
$ echo 'LANG="en_US.UTF-8"' > /fc28/etc/locale.conf
|
||||
```
|
||||
|
||||
> 注意:如果 locale 没有正确配置,一些程序(如 GNOME Terminal)将无法正常工作。
|
||||
|
||||
root 用户密码留空:
|
||||
|
||||
```javascript
|
||||
$ sed -i 's/^root:\*/root:/' /fc28/etc/shadow
|
||||
```
|
||||
|
||||
设置客户端的主机名字:
|
||||
|
||||
```javascript
|
||||
$ MY_CLIENT_HOSTNAME=client-01.example.edu
|
||||
$ echo $MY_CLIENT_HOSTNAME > /fc28/etc/hostname
|
||||
```
|
||||
|
||||
禁用控制台日志输出:
|
||||
|
||||
```javascript
|
||||
$ echo 'kernel.printk = 0 4 1 7' > /fc28/etc/sysctl.d/00-printk.conf
|
||||
```
|
||||
|
||||
定义网络引导镜像中的本地 “liveuser” 用户:
|
||||
|
||||
```javascript
|
||||
$ echo 'liveuser:x:1000:1000::/home/liveuser:/bin/bash' >> /fc28/etc/passwd
|
||||
$ echo 'liveuser::::::::' >> /fc28/etc/shadow
|
||||
$ echo 'liveuser:x:1000:' >> /fc28/etc/group
|
||||
$ echo 'liveuser:!::' >> /fc28/etc/gshadow
|
||||
```
|
||||
|
||||
在 sudo 中启用 “liveuser”:
|
||||
|
||||
```javascript
|
||||
$ echo 'liveuser ALL=(ALL) NOPASSWD: ALL' > /fc28/etc/sudoers.d/liveuser
|
||||
```
|
||||
|
||||
启用自动 home 目录创建:
|
||||
|
||||
```livescript
|
||||
$ dnf install -y --installroot=/fc28 authselect oddjob-mkhomedir
|
||||
$ echo 'dirs /home' > /fc28/etc/rwtab.d/home
|
||||
$ chroot /fc28 authselect select sssd with-mkhomedir --force
|
||||
$ chroot /fc28 systemctl enable oddjobd.service
|
||||
```
|
||||
|
||||
由于多个客户端将会同时挂载我们的镜像,我们需要去配置镜像工作在只读模式中:
|
||||
|
||||
```livescript
|
||||
$ sed -i 's/^READONLY=no$/READONLY=yes/' /fc28/etc/sysconfig/readonly-root
|
||||
```
|
||||
|
||||
配置日志输出到内存而不是持久存储中:
|
||||
|
||||
```livescript
|
||||
$ sed -i 's/^#Storage=auto$/Storage=volatile/' /fc28/etc/systemd/journald.conf
|
||||
```
|
||||
|
||||
配置 DNS:
|
||||
|
||||
```livescript
|
||||
$ MY_DNS1=192.0.2.91
|
||||
$ MY_DNS2=192.0.2.92
|
||||
$ cat << END > /fc28/etc/resolv.conf
|
||||
nameserver $MY_DNS1
|
||||
nameserver $MY_DNS2
|
||||
END
|
||||
```
|
||||
|
||||
解决编写本教程时存在的只读 root 挂载 bug([BZ1542567][7]):
|
||||
|
||||
```livescript
|
||||
$ echo 'dirs /var/lib/gssproxy' > /fc28/etc/rwtab.d/gssproxy
|
||||
$ cat << END > /fc28/etc/rwtab.d/systemd
|
||||
dirs /var/lib/systemd/catalog
|
||||
dirs /var/lib/systemd/coredump
|
||||
END
|
||||
```
|
||||
|
||||
最后,为我们镜像创建 NFS 文件系统,并将它共享到我们的子网中:
|
||||
|
||||
```livescript
|
||||
$ mkdir /export/fc28
|
||||
$ echo '/fc28 /export/fc28 none bind 0 0' >> /etc/fstab
|
||||
$ mount /export/fc28
|
||||
$ echo "/export/fc28 -ro,sec=sys,no_root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports.d/fc28.exports
|
||||
$ exportfs -vr
|
||||
```
|
||||
|
||||
### 创建引导加载器
|
||||
|
||||
现在,我们已经有了可以进行网络引导的操作系统,我们需要一个引导加载器去从客户端系统上启动它。在本教程中我们使用的是 [iPXE][8].
|
||||
|
||||
> 注意:本节和接下来的节 — 使用 QEMU 测试 — 能在另外一台单独的计算机上来完成;它们不需要在网络引导服务器上来运行。
|
||||
|
||||
安装 git 并使用它去下载 iPXE:
|
||||
|
||||
```livescript
|
||||
$ dnf install -y git
|
||||
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
|
||||
```
|
||||
|
||||
现在我们需要去为我们的引导加载器创建一个指定的启动脚本:
|
||||
|
||||
```livescript
|
||||
$ cat << 'END' > $HOME/ipxe/init.ipxe
|
||||
#!ipxe
|
||||
|
||||
prompt --key 0x02 --timeout 2000 Press Ctrl-B for the iPXE command line... && shell ||
|
||||
|
||||
dhcp || exit
|
||||
set prefix file:///linux
|
||||
chain ${prefix}/boot.cfg || exit
|
||||
END
|
||||
```
|
||||
|
||||
启动 “file” 下载协议:
|
||||
|
||||
```livescript
|
||||
$ echo '#define DOWNLOAD_PROTO_FILE' > $HOME/ipxe/src/config/local/general.h
|
||||
```
|
||||
|
||||
安装 C 编译器以及相关的工具和库:
|
||||
|
||||
```livescript
|
||||
$ dnf groupinstall -y "C Development Tools and Libraries"
|
||||
```
|
||||
|
||||
构建引导加载器:
|
||||
|
||||
```livescript
|
||||
$ cd $HOME/ipxe/src
|
||||
$ make clean
|
||||
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe
|
||||
```
|
||||
|
||||
记下新编译的引导加载器的存储位置。我们将在接下来的节中用到它:
|
||||
|
||||
```livescript
|
||||
$ IPXE_FILE="$HOME/ipxe/src/bin-x86_64-efi/ipxe.efi"
|
||||
```
|
||||
|
||||
### 用 QEMU 测试
|
||||
|
||||
这一节是可选的,但是你需要去复制下面显示在物理机器上的 [EFI 系统分区][9] 的布局,在网络引导时需要去配置它们。
|
||||
|
||||
> 注意:如果你想实现一个完全的无盘系统,你也可以复制那个文件到一个 TFTP 服务器,然后从 DHCP 上引用那台服务器。
|
||||
|
||||
为了使用 QEMU 去测试我们的引导加载器,我们继续去创建一个仅包含一个 EFI 系统分区和我们的启动文件的、很小的磁盘镜像。
|
||||
|
||||
从创建 EFI 系统分区所需要的目录布局开始,然后把我们在前面节中创建的引导加载器复制进去:
|
||||
|
||||
```livescript
|
||||
$ mkdir -p $HOME/esp/efi/boot
|
||||
$ mkdir $HOME/esp/linux
|
||||
$ cp $IPXE_FILE $HOME/esp/efi/boot/bootx64.efi
|
||||
```
|
||||
|
||||
下面的命令将识别我们的引导加载器镜像正在使用的内核版本,并将它保存到一个变量中,以备后续的配置命令去使用它:
|
||||
|
||||
```livescript
|
||||
$ DEFAULT_VER=$(ls -c /fc28/lib/modules | head -n 1)
|
||||
```
|
||||
|
||||
定义我们的客户端计算机将使用的引导配置:
|
||||
|
||||
```livescript
|
||||
$ MY_DNS1=192.0.2.91
|
||||
$ MY_DNS2=192.0.2.92
|
||||
$ MY_NFS4=server-01.example.edu
|
||||
$ cat << END > $HOME/esp/linux/boot.cfg
|
||||
#!ipxe
|
||||
|
||||
kernel --name kernel.efi \${prefix}/vmlinuz-$DEFAULT_VER initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=$MY_DNS1 nameserver=$MY_DNS2 root=nfs4:$MY_NFS4:/fc28 console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
|
||||
initrd --name initrd.img \${prefix}/initramfs-$DEFAULT_VER.img
|
||||
boot || exit
|
||||
END
|
||||
```
|
||||
|
||||
> 注意:上面的引导脚本展示了如何使用 iPXE 去网络引导 Linux 的最小示例。还可以做更多更复杂的配置。值得注意的是,iPXE 支持交互式引导菜单,它可以让你配置默认选项和超时时间。比如,一个更高级一点 iPXE 脚本可以默认从本地磁盘引导一个操作系统,如果在倒计时结束之前用户按下了一个键,才会去网络引导一个操作系统。
|
||||
|
||||
复制 Linux 内核并分配 initramfs 给 EFI 系统分区:
|
||||
|
||||
```livescript
|
||||
$ cp $(find /fc28/lib/modules -maxdepth 2 -name 'vmlinuz' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/vmlinuz-$DEFAULT_VER
|
||||
$ cp $(find /fc28/boot -name 'init*' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/initramfs-$DEFAULT_VER.img
|
||||
```
|
||||
|
||||
我们最终的目录布局应该看起来像下面的样子:
|
||||
|
||||
```livescript
|
||||
esp
|
||||
├── efi
|
||||
│ └── boot
|
||||
│ └── bootx64.efi
|
||||
└── linux
|
||||
├── boot.cfg
|
||||
├── initramfs-4.18.18-200.fc28.x86_64.img
|
||||
└── vmlinuz-4.18.18-200.fc28.x86_64
|
||||
```
|
||||
|
||||
使用 QEMU 去使用我们的 EFI 系统分区,我们需要去创建一个小的 “uefi.img” 磁盘镜像来包含它,然后将它连接到 QEMU 作为主引导驱动器。
|
||||
|
||||
开始安装必需的工具:
|
||||
|
||||
```livescript
|
||||
$ dnf install -y parted dosfstools
|
||||
```
|
||||
|
||||
现在创建 “uefi.img” 文件,并将 “esp” 目录中文件复制进去:
|
||||
|
||||
```livescript
|
||||
$ ESP_SIZE=$(du -ks $HOME/esp | cut -f 1)
|
||||
$ dd if=/dev/zero of=$HOME/uefi.img count=$((${ESP_SIZE}+5000)) bs=1KiB
|
||||
$ UEFI_DEV=$(losetup --show -f $HOME/uefi.img)
|
||||
$ parted ${UEFI_DEV} -s mklabel gpt mkpart EFI FAT16 1MiB 100% toggle 1 boot
|
||||
$ mkfs -t msdos ${UEFI_DEV}p1
|
||||
$ mkdir -p $HOME/mnt
|
||||
$ mount ${UEFI_DEV}p1 $HOME/mnt
|
||||
$ cp -r $HOME/esp/* $HOME/mnt
|
||||
$ umount $HOME/mnt
|
||||
$ losetup -d ${UEFI_DEV}
|
||||
```
|
||||
|
||||
> 注意:在物理计算机上,你只需要从 “esp” 目录中复制文件到计算机上已存在的 EFI 系统分区中。你不需要使用 “uefi.img” 文件去引导物理计算机。
|
||||
>
|
||||
> 注意:在一个物理计算机上,如果文件名已存在,你可以重命名 “bootx64.efi” 文件,如果你重命名了它,就需要去编辑计算机的 BIOS 设置,并添加重命令后的 efi 文件到引导列表中。
|
||||
|
||||
接下来我们需要去安装 qemu 包:
|
||||
|
||||
```livescript
|
||||
$ dnf install -y qemu-system-x86
|
||||
```
|
||||
|
||||
允许 QEMU 访问我们在本教程“初始化配置”一节中创建的网桥:
|
||||
|
||||
```livescript
|
||||
$ echo 'allow br0' > /etc/qemu/bridge.conf
|
||||
```
|
||||
|
||||
创建一个 “OVMF_VARS.fd” 镜像的副本去保存我们虚拟机的持久 BIOS 配置:
|
||||
|
||||
```livescript
|
||||
$ cp /usr/share/edk2/ovmf/OVMF_VARS.fd $HOME
|
||||
```
|
||||
|
||||
现在,启动虚拟机:
|
||||
|
||||
```livescript
|
||||
$ qemu-system-x86_64 -machine accel=kvm -nographic -m 1024 -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/ovmf/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=$HOME/OVMF_VARS.fd -drive if=ide,format=raw,file=$HOME/uefi.img -net bridge,br=br0 -net nic,model=virtio
|
||||
```
|
||||
|
||||
如果一切顺利,你将看到类似下图所示的结果:
|
||||
|
||||
![][10]
|
||||
你可以使用 “shutdown” 命令关闭虚拟机回到我们的服务器上:
|
||||
|
||||
```livescript
|
||||
$ sudo shutdown -h now
|
||||
```
|
||||
|
||||
> 注意:如果出现了错误或虚拟机挂住了,你可能需要启动一个新的 SSH 会话去连接服务器,使用 “kill” 命令去终止 “qemu-system-x86_64” 进程。
|
||||
|
||||
### 镜像中添加包
|
||||
|
||||
镜像中添加包应该是一个很简单的问题,在服务器上 chroot 进镜像,然后运行 “dnf install <package_name>”。
|
||||
|
||||
在网络引导镜像中并不限制你能安装什么包。一个完整的图形化安装应该能够完美地工作。
|
||||
|
||||
下面是一个如何将最小化安装的网络引导镜像变成完整的图形化安装的示例:
|
||||
|
||||
```livescript
|
||||
$ for i in dev dev/pts dev/shm proc sys run; do mount -o bind /$i /fc28/$i; done
|
||||
$ chroot /fc28 /usr/bin/bash --login
|
||||
$ dnf -y groupinstall "Fedora Workstation"
|
||||
$ dnf -y remove gnome-initial-setup
|
||||
$ systemctl disable sshd.service
|
||||
$ systemctl enable gdm.service
|
||||
$ systemctl set-default graphical.target
|
||||
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
|
||||
$ logout
|
||||
$ for i in run sys proc dev/shm dev/pts dev; do umount /fc28/$i; done
|
||||
```
|
||||
|
||||
可选,你可能希望去启用 “liveuser” 用户的自动登陆:
|
||||
|
||||
```livescript
|
||||
$ sed -i '/daemon/a AutomaticLoginEnable=true' /fc28/etc/gdm/custom.conf
|
||||
$ sed -i '/daemon/a AutomaticLogin=liveuser' /fc28/etc/gdm/custom.conf
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/
|
||||
|
||||
作者:[Gregory Bartholomew][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/glb/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Network_booting
|
||||
[2]: https://dl.fedoraproject.org/pub/fedora/linux/releases/28/Server/x86_64/iso/
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2018/11/installation-summary-1024x768.png
|
||||
[4]: https://docs.fedoraproject.org/en-US/Fedora/25/html/Networking_Guide/ch-Configure_Host_Names.html#sec_Understanding_Host_Names
|
||||
[5]: https://en.wikipedia.org/wiki/Bridging_(networking)
|
||||
[6]: https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s3-nfs-server-config-exportfs-nfsv4.html
|
||||
[7]: https://bugzilla.redhat.com/show_bug.cgi?id=1542567
|
||||
[8]: https://ipxe.org/
|
||||
[9]: https://en.wikipedia.org/wiki/EFI_system_partition
|
||||
[10]: https://fedoramagazine.org/wp-content/uploads/2018/11/netboot-liveuser-1024x641.png
|
Loading…
Reference in New Issue
Block a user