mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-25 00:50:15 +08:00
Merge branch 'master' of https://github.com/LCTT/TranslateProject into new
This commit is contained in:
commit
83680dce4c
@ -0,0 +1,198 @@
|
||||
如何在 Linux 中压缩和解压缩文件
|
||||
======
|
||||
|
||||

|
||||
|
||||
当在备份重要文件和通过网络发送大文件的时候,对文件进行压缩非常有用。请注意,压缩一个已经压缩过的文件会增加额外开销,因此你将会得到一个更大一些的文件。所以,请不要压缩已经压缩过的文件。在 GNU/Linux 中,有许多程序可以用来压缩和解压缩文件。在这篇教程中,我们仅学习其中两个应用程序。
|
||||
|
||||
在类 Unix 系统中,最常见的用来压缩文件的程序是:
|
||||
|
||||
1. gzip
|
||||
2. bzip2
|
||||
|
||||
### 1. 使用 gzip 程序来压缩和解压缩文件
|
||||
|
||||
`gzip` 是一个使用 Lempel-Ziv 编码(LZ77)算法来压缩和解压缩文件的实用工具。
|
||||
|
||||
#### 1.1 压缩文件
|
||||
|
||||
如果要压缩一个名为 `ostechnix.txt` 的文件,使之成为 gzip 格式的压缩文件,那么只需运行如下命令:
|
||||
|
||||
```
|
||||
$ gzip ostechnix.txt
|
||||
```
|
||||
|
||||
上面的命令运行结束之后,将会出现一个名为 `ostechnix.txt.gz` 的 gzip 格式压缩文件,代替了原始的 `ostechnix.txt` 文件。
|
||||
|
||||
`gzip` 命令还可以有其他用法。一个有趣的例子是,我们可以将一个特定命令的输出通过管道传递,然后作为 `gzip` 程序的输入来创建一个压缩文件。看下面的命令:
|
||||
|
||||
```
|
||||
$ ls -l Downloads/ | gzip > ostechnix.txt.gz
|
||||
```
|
||||
|
||||
上面的命令将会创建一个 gzip 格式的压缩文件,文件的内容为 `Downloads` 目录的目录项。
|
||||
|
||||
#### 1.2 压缩文件并将输出写到新文件中(不覆盖原始文件)
|
||||
|
||||
默认情况下,`gzip` 程序会压缩给定文件,并以压缩文件替代原始文件。但是,你也可以保留原始文件,并将输出写到标准输出。比如,下面这个命令将会压缩 `ostechnix.txt` 文件,并将输出写入文件 `output.txt.gz`。
|
||||
|
||||
```
|
||||
$ gzip -c ostechnix.txt > output.txt.gz
|
||||
```
|
||||
|
||||
类似地,要解压缩一个 `gzip` 格式的压缩文件并指定输出文件的文件名,只需运行:
|
||||
|
||||
```
|
||||
$ gzip -c -d output.txt.gz > ostechnix1.txt
|
||||
```
|
||||
|
||||
上面的命令将会解压缩 `output.txt.gz` 文件,并将输出写入到文件 `ostechnix1.txt` 中。在上面两个例子中,原始文件均不会被删除。
|
||||
|
||||
#### 1.3 解压缩文件
|
||||
|
||||
如果要解压缩 `ostechnix.txt.gz` 文件,并以原始未压缩版本的文件来代替它,那么只需运行:
|
||||
|
||||
```
|
||||
$ gzip -d ostechnix.txt.gz
|
||||
```
|
||||
|
||||
我们也可以使用 `gunzip` 程序来解压缩文件:
|
||||
|
||||
```
|
||||
$ gunzip ostechnix.txt.gz
|
||||
```
|
||||
|
||||
#### 1.4 在不解压缩的情况下查看压缩文件的内容
|
||||
|
||||
如果你想在不解压缩的情况下,使用 `gzip` 程序查看压缩文件的内容,那么可以像下面这样使用 `-c` 选项:
|
||||
|
||||
```
|
||||
$ gunzip -c ostechnix1.txt.gz
|
||||
```
|
||||
|
||||
或者,你也可以像下面这样使用 `zcat` 程序:
|
||||
|
||||
```
|
||||
$ zcat ostechnix.txt.gz
|
||||
```
|
||||
|
||||
你也可以通过管道将输出传递给 `less` 命令,从而一页一页的来查看输出,就像下面这样:
|
||||
|
||||
```
|
||||
$ gunzip -c ostechnix1.txt.gz | less
|
||||
$ zcat ostechnix.txt.gz | less
|
||||
```
|
||||
|
||||
另外,`zless` 程序也能够实现和上面的管道同样的功能。
|
||||
|
||||
```
|
||||
$ zless ostechnix1.txt.gz
|
||||
```
|
||||
|
||||
#### 1.5 使用 gzip 压缩文件并指定压缩级别
|
||||
|
||||
`gzip` 的另外一个显著优点是支持压缩级别。它支持下面给出的 3 个压缩级别:
|
||||
|
||||
* **1** – 最快 (最差)
|
||||
* **9** – 最慢 (最好)
|
||||
* **6** – 默认级别
|
||||
|
||||
要压缩名为 `ostechnix.txt` 的文件,使之成为“最好”压缩级别的 gzip 压缩文件,可以运行:
|
||||
|
||||
```
|
||||
$ gzip -9 ostechnix.txt
|
||||
```
|
||||
|
||||
#### 1.6 连接多个压缩文件
|
||||
|
||||
我们也可以把多个需要压缩的文件压缩到同一个文件中。如何实现呢?看下面这个例子。
|
||||
|
||||
```
|
||||
$ gzip -c ostechnix1.txt > output.txt.gz
|
||||
$ gzip -c ostechnix2.txt >> output.txt.gz
|
||||
```
|
||||
|
||||
上面的两个命令将会压缩文件 `ostechnix1.txt` 和 `ostechnix2.txt`,并将输出保存到一个文件 `output.txt.gz` 中。
|
||||
|
||||
你可以通过下面其中任何一个命令,在不解压缩的情况下,查看两个文件 `ostechnix1.txt` 和 `ostechnix2.txt` 的内容:
|
||||
|
||||
```
|
||||
$ gunzip -c output.txt.gz
|
||||
$ gunzip -c output.txt
|
||||
$ zcat output.txt.gz
|
||||
$ zcat output.txt
|
||||
```
|
||||
|
||||
如果你想了解关于 `gzip` 的更多细节,请参阅它的 man 手册。
|
||||
|
||||
```
|
||||
$ man gzip
|
||||
```
|
||||
|
||||
### 2. 使用 bzip2 程序来压缩和解压缩文件
|
||||
|
||||
`bzip2` 和 `gzip` 非常类似,但是 `bzip2` 使用的是 Burrows-Wheeler 块排序压缩算法,并使用<ruby>哈夫曼<rt>Huffman</rt></ruby>编码。使用 `bzip2` 压缩的文件以 “.bz2” 扩展结尾。
|
||||
|
||||
正如我上面所说的, `bzip2` 的用法和 `gzip` 几乎完全相同。只需在上面的例子中将 `gzip` 换成 `bzip2`,将 `gunzip` 换成 `bunzip2`,将 `zcat` 换成 `bzcat` 即可。
|
||||
|
||||
要使用 `bzip2` 压缩一个文件,并以压缩后的文件取而代之,只需运行:
|
||||
|
||||
```
|
||||
$ bzip2 ostechnix.txt
|
||||
```
|
||||
|
||||
如果你不想替换原始文件,那么可以使用 `-c` 选项,并把输出写入到新文件中。
|
||||
|
||||
```
|
||||
$ bzip2 -c ostechnix.txt > output.txt.bz2
|
||||
```
|
||||
|
||||
如果要解压缩文件,则运行:
|
||||
|
||||
```
|
||||
$ bzip2 -d ostechnix.txt.bz2
|
||||
```
|
||||
|
||||
或者,
|
||||
|
||||
```
|
||||
$ bunzip2 ostechnix.txt.bz2
|
||||
```
|
||||
|
||||
如果要在不解压缩的情况下查看一个压缩文件的内容,则运行:
|
||||
|
||||
```
|
||||
$ bunzip2 -c ostechnix.txt.bz2
|
||||
```
|
||||
|
||||
或者,
|
||||
|
||||
```
|
||||
$ bzcat ostechnix.txt.bz2
|
||||
```
|
||||
|
||||
如果你想了解关于 `bzip2` 的更多细节,请参阅它的 man 手册。
|
||||
|
||||
```
|
||||
$ man bzip2
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
在这篇教程中,我们学习了 `gzip` 和 `bzip2` 程序是什么,并通过 GNU/Linux 下的一些例子学习了如何使用它们来压缩和解压缩文件。接下来,我们将要学习如何在 Linux 中将文件和目录归档。
|
||||
|
||||
干杯!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-compress-and-decompress-files-in-linux/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.ostechnix.com/author/sk/
|
@ -1,3 +1,5 @@
|
||||
translating---geekpi
|
||||
|
||||
How to build a URL shortener with Apache
|
||||
======
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
5 tips to improve productivity with zsh
|
||||
======
|
||||
|
||||
### **[翻译中] by tnuoccalanosrep**
|
||||
|
||||

|
||||
|
||||
The Z shell known as [zsh][1] is a [shell][2] for Linux/Unix-like operating systems. It has similarities to other shells in the `sh` (Bourne shell) family, such as as `bash` and `ksh`, but it provides many advanced features and powerful command line editing options, such as enhanced Tab completion.
|
||||
|
@ -1,3 +1,5 @@
|
||||
XiatianSummer translating
|
||||
|
||||
13 Keyboard Shortcut Every Ubuntu 18.04 User Should Know
|
||||
======
|
||||
Knowing keyboard shortcuts increase your productivity. Here are some useful Ubuntu shortcut keys that will help you use Ubuntu like a pro.
|
||||
|
@ -0,0 +1,62 @@
|
||||
Know Your Storage: Block, File & Object
|
||||
======
|
||||
|
||||

|
||||
|
||||
Dealing with the tremendous amount of data generated today presents a big challenge for companies who create or consume such data. It’s a challenge for tech companies that are dealing with related storage issues.
|
||||
|
||||
“Data is growing exponentially each year, and we find that the majority of data growth is due to increased consumption and industries adopting transformational projects to expand value. Certainly, the Internet of Things (IoT) has contributed greatly to data growth, but the key challenge for software-defined storage is how to address the use cases associated with data growth,” said Michael St. Jean, principal product marketing manager, Red Hat Storage.
|
||||
|
||||
Every challenge is an opportunity. “The deluge of data being generated by old and new sources today is certainly presenting us with opportunities to meet our customers escalating needs in the areas of scale, performance, resiliency, and governance,” said Tad Brockway, General Manager for Azure Storage, Media and Edge.
|
||||
|
||||
### Trinity of modern software-defined storage
|
||||
|
||||
There are three different kinds of storage solutions -- block, file, and object -- each serving a different purpose while working with the others.
|
||||
|
||||
Block storage is the oldest form of data storage, where data is stored in fixed-length blocks or chunks of data. Block storage is used in enterprise storage environments and usually is accessed using Fibre Channel or iSCSI interface. “Block storage requires an application to map where the data is stored on the storage device,” according to SUSE’s Larry Morris, Sr. Product Manager, Software Defined Storage.
|
||||
|
||||
Block storage is virtualized in storage area network and software defined storage systems, which are abstracted logical devices that reside on a shared hardware infrastructure and are created and presented to the host operating system of a server, virtual server, or hypervisor via protocols like SCSI, SATA, SAS, FCP, FCoE, or iSCSI.
|
||||
|
||||
“Block storage splits a single storage volume (like a virtual or cloud storage node, or a good old fashioned hard disk) into individual instances known as blocks,” said St. Jean.
|
||||
|
||||
Each block exists independently and can be formatted with its own data transfer protocol and operating system — giving users complete configuration autonomy. Because block storage systems aren’t burdened with the same investigative file-finding duties as the file storage systems, block storage is a faster storage system. Pairing that speed with configuration flexibility makes block storage ideal for raw server storage or rich media databases.
|
||||
|
||||
Block storage can be used to host operating systems, applications, databases, entire virtual machines and containers. Traditionally, block storage can only be accessed by individual machine, or machines in a cluster, to which it has been presented.
|
||||
|
||||
### File-based storage
|
||||
|
||||
File-based storage uses a filesystem to map where the data is stored on the storage device. It’s a dominant technology used on direct- and networked-attached storage system, and it takes care of two things: organizing data and representing it to users. “With file storage, data is arranged on the server side in the exact same format as the clients see it. This allows the user to request a file by some unique identifier — like a name, location, or URL — which is communicated to the storage system using specific data transfer protocols,” said St. Jean.
|
||||
|
||||
The result is a type of hierarchical file structure that can be navigated from top to bottom. File storage is layered on top of block storage, allowing users to see and access data as files and folders, but restricting access to the blocks that stand up those files and folders.
|
||||
|
||||
“File storage is typically represented by shared filesystems like NFS and CIFS/SMB that can be accessed by many servers over an IP network. Access can be controlled at a file, directory, and export level via user and group permissions. File storage can be used to store files needed by multiple users and machines, application binaries, databases, virtual machines, and can be used by containers,” explained Brockway.
|
||||
|
||||
### Object storage
|
||||
|
||||
Object storage is the newest form of data storage, and it provides a repository for unstructured data which separates the content from the indexing and allows the concatenation of multiple files into an object. An object is a piece of data paired with any associated metadata that provides context about the bytes contained within the object (things like how old or big the data is). Those two things together — the data and metadata — make an object.
|
||||
|
||||
One advantage of object storage is the unique identifier associated with each piece of data. Accessing the data involves using the unique identifier and does not require the application or user to know where the data is actually stored. Object data is accessed through APIs.
|
||||
|
||||
“The data stored in objects is uncompressed and unencrypted, and the objects themselves are arranged in object stores (a central repository filled with many other objects) or containers (a package that contains all of the files an application needs to run). Objects, object stores, and containers are very flat in nature — compared to the hierarchical structure of file storage systems — which allow them to be accessed very quickly at huge scale,” explained St. Jean.
|
||||
|
||||
Object stores can scale to many petabytes to accommodate the largest datasets and are a great choice for images, audio, video, logs, backups, and data used by analytics services.
|
||||
|
||||
### Conclusion
|
||||
|
||||
Now you know about the various types of storage and how they are used. Stay tuned to learn more about software-defined storage as we examine the topic in the future.
|
||||
|
||||
Join us at [Open Source Summit + Embedded Linux Conference Europe][1] in Edinburgh, UK on October 22-24, 2018, for 100+ sessions on Linux, Cloud, Containers, AI, Community, and more.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/2018/9/know-your-storage-block-file-object
|
||||
|
||||
作者:[Swapnil Bhartiya][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/arnieswap
|
||||
[1]: https://events.linuxfoundation.org/events/elc-openiot-europe-2018/
|
@ -1,3 +1,5 @@
|
||||
XiatianSummer translating
|
||||
|
||||
Visualize Disk Usage On Your Linux System
|
||||
======
|
||||
|
||||
|
@ -0,0 +1,124 @@
|
||||
How To Configure Mouse Support For Linux Virtual Consoles
|
||||
======
|
||||
|
||||

|
||||
|
||||
I use Oracle VirtualBox to test various Unix-like operating systems. Most of my VMs are headless servers that does not have graphical desktop environment. For a long time, I have been wondering how can we use the mouse in the text-based terminals in headless Linux servers. Thanks to **GPM** , today I learned that we can use Mouse in virtual consoles for copy and paste operations. **GPM** , acronym for **G** eneral **P** urpose **M** ouse, is a daemon that helps you to configure mouse support for Linux virtual consoles. Please do not confuse GPM with **GDM** (GNOME Display manager). Both serves entirely different purpose.
|
||||
|
||||
GPM is especially useful in the following scenarios:
|
||||
|
||||
* New Linux server installations or for systems that cannot or do not use an X windows system by default, like Arch Linux and Gentoo.
|
||||
* Use copy/paste operations around in the virtual terminals/consoles.
|
||||
* Use copy/paste in text-based editors and browsers (Eg. emacs, lynx).
|
||||
* Use copy/paste in text file managers (Eg. Ranger, Midnight commander).
|
||||
|
||||
|
||||
|
||||
In this brief tutorial, we are going to see how to use Mouse in Text-based terminals in Unix-like operating systems.
|
||||
|
||||
### Installing GPM
|
||||
|
||||
To enable mouse support in Text-only Linux systems, install GPM package. It is available in the default repositories of most Linux distributions.
|
||||
|
||||
On Arch Linux and its variants like Antergos, Manjaro Linux, run the following command to install GPM:
|
||||
|
||||
```
|
||||
$ sudo pacman -S gpm
|
||||
```
|
||||
|
||||
On Debian, Ubuntu, Linux Mint:
|
||||
|
||||
```
|
||||
$ sudo apt install gpm
|
||||
```
|
||||
|
||||
On Fedora:
|
||||
|
||||
```
|
||||
$ sudo dnf install gpm
|
||||
```
|
||||
|
||||
On openSUSE:
|
||||
|
||||
```
|
||||
$ sudo zypper install gpm
|
||||
```
|
||||
|
||||
Once installed, enable and start GPM service using the following commands:
|
||||
|
||||
```
|
||||
$ sudo systemctl enable gpm
|
||||
$ sudo systemctl start gpm
|
||||
```
|
||||
|
||||
In Debian-based systems, gpm service will be automatically started after you installed it, so you need not to manually start the service as shown above.
|
||||
|
||||
### Configure Mouse Support For Linux Virtual Consoles
|
||||
|
||||
There is no special configuration required. GPM will start working as soon as you installed it and started gpm service.
|
||||
|
||||
Have a look at the following screenshot of my Ubuntu 18.04 LTS server before installing GPM:
|
||||
|
||||

|
||||
|
||||
As you see in the above screenshot, there is no visible Mouse pointer in my Ubuntu 18.04 LTS headless server. Only a blinking cursor and it won’t let me to select a text, copy/paste text using mouse. In CLI-only Linux servers, the mouse is literally not useful at all.
|
||||
|
||||
Now check the following screenshot of Ubuntu 18.04 LTS server after installing GPM:
|
||||
|
||||

|
||||
|
||||
See? I can now be able to select the text.
|
||||
|
||||
To select, copy and paste text, do the following:
|
||||
|
||||
* To select text, press the left mouse button and drag the mouse.
|
||||
* Once you selected the text, release the left mouse button and paste text in the same or another console by pressing the middle mouse button.
|
||||
* The right button is used to extend the selection, like in `xterm’.
|
||||
* If you’re using two-button mouse, use the right button to paste text.
|
||||
|
||||
|
||||
|
||||
It’s that simple!
|
||||
|
||||
Like I already said, GPM works just fine and there is no extra configuration needed. Here is the sample contents of GPM configuration file **/etc/gpm.conf** (or `/etc/conf.d/gpm` in some distributions):
|
||||
|
||||
```
|
||||
# protected from evaluation (i.e. by quoting them).
|
||||
#
|
||||
# This file is used by /etc/init.d/gpm and can be modified by
|
||||
# "dpkg-reconfigure gpm" or by hand at your option.
|
||||
#
|
||||
device=/dev/input/mice
|
||||
responsiveness=
|
||||
repeat_type=none
|
||||
type=exps2
|
||||
append=''
|
||||
sample_rate=
|
||||
```
|
||||
|
||||
In my example, I use USB mouse. If you’re using different mouse, you might have to change the values of **device=/dev/input/mice** and **type=exps2** parameters.
|
||||
|
||||
For more details, refer man pages.
|
||||
|
||||
```
|
||||
$ man gpm
|
||||
```
|
||||
|
||||
And, that’s all for now. Hope this was useful. More good stuffs to come. Stay tuned!
|
||||
|
||||
Cheers!
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-configure-mouse-support-for-linux-virtual-consoles/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
@ -0,0 +1,335 @@
|
||||
How subroutine signatures work in Perl 6
|
||||
======
|
||||
In the fourth article in this series comparing Perl 5 to Perl 6, learn how signatures work in Perl 6.
|
||||
|
||||

|
||||
|
||||
In the [first article][1] in this series comparing Perl 5 to Perl 6, we looked into some of the issues you might encounter when migrating code into Perl 6. In the [second article][2], we examined how garbage collection works in Perl 6, and in the [third article][3], we looked at how containers replaced references in Perl 6. Here in the fourth article, we will focus on (subroutine) signatures in Perl 6 and how they differ from those in Perl 5.
|
||||
|
||||
### Experimental signatures in Perl 5
|
||||
|
||||
If you're migrating from Perl 5 code to Perl 6, you're probably not using the [experimental signature feature][4] that became available in Perl 5.20 or any of the older CPAN modules like [signatures][5], [Function::Parameters][6], or any of the other Perl 5 modules on CPAN with ["signature" in their name][7].
|
||||
|
||||
Also, in my experience, [prototypes][8] haven't been used very often in the Perl programs out in the world (e.g., the [DarkPAN][9] ).
|
||||
|
||||
For these reasons, I will compare Perl 6 functionality only with the most common use of "classic" Perl 5 argument passing.
|
||||
|
||||
### Argument passing in Perl 5
|
||||
|
||||
All arguments you pass to a Perl 5 subroutine are flattened and put into the automatically defined `@_` array variable inside. That is basically all Perl 5 does with passing arguments to subroutines. Nothing more, nothing less. There are, however, several idioms in Perl 5 that take it from there. The most common (I would say "standard") idiom in my experience is:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my ($foo, $bar) = @_;
|
||||
# actually do something with $foo and $bar
|
||||
}
|
||||
```
|
||||
|
||||
This idiom performs a list assignment (copy) to two (new) lexical variables. This way of accessing the arguments to a subroutine is also supported in Perl 6, but it's intended just as a way to make migrations easier.
|
||||
|
||||
If you expect a fixed number of arguments followed by a variable number of arguments, the following idiom is typically used:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my $foo = shift;
|
||||
my $bar = shift;
|
||||
for (@_) {
|
||||
# do something for each element in @_
|
||||
}
|
||||
}do_something
|
||||
```
|
||||
|
||||
This idiom depends on the magic behavior of [shift][10], which shifts from `@_` in this context. If the subroutine is intended to be called as a method, something like this is usually seen:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my $self = shift;
|
||||
# do something with $self
|
||||
}do_something
|
||||
```
|
||||
|
||||
as the first argument passed is the [invocant][11] in Perl 5.
|
||||
|
||||
By the way, this idiom can also be written in the first idiom:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my ($foo, $bar, @rest) = @_;
|
||||
for (@rest) {
|
||||
# do something for each element in @rest
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
But that would be less efficient, as it would involve copying a potentially long list of values.
|
||||
|
||||
The third idiom revolves on directly accessing the `@_` array.
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub sum_two {
|
||||
return $_[0] + $_[1]; # return the sum of the two parameters
|
||||
}sum_two
|
||||
```
|
||||
|
||||
This idiom is typically used for small, one-line subroutines, as it is one of the most efficient ways of handling arguments because no copying takes place.
|
||||
|
||||
This idiom is also used if you want to change any variable that is passed as a parameter. Since the elements in `@_` are aliases to any variables specified (in Perl 6 you would say: "are bound to the variables"), it is possible to change the contents:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub make42 {
|
||||
$_[0] = 42;
|
||||
}
|
||||
my $a = 666;
|
||||
make42($a);
|
||||
say $a; # 42
|
||||
```
|
||||
|
||||
### Named arguments in Perl 5
|
||||
|
||||
Named arguments (as such) don't exist in Perl 5. But there is an often-used idiom that effectively mimics named arguments:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my %named = @_;
|
||||
if (exists %named{bar}) {
|
||||
# do stuff if named variable "bar" exists
|
||||
}
|
||||
}do_somethingbar
|
||||
```
|
||||
|
||||
This initializes the hash `%named` by alternately taking a key and a value from the `@_` array. If you call a subroutine with arguments using the fat-comma syntax:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
frobnicate( bar => 42 );
|
||||
```
|
||||
|
||||
it will pass two values, `"foo"` and `42`, which will be placed into the `%named` hash as the value `42` associated with key `"foo"`. But the same thing would have happened if you had specified:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
frobnicate( "bar", 42 );
|
||||
```
|
||||
|
||||
The `=>` is syntactic sugar for automatically quoting the left side. Otherwise, it functions just like a comma (hence the name "fat comma").
|
||||
|
||||
If a subroutine is called as a method with named arguments, this idiom is combined with the standard idiom:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my ($self, %named) = @_;
|
||||
# do something with $self and %named
|
||||
}
|
||||
```
|
||||
|
||||
alternatively:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my $self = shift;
|
||||
my %named = @_;
|
||||
# do something with $self and %named
|
||||
}do_something
|
||||
```
|
||||
|
||||
### Argument passing in Perl 6
|
||||
|
||||
In their simplest form, subroutine signatures in Perl 6 are very much like the "standard" idiom of Perl 5. But instead of being part of the code, they are part of the definition of the subroutine, and you don't need to do the assignment:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub do-something($foo, $bar) {
|
||||
# actually do something with $foo and $bar
|
||||
}
|
||||
```
|
||||
|
||||
versus:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub do_something {
|
||||
my ($foo, $bar) = @_;
|
||||
# actually do something with $foo and $bar
|
||||
}
|
||||
```
|
||||
|
||||
In Perl 6, the `($foo, $bar)` part is called the signature of the subroutine.
|
||||
|
||||
Since Perl 6 has an actual `method` keyword, it is not necessary to take the invocant into account, as that is automatically available with the `self` term:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
class Foo {
|
||||
method do-something-else($foo, $bar) {
|
||||
# do something else with self, $foo and $bar
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Such parameters are called positional parameters in Perl 6. Unless indicated otherwise, positional parameters must be specified when calling the subroutine.
|
||||
|
||||
If you need the aliasing behavior of using `$_[0]` directly in Perl 5, you can mark the parameter as writable by specifying the `is rw` trait:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub make42($foo is rw) {
|
||||
$foo = 42;
|
||||
}
|
||||
my $a = 666;
|
||||
make42($a);
|
||||
say $a; # 42
|
||||
```
|
||||
|
||||
When you pass an array as an argument to a subroutine, it doesn't get flattened in Perl 6. You only need to accept an array as an array in the signature:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub handle-array(@a) {
|
||||
# do something with @a
|
||||
}
|
||||
my @foo = "a" .. "z";
|
||||
handle-array(@foo);
|
||||
```
|
||||
|
||||
You can pass any number of arrays:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub handle-two-arrays(@a, @b) {
|
||||
# do something with @a and @b
|
||||
}
|
||||
my @bar = 1..26;
|
||||
handle-two-arrays(@foo, @bar);
|
||||
```
|
||||
|
||||
If you want the ([variadic][12]) flattening semantics of Perl 5, you can indicate this with a so-called "slurpy array" by prefixing the array with an asterisk in the signature:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub slurp-an-array(*@values) {
|
||||
# do something with @values
|
||||
}
|
||||
slurp-an-array("foo", 42, "baz");slurpanarrayslurpanarray
|
||||
```
|
||||
|
||||
A slurpy array can occur only as the last positional parameter in a signature.
|
||||
|
||||
If you prefer to use the Perl 5 way of specifying parameters in Perl 6, you can do this by specifying a slurpy array `*@_` in the signature:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub do-like-5(*@_) {
|
||||
my ($foo, $bar) = @_;
|
||||
}
|
||||
```
|
||||
|
||||
### Named arguments in Perl 6
|
||||
|
||||
On the calling side, named arguments in Perl 6 can be expressed very similarly to how they are expressed in Perl 5:
|
||||
|
||||
```
|
||||
# Perl 5 and Perl 6
|
||||
frobnicate( bar => 42 );
|
||||
```
|
||||
|
||||
However, on the definition side of the subroutine, things are very different:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub frobnicate(:$bar) {
|
||||
# do something with $bar
|
||||
}
|
||||
```
|
||||
|
||||
The difference between an ordinary (positional) parameter and a named parameter is the colon, which precedes the [sigil][13] and the variable name in the definition:
|
||||
|
||||
```
|
||||
$foo # positional parameter, receives in $foo
|
||||
:$bar # named parameter "bar", receives in $bar
|
||||
```
|
||||
|
||||
Unless otherwise specified, named parameters are optional. If a named argument is not specified, the associated variable will contain the default value, which usually is the type object `Any`.
|
||||
|
||||
If you want to catch any (other) named arguments, you can use a so-called "slurpy hash." Just like the slurpy array, it is indicated with an asterisk before a hash:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub slurp-nameds(*%nameds) {
|
||||
say "Received: " ~ join ", ", sort keys %nameds;
|
||||
}
|
||||
slurp-nameds(foo => 42, bar => 666); # Received: bar, fooslurpnamedssayslurpnamedsfoobar
|
||||
```
|
||||
|
||||
As with the slurpy array, there can be only one slurpy hash in a signature, and it must be specified after any other named parameters.
|
||||
|
||||
Often you want to pass a named argument to a subroutine from a variable with the same name. In Perl 5 this looks like: `do_something(bar => $bar)`. In Perl 6, you can specify this in the same way: `do-something(bar => $bar)`. But you can also use a shortcut: `do-something(:$bar)`. This means less typing–and less chance of typos.
|
||||
|
||||
### Default values in Perl 6
|
||||
|
||||
Perl 5 has the following idiom for making parameters optional with a default value:
|
||||
|
||||
```
|
||||
# Perl 5
|
||||
sub dosomething_with_defaults {
|
||||
my $foo = @_ ? shift : 42;
|
||||
my $bar = @_ ? shift : 666;
|
||||
# actually do something with $foo and $bar
|
||||
}dosomething_with_defaults
|
||||
```
|
||||
|
||||
In Perl 6, you can specify default values as part of the signature by specifying an equal sign and an expression:
|
||||
|
||||
```
|
||||
# Perl 6
|
||||
sub dosomething-with-defaults($foo = 42, :$bar = 666) {
|
||||
# actually do something with $foo and $bar
|
||||
}
|
||||
```
|
||||
|
||||
Positional parameters become optional if a default value is specified for them. Named parameters stay optional regardless of any default value.
|
||||
|
||||
### Summary
|
||||
|
||||
Perl 6 has a way of describing how arguments to a subroutine should be captured into parameters of that subroutine. Positional parameters are indicated by their name and the appropriate sigil (e.g., `$foo`). Named parameters are prefixed with a colon (e.g. `:$bar`). Positional parameters can be marked as `is rw` to allow changing variables in the caller's scope.
|
||||
|
||||
Positional arguments can be flattened in a slurpy array, which is prefixed by an asterisk (e.g., `*@values`). Unexpected named arguments can be collected using a slurpy hash, which is also prefixed with an asterisk (e.g., `*%nameds`).
|
||||
|
||||
Default values can be specified inside the signature by adding an expression after an equal sign (e.g., `$foo = 42`), which makes that parameter optional.
|
||||
|
||||
Signatures in Perl 6 have many other interesting features, aside from the ones summarized here; if you want to know more about them, check out the Perl 6 [signature object documentation][14].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/9/signatures-perl-6
|
||||
|
||||
作者:[Elizabeth Mattijsen][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者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/lizmat
|
||||
[1]: https://opensource.com/article/18/7/migrating-perl-5-perl-6
|
||||
[2]: https://opensource.com/article/18/7/garbage-collection-perl-6
|
||||
[3]: https://opensource.com/article/18/7/containers-perl-6
|
||||
[4]: https://metacpan.org/pod/distribution/perl/pod/perlsub.pod#Signatures
|
||||
[5]: https://metacpan.org/pod/signatures
|
||||
[6]: https://metacpan.org/pod/Function::Parameters
|
||||
[7]: https://metacpan.org/search?q=signature
|
||||
[8]: https://metacpan.org/pod/perlsub#Prototypes
|
||||
[9]: http://modernperlbooks.com/mt/2009/02/the-darkpan-dependency-management-and-support-problem.html
|
||||
[10]: https://perldoc.perl.org/functions/shift.html
|
||||
[11]: https://docs.perl6.org/routine/invocant
|
||||
[12]: https://en.wikipedia.org/wiki/Variadic_function
|
||||
[13]: https://www.perl.com/article/on-sigils/
|
||||
[14]: https://docs.perl6.org/type/Signature
|
395
sources/tech/20180912 How to build rpm packages.md
Normal file
395
sources/tech/20180912 How to build rpm packages.md
Normal file
@ -0,0 +1,395 @@
|
||||
How to build rpm packages
|
||||
======
|
||||
|
||||
Save time and effort installing files and scripts across multiple hosts.
|
||||
|
||||

|
||||
|
||||
I have used rpm-based package managers to install software on Red Hat and Fedora Linux since I started using Linux more than 20 years ago. I have used the **rpm** program itself, **yum** , and **DNF** , which is a close descendant of yum, to install and update packages on my Linux hosts. The yum and DNF tools are wrappers around the rpm utility that provide additional functionality, such as the ability to find and install package dependencies.
|
||||
|
||||
Over the years I have created a number of Bash scripts, some of which have separate configuration files, that I like to install on most of my new computers and virtual machines. It reached the point that it took a great deal of time to install all of these packages, so I decided to automate that process by creating an rpm package that I could copy to the target hosts and install all of these files in their proper locations. Although the **rpm** tool was formerly used to build rpm packages, that function was removed and a new tool,was created to build new rpms.
|
||||
|
||||
When I started this project, I found very little information about creating rpm packages, but I managed to find a book, Maximum RPM, that helped me figure it out. That book is now somewhat out of date, as is the vast majority of information I have found. It is also out of print, and used copies go for hundreds of dollars. The online version of [Maximum RPM][1] is available at no charge and is kept up to date. The [RPM website][2] also has links to other websites that have a lot of documentation about rpm. What other information there is tends to be brief and apparently assumes that you already have a good deal of knowledge about the process.
|
||||
|
||||
In addition, every one of the documents I found assumes that the code needs to be compiled from sources as in a development environment. I am not a developer. I am a sysadmin, and we sysadmins have different needs because we don’t—or we shouldn’t—compile code to use for administrative tasks; we should use shell scripts. So we have no source code in the sense that it is something that needs to be compiled into binary executables. What we have is a source that is also the executable.
|
||||
|
||||
For the most part, this project should be performed as the non-root user student. Rpms should never be built by root, but only by non-privileged users. I will indicate which parts should be performed as root and which by a non-root, unprivileged user.
|
||||
|
||||
### Preparation
|
||||
|
||||
First, open one terminal session and `su` to root. Be sure to use the `-` option to ensure that the complete root environment is enabled. I do not believe that sysadmins should use `sudo` for any administrative tasks. Find out why in my personal blog post: [Real SysAdmins don’t sudo][3].
|
||||
|
||||
```
|
||||
[student@testvm1 ~]$ su -
|
||||
Password:
|
||||
[root@testvm1 ~]#
|
||||
```
|
||||
|
||||
Create a student user that can be used for this project and set a password for that user.
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# useradd -c "Student User" student
|
||||
[root@testvm1 ~]# passwd student
|
||||
Changing password for user student.
|
||||
New password: <Enter the password>
|
||||
Retype new password: <Enter the password>
|
||||
passwd: all authentication tokens updated successfully.
|
||||
[root@testvm1 ~]#
|
||||
```
|
||||
|
||||
Building rpm packages requires the `rpm-build` package, which is likely not already installed. Install it now as root. Note that this command will also install several dependencies. The number may vary, depending upon the packages already installed on your host; it installed a total of 17 packages on my test VM, which is pretty minimal.
|
||||
|
||||
```
|
||||
dnf install -y rpm-build
|
||||
```
|
||||
|
||||
The rest of this project should be performed as the user student unless otherwise explicitly directed. Open another terminal session and use `su` to switch to that user to perform the rest of these steps. Download a tarball that I have prepared of a development directory structure, utils.tar, from GitHub using the following command:
|
||||
|
||||
```
|
||||
wget https://github.com/opensourceway/how-to-rpm/raw/master/utils.tar
|
||||
```
|
||||
|
||||
This tarball includes all of the files and Bash scripts that will be installed by the final rpm. There is also a complete spec file, which you can use to build the rpm. We will go into detail about each section of the spec file.
|
||||
|
||||
As user student, using your home directory as your present working directory (pwd), untar the tarball.
|
||||
|
||||
```
|
||||
[student@testvm1 ~]$ cd ; tar -xvf utils.tar
|
||||
```
|
||||
|
||||
Use the `tree` command to verify that the directory structure of ~/development and the contained files looks like the following output:
|
||||
|
||||
```
|
||||
[student@testvm1 ~]$ tree development/
|
||||
development/
|
||||
├── license
|
||||
│ ├── Copyright.and.GPL.Notice.txt
|
||||
│ └── GPL_LICENSE.txt
|
||||
├── scripts
|
||||
│ ├── create_motd
|
||||
│ ├── die
|
||||
│ ├── mymotd
|
||||
│ └── sysdata
|
||||
└── spec
|
||||
└── utils.spec
|
||||
|
||||
3 directories, 7 files
|
||||
[student@testvm1 ~]$
|
||||
```
|
||||
|
||||
The `mymotd` script creates a “Message Of The Day” data stream that is sent to stdout. The `create_motd` script runs the `mymotd` scripts and redirects the output to the /etc/motd file. This file is used to display a daily message to users who log in remotely using SSH.
|
||||
|
||||
The `die` script is my own script that wraps the `kill` command in a bit of code that can find running programs that match a specified string and kill them. It uses `kill -9` to ensure that they cannot ignore the kill message.
|
||||
|
||||
The `sysdata` script can spew tens of thousands of lines of data about your computer hardware, the installed version of Linux, all installed packages, and the metadata of your hard drives. I use it to document the state of a host at a point in time. I can later use it for reference. I used to do this to maintain a record of hosts that I installed for customers.
|
||||
|
||||
You may need to change ownership of these files and directories to student.student. Do this, if necessary, using the following command:
|
||||
|
||||
```
|
||||
chown -R student.student development
|
||||
```
|
||||
|
||||
Most of the files and directories in this tree will be installed on Fedora systems by the rpm you create during this project.
|
||||
|
||||
### Creating the build directory structure
|
||||
|
||||
The `rpmbuild` command requires a very specific directory structure. You must create this directory structure yourself because no automated way is provided. Create the following directory structure in your home directory:
|
||||
|
||||
```
|
||||
~ ─ rpmbuild
|
||||
├── RPMS
|
||||
│ └── noarch
|
||||
├── SOURCES
|
||||
├── SPECS
|
||||
└── SRPMS
|
||||
```
|
||||
|
||||
We will not create the rpmbuild/RPMS/X86_64 directory because that would be architecture-specific for 64-bit compiled binaries. We have shell scripts that are not architecture-specific. In reality, we won’t be using the SRPMS directory either, which would contain source files for the compiler.
|
||||
|
||||
### Examining the spec file
|
||||
|
||||
Each spec file has a number of sections, some of which may be ignored or omitted, depending upon the specific circumstances of the rpm build. This particular spec file is not an example of a minimal file required to work, but it is a good example of a moderately complex spec file that packages files that do not need to be compiled. If a compile were required, it would be performed in the `%build` section, which is omitted from this spec file because it is not required.
|
||||
|
||||
#### Preamble
|
||||
|
||||
This is the only section of the spec file that does not have a label. It consists of much of the information you see when the command `rpm -qi [Package Name]` is run. Each datum is a single line which consists of a tag, which identifies it and text data for the value of the tag.
|
||||
|
||||
```
|
||||
###############################################################################
|
||||
# Spec file for utils
|
||||
################################################################################
|
||||
# Configured to be built by user student or other non-root user
|
||||
################################################################################
|
||||
#
|
||||
Summary: Utility scripts for testing RPM creation
|
||||
Name: utils
|
||||
Version: 1.0.0
|
||||
Release: 1
|
||||
License: GPL
|
||||
URL: http://www.both.org
|
||||
Group: System
|
||||
Packager: David Both
|
||||
Requires: bash
|
||||
Requires: screen
|
||||
Requires: mc
|
||||
Requires: dmidecode
|
||||
BuildRoot: ~/rpmbuild/
|
||||
|
||||
# Build with the following syntax:
|
||||
# rpmbuild --target noarch -bb utils.spec
|
||||
```
|
||||
|
||||
Comment lines are ignored by the `rpmbuild` program. I always like to add a comment to this section that contains the exact syntax of the `rpmbuild` command required to create the package. The Summary tag is a short description of the package. The Name, Version, and Release tags are used to create the name of the rpm file, as in utils-1.00-1.rpm. Incrementing the release and version numbers lets you create rpms that can be used to update older ones.
|
||||
|
||||
The License tag defines the license under which the package is released. I always use a variation of the GPL. Specifying the license is important to clarify the fact that the software contained in the package is open source. This is also why I included the license and GPL statement in the files that will be installed.
|
||||
|
||||
The URL is usually the web page of the project or project owner. In this case, it is my personal web page.
|
||||
|
||||
The Group tag is interesting and is usually used for GUI applications. The value of the Group tag determines which group of icons in the applications menu will contain the icon for the executable in this package. Used in conjunction with the Icon tag (which we are not using here), the Group tag allows adding the icon and the required information to launch a program into the applications menu structure.
|
||||
|
||||
The Packager tag is used to specify the person or organization responsible for maintaining and creating the package.
|
||||
|
||||
The Requires statements define the dependencies for this rpm. Each is a package name. If one of the specified packages is not present, the DNF installation utility will try to locate it in one of the defined repositories defined in /etc/yum.repos.d and install it if it exists. If DNF cannot find one or more of the required packages, it will throw an error indicating which packages are missing and terminate.
|
||||
|
||||
The BuildRoot line specifies the top-level directory in which the `rpmbuild` tool will find the spec file and in which it will create temporary directories while it builds the package. The finished package will be stored in the noarch subdirectory that we specified earlier. The comment showing the command syntax used to build this package includes the option `–target noarch`, which defines the target architecture. Because these are Bash scripts, they are not associated with a specific CPU architecture. If this option were omitted, the build would be targeted to the architecture of the CPU on which the build is being performed.
|
||||
|
||||
The `rpmbuild` program can target many different architectures, and using the `--target` option allows us to build architecture-specific packages on a host with a different architecture from the one on which the build is performed. So I could build a package intended for use on an i686 architecture on an x86_64 host, and vice versa.
|
||||
|
||||
Change the packager name to yours and the URL to your own website if you have one.
|
||||
|
||||
#### %description
|
||||
|
||||
The `%description` section of the spec file contains a description of the rpm package. It can be very short or can contain many lines of information. Our `%description` section is rather terse.
|
||||
|
||||
```
|
||||
%description
|
||||
A collection of utility scripts for testing RPM creation.
|
||||
```
|
||||
|
||||
#### %prep
|
||||
|
||||
The `%prep` section is the first script that is executed during the build process. This script is not executed during the installation of the package.
|
||||
|
||||
This script is just a Bash shell script. It prepares the build directory, creating directories used for the build as required and copying the appropriate files into their respective directories. This would include the sources required for a complete compile as part of the build.
|
||||
|
||||
The $RPM_BUILD_ROOT directory represents the root directory of an installed system. The directories created in the $RPM_BUILD_ROOT directory are fully qualified paths, such as /user/local/share/utils, /usr/local/bin, and so on, in a live filesystem.
|
||||
|
||||
In the case of our package, we have no pre-compile sources as all of our programs are Bash scripts. So we simply copy those scripts and other files into the directories where they belong in the installed system.
|
||||
|
||||
```
|
||||
%prep
|
||||
################################################################################
|
||||
# Create the build tree and copy the files from the development directories #
|
||||
# into the build tree. #
|
||||
################################################################################
|
||||
echo "BUILDROOT = $RPM_BUILD_ROOT"
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/local/bin/
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/local/share/utils
|
||||
|
||||
cp /home/student/development/utils/scripts/* $RPM_BUILD_ROOT/usr/local/bin
|
||||
cp /home/student/development/utils/license/* $RPM_BUILD_ROOT/usr/local/share/utils
|
||||
cp /home/student/development/utils/spec/* $RPM_BUILD_ROOT/usr/local/share/utils
|
||||
|
||||
exit
|
||||
```
|
||||
|
||||
Note that the exit statement at the end of this section is required.
|
||||
|
||||
#### %files
|
||||
|
||||
This section of the spec file defines the files to be installed and their locations in the directory tree. It also specifies the file attributes and the owner and group owner for each file to be installed. The file permissions and ownerships are optional, but I recommend that they be explicitly set to eliminate any chance for those attributes to be incorrect or ambiguous when installed. Directories are created as required during the installation if they do not already exist.
|
||||
|
||||
```
|
||||
%files
|
||||
%attr(0744, root, root) /usr/local/bin/*
|
||||
%attr(0644, root, root) /usr/local/share/utils/*
|
||||
```
|
||||
|
||||
#### %pre
|
||||
|
||||
This section is empty in our lab project’s spec file. This would be the place to put any scripts that are required to run during installation of the rpm but prior to the installation of the files.
|
||||
|
||||
#### %post
|
||||
|
||||
This section of the spec file is another Bash script. This one runs after the installation of files. This section can be pretty much anything you need or want it to be, including creating files, running system commands, and restarting services to reinitialize them after making configuration changes. The `%post` script for our rpm package performs some of those tasks.
|
||||
|
||||
```
|
||||
%post
|
||||
################################################################################
|
||||
# Set up MOTD scripts #
|
||||
################################################################################
|
||||
cd /etc
|
||||
# Save the old MOTD if it exists
|
||||
if [ -e motd ]
|
||||
then
|
||||
cp motd motd.orig
|
||||
fi
|
||||
# If not there already, Add link to create_motd to cron.daily
|
||||
cd /etc/cron.daily
|
||||
if [ ! -e create_motd ]
|
||||
then
|
||||
ln -s /usr/local/bin/create_motd
|
||||
fi
|
||||
# create the MOTD for the first time
|
||||
/usr/local/bin/mymotd > /etc/motd
|
||||
```
|
||||
|
||||
The comments included in this script should make its purpose clear.
|
||||
|
||||
#### %postun
|
||||
|
||||
This section contains a script that would be run after the rpm package is uninstalled. Using rpm or DNF to remove a package removes all of the files listed in the `%files` section, but it does not remove files or links created by the `%post` section, so we need to handle that in this section.
|
||||
|
||||
This script usually consists of cleanup tasks that simply erasing the files previously installed by the rpm cannot accomplish. In the case of our package, it includes removing the link created by the `%post` script and restoring the saved original of the motd file.
|
||||
|
||||
```
|
||||
%postun
|
||||
# remove installed files and links
|
||||
rm /etc/cron.daily/create_motd
|
||||
|
||||
# Restore the original MOTD if it was backed up
|
||||
if [ -e /etc/motd.orig ]
|
||||
then
|
||||
mv -f /etc/motd.orig /etc/motd
|
||||
fi
|
||||
```
|
||||
|
||||
#### %clean
|
||||
|
||||
This Bash script performs cleanup after the rpm build process. The two lines in the `%clean` section below remove the build directories created by the `rpm-build` command. In many cases, additional cleanup may also be required.
|
||||
|
||||
```
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT/usr/local/bin
|
||||
rm -rf $RPM_BUILD_ROOT/usr/local/share/utils
|
||||
```
|
||||
|
||||
#### %changelog
|
||||
|
||||
This optional text section contains a list of changes to the rpm and files it contains. The newest changes are recorded at the top of this section.
|
||||
|
||||
```
|
||||
%changelog
|
||||
* Wed Aug 29 2018 Your Name <Youremail@yourdomain.com>
|
||||
- The original package includes several useful scripts. it is
|
||||
primarily intended to be used to illustrate the process of
|
||||
building an RPM.
|
||||
```
|
||||
|
||||
Replace the data in the header line with your own name and email address.
|
||||
|
||||
### Building the rpm
|
||||
|
||||
The spec file must be in the SPECS directory of the rpmbuild tree. I find it easiest to create a link to the actual spec file in that directory so that it can be edited in the development directory and there is no need to copy it to the SPECS directory. Make the SPECS directory your pwd, then create the link.
|
||||
|
||||
```
|
||||
cd ~/rpmbuild/SPECS/
|
||||
ln -s ~/development/spec/utils.spec
|
||||
```
|
||||
|
||||
Run the following command to build the rpm. It should only take a moment to create the rpm if no errors occur.
|
||||
|
||||
```
|
||||
rpmbuild --target noarch -bb utils.spec
|
||||
```
|
||||
|
||||
Check in the ~/rpmbuild/RPMS/noarch directory to verify that the new rpm exists there.
|
||||
|
||||
```
|
||||
[student@testvm1 ~]$ cd rpmbuild/RPMS/noarch/
|
||||
[student@testvm1 noarch]$ ll
|
||||
total 24
|
||||
-rw-rw-r--. 1 student student 24364 Aug 30 10:00 utils-1.0.0-1.noarch.rpm
|
||||
[student@testvm1 noarch]$
|
||||
```
|
||||
|
||||
### Testing the rpm
|
||||
|
||||
As root, install the rpm to verify that it installs correctly and that the files are installed in the correct directories. The exact name of the rpm will depend upon the values you used for the tags in the Preamble section, but if you used the ones in the sample, the rpm name will be as shown in the sample command below:
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# cd /home/student/rpmbuild/RPMS/noarch/
|
||||
[root@testvm1 noarch]# ll
|
||||
total 24
|
||||
-rw-rw-r--. 1 student student 24364 Aug 30 10:00 utils-1.0.0-1.noarch.rpm
|
||||
[root@testvm1 noarch]# rpm -ivh utils-1.0.0-1.noarch.rpm
|
||||
Preparing... ################################# [100%]
|
||||
Updating / installing...
|
||||
1:utils-1.0.0-1 ################################# [100%]
|
||||
```
|
||||
|
||||
Check /usr/local/bin to ensure that the new files are there. You should also verify that the create_motd link in /etc/cron.daily has been created.
|
||||
|
||||
Use the `rpm -q --changelog utils` command to view the changelog. View the files installed by the package using the `rpm -ql utils` command (that is a lowercase L in `ql`.)
|
||||
|
||||
```
|
||||
[root@testvm1 noarch]# rpm -q --changelog utils
|
||||
* Wed Aug 29 2018 Your Name <Youremail@yourdomain.com>
|
||||
- The original package includes several useful scripts. it is
|
||||
primarily intended to be used to illustrate the process of
|
||||
building an RPM.
|
||||
|
||||
[root@testvm1 noarch]# rpm -ql utils
|
||||
/usr/local/bin/create_motd
|
||||
/usr/local/bin/die
|
||||
/usr/local/bin/mymotd
|
||||
/usr/local/bin/sysdata
|
||||
/usr/local/share/utils/Copyright.and.GPL.Notice.txt
|
||||
/usr/local/share/utils/GPL_LICENSE.txt
|
||||
/usr/local/share/utils/utils.spec
|
||||
[root@testvm1 noarch]#
|
||||
```
|
||||
|
||||
Remove the package.
|
||||
|
||||
```
|
||||
rpm -e utils
|
||||
```
|
||||
|
||||
### Experimenting
|
||||
|
||||
Now you will change the spec file to require a package that does not exist. This will simulate a dependency that cannot be met. Add the following line immediately under the existing Requires line:
|
||||
|
||||
```
|
||||
Requires: badrequire
|
||||
```
|
||||
|
||||
Build the package and attempt to install it. What message is displayed?
|
||||
|
||||
We used the `rpm` command to install and delete the `utils` package. Try installing the package with yum or DNF. You must be in the same directory as the package or specify the full path to the package for this to work.
|
||||
|
||||
### Conclusion
|
||||
|
||||
There are many tags and a couple sections that we did not cover in this look at the basics of creating an rpm package. The resources listed below can provide more information. Building rpm packages is not difficult; you just need the right information. I hope this helps you—it took me months to figure things out on my own.
|
||||
|
||||
We did not cover building from source code, but if you are a developer, that should be a simple step from this point.
|
||||
|
||||
Creating rpm packages is another good way to be a lazy sysadmin and save time and effort. It provides an easy method for distributing and installing the scripts and other files that we as sysadmins need to install on many hosts.
|
||||
|
||||
### Resources
|
||||
|
||||
* Edward C. Baily, Maximum RPM, Sams Publishing, 2000, ISBN 0-672-31105-4
|
||||
|
||||
* Edward C. Baily, [Maximum RPM][1], updated online version
|
||||
|
||||
* [RPM Documentation][4]: This web page lists most of the available online documentation for rpm. It includes many links to other websites and information about rpm.
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/9/how-build-rpm-packages
|
||||
|
||||
作者:[David Both][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者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/dboth
|
||||
[1]: http://ftp.rpm.org/max-rpm/
|
||||
[2]: http://rpm.org/index.html
|
||||
[3]: http://www.both.org/?p=960
|
||||
[4]: http://rpm.org/documentation.html
|
201
sources/tech/20180912 How to turn on an LED with Fedora IoT.md
Normal file
201
sources/tech/20180912 How to turn on an LED with Fedora IoT.md
Normal file
@ -0,0 +1,201 @@
|
||||
How to turn on an LED with Fedora IoT
|
||||
======
|
||||
|
||||

|
||||
|
||||
Do you enjoy running Fedora, containers, and have a Raspberry Pi? What about using all three together to play with LEDs? This article introduces Fedora IoT and shows you how to install a preview image on a Raspberry Pi. You’ll also learn how to interact with GPIO in order to light up an LED.
|
||||
|
||||
### What is Fedora IoT?
|
||||
|
||||
Fedora IoT is one of the current Fedora Project objectives, with a plan to become a full Fedora Edition. The result will be a system that runs on ARM (aarch64 only at the moment) devices such as the Raspberry Pi, as well as on the x86_64 architecture.
|
||||
|
||||
![][1]
|
||||
|
||||
Fedora IoT is based on OSTree, like [Fedora Silverblue][2] and the former [Atomic Host][3].
|
||||
|
||||
### Download and install Fedora IoT
|
||||
|
||||
The official Fedora IoT images are coming with the Fedora 29 release. However, in the meantime you can download a [Fedora 28-based image][4] for this experiment.
|
||||
|
||||
You have two options to install the system: either flash the SD card using a dd command, or use a fedora-arm-installer tool. The Fedora Wiki offers more information about [setting up a physical device][5] for IoT. Also, remember that you might need to resize the third partition.
|
||||
|
||||
Once you insert the SD card into the device, you’ll need to complete the installation by creating a user. This step requires either a serial connection, or a HDMI display with a keyboard to interact with the device.
|
||||
|
||||
When the system is installed and ready, the next step is to configure a network connection. Log in to the system with the user you have just created choose one of the following options:
|
||||
|
||||
* If you need to configure your network manually, run a command similar to the following. Remember to use the right addresses for your network:
|
||||
```
|
||||
$ nmcli connection add con-name cable ipv4.addresses \
|
||||
192.168.0.10/24 ipv4.gateway 192.168.0.1 \
|
||||
connection.autoconnect true ipv4.dns "8.8.8.8,1.1.1.1" \
|
||||
type ethernet ifname eth0 ipv4.method manual
|
||||
|
||||
```
|
||||
|
||||
* If there’s a DHCP service on your network, run a command like this:
|
||||
|
||||
```
|
||||
$ nmcli con add type ethernet con-name cable ifname eth0
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### **The GPIO interface in Fedora**
|
||||
|
||||
Many tutorials about GPIO on Linux focus on a legacy GPIO sysfis interface. This interface is deprecated, and the upstream Linux kernel community plan to remove it completely, due to security and other issues.
|
||||
|
||||
The Fedora kernel is already compiled without this legacy interface, so there’s no /sys/class/gpio on the system. This tutorial uses a new character device /dev/gpiochipN provided by the upstream kernel. This is the current way of interacting with GPIO.
|
||||
|
||||
To interact with this new device, you need to use a library and a set of command line interface tools. The common command line tools such as echo or cat won’t work with this device.
|
||||
|
||||
You can install the CLI tools by installing the libgpiod-utils package. A corresponding Python library is provided by the python3-libgpiod package.
|
||||
|
||||
### **Creating a container with Podman**
|
||||
|
||||
[Podman][6] is a container runtime with a command line interface similar to Docker. The big advantage of Podman is it doesn’t run any daemon in the background. That’s especially useful for devices with limited resources. Podman also allows you to start containerized services with systemd unit files. Plus, it has many additional features.
|
||||
|
||||
We’ll create a container in these two steps:
|
||||
|
||||
1. Create a layered image containing the required packages.
|
||||
2. Create a new container starting from our image.
|
||||
|
||||
|
||||
|
||||
First, create a file Dockerfile with the content below. This tells podman to build an image based on the latest Fedora image available in the registry. Then it updates the system inside and installs some packages:
|
||||
|
||||
```
|
||||
FROM fedora:latest
|
||||
RUN dnf -y update
|
||||
RUN dnf -y install libgpiod-utils python3-libgpiod
|
||||
|
||||
```
|
||||
|
||||
You have created a build recipe of a container image based on the latest Fedora with updates, plus packages to interact with GPIO.
|
||||
|
||||
Now, run the following command to build your base image:
|
||||
|
||||
```
|
||||
$ sudo podman build --tag fedora:gpiobase -f ./Dockerfile
|
||||
|
||||
```
|
||||
|
||||
You have just created your custom image with all the bits in place. You can play with this base container images as many times as you want without installing the packages every time you run it.
|
||||
|
||||
### Working with Podman
|
||||
|
||||
To verify the image is present, run the following command:
|
||||
|
||||
```
|
||||
$ sudo podman images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
localhost/fedora gpiobase 67a2b2b93b4b 10 minutes ago 488MB
|
||||
docker.io/library/fedora latest c18042d7fac6 2 days ago 300MB
|
||||
|
||||
```
|
||||
|
||||
Now, start the container and do some actual experiments. Containers are normally isolated and don’t have an access to the host system, including the GPIO interface. Therefore, you need to mount it inside while starting the container. To do this, use the –device option in the following command:
|
||||
|
||||
```
|
||||
$ sudo podman run -it --name gpioexperiment --device=/dev/gpiochip0 localhost/fedora:gpiobase /bin/bash
|
||||
|
||||
```
|
||||
|
||||
You are now inside the running container. Before you move on, here are some more container commands. For now, exit the container by typing exit or pressing **Ctrl+D**.
|
||||
|
||||
To list the the existing containers, including those not currently running, such as the one you just created, run:
|
||||
|
||||
```
|
||||
$ sudo podman container ls -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
64e661d5d4e8 localhost/fedora:gpiobase /bin/bash 37 seconds ago Exited (0) Less than a second ago gpioexperiment
|
||||
|
||||
```
|
||||
|
||||
To create a new container, run this command:
|
||||
|
||||
```
|
||||
$ sudo podman run -it --name newexperiment --device=/dev/gpiochip0 localhost/fedora:gpiobase /bin/bash
|
||||
|
||||
```
|
||||
|
||||
Delete it with the following command:
|
||||
|
||||
```
|
||||
$ sudo podman rm newexperiment
|
||||
|
||||
```
|
||||
|
||||
### **Turn on an LED**
|
||||
|
||||
Now you can use the container you already created. If you exited from the container, start it again with this command:
|
||||
|
||||
```
|
||||
$ sudo podman start -ia gpioexperiment
|
||||
|
||||
```
|
||||
|
||||
As already discussed, you can use the CLI tools provided by the libgpiod-utils package in Fedora. To list the available GPIO chips, run:
|
||||
|
||||
```
|
||||
$ gpiodetect
|
||||
gpiochip0 [pinctrl-bcm2835] (54 lines)
|
||||
|
||||
```
|
||||
|
||||
To get the list of the lines exposed by a specific chip, run:
|
||||
|
||||
```
|
||||
$ gpioinfo gpiochip0
|
||||
|
||||
```
|
||||
|
||||
Notice there’s no correlation between the number of physical pins and the number of lines printed by the previous command. What’s important is the BCM number, as shown on [pinout.xyz][7]. It is not advised to play with the lines that don’t have a corresponding BCM number.
|
||||
|
||||
Now, connect an LED to the physical pin 40, that is BCM 21. Remember: the shorter leg of the LED (the negative leg, called the cathode) must be connected to a GND pin of the Raspberry Pi with a 330 ohm resistor, and the long leg (the anode) to the physical pin 40.
|
||||
|
||||
To turn the LED on, run the following command. It will stay on until you press **Ctrl+C** :
|
||||
|
||||
```
|
||||
$ gpioset --mode=wait gpiochip0 21=1
|
||||
|
||||
```
|
||||
|
||||
To light it up for a certain period of time, add the -b (run in the background) and -s NUM (how many seconds) parameters, as shown below. For example, to light the LED for 5 seconds, run:
|
||||
|
||||
```
|
||||
$ gpioset -b -s 5 --mode=time gpiochip0 21=1
|
||||
|
||||
```
|
||||
|
||||
Another useful command is gpioget. It gets the status of a pin (high or low), and can be useful to detect buttons and switches.
|
||||
|
||||
![Closeup of LED connection with GPIO][8]
|
||||
|
||||
### **Conclusion**
|
||||
|
||||
You can also play with LEDs using Python — [there are some examples here][9]. And you can also use the i2c devices inside the container as well. In addition, Podman is not strictly related to this Fedora edition. You can install it on any existing Fedora Edition, or try it on the two new OSTree-based systems in Fedora: [Fedora Silverblue][2] and [Fedora CoreOS][10].
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/turnon-led-fedora-iot/
|
||||
|
||||
作者:[Alessio Ciregia][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://alciregi.id.fedoraproject.org/
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2018/08/oled-1024x768.png
|
||||
[2]: https://teamsilverblue.org/
|
||||
[3]: https://www.projectatomic.io/
|
||||
[4]: https://kojipkgs.fedoraproject.org/compose/iot/latest-Fedora-IoT-28/compose/IoT/
|
||||
[5]: https://fedoraproject.org/wiki/InternetOfThings/GettingStarted#Setting_up_a_Physical_Device
|
||||
[6]: https://github.com/containers/libpod
|
||||
[7]: https://pinout.xyz/
|
||||
[8]: https://fedoramagazine.org/wp-content/uploads/2018/08/breadboard-1024x768.png
|
||||
[9]: https://github.com/brgl/libgpiod/tree/master/bindings/python/examples
|
||||
[10]: https://coreos.fedoraproject.org/
|
@ -1,73 +1,72 @@
|
||||
何为开源?
|
||||
何谓开源编程?
|
||||
======
|
||||
> 开源就是丢一些代码到 GitHub 上。了解一下它是什么,以及不是什么?
|
||||
|
||||

|
||||
|
||||
简单来说,开源项目就是书写一些大家可以随意取用、修改的代码。但你肯定听过关于Go语言的那个笑话,说 Go 语言简单到看一眼就可以明白规则,但需要一辈子去学会运用它。其实写开源代码也是这样的。往 GitHub, Bitbucket, SourceForge 等网站或者是你自己的博客,网站上丢几行代码不是难事,但想要有效地操作,还需要个人的努力付出,和高瞻远瞩。
|
||||
最简单的来说,开源编程就是编写一些大家可以随意取用、修改的代码。但你肯定听过关于 Go 语言的那个老笑话,说 Go 语言“简单到看一眼就可以明白规则,但需要一辈子去学会运用它”。其实写开源代码也是这样的。往 GitHub、Bitbucket、 SourceForge 等网站或者是你自己的博客或网站上丢几行代码不是难事,但想要卓有成效,还需要个人的努力付出和高瞻远瞩。
|
||||
|
||||

|
||||
|
||||
### 我们对开源项目的误解
|
||||
### 我们对开源编程的误解
|
||||
|
||||
首先我要说清楚一点:把你的代码写在 GitHub 的公开资源库中并不意味着把你的代码开源化了。在几乎全世界,根本不用创作者做什么,只要作品形成,版权就随之而生了。在创作者进行授权之前,只有作者可以行使版权相关的权力。未经创作者授权的代码,不论有多少人在使用,都是一颗定时炸弹,只有愚蠢的人才会去用它。
|
||||
首先我要说清楚一点:把你的代码放在 GitHub 的公开仓库中并不意味着把你的代码开源了。在几乎全世界,根本不用创作者做什么,只要作品形成,版权就随之而生了。在创作者进行授权之前,只有作者可以行使版权相关的权力。未经创作者授权的代码,不论有多少人在使用,都是一颗定时炸弹,只有愚蠢的人才会去用它。
|
||||
|
||||
有些创作者很善良,认为“很明显我的代码是免费提供给大家使用的。”,他也并不想起诉那些用了他的代码的人,但这并不意味着这些代码可以放心使用。不论在你眼中创作者们多么善良,他们都是有权力起诉任何使用、修改代码,或未经明确授权就将代码嵌入的人。
|
||||
有些创作者很善良,认为“很明显我的代码是免费提供给大家使用的。”,他也并不想起诉那些用了他的代码的人,但这并不意味着这些代码可以放心使用。不论在你眼中创作者们多么善良,他们都是*有权力*起诉任何使用、修改代码,或未经明确授权就将代码嵌入的人。
|
||||
|
||||
很明显,你不应该在没有指定开源许可证的情况下将你的源代码发布到网上然后期望别人使用它并为其做出贡献,我建议你也尽量避免使用这种代码,甚至疑似未授权的也不要使用。如果你开发了一个函数和实现,它和之前一个疑似未授权代码很像,源代码作者就可以对你就侵权提起诉讼。
|
||||
很明显,你不应该在没有指定开源许可证的情况下将你的源代码发布到网上然后期望别人使用它并为其做出贡献,我建议你也尽量避免使用这种代码,甚至疑似未授权的也不要使用。如果你开发了一个函数和例程,它和之前一个疑似未授权代码很像,源代码作者就可以对你就侵权提起诉讼。
|
||||
|
||||
举个例子, Jill Schmill 写了 AwesomeLib 然后未明确授权就把它放到了 GitHub 上,就算 Jill Schmill 不起诉任何人,只要她把 AwesomeLib 的完整版权都卖给 EvilCorp,EvilCorp 就会起诉之前违规使用这段代码的人。这种行为就好像是埋下了计算机安全隐患,总有一天会为人所用。
|
||||
|
||||
没有许可证的代码的危险的,以上。
|
||||
没有许可证的代码的危险的,切记。
|
||||
|
||||
### 选择恰当的开源许可证
|
||||
|
||||
假设你证要写一个新程序,而且打算把它放在开源平台上,你需要选择最贴合你需求的[许可证][1]。和宣传中说的一样,你可以从 [GitHub-curated][2] 上得到你想要的信息。这个网站设置得像个小问卷,特别方便快捷,点几下就能找到合适的许可证。
|
||||
假设你正要写一个新程序,而且打算让人们以开源的方式使用它,你需要做的就是选择最贴合你需求的[许可证][1]。和宣传中说的一样,你可以从 GitHub 所支持的 [choosealicense.com][2] 开始。这个网站设置得像个简单的问卷,特别方便快捷,点几下就能找到合适的许可证。
|
||||
|
||||
没有许可证的代码的危险的,切记。
|
||||
警示:在选择许可证时不要过于自负,如果你选的是 [Apache 许可证][3] 或者 [GPLv3][4] 这种广为使用的许可证,人们很容易理解其对于权利的规划,你也不需要请律师来排查其中的漏洞。你选择的许可证使用的人越少,带来的麻烦越多。
|
||||
|
||||
在选择许可证时不要过于自负,如果你选的是 [Apache License][3] 或者 [GPLv3][4] 这种广为使用的许可证,人们很容易理解其对于权利的规划,你也不需要请律师来排查其中的漏洞。你选择的许可证使用的人越少,带来的麻烦越多。
|
||||
最重要的一点是:*千万不要试图自己编造许可证!*自己编造许可证会给大家带来更多的困惑和困扰,不要这样做。如果在现有的许可证中确实找不到你需要的条款,你可以在现有的许可证中附加上你的要求,并且重点标注出来,提醒使用者们注意。
|
||||
|
||||
最重要的一点是:千万不要试图自己编造许可证!自己编造许可证会给大家带来更多的困惑和困扰,不要这样做。如果在现有的许可证中确实找不到你需要的程式,你可以在现有的许可证中附加上你的要求,并且重点标注出来,提醒使用者们注意。
|
||||
|
||||
我知道有些人会说:“我才懒得管什么许可证,我已经把代码发到公共域了。”但问题是,公共域的法律效力并不是受全世界认可的。在不同的国家,公共域的效力和表现形式不同。有些国家的政府管控下,你甚至不可以把自己的源代码发到公共域中。万幸,[Unlicense][5] 可以弥补这些漏洞,它语言简洁,但其效力为全世界认可。
|
||||
我知道有些人会说:“我才懒得管什么许可证,我已经把代码发到<ruby>公开领域<rt>public domain</rt></ruby>了。”但问题是,公开领域的法律效力并不是受全世界认可的。在不同的国家,公开领域的效力和表现形式不同。有些国家的政府管控下,你甚至不可以把自己的源代码发到公开领域中。万幸,[Unlicense][5] 可以弥补这些漏洞,它语言简洁,使用几个词清楚地描述了“就把它放到公开领域”,但其效力为全世界认可。
|
||||
|
||||
### 怎样引入许可证
|
||||
|
||||
确定使用哪个许可证之后,你需要明文指定它。如果你是在 GitHub 、 GitLab 或 BitBucket 这几个网站发布,你需要构建很多个文件夹,在根文件夹中,你应把许可证创建为一个以 LICENSE 命名的 txt 格式明文文件。
|
||||
确定使用哪个许可证之后,你需要清晰而无疑义地指定它。如果你是在 GitHub、 GitLab 或 BitBucket 这几个网站发布,你需要构建很多个文件夹,在根文件夹中,你应把许可证创建为一个以 `LICENSE.txt` 命名的明文文件。
|
||||
|
||||
创建 LICENSE.txt 这个文件之后还有其他事要做。你需要在每个有效文件的页眉中添加注释块来申明许可证。如果你使用的是一现有的许可证,这一步对你来说十分简便。一个 `# 项目名 (c)2018作者名, GPLv3 许可证,详情见 https://www.gnu.org/licenses/gpl-3.0.en.html` 这样的注释块比隐约指代的许可证的效力要强得多。
|
||||
创建 `LICENSE.txt` 这个文件之后还有其他事要做。你需要在每个有效文件的页眉中添加注释块来申明许可证。如果你使用的是一现有的许可证,这一步对你来说十分简便。一个 `# 项目名 (c)2018 作者名, GPLv3 许可证,详情见 https://www.gnu.org/licenses/gpl-3.0.en.html` 这样的注释块比隐约指代的许可证的效力要强得多。
|
||||
|
||||
如果你是要发布在自己的网站上,步骤也差不多。先创建 LICENSE.txt 文件,放入许可证,再表明许可证出处。
|
||||
如果你是要发布在自己的网站上,步骤也差不多。先创建 `LICENSE.txt` 文件,放入许可证,再表明许可证出处。
|
||||
|
||||
### 开源代码的不同之处
|
||||
|
||||
开源代码和专有代码的一个区别的开源代码写出来就是为了给别人看的。我是个40多岁的系统管理员,已经写过许许多多的代码。最开始我写代码是为了工作,为了解决公司的问题,所以其中大部分代码都是专有代码。这种代码的目的很简单,只要能在特定场合通过特定方式发挥作用就行。
|
||||
开源代码和专有代码的一个主要区别是开源代码写出来就是为了给别人看的。我是个 40 多岁的系统管理员,已经写过许许多多的代码。最开始我写代码是为了工作,为了解决公司的问题,所以其中大部分代码都是专有代码。这种代码的目的很简单,只要能在特定场合通过特定方式发挥作用就行。
|
||||
|
||||
开源代码则大不相同。在写开源代码时,你知道它可能会被用于各种各样的环境中。也许你的使用案例的环境条件很局限,但你仍旧希望它能在各种环境下发挥理想的效果。不同的人使用这些代码时,你会看到各类冲突,还有你没有考虑过的思路。虽然代码不一定要满足所有人,但最少它们可以顺利解决使用者遇到的问题,就算解决不了,也可以转换回常见的逻辑,不会给使用者添麻烦。(例如“第583行的内容除以零”就不能作为命令行参数正确的结果)
|
||||
开源代码则大不相同。在写开源代码时,你知道它可能会被用于各种各样的环境中。也许你的使用案例的环境条件很局限,但你仍旧希望它能在各种环境下发挥理想的效果。不同的人使用这些代码时,你会看到各类冲突,还有你没有考虑过的思路。虽然代码不一定要满足所有人,但最少它们可以顺利解决使用者遇到的问题,就算解决不了,也可以转换回常见的逻辑,不会给使用者添麻烦。(例如“第 583 行出现零除错误”就不能作为错误地提供命令行参数的响应结果)
|
||||
|
||||
你的源代码也可能逼疯你,尤其是在你一遍又一遍地修改错误的函数或是子过程后,终于出现了你希望的结果,这时你不会叹口气就继续下一个任务,你会把过程清理干净,因为你不会愿意别人看出你一遍遍尝试的痕迹。比如你会把 `$variable` `$lol`全都换成有意义的 `$iterationcounter` 和 `$modelname`。这意味着你要认真专业地进行注释(尽管对于头脑风暴中的你来说它并不难懂),但为了之后有更多的人可以使用你的代码,你会尽力去注释,但注意适可而止。
|
||||
你的源代码也可能逼疯你,尤其是在你一遍又一遍地修改错误的函数或是子过程后,终于出现了你希望的结果,这时你不会叹口气就继续下一个任务,你会把过程清理干净,因为你不会愿意别人看出你一遍遍尝试的痕迹。比如你会把 `$variable`、`$lol` 全都换成有意义的 `$iterationcounter` 和 `$modelname`。这意味着你要认真专业地进行注释(尽管对于头脑风暴中的你来说它并不难懂),但为了之后有更多的人可以使用你的代码,你会尽力去注释,但注意适可而止。
|
||||
|
||||
这个过程难免有些痛苦沮丧,毕竟这不是你常做的事,会有些不习惯。但它会使你成为一位更好的程序员,也会让你的代码升华。即使你的项目只有你在贡献,清理代码也会节约你后期的很多工作,相信我一年后你更新 app 时,你会庆幸自己现在写下的是 `$modelname`,还有清晰的注释,而不是什么不知名的数列,甚至连 `$lol`也不是。
|
||||
这个过程难免有些痛苦沮丧,毕竟这不是你常做的事,会有些不习惯。但它会使你成为一位更好的程序员,也会让你的代码升华。即使你的项目只有你一位贡献者,清理代码也会节约你后期的很多工作,相信我一年后你更新 app 时,你会庆幸自己现在写下的是 `$modelname`,还有清晰的注释,而不是什么不知名的数列,甚至连 `$lol`也不是。
|
||||
|
||||
### 你并不是为你一人而写
|
||||
|
||||
开源的真正核心并不是那些代码,是社区。更大的社区的项目维持的时间更长,也更容易为人们接受。因此不仅要加入社区,还要多多为社区发展贡献思路,让自己的项目能够为社区所用。
|
||||
|
||||
蝙蝠侠为了完成目标暗中独自花了很大功夫,你用不着这样,你可以登录 Twitter , Reddit, 或者给你项目的相关人士发邮件,发布你正在筹备新项目的消息,仔细聊聊项目的设计初衷和你的计划,让大家一起帮忙,向大家征集数据输入,类似的使用案例,把这些信息整合起来,用在你的代码里。你不用看所有的回复,但你要对它有个大概把握,这样在你之后完善时可以躲过一些陷阱。
|
||||
蝙蝠侠为了完成目标暗中独自花了很大功夫,你用不着这样,你可以登录 Twitter、 Reddit,或者给你项目的相关人士发邮件,发布你正在筹备新项目的消息,仔细聊聊项目的设计初衷和你的计划,让大家一起帮忙,向大家征集数据输入,类似的使用案例,把这些信息整合起来,用在你的代码里。你不用看所有的回复,但你要对它有个大概把握,这样在你之后完善时可以躲过一些陷阱。
|
||||
|
||||
不发首次通告这个过程还不算完整。如果你希望大家能够接受你的作品,并且使用它,你就要以此为初衷来设计。公众说不定可以帮到你,你不必对公开这件事如临大敌。所以不要闭门造车,既然你是为大家而写,那就开设一个真实、公开的项目,想象你在社区的监督下,认真地一步步完成它。
|
||||
|
||||
### 建立项目的方式
|
||||
|
||||
你可以在 GitHub, GitLab, or BitBucket 上免费注册账号来管理你的项目。注册之后,创建知识库,建立 README 文件,分配一个许可证,一步步写入代码。这样可以帮你建立好习惯,让你之后和现实中的团队一起工作时,也能目的清晰地朝着目标稳妥地进行工作。这样你做得越久,就越有兴趣。
|
||||
你可以在 GitHub、 GitLab 或 BitBucket 上免费注册账号来管理你的项目。注册之后,创建知识库,建立 `README` 文件,分配一个许可证,一步步写入代码。这样可以帮你建立好习惯,让你之后和现实中的团队一起工作时,也能目的清晰地朝着目标稳妥地进行工作。这样你做得越久,就越有兴趣。
|
||||
|
||||
用户们会开始对你产生兴趣,这会让你开心也会让你不爽,但你应该亲切礼貌地对待他们,就算他们很多人根本不知道你的项目做的是什么,你可以把文件给他们看,让他们了解你在干什么。有些还在犹豫的用户可以给你提个醒,告诉你最开始设计的用户范围中落下了哪些人。
|
||||
|
||||
如果你的项目很受用户青睐,总会有开发者出现,并表示出兴趣。这也许是好事,也可能激怒你。最开始你可能只会做简单的错误修正,但总有一天你会收到拉请求,有可能是特殊利基案例,它可能改变你项目的作用域,甚至改变你项目的初衷。你需要学会分辨哪个有贡献,根据这个决定合并哪个,婉拒哪个。
|
||||
如果你的项目很受用户青睐,总会有开发者出现,并表示出兴趣。这也许是好事,也可能激怒你。最开始你可能只会做简单的错误修正,但总有一天你会收到拉取请求,有可能是特殊利基案例,它可能改变你项目的作用域,甚至改变你项目的初衷。你需要学会分辨哪个有贡献,根据这个决定合并哪个,婉拒哪个。
|
||||
|
||||
### 我们为什么要开源?
|
||||
|
||||
开源听起来任务繁重,它也确实是这样。但它对你也有很多好处。它可以在无形之中磨练你,让你写出纯净持久的代码,也教会你与人沟通,团队协作。对于一位志向远大的专业开发者来说,它是最好的简历书写者。你的未来雇主很有可能点开你的知识库,了解你的能力范围;而你的开发者也有可能想带你进全球信息网络工作。
|
||||
开源听起来任务繁重,它也确实是这样。但它对你也有很多好处。它可以在无形之中磨练你,让你写出纯净持久的代码,也教会你与人沟通,团队协作。对于一位志向远大的专业开发者来说,它是最好的简历书写者。你的未来雇主很有可能点开你的仓库,了解你的能力范围;而社区项目的开发者也有可能给你带来工作。
|
||||
|
||||
最后,为开源工作,意味着个人的提升,因为你在做的事不是为了你一个人,这比养活自己重要得多。
|
||||
|
||||
@ -77,7 +76,7 @@ via: https://opensource.com/article/18/3/what-open-source-programming
|
||||
|
||||
作者:[Jim Salter][a]
|
||||
译者:[Valoniakim](https://github.com/Valoniakim)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
|
@ -1,211 +0,0 @@
|
||||
如何在 Linux 中压缩和解压缩文件
|
||||
======
|
||||
|
||||

|
||||
|
||||
当在备份重要文件和通过网络发送大文件的时候,对文件进行压缩非常有用。请注意,压缩一个已经压缩过的文件会增加额外开销,因此你将会得到一个更大一些的文件。所以,请不要压缩已经压缩过的文件。在 GNU/Linux 中,有许多程序可以用来压缩和解压缩文件。在这篇教程中,我们仅学习其中两个应用程序。
|
||||
|
||||
### 压缩和解压缩文件
|
||||
|
||||
在类 Unix 系统中,最常见的用来压缩文件的程序是:
|
||||
|
||||
1. gzip
|
||||
2. bzip2
|
||||
|
||||
|
||||
|
||||
##### 1\. 使用 Gzip 程序来压缩和解压缩文件
|
||||
|
||||
Gzip 是一个使用 Lempel-Ziv 编码(LZ77)算法来压缩和解压缩文件的实用工具。
|
||||
|
||||
**1.1 压缩文件**
|
||||
|
||||
如果要压缩一个名为 ostechnix.txt 的文件,使之成为 gzip 格式的压缩文件,那么只需运行如下命令:
|
||||
```
|
||||
$ gzip ostechnix.txt
|
||||
|
||||
```
|
||||
|
||||
上面的命令运行结束之后,将会出现一个名为 ostechnix.txt.gz 的 gzip 格式压缩文件,代替原始的 ostechnix.txt 文件。
|
||||
|
||||
gzip 命令还可以有其他用法。一个有趣的例子是,我们可以将一个特定命令的输出通过管道传递,然后作为 gzip 程序的输入来创建一个压缩文件。看下面的命令:
|
||||
```
|
||||
$ ls -l Downloads/ | gzip > ostechnix.txt.gz
|
||||
|
||||
```
|
||||
|
||||
上面的命令将会创建一个 gzip 格式的压缩文件,文件的内容为 “Downloads” 目录的目录项。
|
||||
|
||||
**1.2 压缩文件并将输出写到新文件中(不覆盖原始文件)
|
||||
**
|
||||
|
||||
默认情况下,gzip 程序会压缩给定文件,并以压缩文件替代原始文件。但是,你也可以保留原始文件,并将输出写到标准输出。比如,下面这个命令将会压缩 ostechnix.txt 文件,并将输出写入文件 output.txt.gz 。
|
||||
```
|
||||
$ gzip -c ostechnix.txt > output.txt.gz
|
||||
|
||||
```
|
||||
|
||||
类似地,要解压缩一个 gzip 格式的压缩文件并指定输出文件的文件名,只需运行:
|
||||
```
|
||||
$ gzip -c -d output.txt.gz > ostechnix1.txt
|
||||
|
||||
```
|
||||
|
||||
上面的命令将会解压缩 output.txt.gz 文件,并将输出写入到文件 ostechnix1.txt 中。在上面两个例子中,原始文件均不会被删除。
|
||||
|
||||
**1.3 解压缩文件**
|
||||
|
||||
如果要解压缩 ostechnix.txt.gz 文件,并以原始未压缩版本的文件来代替它,那么只需运行:
|
||||
```
|
||||
$ gzip -d ostechnix.txt.gz
|
||||
|
||||
```
|
||||
|
||||
我们也可以使用 gunzip 程序来解压缩文件:
|
||||
```
|
||||
$ gunzip ostechnix.txt.gz
|
||||
|
||||
```
|
||||
|
||||
**1.4 在不解压缩的情况下查看压缩文件的内容**
|
||||
|
||||
如果你想在不解压缩的情况下,使用 gzip 程序查看压缩文件的内容,那么可以像下面这样使用 -c 选项:
|
||||
```
|
||||
$ gunzip -c ostechnix1.txt.gz
|
||||
|
||||
```
|
||||
|
||||
或者,你也可以像下面这样使用 zcat 程序:
|
||||
```
|
||||
$ zcat ostechnix.txt.gz
|
||||
|
||||
```
|
||||
|
||||
你也可以通过管道将输出传递给 less 命令,从而一页一页的来查看输出,就像下面这样:
|
||||
```
|
||||
$ gunzip -c ostechnix1.txt.gz | less
|
||||
|
||||
$ zcat ostechnix.txt.gz | less
|
||||
|
||||
```
|
||||
|
||||
另外,zless 程序也能够实现和上面的管道同样的功能。
|
||||
```
|
||||
$ zless ostechnix1.txt.gz
|
||||
|
||||
```
|
||||
|
||||
**1.5 使用 gzip 压缩文件并指定压缩级别**
|
||||
|
||||
Gzip 的另外一个显著优点是支持压缩级别。它支持下面给出的 3 个压缩级别:
|
||||
|
||||
* **1** – 最快 (最差)
|
||||
* **9** – 最慢 (最好)
|
||||
* **6** – 默认级别
|
||||
|
||||
|
||||
|
||||
要压缩名为 ostechnix.txt 的文件,使之成为“最好”压缩级别的 gzip 压缩文件,可以运行:
|
||||
```
|
||||
$ gzip -9 ostechnix.txt
|
||||
|
||||
```
|
||||
|
||||
**1.6 连接多个压缩文件**
|
||||
|
||||
我们也可以把多个需要压缩的文件压缩到同一个文件中。如何实现呢?看下面这个例子。
|
||||
```
|
||||
$ gzip -c ostechnix1.txt > output.txt.gz
|
||||
|
||||
$ gzip -c ostechnix2.txt >> output.txt.gz
|
||||
|
||||
```
|
||||
|
||||
上面的两个命令将会压缩文件 ostechnix1.txt 和 ostechnix2.txt,并将输出保存到一个文件 output.txt.gz 中。
|
||||
|
||||
你可以通过下面其中任何一个命令,在不解压缩的情况下,查看两个文件 ostechnix1.txt 和 ostechnix2.txt 的内容:
|
||||
```
|
||||
$ gunzip -c output.txt.gz
|
||||
|
||||
$ gunzip -c output.txt
|
||||
|
||||
$ zcat output.txt.gz
|
||||
|
||||
$ zcat output.txt
|
||||
|
||||
```
|
||||
|
||||
如果你想了解关于 gzip 的更多细节,请参阅它的 man 手册。
|
||||
```
|
||||
$ man gzip
|
||||
|
||||
```
|
||||
|
||||
##### 2\. 使用 bzip2 程序来压缩和解压缩文件
|
||||
|
||||
bzip2 和 gzip 非常类似,但是 bzip2 使用的是 Burrows-Wheeler 块排序压缩算法,并使用<ruby>哈夫曼<rt>Huffman</rt></ruby>编码。使用 bzip2 压缩的文件以 “.bz2” 扩展结尾。
|
||||
|
||||
正如我上面所说的, bzip2 的用法和 gzip 几乎完全相同。只需在上面的例子中将 gzip 换成 bzip2,将 gunzip 换成 bunzip2,将 zcat 换成 bzcat 即可。
|
||||
|
||||
要使用 bzip2 压缩一个文件,并以压缩后的文件取而代之,只需运行:
|
||||
```
|
||||
$ bzip2 ostechnix.txt
|
||||
|
||||
```
|
||||
|
||||
如果你不想替换原始文件,那么可以使用 -c 选项,并把输出写入到新文件中。
|
||||
```
|
||||
$ bzip2 -c ostechnix.txt > output.txt.bz2
|
||||
|
||||
```
|
||||
|
||||
如果要解压缩文件,则运行:
|
||||
```
|
||||
$ bzip2 -d ostechnix.txt.bz2
|
||||
|
||||
```
|
||||
|
||||
或者,
|
||||
```
|
||||
$ bunzip2 ostechnix.txt.bz2
|
||||
|
||||
```
|
||||
|
||||
如果要在不解压缩的情况下查看一个压缩文件的内容,则运行:
|
||||
```
|
||||
$ bunzip2 -c ostechnix.txt.bz2
|
||||
|
||||
```
|
||||
|
||||
或者,
|
||||
```
|
||||
$ bzcat ostechnix.txt.bz2
|
||||
|
||||
```
|
||||
|
||||
如果你想了解关于 bzip2 的更多细节,请参阅它的 man 手册。
|
||||
```
|
||||
$ man bzip2
|
||||
|
||||
```
|
||||
|
||||
##### 总结
|
||||
|
||||
在这篇教程中,我们学习了 gzip 和 bzip2 程序是什么,并通过 GNU/Linux 下的一些例子学习了如何使用它们来压缩和解压缩文件。接下来,我们将要学习如何在 Linux 中将文件和目录归档。
|
||||
|
||||
干杯!
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-compress-and-decompress-files-in-linux/
|
||||
|
||||
作者:[SK][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.ostechnix.com/author/sk/
|
Loading…
Reference in New Issue
Block a user