标签 源代码 下的文章

不是所有的程序都可以在官方或者第三方库中找到,因此你不能使用常规的包管理来安装它们。有时你不得不从源代码中手动构建这些程序。就如你已经知道的一样,当你从源代码中安装一个程序的时候,这个软件包所包含的文件将会复制到本地的多个位置,例如 /usr/local/bin/usr/local/etc/。如果从源代码中安装的程序没有内置的卸载程序,当你不再需要这个程序的时候,卸载它就会很麻烦。你可能会花费双倍(甚至更多)的时间找出这些文件然后手动删除它们。我以前一直是这样做的,直到我发现了 GNU Stow。谢天谢地,Stow 有一个很棒的方法可以轻松管理从源代码安装的程序。

引用官方网站里的一段介绍,

GNU Stow 是一个符号链接归集管理器,它可以收集文件系统上不同目录中的不同软件和/或数据包,使它们看起来像是一个整体。

简单来说,Stow 帮助你把这些程序文件以一种容易管理的方式组织在了一起。在这个方法中,文件将不会被复制到多个位置。所有的这些文件都会被保存在一个特定的文件夹中,通常是以程序名命名的,然后 Stow 会在一个合适的位置为所有的程序文件创建符号连接。比如 /usr/local/bin 中会包含 /usr/local/stow/vim/bin/usr/local/stow/python/bin 中文件的符号链接。并且同样递归地用于其他的任何的子目录,例如 .../share.../man,等等。在这篇教程中,我将会举例教你如何轻松地使用 Stow 管理从源中安装的程序。

安装 GNU Stow

GNU Stow 在流行 Linux 操作系统的默认库中都可用。

在 Arch Linux 及它的衍生版本中,运行下面的命令安装 Stow。

$ sudo pacman -S stow

在 Debian、Ubuntu、Linux Mint 上:

$ sudo apt install stow

在 Fedora 上:

$ sudo dnf install stow

在 RHEL/CentOS 上:

$ sudo yum install epel-release
$ sudo yum install stow

在 Linux 上轻松移除从源代码安装的程序

就像我之前提到的,所有包的程序文件都将被保存在位于 /usr/local/stow/ 的一个根文件夹。在这个根文件夹或者父目录之下,每个包都将保存在对应的子目录中。例如,如果我们从源代码中安装了 Vim 编辑器,所有关联到 Vim 的程序文件和目录都将保存在 /usr/local/stow/vim 文件夹之下。如果你从源代码中安装了 Python,所有关联到 python 的文件都会保存在 /usr/local/stow/python 之下。

我现在从源代码中来安装一个叫做 hello 的程序。

首先下载 hello 程序的压缩包。

$ wget http://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz

使用下面的命令解压压缩包:

$ tar -zxvf hello-2.10.tar.gz

上面的命令将会在当前工作目录下创建一个叫做 hello-2.10 的目录,并且提取压缩包中的所有内容到其中去。

切换到这个目录当中:

$ cd hello-2.10/

运行下面的命令,并且添加 -prefix 选项。

$ ./configure --prefix=/usr/local/stow/hello

上面的命令将会保存构建文件到一个指定位置,在这个例子中是 /usr/local/stow/hello

最后,使用下面的命令构建并安装 hello 这个程序:

$ make
$ sudo make install

就这样。hello 这个程序就已经安装在 /usr/local/stow/hello/ 这个位置了。你可以使用下面的 ls 命令确认一下。

$ ls /usr/local/stow/hello/
bin share

最后,进入 /usr/local/stow/ 目录,运行下面的命令来生成必要的符号链接。

$ cd /usr/local/stow/
$ sudo stow hello

大功告成!

刚才那一步是将包含在 hello 这个程序中的所有文件或者目录创建了链接到 /usr/local/ 目录中。换一种说法, /usr/local/stow/hello/bin 链接到 /usr/local/share,以及 /usr/local/stow/hello/share/man 链接到 /usr/local/share,还有 /usr/local/stow/hello/share/man 链接到 /usr/local/share/man

你可以使用 ls 命令来确认一下:

$ ls /usr/local/bin/
hello

可以使用下面的命令来确认 hello 这个程序是否可以正常工作了:

$ hello
Hello, world!

很好,它已经开始工作了!!

类似地,你可以像上面描述的那样安装程序到它对应的子目录下。

下面是 Stow 根目录包含的内容:

$ tree /usr/local/stow/

看,hello 这个程序已经安装在 /usr/local/stow/hello/ 下。同样地,所有的包都将保存在它们对应的目录之下。

下面进入主要环节,移除 hello 这个程序。首先进入 /usr/local/stow/ 目录:

$ cd /usr/local/stow/

然后运行下面的命令:

$ sudo stow --delete hello

hello 这个程序就会被移除了。你可以使用下面的命令确认它是否真的被移除了:

$ hello
-bash: /usr/local/bin/hello: No such file or directory

看, Hello 已经被移除了!

请注意 Stow 仅仅只移除了符号链接。所有与 hello 这个程序相关的文件或者目录还保存在 /usr/local/stow/hello 目录下。所以你无需再次下载源文件就可以再次安装 hello 这个程序。如果你不再需要它了,直接删除这个文件夹即可。

$ sudo rm -fr /usr/local/stow/hello/

想了解更多 Stow 的细节,请参阅 man 手册。

$ man stow

Stow 可以像安装程序一样轻松地帮你移除它。如果你想知道如何高效的管理很多从源代码中安装的程序,GNU Stow 就是一个使得这个任务更加轻松的一个选择,尝试一下,你一定不会失望的。

这就是所有的内容了,希望对你有所帮助。还有更多干活即将到来,可以期待一下的!

祝近祺!


via: https://www.ostechnix.com/an-easy-way-to-remove-programs-installed-from-source-in-linux/

作者:SK 选题:lujun9972 译者:dianbanjiu 校对:wxy

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

目的

使用 GNU Stow 轻松管理从源代码安装的程序和点文件(LCTT 译注: 点文件 dotfile ,即以 . 开头的文件,在 *nix 下默认为隐藏文件,常用于存储程序的配置信息。)

要求

  • root 权限

难度

简单

约定

  • # - 给定的命令要求直接以 root 用户身份或使用 sudo 命令以 root 权限执行
  • $ - 给定的命令将作为普通的非特权用户来执行

介绍

有时候我们必须从源代码安装程序,因为它们也许不能通过标准渠道获得,或者我们可能需要特定版本的软件。 GNU Stow 是一个非常不错的 符号链接工厂 symlinks factory 程序,它可以帮助我们保持文件的整洁,易于维护。

获得 stow

你的 Linux 发行版本很可能包含 stow,例如在 Fedora,你安装它只需要:

# dnf install stow

在 Ubuntu/Debian 中,安装 stow 需要执行:

# apt install stow

在某些 Linux 发行版中,stow 在标准库中是不可用的,但是可以通过一些额外的软件源(例如 RHEL 和 CentOS7 中的EPEL )轻松获得,或者,作为最后的手段,你可以从源代码编译它。只需要很少的依赖关系。

从源代码编译

最新的可用 stow 版本是 2.2.2。源码包可以在这里下载:https://ftp.gnu.org/gnu/stow/

一旦你下载了源码包,你就必须解压它。切换到你下载软件包的目录,然后运行:

$ tar -xvpzf stow-2.2.2.tar.gz

解压源文件后,切换到 stow-2.2.2 目录中,然后编译该程序,只需运行:

$ ./configure
$ make

最后,安装软件包:

# make install

默认情况下,软件包将安装在 /usr/local/ 目录中,但是我们可以改变它,通过配置脚本的 --prefix 选项指定目录,或者在运行 make install 时添加 prefix="/your/dir"

此时,如果所有工作都按预期工作,我们应该已经在系统上安装了 stow

stow 是如何工作的?

stow 背后主要的概念在程序手册中有很好的解释:

Stow 使用的方法是将每个软件包安装到自己的目录树中,然后使用符号链接使它看起来像文件一样安装在公共的目录树中

为了更好地理解这个软件的运作,我们来分析一下它的关键概念:

stow 文件目录

stow 目录是包含所有 stow 软件包的根目录,每个包都有自己的子目录。典型的 stow 目录是 /usr/local/stow:在其中,每个子目录代表一个软件包。

stow 软件包

如上所述,stow 目录包含多个“软件包”,每个软件包都位于自己单独的子目录中,通常以程序本身命名。包就是与特定软件相关的文件和目录列表,作为一个实体进行管理。

stow 目标目录

stow 目标目录解释起来是一个非常简单的概念。它是包文件应该安装到的目录。默认情况下,stow 目标目录被视作是调用 stow 的目录。这种行为可以通过使用 -t 选项( --target 的简写)轻松改变,这使我们可以指定一个替代目录。

一个实际的例子

我相信一个好的例子胜过 1000 句话,所以让我来展示 stow 如何工作。假设我们想编译并安装 libx264,首先我们克隆包含其源代码的仓库:

$ git clone git://git.videolan.org/x264.git

运行该命令几秒钟后,将创建 x264 目录,它将包含准备编译的源代码。我们切换到 x264 目录中并运行 configure 脚本,将 --prefix 指定为 /usr/local/stow/libx264 目录。

$ cd x264 && ./configure --prefix=/usr/local/stow/libx264

然后我们构建该程序并安装它:

$ make
# make install

x264 目录应该创建在 stow 目录内:它包含了所有通常直接安装在系统中的东西。 现在,我们所要做的就是调用 stow。 我们必须从 stow 目录内运行这个命令,通过使用 -d 选项来手动指定 stow 目录的路径(默认为当前目录),或者通过如前所述用 -t 指定目标。我们还应该提供要作为参数存储的软件包的名称。 在这里,我们从 stow 目录运行程序,所以我们需要输入的内容是:

# stow libx264

libx264 软件包中包含的所有文件和目录现在已经在调用 stow 的父目录 (/usr/local) 中进行了符号链接,因此,例如在 /usr/local/ stow/x264/bin 中包含的 libx264 二进制文件现在符号链接在 /usr/local/bin 之中,/usr/local/stow/x264/etc 中的文件现在符号链接在 /usr/local/etc 之中等等。通过这种方式,系统将显示文件已正常安装,并且我们可以容易地跟踪我们编译和安装的每个程序。要反转该操作,我们只需使用 -D 选项:

# stow -d libx264

完成了!符号链接不再存在:我们只是“卸载”了一个 stow 包,使我们的系统保持在一个干净且一致的状态。 在这一点上,我们应该清楚为什么 stow 还可以用于管理点文件。 通常的做法是在 git 仓库中包含用户特定的所有配置文件,以便轻松管理它们并使它们在任何地方都可用,然后使用 stow 将它们放在适当位置,如放在用户主目录中。

stow 还会阻止你错误地覆盖文件:如果目标文件已经存在,并且没有指向 stow 目录中的包时,它将拒绝创建符号链接。 这种情况在 stow 术语中称为冲突。

就是这样!有关选项的完整列表,请参阅 stow 帮助页,并且不要忘记在评论中告诉我们你对此的看法。


via: https://linuxconfig.org/how-to-use-gnu-stow-to-manage-programs-installed-from-source-and-dotfiles

作者:Egidio Docile 译者:MjSeven 校对:wxy

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

提要:对于开源软件来说,其许可证信息内嵌在源代码中。为了降低复杂性,您可以生成不同的视图。

您可以通过查看源代码找到开源软件的许可证信息。为了满足不同的需求,可以生成关于该许可证信息的不同视图或报告。

尽管直接在源代码中提供许可证信息并不是开源软件的必要条件,但是这样做的实际好处显而易见。由于开源许可证促进了软件的传播,与代码一起传输的许可证信息简化了管理过程,即使代码接收人通过间接方式获得代码,也可以使他随时可以获得权限声明。

什么是许可证条款?

在源码树中嵌入许可证信息的价值被低估了。让我们暂停一下,反思一下这种常见做法是多么有用。

什么是许可证条款呢? 对于许多开源软件来说,有一个简单的答案:一个许可证文本包含整个软件的所有许可证信息。但是开源的力量在于,它推动了其他开发者在这个起点之上进行构建,而这个过程会使许可证信息复杂化。

开源软件可以被扩展、再利用,或者与其他软件结合使用。与机械设备不同,不同群体之间的合作更具挑战性,复杂软件从许多人的工作中受益是切实可行的。开源许可证提供了促进这种开发动态的权限。具有复杂历史的软件也可能具有复杂的许可证信息。

考虑下面的例子:有人写了一个新的程序,在每个源文件中包含一个版权声明,声明该软件根据 Apache 2.0 版许可证进行许可,并且在源码树的根目录中包含 Apache 许可证文本。之后,添加了一个具有不同的版权声明的文件,以及一个 BSD 2 句版许可证副本的文件。然后,添加了一个新的子目录,其中文件具有 Apache 许可证声明,但具有标识不同版权所有者的版权声明。再之后,一个 MIT 许可证的副本添加到了新的子目录中,该子目录包含了版权声明与 MIT 许可证文件中相同的文件,但没有任何其他许可证指示信息。

这个例子表明,嵌入在源码树中的许可证信息可能很复杂而且很详细。根目录和/或各个子目录中都可能有许可证文本。一些源文件可能有许可证通知;其他源文件可能不会有。也许会有版权声明来识别各种版权所有者。但是,在不丢失信息的前提下将法律文本从代码中分离出来似乎是不可能的。因此,源代码即是许可证。

从源码树的角度来看,上面例子中对许可证信息的解释是非常简单的。但是,要在简单、明确的独立声明中获取许可证信息将是一件困难的事情。截取了源代码中所有许可证信息的许可证声明会比源代码更短,但这将是不方便的——谁会希望得到如此高度详细的单独声明?大多数用户可能会更喜欢一个概要,虽然不完整,但其获取的关键点符合自己的特定意图和敏感性要求。

用视图来概括许可证信息

对于“许可证条款是什么”这个问题,用整个源码树副本来回答可能没什么用,因为它过于庞杂和分散。大多数人只想要一个概要。但这面临一个挑战:当许可证信息比较复杂时,人们需要不同的概要,因为他们对于什么是重要的有不同的定义。

对于某些人来说,对以下问题回答“是”可能是足够的:该软件 1)是否根据一个或多个开源许可证获得许可,2)其被组装和许可后是否使得其分发和使用与所有这些许可证一致? 其他人可能需要所有许可证的列表,或者他们可能想要查看哪个软件组件对应于哪个许可证。还有一些人可能想要一个逐个组件的列表来标识任何 左版 copyleft 许可证(也许自己要做深入的左版合规研究)。 有些人可能有兴趣看到所有版权声明和软件组件的相关列表。

单一的概要可能不会满足所有人的利益。简单地将概要具体化可能会减少它对一些人的效用,而对其他人则显得不足。因此,需要将源代码中包含的许可证信息展现为不同的 “视图” views 。这里使用的“视图”术语可以视为与在数据库中使用它相似。或者,您也可以将“视图”看作是 “报告” reports

考虑将源代码作为许可证有一个优势,并且可以从中提取多个不同的视图。

您可能会尝试创建一个“全能”概要,从中可以创建其他较短的概要。但是以中间状态表达许可证信息至少有三个缺点:

  1. 时机:主概要的维护人员可能无法按计划进行更新。
  2. 版本:主概要可能基于与您使用的软件不同的版本。
  3. 质量:您的视图继承了主概要的错误和评判性。

因此,根据需要直接从您使用的源码树版本生成您的首选视图是有价值的。

有工具可以生成视图。按需视图的生成取决于工具。许可证信息展示的清晰(或混乱)程度会促进(或妨碍)该工具的功效。我们不需要许可证信息的特定机器编码,但是我们应该充分利用众多经验来源,以既可以被人读取,也可以被机器提取的方式来表达信息。

Jeff Kaufman 在他的文章《开源软件许可证合规的经济高效模型》中指出:由于源代码包含许可证信息,因此分发源代码是满足某些许可证要求的有效方式。

将所有许可证信息嵌入到源码树中是最佳实践。如果您发现源码树中没有显示许可证信息,请考虑通过提交错误报告来改进该项目,建议将该信息添加到源码树中。

源代码即是许可证。从完整的记录中,可以生成许可证信息的视图。工具可以将许可证信息提取到各种报告中,以满足特定需求或敏感性要求。

为了获得这个愿景的全部好处,我们还有工作要做。您对工具状态以及许可证信息展现有什么看法呢?


作者简介:Scott Peterson 是红帽公司法律团队成员。很久以前,一位工程师就一个叫做 GPL 的奇怪文件向 Scott 征询法律建议,这个致命的问题让 Scott 走上了探索包括技术标准和开源软件在内的协同开发法律问题的纠结之路。

译者简介:薛亮,集慧智佳知识产权咨询公司高级咨询师,擅长专利检索、专利分析、竞争对手跟踪、FTO分析、开源软件知识产权风险分析,致力于为互联网企业、高科技公司提供知识产权咨询服务。

How to install software from source code

简介:这篇文章详细介绍了在 Linux 中怎么用源代码安装程序,以及怎么去卸载用源代码安装的程序。

Linux 发行版的一个最大的优点就是它的包管理器和相关的软件库。通过它们提供的资源和工具,你才能够以完全自动化的方式在你的计算机上下载和安装软件。

但是,尽管付出了很多的努力,包维护者仍然没法照顾好每种情况,也不可能将所有的可用软件都打包进去。因此,仍然存在需要你自已去编译和安装一个新软件的情形。对于我来说,到目前为止,最主要的原因是,我编译一些软件是我需要去运行一个特定的版本。或者是我想去修改源代码或使用一些想要的编译选项。

如果你也属于后一种情况,那你已经知道你应该怎么做了。但是,对于绝大多数的 Linux 用户来说,第一次从源代码中编译和安装一个软件看上去像是一个入门仪式:它让很多人感到恐惧;但是,如果你能克服困难,你将可能进入一个全新的世界,并且,如果你做到了,那么你将成为社区中享有特权的一部分人。

A. 在 Linux 中从源代码开始安装软件

这正是我们要做的。因为这篇文章的需要,我要在我的系统上安装 NodeJS 8.1.1。它是个完全真实的版本。这个版本在 Debian 仓库中没有:

sh$ apt-cache madison nodejs | grep amd64
    nodejs | 6.11.1~dfsg-1 | http://deb.debian.org/debian experimental/main amd64 Packages
    nodejs | 4.8.2~dfsg-1 | http://ftp.fr.debian.org/debian stretch/main amd64 Packages
    nodejs | 4.8.2~dfsg-1~bpo8+1 | http://ftp.fr.debian.org/debian jessie-backports/main amd64 Packages
    nodejs | 0.10.29~dfsg-2 | http://ftp.fr.debian.org/debian jessie/main amd64 Packages
    nodejs | 0.10.29~dfsg-1~bpo70+1 | http://ftp.fr.debian.org/debian wheezy-backports/main amd64 Packages

第 1 步:从 GitHub 上获取源代码

像大多数开源项目一样,NodeJS 的源代码可以在 GitHub:https://github.com/nodejs/node 上找到。

所以,我们直接开始吧。

The NodeJS official GitHub repository

如果你不熟悉 GitHubgit 或者提到的其它 版本管理系统包含了这个软件的源代码,以及多年来对该软件的所有修改的历史。甚至可以回溯到该软件的最早版本。对于开发者来说,保留它的历史版本有很多好处。如今对我来说,其中一个好处是可以得到任何一个给定时间点的项目源代码。更准确地说,我可以得到我所要的 8.1.1 发布时的源代码。即便从那之后他们有了很多的修改。

Choose the v8.1.1 tag in the NodeJS GitHub repository

在 GitHub 上,你可以使用 “branch” (分支)按钮导航到这个软件的不同版本。“分支” 和 “标签” 是 Git 中一些相关的概念。总的来说,开发者创建 “分支” 和 “标签” 来在项目历史中对重要事件保持跟踪,比如当他们启用一个新特性或者发布一个新版本时。在这里先不详细介绍了,你现在只需要知道我在找被标记为 “v8.1.1” 的版本。

The NodeJS GitHub repository as it was at the time the v8.1.1 tag was created

在选择了 “v8.1.1” 标签后,页面被刷新,最显著的变化是标签现在作为 URL 的一部分出现。另外,你可能会注意到文件改变日期也有所不同。你现在看到的源代码树是创建了 v8.1.1 标签时的代码。在某种意义上,你也可以认为像 git 这样的版本管理工具是一个时光穿梭机,允许你在项目历史中来回穿梭。

NodeJS GitHub repository download as a ZIP button

此时,我们可以下载 NodeJS 8.1.1 的源代码。你不要忘记去点那个建议的大的蓝色按钮来下载一个项目的 ZIP 压缩包。对于我来说,为讲解的目的,我从命令行中下载并解压这个 ZIP 压缩包。但是,如果你更喜欢使用一个 GUI 工具,不用担心,你可以取代下面的命令方式:

wget https://github.com/nodejs/node/archive/v8.1.1.zip
unzip v8.1.1.zip
cd node-8.1.1/

下载一个 ZIP 包就可以,但是如果你希望“像个专家一样”,我建议你直接使用 git 工具去下载源代码。它一点也不复杂 — 并且如果你是第一次使用该工具,它将是一个很好的开端,你以后将经常用到它:

# first ensure git is installed on your system
sh$ sudo apt-get install git
# Make a shallow clone the NodeJS repository at v8.1.1
sh$ git clone --depth 1 \
              --branch v8.1.1 \
              https://github.com/nodejs/node
sh$ cd node/

顺便说一下,如果你有任何问题,这篇文章的第一部分只是做一个总体介绍而已。后面,为了帮你排除常见问题,我们将基于 Debian 和基于 RedHat 的发行版更详细地解释。

不管怎样,在你使用 git 或者作为一个 ZIP 压缩包下载了源代码后,在当前目录下就有了同样的源代码文件:

sh$ ls
android-configure  BUILDING.md            common.gypi      doc            Makefile   src
AUTHORS            CHANGELOG.md           configure        GOVERNANCE.md  node.gyp   test
benchmark          CODE_OF_CONDUCT.md     CONTRIBUTING.md  lib            node.gypi  tools
BSDmakefile        COLLABORATOR_GUIDE.md  deps             LICENSE        README.md  vcbuild.bat

第 2 步:理解程序的构建系统

构建系统就是我们通常所说的“编译源代码”,其实,编译只是从源代码中生成一个可使用的软件的其中一个阶段。构建系统是一套工具,用于自动处置不同的任务,以便可以仅通过几个命令就能构建整个软件。

虽然概念很简单,实际上编译做了很多事情。因为不同的项目或者编程语言也许有不同的要求,或者因为编程者的好恶,或者因为支持的平台、或者因为历史的原因,等等等等 … 选择或创建另外一个构建系统的原因几乎数不清。这方面有许多种不同的解决方案。

NodeJS 使用一种 GNU 风格的构建系统。这在开源社区中这是一个很流行的选择。由此开始,你将进入一段精彩的旅程。

写出和调优一个构建系统是一个非常复杂的任务。但是,作为 “终端用户” 来说,GNU 风格的构建系统使用两个工具让他们免于此难:configuremake

configure 文件是个项目专用的脚本,它将检查目标系统的配置和可用功能,以确保该项目可以被构建,并最终吻合当前平台的特性。

一个典型的 configure 任务的重要部分是去构建 Makefile。这个文件包含了有效构建项目所需的指令。

另一方面,make 工具,这是一个可用于任何类 Unix 系统的 POSIX 工具。它将读取项目专用的 Makefile 然后执行所需的操作去构建和安装你的程序。

但是,在 Linux 的世界中,你仍然有一些定制你自己专用的构建的理由。

./configure --help

configure -help 命令将展示你可用的所有配置选项。再强调一下,这是非常的项目专用。说实话,有时候,在你完全理解每个配置选项的作用之前,你需要深入到项目中去好好研究。

不过,这里至少有一个标准的 GNU 自动化工具选项是你该知道的,它就是众所周知的 --prefix 选项。它与文件系统的层次结构有关,它是你软件要安装的位置。

第 3 步:文件系统层次化标准(FHS)

大部分典型的 Linux 发行版的文件系统层次结构都遵从 文件系统层次化标准(FHS)

这个标准说明了你的系统中各种目录的用途,比如,/usr/tmp/var 等等。

当使用 GNU 自动化工具 和大多数其它的构建系统 时,它会把新软件默认安装在你的系统的 /usr/local 目录中。这是依据 FHS 中 /usr/local 层级是为系统管理员本地安装软件时使用的,它在系统软件更新覆盖时是安全的。它也可以用于存放在一组主机中共享,但又没有放到 /usr 中的程序和数据”,因此,它是一个非常好的选择。

/usr/local 层级以某种方式复制了根目录,你可以在 /usr/local/bin 这里找到可执行程序,在 /usr/local/lib 中找到库,在 /usr/local/share 中找到架构无关的文件,等等。

使用 /usr/local 树作为你定制安装的软件位置的唯一问题是,你的软件的文件将在这里混杂在一起。尤其是你安装了多个软件之后,将很难去准确地跟踪 /usr/local/bin/usr/local/lib 中的哪个文件到底属于哪个软件。它虽然不会导致系统的问题。毕竟,/usr/bin 也是一样混乱的。但是,有一天你想去卸载一个手工安装的软件时它会将成为一个问题。

要解决这个问题,我通常喜欢安装定制的软件到 /opt 子目录下。再次引用 FHS:

/opt 是为安装附加的应用程序软件包而保留的。

包安装在 /opt 下的软件包必须将它的静态文件放在单独的 /opt/<package> 或者 /opt/<provider> 目录中,此处 <package> 是所说的那个软件名的名字,而 <provider> 处是提供者的 LANANA 注册名字。”(LCTT 译注:LANANA 是指 The Linux Assigned Names And Numbers Authority。 )

因此,我们将在 /opt 下创建一个子目录,用于我们定制的 NodeJS 安装。并且,如果有一天我想去卸载它,我只是很简单地去删除那个目录:

sh$ sudo mkdir /opt/node-v8.1.1
sh$ sudo ln -sT node-v8.1.1 /opt/node
# What is the purpose of the symbolic link above?
# Read the article till the end--then try to answer that
# question in the comment section!

sh$ ./configure --prefix=/opt/node-v8.1.1
sh$ make -j9 && echo ok
# -j9 means run up to 9 parallel tasks to build the software.
# As a rule of thumb, use -j(N+1) where N is the number of cores
# of your system. That will maximize the CPU usage (one task per
# CPU thread/core + a provision of one extra task when a process
# is blocked by an I/O operation.

在你运行完成 make 命令之后,如果有任何的除了 “ok” 以外的信息,将意味着在构建过程中有错误。当我们使用一个 -j 选项去运行并行构建时,在构建系统的大量输出过程中,检索错误信息并不是件很容易的事。

在这种情况下,只能是重新开始 make,并且不要使用 -j 选项。这样错误将会出现在输出信息的最后面:

sh$ make

最终,编译结束后,你可以运行这个命令去安装你的软件:

sh$ sudo make install

然后测试它:

sh$ /opt/node/bin/node --version
v8.1.1

B. 如果在源代码安装的过程中出现错误怎么办?

我上面介绍的大多是你能在文档完备的项目的“构建指令”页面上看到。但是,本文的目标是让你从源代码开始去编译你的第一个软件,它可能要花一些时间去研究一些常见的问题。因此,我将再次重新开始一遍整个过程,但是,这次是在一个最新的、最小化安装的 Debian 9.0 和 CentOS 7.0 系统上。因此,你可能看到我遇到的错误以及我怎么去解决它。

从 Debian 9.0 中 “Stretch” 开始

itsfoss@debian:~$ git clone --depth 1 \
                             --branch v8.1.1 \
                             https://github.com/nodejs/node
-bash: git: command not found

这个问题非常容易去诊断和解决。去安装这个 git 包即可:

itsfoss@debian:~$ sudo apt-get install git
itsfoss@debian:~$ git clone --depth 1 \
                             --branch v8.1.1 \
                             https://github.com/nodejs/node && echo ok
[...]
ok
itsfoss@debian:~/node$ sudo mkdir /opt/node-v8.1.1
itsfoss@debian:~/node$ sudo ln -sT node-v8.1.1 /opt/node

现在没有问题了。

itsfoss@debian:~/node$ ./configure --prefix=/opt/node-v8.1.1/
WARNING: failed to autodetect C++ compiler version (CXX=g++)
WARNING: failed to autodetect C compiler version (CC=gcc)
Node.js configure error: No acceptable C compiler found!
        Please make sure you have a C compiler installed on your system and/or
        consider adjusting the CC environment variable if you installed
        it in a non-standard prefix.

很显然,编译一个项目,你需要一个编译器。NodeJS 是使用 C++ 语言 写的,我们需要一个 C++ 编译器。在这里我将安装 g++,它就是为这个目的写的 GNU C++ 编译器:

itsfoss@debian:~/node$ sudo apt-get install g++
itsfoss@debian:~/node$ ./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
itsfoss@debian:~/node$ make -j9 && echo ok
-bash: make: command not found

还差一个其它工具。同样的症状。同样的解决方案:

itsfoss@debian:~/node$ sudo apt-get install make
itsfoss@debian:~/node$ make -j9 && echo ok
[...]
ok
itsfoss@debian:~/node$ sudo make install
[...]
itsfoss@debian:~/node$ /opt/node/bin/node --version
v8.1.1

成功!

请注意:我将一次又一次地安装各种工具去展示怎么去诊断编译问题,以及展示怎么去解决这些问题。但是,如果你搜索关于这个主题的更多文档,或者读其它的教程,你将发现,很多发行版有一个 “meta-packages”,它包罗了安装一些或者全部的用于编译软件的常用工具。在基于 Debian 的系统上,你或许遇到过 build-essentials 包,它就是这种用作。在基于 Red Hat 的发行版中,它将是 “Development Tools” 组。

在 CentOS 7.0 上

[itsfoss@centos ~]$ git clone --depth 1 \
                               --branch v8.1.1 \
                               https://github.com/nodejs/node
-bash: git: command not found

命令没有找到?可以用 yum 包管理器去安装它:

[itsfoss@centos ~]$ sudo yum install git
[itsfoss@centos ~]$ git clone --depth 1 \
                               --branch v8.1.1 \
                               https://github.com/nodejs/node && echo ok
[...]
ok
[itsfoss@centos ~]$ sudo mkdir /opt/node-v8.1.1
[itsfoss@centos ~]$ sudo ln -sT node-v8.1.1 /opt/node
[itsfoss@centos ~]$ cd node
[itsfoss@centos node]$ ./configure --prefix=/opt/node-v8.1.1/
WARNING: failed to autodetect C++ compiler version (CXX=g++)
WARNING: failed to autodetect C compiler version (CC=gcc)
Node.js configure error: No acceptable C compiler found!

        Please make sure you have a C compiler installed on your system and/or
        consider adjusting the CC environment variable if you installed
        it in a non-standard prefix.

你知道的:NodeJS 是使用 C++ 语言写的,但是,我的系统缺少合适的编译器。Yum 可以帮到你。因为,我不是一个合格的 CentOS 用户,我实际上是在互联网上搜索到包含 g++ 编译器的包的确切名字的。这个页面指导了我:https://superuser.com/questions/590808/yum-install-gcc-g-doesnt-work-anymore-in-centos-6-4

[itsfoss@centos node]$ sudo yum install gcc-c++
[itsfoss@centos node]$ ./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
[itsfoss@centos node]$ make -j9 && echo ok
[...]
ok
[itsfoss@centos node]$ sudo make install && echo ok
[...]
ok
[itsfoss@centos node]$ /opt/node/bin/node --version
v8.1.1

再次成功!

C. 从源代码中对要安装的软件做一些改变

从源代码中安装一个软件,可能是因为你的分发仓库中没有一个可用的特定版本。或者因为你想去 修改 那个程序。也可能是修复一个 bug 或者增加一个特性。毕竟,开源软件这些都可以做到。因此,我将抓住这个机会,让你亲自体验怎么去编译你自己的软件。

在这里,我将在 NodeJS 源代码上做一个微小改变。然后,我们将看到我们的改变将被纳入到软件的编译版本中:

用你喜欢的 文本编辑器(如,vim、nano、gedit、 … )打开文件 node/src/node.cc。然后,尝试找到如下的代码片段:

   if (debug_options.ParseOption(argv[0], arg)) {
      // Done, consumed by DebugOptions::ParseOption().
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
      printf("%s\n", NODE_VERSION);
      exit(0);
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
      PrintHelp();
      exit(0);
    }

它在 文件的 3830 行 附近。然后,修改包含 printf 的行,将它替换成如下内容:

      printf("%s (compiled by myself)\n", NODE_VERSION);

然后,返回到你的终端。在继续之前,为了对强大的 Git 支持有更多的了解,你可以去检查一下,你修改是文件是否正确:

diff --git a/src/node.cc b/src/node.cc
index bbce1022..a5618b57 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -3828,7 +3828,7 @@ static void ParseArgs(int* argc,
     if (debug_options.ParseOption(argv[0], arg)) {
       // Done, consumed by DebugOptions::ParseOption().
     } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
-      printf("%s\n", NODE_VERSION);
+      printf("%s (compiled by myself)\n", NODE_VERSION);
       exit(0);
     } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
       PrintHelp();

在你前面改变的那行之前,你将看到一个 “-” (减号标志)。而在改变之后的行前面有一个 “+” (加号标志)。

现在可以去重新编译并重新安装你的软件了:

make -j9 && sudo make install && echo ok
[...]
ok

这个时候,可能失败的唯一原因就是你改变代码时的输入错误。如果就是这种情况,在文本编辑器中重新打开 node/src/node.cc 文件并修复错误。

一旦你完成了新修改版本的 NodeJS 的编译和安装,就可以去检查你的修改是否包含到软件中:

itsfoss@debian:~/node$ /opt/node/bin/node --version
v8.1.1 (compiled by myself)

恭喜你!你对开源程序做出了你的第一个改变!

D. 让 shell 找到我们定制构建的软件

到目前为止,你可能注意到,我通常启动我新编译的 NodeJS 软件是通过指定到该二进制文件的绝对路径。

/opt/node/bin/node

这是可以正常工作的。但是,这样太麻烦。实际上有两种办法可以去解决这个问题。但是,去理解它们,你必须首先明白,你的 shell 定位可执行文件是通过在环境变量 PATH 中指定的目录里面查找的。

itsfoss@debian:~/node$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

在这个 Debian 系统上,如果你不指定一个精确的目录做为命令名字的一部分,shell 将首先在 /usr/local/bin 中查找可执行程序;如果没有找到,然后进入 /usr/bin 中查找;如果没有找到,然后进入 /bin查找;如果没有找到,然后进入 /usr/local/games 查找;如果没有找到,然后进入 /usr/games 查找;如果没有找到,那么,shell 将报告一个错误,“command not found”

由此,我们可以知道有两种方法去确保命令可以被 shell 访问到:将它(该二进制程序)增加到已经配置好的 PATH 目录中,或者将包含可执行程序的目录添加到 PATH 中。

从 /usr/local/bin 中添加一个链接

只是从 /opt/node/bin拷贝 NodeJS 二进制可执行文件到 /usr/local/bin 是一个错误的做法。因为,如果这么做,该可执行程序将无法定位到在 /opt/node/ 中的需要的其它组件。(软件以它自己的位置去定位它所需要的资源文件是常见的做法)

因此,传统的做法是去使用一个符号链接:

itsfoss@debian:~/node$ sudo ln -sT /opt/node/bin/node /usr/local/bin/node
itsfoss@debian:~/node$ which -a node || echo not found
/usr/local/bin/node
itsfoss@debian:~/node$ node --version
v8.1.1 (compiled by myself)

这一个简单而有效的解决办法,尤其是,如果一个软件包是由好几个众所周知的可执行程序组成的,因为,你将为每个用户调用的命令创建一个符号链接。例如,如果你熟悉 NodeJS,你知道应用的 npm 组件,也应该从 /usr/local/bin 做个符号链接。我把这个留给你做练习。

修改 PATH

首先,如果你尝试过前面的解决方案,请先移除前面创建的节点符号链接,去从一个干净的状态开始:

itsfoss@debian:~/node$ sudo rm /usr/local/bin/node
itsfoss@debian:~/node$ which -a node || echo not found
not found

现在,这里有一个改变你的 PATH 的魔法命令:

itsfoss@debian:~/node$ export PATH="/opt/node/bin:${PATH}"
itsfoss@debian:~/node$ echo $PATH
/opt/node/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

简单说就是,我用环境变量 PATH 之前的内容前缀了一个 /opt/node/bin 替换了其原先的内容。因此,你可以想像一下,shell 将先进入到 /opt/node/bin 目录中查找可执行程序。我们也可以使用 which 命令去确认一下:

itsfoss@debian:~/node$ which -a node || echo not found
/opt/node/bin/node
itsfoss@debian:~/node$ node --version
v8.1.1 (compiled by myself)

鉴于 “符号链接” 解决方案是永久的,只要创建到 /usr/local/bin 的符号链接就行了,而对 PATH 的改变仅影响到当前的 shell。你可以自己做一些研究,如何做到对 PATH 的永久改变。给你一个提示,可以将它写到你的 “profile” 中。如果你找到这个解决方案,不要犹豫,通过下面的评论区共享给其它的读者!

E. 怎么去卸载刚才从源代码中安装的软件

因为我们定制编译的 NodeJS 软件全部在 /opt/node-v8.1.1 目录中,卸载它不需要做太多的工作,仅使用 rm 命令去删除那个目录即可:

sudo rm -rf /opt/node-v8.1.1

注意:sudorm -rf 是 “非常危险的鸡尾酒”!一定要在按下回车键之前多检查几次你的命令。你不会得到任何的确认信息,并且如果你删除了错误的目录它是不可恢复的 …

然后,如果你修改了你的 PATH,你可以去恢复这些改变。它一点也不复杂。

如果你从 /usr/local/bin 创建了一个符号链接,你应该去删除它们:

itsfoss@debian:~/node$ sudo find /usr/local/bin \
                                 -type l \
                                 -ilname "/opt/node/*" \
                                 -print -delete
/usr/local/bin/node

等等? 依赖地狱在哪里?

作为最终的讨论,如果你读过有关的编译定制软件的文档,你可能听到关于 依赖地狱 dependency hell 的说法。那是在你能够成功编译一个软件之前,对那种烦人情况的一个别名,你必须首先编译一个前提条件所需要的库,它又可能要求其它的库,而这些库有可能与你的系统上已经安装的其它软件不兼容。

发行版的软件包维护者的部分工作,就是实际去地解决那些依赖地狱,确保你的系统上的各种软件都使用了兼容的库,并且按正确的顺序去安装。

在这篇文章中,我特意选择了 NodeJS 去安装,是因为它几乎没有依赖。我说 “几乎” 是因为,实际上,它 依赖。但是,这些源代码的依赖已经预置到项目的源仓库中(在 node/deps 子目录下),因此,在你动手编译之前,你不用手动去下载和安装它们。

如果你有兴趣了解更多关于那个问题的知识和学习怎么去处理它。请在下面的评论区告诉我,它将是更高级别的文章的好主题!


作者简介:

充满激情的工程师,职业是教师,我的目标是:热心分享我所教的内容,并让我的学生自己培养它们的技能。你也可以在我的网站上联系到我。


via: https://itsfoss.com/install-software-from-source-code/

作者:Sylvain Leroux 译者:qhwdw 校对:wxy

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

在下载并解压内核源代码后,用户可以看到许多文件夹和文件。尝试去找一个特定的文件或许是一个挑战。谢天谢地,源代码以一个特定的方式组织的。这使开发者能够轻松找到任何文件或者内核的一部分。

内核源代码的根目录下包含了以下文件夹

arch
block
crypto
Documentation
drivers
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt

还有一些文件在源代码的根目录下。它们会在下面列出。

COPYING -许可和授权信息。Linux内核在GPLv2许可证下授权。该许可证授予任何人有权免费去使用、修改、分发和共享源代码和编译代码。然而,没有人可以出售源代码。

CREDITS - 贡献者列表

Kbuild - 这是一个设置一些内核设定的脚本。打个比方,这个脚本设定一个ARCH变量,这是开发者想要生成的内核支持的处理器类型。

Kconfig - 这个脚本会在开发人员配置内核的时候用到,这会在以后的文章中讨论。

MAINTAINERS - 这是一个目前维护者列表,他们的电子邮件地址,主页,和他们负责开发和维护的内核的特定部分或文件。当一个开发者在内核中发现一个问题,并希望能够报告给能够处理这个问题的维护者时,这是是很有用的。

Makefile - This script is the main file that is used to compile the kernel. This file passes parameters to the compiler as well as the list of files to compile and any other necessary information. 这个脚本是编译内核的主要文件。这个文件将编译参数和编译所需的文件和必要的信息传给编译器。

README - 这个文档提供给开发者想要知道的如何编译内核的信息。

REPORTING-BUGS - 这个文档提供如何报告问题的信息。

内核的代码是以“.c”或“.h”为扩展名的文件。 “.c”的扩展名表明内核是用众多的编程语言之一的C语言写的, “h”的文件是头文件,而他们也是用C写成。头文件包含了许多“.c”文件需要使用的代码,因为他们可以引入已有的代码而不是重新编写代码,这节省了程序员的时间。否则,一组执行相同的动作的代码,将存在许多或全部都是“c”文件。这也会消耗和浪费硬盘空间。(译注:头文件不仅仅可节省重复编码,而且代码复用也会降低代码错误的几率)

所有上面列出的文件夹中的文件都组织得很好。文件夹名称至少可以帮助开发人员很好地猜测文件夹中的内容。下面提供了一个目录树和描述。

arch - 这个文件夹包含了一个Kconfig文件,它用于设置这个目录里的源代码编译所需的一系列设定。每个支持的处理器架构都在它相应的文件夹中。如,Alpha处理器的源代码在alpha文件夹中。请记住,随着时间的推移,一些新的处理器将被支持,有些会被放弃。对于Linux v3.9.4,arch下有以下文件夹:

alpha
arc
arm
arm64
avr32
blackfin
c6x
cris
frv
h8300
hexagon
ia64
m32r
m68k
metag
microblaze
mips
mn10300
openrisc
parisc
powerpc
s390
score
sh
sparc
tile
um
unicore32
x86
xtensa

block – 此文件夹包含块设备驱动程序的代码。块设备是以数据块方式接收和发送的数据的设备。数据块都是一块一块的数据而不是持续的数据流。

crypto - 这个文件夹包含许多加密算法的源代码。例如,“sha1\_generic.c”这个文件包含了SHA1加密算法的代码。

Documentation - 此文件夹包含了内核信息和其他许多文件信息的文本文档。如果开发者需要一些信息,他们也许能在这里找到所需要的信息。

drivers - 该目录包含了驱动代码。驱动是一个控制硬件的软件。例如,要让计算机知道键盘并使其可用,键盘驱动是必要的。这个文件夹中存在许多文件夹。每个文件夹都以硬件的种类或者型号命名。例如,'bluetooth'包含了蓝牙驱动程序的代码。还有其他很明显的驱动像SCSI、USB和火线等。有些驱动程序可能会比较难找到。例如,操纵杆驱动不在'joystick'文件夹中,它们却在./drivers/input/joystick。同样键盘和鼠标驱动也在这个input文件夹中。 'Macintosh'包含了苹果的硬件代码。 'Xen'包含了Xen hypervisor代码。(hypervisor是一种允许用户在一台计算机上运行多个操作系统的软件或硬件。这意味着在Xen允许用户在一台计算机上同时运行的两个或两个以上的Linux系统。用户还可以运行Windows,Solaris,FreeBSD或其他操作系统在Linux系统上。)driver文件夹下还有许多其他的文件夹,但他们在这篇文章中无法一一列举,他们将在以后的文章中提到。

firmware - fireware中包含了让计算机读取和理解从设备发来的信号的代码。举例来说,一个摄像头管理它自己的硬件,但计算机必须了解摄像头给计算机发送的信号。Linux系统会使用vicam固件(firmware)来理解摄像头的通讯。否则,没有了固件,Linux系统将不知道如何处理摄像头发来的信息。另外,固件同样有助于将Linux系统发送消息给该设备。这样Linux系统可以告诉摄像头重新调整或关闭摄像头。

fs - 这是文件系统的文件夹。理解和使用的文件系统所需要的所有的代码就在这里。在这个文件夹里,每种文件系统都有自己的文件夹。例如,ext4文件系统的代码在ext4文件夹内。 在fs文件夹内,开发者会看到一些不在文件夹中的文件。这些文件用来控制整个文件系统。例如,mount.h中会包含挂载文件系统的代码。文件系统是以结构化的方式来存储和管理的存储设备上的文件和目录。每个文件系统都有自己的优点和缺点。这是由文件系统的设计决定的。举例来说,NTFS文件系统支持的透明压缩(当启用时,会在用户不知道的情况下自动压缩存储文件)。大多数文件系统缺乏此功能,但如果在fs文件夹里编入相应的文件,它们也有这种能力。

include - include包含了内核所需的各种头文件.这个名字来自于C语言用"include"来在编译时导入头文件。

init - init文件夹包含了内核启动的处理代码(INITiation)。main.c是内核的核心文件,这是用来衔接所有的其他文件的源代码主文件。

ipc - IPC代表进程间通讯。此文件夹中的代码是作为内核与进程之间的通信层。内核控制着硬件,因此程序只能请求内核来执行任务。假设用户有一个打开DVD托盘的程序。程序不直接打开托盘,相反,该程序通知内核托盘应该被打开。然后,内核给硬件发送一个信号去打开托盘。这些代码同样管理kill信号。举例来说,当系统管理员打开进程管理器去关闭一个已经锁死的程序,这个关闭程序的信号被称为kill信号。内核接收到信号,然后内核会要求程序停止或直接把进程从内存和CPU中移除(取决于kill的类型)。命令行中的管道同样用于进程间通信。管道会告诉内核在某个内存页上写入输出数据。程序或者命令得到的数据是来自内存页上的某个给定的指针。

kernel - 这个文件夹中的代码控制内核本身。例如,如果一个调试器需要跟踪问题,内核将使用这个文件夹中代码来将内核指令通知调试器跟踪内核进行的所有动作。这里也有跟踪时间的代码。在内核文件夹下有个"power"文件夹,这里的代码可以使计算机重新启动、关机和挂起。

lib - 这个文件夹包含了内核需要引用的一系列内核库文件代码。

mm - mm文件夹中包含了内存管理代码。内存并不是任意存储在RAM芯片上的。相反,内核小心地将数据放在RAM芯片上。内核不会覆盖任何正在使用或保存重要数据的内存区域。

net - net文件夹中包含了网络协议代码。这包括IPv6、AppleTalk、以太网、WiFi、蓝牙等的代码,此外处理网桥和DNS解析的代码也在net目录。

samples - 此文件夹包含了程序示例和正在编写中的模块代码。假设一个新的模块引入了一个想要的有用功能,但没有程序员说它已经可以正常运行在内核上。那么,这些模块就会移到这里。这给了新内核程序员一个机会通过这个文件夹来获得帮助,或者选择一个他们想要协助开发的模块。

scripts - 这个文件夹有内核编译所需的脚本。最好不要改变这个文件夹内的任何东西。否则,您可能无法配置或编译内核。

security - 这个文件夹是有关内核安全的代码。它对计算机免于受到病毒和黑客的侵害很重要。否则,Linux系统可能会遭到损坏。关于内核的安全性,将在以后的文章中讨论。

sound - 这个文件夹中包含了声卡驱动。

tools - 这个文件夹中包含了和内核交互的工具。

usr - 还记得在以前的文章中提到vmlinuz和其他类似的文件么?这个文件夹中的代码在内核编译完成后创建这些文件。

virt - 此文件夹包含了虚拟化代码,它允许用户一次运行多个操作系统。这与先前提到的Xen是不同的。通过虚拟化,客户机操作系统就像任何其他运行在Linux主机的应用程序一样运行。通过Xen这样的hypervisor(注:虚拟机管理程序),两个操作系统可以同时管理硬件。在虚拟化中,在客户机操作系统上运行在Linux内核上,而在hypervisor中,它没有客户系统并且所有的系统不互相依赖。

提示: 绝不在内核源代码内移动文件,除非你知道你在做什么。否则,编译会由于缺失文件失败。

Linux内核的文件夹结构保持相对稳定。内核开发者会做一些修改,但总体来说,这些设置对整个内核版本都是一样。驱动程序文件夹的布局也基本保持一样。

via: http://www.linux.org/threads/the-linux-kernel-the-source-code.4204/

译者:geekpi 校对:wxy

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