mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-26 21:30:55 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
2b6bd9dd59
@ -0,0 +1,452 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12862-1.html)
|
||||
[#]: subject: (Use your favorite programming language to provision Infrastructure as Code)
|
||||
[#]: via: (https://opensource.com/article/20/8/infrastructure-as-code-pulumi)
|
||||
[#]: author: (Lee Briggs https://opensource.com/users/lbriggs)
|
||||
|
||||
使用你喜欢的编程语言,将基础设施作为代码进行配置
|
||||
======
|
||||
|
||||
> 用 Node.js 或其他编程语言为你提供启动基础设施所需的一切服务。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202011/27/151108bnnggmxegfzwog46.jpg)
|
||||
|
||||
当你在 IT 和技术的世界里遨游时,你会反复遇到一些术语。其中有些术语很难量化,随着时间的推移,可能会有不同的含义。[“DevOps”][2] 就是一个例子,这个词似乎(在我看来)会根据使用它的人而改变;最初的 DevOps 先驱者可能甚至不认识我们今天所说的 DevOps。
|
||||
|
||||
如果你是一个软件开发者,“<ruby>基础架构即代码<rt>Infrastructure as Code</rt></ruby>”(IaC)可能是其中一个术语。IaC 是使用与你编写面向用户的功能相同的软件开发实践来声明应用程序运行的基础设施。这通常意味着使用 [Git][3] 或 [Mercurial][4] 等工具进行版本控制,使用 Puppet、Chef 或 Ansible 进行[配置管理][5]。在基础设施供应层,最常见的技术是 CloudFormation(专用于 AWS),或开源替代品 [Terraform][6],用来创建供你的应用程序运行的混合云资源。
|
||||
|
||||
在配置管理领域有很好产品可供选择,可以将 IaC 写成配置文件或首选的编程语言,但这种选择在基础设施供应领域并不常见。
|
||||
|
||||
[Pulumi][7] 提供了一个使用标准编程语言来定义基础设施的方式。它支持一系列语言,包括 [JavaScript][8]、[TypeScript][9]、[Go][10]、[Python][11] 和 [C#][12]。就像 Terraform 一样,Pulumi 对许多熟悉的云提供商有一流的支持,比如 [AWS][13]、[Azure][14]、[Google Cloud][15] 和[其他提供商][16]。
|
||||
|
||||
在本文中,我将向你展示如何使用 Pulumi 以 Node.js 编写基础设施。
|
||||
|
||||
### 先决条件
|
||||
|
||||
首先,确保你已经做好了使用 Pulumi 的准备。Pulumi 支持所有主流的操作系统,所以你安装其先决条件的方法取决于你使用的操作系统。
|
||||
|
||||
首先,安装你喜欢的编程语言的解释器。我将使用 TypeScript,所以我需要安装 `node` 二进制。请查阅 Node 的[安装说明][17],了解你的操作系统的信息。你可以在 [Mac][19] 或 [Linux][20] 上使用 [Homebrew][18] 来安装:
|
||||
|
||||
```
|
||||
brew install node
|
||||
```
|
||||
|
||||
在 Linux 上,你可以使用你常用的软件包管理器,如 `apt` 或 `dnf`。
|
||||
|
||||
```
|
||||
$ sudo dnf install nodejs
|
||||
```
|
||||
|
||||
无论哪种情况,结果都应该是 `node` 二进制文件在你的 `$PATH` 中可用。要确认它是可访问的,运行:
|
||||
|
||||
```
|
||||
node --version
|
||||
```
|
||||
|
||||
接下来,安装 Pulumi 命令行界面(CLI)。你可以在 Pulumi 的文档中找到针对不同操作系统的[安装说明][21]。在 Mac 或 Linux 上使用 `brew`:
|
||||
|
||||
```
|
||||
brew install pulumi
|
||||
```
|
||||
|
||||
另外,你也可以使用安装脚本。首先下载并审查它,然后执行它:
|
||||
|
||||
```
|
||||
$ curl -fsSL --output pulumi_installer.sh https://get.pulumi.com/
|
||||
$ more pulumi_installer.sh
|
||||
$ sh ./pulumi_installer.sh
|
||||
```
|
||||
|
||||
同样,我们所希望的结果是在你的路径上有 `pulumi` 二进制。检查版本以确保你已经准备好了:
|
||||
|
||||
```
|
||||
pulumi version
|
||||
v2.5.0
|
||||
```
|
||||
|
||||
### 配置 Pulumi
|
||||
|
||||
在你开始配置任何基础设施之前,给 Pulumi 一个存储其[状态][22]的地方。
|
||||
|
||||
Pulumi 将其状态存储在后端。默认的后端是 Pulumi 的软件即服务(它有一个针对个人用户的免费计划),但在这个例子中,我使用替代的文件后端。文件后端将在你的本地文件系统上创建一个文件来存储状态:
|
||||
|
||||
```
|
||||
pulumi login --local
|
||||
```
|
||||
|
||||
如果你打算和别人分享这个项目,文件后台可能不是一个好的起点。Pulumi 还可以将其状态存储在 AWS S3 等云对象存储中。要使用它,请创建一个 S3 bucket 并登录:
|
||||
|
||||
```
|
||||
pulumi login --cloud-url s3://my-pulumi-state-bucket
|
||||
```
|
||||
|
||||
现在你已经登录到了状态后端,你可以创建一个项目和一个堆栈了!
|
||||
|
||||
在你开始创建 Pulumi 项目之前,请先了解以下 Pulumi 术语,你将在本教程中看到这些术语。
|
||||
|
||||
#### 项目
|
||||
|
||||
<ruby>[项目][23]<rt>project</rt></ruby>是一个包含 `Pulumi.yaml` 文件的目录。这个文件包含了 Pulumi 需要知道的元数据,以便进行它的工作。在 `Pulumi.yaml` 文件中可以找到的示例字段有:
|
||||
|
||||
* 运行时(例如,Python、Node、Go、.Net)
|
||||
* 项目说明(如“我的第一个 Pulumi 项目”)
|
||||
* 项目名称
|
||||
|
||||
项目是一个松散的概念,可以满足你的需求。一般来说,一个项目包含了一系列的*资源*,这些资源是你想要提供和控制的东西。你可以选择拥有资源很少的小型 Pulumi 项目,也可以选择包含所有你需要的资源的大型项目。随着你对 Pulumi 越来越熟悉,你想如何布局你的项目会变得更加清晰。
|
||||
|
||||
#### 堆栈
|
||||
|
||||
Pulumi <ruby>[堆栈][24]<rt>stack</rt></ruby>允许你根据可配置的值来区分你的 Pulumi 项目。一个常见的用途是将一个项目部署到不同的环境,如开发或生产环境,或不同的地区,如欧洲、中东和非洲以及美国。
|
||||
|
||||
在入门时,你不大需要一个复杂的堆栈设置,所以本演练使用默认的堆栈名称 `dev`。
|
||||
|
||||
### 在 IaC 中使用 TypeScript
|
||||
|
||||
你可以使用方便的 `pulumi new` 命令来<ruby>初建<rt>bootstrap</rt></ruby>一个 Pulumi 项目。`new` 命令有一大堆标志和选项,可以帮助你入门 Pulumi,所以请继续创建你的第一个项目:
|
||||
|
||||
```
|
||||
$ pulumi new typescript
|
||||
This command will walk you through creating a new Pulumi project.
|
||||
|
||||
Enter a value or leave blank to accept the (default), and press <ENTER>.
|
||||
Press ^C at any time to quit.
|
||||
|
||||
project name: (pulumi) my-first-project
|
||||
project description: (A minimal TypeScript Pulumi program) My very first Pulumi program
|
||||
Created project 'my-first-project'
|
||||
|
||||
Please enter your desired stack name.
|
||||
To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`).
|
||||
stack name: (dev) dev
|
||||
Created stack 'dev'
|
||||
|
||||
Installing dependencies...
|
||||
|
||||
|
||||
> node scripts/postinstall
|
||||
|
||||
added 82 packages from 126 contributors and audited 82 packages in 2.84s
|
||||
|
||||
13 packages are looking for funding
|
||||
run `npm fund` for details
|
||||
|
||||
found 0 vulnerabilities
|
||||
|
||||
Finished installing dependencies
|
||||
|
||||
Your new project is ready to go! ✨
|
||||
|
||||
To perform an initial deployment, run 'pulumi up'
|
||||
```
|
||||
|
||||
这里发生了很多事情,我将其展开来说:
|
||||
|
||||
第一部分是为你的 Pulumi 项目确定一个模板。我选择了通用的 `typescript` 选项,但是有[很多选项可供选择][25]。
|
||||
|
||||
这个 `new` 命令从你的模板库中抓取模板,并将这个文件复制到本地,包括运行时的依赖关系(在本例中是 `package.json`)。
|
||||
|
||||
`new` 命令通过在这个目录下运行 `npm install` 来安装这些依赖关系。然后 `npm install` 下载并安装运行 Pulumi 程序所需的一切,在这种情况下就是:`@pulumi/pulumi` NPM 包。
|
||||
|
||||
你已经准备好创建你的第一个资源了!
|
||||
|
||||
### 创建你的第一个云资源
|
||||
|
||||
资源是一个由你的基础设施供应软件生命周期进行管理的东西。资源一般是一个<ruby>云提供商对象<rt>cloud provider object</rt></ruby>,比如 S3 桶。Pulumi 的提供商处理 Pulumi 资源,提供商是具体的云提供商。Pulumi 有大约 [40 个提供商][26]可供你使用,但对于你的第一个资源,使用一个最简单的:<ruby>[随机提供商][27]<rt>random provider</rt></ruby>。
|
||||
|
||||
随机提供者顾名思义:它幂等地创建一个随机资源(例如,可以是一个字符串),并将其存储在 Pulumi 状态中。
|
||||
|
||||
使用 `npm` 将其添加到你的 Pulumi 项目中作为依赖关系:
|
||||
|
||||
```
|
||||
npm install @pulumi/random
|
||||
```
|
||||
|
||||
npm 包管理器下载并安装随机提供者包,并为你安装。现在你已经准备好编写你的 Pulumi 程序了。
|
||||
|
||||
当你之前生成你的项目时,Pulumi 的初建过程创建了一个 `index.ts` TypeScript 文件。在你喜欢的集成开发环境(IDE)中打开它,并添加你的第一个资源:
|
||||
|
||||
```
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as random from "@pulumi/random";
|
||||
|
||||
const password = new random.RandomString(`password`, {
|
||||
length: 10
|
||||
})
|
||||
```
|
||||
|
||||
如果你对 TypeScript 或 JavaScript 非常熟悉,这看起来会非常熟悉,因为它是用你熟悉的编程语言编写的。如果你使用的是 Pulumi 支持的其他语言之一,也是一样的。这里是之前的那个随机资源,但这次是用 Python 写的:
|
||||
|
||||
```
|
||||
import pulumi_random as random
|
||||
|
||||
password = random.RandomString("password", length=10)
|
||||
```
|
||||
|
||||
一个 Pulumi 项目目前只支持单一一种语言,但每个项目都可以引用其他语言编写的项目,这对于多语言团队的成员来说是一个很有用的技巧。
|
||||
|
||||
你已经编写了第一个 Pulumi 资源。现在你需要部署它。
|
||||
|
||||
离开编辑器,回到命令行。在你的项目目录下,运行 `pulumi up`,然后看着神奇的事情发生:
|
||||
|
||||
```
|
||||
pulumi up
|
||||
|
||||
Previewing update (dev):
|
||||
Type Name Plan
|
||||
+ pulumi:pulumi:Stack my-first-project-dev create
|
||||
+ └─ random:index:RandomString password create
|
||||
|
||||
Resources:
|
||||
+ 2 to create
|
||||
|
||||
Do you want to perform this update? yes
|
||||
Updating (dev):
|
||||
Type Name Status
|
||||
+ pulumi:pulumi:Stack my-first-project-dev created
|
||||
+ └─ random:index:RandomString password created
|
||||
|
||||
Resources:
|
||||
+ 2 created
|
||||
|
||||
Duration: 2s
|
||||
|
||||
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
|
||||
```
|
||||
|
||||
太好了,你有了第一个 Pulumi 资源! 虽然你可能很享受这种成就感,但不幸的是,这个随机资源并没有那么有用:它只是一个随机的字符串,你甚至看不到它是什么。先解决这部分问题。修改你之前的程序,在你创建的常量中加入 `export`:
|
||||
|
||||
```
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as random from "@pulumi/random";
|
||||
|
||||
export const password = new random.RandomString(`password`, {
|
||||
length: 10
|
||||
})
|
||||
```
|
||||
|
||||
重新运行 `pulumi up`,看看输出:
|
||||
|
||||
```
|
||||
pulumi up
|
||||
Previewing update (dev):
|
||||
Type Name Plan
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
|
||||
Outputs:
|
||||
+ password: {
|
||||
+ id : "&+r?{}J$J7"
|
||||
+ keepers : output<string>
|
||||
+ length : 10
|
||||
+ lower : true
|
||||
+ minLower : 0
|
||||
+ minNumeric : 0
|
||||
+ minSpecial : 0
|
||||
+ minUpper : 0
|
||||
+ number : true
|
||||
+ overrideSpecial: output<string>
|
||||
+ result : "&+r?{}J$J7"
|
||||
+ special : true
|
||||
+ upper : true
|
||||
+ urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
2 unchanged
|
||||
|
||||
Do you want to perform this update? yes
|
||||
Updating (dev):
|
||||
Type Name Status
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
|
||||
Outputs:
|
||||
+ password: {
|
||||
+ id : "&+r?{}J$J7"
|
||||
+ length : 10
|
||||
+ lower : true
|
||||
+ minLower : 0
|
||||
+ minNumeric: 0
|
||||
+ minSpecial: 0
|
||||
+ minUpper : 0
|
||||
+ number : true
|
||||
+ result : "&+r?{}J$J7"
|
||||
+ special : true
|
||||
+ upper : true
|
||||
+ urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
2 unchanged
|
||||
|
||||
Duration: 1s
|
||||
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
|
||||
```
|
||||
|
||||
现在你可以在 `Outputs` 的 `result` 部分下看到一个随机生成的字符串。你现在可以看到你创建的资源有很多属性。
|
||||
|
||||
这一切都很好,但如果你想享受 IaC,你得提供一些随机字符串以外的东西。试试吧。
|
||||
|
||||
### 部署一个容器
|
||||
|
||||
到目前为止,你已经通过安装依赖关系和注册一个简单的随机资源来 体验了初建你的 Pulumi。现在部署一些实际的基础设施,尽管是在你的本地机器上。
|
||||
|
||||
首先,将 `@pulumi/docker` 提供者添加到你的堆栈中。使用你选择的包管理器将其添加到项目中:
|
||||
|
||||
```
|
||||
npm install @pulumi/docker
|
||||
```
|
||||
|
||||
你已经从 `npm` 下拉了 Pulumi Docker 提供商包,这意味着你现在可以在你的项目中创建 Docker 镜像。
|
||||
|
||||
如果你的机器上还没有安装 Docker,现在是一个极好的时机去安装它。说明将取决于你的操作系统,所以看看 [Docker 的安装页面][28]了解信息。
|
||||
|
||||
再次打开你喜欢的 IDE,运行一个 Docker 容器。修改你之前的 `index.ts` 文件,让它看起来像这样:
|
||||
|
||||
```
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as random from "@pulumi/random";
|
||||
import * as docker from "@pulumi/docker";
|
||||
|
||||
const password = new random.RandomString(`password`, {
|
||||
length: 10
|
||||
})
|
||||
|
||||
const container = new docker.Container(`my-password`, {
|
||||
image: 'hashicorp/http-echo',
|
||||
command: [ pulumi.interpolate`-text=Your super secret password is: ${password.result}` ],
|
||||
ports: [{
|
||||
internal: 5678,
|
||||
external: 5678,
|
||||
}]
|
||||
})
|
||||
|
||||
export const id = container.id
|
||||
```
|
||||
|
||||
这将创建一个容器,创建一个 Web 服务器。Web 服务器的输出是你随机生成的字符串,在本例中是一个密码。运行这个,看看会发生什么:
|
||||
|
||||
```
|
||||
pulumi up
|
||||
|
||||
Previewing update (dev):
|
||||
Type Name Plan
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
+ └─ docker:index:Container my-password create
|
||||
|
||||
Outputs:
|
||||
+ id : output<string>
|
||||
~ password: {
|
||||
id : "&+r?{}J$J7"
|
||||
length : 10
|
||||
lower : true
|
||||
minLower : 0
|
||||
minNumeric: 0
|
||||
minSpecial: 0
|
||||
minUpper : 0
|
||||
number : true
|
||||
result : "&+r?{}J$J7"
|
||||
special : true
|
||||
upper : true
|
||||
urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
+ 1 to create
|
||||
2 unchanged
|
||||
|
||||
Do you want to perform this update? yes
|
||||
Updating (dev):
|
||||
Type Name Status
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
+ └─ docker:index:Container my-password created
|
||||
|
||||
Outputs:
|
||||
+ id : "e73b34aeca34a64b72b61b0b9b8438637ce28853937bc359a1528ca99f49ddda"
|
||||
password: {
|
||||
id : "&+r?{}J$J7"
|
||||
length : 10
|
||||
lower : true
|
||||
minLower : 0
|
||||
minNumeric: 0
|
||||
minSpecial: 0
|
||||
minUpper : 0
|
||||
number : true
|
||||
result : "&+r?{}J$J7"
|
||||
special : true
|
||||
upper : true
|
||||
urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
+ 1 created
|
||||
2 unchanged
|
||||
|
||||
Duration: 2s
|
||||
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
|
||||
```
|
||||
|
||||
你会注意到在 `Outputs` 部分,你输出的值已经改变了,它只是一个 Docker 容器 ID。检查你的非常简单的密码生成器是否工作:
|
||||
|
||||
```
|
||||
curl http://localhost:5678
|
||||
Your super secret password is: &+r?{}J$J7
|
||||
```
|
||||
|
||||
就是这样! 你刚刚用 TypeScript 配置了你的第一个基础架构。
|
||||
|
||||
#### 关于 Pulumi 输出的快速说明
|
||||
|
||||
你会注意到在创建 Docker 容器的代码中,它使用了一个特殊的 `pulumi.interpolate` 调用。如果你熟悉 TypeScript,你可能会好奇为什么需要这样做(因为它是 Pulumi 特有的)。这有一个有趣的原因。
|
||||
|
||||
当 Pulumi 创建一个资源时,直到程序执行时有一些值是 Pulumi 不知道的。在 Pulumi 中,这些值被称为 `Outputs`。这些 `Outputs` 可以在上面的代码中看到,例如,在你的第一个随机资源中,你使用 `export` 关键字来输出随机资源的属性,你还输出了你创建的容器的容器 ID。
|
||||
|
||||
因为 Pulumi 直到执行时才知道这些 `Outputs` 的值,所以在操作字符串时,它需要特殊的助手来使用它们。如果你想了解更多关于这个特殊的编程模型,请观看[这个短视频][29]。
|
||||
|
||||
### 总结
|
||||
|
||||
随着混合云基础架构中出现的复杂性,IaC 在很多方面都有了发展。在基础设施供应领域,Pulumi 是一个很好的选择,它可以使用你最喜欢的编程语言来供应你所需要的一切基础设施,然后你可以在你最喜欢的配置管理工具中进行标记,以采取下一步措施。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/8/infrastructure-as-code-pulumi
|
||||
|
||||
作者:[Lee Briggs][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/lbriggs
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/puzzle_computer_solve_fix_tool.png?itok=U0pH1uwj (Puzzle pieces coming together to form a computer screen)
|
||||
[2]: https://opensource.com/resources/devops
|
||||
[3]: https://git-scm.com/
|
||||
[4]: https://www.mercurial-scm.org/
|
||||
[5]: https://opensource.com/article/18/12/configuration-management-tools
|
||||
[6]: https://opensource.com/article/20/7/terraform-kubernetes
|
||||
[7]: https://www.pulumi.com/
|
||||
[8]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
|
||||
[9]: https://www.typescriptlang.org/
|
||||
[10]: https://golang.org/
|
||||
[11]: https://www.python.org/
|
||||
[12]: https://en.wikipedia.org/wiki/C_Sharp_(programming_language)
|
||||
[13]: https://www.pulumi.com/docs/intro/cloud-providers/aws/
|
||||
[14]: https://www.pulumi.com/docs/intro/cloud-providers/azure/
|
||||
[15]: https://www.pulumi.com/docs/intro/cloud-providers/gcp/
|
||||
[16]: https://www.pulumi.com/docs/reference/pkg/
|
||||
[17]: https://nodejs.org/en/download/
|
||||
[18]: https://brew.sh/
|
||||
[19]: https://opensource.com/article/20/6/homebrew-mac
|
||||
[20]: https://opensource.com/article/20/6/homebrew-linux
|
||||
[21]: https://www.pulumi.com/docs/get-started/install/
|
||||
[22]: https://www.pulumi.com/docs/intro/concepts/state/
|
||||
[23]: https://www.pulumi.com/docs/intro/concepts/project/
|
||||
[24]: https://www.pulumi.com/docs/intro/concepts/stack/
|
||||
[25]: https://github.com/pulumi/templates
|
||||
[26]: https://www.pulumi.com/docs/intro/cloud-providers/
|
||||
[27]: https://www.pulumi.com/docs/intro/cloud-providers/random/
|
||||
[28]: https://docs.docker.com/get-docker/
|
||||
[29]: https://www.youtube.com/watch?v=lybOxul2otM
|
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12860-1.html)
|
||||
[#]: subject: (Secure NTP with NTS)
|
||||
[#]: via: (https://fedoramagazine.org/secure-ntp-with-nts/)
|
||||
[#]: author: (Miroslav Lichvar https://fedoramagazine.org/author/mlichvar/)
|
||||
@ -10,13 +10,13 @@
|
||||
用 NTS 保证 NTP 的安全
|
||||
======
|
||||
|
||||
![][1]
|
||||
![](https://img.linux.net.cn/data/attachment/album/202011/26/111649pt32v9j22x3ooa33.jpg)
|
||||
|
||||
许多计算机使用<ruby>网络时间协议<rt>Network Time Protocol</rt></ruby>(NTP)通过互联网同步系统时钟。NTP 是少数几个仍在普遍使用的不安全的互联网协议之一。攻击者如果能够观察到客户端和服务器之间的网络流量,就可以向客户端提供虚假的数据,并根据客户端的实现和配置,强迫其将系统时钟设置为任何时间和日期。如果客户端的系统时钟不准确,一些程序和服务可能无法工作。例如,如果根据客户端的系统时钟,Web 服务器的证书似乎已经过期,Web 浏览器将无法正常工作。可以使用<ruby>网络时间安全<rt>Network Time Security</rt></ruby>(NTS)来保证 NTP 的安全。
|
||||
许多计算机使用<ruby>网络时间协议<rt>Network Time Protocol</rt></ruby>(NTP)通过互联网来同步系统时钟。NTP 是少数几个仍在普遍使用的不安全的互联网协议之一。攻击者如果能够观察到客户端和服务器之间的网络流量,就可以向客户端提供虚假的数据,并根据客户端的实现和配置,强迫其将系统时钟设置为任何时间和日期。如果客户端的系统时钟不准确,一些程序和服务就可能无法工作。例如,如果根据客户端的系统时钟,Web 服务器的证书似乎已经过期,Web 浏览器将无法正常工作。可以使用<ruby>网络时间安全<rt>Network Time Security</rt></ruby>(NTS)来保证 NTP 的安全。
|
||||
|
||||
Fedora 33 [^1] 是第一个支持 NTS 的 Fedora 版本。NTS 是一种新的 NTP 验证机制。它使客户端能够验证他们从服务器接收的数据包在传输过程中有没有被修改。当 NTS 启用时,攻击者唯一能做的就是丢弃或延迟数据包。关于 NTS 的更多细节,请参见 [RFC8915][3]。
|
||||
Fedora 33 [^1] 是第一个支持 NTS 的 Fedora 版本。NTS 是一种新的 NTP 验证机制。它使客户端能够验证它们从服务器接收的数据包在传输过程中有没有被修改。当 NTS 启用时,攻击者唯一能做的就是丢弃或延迟数据包。关于 NTS 的更多细节,请参见 [RFC8915][3]。
|
||||
|
||||
使用对称密钥可以很好地保证 NTP 的安全。遗憾的是,服务器必须为每个客户端配备不同的密钥,而且密钥必须安全地分发。这对于本地网络上的私有服务器来说可能是实用的,但它不能扩展到有着数百万客户端的公共服务器上。
|
||||
使用对称密钥可以很好地保证 NTP 的安全。遗憾的是,服务器必须为每个客户端配备不同的密钥,而且密钥必须安全地分发才行。这对于本地网络上的私有服务器来说可能是实用的,但它不能扩展到有着数百万客户端的公共服务器上。
|
||||
|
||||
NTS 包括一个<ruby>密钥建立<rt>Key Establishment</rt></ruby>(NTS-KE)协议,它可以自动创建服务器与其客户端之间使用的加密密钥。它在 TCP 端口 4460 上使用<ruby>传输层安全<rt>Transport Layer Security</rt></ruby>(TLS)。它被设计成可以扩展到非常多的客户端,而对准确性的影响最小。服务器不需要保存任何客户端特定的状态。它为客户提供 cookie,cookie 是加密的,包含验证 NTP 数据包所需的密钥。隐私是 NTS 的目标之一。客户端在每次服务器响应时都会得到一个新的 cookie,所以它不必重复使用 cookie。这可以防止被动观察者跟踪在网络之间迁移的客户端。
|
||||
|
||||
@ -30,7 +30,7 @@ Fedora 中默认的 NTP 客户端是 Chrony。Chrony 在 4.0 版本中增加了
|
||||
|
||||
### 在安装程序中启用客户端 NTS
|
||||
|
||||
安装 Fedora 33 时,你可以在“Network Time”配置的“Time & Date”对话框中启用 NTS。在点击“+”(添加)按钮之前,请输入服务器的名称并检查 NTS 支持情况。你可以添加一个或多个具有 NTS 的服务器或池。要删除默认的服务器池(`2.fedora.pool.ntp.org`),请取消选中“Use”列中的相应标记。
|
||||
安装 Fedora 33 时,你可以在“Time & Date”对话框的“Network Time”配置中启用 NTS。在点击“+”(添加)按钮之前,请输入服务器的名称并检查 NTS 支持情况。你可以添加一个或多个具有 NTS 的服务器或池。要删除默认的服务器池(`2.fedora.pool.ntp.org`),请取消选中“Use”列中的相应标记。
|
||||
|
||||
![Fedora 安装程序中的网络时间配置][7]
|
||||
|
||||
@ -92,13 +92,13 @@ MS Name/IP address Stratum Poll Reach LastRx Last sample
|
||||
^+ nts.sth2.ntp.se 1 6 377 44 -170us[ -170us] +/- 22ms
|
||||
```
|
||||
|
||||
`Reach` 列应该有一个非零值,最好是 377。上图所示的值 377 是一个八进制数,它表示最后八个请求都有有效的响应。如果启用了 NTS 的话,验证检查将包括 NTS 认证。如果该值一直很少或从未达到 377,则表明 NTP 请求或响应在网络中丢失了。众所周知,一些主要的网络运营商有中间机器,它可以阻止或限制大的 NTP 数据包的速率,以缓解利用 `ntpd` 的监控协议进行的放大攻击。不幸的是,这影响了受 NTS 保护的 NTP 数据包,尽管它们不会引起任何放大。NTP 工作组正在考虑为 NTP 提供一个替代端口,作为解决这个问题的办法。
|
||||
`Reach` 列应该有一个非零值,最好是 377。上图所示的值 377 是一个八进制数,它表示最后八个请求都有有效的响应。如果启用了 NTS 的话,验证检查将包括 NTS 认证。如果该值一直很少或从未达到 377,则表明 NTP 请求或响应在网络中丢失了。众所周知,一些主要的网络运营商有中间设备,它可以阻止或限制大的 NTP 数据包的速率,以缓解利用 `ntpd` 的监控协议进行的放大攻击。不幸的是,这影响了受 NTS 保护的 NTP 数据包,尽管它们不会引起任何放大。NTP 工作组正在考虑为 NTP 提供一个替代端口,作为解决这个问题的办法。
|
||||
|
||||
### 在服务器上启用 NTS
|
||||
|
||||
如果你有自己的 NTP 服务器,运行着 `chronyd`,你可以启用服务器的 NTS 支持,让它的客户端安全同步。如果该服务器是其他服务器的客户端,它应该使用 NTS 或对称密钥与之同步。客户端假设同步链在所有服务器到主时间服务器之间是安全的。
|
||||
|
||||
启用服务器 NTS 类似于在 Web 服务器上启用HTTPS。你只需要一个私钥和证书。例如,证书可以由 Let's Encrypt 权威机构使用 `certbot` 工具签署。当你有了密钥和证书文件(包括中间证书),在 `chrony.conf` 中用以下指令指定它们:
|
||||
启用服务器 NTS 类似于在 Web 服务器上启用 HTTPS。你只需要一个私钥和证书。例如,证书可以由 Let's Encrypt 权威机构使用 `certbot` 工具签署。当你有了密钥和证书文件(包括中间证书),在 `chrony.conf` 中用以下指令指定它们:
|
||||
|
||||
```
|
||||
ntsserverkey /etc/pki/tls/private/foo.example.net.key
|
||||
@ -152,7 +152,7 @@ via: https://fedoramagazine.org/secure-ntp-with-nts/
|
||||
作者:[Miroslav Lichvar][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
90
published/20201106 Reclaim hard-drive space with LVM.md
Normal file
90
published/20201106 Reclaim hard-drive space with LVM.md
Normal file
@ -0,0 +1,90 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12864-1.html)
|
||||
[#]: subject: (Reclaim hard-drive space with LVM)
|
||||
[#]: via: (https://fedoramagazine.org/reclaim-hard-drive-space-with-lvm/)
|
||||
[#]: author: (Troy Curtis Jr https://fedoramagazine.org/author/troycurtisjr/)
|
||||
|
||||
使用 LVM 扩展卷空间
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202011/27/193719d3df4p4z748f33f3.jpg)
|
||||
|
||||
LVM 是一个逻辑卷管理工具,包括分配磁盘、条带化、镜像和调整逻辑卷的大小。它在 Fedora 安装中被普遍使用(在 BTRFS 作为默认文件系统之前是 LVM + Ext4)。但是你是否曾经遇到过启动系统时,GNOME 提示 home 卷几乎没有空间了!幸运的是,很有可能有一些空间在另一个卷中,而未被使用,可以用于重新分配。下面就来看看如何用 LVM 回收硬盘空间。
|
||||
|
||||
在卷之间轻松重新分配空间的关键是[逻辑卷管理器(LVM)][2]。Fedora 32 及以前的系统默认使用 LVM 来划分磁盘空间。这种技术类似于标准的硬盘分区,但 LVM 更加灵活。LVM 不仅可以实现灵活的卷大小管理,还可以实现一些高级功能,比如读写快照、在多个硬盘上进行数据条带化或镜像、将高速硬盘作为慢速硬盘的缓存等等。所有这些高级选项可能会让人有点不知所措,但调整卷的大小很简单的。
|
||||
|
||||
### LVM 基础
|
||||
|
||||
**卷组**(VG)作为 LVM 系统中的主要容器。默认情况下,Fedora 只定义了一个卷组,但你可以根据需要定义多个卷组。实际的硬盘和硬盘分区被添加到卷组中作为**物理卷**(PV)。物理卷会将可用的空间添加到卷组中。一个典型的 Fedora 安装有一个格式化的启动分区,其余的硬盘是一个配置为 LVM 物理卷的分区。
|
||||
|
||||
从这个可用空间池中,卷组分配了一个或多个**逻辑卷**(LV)。这些卷类似于硬盘分区,但没有磁盘上连续空间的限制。LVM 的逻辑卷甚至可以跨越多个设备!就像硬盘分区一样,逻辑卷有一个定义的大小,可以包含任何文件系统,然后可以挂载到特定的目录。
|
||||
|
||||
### 需要什么
|
||||
|
||||
在 gnome-disks 应用中确认系统使用 LVM ,并确保其他卷中有可用的空间。如果没有可以从另一个卷中回收的空间,这个指南就没有用。还需要一个 [Fedora 临场 CD/USB][3]。任何需要收缩的文件系统都必须卸载。从<ruby>临场<rt>Live</rt></ruby>镜像运行,可以让硬盘上的所有卷保持未挂载状态,甚至包括像 `/` 和 `/home` 这样的重要目录。
|
||||
|
||||
![Use gnome-disks to verify free space][4]
|
||||
|
||||
### 一句话警告
|
||||
|
||||
按照这个指南,应该不会丢失任何数据,但它确实会使用一些非常底层和强大的命令。一个错误可能会破坏硬盘上的所有数据。所以要先备份磁盘上的所有数据!
|
||||
|
||||
### 调整 LVM 卷的大小
|
||||
|
||||
开始时,启动 Fedora 临场镜像并在对话框中选择 “Try Fedora”。接下来,使用 “Run Command” 启动 “blivet-gui” 应用(按 `Alt-F2`,输入 `blivet-gui`,然后按回车)。选择左侧 “LVM” 下的卷组。逻辑卷在右边。
|
||||
|
||||
![Explore logical volumes in blivet-gui][5]
|
||||
|
||||
逻辑卷标签由卷组名称和逻辑卷名称组成。在本例中,卷组是 `fedora_localhost-live`,分配了 `home`、`root` 和 `swap` 逻辑卷。要找到完整的卷,选择每一个卷,点击“齿轮”图标,然后选择 “resize”。调整大小对话框中的滑块表示卷的允许大小。左边的最小值是文件系统中已经使用的空间,所以这是最小可能的尺寸大小(不删除数据)。右边的最大值是基于卷组中的最大可用空间。
|
||||
|
||||
![Resize dialog in blivet-gui][6]
|
||||
|
||||
灰色的 “resize” 选项意味着该卷已经满了,而且卷组中没有可用空间。
|
||||
|
||||
现在可以更改大小了!查看所有的卷,就像上面的截图那样,找到一个有足够空间的卷。并像上面的截图那样,在所有的卷中找到一个有大量额外空间的卷。向左移动滑块来设置新的大小。腾出足够的空间对整个卷有用,但仍然要为未来的数据增长留出足够的空间。否则,这个卷将是下一个被填满的卷。
|
||||
|
||||
点击 “resize”,注意卷列表中出现了一个新项目:“free space”。现在选择这次要调整的卷,并将滑块一直向右移动。按 “resize” 键,并查看新改进的卷的布局。然而,硬盘驱动器上的任何东西现在都还没有改变。点击“勾选”选项将更改提交到磁盘。
|
||||
|
||||
![Review changes in blivet-gui][7]
|
||||
|
||||
查看更改的摘要,如果一切看起来都是正确的,点击 “Ok” 继续。等待 “blivet-gui” 完成。现在重新启动回到 Fedora,可以使用之前被充满的卷上的新空间了。
|
||||
|
||||
### 为未来计划
|
||||
|
||||
要知道任何特定卷在未来需要多少空间是很困难的。与其立即分配所有可用的空闲空间,不如考虑在卷组中留出空闲空间。事实上,Fedora Server 默认在卷组中保留空间。当一个卷处于在线和使用中时,扩展卷是可能的。不需要临场镜像或重启。当一个卷几乎满的时候,可以使用部分可用空间轻松扩展卷并继续工作。遗憾的是,默认的磁盘管理器 gnome-disks 不支持 LVM 卷的大小调整,所以安装 [blivet-gui][8] 作为图形化管理工具。另外,还有一个简单的终端命令来扩展卷:
|
||||
|
||||
```
|
||||
lvresize -r -L +1G /dev/fedora_localhost-live/root
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
用 LVM 回收硬盘空间只是 LVM 功能的表面。大多数人,特别是在桌面中,可能不需要更高级的功能。然而,当需要的时候,LVM 就在那里,尽管它的实现可能会变得有点复杂。从 [Fedora 33][10] 开始,[BTRFS][9] 是默认的文件系统,没有 LVM。BTRFS 可以更容易管理,同时对于大多数常见的使用来说也足够灵活。查看最近 [Fedora Magazine 关于 BTRFS 的文章][11]了解更多。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/reclaim-hard-drive-space-with-lvm/
|
||||
|
||||
作者:[Troy Curtis Jr][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/troycurtisjr/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2020/11/lvm-resize-816x345.jpg
|
||||
[2]: http://sourceware.org/lvm2/
|
||||
[3]: https://getfedora.org/en/workstation/download/
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2020/11/gnome-disks.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2020/11/blivet-overview.png
|
||||
[6]: https://fedoramagazine.org/wp-content/uploads/2020/11/blivet-resize-1024x525.png
|
||||
[7]: https://fedoramagazine.org/wp-content/uploads/2020/11/blivet-summary-1024x525.png
|
||||
[8]: https://fedoraproject.org/wiki/Blivet-gui
|
||||
[9]: https://fedoramagazine.org/btrfs-coming-to-fedora-33/
|
||||
[10]: https://fedoramagazine.org/whats-new-fedora-33-workstation/
|
||||
[11]: https://fedoramagazine.org/btrfs-snapshots-backup-incremental/
|
@ -0,0 +1,87 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Got something to say? How to get started writing)
|
||||
[#]: via: (https://opensource.com/article/20/11/how-write-article)
|
||||
[#]: author: (Jen Wike Huger https://opensource.com/users/jen-wike)
|
||||
|
||||
Got something to say? How to get started writing
|
||||
======
|
||||
A community manager and editor shares her inspiration and tips for
|
||||
finding and sharing your expertise with others.
|
||||
![A person writing.][1]
|
||||
|
||||
Well, I suppose after all this talk of how to find your story and then write your story, I should make a post about how to do just that. I've broken it down into three sections: how to find your story, how to write your story, and how to share it and get it published.
|
||||
|
||||
During the All Things Open virtual event this year, I was invited to share my tips, and now you can watch that. It's about 20 minutes with some questions and commentary at the end.
|
||||
|
||||
You may have a clear reason why you want to write, or you may need some prodding. My belief is that we all have something valuable to share. Really. And the reasons are made clear in the survey answers in [this document][2]. One reason that resonates with many in the tech world is "because my manager wants me to," which could lead to a promotion or increased thought leadership in your field. Another great one for those working on an open source project is, "it is an act of giving back to the community... with the simultaneous goal of getting your name out in the community and building connections for other career opportunities."
|
||||
|
||||
### How to find your story
|
||||
|
||||
Do your homework, but this time hopefully it's a bit more fun and a bit less time-consuming. By all means, take the afternoon or the week to complete [this worksheet][3], but if you have an hour during work, this can fit into your busy schedule. Although I'm happy to take a look and help guide you once you get started, no one is grading your responses. They're yours, and their only goal is to get you closer to that elusive article. Whether it's your first, or your 100th, we all have reasons why it can be difficult to write.
|
||||
|
||||
The [worksheet][3] asks a variety of questions in a "choose your own adventure" type way. You can answer all of the questions, or skip to the parts that interest you most. It starts with asking:
|
||||
|
||||
* What do you do at your job?
|
||||
* What are you passionate about?
|
||||
* What communities are you or do you want to be a part of?
|
||||
|
||||
|
||||
|
||||
After you complete the worksheet to your liking, take a break. A few minutes, a few hours or days, and go back to it. What jumps off the page and still rings true? Perhaps it's now plainly obvious what your article should be about. If you still need a way to prioritize your choices, label each one with one of these time-based categories:
|
||||
|
||||
* Easy to write (you know this topic backward and forwards)
|
||||
* Quick to write (explaining is fast and a short read)
|
||||
* Hard to write (you may need to think through the process and list out many details)
|
||||
* Time-consuming to write (this may take some additional research in addition to being highly detailed)
|
||||
|
||||
|
||||
|
||||
### How to write an article
|
||||
|
||||
First, sit down and make yourself write an outline. I know, I know... boring! But this can save you a lot of time. Once you've landed on an outline that works for you and your topic, once you sit down and start writing, there's a better chance you'll get into the flow, following your outline, and knock it out in less time than you imagined. And in an amount of time that feels good to you and gives you a good feeling about writing, especially again and again.
|
||||
|
||||
Then, share it with a friend or an editor. Friends can be a quick and easy outlet, especially if they are of the writer sort. And, I encourage you to send it to an editor if you have a particular publication in mind for where you'd like to try to get it published. While you wait, buff up on your writing by taking a look at [a solid style guide][4].
|
||||
|
||||
Once you get to a place where you feel ready to get writing, review the format of an article and identify who your audience is. The format of an introduction that describes what the article is about and what the reader will learn, the body of the article focused on walking the reader logically through the steps or phases with straightforward headers, and a conclusion that gives final thoughts and a summary.
|
||||
|
||||
I like to write using a shareable document for easy collaboration and editing with others and editors.
|
||||
|
||||
### How to get your article published
|
||||
|
||||
First, decide whether you want to self-publish, on your own blog or a place like Medium, or if you want to get your article published on a publication like Opensource.com or Linux Today.
|
||||
|
||||
If you're reaching out to a publication, try to find information about how they would like you to submit your article. Some have webforms, some want you to simply send them an email. Some, like us, [have both][5]. Let them know who you are, what you wrote about, and perhaps why you wrote about it.
|
||||
|
||||
For example: My name is Jen Wike Huger. I'm a community manager and editor for Opensource.com, so my expertise is writing and working with authors. My article is about how to find your story, writing, and getting published.
|
||||
|
||||
### Wrapping up
|
||||
|
||||
The slide deck, worksheet, survey answers, and style guides for writing are [on GitHub][6].
|
||||
|
||||
The slides are from the All Things Open presentation. The worksheet is to help you decide what to write about, to find your story. The survey answers will inspire you and answer the question: Why should I write about what I know anyway? And the style guides will help you before and during the actual writing process, covering grammar, formatting, and more.
|
||||
|
||||
There are a ton more details baked into every part of this, so if you have specific questions, I welcome them in the comments, via email, or on Twitter.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/11/how-write-article
|
||||
|
||||
作者:[Jen Wike Huger][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://opensource.com/users/jen-wike
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003784_02_os.comcareers_resume_rh1x.png?itok=S3HGxi6E (A person writing.)
|
||||
[2]: https://github.com/JenWike/getpublished/blob/main/Why%20write_.txt
|
||||
[3]: https://github.com/JenWike/getpublished/blob/main/Worksheet_%20How%20to%20find%20your%20story.odt
|
||||
[4]: https://github.com/JenWike/getpublished/blob/main/styleguides
|
||||
[5]: https://opensource.com/how-submit-article
|
||||
[6]: https://github.com/JenWike/getpublished/
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,472 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Use your favorite programming language to provision Infrastructure as Code)
|
||||
[#]: via: (https://opensource.com/article/20/8/infrastructure-as-code-pulumi)
|
||||
[#]: author: (Lee Briggs https://opensource.com/users/lbriggs)
|
||||
|
||||
Use your favorite programming language to provision Infrastructure as Code
|
||||
======
|
||||
Provision everything you need to get your infrastructure off the ground
|
||||
with Node.js or another programming language.
|
||||
![Puzzle pieces coming together to form a computer screen][1]
|
||||
|
||||
As you navigate the world of IT and technology, there are some terms you come across repeatedly. Some of them are hard to quantify and may take on different meanings as time goes on. ["DevOps"][2] is an example of a word that seems (to me) to change depending on the person using it; the original DevOps pioneers might not even recognize what we call DevOps today.
|
||||
|
||||
If you're a software developer, "Infrastructure as Code" (IaC) may be one of those terms. IaC is using the same software-development practices you'd use to write user-facing features to declare the infrastructure that applications run on. This often means using tools like [Git][3] or [Mercurial][4] for version control and Puppet, Chef, or Ansible for [configuration management][5]. At the infrastructure-provisioning layer, the most common technology is CloudFormation (for AWS specifically) or [Terraform][6] as an open source alternative for creating hybrid-cloud resources for your applications to run on.
|
||||
|
||||
There are great options in the configuration-management space to write IaC as either configuration files or preferred programming languages, but this choice is not well-known in the infrastructure-provisioning space.
|
||||
|
||||
[Pulumi][7] offers an option to use standard programming languages to define infrastructure. It supports an array of languages, including [JavaScript][8], [TypeScript][9], [Go][10], [Python][11] and [C#][12]. Much like Terraform, Pulumi has first-class support for many familiar cloud providers, like [AWS][13], [Azure][14], [Google Cloud][15], and [other providers][16].
|
||||
|
||||
In this article, I'll show you how to use Pulumi to write infrastructure in Node.js.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
First, make sure you're ready to use Pulumi. Pulumi supports all major operating systems, so the methods you use to install its prerequisites depend on the operating system you're using.
|
||||
|
||||
First, install the interpreter for your preferred programming language. I'll be using TypeScript, so I need to install the `node` binary. Consult Node's [installation instructions][17] for information about your operating system. You can use [Homebrew][18] on [Mac][19] or [Linux][20] to install:
|
||||
|
||||
|
||||
```
|
||||
`brew install node`
|
||||
```
|
||||
|
||||
On Linux, you can alternately use your usual package manager, such as **apt** or **dnf**:
|
||||
|
||||
|
||||
```
|
||||
`$ sudo dnf install nodejs`
|
||||
```
|
||||
|
||||
In either case, the result should be that the `node` binary is available in your `$PATH`. To confirm it's accessible, run:
|
||||
|
||||
|
||||
```
|
||||
`node --version`
|
||||
```
|
||||
|
||||
Next, install the Pulumi command-line interface (CLI). You can find operating system-specific [installation instructions][21] in Pulumi's docs. With `brew` on a Mac or Linux:
|
||||
|
||||
|
||||
```
|
||||
`brew install pulumi`
|
||||
```
|
||||
|
||||
Alternately, you can use the install script. First download it and review it, and then execute it:
|
||||
|
||||
|
||||
```
|
||||
$ curl -fsSL --output pulumi_installer.sh \
|
||||
<https://get.pulumi.com/>
|
||||
$ more pulumi_installer.sh
|
||||
$ sh ./pulumi_installer.sh
|
||||
```
|
||||
|
||||
Again, the desired result is to have the `pulumi` binary available in your path. Check the version to make sure you're ready to proceed:
|
||||
|
||||
|
||||
```
|
||||
pulumi version
|
||||
v2.5.0
|
||||
```
|
||||
|
||||
### Configure Pulumi
|
||||
|
||||
Before you start provisioning any infrastructure, give Pulumi somewhere to store its [state][22].
|
||||
|
||||
Pulumi stores its state in a backend. The default backend is Pulumi's software-as-a-service (which has a free plan for individual users), but for this example, use the alternative file backend. The file backend will create a file on your local filesystem to store the state with:
|
||||
|
||||
|
||||
```
|
||||
`pulumi login --local`
|
||||
```
|
||||
|
||||
If you're planning on sharing this project with someone else, the file backend might not be a good starting point. Pulumi can also store its state in a cloud object store like AWS S3. To use it, create an S3 bucket and log in:
|
||||
|
||||
|
||||
```
|
||||
`pulumi login --cloud-url s3://my-pulumi-state-bucket`
|
||||
```
|
||||
|
||||
Now that you've logged into a state backend, you can create a project and a stack!
|
||||
|
||||
Before you start creating a Pulumi project, get to know the following Pulumi terminology, which you'll see in this tutorial.
|
||||
|
||||
#### Project
|
||||
|
||||
A [project][23] is a directory that contains a Pulumi.yaml file. This file contains metadata Pulumi needs to know to do its thing. Example fields you'll find in a Pulumi.yaml file are:
|
||||
|
||||
* The runtime (e.g., Python, Node, Go, .Net)
|
||||
* A description of the project (e.g., "my first Pulumi project")
|
||||
* A name for the project
|
||||
|
||||
|
||||
|
||||
A project is a loosely defined concept that can fit your needs. Generally, a project contains a bunch of _resources_, which are things you want to provision and control. You might choose to have small Pulumi projects with very few resources or large projects that contain all the resources you need. As you become more familiar with Pulumi, it'll become more apparent how you want to lay out your projects.
|
||||
|
||||
#### Stack
|
||||
|
||||
A Pulumi [stack][24] allows you to differentiate your Pulumi projects depending on configurable values. A common use is to deploy a project to different environments like development or production or different regions like Europe, the Middle East and Africa, and the US.
|
||||
|
||||
When getting started, you're not likely to need a complex stack setup, so this walkthrough uses the default stack name, `dev`.
|
||||
|
||||
### Use TypeScript for IaC
|
||||
|
||||
You can bootstrap a Pulumi project using the handy `pulumi new` command. The `new` command has a whole host of flags and options that should help you get started with Pulumi, so go ahead and create your first project:
|
||||
|
||||
|
||||
```
|
||||
$ pulumi new typescript
|
||||
This command will walk you through creating a new Pulumi project.
|
||||
|
||||
Enter a value or leave blank to accept the (default), and press <ENTER>.
|
||||
Press ^C at any time to quit.
|
||||
|
||||
project name: (pulumi) my-first-project
|
||||
project description: (A minimal TypeScript Pulumi program) My very first Pulumi program
|
||||
Created project 'my-first-project'
|
||||
|
||||
Please enter your desired stack name.
|
||||
To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`).
|
||||
stack name: (dev) dev
|
||||
Created stack 'dev'
|
||||
|
||||
Installing dependencies...
|
||||
|
||||
> node scripts/postinstall
|
||||
|
||||
added 82 packages from 126 contributors and audited 82 packages in 2.84s
|
||||
|
||||
13 packages are looking for funding
|
||||
run `npm fund` for details
|
||||
|
||||
found 0 vulnerabilities
|
||||
|
||||
Finished installing dependencies
|
||||
|
||||
Your new project is ready to go! ✨
|
||||
|
||||
To perform an initial deployment, run 'pulumi up'
|
||||
```
|
||||
|
||||
A lot happened here, so I'll break it down:
|
||||
|
||||
The first part identifies a template for your Pulumi project. I chose the generic `typescript` option, but there are [many options available][25].
|
||||
|
||||
This `new` command grabbed the template from your templates repository and copied this file locally, including the runtime dependencies (in this case, `package.json`).
|
||||
|
||||
The `new` command took care of installing those dependencies by running `npm install` inside this directory. Then `npm install` downloaded and installed everything needed to run your Pulumi program, which, in this case, is very straightforward: the `@pulumi/pulumi` NPM package.
|
||||
|
||||
You're ready to create your very first resource!
|
||||
|
||||
### Create your first cloud resource
|
||||
|
||||
A resource is a thing that is managed by your infrastructure-provisioning software lifecycle. Resources are generally a cloud provider object, like an S3 bucket. Pulumi providers handle Pulumi resources, and providers are specific to the cloud provider they manage. Pulumi has around [40 providers][26] you can use, but for your first resource, use one of the simplest—the [random provider][27].
|
||||
|
||||
The random provider does what the name suggests: it idempotently creates a random resource (which could be a string, for example) and stores it in the Pulumi state.
|
||||
|
||||
Add this as a dependency to your Pulumi project using npm:
|
||||
|
||||
|
||||
```
|
||||
`npm install @pulumi/random`
|
||||
```
|
||||
|
||||
The npm package manager downloads and installs the random provider package and installs it for you. Now you're ready to write your Pulumi program.
|
||||
|
||||
When you generated your project earlier, Pulumi's bootstrap process created an `index.ts` TypeScript file. Open it in your favorite integrated development environment (IDE) and add your first resource:
|
||||
|
||||
|
||||
```
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as random from "@pulumi/random";
|
||||
|
||||
const password = new random.RandomString(`password`, {
|
||||
length: 10
|
||||
})
|
||||
```
|
||||
|
||||
If you're at all familiar with TypeScript or JavaScript, this will look very familiar because it's written in a programming language you know. This also applies if you're using one of Pulumi's other supported languages. Here's that same random resource from before, but this time in Python:
|
||||
|
||||
|
||||
```
|
||||
import pulumi_random as random
|
||||
|
||||
password = random.RandomString("password", length=10)
|
||||
```
|
||||
|
||||
Pulumi projects currently support only a single language, but each project can reference other projects written in other languages—a useful trick for members of the polyglot team.
|
||||
|
||||
You've written your first Pulumi resource. Now you need to deploy it.
|
||||
|
||||
Leave your editor and head back to the command line. From your project directory, run `pulumi up` and watch the magic happen:
|
||||
|
||||
|
||||
```
|
||||
pulumi up
|
||||
|
||||
Previewing update (dev):
|
||||
Type Name Plan
|
||||
+ pulumi:pulumi:Stack my-first-project-dev create
|
||||
+ └─ random:index:RandomString password create
|
||||
|
||||
Resources:
|
||||
+ 2 to create
|
||||
|
||||
Do you want to perform this update? yes
|
||||
Updating (dev):
|
||||
Type Name Status
|
||||
+ pulumi:pulumi:Stack my-first-project-dev created
|
||||
+ └─ random:index:RandomString password created
|
||||
|
||||
Resources:
|
||||
+ 2 created
|
||||
|
||||
Duration: 2s
|
||||
|
||||
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
|
||||
```
|
||||
|
||||
Excellent, you have your first Pulumi resource! While you might be enjoying this sense of achievement, unfortunately, this random resource isn't that useful—it's just a random string, and you can't even see what it is. Address that part first: Modify your earlier program and add `export` to the constant you created:
|
||||
|
||||
|
||||
```
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as random from "@pulumi/random";
|
||||
|
||||
export const password = new random.RandomString(`password`, {
|
||||
length: 10
|
||||
})
|
||||
```
|
||||
|
||||
Rerun `pulumi up` and look at the output:
|
||||
|
||||
|
||||
```
|
||||
pulumi up
|
||||
Previewing update (dev):
|
||||
Type Name Plan
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
|
||||
Outputs:
|
||||
+ password: {
|
||||
+ id : "&+r?{}J$J7"
|
||||
+ keepers : output<string>
|
||||
+ length : 10
|
||||
+ lower : true
|
||||
+ minLower : 0
|
||||
+ minNumeric : 0
|
||||
+ minSpecial : 0
|
||||
+ minUpper : 0
|
||||
+ number : true
|
||||
+ overrideSpecial: output<string>
|
||||
+ result : "&+r?{}J$J7"
|
||||
+ special : true
|
||||
+ upper : true
|
||||
+ urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
2 unchanged
|
||||
|
||||
Do you want to perform this update? yes
|
||||
Updating (dev):
|
||||
Type Name Status
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
|
||||
Outputs:
|
||||
+ password: {
|
||||
+ id : "&+r?{}J$J7"
|
||||
+ length : 10
|
||||
+ lower : true
|
||||
+ minLower : 0
|
||||
+ minNumeric: 0
|
||||
+ minSpecial: 0
|
||||
+ minUpper : 0
|
||||
+ number : true
|
||||
+ result : "&+r?{}J$J7"
|
||||
+ special : true
|
||||
+ upper : true
|
||||
+ urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
2 unchanged
|
||||
|
||||
Duration: 1s
|
||||
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
|
||||
```
|
||||
|
||||
Now you can see a randomly generated string under the `result` section of the `Outputs`. The resource you created has a number of properties that you can see now.
|
||||
|
||||
This is all well and good, but if you want to enjoy IaC, you're going to have to provision something other than a random string. Give it a try!
|
||||
|
||||
### Deploy a container
|
||||
|
||||
So far, you've bootstrapped your Pulumi experience by installing dependencies and registered a simple random resource. Now deploy some actual infrastructure, albeit to your local machine.
|
||||
|
||||
First, add the `@pulumi/docker` provider to your stack. Use your chosen package manager to add it to the project:
|
||||
|
||||
|
||||
```
|
||||
`npm install @pulumi/docker`
|
||||
```
|
||||
|
||||
You've pulled down the Pulumi Docker provider package from npm, which means you can now create Docker images in your project.
|
||||
|
||||
If you don't have Docker installed on your machine, now is an excellent time to get it. Instructions will depend on your operating system, so take a look at [Docker's installation page][28] for information.
|
||||
|
||||
Open up your favorite IDE again and run a Docker container. Modify your `index.ts` file from earlier to make it look like this:
|
||||
|
||||
|
||||
```
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as random from "@pulumi/random";
|
||||
import * as docker from "@pulumi/docker";
|
||||
|
||||
const password = new random.RandomString(`password`, {
|
||||
length: 10
|
||||
})
|
||||
|
||||
const container = new docker.Container(`my-password`, {
|
||||
image: 'hashicorp/http-echo',
|
||||
command: [ pulumi.interpolate`-text=Your super secret password is: ${password.result}` ],
|
||||
ports: [{
|
||||
internal: 5678,
|
||||
external: 5678,
|
||||
}]
|
||||
})
|
||||
|
||||
export const id = container.id
|
||||
```
|
||||
|
||||
This creates a container that creates a web server. The output of the web server is your randomly generated string, in this case, a password. Run this and see what happens:
|
||||
|
||||
|
||||
```
|
||||
pulumi up
|
||||
|
||||
Previewing update (dev):
|
||||
Type Name Plan
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
+ └─ docker:index:Container my-password create
|
||||
|
||||
Outputs:
|
||||
+ id : output<string>
|
||||
~ password: {
|
||||
id : "&+r?{}J$J7"
|
||||
length : 10
|
||||
lower : true
|
||||
minLower : 0
|
||||
minNumeric: 0
|
||||
minSpecial: 0
|
||||
minUpper : 0
|
||||
number : true
|
||||
result : "&+r?{}J$J7"
|
||||
special : true
|
||||
upper : true
|
||||
urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
+ 1 to create
|
||||
2 unchanged
|
||||
|
||||
Do you want to perform this update? yes
|
||||
Updating (dev):
|
||||
Type Name Status
|
||||
pulumi:pulumi:Stack my-first-project-dev
|
||||
+ └─ docker:index:Container my-password created
|
||||
|
||||
Outputs:
|
||||
+ id : "e73b34aeca34a64b72b61b0b9b8438637ce28853937bc359a1528ca99f49ddda"
|
||||
password: {
|
||||
id : "&+r?{}J$J7"
|
||||
length : 10
|
||||
lower : true
|
||||
minLower : 0
|
||||
minNumeric: 0
|
||||
minSpecial: 0
|
||||
minUpper : 0
|
||||
number : true
|
||||
result : "&+r?{}J$J7"
|
||||
special : true
|
||||
upper : true
|
||||
urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
|
||||
}
|
||||
|
||||
Resources:
|
||||
+ 1 created
|
||||
2 unchanged
|
||||
|
||||
Duration: 2s
|
||||
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
|
||||
```
|
||||
|
||||
You'll notice in the `Outputs` section that the values you're outputting have changed; it's just a Docker container ID. Check whether your very simple password generator works:
|
||||
|
||||
|
||||
```
|
||||
curl <http://localhost:5678>
|
||||
Your super secret password is: &+r?{}J$J7
|
||||
```
|
||||
|
||||
It does! You just provisioned your first piece of infrastructure with TypeScript!
|
||||
|
||||
#### A quick note on Pulumi outputs
|
||||
|
||||
You'll notice in the code that creates the Docker container that it uses a special `pulumi.interpolate` call. If you're familiar with TypeScript, you might be curious why that's needed (as it's Pulumi-specific). There's an interesting reason.
|
||||
|
||||
When Pulumi creates a resource, there are values that Pulumi doesn't know until the program executes. In Pulumi, these are called `Outputs`. These `Outputs` can be seen in the code above; for example, in your first random resource, you used the `export` keyword to output the random resource's properties, and you also exported the container ID of the container you created.
|
||||
|
||||
Because Pulumi doesn't know the value of these `Outputs` until execution time, it needs special helpers to use them when manipulating strings. If you want to know more about this special programming model, watch [this short video][29].
|
||||
|
||||
### Wrapping up
|
||||
|
||||
IaC has evolved in many ways as complexity has arisen in hybrid-cloud infrastructures. In the infrastructure-provisioning space, Pulumi is a great choice for using your favorite programming language to provision everything you need to get your infrastructure off the ground, then you can tag in your favorite configuration management tooling to take the next steps.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/8/infrastructure-as-code-pulumi
|
||||
|
||||
作者:[Lee Briggs][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://opensource.com/users/lbriggs
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/puzzle_computer_solve_fix_tool.png?itok=U0pH1uwj (Puzzle pieces coming together to form a computer screen)
|
||||
[2]: https://opensource.com/resources/devops
|
||||
[3]: https://git-scm.com/
|
||||
[4]: https://www.mercurial-scm.org/
|
||||
[5]: https://opensource.com/article/18/12/configuration-management-tools
|
||||
[6]: https://opensource.com/article/20/7/terraform-kubernetes
|
||||
[7]: https://www.pulumi.com/
|
||||
[8]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
|
||||
[9]: https://www.typescriptlang.org/
|
||||
[10]: https://golang.org/
|
||||
[11]: https://www.python.org/
|
||||
[12]: https://en.wikipedia.org/wiki/C_Sharp_(programming_language)
|
||||
[13]: https://www.pulumi.com/docs/intro/cloud-providers/aws/
|
||||
[14]: https://www.pulumi.com/docs/intro/cloud-providers/azure/
|
||||
[15]: https://www.pulumi.com/docs/intro/cloud-providers/gcp/
|
||||
[16]: https://www.pulumi.com/docs/reference/pkg/
|
||||
[17]: https://nodejs.org/en/download/
|
||||
[18]: https://brew.sh/
|
||||
[19]: https://opensource.com/article/20/6/homebrew-mac
|
||||
[20]: https://opensource.com/article/20/6/homebrew-linux
|
||||
[21]: https://www.pulumi.com/docs/get-started/install/
|
||||
[22]: https://www.pulumi.com/docs/intro/concepts/state/
|
||||
[23]: https://www.pulumi.com/docs/intro/concepts/project/
|
||||
[24]: https://www.pulumi.com/docs/intro/concepts/stack/
|
||||
[25]: https://github.com/pulumi/templates
|
||||
[26]: https://www.pulumi.com/docs/intro/cloud-providers/
|
||||
[27]: https://www.pulumi.com/docs/intro/cloud-providers/random/
|
||||
[28]: https://docs.docker.com/get-docker/
|
||||
[29]: https://www.youtube.com/watch?v=lybOxul2otM
|
@ -1,151 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Easily set image transparency using GIMP)
|
||||
[#]: via: (https://opensource.com/article/20/9/chroma-key-gimp)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Easily set image transparency using GIMP
|
||||
======
|
||||
Use chroma key or "green screen" techniques to set transparencies on
|
||||
your video-game graphics.
|
||||
![Gaming with penguin pawns][1]
|
||||
|
||||
Whether you're programming a game or an app with [Python][2] or [Lua][3], you're probably using PNG graphics for your game assets. An advantage of the PNG format, which is not available in a JPEG, is the ability to store an **alpha channel**. Alpha is, essentially, the "color" of invisibility or transparency. Alpha is the part of an image you _don't_ see. For example, if you were to draw a doughnut, the doughnut hole would be filled with alpha, and you could see whatever was behind it.
|
||||
|
||||
A common problem is how to find the alpha part of an image. Sometimes, your programming framework, whether it's [Python Arcade][4], [Pygame][5], LÖVE, or anything else, detects the alpha channel and treats it (after the appropriate function calls) as transparency. That means it renders no new pixels where there's alpha, leaving that doughnut hole empty. It's 100% transparent or 0% opaque and functionally "invisible."
|
||||
|
||||
Other times, your framework and your graphic asset don't agree on where the alpha channel is located (or that an alpha channel exists at all), and you get pixels where you wanted transparency.
|
||||
|
||||
This article describes the most sure-fire way I know to work around that.
|
||||
|
||||
### Chroma key
|
||||
|
||||
In computer graphics, there are a few values that contribute to how a pixel is rendered. **Chrominance**, or **chroma**, describes the saturation or intensity of a pixel. The **chroma key** technique (also known as **green screening**) was originally developed as a chemical process, in which a specific color (blue at first and later green) was deliberately obscured by a **matte** during the copying of a film negative, allowing another image to be substituted where there once was a blue or green screen. That's a simplified explanation, but it demonstrates the origins of what is known as the alpha channel in computer graphics.
|
||||
|
||||
An alpha channel is information saved in a graphic to identify pixels that are meant to be transparent. RGB graphics, for example, have red, green, and blue channels. RGBA graphics contain red, green, blue, and alpha. The value of alpha can range from 0 to 1, with decimal points being valid entries.
|
||||
|
||||
Because an alpha channel can be expressed in several different ways, relying on an embedded alpha channel can be problematic. Instead, you can pick a color and turn it into an alpha value of 0 in your game framework. For that to work, you must know the colors in your graphic.
|
||||
|
||||
### Prepare your graphic
|
||||
|
||||
To prepare a graphic with an explicit color reserved exclusively for a chroma key, open the graphic in your favorite graphic editor. I recommend [GIMP][6] or [Glimpse][7], but [mtPaint][8] or [Pinta][9] or even [Inkscape][10] can work just as well, depending on the nature of your graphics and your ability to translate these instructions to a different tool.
|
||||
|
||||
Start by opening this graphic of Tux the penguin:
|
||||
|
||||
![Tux the penguin][11]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
### Select the graphic
|
||||
|
||||
Once the graphic is open, go to the **Windows** menu and select **Dockable Dialogs** and then **Layers**. Right-click on Tux's layer in the **Layer** palette. From the pop-up menu, select **Alpha to Selection**. If your image does not have a built-in alpha channel, then you must create your own selection manually.
|
||||
|
||||
![Alpha to selection][13]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
To create a selection manually, click the **Paths** tool from the toolbox.
|
||||
|
||||
![GIMP Paths tool][14]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
Using the **Paths** tool, move your mouse around the graphic, clicking and releasing (do not drag) at each major intersection of its outline. Don't worry about following curves; just find the major intersections and corners. This creates a node at each point, with a straight line drawn between them. You don't need to close your path, so when you reach the final intersection before the one where you started, you're done.
|
||||
|
||||
![Create a path in GIMP][15]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
Once you've created your outline path, go to the **Windows** menu and select **Dockable Dialogs** and then **Tool Options**. In the **Tool Options** panel, select **Edit (Ctrl)**. With this activated, you can edit the paths you've just drawn by clicking the lines or nodes and adjusting them to fit your graphic better. You can even give the lines curves.
|
||||
|
||||
![Edit path][16]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
Now select the **Paths** panel from the **Windows > Dockable Dialogs** menu. In the **Paths** panel, click the **Path to Selection** button. Your graphic is now selected.
|
||||
|
||||
### Grow the selection
|
||||
|
||||
If you feel your selection is too tight, you can give yourself a little slack by growing the selection. I sometimes do this when I want to impose or thicken a border around a graphic.
|
||||
|
||||
To grow a selection, click the **Select** menu and choose **Grow**. Enter a pixel value and click **OK**.
|
||||
|
||||
### Invert the selection
|
||||
|
||||
You have your graphic selected, but what you actually want to select is everything _except_ your graphic. That's because you're creating an alpha matte to define what in your graphic will be replaced by something else. In other words, you need to mark the pixels that will be turned invisible.
|
||||
|
||||
To invert the selection, click on the **Select** menu and choose **Invert**. Now everything except your graphic is selected.
|
||||
|
||||
### Fill with alpha
|
||||
|
||||
With everything except your graphic selected, choose the color you want to use to designate your alpha matte. The most common color is green (as you might guess from the term "green screen"). There's nothing magical about the color green or even a particular shade of green. It's used because humans, frequent subjects of graphic manipulation, contain no green pigment, so it's easy to key out green without accidentally keying out part of the central subject. Of course, if your graphic is a green alien or an emerald or something that _does_ contain green, you should use a different color. You can use any color you want, as long as it's solid and consistent. If you're doing this to many graphics, your choice should be consistent across all graphics.
|
||||
|
||||
![Foreground color in toolbox][17]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
Set your foreground color with the color value you've chosen. To ensure that your choice is exact, use the [HTML][18] or [HSV][19] representation of the color. For example, if you're using pure green, it can be expressed in GIMP (and most open source graphic applications) as `00ff00` (that's 00 red, FF green, and 00 blue, with F being the maximum amount).
|
||||
|
||||
![Setting color values][20]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
Whatever color you choose, make sure you take note of the HTML or HSV values so you use the exact same color for every graphic.
|
||||
|
||||
To fill in your alpha matte, click the **Edit** menu and choose **Fill with FG Color**.
|
||||
|
||||
### Flatten and export
|
||||
|
||||
If you've left a border around your graphic, set your background color to the color you want to use as the border stroke. This is usually either black or white, but it can be anything that suits your game's aesthetic.
|
||||
|
||||
Once you have set the background color, click on the **Image** menu and select **Flatten Image**. It's safe to do this whether or not you added a border. This process removes the alpha channel from your image, filling in any "transparent" pixels with the background color.
|
||||
|
||||
![Flattening image][21]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
You now have an image ready for your game engine. Export the image to whatever format your game engine prefers, and then import it into your game using whatever function calls it requires. In your code, set the alpha value to `00ff00` (or whatever color you used), and then use the game engine's graphic transforms to treat that color as an alpha channel.
|
||||
|
||||
### Other methods
|
||||
|
||||
This isn't the only way to get transparency in your game graphics. Check your game engine's documentation to find out how it tries to process alpha channels by default, and when you're not certain, try letting your game engine auto-detect transparency in your graphic before you go about editing it. Sometimes, your game engine's expectations and your graphic's preset values happen to match, and you get transparency without having to do any extra work.
|
||||
|
||||
When that fails, though, try a little chroma key. It's worked for the film industry for nearly 100 years, and it can work for you too.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/9/chroma-key-gimp
|
||||
|
||||
作者:[Seth Kenlon][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://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/gaming_grid_penguin.png?itok=7Fv83mHR (Gaming with penguin pawns)
|
||||
[2]: https://opensource.com/article/17/10/python-101
|
||||
[3]: https://opensource.com/article/17/4/how-program-games-raspberry-pi
|
||||
[4]: https://opensource.com/article/18/4/easy-2d-game-creation-python-and-arcade
|
||||
[5]: https://opensource.com/article/17/12/game-framework-python
|
||||
[6]: http://gimp.org
|
||||
[7]: https://glimpse-editor.github.io
|
||||
[8]: https://opensource.com/article/17/2/mtpaint-pixel-art-animated-gifs
|
||||
[9]: https://www.pinta-project.com/
|
||||
[10]: http://inkscape.org
|
||||
[11]: https://opensource.com/sites/default/files/uploads/tux.png (Tux the penguin)
|
||||
[12]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[13]: https://opensource.com/sites/default/files/uploads/gimp_alpha-to-selection.jpg (Alpha to selection)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/gimp_path-tool.jpg (GIMP Paths tool)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/gimp_path-create.jpg (Create a path in GIMP)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/gimp_path-edit.jpg (Edit path)
|
||||
[17]: https://opensource.com/sites/default/files/uploads/gimp_foreground-colour.jpg (Foreground color in toolbox)
|
||||
[18]: https://www.w3schools.com/colors/colors_picker.asp
|
||||
[19]: https://en.wikipedia.org/wiki/HSL_and_HSV
|
||||
[20]: https://opensource.com/sites/default/files/uploads/gimp_colour.jpg (Setting color values)
|
||||
[21]: https://opensource.com/sites/default/files/uploads/gimp_matte.jpg (Flattening image)
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,99 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Day 1: a confusing Rails error message)
|
||||
[#]: via: (https://jvns.ca/blog/2020/11/09/day-1--a-little-rails-/)
|
||||
[#]: author: (Julia Evans https://jvns.ca/)
|
||||
|
||||
Day 1: a confusing Rails error message
|
||||
======
|
||||
|
||||
Today I started an Recurse Center batch! I got to meet a few people, and started on a tiny fun Rails project. I think I won’t talk too much about what the project actually is today, but here are some quick notes on a day with Rails:
|
||||
|
||||
### some notes on getting started
|
||||
|
||||
The main thing I learned about setting up a Rails project is that
|
||||
|
||||
1. it uses sqlite by default, you have to tell it to use Postgres
|
||||
2. there are a ton of things that Rails includes by default that you can disable.
|
||||
|
||||
|
||||
|
||||
I installed and `rm -rf`’d Rails maybe 7 times before I was satisfied with it and ended up with this incantation:
|
||||
|
||||
```
|
||||
rails new . -d postgresql --skip-sprockets --skip-javascript`
|
||||
```
|
||||
|
||||
Basically because I definitely wanted to use Postgres and not sqlite, and skipping sprockets and javascript seemed to make installing Rails faster, and I figured I could install them later if I decided I wanted them.
|
||||
|
||||
### the official Rails guide is really good
|
||||
|
||||
I used 2 main resources for creating my starter Rails app:
|
||||
|
||||
* DHH’s original Rails talk from 2005 <https://www.youtube.com/watch?v=Gzj723LkRJY> (which I didn’t watch this time, but I watched the last time I spent a day with Rails, and I found it pretty inspiring and helpful)
|
||||
* The official Rails “getting started” guide, which seems pretty short and clear <https://guides.rubyonrails.org/v5.0/getting_started.html>
|
||||
|
||||
|
||||
|
||||
### a mysterious error message: `undefined method 'user'`
|
||||
|
||||
I love bugs, so here’s a weird Rails error I ran into today! I had some code that looked like this:
|
||||
|
||||
```
|
||||
@user = User.new(user_params)
|
||||
@user.save
|
||||
```
|
||||
|
||||
Pretty simple, right? But when that code ran, I got this baffling error message:
|
||||
|
||||
```
|
||||
undefined method `user' for #<User:0x00007fb6f4012ab8> Did you mean? super
|
||||
```
|
||||
|
||||
I was EXTREMELY confused about what was going on here because I hadn’t _called_ a method called `user`. I’d called `.save`. What???? I stayed confused and frustrated about this for maybe 20 minutes, and then finally I looked at my `User` model and found this code:
|
||||
|
||||
```
|
||||
class User < ApplicationRecord
|
||||
has_secure_password
|
||||
|
||||
validates :user, presence: true, uniqueness: true
|
||||
end
|
||||
```
|
||||
|
||||
`validates :user...` was _supposed_ to be some Rails magic validating that every `User` had a `username`, and that usernames had to be unique. But I’d made a typo, and I’d written `user` and not `username`. I fixed this and then everything worked! hooray!
|
||||
|
||||
I still don’t understand how I was supposed to debug this though: the stack trace told me the problem was with the `@user.save` line, and never mentioned that `validates :user` thing at all. I feel like there must be a way to debug this but I don’t know what it is.
|
||||
|
||||
The whole point of me playing with Rails is to see how the Rails magic plays out in practice so this was a fun bug to hit early on.
|
||||
|
||||
### a simple user management system
|
||||
|
||||
I decided I wanted users in my toy app. Some Googling showed me that there’s an extremely popular gem called [devise][1] that handles users. I found the README a little overwhelming and I knew that I wanted a very minimal user management system in my toy app, so instead I followed this guide called [Authentication from Scratch with Rails 5.2][2] which seems to be working out so far. Rails seems to already have a bunch of built in stuff for managing users – I was really surprised by how short that guide was and how little code I needed to write.
|
||||
|
||||
I learned while implementing users that Rails has a built in magical session management system (see [How Rails Sessions Work][3]. By default all the session data seems to be stored in a cookie on the user’s computer, though I guess you can also store the session data in a database if it gets too big for a cookie.
|
||||
|
||||
It’s definitely kind of strange to already have a session management system and cookies and users without quite knowing what’s going on exactly, but it’s also kind of fun! We’ll see how it goes.
|
||||
|
||||
### tomorrow: more rails!
|
||||
|
||||
Maybe tomorrow I can actually make some progress on implementing my fun rails app idea!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2020/11/09/day-1--a-little-rails-/
|
||||
|
||||
作者:[Julia Evans][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://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/heartcombo/devise
|
||||
[2]: https://medium.com/@wintermeyer/authentication-from-scratch-with-rails-5-2-92d8676f6836
|
||||
[3]: https://www.justinweiss.com/articles/how-rails-sessions-work/
|
@ -1,89 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to Increase Disk Size of Your Existing Virtual Machines in VirtualBox)
|
||||
[#]: via: (https://itsfoss.com/increase-disk-size-virtualbox/)
|
||||
[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
|
||||
|
||||
How to Increase Disk Size of Your Existing Virtual Machines in VirtualBox
|
||||
======
|
||||
|
||||
Here’s the scenario you may come across sooner or later.
|
||||
|
||||
You installed one or more operating systems in [VirtualBox][1]. While creating those virtual operating systems, you also created virtual hard disks for them in VirtualBox.
|
||||
|
||||
You specified the maximum size of the virtual disk to say 15 or 20 GB but now after using it for some time, you realize that your virtual machine is running out of space.
|
||||
|
||||
While [there are ways to free up disk space on Ubuntu][2] and other operating systems, a more robust way of handling the situation is to increase the disk size of your virtual machines created in VirtualBox.
|
||||
|
||||
Yes, you can enlarge the virtual hard disk in VirtualBox even after creation. Although this is a safe and tested procedure, it is highly recommended to create a backup of your virtual machine before you perform such an action.
|
||||
|
||||
### How to enlarge VirtualBox disk size
|
||||
|
||||
![][3]
|
||||
|
||||
I will show you how to resize disk in VirtualBox graphically and via command line (for Linux geeks). Both methods are easy and straightforward.
|
||||
|
||||
#### Method 1: Using the Virtual Media Manager in VirtualBox
|
||||
|
||||
VirtualBox 6 added a graphical option for resizing virtual disks. You can find it at the file tab of VirtualBox home page.
|
||||
|
||||
Go to _**File->Virtual Media Manager**_:
|
||||
|
||||
![][4]
|
||||
|
||||
Select one of your virtual machines in the list and use the “Size” slider or type the size value that you need. Once done click “Apply”.
|
||||
|
||||
![][5]
|
||||
|
||||
Keep in mind that though you increased the size of your virtual disk, the **actual partition size remains the same if your space is dynamically allocated**.
|
||||
|
||||
#### Method 2: Increase VirtualBox disk space using Linux command line
|
||||
|
||||
If you are using a Linux operating system as a host, open the terminal and type the following command to resize VDI:
|
||||
|
||||
```
|
||||
VBoxManage modifymedium "/path_to_vdi_file" --resize <megabytes>
|
||||
```
|
||||
|
||||
The resize process should finish right after you click the enter button to execute the command.
|
||||
|
||||
Note
|
||||
|
||||
The commands **modifyvdi** and **modifyhd** of earlier versions of VirtualBox commands are also supported and mapped internally to the **modifymedium** command.
|
||||
|
||||
![][6]
|
||||
|
||||
If you are not sure where your virtual machines are saved, you can find the default location from the VirtualBox home page by clicking on **Files -> Preferences** or by using the keyboard shortcut **Ctrl+G**.
|
||||
|
||||
![][7]
|
||||
|
||||
#### Conclusion
|
||||
|
||||
Personally, I prefer to use the terminal on every Linux distribution that I use for expanding disk, the graphical option is a very handy addition to the latest VirtualBox release.
|
||||
|
||||
This is an easy and quick tip but a great addition to VirtualBox fundamentals. If you find this tip useful, check out a few features of [VirtualBox guest additions][8].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/increase-disk-size-virtualbox/
|
||||
|
||||
作者:[Dimitrios Savvopoulos][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://itsfoss.com/author/dimitrios/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.virtualbox.org/
|
||||
[2]: https://itsfoss.com/free-up-space-ubuntu-linux/
|
||||
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/11/enlarge-disk-size-virtualbox.png?resize=800%2C450&ssl=1
|
||||
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/1-virtual-box-media-manager.png?resize=800%2C600&ssl=1
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/2-virtual-box-increase-disc-space.png?resize=800%2C505&ssl=1
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/3-virtual-box-increase-disc-space-terminal.png?resize=800%2C600&ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/4-virtual-box-preferences.png?resize=800%2C450&ssl=1
|
||||
[8]: https://itsfoss.com/install-fedora-in-virtualbox/
|
@ -1,113 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Compare Files and Folders Graphically in Linux With Meld)
|
||||
[#]: via: (https://itsfoss.com/meld-gui-diff/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
Compare Files and Folders Graphically in Linux With Meld
|
||||
======
|
||||
|
||||
How do you compare two similar files to check for differences? The obvious answer is [to use the diff command in Linux][1].
|
||||
|
||||
The problem is that not everyone would be comfortable comparing files in Linux terminal. And the diff command output could be confusing for some.
|
||||
|
||||
Take this diff command output for example:
|
||||
|
||||
![][2]
|
||||
|
||||
There is definitely a learning curve involved here. However, if you are using desktop Linux, you can use [GUI][3] applications to easily compare two files for any differences.
|
||||
|
||||
There are several GUI diff tools available for Linux. I am going to highlight my favorite tool Meld in this week’s Linux application highlight.
|
||||
|
||||
### Meld: Visual Diff and Merge tool for Linux (and Windows)
|
||||
|
||||
With [Meld][4], you can compare two files in side by side view. Not only that, you may also modify the files to make changes accordingly. That’s what you would want to do in most situations, right?
|
||||
|
||||
![File Comparison][5]
|
||||
|
||||
Meld is also capable of comparing directories and show which files are different. It will also show while files are new or missing.
|
||||
|
||||
![Directory Comparison][6]
|
||||
|
||||
You may also use Meld for a three-way comparison.
|
||||
|
||||
![Three Way File Comparison][7]
|
||||
|
||||
The graphical side-by-side comparison helps in a number of situations. If you are a developer, you can use it to understand code patches. Meld also supports version control systems like Git, [Mercurial][8], [Subversion][9] etc.
|
||||
|
||||
### Features of Meld
|
||||
|
||||
![][10]
|
||||
|
||||
The open source Meld tools has the following main features:
|
||||
|
||||
* Perform two and three-way difference comparison
|
||||
* Edit files in-place and the difference comparison updates immediately
|
||||
* Navigate between differences and conflicts
|
||||
* Visualize global and local differences with insertions, changes and conflicts marked accordingly
|
||||
* Use regex text filtering to ignore certain differences
|
||||
* Syntax highlighting
|
||||
* Compare two or three directories for newly added, missing and altered files
|
||||
* Exclude some files from comparison
|
||||
* Support for popular version control systems like Git, Mercurial, Bazaar and SVN
|
||||
* Support for many international languages
|
||||
* Open source GPL v2 license
|
||||
* Available for Linux as well as Windows
|
||||
|
||||
|
||||
|
||||
### Installing Meld on Linux
|
||||
|
||||
Meld is a popular application and it is available in the official repositories of most Linux distributions.
|
||||
|
||||
Check your distribution’s software center and see if Meld is available.
|
||||
|
||||
![Meld In Ubuntu Software Center][11]
|
||||
|
||||
Alternatively, you can also use command line package manager of your distribution to install Meld. On [Ubuntu, it is available in the Universe repository][12] and can be [installed using the apt command][13]:
|
||||
|
||||
```
|
||||
sudo apt install meld
|
||||
```
|
||||
|
||||
You may find the source code of Meld on GNOME’s GitLab repository:
|
||||
|
||||
[Meld Source Code][14]
|
||||
|
||||
### Worth it?
|
||||
|
||||
I know that [most modern open source code editors][15] come with this feature but sometimes you just want a simple interface without the trouble of installing additional add-ons for comparing files. Meld provides you just that.
|
||||
|
||||
Do you use some other tools for checking differences between files? Which tool would that be? What’s your experience with Meld, if you ever used it? The comment sections is all yours for sharing your opinion.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/meld-gui-diff/
|
||||
|
||||
作者:[Abhishek Prakash][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://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://linuxhandbook.com/diff-command/
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/diff-command-complicated-output.png?resize=795%2C551&ssl=1
|
||||
[3]: https://itsfoss.com/gui-cli-tui/
|
||||
[4]: https://meldmerge.org
|
||||
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/file-comaprison-in-Linux-with-meld.png?resize=800%2C498&ssl=1
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/directory-comparison-in-Linux-with_meld.png?resize=800%2C497&ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/three-way-file-comaprison-with-meld-in-linux.png?resize=800%2C466&ssl=1
|
||||
[8]: https://www.mercurial-scm.org/
|
||||
[9]: https://subversion.apache.org/
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/meld-visual-diff.png?resize=786%2C455&ssl=1
|
||||
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/Meld-in-Ubuntu-Software-Center.png?resize=800%2C384&ssl=1
|
||||
[12]: https://itsfoss.com/ubuntu-repositories/
|
||||
[13]: https://itsfoss.com/apt-command-guide/
|
||||
[14]: https://gitlab.gnome.org/GNOME/meld
|
||||
[15]: https://itsfoss.com/best-modern-open-source-code-editors-for-linux/
|
@ -0,0 +1,247 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Get started with Fossil, an alternative to Git)
|
||||
[#]: via: (https://opensource.com/article/20/11/fossil)
|
||||
[#]: author: (Klaatu https://opensource.com/users/klaatu)
|
||||
|
||||
Get started with Fossil, an alternative to Git
|
||||
======
|
||||
Fossil is an all-in-one version control system, bug tracker, wiki,
|
||||
forum, and documentation solution.
|
||||
![Dinosaurs on land at sunset][1]
|
||||
|
||||
As any programmer knows, there are many reasons it's vital to keep track of code changes. Sometimes you just want a history of how your project started and evolved, as a matter of curiosity or education. Other times, you want to enable other coders to contribute to your project, and you need a reliable way to merge disparate parts. And more critically, sometimes an adjustment you make to fix one problem breaks something else that was working.
|
||||
|
||||
The [Fossil][2] source code management system is an all-in-one version control system, bug tracker, wiki, forum, and documentation solution from the creator of the famous [SQLite][3] database.
|
||||
|
||||
### Install Fossil
|
||||
|
||||
Fossil is a single, self-contained C program, so you can probably just [download Fossil][4] from its website and place it anywhere in your system [PATH][5]. For example, assuming `/usr/local/bin` is in your path, as it usually is by default:
|
||||
|
||||
|
||||
```
|
||||
$ wget <https://fossil-scm.org/home/uv/fossil-linux-x64-X.Y.tar.gz>
|
||||
$ sudo tar xvf fossil-linux-x64-X.Y.tar.gz \
|
||||
\--directory /usr/local/bin
|
||||
```
|
||||
|
||||
You might also find Fossil in your software repository through your package manager, or you can compile it from source code.
|
||||
|
||||
### Create a Fossil repository
|
||||
|
||||
If you have a coding project you want to track with Fossil, the first step is to create a Fossil repository:
|
||||
|
||||
|
||||
```
|
||||
$ fossil init myproject.fossil
|
||||
project-id: 010836ac6112fefb0b015702152d447c8c1d8604
|
||||
server-id: 54d837e9dc938ba1caa56d31b99c35a4c9627f44
|
||||
admin-user: klaatu (initial password is "14b605")
|
||||
```
|
||||
|
||||
Creating a Fossil repo returns three items: a unique project ID, a unique server ID, and an admin ID and password. The project and server IDs are version numbers. The admin credentials establish your ownership of this repository and can be used if you decide to run Fossil as a server for other users to access.
|
||||
|
||||
### Work in a Fossil repository
|
||||
|
||||
To start working in a Fossil repo, you must create a working location for its data. You might think of this process as creating a virtual environment in Python or unzipping a ZIP file that you intend to zip back up again later.
|
||||
|
||||
Create a working directory and change into it:
|
||||
|
||||
|
||||
```
|
||||
$ mkdir myprojectdir
|
||||
$ cd myprojectdir
|
||||
```
|
||||
|
||||
Open your Fossil repository into the directory you created:
|
||||
|
||||
|
||||
```
|
||||
$ fossil open ../myproject
|
||||
project-name: <unnamed>
|
||||
repository: /home/klaatu/myprojectdir/../myproject
|
||||
local-root: /home/klaatu/myprojectdir/
|
||||
config-db: /home/klaatu/.fossil
|
||||
project-code: 010836ac6112fefb0b015702152d447c8c1d8604
|
||||
checkout: 9e6cd96dd675544c58a246520ad58cdd460d1559 2020-11-09 04:09:35 UTC
|
||||
tags: trunk
|
||||
comment: initial empty check-in (user: klaatu)
|
||||
check-ins: 1
|
||||
```
|
||||
|
||||
You might notice that Fossil created a hidden file called `.fossil` in your home directory to track your global Fossil preferences. This is not specific to your project; it's just an artifact of the first time you use Fossil.
|
||||
|
||||
#### Add files
|
||||
|
||||
To add files to your repository, use the `add` and `commit` subcommands. For example, create a simple README file and add it to the repository:
|
||||
|
||||
|
||||
```
|
||||
$ echo "My first Fossil project" > README
|
||||
$ fossil add README
|
||||
ADDED README
|
||||
$ fossil commit -m 'My first commit'
|
||||
New_Version: 2472a43acd11c93d08314e852dedfc6a476403695e44f47061607e4e90ad01aa
|
||||
```
|
||||
|
||||
#### Use branches
|
||||
|
||||
By default, a Fossile repository starts with a main branch called `trunk`. You can branch off the trunk when you want to work on code without affecting your primary codebase. Creating a new branch requires the `branch` subcommand, along with a new branch name and the branch you want to use as the basis for your new one. In this example, the only branch is `trunk`, so try creating a new branch called `dev`:
|
||||
|
||||
|
||||
```
|
||||
$ fossil branch --help
|
||||
Usage: fossil branch new BRANCH-NAME BASIS ?OPTIONS?
|
||||
$ fossil branch new dev trunk
|
||||
New branch: cb90e9c6f23a9c98e0c3656d7e18d320fa52e666700b12b5ebbc4674a0703695
|
||||
```
|
||||
|
||||
You've created a new branch, but your current branch is still `trunk`:
|
||||
|
||||
|
||||
```
|
||||
$ fossil branch current
|
||||
trunk
|
||||
```
|
||||
|
||||
To make your new `dev` branch active, use the `checkout` command:
|
||||
|
||||
|
||||
```
|
||||
$ fossil checkout dev
|
||||
dev
|
||||
```
|
||||
|
||||
#### Merge changes
|
||||
|
||||
Suppose you add an exciting new file to your `dev` branch, and having tested it, you're satisfied that it's ready to take its place in `trunk`. This is called a _merge_.
|
||||
|
||||
First, change your branch back to your target branch (in this example, that's `trunk`):
|
||||
|
||||
|
||||
```
|
||||
$ fossil checkout trunk
|
||||
trunk
|
||||
$ ls
|
||||
README
|
||||
```
|
||||
|
||||
Your new file (or any changes you made to an existing file) doesn't exist there yet, but that's what performing the merge will take care of:
|
||||
|
||||
|
||||
```
|
||||
$ fossil merge dev
|
||||
"fossil undo" is available to undo changes to the working checkout.
|
||||
$ ls
|
||||
myfile.lua README
|
||||
```
|
||||
|
||||
### View the Fossil timeline
|
||||
|
||||
To see the history of your repository, use the `timeline` option. This shows a detailed list of all activity in your repository, including a hash representing the change, the commit message you provided when committing code, and who made the change:
|
||||
|
||||
|
||||
```
|
||||
$ fossil timeline
|
||||
=== 2020-11-09 ===
|
||||
06:24:16 [5ef06e668b] added exciting new file (user: klaatu tags: dev)
|
||||
06:11:19 [cb90e9c6f2] Create new branch named "dev" (user: klaatu tags: dev)
|
||||
06:08:09 [a2bb73e4a3] *CURRENT* some additions were made (user: klaatu tags: trunk)
|
||||
06:00:47 [2472a43acd] This is my first commit. (user: klaatu tags: trunk)
|
||||
04:09:35 [9e6cd96dd6] initial empty check-in (user: klaatu tags: trunk)
|
||||
+++ no more data (5) +++
|
||||
```
|
||||
|
||||
![Fossil UI][6]
|
||||
|
||||
(Klaatu, [CC BY-SA 4.0][7])
|
||||
|
||||
### Make your Fossil repository public
|
||||
|
||||
Because Fossil features a built-in web interface, Fossil doesn't need a hosting service like GitLab or Gitea do. Fossil is its own hosting service, as long as you have a server to put it on. Before making your Fossil project public, though, you must configure some attributes through the web user interface (UI).
|
||||
|
||||
Launch a local instance with the `ui` subcommand:
|
||||
|
||||
|
||||
```
|
||||
$ pwd
|
||||
/home/klaatu/myprojectdir/
|
||||
$ fossil ui
|
||||
```
|
||||
|
||||
Specifically, look at **Users** and **Settings** for security, and **Configuration** for project properties (including a proper title). The web interface isn't just a convenience function. It's intended for actual use and is indeed used as the host for the Fossil project. There are several surprisingly advanced options, from user management (or self-management, if you please) to single-sign-on (SSO) with other Fossil repositories on the same server.
|
||||
|
||||
Once you're satisfied with your changes, close the web interface and press **Ctrl+C** to stop the UI engine from running. Commit your web changes just as you would any other update:
|
||||
|
||||
|
||||
```
|
||||
$ fossil commit -m 'web ui updates'
|
||||
New_Version: 11fe7f2855a3246c303df00ec725d0fca526fa0b83fa67c95db92283e8273c60
|
||||
```
|
||||
|
||||
Now you're ready to set up your Fossil server.
|
||||
|
||||
1. Copy your Fossil repository (in this example, `myproject.fossil`) to your server. You only need the single file.
|
||||
2. Install Fossil on your server, if it's not already installed. The process for installing Fossil to your server is the same as it was for your local computer.
|
||||
3. In your `cgi-bin` directory (or the equivalent of that directory, depending upon which HTTP daemon you're running), create a file called `repo_myproject.cgi`:
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
#!/usr/local/bin/fossil
|
||||
repository: /home/klaatu/public_html/myproject.fossil
|
||||
```
|
||||
|
||||
Make the script executable:
|
||||
|
||||
|
||||
```
|
||||
`$ chmod +x repo_myproject.cgi`
|
||||
```
|
||||
|
||||
That's all there is to it. Your project is now live on the internet.
|
||||
|
||||
You can visit the web UI by navigating to your CGI script, such as `https://example.com/cgi-bin/repo_myproject.cgi`.
|
||||
|
||||
Or you can interact with your repository from a terminal through the same URL:
|
||||
|
||||
|
||||
```
|
||||
`$ fossil clone https://klaatu@example.com/cgi-bin/repo_myproject.cgi`
|
||||
```
|
||||
|
||||
Working with a local clone requires you to use the `push` subcommand to send local changes back to your remote repository and the `pull` subcommand to get remotely made changes into your local copy:
|
||||
|
||||
|
||||
```
|
||||
`$ fossil push https://klaatu@example.com/cgi-bin/repo_myproject.cgi`
|
||||
```
|
||||
|
||||
### Use Fossil for independent hosting
|
||||
|
||||
Fossil places a lot of power into your hands (and the hands of your collaborators) and makes you independent of hosting services. This article only hints at the basics. There's so much more to Fossil that can help you and your teams in your code projects. Give Fossil a try. It won't just change the way you think about version control; it'll help you stop thinking about version control altogether.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/11/fossil
|
||||
|
||||
作者:[Klaatu][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://opensource.com/users/klaatu
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_dinosaur_sunset.png?itok=lbzpbW5p (Dinosaurs on land at sunset)
|
||||
[2]: https://fossil-scm.org/home/doc/trunk/www/index.wiki
|
||||
[3]: https://www.sqlite.org/index.html
|
||||
[4]: https://fossil-scm.org/home/uv/download.html
|
||||
[5]: https://opensource.com/article/17/6/set-path-linux
|
||||
[6]: https://opensource.com/sites/default/files/uploads/fossil-ui.jpg (Fossil UI)
|
||||
[7]: https://creativecommons.org/licenses/by-sa/4.0/
|
@ -0,0 +1,102 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Keep track of multiple Git remote repositories)
|
||||
[#]: via: (https://opensource.com/article/20/11/multiple-git-repositories)
|
||||
[#]: author: (Peter Portante https://opensource.com/users/portante)
|
||||
|
||||
Keep track of multiple Git remote repositories
|
||||
======
|
||||
Having consistent naming standards is key to keeping local and upstream
|
||||
Git repos straight.
|
||||
![Digital hand surrounding by objects, bike, light bulb, graphs][1]
|
||||
|
||||
Working with remote repositories gets confusing when the names of the remote repositories in your local Git repo are inconsistent.
|
||||
|
||||
One approach to solving this issue is to standardize the use and meaning of two words: `origin`, referring to your personal `example.com/<USER>/*` repos, and `upstream`, referring to the `example.com` repo from which you forked the `origin` repo. In other words, `upstream` refers to the upstream repo where work is publicly submitted, while `origin` refers to your local fork of the upstream repo from which you generate pull requests (PRs), for example.
|
||||
|
||||
Using the [pbench][2] repo as an example, here is a step-by-step approach to set up a new local clone with `origin` and `upstream` defined consistently.
|
||||
|
||||
1. On most Git hosting services, you must fork a project when you want to work on it. When you run your own Git server, that's not necessary, but for a codebase that's open to the public, it's an easy way to transfer diffs among contributors.
|
||||
|
||||
Create a fork of a Git repository. For this example, assume your fork is located at `example.com/<USER>/pbench`.
|
||||
|
||||
2. Next, you must obtain a Uniform Resource Identifier ([URI][3]) for cloning over SSH. On most Git hosting services, such as GitLab or GitHub, it's in a button or panel labeled **Clone** or **Clone over SSH**. Copy the clone URI to your clipboard.
|
||||
|
||||
3. On your development system, clone the repo using the text you copied:
|
||||
|
||||
|
||||
```
|
||||
`$ git clone git@example.com:<USER>/pbench.git`
|
||||
```
|
||||
|
||||
This clones the Git repository with the default name `origin` for your forked copy of the pbench repo.
|
||||
|
||||
4. Change directory to the repo you just cloned:
|
||||
|
||||
|
||||
```
|
||||
`$ cd ~/pbench`
|
||||
```
|
||||
|
||||
5. Next, obtain the SSH URI of the source repo (the one you originally forked). This is probably done the same way as above: Find the **Clone** button or panel and copy the clone address. In software development, this is typically referred to as "upstream" because (in theory) this is where most commits happen, and you intend to let those commits flow downstream into your copy of the repository.
|
||||
|
||||
6. Add the URI to your local copy of the repository. Yes, there will be _two different_ remotes assigned to your local copy of the repository:
|
||||
|
||||
|
||||
```
|
||||
`$ git remote add upstream \ git@example.com:bigproject/pbench.git`
|
||||
```
|
||||
|
||||
7. You now have two named remote repos: `origin` and `upstream`. You can see your remote repos with the remote subcommand:
|
||||
|
||||
|
||||
```
|
||||
`$ git remote -v`
|
||||
```
|
||||
|
||||
Right now, your local `master` branch is tracking the `origin` master, which is not necessarily what you want. You probably want to track the `upstream` version of this branch because upstream is where most development takes place. The idea is that you are adding your changes on top of whatever you get from upstream.
|
||||
|
||||
8. Change your local master branch to track `upstream/master`:
|
||||
|
||||
|
||||
```
|
||||
$ git fetch upstream
|
||||
$ git branch --set-upstream-to=upstream/master master
|
||||
```
|
||||
|
||||
You can do this for any branch you want, not just `master`. For instance, some projects use a `dev` branch for all unstable changes, reserving `master` for code approved for release.
|
||||
|
||||
9. Once you've set your tracking branches, be sure to `rebase` your master to bring it up to date to any new changes made to the upstream repo:
|
||||
|
||||
|
||||
```
|
||||
$ git remote update
|
||||
$ git checkout master
|
||||
$ git rebase
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
This is a great way to keep your Git repositories synchronized between forks. If you want to automate this, read Seth Kenlon's article on [cohosting Git repositories with Ansible][4] to learn how.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/11/multiple-git-repositories
|
||||
|
||||
作者:[Peter Portante][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://opensource.com/users/portante
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003588_01_rd3os.combacktoschoolseriesk12_rh_021x_0.png?itok=fvorN0e- (Digital hand surrounding by objects, bike, light bulb, graphs)
|
||||
[2]: https://github.com/distributed-system-analysis/pbench
|
||||
[3]: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
|
||||
[4]: https://opensource.com/article/19/11/how-host-github-gitlab-ansible
|
122
sources/tech/20201126 5 open source alternatives to GitHub.md
Normal file
122
sources/tech/20201126 5 open source alternatives to GitHub.md
Normal file
@ -0,0 +1,122 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (5 open source alternatives to GitHub)
|
||||
[#]: via: (https://opensource.com/article/20/11/open-source-alternatives-github)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
5 open source alternatives to GitHub
|
||||
======
|
||||
Stay resilient by keeping your open source code in an open source
|
||||
repository.
|
||||
![Woman programming][1]
|
||||
|
||||
Git is a popular version-control system, primarily used for code but popular in [other disciplines][2], too. It can run locally on your computer for personal use, it can run on a server for collaboration, and it can also run as a hosted service for widespread public participation. There are many hosted services out there, and one of the most popular brands is [GitHub][3].
|
||||
|
||||
GitHub is not open source. Pragmatically, this doesn't make much of a difference to most users. The vast majority of code put onto GitHub is, presumably, encouraged to be shared by everyone, so GitHub's primary function is a sort of public backup service. Should GitHub fold or drastically change its terms of service, recovering data would be relatively simple because it's expected that you have a local copy of the code you keep on GitHub. However, some organizations have come to rely on the non-Git parts of GitHub's service offerings, making migration away from GitHub difficult. That's an awkward place to be, so for many people and organizations, insurance against vendor lock-in is a worthwhile investment.
|
||||
|
||||
If that's the position you're in, check out these five GitHub alternatives, all of which are open source.
|
||||
|
||||
### 1\. GitLab
|
||||
|
||||
![GitLab][4]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][5])
|
||||
|
||||
GitLab is more than just a GitHub alternative; it's more like a complete DevOps platform. GitLab is nearly all the infrastructure a software development house requires, as it provides code and project management tools, issue reporting, continuous delivery, and monitoring. You can use GitLab on [GitLab.com][6], or you can download the codebase and run it locally with or without paid support. GitLab has a web interface, but all Git-specific commands work as expected.
|
||||
|
||||
GitLab is committed to open source, both in its code and the organization behind it, and to Git itself. The organization publishes much of its business documentation, including [how employees are onboarded][7], their [marketing policies][8], and much more. As a site, GitLab is ardent in promoting Git. When you use a site-specific feature (such as a merge request), GitLab's interface explains how to resolve the request in pure Git, should you prefer to work in the terminal.
|
||||
|
||||
### 2\. Gitolite
|
||||
|
||||
[Gitolite][9] is quite probably the minimal amount of code required to provide a server administrator a frontend for Git repository management. Unlike GitHub, it has no web interface, no desktop client, and adds nothing to Git from the user perspective. In fact, your users don't really use Gitolite directly. They just use Git, as usual, whether they're used to Git in a terminal or Git in a frontend client like [Git Cola][10].
|
||||
|
||||
From the server administrator's perspective, though, Gitolite solves all the permission and access problems you'd have to manage manually if you ran a plain Git server. With Gitolite, you create only one user (for instance, a user called `git`) on your server. You allow your users to use this single login identity to access your Git server, but when they log in, they must deal with your Git server through Gitolite. It's Gitolite that verifies users' access permissions, manages their SSH keys, verifies their privilege level when accessing specific repositories, and more. Instead of creating and managing countless Unix user accounts, all the administrator has to do is list users (identified by their SSH public keys) to the repositories they are allowed to access. Gitolite takes care of everything else.
|
||||
|
||||
Gitolite is nearly invisible to users, and it makes Git management nearly invisible to the server admin. As long as you don't require a web interface, Gitolite is a net win for everyone involved.
|
||||
|
||||
### 3\. Gitea and Gogs
|
||||
|
||||
![Gitea][11]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][5])
|
||||
|
||||
The [Gogs project][12] is an MIT-Licensed Git server framework and web user interface. In 2016, some Gogs users felt development was hindered because only its initial developer had write access to its development repository, so they forked the code to [Gitea][13]. Today, both projects co-exist independently of one another, and from a user's perspective, they are basically the same experience. Ironically, both projects are hosted on GitHub.
|
||||
|
||||
With Gitea and Gogs, you download the source code and run it as a service on your server. This provides a website for users, where they can create an account, log in, create their own repositories, upload code, navigate through code, file issues and bug reports, request code merges, manage SSH keys, and so on. The interface is similar in look and feel to GitLab, GitHub, or Bitbucket, so if users have any experience with an online-code management system, they're already essentially familiar with Gitea and Gogs.
|
||||
|
||||
Gitea or Gogs can be installed as a package on any Linux server, including a Raspberry Pi, as a container, on BSD, macOS, or Windows, or compiled from source code. They're both cross-platform, so they can be run on anything that runs Go. Read Ricardo Gerardi's article about [setting up a Gogs container using Podman][14] for more information.
|
||||
|
||||
### 4\. Independent communities
|
||||
|
||||
![Notabug][15]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][5])
|
||||
|
||||
If you're not up for self-hosting, you can cheat a little by using a self-hosted option on somebody else's server. There are many independent sites out there, such as [Codeberg][16], Nixnet, Tinfoil-hat, and [Notabug.org][17]. Some run Gitea and others run Gogs, but the result is the same: free code hosting to help you keep your work safe and public. These solutions may not be as complex as something like GitLab or GitHub, they may not offer on-demand Jenkins pipelines and continuous integration/continuous development (CI/CD) solutions, but they're great mirrors for your work.
|
||||
|
||||
There are purpose-specific providers, too: a [Gitea instance for FSFE supporters][18], a Gitlab instance for [Freedesktop projects][19], and another for [GNOME projects][20].
|
||||
|
||||
Because these independent servers are smaller communities, you might also find that the "social" aspect of social coding is more significant. I've made several online friends through an independent Git provider, while GitHub has proven to be, at least socially, underwhelming.
|
||||
|
||||
The message is clear: there's no requirement or advantage for there to be a centralized, dominant, non-free Git software hosting service.
|
||||
|
||||
### 5\. Git
|
||||
|
||||
It might surprise you to know that Git is surprisingly self-reliant as a server. While it lacks user management and permission settings, Git integrates with SSH and ships with a special `git-shell` application designed specifically to serve as a limited environment for using Git commands. By setting users' default shell to `git-shell`, you can limit what actions are available to them when they interact with your server.
|
||||
|
||||
What Git alone does not offer is repository permission tools to help you manage what each user has access to. For this, you'll have to fall back on the operating system's user and access control list (ACL) controls, which can become tedious should you have more than just a handful of users. For small projects or projects just starting, running Git on a Linux server is an easy and immediate solution to the need for a collaborative space. For more information, read my article on [building a Git server][21].
|
||||
|
||||
### Bonus: Fossil
|
||||
|
||||
![Fossil UI][22]
|
||||
|
||||
(Klaatu, [CC BY-SA 4.0][5])
|
||||
|
||||
Fossil isn't by any means Git, and in a sense, that's its appeal as an alternative to GitHub. In fact, Fossil is an alternative to the entire Git system. It's a complete version-control system, like Git, and it also has bug tracking, wiki, forum, and documentation features _built into every repository you create_. It also has a web interface included and is entirely self-contained. If it all sounds too good to be true, you can see it in action at [fossil-scm.org][23], because Fossil's homepage runs on Fossil!
|
||||
|
||||
Read Klaatu's article on [getting started with Fossil][24] for more information.
|
||||
|
||||
### Open source means choice
|
||||
|
||||
The best thing about Git (and Fossil) is that they're open source technologies. You can choose whatever solution works best for you. In fact, because Git is also distributed, you can even choose _multiple_ solutions. There's nothing stopping you from hosting your code on several services and writing to all of them with each push. Take a look at your options, decide what works best for you, and get to work!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/11/open-source-alternatives-github
|
||||
|
||||
作者:[Seth Kenlon][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://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop-music-headphones.png?itok=EQZ2WKzy (Woman programming)
|
||||
[2]: https://opensource.com/article/19/4/write-git
|
||||
[3]: https://github.com/
|
||||
[4]: https://opensource.com/sites/default/files/uploads/gitlab.jpg (GitLab)
|
||||
[5]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[6]: https://gitlab.com
|
||||
[7]: https://about.gitlab.com/handbook/people-group/general-onboarding/onboarding-processes
|
||||
[8]: https://about.gitlab.com/handbook
|
||||
[9]: https://gitolite.com/gitolite/index.html
|
||||
[10]: https://opensource.com/article/20/3/git-cola
|
||||
[11]: https://opensource.com/sites/default/files/uploads/gitea.jpg (Gitea)
|
||||
[12]: https://gogs.io
|
||||
[13]: https://gitea.io
|
||||
[14]: https://www.redhat.com/sysadmin/git-gogs-podman
|
||||
[15]: https://opensource.com/sites/default/files/uploads/notabug.jpg (Notabug)
|
||||
[16]: https://join.codeberg.org/
|
||||
[17]: https://notabug.org
|
||||
[18]: https://git.fsfe.org/
|
||||
[19]: https://gitlab.freedesktop.org
|
||||
[20]: https://gitlab.gnome.org
|
||||
[21]: https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6
|
||||
[22]: https://opensource.com/sites/default/files/uploads/fossil-ui.jpg (Fossil UI)
|
||||
[23]: https://www.fossil-scm.org
|
||||
[24]: https://opensource.com/article/20/11/fossil
|
@ -0,0 +1,150 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Easily set image transparency using GIMP)
|
||||
[#]: via: (https://opensource.com/article/20/9/chroma-key-gimp)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
使用 GIMP 轻松地设置图片透明度
|
||||
======
|
||||
使用 chroma 按键或 "绿屏" 技巧来设置你电脑游戏中图片的透明度。
|
||||
![企鹅兵游戏][1]
|
||||
|
||||
不管你是否正在使用 [Python][2] 或 [Lua][3] 编程一个游戏或一个 APP,你都有可能在你的游戏资产中使用 PNG 图像。PNG 格式图像的一个优点是能够存储一个 **alpha 通道**,这在一个 JPEG 格式的图像中是不可能获得的。Alpha 在本质上是不可见的或透明的 "颜色" 。Alpha 是你图像 _不可见_ 的一部分。例如,你要绘制一个甜甜圈,甜甜圈的空洞将使用 alpha 填充,你就可以看到它后面的任何东西。
|
||||
|
||||
一个常见的问题是如何找到一幅图像的 alpha 部分。有时你的编程框架,不管它是 [Python Arcade][4],[Pygame][5],LÖVE,或者其它的任何东西,侦察出 alpha 通道,(在适当地调用函数后) 将其作为透明处理。这意味着它将不会在 alpha 部分来渲染新的像素,而留下甜甜圈的空洞。100% 是透明的,0% 是不透明的,在功能上起 "不可见" 的作用。
|
||||
|
||||
有些时候,你的框架与你的图像资源在 alpha 通道的位置上是不一致的 (或者说,一个 alpha 通道根本就不存在),你可以在你想要透明度的地方得到像素。
|
||||
|
||||
这篇文章描述了我所知道的最可靠的方法来解决透明度的问题。
|
||||
|
||||
### Chroma key
|
||||
|
||||
在计算机图形学中,有一些有助于确定每一个像素是如何渲染的值。**Chrominance** ,或者 **chroma** ,描述一个像素的饱和度或强度。**chroma key** 技术 (也称为 **绿屏**) 最初是作为一种化学工艺而开发的,在复印一张底片时,使用一种特定的 **无光泽** 的颜色 (最初是蓝色,后来的绿色) 来故意遮掩,以允许使用另一幅图像来取代曾经有蓝色或绿色屏幕的地方。这是一种简化的解释,但是它说明了计算机图形学中被称为 alpha 通道的起源。
|
||||
|
||||
alpha 通道是保存在一幅图像中的信息,用以标识意欲透明的像素。例如,RGB 图像有红,绿,蓝通道。RGBA 图像包含红,绿,蓝通道,以及 alpha 通道。alpha 值的范围可以从 0 到 1 ,使用小数是也有效的。
|
||||
|
||||
因为一个 alpha 通道可以用几种不同的方法表达,依赖于一个嵌入的 alpha 通道可能是有问题的。作为替代方案,你可以在你的游戏框架中选择一种颜色并将其转化为一个 alpha 值。要做到这一点,你必需知道在你图像中的颜色值。
|
||||
|
||||
### 准备你的图片
|
||||
|
||||
为一次绿屏操作来准备一张清晰的使用独占保留颜色的图片,在你最喜欢的图片编辑器中打开图片。我建议使用 [GIMP][6] 或 [Glimpse][7],但是 [mtPaint][8] 或 [Pinta][9],甚至 [Inkscape][10] 也能很好地工作,这取决于你的图像的性质,以及你将这些操作指南转换到一种不同图片编辑器工具的能力。
|
||||
|
||||
首先打开这幅 Tux 企鹅的图像:
|
||||
|
||||
![Tux 企鹅][11]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
### 选择图片
|
||||
|
||||
在图片打开后,转到 **窗口** 菜单,选择 **可停靠对话框** ,接下来选择 **图层**。在 **图层** 面板中 Tux 图层上右击。从弹出菜单中,选择 **Alpha 到选区** 。如果你的图像没有内置的 alpha 通道,那么你必需手动创建你自己的选区。
|
||||
|
||||
![Alpha 到选区][13]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
为手动创建一个选区,单击来自工具箱的 **路径** 工具。
|
||||
|
||||
![GIMP 的路径工具][14]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
使用 **路径** 工具,在图像周围移动鼠标,在其轮廓的每个主要交叉点处都单击和释放 (不要拖动) 。 不要担心下面的曲线;只需要找到主要的交叉点和拐角。这将在每个点处创建一个节点,并在节点中间绘制一条条线段。你不需要关闭你的路径,因此当你最后到达你开始时的交叉点时,你就完成了。
|
||||
|
||||
![在 GIMP 中创建一个路径][15]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
在你创建你的轮廓路径后,转到 **窗口** 菜单,选择 **可停靠对话框** ,接下来选择 **工具选项** 。在 **工具选项** 面板中,选择 **编辑 (Ctrl)** 。随着这项操作的激活,你可以编辑你刚刚通过单击线或单击节点绘制的路径,并通过调整它们来更好地适应你的图像。你甚至能够将直线弯曲。
|
||||
|
||||
![编辑路径][16]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
现在从 **窗口 > 可停靠对话框** 菜单中选择 **路径** 面板。在 **路径** 面板中,单击 **路径到选区** 按钮。你的绘图现在已经被选中了。
|
||||
|
||||
### 扩大选区
|
||||
|
||||
如果你觉得你的选区太紧贴了,你可以通过扩大来给予你自己的选区一些富余。当我想在一张图像周围采用或加厚一个边框时,我有时会这么扩大选区。
|
||||
|
||||
为扩大一个选区,单击 **选择** 菜单,选择 **扩大** 。输入一个像素值并单击 **确定** 。
|
||||
|
||||
### 反转选区
|
||||
|
||||
你已经选择了你的图形,但是你真正想选择的东西却 _不包括_ 你所选择的图像。这是因为你正在创建的在你图像中定义的一些东西的一个 alpha 蒙版来将被其它的一些东西所替换。换句话说,你需要标记将被转变为不可视的像素。
|
||||
|
||||
为了反转选择区,单击 **选择** 菜单,选择 **反转** 。现在除你的图像以外的一切东西都是被选择的。
|
||||
|
||||
### 使用 alpha 填充
|
||||
|
||||
随着除你的图像以外的一切东西被选择,选择你想使用的颜色来指定你的 alpha 蒙版。最常用的颜色的绿色(正如你可能从 术语 "绿屏" 中所猜到的一样)。绿色或者绿色的特殊阴影并没有什么神奇的。使用 "绿屏" 是因为人们经常处理不包含绿色色素的图像,这样人们能够很容易分离出绿色,而不会意外地分离出图像中重要的部分。当然,如果你的图像是一位绿色的外星人或一枚绿宝石或一些 _确实_ 包含绿色的东西,那么你应该使用一种不同的颜色。只要你所选择的颜色是始终如一的单色,那么你就可以使用你所希望的任意颜色。如果你正在处理很多图像,那么你选择颜色时应该考虑所有的图像颜色。
|
||||
|
||||
![在工具箱中的前景色][17]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
使用你选择的颜色值来设置你的前景色。为确保你的选择是精确是,使用 [HTML][18] 或 [HSV][19] 描述的颜色。例如,如果你正在使用纯绿色,它可以在 GIMP ( 以及大多数的开放源码图像应用程序 ) 中表示为 `00ff00` ( 00 是红色,FF 是绿色,00 是蓝色,F 是最大值 ) 。
|
||||
|
||||
![设置颜色值][20]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
不管你选择什么颜色,务必记录下 HTML 或 HSV 的值,以便你可以为每一张图像使用完全相同的颜色。
|
||||
|
||||
为填充你的 alpha 蒙版,单击 **编辑** 菜单,选择 **使用前景色填充** 。
|
||||
|
||||
### 平整和导出
|
||||
|
||||
如果你在你的图像周围留下边框,设置背景颜色来着色你想使用的边界笔刷。这通常是黑色或白色,但是它也可以是任何适宜你游戏审美观的颜色。
|
||||
|
||||
在你设置背景颜色后,单击 **图像** 菜单,选择 **平整图像**。不管你是否添加了边界,这样做都是安全的。这个过程将从图像中移除 alpha 通道,并使用背景色填充任何 "透明的" 像素。
|
||||
|
||||
![平整图像][21]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][12])
|
||||
|
||||
你现在已经为你的游戏引擎准备好了一张图像。导出图像到你的游戏引擎喜欢的任何格式,接下来使用游戏引擎所需要的每一个函数来将图像导入的你的游戏中。在的代码中,设置 alpha 值为 `00ff00` ( 或你使用的任何颜色 ),接下来使用游戏引擎的图像转换器来讲该颜色作为 alpha 通道处理。
|
||||
|
||||
### 其它的方法
|
||||
|
||||
这不是唯一能在你游戏图像中获取透明度的方法。查看你游戏引擎的文档来找出它是如何默认尝试处理 alpha 通道的,在你不确定的时候,在你开始编辑图像前,尝试让你的游戏引擎来自动侦测图像中透明度。有时,你游戏引擎的预期值和你图像的预设值恰巧匹配,那么你就可以直接获取透明度,而不需要做任何额外的工作。
|
||||
|
||||
不过,当这些尝试都失败时,尝试一下 chroma key。它为电影业工作了将近 100 年,它也可以为你工作。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/9/chroma-key-gimp
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/gaming_grid_penguin.png?itok=7Fv83mHR (Gaming with penguin pawns)
|
||||
[2]: https://opensource.com/article/17/10/python-101
|
||||
[3]: https://opensource.com/article/17/4/how-program-games-raspberry-pi
|
||||
[4]: https://opensource.com/article/18/4/easy-2d-game-creation-python-and-arcade
|
||||
[5]: https://opensource.com/article/17/12/game-framework-python
|
||||
[6]: http://gimp.org
|
||||
[7]: https://glimpse-editor.github.io
|
||||
[8]: https://opensource.com/article/17/2/mtpaint-pixel-art-animated-gifs
|
||||
[9]: https://www.pinta-project.com/
|
||||
[10]: http://inkscape.org
|
||||
[11]: https://opensource.com/sites/default/files/uploads/tux.png (Tux the penguin)
|
||||
[12]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[13]: https://opensource.com/sites/default/files/uploads/gimp_alpha-to-selection.jpg (Alpha to selection)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/gimp_path-tool.jpg (GIMP Paths tool)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/gimp_path-create.jpg (Create a path in GIMP)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/gimp_path-edit.jpg (Edit path)
|
||||
[17]: https://opensource.com/sites/default/files/uploads/gimp_foreground-colour.jpg (Foreground color in toolbox)
|
||||
[18]: https://www.w3schools.com/colors/colors_picker.asp
|
||||
[19]: https://en.wikipedia.org/wiki/HSL_and_HSV
|
||||
[20]: https://opensource.com/sites/default/files/uploads/gimp_colour.jpg (Setting color values)
|
||||
[21]: https://opensource.com/sites/default/files/uploads/gimp_matte.jpg (Flattening image)
|
@ -1,90 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Reclaim hard-drive space with LVM)
|
||||
[#]: via: (https://fedoramagazine.org/reclaim-hard-drive-space-with-lvm/)
|
||||
[#]: author: (Troy Curtis Jr https://fedoramagazine.org/author/troycurtisjr/)
|
||||
|
||||
使用 LVM 回收硬盘空间
|
||||
======
|
||||
|
||||
![Hard drive image][1]
|
||||
|
||||
照片:Frank R @ Unsplash.com
|
||||
|
||||
LVM 是一个逻辑卷管理工具,包括分配磁盘、区代化、镜像和调整逻辑卷的大小。它在 Fedora 安装中被普遍使用(在 BTRFS 作为默认之前是 LVM+Ext4)。但是你是否曾经遇到过启动系统时,Gnome 提示主卷几乎没有空间了!幸运的是,很有可能有一些空间在另一个卷中,而未被使用,并准备重新分配。下面就来看看如何用 LVM 回收硬盘空间。
|
||||
|
||||
在卷之间轻松重新分配空间的关键是[逻辑卷管理器 (LVM)][2]。Fedora 32 及以前的系统默认使用 LVM 来划分磁盘空间。这种技术类似于标准的硬盘分区,但 LVM 更加灵活。LVM 不仅可以实现灵活的卷大小管理,还可以实现一些高级功能,比如读写快照、在多个硬盘上进行数据区带化或镜像、将高速硬盘作为慢速硬盘的缓存等等。所有这些高级选项可能会让人有点不知所措,但调整卷的大小很直接的。
|
||||
|
||||
### LVM 基础
|
||||
|
||||
_卷组_作为 LVM 系统中的主要容器。默认情况下,Fedora 只定义了一个卷组,但你可以根据需要定义多个卷组。实际的硬盘和硬盘分区被添加到 _卷组_中作为_物理卷_。_物理卷_会将可用的空间添加到_卷组_中。一个典型的 Fedora 安装有一个格式化的启动分区,其余的硬盘是一个配置为 LVM _物理卷_的分区。
|
||||
|
||||
从这个可用空间池中,_卷组_分配了一个或多个_逻辑卷_。这些卷类似于硬盘分区,但没有磁盘上连续空间的限制。LVM 的_逻辑卷_甚至可以跨越多个设备!就像硬盘分区一样,_逻辑卷_有一个定义的大小,可以包含任何文件系统,然后可以挂载到特定的目录。
|
||||
|
||||
### 需要什么
|
||||
|
||||
在 gnome-disks 应用中确认系统使用 LVM ,并确保其他卷中有可用的空间。如果没有从另一个卷中回收的空间,这个指南就没有用。还需要一个 [Fedora live CD/USB][3]。任何需要收缩的文件系统都必须卸载。从 Live 镜像运行可以让硬盘上的所有卷保持未挂载状态,甚至包括像 _/_ 和 _/home_ 这样的重要目录。
|
||||
|
||||
![Use gnome-disks to verify free space][4]
|
||||
|
||||
### 一句话警告
|
||||
|
||||
按照这个指南,应该不会丢失任何数据,但它确实会使用一些非常底层和强大的命令。一个错误可能会破坏硬盘上的所有数据。所以要先备份磁盘上的所有数据!
|
||||
|
||||
### 调整 LVM 卷的大小
|
||||
|
||||
开始时,启动 Fedora Live 镜像并在对话框中选择 _Try Fedora_。接下来,使用 _Run Command_ 启动 _blivet-gui_ 应用(按 _Alt-F2_,输入 _blivet-gui_,然后按_回车_)。选择左侧 _LVM_ 下的卷组。逻辑卷在右边。
|
||||
|
||||
![Explore logical volumes in blivet-gui][5]
|
||||
|
||||
逻辑卷标签由卷组名称和逻辑卷名称组成。在本例中,卷组是 “fedora_localhost-live”,分配了 “home”、“root” 和 “swap” 逻辑卷。要找到完整的卷,选择每一个卷,点击_齿轮_图标,然后选择 _resize_。调整大小对话框中的滑块表示卷的允许大小。左边的最小值是文件系统中已经使用的空间,所以这是最小可能的体积大小(不删除数据)。右边的最大值是基于_卷组_中的最大可用空间。
|
||||
|
||||
![Resize dialog in blivet-gui][6]
|
||||
|
||||
灰色的 _resize_ 选项意味着该卷已经满了,而且卷组中没有可用空间。现在可以更改大小了!查看所有的卷,就像上面的截图那样,找到一个有足够空间的卷。并像上面的截图那样,在所有的卷中找到一个有大量额外空间的卷。向左移动滑块来设置新的大小。腾出足够的空间对整个卷有用,但仍然为未来的数据增长留出足够的空间。否则,这个卷将是下一个被填满的卷。
|
||||
|
||||
点击 _resize_,注意卷列表中出现了一个新项目:_空闲空间_。现在选择这次要调整的卷,并将滑块一直向右移动。按 _resize_ 键,并查看新改进的卷的布局。然而,硬盘驱动器上的任何东西都还没有改变。点击_勾选按钮_将更改提交到磁盘。
|
||||
|
||||
![Review changes in blivet-gui][7]
|
||||
|
||||
查看更改的摘要,如果一切看起来都是正确的,点击 _Ok_ 继续。等待 _blivet-gui_ 完成。现在重新启动回到 Fedora ,享受之前被充满的卷上的新空间。
|
||||
|
||||
### 为未来计划
|
||||
|
||||
要知道任何特定卷在未来需要多少空间是很困难的。与其立即分配所有可用的空闲空间,不如考虑在卷组中留出空闲空间。事实上,Fedora Server 默认在卷组中保留空间。当一个卷处于在线和使用中时,扩展卷是可能的。不需要 Live 镜像或重启。当一个卷几乎满的时候,可以使用部分可用空间轻松扩展卷并继续工作。遗憾的是,默认的磁盘管理器 _gnome-disks_ 不支持 LVM 卷的大小调整,所以安装 _[blivet-gui][8]_ 作为图形化管理工具。另外,还有一个简单的终端命令来扩展卷。
|
||||
|
||||
```
|
||||
lvresize -r -L +1G /dev/fedora_localhost-live/root
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
用 LVM 回收硬盘空间只是 LVM 功能的表面。大多数人,特别是在桌面中,可能不需要更高级的功能。然而,当需要的时候,LVM 就在那里,尽管它的实现可能会变得有点复杂。从 [Fedora 33][10] 开始,[BTRFS][9] 是默认的文件系统,没有 LVM。BTRFS 可以更容易管理,同时对于大多数常见的使用来说也足够灵活。查看最近 [Fedora Magazine 关于 BTRFS 的文章][11]了解更多。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/reclaim-hard-drive-space-with-lvm/
|
||||
|
||||
作者:[Troy Curtis Jr][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/troycurtisjr/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2020/11/lvm-resize-816x345.jpg
|
||||
[2]: http://sourceware.org/lvm2/
|
||||
[3]: https://getfedora.org/en/workstation/download/
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2020/11/gnome-disks.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2020/11/blivet-overview.png
|
||||
[6]: https://fedoramagazine.org/wp-content/uploads/2020/11/blivet-resize-1024x525.png
|
||||
[7]: https://fedoramagazine.org/wp-content/uploads/2020/11/blivet-summary-1024x525.png
|
||||
[8]: https://fedoraproject.org/wiki/Blivet-gui
|
||||
[9]: https://fedoramagazine.org/btrfs-coming-to-fedora-33/
|
||||
[10]: https://fedoramagazine.org/whats-new-fedora-33-workstation/
|
||||
[11]: https://fedoramagazine.org/btrfs-snapshots-backup-incremental/
|
@ -0,0 +1,95 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Day 1: a confusing Rails error message)
|
||||
[#]: via: (https://jvns.ca/blog/2020/11/09/day-1--a-little-rails-/)
|
||||
[#]: author: (Julia Evans https://jvns.ca/)
|
||||
|
||||
Rails 之旅第 1 天:一个令人困惑的 Rails 错误信息
|
||||
======
|
||||
|
||||
今天,我开始了一个 Recurse Center 的批次学习!我认识了一些人,并开始了一个小小的有趣的 Rails 项目。我想我今天不会谈太多关于这个项目的实际内容,但这里有一些关于 Rails 一天的快速笔记。
|
||||
|
||||
### 一些关于开始的笔记
|
||||
|
||||
在建立 Rails 项目的过程中,我学到的主要是:
|
||||
|
||||
1. 它默认使用 sqlite,你必须告诉它使用 Postgres。
|
||||
2. Rails 默认包含了大量的东西,你可以禁用。
|
||||
|
||||
我安装并 `rm -rf` Rails 大概 7 次后才满意,最后用了这个咒语:
|
||||
|
||||
```
|
||||
rails new . -d postgresql --skip-sprockets --skip-javascript
|
||||
```
|
||||
|
||||
主要是因为我想用 Postgres 而不是 sqlite,而且跳过 sprockets 和 javascript 似乎能让安装 Rails 的速度更快,而且我想如果我决定要它们的话,我可以在以后再安装。
|
||||
|
||||
### 官方的 Rails 指南真的很不错
|
||||
|
||||
我在创建我的 Rails 入门应用时主要参考了 2 个资源:
|
||||
|
||||
* DHH 在 2005 年的 Rails 原版演讲 <https://www.youtube.com/watch?v=Gzj723LkRJY>(这次我没有看,但上次我花了一天时间学习 Rails 时看了,我发现它很有启发和帮助)。
|
||||
* 官方的 Rails 入门指南,似乎非常简短明了 <https://guides.rubyonrails.org/v5.0/getting_started.html>。
|
||||
|
||||
### 一个神秘的错误信息:`undefined method 'user'`
|
||||
|
||||
我喜欢 bug,所以今天我遇到了一个奇怪的 Rails 错误! 我有一些看起来像这样的代码:
|
||||
|
||||
```
|
||||
@user = User.new(user_params)
|
||||
@user.save
|
||||
```
|
||||
|
||||
很简单吧?但当这段代码运行时,我得到了这个令人费解的错误信息:
|
||||
|
||||
```
|
||||
undefined method `user' for #<User:0x00007fb6f4012ab8> Did you mean? super
|
||||
```
|
||||
|
||||
我对这里发生的事情感到**超级**困惑,因为我没有调用一个叫做 `user` 的方法。我调用的是 `.save`。什么嘛?!我对此感到困惑和沮丧,大概呆了 20 分钟,最后我看了看我的 `User` 模型,发现了这段代码:
|
||||
|
||||
```
|
||||
class User < ApplicationRecord
|
||||
has_secure_password
|
||||
|
||||
validates :user, presence: true, uniqueness: true
|
||||
end
|
||||
```
|
||||
|
||||
`validates :user...` *应该*是一些 Rails 魔法,验证每个 `User` 都有一个 `username`,而且用户名必须是唯一的。但我犯了一个错,我写的是 `user` 而不是 `username`。我把这个问题解决了,然后一切都正常了!万岁。
|
||||
|
||||
我仍然不明白我应该如何调试这个问题:堆栈跟踪告诉我问题出在 `@user.save` 行,根本没有提到 `validates :user` 的事情。我觉得一定有办法调试这个问题,但我不知道是什么办法。
|
||||
|
||||
我学 Rails 的目的就是想看看 Rails 的魔力在实践中是如何发挥的,所以这是个很有意思的 bug,早早的就掉坑里了。
|
||||
|
||||
### 一个简单的用户管理系统
|
||||
|
||||
我决定在我的玩具应用中加入用户。我在网上搜索了一下,发现有一个非常流行的叫做 [devise][1] 的工具可以处理用户。我发现它的 `README` 有点让人不知所措,而且我知道想要在我的玩具应用中建立一个非常简陋的用户管理系统,所以我遵循了这个名为《[Rails 5.2 中从零开始进行用户验证][2]》的指南,到目前为止,这个指南似乎还不错。Rails 似乎已经有了一大堆管理用户的内置东西,我真的很惊讶于这本指南的短小和我需要写的代码之少。
|
||||
|
||||
我在实现用户功能的时候了解到,Rails 有一个内置的神奇的会话管理系统(参见 [Rails 会话如何工作][3]。默认情况下,所有的会话数据似乎都存储在用户电脑上的 cookie 中,不过我想如果 cookie 太大了,你也可以把会话数据存储在数据库中。
|
||||
|
||||
已经有了会话管理系统,有了 cookie 和用户,却不太清楚到底发生了什么,这肯定是有点奇怪的,但也是挺好玩的!我们会看看情况如何。我们将拭目以待。
|
||||
|
||||
### 明天:更多的 Rails!
|
||||
|
||||
也许明天我可以在实现我的有趣的 rails 应用的想法上取得一些进展!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2020/11/09/day-1--a-little-rails-/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/heartcombo/devise
|
||||
[2]: https://medium.com/@wintermeyer/authentication-from-scratch-with-rails-5-2-92d8676f6836
|
||||
[3]: https://www.justinweiss.com/articles/how-rails-sessions-work/
|
@ -0,0 +1,89 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to Increase Disk Size of Your Existing Virtual Machines in VirtualBox)
|
||||
[#]: via: (https://itsfoss.com/increase-disk-size-virtualbox/)
|
||||
[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
|
||||
|
||||
如何在 VirtualBox 中增加现有虚拟机的磁盘大小
|
||||
======
|
||||
|
||||
下面是你迟早会遇到的情况。
|
||||
|
||||
你在 [VirtualBox][1] 中安装了一个或多个操作系统。在创建这些虚拟操作系统的同时,你还在 VirtualBox 中为它们创建了虚拟硬盘。
|
||||
|
||||
你指定了虚拟磁盘的最大大小,比如说 15 或 20GB,但现在使用了一段时间后,你发现你的虚拟机已经没有空间了。
|
||||
|
||||
虽然[在 Ubuntu 和其他操作系统上有释放磁盘空间的方法][2],但更稳健的处理方式是增加 VirtualBox 中创建的虚拟机的磁盘大小。
|
||||
|
||||
是的,你可以在 VirtualBox 中扩大虚拟硬盘,即使在创建之后也可以。虽然这是一个安全且经过测试的过程,但我们强烈建议你在执行这样的操作之前,先创建一个虚拟机的备份。
|
||||
|
||||
### 如何扩大 VirtualBox 磁盘大小
|
||||
|
||||
![][3]
|
||||
|
||||
我将向你展示如何在 VirtualBox 中以图形和命令行(对于 Linux 极客)方式调整磁盘大小。这两种方法都很简单直接。
|
||||
|
||||
#### 方法 1:在 VirtualBox 中使用虚拟媒体管理器
|
||||
|
||||
VirtualBox 6 增加了一个调整虚拟磁盘大小的图形化选项。你可以在 VirtualBox 主页的文件选项卡中找到它。
|
||||
|
||||
进入 _**File->Virtual Media Manager**_:
|
||||
|
||||
![][4]
|
||||
|
||||
在列表中选择一个虚拟机,然后使用 ”Size“ 滑块或输入你需要的大小值。完成后点击 ”Apply“。
|
||||
|
||||
![][5]
|
||||
|
||||
请记住,虽然你增加了虚拟磁盘的大小,但**如果你的空间是动态分配的,那么实际的分区大小仍然不变**。
|
||||
|
||||
#### 方法 2:使用 Linux 命令行增加 VirtualBox 磁盘空间
|
||||
|
||||
如果你使用 Linux 操作系统作为宿主机,打开终端并输入以下命令来调整 VDI 的大小:
|
||||
|
||||
```
|
||||
VBoxManage modifymedium "/path_to_vdi_file" --resize <megabytes>
|
||||
```
|
||||
|
||||
在你按下回车执行命令后,调整大小的过程应该马上结束。
|
||||
|
||||
注意事项
|
||||
|
||||
VirtualBox 早期版本命令中的 **modifyvdi** 和 **modifyhd** 命令也支持,并在内部映射到 **modifymedium** 命令。
|
||||
|
||||
![][6]
|
||||
|
||||
如果你不确定虚拟机的保存位置,可以在 VirtualBox 主页面点击 **Files -> Preferences** 或使用键盘快捷键 **Ctrl+G** 找到默认位置。
|
||||
|
||||
![][7]
|
||||
|
||||
#### 总结
|
||||
|
||||
就我个人而言,我更喜欢在每个 Linux 发行版上使用终端来扩展磁盘,图形化选项是最新的 VirtualBox 版本的一个非常方便的补充。
|
||||
|
||||
这是一个简单快捷的小技巧,但对 VirtualBox 基础知识是一个很好的补充。如果你觉得这个小技巧很有用,可以看看 [VirtualBox 客户端增强包][8]的几个功能。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/increase-disk-size-virtualbox/
|
||||
|
||||
作者:[Dimitrios Savvopoulos][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/dimitrios/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.virtualbox.org/
|
||||
[2]: https://itsfoss.com/free-up-space-ubuntu-linux/
|
||||
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/11/enlarge-disk-size-virtualbox.png?resize=800%2C450&ssl=1
|
||||
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/1-virtual-box-media-manager.png?resize=800%2C600&ssl=1
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/2-virtual-box-increase-disc-space.png?resize=800%2C505&ssl=1
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/3-virtual-box-increase-disc-space-terminal.png?resize=800%2C600&ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/4-virtual-box-preferences.png?resize=800%2C450&ssl=1
|
||||
[8]: https://itsfoss.com/install-fedora-in-virtualbox/
|
@ -0,0 +1,113 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Compare Files and Folders Graphically in Linux With Meld)
|
||||
[#]: via: (https://itsfoss.com/meld-gui-diff/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
使用 Meld 在 Linux 中以图形方式比较文件和文件夹
|
||||
======
|
||||
|
||||
如何比较两个相似的文件来检查差异?答案显而易见,就是[使用 Linux 中的 diff 命令][1]。
|
||||
|
||||
问题是,并不是每个人都能自如地在 Linux 终端中比较文件,而且 diff 命令的输出可能会让一些人感到困惑。
|
||||
|
||||
以这个 diff 命令的输出为例:
|
||||
|
||||
![][2]
|
||||
|
||||
这里肯定涉及到一个学习曲线。然而,如果你使用的是桌面 Linux,你可以使用 [GUI][3] 应用来轻松比较两个文件是否有任何差异。
|
||||
|
||||
有几个 Linux 中的 GUI diff 工具。我将在本周的 Linux 应用亮点中重点介绍我最喜欢的工具 Meld。
|
||||
|
||||
### Meld:Linux (及 Windows) 下的可视化比较和合并工具
|
||||
|
||||
通过 [Meld][4],你可以将两个文件并排比较。不仅如此,你还可以对文件进行相应的修改。这是你在大多数情况下想做的事情,对吗?
|
||||
|
||||
![File Comparison][5]
|
||||
|
||||
Meld 还能够比较目录,并显示哪些文件是不同的。它还会显示而文件是新的或是缺失的。
|
||||
|
||||
![Directory Comparison][6]
|
||||
|
||||
你也可以使用 Meld 进行三向比较。
|
||||
|
||||
![Three Way File Comparison][7]
|
||||
|
||||
图形化的并排比较在很多情况下都有帮助。如果你是开发人员,你可以用它来了解代码补丁。Meld 还支持版本控制系统,如 Git、[Mercurial][8]、[Subversion][9] 等。
|
||||
|
||||
### Meld 的功能
|
||||
|
||||
![][10]
|
||||
|
||||
开源的 Meld 工具具有以下主要功能:
|
||||
|
||||
* 进行双向和三向差异比较
|
||||
* 就地编辑文件,差异比较立即更新。
|
||||
* 在差异和冲突之间进行导航
|
||||
* 通过插入、更改和冲突相应地标示出全局和局部差异,使其可视化
|
||||
* 使用正则文本过滤来忽略某些差异。
|
||||
* 语法高亮显示
|
||||
* 比较两个或三个目录,看是否有新增加、缺失和更改的文件。
|
||||
* 将一些文件排除在比较之外
|
||||
* 支持流行的版本控制系统,如 Git、Mercurial、Bazaar 和 SVN。
|
||||
* 支持多种国际语言
|
||||
* 开源 GPL v2 许可证
|
||||
* 既可用于 Linux,也可用于 Windows。
|
||||
|
||||
|
||||
|
||||
### 在 Linux 上安装 Meld
|
||||
|
||||
Meld 是一个流行的应用程序,它在大多数 Linux 发行版的官方仓库中都有。
|
||||
|
||||
检查你的发行版的软件中心,看看 Meld 是否可用。
|
||||
|
||||
![Meld In Ubuntu Software Center][11]
|
||||
|
||||
另外,你也可以使用你的发行版的命令行包管理器来安装 Meld。在 [Ubuntu 上,它可以在 Universe 仓库中找到][12],并且可以[使用 apt 命令安装][13]:
|
||||
|
||||
```
|
||||
sudo apt install meld
|
||||
```
|
||||
|
||||
你可以在 GNOME 的 GitLab 仓库中找到 Meld 的源码:
|
||||
|
||||
[Meld Source Code][14]
|
||||
|
||||
### 它值得吗?
|
||||
|
||||
我知道[大多数现代开源编辑器][15]都有这个功能,但有时你只是想要一个简单的界面,而不需要安装额外的附加软件来比较文件。Meld 就为你提供了这样的功能。
|
||||
|
||||
你是否使用一些其他工具来检查文件之间的差异?是哪种工具呢?如果你用过 Meld,你有什么经验?请在评论区分享你的意见。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/meld-gui-diff/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://linuxhandbook.com/diff-command/
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/diff-command-complicated-output.png?resize=795%2C551&ssl=1
|
||||
[3]: https://itsfoss.com/gui-cli-tui/
|
||||
[4]: https://meldmerge.org
|
||||
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/file-comaprison-in-Linux-with-meld.png?resize=800%2C498&ssl=1
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/directory-comparison-in-Linux-with_meld.png?resize=800%2C497&ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/three-way-file-comaprison-with-meld-in-linux.png?resize=800%2C466&ssl=1
|
||||
[8]: https://www.mercurial-scm.org/
|
||||
[9]: https://subversion.apache.org/
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/11/meld-visual-diff.png?resize=786%2C455&ssl=1
|
||||
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/11/Meld-in-Ubuntu-Software-Center.png?resize=800%2C384&ssl=1
|
||||
[12]: https://itsfoss.com/ubuntu-repositories/
|
||||
[13]: https://itsfoss.com/apt-command-guide/
|
||||
[14]: https://gitlab.gnome.org/GNOME/meld
|
||||
[15]: https://itsfoss.com/best-modern-open-source-code-editors-for-linux/
|
Loading…
Reference in New Issue
Block a user