分类 技术 下的文章

你不需要知道如何写或读代码就可以编译它。

 title=

安装软件的方法有很多,但开源让你有了一个其他地方所没有的选择:你可以自己编译代码。编译源代码的经典三步流程是:

$ ./configure
$ make
$ sudo make install

由于有了这些命令,你可能会惊讶地发现,你不需要知道如何写代码,甚至不需要读代码就可以编译它。

安装用来构建软件的命令

由于这是你第一次进行编译,所以有一个一次性的准备步骤,即安装用于构建软件的命令。具体来说,你需要一个编译器。编译器(比如 GCC 或 LLVM)可以将像这样的源代码:

#include <iostream>

using namespace std;

int main() {
  cout << "hello world";
}

变成 机器语言,即 CPU 用来处理信息的指令。你可以看一下机器代码,但它对你来说没有任何意义(除非你是一个 CPU)。

你可以使用你的软件包管理器安装 GNU 编译器集合(GCC)和 LLVM 编译器,以及其他在 Fedora、CentOS、Mageia 和类似发行版上进行编译的基本命令:

$ sudo dnf install @development clang

在 Debian、Elementary、Mint 和类似发行版上命令如下:

$ sudo apt install build-essential clang

在你的系统设置好后,有几项你每次编译软件时都要重复进行的任务:

  1. 下载源代码
  2. 展开源代码的存档文件
  3. 编译

你已经有了所有你需要的命令,所以现在你需要一些软件来编译。

1、下载源代码

获得一个应用程序的源代码和获得任何可下载的软件一样。你得去一个网站或一个代码管理网站,如 GitLab、SourceForge 或 GitHub。 通常情况下,开源软件既有正在进行的工作(“ 当前 current ”或 “ 每夜 nightly ”)的构建版本,也有打包的“ 稳定 stable ”发布版本。在可能的情况下,使用稳定版本,除非你有理由相信,或者对代码有足够的了解,能够在出现故障时修复。术语“稳定版”表明这些代码经过了测试,而且该应用程序的程序员对代码有足够的信心,从而将其打包成 .zip.tar 归档,给了它一个官方编号,有时还有一个发布名称,然后提供给一般的非程序员公众下载。

在这个练习中,我使用 Angband,一个开源的(GPLv2)ASCII 地牢猎手游戏。这是一个简单的应用程序,其复杂程度刚好可以说明你在自己编译软件时需要考虑的问题。

网站 上下载其源代码。

2、展开源代码的存档文件

源代码通常是以存档的形式交付的,因为源代码通常由多个文件组成的。在与之交互之前,你必须先解压,不管它是一个 tarball、一个 zip 文件、一个 7z 文件,还是其他完全不同的东西。

$ tar --extract --file Angband-x.y.z.tar.gz

一旦解压缩后,就把目录切换到解压缩的目录,然后看一看。通常在目录的顶层有一个 README 文件。这个文件,一般会包含你需要做什么来编译代码的指导。README 通常包含关于代码的这些重要方面的信息:

  • 语言:代码使用的是什么语言(例如,C、C++、Rust、Python)。
  • 依赖性:你需要在你的系统上安装其他什么的软件,以便这个应用程序能够构建和运行。
  • 说明:你构建该软件所需要采取的明确步骤。偶尔,他们会在一个专门的文件中包含这些信息,这个文件被直观地称为 INSTALL

如果 README 文件中不包含这些信息,可以考虑向开发者提交一份错误报告。你不是唯一需要介绍一下源代码的人。不管他们有多么丰富的经验,每个人都会对从未见过的源代码感到陌生,而文档是很重要的!

Angband 的维护者给出了在线说明的链接,描述了如何编译代码。这份文件还描述了你需要安装哪些其他软件,尽管它并没有确切地说明这一点。该网站说,“有几个不同的可选构建的前端(GCU、SDL、SDL2 和 X11),你可以使用诸如 --enable-sdl--disable-x11 的参数配置。”这可能对你来说看起来像天书,但你经常编译代码后就会习惯。无论你是否理解 X11 或 SDL2 是什么,它们都是你经过几个月定期编译代码后经常看到的要求。你会对大多数软件需要其他软件库的想法感到适应,因为它们建立在其他技术之上。不过在这种情况下,Angband 非常灵活,无论是否有这些可选的依赖,都可以进行编译,所以现在,你可以假装没有额外的依赖。

3、编译代码

构建代码的典型步骤是:

$ ./configure
$ make
$ sudo make install

这些是使用 Autotools 构建的项目的步骤,该框架是为了规范源代码的交付方式而创建的。然而,还有一些其他框架(如 Cmake),它们需要不同的步骤。当项目没有遵循 Autotools 或 Cmake 框架时,它们往往会在 README 文件中提醒你。

配置

Angband 使用 Autotools,所以现在是编译代码的时候了!

在 Angband 目录中,首先,运行随源码一起提供的配置脚本:

$ ./configure

这一步将扫描你的系统,找到 Angband 正确构建所需的依赖性。有些依赖是非常基本的,没有它们你的电脑就无法运行,而有些则是专门的。在这一过程结束时,该脚本会给你一份关于它所发现的东西的报告:

[...]
configure: creating ./config.status
config.status: creating mk/buildsys.mk
config.status: creating mk/extra.mk
config.status: creating src/autoconf.h

Configuration:

  Install path:    /usr/local
  binary path:     /usr/local/games
  config path:     /usr/local/etc/angband/
  lib path:        /usr/local/share/angband/
  doc path:        /usr/local/share/doc/angband/
  var path:        (not used)
  (save and score files in ~/.angband/Angband/)

-- Frontends --
- Curses            Yes
- X11               Yes
- SDL2              Disabled
- SDL               Disabled
- Windows           Disabled
- Test              No
- Stats             No
- Spoilers          Yes

- SDL2 sound        Disabled
- SDL sound         Disabled

有些输出可能对你有意义,有些可能没有。无论如何,你可能注意到 SDL2 和 SDL 被标记为 “Disabled”,Test 和 Stats 都被标记为 “None”。虽然这些信息是负面的,但这并不一定是一件坏事。从本质上讲,这就是警告错误之间的区别。如果配置脚本遇到了会阻止它构建代码的东西,它就会用一个错误来提醒你。

如果你想稍微优化一下你的构建,你可以选择解决这些负面信息。通过搜索 Angband 文档,你可能会确定 Test 和 Stats 实际上并不是你感兴趣的(它们是 Angband 专用于开发者的选项)。然而,通过在线研究,你可能会发现 SDL2 将是一个很好的功能。

要解决编译代码时的依赖问题,你需要安装缺少的组件和该缺少的组件的 开发库。换句话说,Angband 需要 SDL2 来播放声音,但它需要 SDL2-devel(在 Debian 系统上称为 libsdl2-dev)来构建。用你的软件包管理器安装这两个组件:

$ sudo dnf install sdl2 sdl2-devel

再试一下配置脚本:

$ ./configure --enable-sdl2
[...]
Configuration:
[...]
- Curses                                  Yes
- X11                                     Yes
- SDL2                                    Yes
- SDL                                     Disabled
- Windows                                 Disabled
- Test                                    No
- Stats                                   No
- Spoilers                                Yes

- SDL sound                               Disabled
- SDL2 sound                              Yes

制作(编译)

一旦一切配置完毕,运行 make 命令:

$ make

这通常需要一段时间,但它提供了很多视觉反馈,所以你会知道代码正在被编译。

安装

最后一步是安装你刚刚编译的代码。安装代码并没有什么神奇之处。所做的就是复制很多文件到非常具体的目录中。无论你是从源代码编译还是运行花哨的图形安装向导,都是如此。由于这些代码会被复制到系统级目录,你必须有 root(管理)权限,这是由 sudo 命令授予的。

$ sudo make install

运行该应用程序

一旦应用程序被安装,你就可以运行它。根据 Angband 文档,启动游戏的命令是 angband,所以可以试试:

$ angband

 title=

编译代码

无论是在我的 Slackware 台式电脑上,还是在我的 CentOS 笔记本电脑上,我都会使用 NetBSD 的 pkgsrc 系统编译我自己的大部分应用程序。我发现,通过自己编译软件,我可以对应用程序中包含的功能、如何配置、使用的库版本等有自己的想法。这很有意义,它帮助我跟上了新的版本,而且因为我有时会在这个过程中发现错误,它帮助我参与了很多不同的开源项目。

你很少会只有编译软件的一种方式可选,大多数开源项目同时提供源代码(这就是为什么它被称为“开源”)和可安装包。是否从源代码编译是你自己的选择,也许是因为你想要最新版本中还没有的新功能,或者只是因为你喜欢自己编译代码。

家庭作业

Angband 可以使用 Autotools 或 Cmake,所以如果你想体验另一种构建代码的方式,可以试试这个:

$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install

你也可以尝试用 LLVM 编译器而不是 GNU 编译器集合(GCC)进行编译。现在,我把这个问题留给你自己去研究(提示:尝试设置 CC 环境变量)。

一旦你完成了对 Angband 的源代码和至少几个地牢的探索(你已经赢得了一些休息时间),可以看看其他一些代码库。很多人都会使用 Autotools 或 Cmake,而其他人可能会使用不同的东西。看看你能构建的成果!


via: https://opensource.com/article/21/11/compiling-code

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

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

熟悉 FreeDOS 软件包管理器 FDIMPLES 。

在 Linux 上,你可能已经使用过 “软件包管理器” 来安装或移除软件包。例如,在 Debian Linux 上的默认软件包管理器是 deb 命令,在 Fedora Linux 上的默认软件包管理器是 dnf 命令。 但是你知道 FreeDOS 也有一个软件包管理器吗?

安装软件包

FreeDOS 1.3 RC4 发行版包含了很多极好的你可以使用的程序和应用程序。不过,我们不会默认安装其中的全部的程序 —— 我们不想过度地填充你的硬盘驱动器空间,尤其是在一个较老的系统上,可能仅有几百兆字节容量的硬盘驱动器。当你安装 FreeDOS 时,如果你选择 “Plain DOS system” 选项,你将发现你的 FreeDOS 系统是非常小的(大约 20 MB 大小)。

不过,要安装新的软件包很容易。在命令行中运行 FDIMPLES 程序。因为 DOS 是 不区分大小写 的,所以,你可以使用大写字母或小写字母来输入这个命令: fdimples 。(fdimplesFDIMPLESFDImples 等同)

fdimples

在 FreeDOS 1.3 RC4 上的 FDIMPLES 软件包管理器(运行在 QEMU 之中)(Jim Hall, CC-BY SA 4.0

FDIMPLES 是 "FreeDOS Installer - My Package List Editor Software" 的首字母缩略词,是一个交互式软件包管理器。FDIMPLES 读取安装介质来识别可以安装或移除的软件包。如果你看到一个不同的菜单,它显示 “Installed!” ,但是,不让你安装其它的软件的话,请检查你系统中是否有 FreeDOS 的 CD-ROM 的安装介质。在物理机器上,你将需要将 CD-ROM 插入 CD-ROM 驱动器;在诸如 QEMU 或 VirtualBox 之类的虚拟机器上,你需要将安装 FreeDOS 的 CD-ROM 的安装介质与虚拟机器关联在一起。

fdimples installed

如果你仅看到一条 “Installed!” 的信息,检查 CD-ROM 是否已经加载(Jim Hall, CC-BY SA 4.0

让我们假设你想安装一些可以让你听音乐文件或其它声音文件的软件。使用向上箭头和向下箭头按键来导航到菜单中的 声音工具 项。这是一个针对声音和音乐程序的 软件包组

fdimples sound

在 FDIMPLES 中突出显示声音软件包组(Jim Hall, CC-BY SA 4.0

要选择这个组中的所有软件包,在你的键盘上按下空格键。如果你决定安装这个组中的某个软件包,按下 Tab 按键来移动到 软件包列表 方框面板,接下来使用空格键来选择每个软件包。

fdimples sound select

通过按下空格键来选择一个组中的所有的软件包(Jim Hall, CC-BY SA 4.0

你可以继续选择你想要安装的其它的软件包或软件包组。当你选择好一切的东西后,使用 “Tab” 按键来高亮显示 “OK” 按键,并按下空格键按键。

fdimples sound select ok

当你准备好安装时,突出显示 “Ok” 按钮(Jim Hall, CC-BY SA 4.0

FDIMPLES 接下来会安装你所选择的所有的软件包。如果你仅选择几个小型的软件包,这可能只需要花费片刻的时间,或者,如果你要求安装很多大型的软件包,它可能会花费数分钟的时间。当 FDIMPLES 安装每个软件包时,FDIMPLES 会输出安装状态。在安装完后,FDIMPLES 退出到命令行之中,以便你可以回去继续工作。

fdimples sound install done

当 FDIMPLES 安装软件包时,FDIMPLES 会显示安装过程,并在完成安装后自动地退出(Jim Hall, CC-BY SA 4.0

移除软件包

如果你安装了一个软件包,但是后来发现你不想要它了怎么办?在 FDIMPLES 中移除软件包也同样容易。

就像安装软件包一样,启动 FDIMPLES ,使用箭头键导航到包含你想要移除的软件包的组。例如,如果我想卸载一些我先前安装的音乐播放器软件包,我将导航到 “Sound Tools” 软件包组。

fdimples sound select

导航到你想要移除的软件包组(Jim Hall, CC-BY SA 4.0

为一次移除整个软件包组,你可以在你想要移除的软件包组上按下空格键来取消选择它们。但是,在这里让我们假设我只是想移除几个我不需要的软件包,像音频 CD 播放器 “CDP”。(我没有任何的真实的音乐 CD 光盘)。为移除 CDP ,敲击 Tab 按键来移动到软件包列表方框面板,接下来使用空格键来取消选择 CDP 软件包。这会在该软件包上移除 “X” 标志。

fdimples unselect cdp

取消选择一个软件包来移除它(Jim Hall, CC-BY SA 4.0

你可以继续取消选择你想要移除的其它的软件包或软件包组。当你选择一切的东西后,使用 Tab 按键来突出显示 “OK” 按钮,并按下空格键按键。FDIMPLES 将移除你取消选择的软件包,然后自动地返回到命令行之中。

fdimples cdp removed

FDIMPLES 移除软件包,然后返回到命令行之中(Jim Hall, CC-BY SA 4.0

在 FreeDOS 中。我们包含很多的软件包,遍及各种各样的软件包组。使用 FDIMPLES 来安装你需要的软件。请随意实验!如果你决定你不想要保留一个软件包了,你可以移除它,并为其它的软件包来释放所占用的磁盘空间。


via: https://opensource.com/article/21/6/freedos-package-manager

作者:Jim Hall 选题:lujun9972 译者:robsean 校对:wxy

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

下次当你为控制台输出的格式而苦恼时,请参考这篇文章及其速查表。

我写文章主要是为了给自己写文档。我在编程时非常健忘,所以我经常会写下有用的代码片段、特殊的特性,以及我使用的编程语言中的常见错误。这篇文章完全切合我最初的想法,因为它涵盖了从 C++ 控制台格式化打印时的常见用例。

像往常一样,这篇文章带有大量的例子。除非另有说明,代码片段中显示的所有类型和类都是 std 命名空间的一部分。所以当你阅读这段代码时,你必须在类型和类的前面加上using namespace std;。当然,该示例代码也可以在 GitHub 上找到。

面向对象的流

如果你曾经用过 C++ 编程,你肯定使用过 cout。当你包含 <iostream> 时,ostream 类型的 cout 对象就进入了作用域。这篇文章的重点是 cout,它可以让你打印到控制台,但这里描述的一般格式化对所有 ostream 类型的流对象都有效。ostream 对象是 basic_ostream 的一个实例,其模板参数为 char 类型。头文件 <iosfwd><iostream> 的包含层次结构的一部分,包含了常见类型的前向声明。

basic_ostream 继承于 basic_ios,该类型又继承于 ios_base。在 cppreference.com 上你可以找到一个显示不同类之间关系的类图。

ios_base 类是所有 I/O 流类的基类。basic_ios 类是一个模板类,它对常见的字符类型进行了 模板特化 specialization ,称为 ios。因此,当你在标准 I/O 的上下文中读到 ios 时,它是 basic_ioschar 类型的模板特化。

格式化流

一般来说,基于 ostream 的流有三种格式化的方法。

  1. 使用 ios_base 提供的格式标志。
  2. 在头文件 <iomanip><ios> 中定义的流修改函数。
  3. 通过调用 << 操作符的 特定重载

所有这些方法都有其优点和缺点,通常取决于使用哪种方法的情况。下面显示的例子混合使用所有这些方法。

右对齐

默认情况下,cout 占用的空间与要打印的数据所需的空间一样大。为了使这种右对齐的输出生效,你必须定义一个行允许占用的最大宽度。我使用格式标志来达到这个目的。

右对齐输出的标志和宽度调整只适用于其后的行。

cout.setf(ios::right, ios::adjustfield);
cout.width(50);
cout << "This text is right justified" << endl;
cout << "This text is left justified again" << endl;

在上面的代码中,我使用 setf 配置了右对齐的输出。我建议你将位掩码 ios::adjustfield 应用于 setf,这将使位掩码指定的所有标志在实际的 ios::right 标志被设置之前被重置,以防止发生组合碰撞。

填充空白

当使用右对齐输出时,默认情况下,空的地方会用空白字符填充。你可以通过使用 setfill 指定填充字符来改变它:

cout << right << setfill('.') << setw(30) << 500 << " pcs" << endl;
cout << right << setfill('.') << setw(30) << 3000 << " pcs" << endl;
cout << right << setfill('.') << setw(30) << 24500 << " pcs" << endl;

代码输出如下:

...........................500 pcs
..........................3000 pcs
.........................24500 pcs

组合

想象一下,你的 C++ 程序记录了你的储藏室库存。不时地,你想打印一份当前库存的清单。要做到这一点,你可以使用以下格式。

下面的代码是左对齐和右对齐输出的组合,使用点作为填充字符,可以得到一个漂亮的列表:

cout << left << setfill('.') << setw(20) << "Flour" << right << setfill('.') << setw(20) << 0.7 << " kg" << endl;
cout << left << setfill('.') << setw(20) << "Honey" << right << setfill('.') << setw(20) << 2 << " Glasses" << endl;
cout << left << setfill('.') << setw(20) << "Noodles" << right << setfill('.') << setw(20) << 800 << " g" << endl;
cout << left << setfill('.') << setw(20) << "Beer" << right << setfill('.') << setw(20) << 20 << " Bottles" << endl;

输出:

Flour...............................0.70 kg
Honey..................................2 Glasses
Noodles..............................800 g
Beer..................................20 Bottles

打印数值

当然,基于流的输出也能让你输出各种变量类型。

布尔型

boolalpha 开关可以让你把布尔型的二进制解释转换为字符串:

cout << "Boolean output without using boolalpha: " << true << " / " << false << endl;
cout << "Boolean output using boolalpha: " << boolalpha << true << " / " << false << endl;

以上几行产生的输出结果如下:

Boolean output without using boolalpha: 1 / 0
Boolean output using boolalpha: true / false

地址

如果一个整数的值应该被看作是一个地址,那么只需要把它投到 void* 就可以了,以便调用正确的重载。下面是一个例子:

unsigned long someAddress = 0x0000ABCD;
cout << "Treat as unsigned long: " << someAddress << endl;
cout << "Treat as address: " << (void*)someAddress << endl;

该代码产生了以下输出:

Treat as unsigned long: 43981
Treat as address: 0000ABCD

该代码打印出了具有正确长度的地址。一个 32 位的可执行文件产生了上述输出。

整数

打印整数是很简单的。为了演示,我使用 setfsetiosflags 来指定数字的基数。应用流修改器 hex/oct 也有同样的效果。

int myInt = 123;

cout << "Decimal: " << myInt << endl;

cout.setf(ios::hex, ios::basefield);
cout << "Hexadecimal: " << myInt << endl;

cout << "Octal: " << resetiosflags(ios::basefield) <<  setiosflags(ios::oct) << myInt << endl;

注意: 默认情况下,没有指示所使用的基数,但你可以使用 showbase 添加一个。

Decimal: 123
Hexadecimal: 7b
Octal: 173

用零填充

0000003
0000035
0000357
0003579

你可以通过指定宽度和填充字符得到类似上述的输出:

cout << setfill('0') << setw(7) << 3 << endl;
cout << setfill('0') << setw(7) << 35 << endl;
cout << setfill('0') << setw(7) << 357 << endl;
cout << setfill('0') << setw(7) << 3579 << endl;

浮点值

如果我想打印浮点数值,我可以选择“固定”和“科学”格式。此外,我还可以指定精度:

double myFloat = 1234.123456789012345;
int defaultPrecision = cout.precision(); // == 2

cout << "Default precision: " << myFloat << endl;
cout.precision(4);
cout << "Modified precision: " << myFloat << endl;
cout.setf(ios::scientific, ios::floatfield);
cout << "Modified precision & scientific format: " << myFloat << endl;
/* back to default */
cout.precision(defaultPrecision);
cout.setf(ios::fixed, ios::floatfield);
cout << "Default precision & fixed format:  " << myFloat << endl;

上面的代码产生以下输出:

Default precision: 1234.12
Modified precision: 1234.1235
Modified precision & scientific format: 1.2341e+03
Default precision & fixed format:  1234.12

时间和金钱

通过 put_money,你可以用正确的、与当地有关的格式来打印货币单位。这需要你的控制台能够输出 UTF-8 字符集。请注意,变量 specialOffering 以美分为单位存储货币价值。

long double specialOffering = 9995;

cout.imbue(locale("en_US.UTF-8"));
cout << showbase << put_money(specialOffering) << endl;
cout.imbue(locale("de_DE.UTF-8"));
cout << showbase << put_money(specialOffering) << endl;
cout.imbue(locale("ru_RU.UTF-8"));
cout  << showbase << put_money(specialOffering) << endl;

iosimbue 方法让你指定一个地区。通过命令 locale -a,你可以得到你系统中所有可用的地区标识符的列表。

$99.95
99,950€
99,950₽

(不知道出于什么原因,在我的系统上,它打印的欧元和卢布有三个小数位,对我来说看起来很奇怪,但这也许是官方的格式。)

同样的原则也适用于时间输出。函数 put_time 可以让你以相应的地区格式打印时间。此外,你可以指定时间对象的哪些部分被打印出来。

time_t now = time(nullptr);
tm localtm = *localtime(&now);


cout.imbue(locale("en_US.UTF-8"));
cout << "en_US : " << put_time(&localtm, "%c") << endl;
cout.imbue(locale("de_DE.UTF-8"));
cout << "de_DE : " << put_time(&localtm, "%c") << endl;
cout.imbue(locale("ru_RU.UTF-8"));
cout << "ru_RU : " << put_time(&localtm, "%c") << endl;

格式指定符 %c 会打印一个标准的日期和时间字符串:

en_US : Tue 02 Nov 2021 07:36:36 AM CET
de_DE : Di 02 Nov 2021 07:36:36 CET
ru_RU : Вт 02 ноя 2021 07:36:36

创建自定义的流修改器

你也可以创建你自己的流。下面的代码在应用于 ostream 对象时插入了一个预定义的字符串:

ostream& myManipulator(ostream& os) {
    string myStr = ">>>Here I am<<<";
    os << myStr;
    return os;
}

另一个例子: 如果你有重要的事情要说,就像互联网上的大多数人一样,你可以使用下面的代码在你的信息后面根据重要程度插入感叹号。重要程度被作为一个参数传递:

struct T_Importance {
     int levelOfSignificance;
};

T_Importance importance(int lvl){
    T_Importance x = {.levelOfSignificance = lvl };
    return x;
}

ostream& operator<<(ostream& __os, T_Importance t){

    for(int i = 0; i < t.levelOfSignificance; ++i){
        __os.put('!');
    }
    return __os;
}

这两个修饰符现在都可以简单地传递给 cout

cout << "My custom manipulator: " << myManipulator << endl;

cout << "I have something important to say" << importance(5) << endl;

产生以下输出:

My custom manipulator: >>>Here I am<<<

I have something important to say!!!!!

结语

下次你再纠结于控制台输出格式时,我希望你记得这篇文章及其 速查表

在 C++ 应用程序中,coutprintf 的新邻居。虽然使用 printf 仍然有效,但我可能总是喜欢使用 cout。特别是与定义在 <ios> 中的修改函数相结合,会产生漂亮的、可读的代码。


via: https://opensource.com/article/21/11/c-stdcout-cheat-sheet

作者:Stephan Avenwedde 选题:lujun9972 译者:wxy 校对:wxy

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

这里是如何在不使用安装程序的情况下来手动设置你的 FreeDOS 系统。

 title=

大多数的人应该能够使用安装程序来非常容易地安装 FreeDOS 1.3 RC4 。FreeDOS 安装程序会先询问几个问题,然后处理剩余的工作,包括为 FreeDOS 制作安装空间和使系统可启动。

但是,如果安装程序不适合你怎么办?或者,你更喜欢 手动 设置你的 FreeDOS 系统,而不喜欢使用安装程序怎么办?使用 FreeDOS ,你也可以做到这些!让我们在不使用安装程序的情况下逐步走完安装 FreeDOS 的步骤。我将使用 QEMU 虚拟机的一个空白的硬盘驱动器镜像来完成所有的步骤。我使用这个 Linux 命令来创建了一个 100 MB 的硬盘驱动器镜像:

$ qemu-img create freedos.img 100M

我下载了 FreeDOS 1.3 RC4 的 LiveCD ,并将其命名为 FD13LIVE.iso ,它提供了一个 “身临其境” 的环境,我可以在其中运行 FreeDOS ,包括所有的标准工具。大多数用户也使用 LiveCD 自带的常规安装程序来安装 FreeDOS 。但是,在这里我将仅使用 LiveCD ,并从其命令行中使用某些类型的命令来安装 FreeDOS 。

我使用这个相当长的 QEMU 命令来启动虚拟机,并选择 “Use FreeDOS 1.3 in Live Environment mode” 启动菜单项:

$ qemu-system-x86_64 -name FreeDOS -machine pc-i440fx-4.2,accel=kvm,usb=off,dump-guest-core=off -enable-kvm -cpu host -m 8 -overcommit mem-lock=off -no-user-config -nodefaults -rtc base=utc,driftfix=slew -no-hpet -boot menu=on,strict=on -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on -hda freedos.img -cdrom FD13LIVE.iso -device sb16 -device adlib -soundhw pcspk -vga cirrus -display sdl -usbdevice mouse

 title=

选择 "Use FreeDOS 1.3 in Live Environment mode" 来启动 LiveCD(Jim Hall, CC-BY SA 4.0

这个 QEMU 命令行包含大量的选项,乍看可能会让你迷糊。因为你完全使用命令行选项配置 QEMU ,所以在这里有很多东西需要审查。但是,我将简单地重点说明几个重要的选项:

  • -m 8:设置系统存储器(RAM)为 8 MB
  • -boot menu=on,strict=on:使用一个启动菜单,这样,我可以选择从 CD-ROM 镜像或硬盘驱动器镜像启动
  • -hda freedos.img:使用 freedos.img 作为硬盘驱动器镜像
  • -cdrom FD13LIVE.iso:使用 FD13LIVE.iso 作为 CD-ROM 镜像
  • -device sb16 -device adlib -soundhw pcspk:定义计算机带有一个 SoundBlaster16 声卡、AdLib 数字音乐卡、PC 扬声器模拟器(如果你想玩 DOS 游戏的话,这些模拟器很有用)
  • -usbdevice mouse:将用户的鼠标识别为一个 USB 鼠标(在 QEMU 窗口中单击以使用鼠标)

对硬盘驱动器进行分区

你可以从 LiveCD 使用 FreeDOS 1.3 RC4 ,但是,如果你想安装 FreeDOS 到你的计算机中,你需要先在硬盘驱动器上制作安装空间。这需要使用 FDISK 程序来创建一个 分区

从 DOS 命令行中,输入 FDISK 来运行 分区 设置程序。FDISK 是一个全屏交互式程序,你只需要输入数字来选择菜单项。从 FDISK 的主菜单中,输入 1 来在驱动器上创建一个 DOS 分区,然后在接下来的屏幕上输入 1 来创建一个 “主” DOS 分区。

 title=

选择 1 来创建一个分区(Jim Hall, CC-BY SA 4.0

 title=

在接下来的菜单上选择 1 来制作一个主分区(Jim Hall, CC-BY SA 4.0

FDISK 会询问你是否想要使用全部的硬盘空间大小来创建分区。除非你需要在这个硬盘驱动器上和另外一个操作系统(例如 Linux)共享硬盘空间,否则,对于这个提示,你应该回答 Y

FDISK 创建新的分区后,在 DOS 能够识别新的分区信息前,你将需要重新启动 DOS 。像所有的 DOS 操作系统一样,FreeDOS 仅在其启动时识别硬盘驱动器信息。因此,如果你创建或删除任何的磁盘分区的话,你都将需要重新启动 FreeDOS ,只有这样做,FreeDOS 才能识别到更改的分区信息。FDISK 会提醒你重新启动,因此,你是不会忘记的。

 title=

你需要重新启动以识别新的分区(Jim Hall, CC-BY SA 4.0

你可以通过停止或重新启动 QEMU 虚拟机来重新启动 FreeDOS,但是我更喜欢在 FreeDOS 命令行中使用 FreeDOS 的高级电源管理(FDADPM)工具来重新启动 FreeDOS 。为了重新启动,输入命令 FDADPM /WARMBOOT ,FreeDOS 将自动重新启动。

对硬盘驱动器进行格式化

在 FreeDOS 重新启动后,你可以继续设置硬盘驱动器。创建磁盘分区是这个过程的“第一步”;现在你需要在分区上创建一个 DOS 文件系统 ,以便 FreeDOS 可以使用它。

DOS 系统使用字母 AZ 来识别“驱动器”。FreeDOS 将识别第一个硬盘驱动器的第一个分区为 C 驱动器,依此论推。你经常使用字母和一个冒号(:)来表示驱动器,因此我们在上面创建的新分区实际上是 C: 驱动器。

你可以在新的分区上使用 FORMAT 命令来创建一个 DOS 文件系统。这个命令带有一些选项,但是,我们将仅使用 /S 选项来告诉 FORMAT 来使新的文件系统可启动: S 意味着安装 FreeDOS “系统” 文件。输入 FORMAT /S C: 来在 C: 驱动器上制作一个新的 DOS 文件系统。

 title=

格式化分区来创建 DOS 文件系统(Jim Hall, CC-BY SA 4.0

使用 /S 选项,FORMAT 将运行 SYS 程序来传输系统文件。你将看到这是从 FORMAT 输出的一部分:

 title=

FORMAT /S 将使用 SYS 来使磁盘可启动(Jim Hall, CC-BY SA 4.0

安装软件

在使用 FDISK 创建了一个新的分区,并使用 FORMAT 创建了一个新的文件系统后, 新的 C: 驱动器基本上是空的。此时,C: 驱动器仅包含一份内核和 COMMAND.COM 命令行 shell 的副本。为使新的磁盘可以执行一些有用的操作,我们需要在其上安装软件。这是手动安装过程的最后步骤。

FreeDOS 1.3 RC4 LiveCD 包含所有的你可能希望在新的系统上所要安装的软件。每个 FreeDOS 程序都是一个单独的 “软件包” ,它实际上只是一个 Zip 档案文件。建立标准 DOS 环境的软件包存储在 LiveCD 上 PACKAGES 目录下的 BASE 目录之中。

你可以一次一个的将其中的每一个软件包都 “解压缩” 到硬盘驱动器来完成安装。在 Base 组中有 62 个单独的软件包,如果每次安装一个软件包,这可能会花费非常多的时间。不过,你可以运行一个只有一行的 FOR “循环” 命令来 UNZIP 每个程序。接下来 FreeDOS 可以为你 “解压缩” 所有的软件包。

FOR 循环的基本用法中提及的一个单个字母变量(让我们使用 %F),稍后,FreeDOS 将使用该字母变量来 “填充” 文件名称。FOR 还需要括号中的一个文件列表,这个命令会对每个文件都运行一次。用来解压一系列的 Zip 文件的语法看起来像这样:

FOR %F IN (*.ZIP) DO UNZIP %F

这将提取所有的 Zip 文件到当前目录之中。为提取或 UNZIP 文件到一个不同的位置,在 UNZIP 命令行结尾处使用 -d (“目的地”) 选项。对于大多数的 FreeDOS 系统来说,你应该安装软件包到 C:\FDOS 目录中:

 title=

解压缩所有的基本软件包来完成安装 FreeDOS(Jim Hall, CC-BY SA 4.0

FreeDOS 会处理剩余的工作,安装所有的 62 个软件包到你的系统之中。这可能会花费几分钟的时间,因为 DOS 在处理很多单个的文件时会很慢,这个命令需要提取 62 个 Zip 文件。如果我们使用单个的 BASE.ZIP 档案文件的话,安装过程可能会运行地更快,但是使用软件包的话,在你选择想要安装或不安装软件包时会提供更多的灵活性。

 title=

在安装所有的基本软件包后(Jim Hall, CC-BY SA 4.0

在我们安装完所有的东西后,使用 FDADPM /WARMBOOT 来重新启动你的系统。手动安装意味着你的新 FreeDOS 系统没有常见的 FDCONFIG.SYS 配置文件,因此,当 FreeDOS 在启动时,它将假设一些典型的默认值。因为没有 AUTOXEC.BAT 文件,FreeDOS 也会提示你时间和日期。

 title=

在手动安装后,重新启动 FreeDOS(Jim Hall, CC-BY SA 4.0

大多数的用户应该能够使用比较用户友好的过程来在一台新的计算机上安装 FreeDOS 。但是如果你想自己使用“古老的”方法来安装它,那么你可以手动运行安装步骤。这会提供一些额外的灵活性和控制权,因为是你自己安装的一切。现在你知道如何安装它了。


via: https://opensource.com/article/21/6/install-freedos-without-installer

作者:Jim Hall 选题:lujun9972 译者:robsean 校对:wxy

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

想试一个只是好玩的应用吗?试试 cowsay。

 title=

大多数时候,终端是一个生产力的动力源。但是,终端的作用不止是命令和配置。在所有杰出的开源软件中,有些是 为了好玩而写的。我以前介绍过一些 有趣的命令,但这篇文章只讲一个:古老的 cowsay 命令。

cowsay 是一只可配置的会说话(或思考)的牛。它接受一个文本字符串,并输出一个牛说话的图形。下面是一头牛在说它喜欢 Linux:

< I love Linux >
--------------
       \   ^__^
        \  (oo)\_______
           (__)\       )\/\
               ||----w |
               ||     ||

要得到这个结果,我只需输入:

$ cowsay "I love Linux"

在 Linux 上安装 cowsay

你可以用你的包管理器安装 cowsay。在 Debian、Mint、Elementary 和类似的发行版上:

$ sudo apt install cowsay

在 Fedora 上:

$ sudo apt install cowsay-beefymiracle

Cowsay 命令选项

cowsay 是一个简单又有点傻的应用。除了为你的终端机提供一些不同样式外,它并没有什么实际用途。例如,与其让一头普通的牛说一个有趣短语,你可以让一头长着古怪眼睛的牛说一个有趣的短语。输入:

$ cowsay -e @@ Hello

你会看到:

< Hello >
 -------
       \   ^__^
        \  (@@)\_______
           (__)\       )\/\
               ||----w |
               ||     ||

或者你可以让它伸出舌头。输入:

$ cowsay -T U Hello

你会看到:

< Hello >
-------
       \   ^__^
        \  (oo)\_______
           (__)\       )\/\
            U ||----w |
               ||     ||

更好的是,你可以将 fortune 命令与 cowsay 结合起来:

$ fortune | cowsay

现在你有了一头特别睿智的牛:

 _______________________________________
/ we:                                   \
|                                       |
| The single most important word in the |
\ world.                                /
 ---------------------------------------
       \   ^__^
        \  (oo)\_______
           (__)\       )\/\
               ||----w |
               ||     ||

“结实的奇迹”

在 Fedora 上,有一个额外的 cowsay 选项,也是一个非官方的项目吉祥物。多年来,Fedora 安装程序一直在展示宣传开源贡献的幻灯片。因为它们是根据汽车电影院的插曲设计的,所以幻灯片中常见的卡通人物是拟人化的热狗。

为了与这个主题保持一致,你可以用 Fedora 版本的 cowsay 调用一个所谓的“ 结实的奇迹 beefy miracle ”。(LCTT 译注:Fedora 17 的开发代号。)

$ cowsay -f beefymiracle Hello Fedora

你会得到一个非常傻的输出:

< Hello Fedora >
 --------------      .---. __
          ,    \    /     \   \    ||||
         \\\\      |O___O |    | \\||||
         \   //    | \_/  |    |  \   /
          '--/----/|     /     |   |-'
                 // //  /     -----'
                //  \\ /      /
               //  // /      /
              //  \\ /      /
             //  // /      /
            /|   ' /      /
            //\___/      /
           //   ||\     /
           \\_  || '---'
           /' /  \\_.-
          /  /    --| |
          '-'      |  |
                    '-'

图形化的 cowsay

如果你发现自己需要用图形化的牛来传递信息,可以使用 xcowsay 命令。这是一个类似于 cowsay 的图形程序,它接受一个由用户输入的文本字符串,或从另一个应用(如 Fortune)输送过来的文本字符串。

 title=

有趣的 Linux 命令

虽然 cowsay 不是一个有用的命令,但它是一个有趣的命令,相当于你终端的桌面小工具。它很适合用来分散注意力和进行有趣的管道命令实验(尝试将 ifconfig 管道到 cowsay,或 lsblkmount,或任何东西!)。如果你想让你的终端更有趣,试试 cowsay


via: https://opensource.com/article/21/11/linux-cowsay-command

作者:Don Watkins 选题:lujun9972 译者:geekpi 校对:wxy

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

复制控制器负责管理吊舱的生命周期并确保在任何时候运行着所需的指定数量的吊舱。

 title=

你有没有想过,谁负责监督和管理 Kubernetes 集群内运行的“ 吊舱 pod ”的确切数量?Kubernetes 可以通过多种方式做到这一点,但一个常见的方法是使用 “ 复制控制器 ReplicationController (RC)”。RC 负责管理吊舱的生命周期,并确保在任何时候运行着所需的指定数量的吊舱。但另一方面,它不负责高级的集群能力,如执行自动扩展、准备度和活跃探测以及其他高级的复制能力。Kubernetes 集群中的其他组件可以更好地执行这些功能。

简而言之,RC 的职责有限,通常用于不需要复杂逻辑就能达到某些要求的具体实现(例如,确保所需的吊舱数量总是与指定的数量相符)。如果超过了所需的数量,RC 会删除多余的,并确保即使在节点故障或吊舱终止的情况下,也有相同数量的存在。

简单的事情不需要复杂的解决方案,对我来说,这就是 RC 如何被使用的一个完美的比喻。

如何创建一个 RC

像大多数 Kubernetes 资源一样,你可以使用 YAML 或 JSON 格式创建一个 RC,然后将其发布到 Kubernetes API 端点。

$ kubectl create -f rcexample.yaml
 replicationcontroller/rcexample created

现在,我将深入一下 rcexample.yaml 的样子。

apiVersion: v1
kind: ReplicationController   →  RC 描述符    
metadata:
 name: rcexample            →  复制控制器名字              
spec:
 replicas: 3                 → 预期的吊舱数量      
 selector:                  → 这个 RC 的吊舱选择器
   app: nginx                        
 template:                  → 用于创建新吊舱的模板    
   metadata:                        
     labels:                        
       app: nginx                    
   spec:                            
     containers:                    
     - name: nginx                  
       image: nginx

进一步解释,这个文件在执行时创建了一个名为 rcexample 的 RC,确保三个名为 nginx 的吊舱实例一直在运行。如果一个或所有的 app=nginx 吊舱没有运行,新的吊舱将根据定义的吊舱模板创建。

一个 RC 有三个部分:

  • 复制品:3
  • 吊舱模板:app=nginx
  • 吊舱选择器:app=nginx

注意,吊舱模板要与吊舱选择器相匹配,以防止 RC 一直创建吊舱。如果你创建的 RC 的吊舱选择器与模板不匹配,Kubernetes API 服务器会给你一个错误。

为了验证 RC rcexample 是否被创建:

$ kubectl get po
NAME     READY   STATUS       RESTARTS  AGE
rcexample-53thy  0/1  Running         0     10s
rcexample-k0xz6  0/1  Running         0     10s
rcexample-q3vkg  0/1  Running         0     10s

要删除 RC:

$ kubectl delete rc rcexample
 replicationcontroller "rcexample" deleted

注意,你可以对 RC 中的服务使用 滚动更新 策略,逐个替换吊舱。

其他复制容器的方法

在 Kubernetes 部署中,有多种方法可以实现容器的复制。Kubernetes 成为容器平台的主要选择的主要原因之一是复制容器以获得可靠性、负载平衡和扩展的原生能力。

我在上面展示了你如何轻松地创建一个 RC,以确保在任何时候都有一定数量的吊舱可用。你可以通过更新副本的数量来手动扩展吊舱。

另一种可能的方法是通过使用 “ 复制集 ReplicaSet (RS)”来达到复制的目的。

(kind: ReplicaSet)

RS 的功能几乎与 RC 相同。主要区别在于,RS 不允许滚动更新策略。

另一种实现复制的方法是通过使用 “ 部署 Deployments ”。

(kind: Deployment)

部署是一种更高级的容器复制方法。从功能上讲,部署提供了相同的功能,但在需要时可以推出和回滚变化。这种功能之所以能够实现,是因为部署有 “ 策略类型 StrategyType ” 规范来用新的吊舱替换旧的吊舱。你可以定义两种类型的部署策略:“ 重新创建 Recreate ” 和 “ 滚动更新 RollingUpdate ”。你可以如下指定部署策略:

StrategyType: RollingUpdate

总结

容器的复制功能是大多数企业考虑采用 Kubernetes 的主要原因之一。复制可以让你达到大多数关键应用程序需要的可靠性和可扩展性,作为生产的最低要求。

了解在 Kubernetes 集群中使用哪些方法来实现复制,对于决定哪种方法最适合你的应用架构考虑非常重要。


via: https://opensource.com/article/21/11/kubernetes-replicationcontroller

作者:Mike Calizo 选题:lujun9972 译者:geekpi 校对:wxy

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