mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
commit
c4ddf50168
59
published/20190312 When the web grew up- A browser story.md
Normal file
59
published/20190312 When the web grew up- A browser story.md
Normal file
@ -0,0 +1,59 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (XYenChi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13130-1.html)
|
||||
[#]: subject: (When the web grew up: A browser story)
|
||||
[#]: via: (https://opensource.com/article/19/3/when-web-grew)
|
||||
[#]: author: (Mike Bursell https://opensource.com/users/mikecamel)
|
||||
|
||||
Web 的成长,就是一篇浏览器的故事
|
||||
======
|
||||
|
||||
> 互联网诞生之时我的个人故事。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/18/161753qb8tytkc6bnxbavn.jpg)
|
||||
|
||||
最近,我和大家 [分享了][1] 我在 1994 年获得英国文学和神学学位离开大学后,如何在一个人们还不知道 Web 服务器是什么的世界里成功找到一份运维 Web 服务器的工作。我说的“世界”,并不仅仅指的是我工作的机构,而是泛指所有地方。Web 那时当真是全新的 —— 人们还正尝试理出头绪。
|
||||
|
||||
那并不是说我工作的地方(一家学术出版社)特别“懂” Web。这是个大部分人还在用 28.8K 猫(调制解调器,俗称“猫”)访问网页的世界。我还记得我拿到 33.6K 猫时有多激动。至少上下行速率不对称的日子已经过去了,[^1] 以前 1200/300 的带宽描述特别常见。这意味着(在同一家机构的)印刷人员制作的设计复杂、色彩缤纷、纤毫毕现的文档是完全不可能放在 Web 上的。我不能允许在网站的首页出现大于 40k 的 GIF 图片,这对我们的许多访问者来说是很难接受的。大于大约 60k 图片的会作为独立的图片,以缩略图链接过去。
|
||||
|
||||
如果说市场部只有这一点不喜欢,那是绝对是轻描淡写了。更糟的是布局问题。“浏览器决定如何布局文档,”我一遍又一遍地解释,“你可以使用标题或者段落,但是文档在页面上如何呈现并不取决于文档,而是取决于渲染器!”他们想控制这些,想要不同颜色的背景。后来明白了那些不能实现。我觉得我就像是参加了第一次讨论层叠样式表(CSS)的 W3C 会议,并进行了激烈地争论。关于文档编写者应控制布局的建议真令人厌恶。[^2] CSS 花了一些时间才被人们采用,与此同时,关心这些问题的人搭上了 PDF 这种到处都是安全问题的列车。
|
||||
|
||||
如何呈现文档不是唯一的问题。作为一个实体书出版社,对于市场部来说,拥有一个网站的全部意义在于,让客户(或者说潜在的客户)不仅知道一本书的内容,而且知道买这本书需要花多少钱。但这有一个问题,你看,互联网,包括快速发展的万维网,是开放的,是所有都免费的自由之地,没有人会在意钱;事实上,在那里谈钱是要回避和避免的。
|
||||
|
||||
我和主流“网民”的看法一致,认为没必要把价格信息放在线上。我老板,以及机构里相当多的人都持相反的意见。他们觉得消费者应该能够看到书要花多少钱。他们也觉得我的银行经理也会想看到我的账户里每个月进了多少钱,如果我不认同他们的观点的话,那我的收入就可能堪忧。
|
||||
|
||||
幸运的是,在我被炒鱿鱼之前,我已经自己认清了一些 —— 可能是在我开始迈入 Web 的几星期之后,Web 已经发生变化,有其他人公布他们的产品价格信息。这些新来者通常被那些从早期就开始运行 Web 服务器的老派人士所看不起,[^3] 但很明显,风向是往那边吹的。然而,这并不意味着我们的网站就赢得了战争。作为一个学术出版社,我们和大学共享一个域名(在 “ac.uk” 下)。大学不太相信发布价格信息是合适的,直到出版社的一些资深人士指出,普林斯顿大学出版社正在这样做,如果我们不做……看起来是不是有点傻?
|
||||
|
||||
有趣的事情还没完。在我担任站点管理员(“webmaster@…”)的短短几个月后,我们和其他很多网站一样开始看到了一种令人担忧的趋势。某些访问者可以轻而易举地让我们的 Web 服务器跪了。这些访问者使用了新的网页浏览器:网景浏览器(Netscape)。网景浏览器实在太恶劣了,它居然是多线程的。
|
||||
|
||||
这为什么是个问题呢?在网景浏览器之前,所有的浏览器都是单线程。它们一次只进行一个连接,所以即使一个页面有五张 GIF 图,[^4] 也会先请求 HTML 基本文件进行解析,然后下载第一张 GIF,完成,接着第二张,完成,如此类推。事实上,GIF 的顺序经常出错,使得页面加载得非常奇怪,但这也是常规思路。而粗暴的网景公司的人决定,它们可以同时打开多个连接到 Web 服务器,比如说,可以同时请求所有的 GIF!为什么这是个问题呢?好吧,问题就在于大多数 Web 服务器都是单线程的。它们不是设计来一次进行多个连接的。确实,我们运行的 HTTP 服务的软件(MacHTTP)是单线程的。尽管我们花钱购买了它(最初是共享软件),但我们用的这版无法同时处理多个请求。
|
||||
|
||||
互联网上爆发了大量讨论。这些网景公司的人以为他们是谁,能改变世界的运作方式?它应该如何工作?大家分成了不同阵营,就像所有的技术争论一样,双方都用各种技术热词互丢。问题是,网景浏览器不仅是多线程的,它也比其他的浏览器更好。非常多 Web 服务器代码维护者,包括 MacHTTP 作者 Chuck Shotton 在内,开始坐下来认真地在原有代码基础上更新了多线程测试版。几乎所有人立马转向测试版,它们变得稳定了,最终,浏览器要么采用了这种技术,变成多线程,要么就像所有过时产品一样销声匿迹了。[^6]
|
||||
|
||||
对我来说,这才是 Web 真正成长起来的时候。既不是网页展示的价格,也不是设计者能定义你能在网页上看到什么,[^8] 而是浏览器变得更易用,以及成千上万的浏览者向数百万浏览者转变的网络效应,使天平向消费者而不是生产者倾斜。在我的旅程中,还有更多故事,我将留待下次再谈。但从这时起,我的雇主开始看我们的月报,然后是周报、日报,并意识到这将是一件大事,真的需要关注。
|
||||
|
||||
[^1]: 它们又是怎么回来的?
|
||||
[^2]: 你可能不会惊讶,我还是在命令行里最开心。
|
||||
[^3]: 大约六个月前。
|
||||
[^4]: 莽撞,没错,但它确实发生了 [^5]
|
||||
[^5]: 噢,不,是 GIF 或 BMP,JPEG 还是个好主意,但还没有用上。
|
||||
[^6]: 没有真正的沉寂:总有一些坚持他们的首选解决方案具有技术上的优势,并哀叹互联网的其他人都是邪恶的死硬爱好者。 [^7]
|
||||
[^7]: 我不是唯一一个说“我还在用 Lynx”的人。
|
||||
[^8]: 我会指出,为那些有各种无障碍需求的人制造严重而持续的问题。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/when-web-grew
|
||||
|
||||
作者:[Mike Bursell][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[XYenChi](https://github.com/XYenChi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mikecamel
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/article/18/11/how-web-was-won
|
@ -0,0 +1,69 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (ShuyRoy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13109-1.html)
|
||||
[#]: subject: (Intel formally launches Optane for data center memory caching)
|
||||
[#]: via: (https://www.networkworld.com/article/3387117/intel-formally-launches-optane-for-data-center-memory-caching.html#tk.rss_all)
|
||||
[#]: author: (Andy Patrizio https://www.networkworld.com/author/Andy-Patrizio/)
|
||||
|
||||
英特尔 Optane:用于数据中心内存缓存
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/12/111720yq1rvxcncjdsjb0g.jpg)
|
||||
|
||||
> 英特尔推出了包含 3D Xpoint 内存技术的 Optane 持久内存产品线。英特尔的这个解决方案介乎于 DRAM 和 NAND 中间,以此来提升性能。
|
||||
|
||||
![Intel][1]
|
||||
|
||||
英特尔在 2019 年 4 月的[大规模数据中心活动][2]中正式推出 Optane 持久内存产品线。它已经问世了一段时间,但是目前的 Xeon 服务器处理器还不能充分利用它。而新的 Xeon8200 和 9200 系列可以充分利用 Optane 持久内存的优势。
|
||||
|
||||
由于 Optane 是英特尔的产品(与美光合作开发),所以意味着 AMD 和 ARM 的服务器处理器不能够支持它。
|
||||
|
||||
正如[我之前所说的][3],OptaneDC 持久内存采用与美光合作研发的 3D Xpoint 内存技术。3D Xpoint 是一种比 SSD 更快的非易失性内存,速度几乎与 DRAM 相近,而且它具有 NAND 闪存的持久性。
|
||||
|
||||
第一个 3D Xpoint 产品是被称为英特尔“尺子”的 SSD,因为它们被设计成细长的样子,很像尺子的形状。它们被设计这样是为了适合 1u 的服务器机架。在发布的公告中,英特尔推出了新的利用四芯或者 QLC 3D NAND 内存的英特尔 SSD D5-P4325 [尺子][7] SSD,可以在 1U 的服务器机架上放 1PB 的存储。
|
||||
|
||||
OptaneDC 持久内存的可用容量最初可以通过使用 128GB 的 DIMM 达到 512GB。英特尔数据中心集团执行副总裁及总经理 Navin Shenoy 说:“OptaneDC 持久内存可达到的容量是 DRAM 的 2 到 4 倍。”
|
||||
|
||||
他说:“我们希望服务器系统的容量可以扩展到每个插槽 4.5TB 或者 8 个插槽 36TB,这是我们第一代 Xeon 可扩展芯片的 3 倍。”
|
||||
|
||||
### 英特尔Optane内存的使用和速度
|
||||
|
||||
Optane 有两种不同的运行模式:内存模式和应用直连模式。内存模式是将 DRAM 放在 Optane 内存之上,将 DRAM 作为 Optane 内存的缓存。应用直连模式是将 DRAM 和 OptaneDC 持久内存一起作为内存来最大化总容量。并不是每个工作负载都适合这种配置,所以应该在对延迟不敏感的应用程序中使用。正如英特尔推广的那样,Optane 的主要使用情景是内存模式。
|
||||
|
||||
几年前,当 3D Xpoint 最初发布时,英特尔宣称 Optane 的速度是 NAND 的 1000 倍,耐用是 NAND 的 1000 倍,密度潜力是 DRAM 的 10 倍。这虽然有点夸张,但这些因素确实很令人着迷。
|
||||
|
||||
在 256B 的连续 4 个缓存行中使用 Optane 内存可以达到 8.3GB/秒的读速度和 3.0GB/秒的写速度。与 SATA SSD 的 500MB/秒左右的读/写速度相比,可以看到性能有很大提升。请记住,Optane 充当内存,所以它会缓存被频繁访问的 SSD 中的内容。
|
||||
|
||||
这是了解 OptaneDC 的关键。它能将非常大的数据集存储在离内存非常近的位置,因此具有很低延迟的 CPU 可以最小化访问较慢的存储子系统的访问延迟,无论存储是 SSD 还是 HDD。现在,它提供了一种可能性,即把多个 TB 的数据放在非常接近 CPU 的地方,以实现更快的访问。
|
||||
|
||||
### Optane 内存的一个挑战
|
||||
|
||||
唯一真正的挑战是 Optane 插进内存所在的 DIMM 插槽。现在有些主板的每个 CPU 有多达 16 个 DIMM 插槽,但是这仍然是客户和设备制造商之间需要平衡的电路板空间:Optane 还是内存。有一些 Optane 驱动采用了 PCIe 接口进行连接,可以减轻主板上内存的拥挤。
|
||||
|
||||
3D Xpoint 由于它写数据的方式,提供了比传统的 NAND 闪存更高的耐用性。英特尔承诺 Optane 提供 5 年保修期,而很多 SSD 只提供 3 年保修期。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3387117/intel-formally-launches-optane-for-data-center-memory-caching.html#tk.rss_all
|
||||
|
||||
作者:[Andy Patrizio][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[RiaXu](https://github.com/ShuyRoy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Andy-Patrizio/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://images.idgesg.net/images/article/2018/06/intel-optane-persistent-memory-100760427-large.jpg
|
||||
[2]: https://www.networkworld.com/article/3386142/intel-unveils-an-epic-response-to-amds-server-push.html
|
||||
[3]: https://www.networkworld.com/article/3279271/intel-launches-optane-the-go-between-for-memory-and-storage.html
|
||||
[4]: https://www.networkworld.com/article/3290421/why-nvme-users-weigh-benefits-of-nvme-accelerated-flash-storage.html
|
||||
[5]: https://www.networkworld.com/article/3242807/data-center/top-10-data-center-predictions-idc.html#nww-fsb
|
||||
[6]: https://www.networkworld.com/newsletters/signup.html#nww-fsb
|
||||
[7]: https://www.theregister.co.uk/2018/02/02/ruler_and_miniruler_ssd_formats_look_to_banish_diskstyle_drives/
|
||||
[8]: https://pluralsight.pxf.io/c/321564/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fpaths%2Fapple-certified-technical-trainer-10-11
|
||||
[9]: https://www.facebook.com/NetworkWorld/
|
||||
[10]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,305 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (chensanle)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13107-1.html)
|
||||
[#]: subject: (Tmux Command Examples To Manage Multiple Terminal Sessions)
|
||||
[#]: via: (https://www.ostechnix.com/tmux-command-examples-to-manage-multiple-terminal-sessions/)
|
||||
[#]: author: (sk https://www.ostechnix.com/author/sk/)
|
||||
|
||||
基于 Tmux 的多会话终端管理示例
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/11/101058ffso6wzzw94wm2ng.jpg)
|
||||
|
||||
我们已经了解到如何通过 [GNU Screen][2] 进行多会话管理。今天,我们将要领略另一个著名的管理会话的命令行实用工具 **Tmux**。类似 GNU Screen,Tmux 是一个帮助我们在单一终端窗口中创建多个会话,同一时间内同时运行多个应用程序或进程的终端复用工具。Tmux 自由、开源并且跨平台,支持 Linux、OpenBSD、FreeBSD、NetBSD 以及 Mac OS X。本文将讨论 Tmux 在 Linux 系统下的高频用法。
|
||||
|
||||
### Linux 下安装 Tmux
|
||||
|
||||
Tmux 可以在绝大多数的 Linux 官方仓库下获取。
|
||||
|
||||
在 Arch Linux 或它的变种系统下,执行下列命令来安装:
|
||||
|
||||
```
|
||||
$ sudo pacman -S tmux
|
||||
```
|
||||
|
||||
Debian、Ubuntu 或 Linux Mint:
|
||||
|
||||
```
|
||||
$ sudo apt-get install tmux
|
||||
```
|
||||
|
||||
Fedora:
|
||||
```
|
||||
$ sudo dnf install tmux
|
||||
```
|
||||
|
||||
RHEL 和 CentOS:
|
||||
|
||||
```
|
||||
$ sudo yum install tmux
|
||||
```
|
||||
|
||||
SUSE/openSUSE:
|
||||
|
||||
```
|
||||
$ sudo zypper install tmux
|
||||
```
|
||||
|
||||
以上,我们已经完成 Tmux 的安装。之后我们继续看看一些 Tmux 示例。
|
||||
|
||||
### Tmux 命令示例: 多会话管理
|
||||
|
||||
Tmux 默认所有命令的前置命令都是 `Ctrl+b`,使用前牢记这个快捷键即可。
|
||||
|
||||
> **注意**:**Screen** 的前置命令都是 `Ctrl+a`.
|
||||
|
||||
#### 创建 Tmux 会话
|
||||
|
||||
在终端中运行如下命令创建 Tmux 会话并附着进入:
|
||||
|
||||
```
|
||||
tmux
|
||||
```
|
||||
|
||||
抑或,
|
||||
|
||||
```
|
||||
tmux new
|
||||
```
|
||||
|
||||
一旦进入 Tmux 会话,你将看到一个 **沉在底部的绿色的边栏**,如下图所示。
|
||||
|
||||
![][3]
|
||||
|
||||
*创建 Tmux 会话*
|
||||
|
||||
这个绿色的边栏能很容易提示你当前是否身处 Tmux 会话当中。
|
||||
|
||||
#### 退出 Tmux 会话
|
||||
|
||||
退出当前 Tmux 会话仅需要使用 `Ctrl+b` 和 `d`。无需同时触发这两个快捷键,依次按下 `Ctrl+b` 和 `d` 即可。
|
||||
|
||||
退出当前会话后,你将能看到如下输出:
|
||||
|
||||
```
|
||||
[detached (from session 0)]
|
||||
```
|
||||
|
||||
#### 创建有名会话
|
||||
|
||||
如果使用多个会话,你很可能会混淆运行在多个会话中的应用程序。这种情况下,我们需要会话并赋予名称。譬如需要 web 相关服务的会话,就创建一个名称为 “webserver”(或任意一个其他名称) 的 Tmux 会话。
|
||||
|
||||
```
|
||||
tmux new -s webserver
|
||||
```
|
||||
|
||||
这里是新的 Tmux 有名会话:
|
||||
|
||||
![][4]
|
||||
|
||||
*拥有自定义名称的 Tmux 会话*
|
||||
|
||||
如你所见上述截图,这个 Tmux 会话的名称已经被标注为 “webserver”。如此,你可以在多个会话中,轻易的区分应用程序的所在。
|
||||
|
||||
退出会话,轻按 `Ctrl+b` 和 `d`。
|
||||
|
||||
#### 查看 Tmux 会话清单
|
||||
|
||||
查看 Tmux 会话清单,执行:
|
||||
|
||||
```
|
||||
tmux ls
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
![][5]
|
||||
|
||||
*列出 Tmux 会话*
|
||||
|
||||
如你所见,我们开启了两个 Tmux 会话。
|
||||
|
||||
#### 创建非附着会话
|
||||
|
||||
有时候,你可能想要简单创建会话,但是并不想自动切入该会话。
|
||||
|
||||
创建一个非附着会话,并赋予名称 “ostechnix”,运行:
|
||||
|
||||
```
|
||||
tmux new -s ostechnix -d
|
||||
```
|
||||
|
||||
上述命令将会创建一个名为 “ostechnix” 的会话,但是并不会附着进入。
|
||||
|
||||
你可以通过使用 `tmux ls` 命令验证:
|
||||
|
||||
![][6]
|
||||
|
||||
*创建非附着会话*
|
||||
|
||||
#### 附着进入 Tmux 会话
|
||||
|
||||
通过如下命令,你可以附着进入最后一个被创建的会话:
|
||||
|
||||
```
|
||||
tmux attach
|
||||
```
|
||||
|
||||
抑或,
|
||||
|
||||
```
|
||||
tmux a
|
||||
```
|
||||
|
||||
如果你想附着进入任意一个指定的有名会话,譬如 “ostechnix”,运行:
|
||||
|
||||
```
|
||||
tmux attach -t ostechnix
|
||||
```
|
||||
|
||||
或者,简写为:
|
||||
|
||||
```
|
||||
tmux a -t ostechnix
|
||||
```
|
||||
|
||||
#### 关闭 Tmux 会话
|
||||
|
||||
当你完成或者不再需要 Tmux 会话,你可以通过如下命令关闭:
|
||||
|
||||
```
|
||||
tmux kill-session -t ostechnix
|
||||
```
|
||||
|
||||
当身处该会话时,使用 `Ctrl+b` 以及 `x`。点击 `y` 来关闭会话。
|
||||
|
||||
可以通过 `tmux ls` 命令验证。
|
||||
|
||||
关闭所有 Tmux 服务下的所有会话,运行:
|
||||
|
||||
```
|
||||
tmux kill-server
|
||||
```
|
||||
|
||||
谨慎!这将终止所有 Tmux 会话,并不会产生任何警告,即便会话存在运行中的任务。
|
||||
|
||||
如果不存在活跃的 Tmux 会话,将看到如下输出:
|
||||
|
||||
```
|
||||
$ tmux ls
|
||||
no server running on /tmp/tmux-1000/default
|
||||
```
|
||||
|
||||
#### 切割 Tmux 窗口
|
||||
|
||||
切割窗口成多个小窗口,在 Tmux 中,这个叫做 “Tmux 窗格”。每个窗格中可以同时运行不同的程序,并同时与所有的窗格进行交互。每个窗格可以在不影响其他窗格的前提下可以调整大小、移动位置和控制关闭。我们可以以水平、垂直或者二者混合的方式切割屏幕。
|
||||
|
||||
##### 水平切割窗格
|
||||
|
||||
欲水平切割窗格,使用 `Ctrl+b` 和 `"`(半个双引号)。
|
||||
|
||||
![][7]
|
||||
|
||||
*水平切割 Tmux 窗格*
|
||||
|
||||
可以使用组合键进一步切割面板。
|
||||
|
||||
##### 垂直切割窗格
|
||||
|
||||
垂直切割面板,使用 `Ctrl+b` 和 `%`。
|
||||
|
||||
![][8]
|
||||
|
||||
*垂直切割 Tmux 窗格*
|
||||
|
||||
##### 水平、垂直混合切割窗格
|
||||
|
||||
我们也可以同时采用水平和垂直的方案切割窗格。看看如下截图:
|
||||
|
||||
![][9]
|
||||
|
||||
*切割 Tmux 窗格*
|
||||
|
||||
首先,我通过 `Ctrl+b` `"` 水平切割,之后通过 `Ctrl+b` `%` 垂直切割下方的窗格。
|
||||
|
||||
如你所见,每个窗格下我运行了不同的程序。
|
||||
|
||||
##### 切换窗格
|
||||
|
||||
通过 `Ctrl+b` 和方向键(上下左右)切换窗格。
|
||||
|
||||
##### 发送命令给所有窗格
|
||||
|
||||
之前的案例中,我们在每个窗格中运行了三个不同命令。其实,也可以发送相同的命令给所有窗格。
|
||||
|
||||
为此,使用 `Ctrl+b` 然后键入如下命令,之后按下回车:
|
||||
|
||||
```
|
||||
:setw synchronize-panes
|
||||
```
|
||||
|
||||
现在在任意窗格中键入任何命令。你将看到相同命令影响了所有窗格。
|
||||
|
||||
##### 交换窗格
|
||||
|
||||
使用 `Ctrl+b` 和 `o` 交换窗格。
|
||||
|
||||
##### 展示窗格号
|
||||
|
||||
使用 `Ctrl+b` 和 `q` 展示窗格号。
|
||||
|
||||
##### 终止窗格
|
||||
|
||||
要关闭窗格,直接键入 `exit` 并且按下回车键。或者,按下 `Ctrl+b` 和 `x`。你会看到确认信息。按下 `y` 关闭窗格。
|
||||
|
||||
![][10]
|
||||
|
||||
*关闭窗格*
|
||||
|
||||
##### 放大和缩小 Tmux 窗格
|
||||
|
||||
我们可以将 Tmux 窗格放大到当前终端窗口的全尺寸,以获得更好的文本可视性,并查看更多的内容。当你需要更多的空间或专注于某个特定的任务时,这很有用。在完成该任务后,你可以将 Tmux 窗格缩小(取消放大)到其正常位置。更多详情请看以下链接。
|
||||
|
||||
- [如何缩放 Tmux 窗格以提高文本可见度?](https://ostechnix.com/how-to-zoom-tmux-panes-for-better-text-visibility/)
|
||||
|
||||
#### 自动启动 Tmux 会话
|
||||
|
||||
当通过 SSH 与远程系统工作时,在 Tmux 会话中运行一个长期运行的进程总是一个好的做法。因为,它可以防止你在网络连接突然中断时失去对运行进程的控制。避免这个问题的一个方法是自动启动 Tmux 会话。更多详情,请参考以下链接。
|
||||
|
||||
- [通过 SSH 登录远程系统时自动启动 Tmux 会话](https://ostechnix.com/autostart-tmux-session-on-remote-system-when-logging-in-via-ssh/)
|
||||
|
||||
### 总结
|
||||
|
||||
这个阶段下,你已经获得了基本的 Tmux 技能来进行多会话管理,更多细节,参阅 man 页面。
|
||||
|
||||
```
|
||||
$ man tmux
|
||||
```
|
||||
|
||||
GNU Screen 和 Tmux 工具都能透过 SSH 很好的管理远程服务器。学习 Screen 和 Tmux 命令,像个行家一样,彻底通过这些工具管理远程服务器。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/tmux-command-examples-to-manage-multiple-terminal-sessions/
|
||||
|
||||
作者:[sk][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[chensanle](https://github.com/chensanle)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.ostechnix.com/wp-content/uploads/2019/06/Tmux-720x340.png
|
||||
[2]: https://www.ostechnix.com/screen-command-examples-to-manage-multiple-terminal-sessions/
|
||||
[3]: https://www.ostechnix.com/wp-content/uploads/2019/06/Tmux-session.png
|
||||
[4]: https://www.ostechnix.com/wp-content/uploads/2019/06/Named-Tmux-session.png
|
||||
[5]: https://www.ostechnix.com/wp-content/uploads/2019/06/List-Tmux-sessions.png
|
||||
[6]: https://www.ostechnix.com/wp-content/uploads/2019/06/Create-detached-sessions.png
|
||||
[7]: https://www.ostechnix.com/wp-content/uploads/2019/06/Horizontal-split.png
|
||||
[8]: https://www.ostechnix.com/wp-content/uploads/2019/06/Vertical-split.png
|
||||
[9]: https://www.ostechnix.com/wp-content/uploads/2019/06/Split-Panes.png
|
||||
[10]: https://www.ostechnix.com/wp-content/uploads/2019/06/Kill-panes.png
|
@ -0,0 +1,72 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (scvoet)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13115-1.html)
|
||||
[#]: subject: (Where are all the IoT experts going to come from?)
|
||||
[#]: via: (https://www.networkworld.com/article/3404489/where-are-all-the-iot-experts-going-to-come-from.html)
|
||||
[#]: author: (Fredric Paul https://www.networkworld.com/author/Fredric-Paul/)
|
||||
|
||||
物联网专家都从何而来?
|
||||
======
|
||||
|
||||
> 物联网(IoT)的快速发展催生了对跨职能专家进行培养的需求,这些专家可以将传统的网络和基础设施专业知识与数据库和报告技能相结合。
|
||||
|
||||
![Kevin \(CC0\)][1]
|
||||
|
||||
如果物联网(IoT)要实现其宏伟的诺言,它将需要大量聪明、熟练、**训练有素**的工人军团来实现这一切。而现在,这些人将从何而来尚不清楚。
|
||||
|
||||
这就是我为什么有兴趣同资产优化软件公司 [AspenTech][2] 的产品管理、研发高级总监 Keith Flynn 通邮件的原因,他说,当处理大量属于物联网范畴的新技术时,你需要能够理解如何配置技术和解释数据的人。Flynn 认为,现有的教育机构对物联网特定课程的需求越来越大,这同时也给了以物联网为重点,提供了完善课程的新私立学院机会。
|
||||
|
||||
Flynn 跟我说,“在未来,物联网项目将与如今普遍的数据管理和自动化项目有着巨大的不同……未来需要更全面的技能和交叉交易能力,这样我们才会说同一种语言。”
|
||||
|
||||
Flynn 补充说,随着物联网每年增长 30%,将不再依赖于几个特定的技能,“从传统的部署技能(如网络和基础设施)到数据库和报告技能,坦白说,甚至是基础数据科学,都将需要一起理解和使用。”
|
||||
|
||||
### 召集所有物联网顾问
|
||||
|
||||
Flynn 预测,“受过物联网教育的人的第一个大机会将会是在咨询领域,随着咨询公司对行业趋势的适应或淘汰……有受过物联网培训的员工将有助于他们在物联网项目中的定位,并在新的业务线中提出要求——物联网咨询。”
|
||||
|
||||
对初创企业和小型公司而言,这个问题尤为严重。“组织越大,他们越有可能雇佣到不同技术类别的人”Flynn 这样说到,“但对于较小的组织和较小的物联网项目来说,你则需要一个能同时兼顾的人。”
|
||||
|
||||
两者兼而有之?还是**一应俱全?**物联网“需要将所有知识和技能组合在一起”,Flynn 说到,“并不是所有技能都是全新的,只是在此之前从来没有被归纳在一起或放在一起教授过。”
|
||||
|
||||
### 未来的物联网专家
|
||||
|
||||
Flynn 表示,真正的物联网专业技术是从基础的仪器仪表和电气技能开始的,这能帮助工人发明新的无线发射器或提升技术,以提高电池寿命和功耗。
|
||||
|
||||
“IT 技能,如网络、IP 寻址、子网掩码、蜂窝和卫星也是物联网的关键需求”,Flynn 说。他还认为物联网需要数据库管理技能和云管理和安全专业知识,“特别是当高级过程控制(APC)将传感器数据直接发送到数据库和数据湖等事情成为常态时。”
|
||||
|
||||
### 物联网专家又从何而来?
|
||||
|
||||
Flynn 说,标准化的正规教育课程将是确保毕业生或证书持有者掌握一套正确技能的最佳途径。他甚至还列出了一个样本课程。“按时间顺序开始,从基础知识开始,比如 [电气仪表] 和测量。然后讲授网络知识,数据库管理和云计算课程都应在此之后开展。这个学位甚至可以循序渐进至现有的工程课程中,这可能需要两年时间……来完成物联网部分的学业。”
|
||||
|
||||
虽然企业培训也能发挥作用,但实际上却是“说起来容易做起来难”,Flynn 这样警告,“这些培训需要针对组织的具体努力而推动。”
|
||||
|
||||
当然,现在市面上已经有了 [大量的在线物联网培训课程和证书课程][5]。但追根到底,这一工作全都依赖于工人自身的推断。
|
||||
|
||||
“在这个世界上,随着科技不断改变行业,提升技能是非常重要的”,Flynn 说,“如果这种提升技能的推动力并不是来源于你的雇主,那么在线课程和认证将会是提升你自己很好的一个方式。我们只需要创建这些课程……我甚至可以预见组织将与提供这些课程的高等教育机构合作,让他们的员工更好地开始。当然,物联网课程的挑战在于它需要不断发展以跟上科技的发展。”
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3404489/where-are-all-the-iot-experts-going-to-come-from.html
|
||||
|
||||
作者:[Fredric Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Percy (@scvoet)](https://github.com/scvoet)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Fredric-Paul/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://images.idgesg.net/images/article/2018/07/programmer_certification-skills_code_devops_glasses_student_by-kevin-unsplash-100764315-large.jpg
|
||||
[2]: https://www.aspentech.com/
|
||||
[3]: https://www.networkworld.com/article/3276025/careers/20-hot-jobs-ambitious-it-pros-should-shoot-for.html
|
||||
[4]: https://pluralsight.pxf.io/c/321564/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fpaths%2Fupgrading-your-technology-career
|
||||
[5]: https://www.google.com/search?client=firefox-b-1-d&q=iot+training
|
||||
[6]: https://www.networkworld.com/article/3254185/internet-of-things/tips-for-securing-iot-on-your-network.html#nww-fsb
|
||||
[7]: https://www.networkworld.com/article/2287045/internet-of-things/wireless-153629-10-most-powerful-internet-of-things-companies.html#nww-fsb
|
||||
[8]: https://www.networkworld.com/article/3243928/internet-of-things/what-is-the-industrial-iot-and-why-the-stakes-are-so-high.html#nww-fsb
|
||||
[9]: https://www.networkworld.com/newsletters/signup.html#nww-fsb
|
||||
[10]: https://www.facebook.com/NetworkWorld/
|
||||
[11]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,98 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13096-1.html)
|
||||
[#]: subject: (EndeavourOS Aims to Fill the Void Left by Antergos in Arch Linux World)
|
||||
[#]: via: (https://itsfoss.com/endeavouros/)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
EndeavourOS:填补 Antergos 在 ArchLinux 世界留下的空白
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/07/225558rdb85bmm6uumro71.jpg)
|
||||
|
||||
我相信我们的大多数读者都知道 [Antergos 项目的终结][2]。在这一消息宣布之后,Antergos 社区的成员创建了几个发行版来继承 Antergos。今天,我们将着眼于 Antergos 的“精神继承人”之一:[EndeavourOS][3]。
|
||||
|
||||
### EndeavourOS 不是 Antergos 的分支
|
||||
|
||||
在我们开始之前,我想非常明确地指出,EndeavourOS 并不是一个 Antergos 的复刻版本。开发者们以 Antergos 为灵感,创建了一个基于 Arch 的轻量级发行版。
|
||||
|
||||
![Endeavouros First Boot][4]
|
||||
|
||||
根据 [这个项目网站][5] 的说法,EndeavourOS 的诞生是因为 Antergos 社区的人们想要保持 Antergos 的精神。他们的目标很简单:“让 Arch 拥有一个易于使用的安装程序和一个友好、有帮助的社区,在掌握系统的过程中能够有一个社区可以依靠。”
|
||||
|
||||
与许多基于 Arch 的发行版不同,EndeavourOS 打算像 [原生 Arch][5] 那样使用,“所以没有一键式安装你喜欢的应用程序的解决方案,也没有一堆你最终不需要的预装应用程序。”对于大多数人来说,尤其是那些刚接触 Linux 和 Arch 的人,会有一个学习曲线,但 EndeavourOS 的目标是建立一个大型友好的社区,鼓励人们提出问题并了解他们的系统。
|
||||
|
||||
![Endeavouros Installing][6]
|
||||
|
||||
### 正在进行的工作
|
||||
|
||||
EndeavourOS 在 [2019 年 5 月 23 日首次宣布成立][8] 随后 [在 7 月 15 日发布第一个版本][7]。不幸的是,这意味着开发人员无法将他们计划的所有功能全部整合进来。(LCTT 译注:本文原文发表于 2019 年,而现在,EndeavourOS 还在持续活跃着。)
|
||||
|
||||
例如,他们想要一个类似于 Antergos 的在线安装,但却遇到了[当前选项的问题][9]。“Cnchi 运行在 Antergos 生态系统之外会造成严重的问题,需要彻底重写才能发挥作用。RebornOS 的 Fenix 安装程序还没有完全成型,需要更多时间才能正常运行。”于是现在,EndeavourOS 将会和 [Calamares 安装程序 ][10] 一起发布。
|
||||
|
||||
EndeavourOS 会提供 [比 Antergos 少的东西][9]:它的存储库比 Antergos 小,尽管他们会附带一些 AUR 包。他们的目标是提供一个接近 Arch 却不是原生 Arch 的系统。
|
||||
|
||||
![Endeavouros Updating With Kalu][12]
|
||||
|
||||
开发者[进一步声明 ][13]:
|
||||
|
||||
> “Linux,特别是 Arch,核心精神是自由选择,我们提供了一个基本的安装,让你在一个精细的层面上方便地探索各项选择。我们永远不会强行为你作决定,比如为你安装 GUI 应用程序,如 Pamac,甚至采用沙盒解决方案,如 Flatpak 或 Snaps。想安装成什么样子完全取决于你,这是我们与 Antergos 或 Manjaro 的主要区别,但与 Antergos 一样,如果你安装的软件包遇到问题,我们会尽力帮助你。”
|
||||
|
||||
### 体验 EndeavourOS
|
||||
|
||||
我在 [VirtualBox][14] 中安装了 EndeavourOS,并且研究了一番。当我第一次启动时,我看到一个窗口,里面有关于安装的 EndeavourOS 网站的链接。它还有一个安装按钮和一个手动分区工具。Calamares 安装程序的安装过程非常顺利。
|
||||
|
||||
在我重新启动到新安装的 EndeavourOS 之后,迎接我的是一个彩色主题的 XFCE 桌面。我还收到了一堆通知消息。我使用过的大多数基于 Arch 的发行版都带有一个 GUI 包管理器,比如 [pamac][15] 或 [octopi][16],以进行系统更新。EndeavourOS 配有 [kalu][17](kalu 是 “Keeping Arch Linux Up-to-date” 的缩写)。它可以更新软件包、可以看 Archlinux 新闻、可以更新 AUR 包等等。一旦它检查到有更新,它就会显示通知消息。
|
||||
|
||||
我浏览了一下菜单,看看默认安装了什么。默认的安装并不多,连办公套件都没有。他们想让 EndeavourOS 成为一块空白画布,让任何人都可以创建他们想要的系统。他们正朝着正确的方向前进。
|
||||
|
||||
![Endeavouros Desktop][18]
|
||||
|
||||
### 总结思考
|
||||
|
||||
EndeavourOS 还很年轻。第一个稳定版本都没有发布多久。它缺少一些东西,最重要的是一个在线安装程序。这就是说,我们无法估计他能够走到哪一步。(LCTT 译注:本文发表于 2019 年)
|
||||
|
||||
虽然它不是 Antergos 的精确复刻,但 EndeavourOS 希望复制 Antergos 最重要的部分——热情友好的社区。很多时候,Linux 社区对初学者似乎是不受欢迎甚至是完全敌对的。我看到越来越多的人试图与这种消极情绪作斗争,并将更多的人引入 Linux。随着 EndeavourOS 团队把焦点放在社区建设上,我相信一个伟大的发行版将会诞生。
|
||||
|
||||
如果你当前正在使用 Antergos,有一种方法可以让你[不用重装系统就切换到 EndeavourOS][20]
|
||||
|
||||
如果你想要一个 Antergos 的精确复刻,我建议你去看看 [RebornOS][21]。他们目前正在开发一个名为 Fenix 的 Cnchi 安装程序的替代品。
|
||||
|
||||
你试过 EndeavourOS 了吗?你的感受如何?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/endeavouros/
|
||||
|
||||
作者:[John Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/john/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/endeavouros-logo.png?ssl=1
|
||||
[2]: https://itsfoss.com/antergos-linux-discontinued/
|
||||
[3]: https://endeavouros.com/
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/endeavouros-first-boot.png?resize=800%2C600&ssl=1
|
||||
[5]: https://endeavouros.com/info-2/
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/endeavouros-installing.png?resize=800%2C600&ssl=1
|
||||
[7]: https://endeavouros.com/endeavouros-first-stable-release-has-arrived/
|
||||
[8]: https://forum.antergos.com/topic/11780/endeavour-antergos-community-s-next-stage
|
||||
[9]: https://endeavouros.com/what-to-expect-on-the-first-release/
|
||||
[10]: https://calamares.io/
|
||||
[11]: https://itsfoss.com/veltos-linux/
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/endeavouros-updating-with-kalu.png?resize=800%2C600&ssl=1
|
||||
[13]: https://endeavouros.com/second-week-after-the-stable-release/
|
||||
[14]: https://itsfoss.com/install-virtualbox-ubuntu/
|
||||
[15]: https://aur.archlinux.org/packages/pamac-aur/
|
||||
[16]: https://octopiproject.wordpress.com/
|
||||
[17]: https://github.com/jjk-jacky/kalu
|
||||
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/endeavouros-desktop.png?resize=800%2C600&ssl=1
|
||||
[19]: https://itsfoss.com/clear-linux/
|
||||
[20]: https://forum.endeavouros.com/t/how-to-switch-from-antergos-to-endevouros/105/2
|
||||
[21]: https://rebornos.org/
|
@ -0,0 +1,72 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (stevenzdg988)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13082-1.html)
|
||||
[#]: subject: (The importance of consistency in your Python code)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-consistency)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
Python 代码一致性的重要性
|
||||
======
|
||||
|
||||
> 本文是 Python 之禅特殊系列的一部分,重点是第十二、十三和十四原则:模糊性和明确性的作用。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/03/231758po1lcicxmxyjxlba.jpg)
|
||||
|
||||
最小惊喜原则是设计用户界面时的一个 [准则][2]。它是说,当用户执行某项操作时,程序执行的事情应该使用户尽量少地感到意外。这和孩子们喜欢一遍又一遍地读同一本书的原因是一样的:没有什么比能够预测并让预测成真更让人欣慰的了。
|
||||
|
||||
在开发 [ABC 语言][3](Python 的灵感来源)的过程中,一个重要的见解是,编程设计是用户界面,需要使用与 UI 设计者相同的工具来设计。值得庆幸的是,从那以后,越来越多的语言采用了 UI 设计中的<ruby>可承受性<rt>affordance</rt></ruby>和<ruby>人体工程学<rt>ergonomics</rt></ruby>的概念,即使它们的应用并不严格。
|
||||
|
||||
这就引出了 [Python 之禅][4] 中的三个原则。
|
||||
|
||||
### <ruby>面对歧义,要拒绝猜测的诱惑<rt>In the face of ambiguity, refuse the temptation to guess</rt></ruby>
|
||||
|
||||
`1 + "1"` 的结果应该是什么? `"11"` 和 `2` 都是猜测。这种表达方式是*歧义的*:无论如何做都会让一些人感到惊讶。
|
||||
|
||||
一些语言选择猜测。在 JavaScript 中,结果为 `"11"`。在 Perl 中,结果为 `2`。在 C 语言中,结果自然是空字符串。面对歧义,JavaScript、Perl 和 C 都在猜测。
|
||||
|
||||
在 Python 中,这会引发 `TypeError`:这不是能忽略的错误。捕获 `TypeError` 是非典型的:它通常将终止程序或至少终止当前任务(例如,在大多数 Web 框架中,它将终止对当前请求的处理)。
|
||||
|
||||
Python 拒绝猜测 `1 + "1"` 的含义。程序员必须以明确的意图编写代码:`1 + int("1")`,即 `2`;或者 `str(1) + "1"`,即 `"11"`;或 `"1"[1:]`,这将是一个空字符串。通过拒绝猜测,Python 使程序更具可预测性。
|
||||
|
||||
### <ruby>尽量找一种,最好是唯一一种明显的解决方案<rt>There should be one—and preferably only one—obvious way to do it</rt></ruby>
|
||||
|
||||
预测也会出现偏差。给定一个任务,你能预知要实现该任务的代码吗?当然,不可能完美地预测。毕竟,编程是一项具有创造性的任务。
|
||||
|
||||
但是,不必有意提供多种冗余方式来实现同一目标。从某种意义上说,某些解决方案或许 “更好” 或 “更 <ruby>Python 化<rt>Pythonic</rt></ruby>”。
|
||||
|
||||
对 Python 美学欣赏部分是因为,可以就哪种解决方案更好进行健康的辩论。甚至可以持不同观点而继续编程。甚至为使其达成一致,接受不同意的观点也是可以的。但在这一切之下,必须有一种这样的认识,即正确的解决方案终将会出现。我们必须希望,通过商定实现目标的最佳方法,而最终达成真正的一致。
|
||||
|
||||
### <ruby>虽然这种方式一开始可能并不明显(除非你是荷兰人)<rt>Although that way may not be obvious at first (unless you're Dutch)</rt></ruby>
|
||||
|
||||
这是一个重要的警告:首先,实现任务的最佳方法往往*不*明显。观念在不断发展。Python 也在进化。逐块读取文件的最好方法,可能要等到 Python 3.8 时使用 [walrus 运算符][5](`:=`)。
|
||||
|
||||
逐块读取文件这样常见的任务,在 Python 存在近 *30年* 的历史中并没有 “唯一的最佳方法”。
|
||||
|
||||
当我在 1998 年从 Python 1.5.2 开始使用 Python 时,没有一种逐行读取文件的最佳方法。多年来,知道字典中是否有某个键的最佳方法是使用关键字 `.haskey`,直到 `in` 操作符出现才发生改变。
|
||||
|
||||
只是要意识到找到实现目标的一种(也是唯一一种)方法可能需要 30 年的时间来尝试其它方法,Python 才可以不断寻找这些方法。这种历史观认为,为了做一件事用上 30 年是可以接受的,但对于美国这个存在仅 200 多年的国家来说,人们常常会感到不习惯。
|
||||
|
||||
从 Python 之禅的这一部分来看,荷兰人,无论是 Python 的创造者 [Guido van Rossum][6] 还是著名的计算机科学家 [Edsger W. Dijkstra][7],他们的世界观是不同的。要理解这一部分,某种程度的欧洲人对时间的感受是必不可少的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/zen-python-consistency
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[stevenzdg988](https://github.com/stevenzdg988)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_other11x_cc.png?itok=I_kCDYj0 (Two animated computers waving one missing an arm)
|
||||
[2]: https://www.uxpassion.com/blog/the-principle-of-least-surprise/
|
||||
[3]: https://en.wikipedia.org/wiki/ABC_(programming_language)
|
||||
[4]: https://www.python.org/dev/peps/pep-0020/
|
||||
[5]: https://www.python.org/dev/peps/pep-0572/#abstract
|
||||
[6]: https://en.wikipedia.org/wiki/Guido_van_Rossum
|
||||
[7]: http://en.wikipedia.org/wiki/Edsger_W._Dijkstra
|
@ -0,0 +1,45 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13103-1.html)
|
||||
[#]: subject: (The Zen of Python: Why timing is everything)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-timeliness)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
Python 之禅:时机最重要
|
||||
======
|
||||
|
||||
> 这是 Python 之禅特别系列的一部分,重点是第十五和第十六条原则:现在与将来。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/09/231557dkuzz22ame4ja2jj.jpg)
|
||||
|
||||
Python 一直在不断发展。Python 社区对特性请求的渴求是无止境的,对现状也总是不满意的。随着 Python 越来越流行,这门语言的变化会影响到更多的人。
|
||||
|
||||
确定什么时候该进行变化往往很难,但 [Python 之禅][2] 给你提供了指导。
|
||||
|
||||
### <ruby>现在有总比永远没有好<rt>Now is better than never</rt></ruby>
|
||||
|
||||
总有一种诱惑,就是要等到事情完美才去做,虽然,它们永远没有完美的一天。当它们看起来已经“准备”得足够好了,那就大胆采取行动吧,去做出改变吧。无论如何,变化总是发生在*某个*现在:拖延的唯一作用就是把它移到未来的“现在”。
|
||||
|
||||
### <ruby>虽然将来总比现在好<rt>Although never is often better than right now</rt></ruby>
|
||||
|
||||
然而,这并不意味着应该急于求成。从测试、文档、用户反馈等方面决定发布的标准。在变化就绪之前的“现在”,并不是一个好时机。
|
||||
|
||||
这不仅对 Python 这样的流行语言是个很好的经验,对你个人的小开源项目也是如此。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/zen-python-timeliness
|
||||
|
||||
作者:[Moshe Zadka][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/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/desk_clock_job_work.jpg?itok=Nj4fuhl6 (Clock, pen, and notepad on a desk)
|
||||
[2]: https://www.python.org/dev/peps/pep-0020/
|
@ -0,0 +1,47 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13116-1.html)
|
||||
[#]: subject: (How to tell if implementing your Python code is a good idea)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-implementation)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
如何判断你的 Python 代码实现是否合适?
|
||||
======
|
||||
|
||||
> 这是 Python 之禅特别系列的一部分,重点介绍第十七和十八条原则:困难和容易。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/14/120518rjkwvjs76p9d1911.jpg)
|
||||
|
||||
一门语言并不是抽象存在的。每一个语言功能都必须用代码来实现。承诺一些功能是很容易的,但实现起来就会很麻烦。复杂的实现意味着更多潜在的 bug,甚至更糟糕的是,会带来日复一日的维护负担。
|
||||
|
||||
对于这个难题,[Python 之禅][2] 中有答案。
|
||||
|
||||
### <ruby>如果一个实现难以解释,那就是个坏思路<rt>If the implementation is hard to explain, it's a bad idea</rt></ruby>
|
||||
|
||||
编程语言最重要的是可预测性。有时我们用抽象的编程模型来解释某个结构的语义,而这些模型与实现并不完全对应。然而,最好的释义就是*解释该实现*。
|
||||
|
||||
如果该实现很难解释,那就意味着这条路行不通。
|
||||
|
||||
### <ruby>如果一个实现易于解释,那它可能是一个好思路<rt>If the implementation is easy to explain, it may be a good idea</rt></ruby>
|
||||
|
||||
仅仅因为某事容易,并不意味着它值得。然而,一旦解释清楚,判断它是否是一个好思路就容易得多。
|
||||
|
||||
这也是为什么这个原则的后半部分故意含糊其辞的原因:没有什么可以肯定一定是好的,但总是可以讨论一下。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/zen-python-implementation
|
||||
|
||||
作者:[Moshe Zadka][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/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/devops_confusion_wall_questions.png?itok=zLS7K2JG (Brick wall between two people, a developer and an operations manager)
|
||||
[2]: https://www.python.org/dev/peps/pep-0020/
|
@ -0,0 +1,58 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13123-1.html)
|
||||
[#]: subject: (Namespaces are the shamash candle of the Zen of Python)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-namespaces)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
命名空间是 Python 之禅的精髓
|
||||
======
|
||||
|
||||
> 这是 Python 之禅特别系列的一部分,重点是一个额外的原则:命名空间。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/16/105800d64ceaeertt4u4ee.jpg)
|
||||
|
||||
著名的<ruby>光明节<rt>Hanukkah</rt></ruby>有八个晚上的庆祝活动。然而,光明节的灯台有九根蜡烛:八根普通的蜡烛和总是偏移的第九根蜡烛。它被称为 “shamash” 或 “shamos”,大致可以翻译为“仆人”或“看门人”的意思。
|
||||
|
||||
shamos 是点燃所有其它蜡烛的蜡烛:它是唯一一支可以用火的蜡烛,而不仅仅是观看。当我们结束 Python 之禅系列时,我看到命名空间提供了类似的作用。
|
||||
|
||||
### Python 中的命名空间
|
||||
|
||||
Python 使用命名空间来处理一切。虽然简单,但它们是稀疏的数据结构 —— 这通常是实现目标的最佳方式。
|
||||
|
||||
> *命名空间* 是一个从名字到对象的映射。
|
||||
>
|
||||
> —— [Python.org][2]
|
||||
|
||||
模块是命名空间。这意味着正确地预测模块语义通常只需要熟悉 Python 命名空间的工作方式。类是命名空间,对象是命名空间。函数可以访问它们的本地命名空间、父命名空间和全局命名空间。
|
||||
|
||||
这个简单的模型,即用 `.` 操作符访问一个对象,而这个对象又通常(但并不总是)会进行某种字典查找,这使得 Python 很难优化,但很容易解释。
|
||||
|
||||
事实上,一些第三方模块也采取了这个准则,并以此来运行。例如,[variants][3] 包把函数变成了“相关功能”的命名空间。这是一个很好的例子,说明 [Python 之禅][4] 是如何激发新的抽象的。
|
||||
|
||||
### 结语
|
||||
|
||||
感谢你和我一起参加这次以光明节为灵感的 [我最喜欢的语言][5] 的探索。
|
||||
|
||||
静心参禅,直至悟道。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/zen-python-namespaces
|
||||
|
||||
作者:[Moshe Zadka][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/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_code_programming_laptop.jpg?itok=ormv35tV (Person programming on a laptop on a building)
|
||||
[2]: https://docs.python.org/3/tutorial/classes.html
|
||||
[3]: https://pypi.org/project/variants/
|
||||
[4]: https://www.python.org/dev/peps/pep-0020/
|
||||
[5]: https://opensource.com/article/19/10/why-love-python
|
@ -0,0 +1,244 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13099-1.html)
|
||||
[#]: subject: (Getting Started With Pacman Commands in Arch-based Linux Distributions)
|
||||
[#]: via: (https://itsfoss.com/pacman-command/)
|
||||
[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
|
||||
|
||||
Arch Linux 的 pacman 命令入门
|
||||
======
|
||||
|
||||
> 这本初学者指南向你展示了在 Linux 中可以使用 pacman 命令做什么,如何使用它们来查找新的软件包,安装和升级新的软件包,以及清理你的系统。
|
||||
|
||||
[pacman][1] 包管理器是 [Arch Linux][2] 和其他主要发行版如 Red Hat 和 Ubuntu/Debian 之间的主要区别之一。它结合了简单的二进制包格式和易于使用的 [构建系统][3]。`pacman` 的目标是方便地管理软件包,无论它是来自 [官方库][4] 还是用户自己构建的软件库。
|
||||
|
||||
如果你曾经使用过 Ubuntu 或基于 debian 的发行版,那么你可能使用过 `apt-get` 或 `apt` 命令。`pacman` 在 Arch Linux 中是同样的命令。如果你 [刚刚安装了 Arch Linux][5],在安装 Arch Linux 后,首先要做的 [几件事][6] 之一就是学习使用 `pacman` 命令。
|
||||
|
||||
在这个初学者指南中,我将解释一些基本的 `pacman` 命令的用法,你应该知道如何用这些命令来管理你的基于 Archlinux 的系统。
|
||||
|
||||
### Arch Linux 用户应该知道的几个重要的 pacman 命令
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/09/111411uqadijqdd8afgk56.jpg)
|
||||
|
||||
与其他包管理器一样,`pacman` 可以将包列表与软件库同步,它能够自动解决所有所需的依赖项,以使得用户可以通过一个简单的命令下载和安装软件。
|
||||
|
||||
#### 通过 pacman 安装软件
|
||||
|
||||
你可以用以下形式的代码来安装一个或者多个软件包:
|
||||
|
||||
```
|
||||
pacman -S 软件包名1 软件包名2 ...
|
||||
```
|
||||
|
||||
![安装一个包][8]
|
||||
|
||||
`-S` 选项的意思是<ruby>同步<rt>synchronization</rt></ruby>,它的意思是 `pacman` 在安装之前先与软件库进行同步。
|
||||
|
||||
`pacman` 数据库根据安装的原因将安装的包分为两组:
|
||||
|
||||
* **显式安装**:由 `pacman -S` 或 `-U` 命令直接安装的包
|
||||
* **依赖安装**:由于被其他显式安装的包所 [依赖][9],而被自动安装的包。
|
||||
|
||||
#### 卸载已安装的软件包
|
||||
|
||||
卸载一个包,并且删除它的所有依赖。
|
||||
|
||||
```
|
||||
pacman -R 软件包名
|
||||
```
|
||||
|
||||
![移除一个包][10]
|
||||
|
||||
删除一个包,以及其不被其他包所需要的依赖项:
|
||||
|
||||
```
|
||||
pacman -Rs 软件包名
|
||||
```
|
||||
|
||||
如果需要这个依赖的包已经被删除了,这条命令可以删除所有不再需要的依赖项:
|
||||
|
||||
```
|
||||
pacman -Qdtq | pacman -Rs -
|
||||
```
|
||||
|
||||
#### 升级软件包
|
||||
|
||||
`pacman` 提供了一个简单的办法来 [升级 Arch Linux][11]。你只需要一条命令就可以升级所有已安装的软件包。这可能需要一段时间,这取决于系统的新旧程度。
|
||||
|
||||
以下命令可以同步存储库数据库,*并且* 更新系统的所有软件包,但不包括不在软件库中的“本地安装的”包:
|
||||
|
||||
```
|
||||
pacman -Syu
|
||||
```
|
||||
|
||||
* `S` 代表同步
|
||||
* `y` 代表更新本地存储库
|
||||
* `u` 代表系统更新
|
||||
|
||||
也就是说,同步到中央软件库(主程序包数据库),刷新主程序包数据库的本地副本,然后执行系统更新(通过更新所有有更新版本可用的程序包)。
|
||||
|
||||
![系统更新][12]
|
||||
|
||||
> 注意!
|
||||
>
|
||||
> 对于 Arch Linux 用户,在系统升级前,建议你访问 [Arch-Linux 主页][2] 查看最新消息,以了解异常更新的情况。如果系统更新需要人工干预,主页上将发布相关的新闻。你也可以订阅 [RSS 源][13] 或 [Arch 的声明邮件][14]。
|
||||
>
|
||||
> 在升级基础软件(如 kernel、xorg、systemd 或 glibc) 之前,请注意查看相应的 [论坛][15],以了解大家报告的各种问题。
|
||||
>
|
||||
> 在 Arch 和 Manjaro 等滚动发行版中不支持**部分升级**。这意味着,当新的库版本被推送到软件库时,软件库中的所有包都需要根据库版本进行升级。例如,如果两个包依赖于同一个库,则仅升级一个包可能会破坏依赖于该库的旧版本的另一个包。
|
||||
|
||||
#### 用 Pacman 查找包
|
||||
|
||||
`pacman` 使用 `-Q` 选项查询本地包数据库,使用 `-S` 选项查询同步数据库,使用 `-F` 选项查询文件数据库。
|
||||
|
||||
`pacman` 可以在数据库中搜索包,包括包的名称和描述:
|
||||
|
||||
```
|
||||
pacman -Ss 字符串1 字符串2 ...
|
||||
```
|
||||
|
||||
![查找一个包][16]
|
||||
|
||||
查找已经被安装的包:
|
||||
|
||||
```
|
||||
pacman -Qs 字符串1 字符串2 ...
|
||||
```
|
||||
|
||||
根据文件名在远程软包中查找它所属的包:
|
||||
|
||||
```
|
||||
pacman -F 字符串1 字符串2 ...
|
||||
```
|
||||
|
||||
查看一个包的依赖树:
|
||||
|
||||
```
|
||||
pactree 软件包名
|
||||
```
|
||||
|
||||
#### 清除包缓存
|
||||
|
||||
`pacman` 将其下载的包存储在 `/var/cache/Pacman/pkg/` 中,并且不会自动删除旧版本或卸载的版本。这有一些优点:
|
||||
|
||||
1. 它允许 [降级][17] 一个包,而不需要通过其他来源检索以前的版本。
|
||||
2. 已卸载的软件包可以轻松地直接从缓存文件夹重新安装。
|
||||
|
||||
但是,有必要定期清理缓存以防止文件夹增大。
|
||||
|
||||
[pacman contrib][19] 包中提供的 [paccache(8)][18] 脚本默认情况下会删除已安装和未安装包的所有缓存版本,但最近 3 个版本除外:
|
||||
|
||||
```
|
||||
paccache -r
|
||||
```
|
||||
|
||||
![清除缓存][20]
|
||||
|
||||
要删除当前未安装的所有缓存包和未使用的同步数据库,请执行:
|
||||
|
||||
```
|
||||
pacman -Sc
|
||||
```
|
||||
|
||||
要从缓存中删除所有文件,请使用清除选项两次,这是最激进的方法,不会在缓存文件夹中留下任何内容:
|
||||
|
||||
```
|
||||
pacman -Scc
|
||||
```
|
||||
|
||||
#### 安装本地或者第三方的包
|
||||
|
||||
安装不是来自远程存储库的“本地”包:
|
||||
|
||||
```
|
||||
pacman -U 本地软件包路径.pkg.tar.xz
|
||||
```
|
||||
|
||||
安装官方存储库中未包含的“远程”软件包:
|
||||
|
||||
```
|
||||
pacman -U http://www.example.com/repo/example.pkg.tar.xz
|
||||
```
|
||||
|
||||
### 额外内容:用 pacman 排除常见错误
|
||||
|
||||
下面是使用 `pacman` 管理包时可能遇到的一些常见错误。
|
||||
|
||||
#### 提交事务失败(文件冲突)
|
||||
|
||||
如果你看到以下报错:
|
||||
|
||||
```
|
||||
error: could not prepare transaction
|
||||
error: failed to commit transaction (conflicting files)
|
||||
package: /path/to/file exists in filesystem
|
||||
Errors occurred, no packages were upgraded.
|
||||
```
|
||||
|
||||
这是因为 `pacman` 检测到文件冲突,不会为你覆盖文件。
|
||||
|
||||
解决这个问题的一个安全方法是首先检查另一个包是否拥有这个文件(`pacman-Qo 文件路径`)。如果该文件属于另一个包,请提交错误报告。如果文件不属于另一个包,请重命名“存在于文件系统中”的文件,然后重新发出更新命令。如果一切顺利,文件可能会被删除。
|
||||
|
||||
你可以显式地运行 `pacman -S –overwrite 要覆盖的文件模式**,强制 `pacman` 覆盖与 给模式匹配的文件,而不是手动重命名并在以后删除属于该包的所有文件。
|
||||
|
||||
#### 提交事务失败(包无效或损坏)
|
||||
|
||||
在 `/var/cache/pacman/pkg/` 中查找 `.part` 文件(部分下载的包),并将其删除。这通常是由在 `pacman.conf` 文件中使用自定义 `XferCommand` 引起的。
|
||||
|
||||
#### 初始化事务失败(无法锁定数据库)
|
||||
|
||||
当 `pacman` 要修改包数据库时,例如安装包时,它会在 `/var/lib/pacman/db.lck` 处创建一个锁文件。这可以防止 `pacman` 的另一个实例同时尝试更改包数据库。
|
||||
|
||||
如果 `pacman` 在更改数据库时被中断,这个过时的锁文件可能仍然保留。如果你确定没有 `pacman` 实例正在运行,那么请删除锁文件。
|
||||
|
||||
检查进程是否持有锁定文件:
|
||||
|
||||
```
|
||||
lsof /var/lib/pacman/db.lck
|
||||
```
|
||||
|
||||
如果上述命令未返回任何内容,则可以删除锁文件:
|
||||
|
||||
```
|
||||
rm /var/lib/pacman/db.lck
|
||||
```
|
||||
|
||||
如果你发现 `lsof` 命令输出了使用锁文件的进程的 PID,请先杀死这个进程,然后删除锁文件。
|
||||
|
||||
我希望你喜欢我对 `pacman` 基础命令的介绍。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/pacman-command/
|
||||
|
||||
作者:[Dimitrios Savvopoulos][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/dimitrios/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.archlinux.org/pacman/
|
||||
[2]: https://www.archlinux.org/
|
||||
[3]: https://wiki.archlinux.org/index.php/Arch_Build_System
|
||||
[4]: https://wiki.archlinux.org/index.php/Official_repositories
|
||||
[5]: https://itsfoss.com/install-arch-linux/
|
||||
[6]: https://itsfoss.com/things-to-do-after-installing-arch-linux/
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/essential-pacman-commands.jpg?ssl=1
|
||||
[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-S.png?ssl=1
|
||||
[9]: https://wiki.archlinux.org/index.php/Dependency
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-R.png?ssl=1
|
||||
[11]: https://itsfoss.com/update-arch-linux/
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-Syu.png?ssl=1
|
||||
[13]: https://www.archlinux.org/feeds/news/
|
||||
[14]: https://mailman.archlinux.org/mailman/listinfo/arch-announce/
|
||||
[15]: https://bbs.archlinux.org/
|
||||
[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-Ss.png?ssl=1
|
||||
[17]: https://wiki.archlinux.org/index.php/Downgrade
|
||||
[18]: https://jlk.fjfi.cvut.cz/arch/manpages/man/paccache.8
|
||||
[19]: https://www.archlinux.org/packages/?name=pacman-contrib
|
||||
[20]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-paccache-r.png?ssl=1
|
@ -0,0 +1,170 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13129-1.html)
|
||||
[#]: subject: (A new way to build cross-platform UIs for Linux ARM devices)
|
||||
[#]: via: (https://opensource.com/article/20/5/linux-arm-ui)
|
||||
[#]: author: (Bruno Muniz https://opensource.com/users/brunoamuniz)
|
||||
|
||||
一种为 Linux ARM 设备构建跨平台 UI 的新方法
|
||||
======
|
||||
|
||||
> AndroidXML 和 TotalCross 的运用为树莓派和其他设备创建 UI 提供了更简单的方法。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/18/123715oomfuuz94ioi41ii.jpg)
|
||||
|
||||
为应用程序创建良好的用户体验(UX)是一项艰巨的任务,尤其是在开发嵌入式应用程序时。今天,有两种图形用户界面(GUI)工具通常用于开发嵌入式软件:它们要么涉及复杂的技术,要么非常昂贵。
|
||||
|
||||
然而,我们已经创建了一个概念验证(PoC),它提供了一种新的方法来使用现有的、成熟的工具为运行在桌面、移动、嵌入式设备和低功耗 ARM 设备上的应用程序构建用户界面(UI)。我们的方法是使用 Android Studio 绘制 UI;使用 [TotalCross][2] 在设备上呈现 Android XML;采用被称为 [KnowCode][4] 的新 [TotalCross API][3];以及使用 [树莓派 4][5] 来执行应用程序。
|
||||
|
||||
### 选择 Android Studio
|
||||
|
||||
可以使用 TotalCross API 为应用程序构建一个美观的响应式用户体验,但是在 Android Studio 中创建 UI 缩短了制作原型和实际应用程序之间的时间。
|
||||
|
||||
有很多工具可以用来为应用程序构建 UI,但是 [Android Studio][6] 是全世界开发者最常使用的工具。除了它被大量采用以外,这个工具的使用也非常直观,而且它对于创建简单和复杂的应用程序都非常强大。在我看来,唯一的缺点是使用该工具所需的计算机性能,它比其他集成开发环境 (IDE) 如 VSCode 或其开源替代方案 [VSCodium][7] 要庞大得多。
|
||||
|
||||
通过思考这些问题,我们创建了一个概念验证,使用 Android Studio 绘制 UI,并使用 TotalCross 直接在设备上运行 AndroidXML。
|
||||
|
||||
### 构建 UI
|
||||
|
||||
对于我们的 PoC,我们想创建一个家用电器应用程序来控制温度和其他东西,并在 Linux ARM 设备上运行。
|
||||
|
||||
![Home appliance application to control thermostat][8]
|
||||
|
||||
我们想为树莓派开发我们的应用程序,所以我们使用 Android 的 [ConstraintLayout][10] 来构建 848x480(树莓派的分辨率)的固定屏幕大小的 UI,不过你可以用其他布局构建响应性 UI。
|
||||
|
||||
Android XML 为 UI 创建增加了很多灵活性,使得为应用程序构建丰富的用户体验变得容易。在下面的 XML 中,我们使用了两个主要组件:[ImageView][11] 和 [TextView][12]。
|
||||
|
||||
```
|
||||
<ImageView
|
||||
android:id="@+id/imageView6"
|
||||
android:layout_width="273dp"
|
||||
android:layout_height="291dp"
|
||||
android:background="@drawable/Casa"
|
||||
tools:layout_editor_absoluteX="109dp"
|
||||
tools:layout_editor_absoluteY="95dp" />
|
||||
<TextView
|
||||
android:id="@+id/insideTempEdit"
|
||||
android:layout_width="94dp"
|
||||
android:layout_height="92dp"
|
||||
android:background="#F5F5F5"
|
||||
android:text="20"
|
||||
android:textAlignment="center"
|
||||
android:gravity="center"
|
||||
android:textColor="#000000"
|
||||
android:textSize="67dp"
|
||||
android:textStyle="bold"
|
||||
tools:layout_editor_absoluteX="196dp"
|
||||
tools:layout_editor_absoluteY="246dp" />
|
||||
```
|
||||
|
||||
TextView 元素用于向用户显示一些数据,比如建筑物内的温度。大多数 ImageView 都用作用户与 UI 交互的按钮,但它们也需要实现屏幕上组件提供的事件。
|
||||
|
||||
### 用 TotalCross 整合
|
||||
|
||||
这个 PoC 中的第二项技术是 TotalCross。我们不想在设备上使用 Android 的任何东西,因为:
|
||||
|
||||
1。我们的目标是为 Linux ARM 提供一个出色的 UI。
|
||||
2。我们希望在设备上实现低占用。
|
||||
3。我们希望应用程序在低计算能力的低端硬件设备上运行(例如,没有 GPU、 低 RAM 等)。
|
||||
|
||||
首先,我们使用 [VSCode 插件][13] 创建了一个空的 TotalCross 项目。接下来,我们保存了 `drawable` 文件夹中的图像副本和 `xml` 文件夹中的 Android XML 文件副本,这两个文件夹都位于 `resources` 文件夹中:
|
||||
|
||||
![Home Appliance file structure][14]
|
||||
|
||||
为了使用 TotalCross 模拟器运行 XML 文件,我们添加了一个名为 KnowCode 的新 TotalCross API 和一个主窗口来加载 XML。下面的代码使用 API 加载和呈现 XML:
|
||||
|
||||
```
|
||||
public void initUI() {
|
||||
XmlScreenAbstractLayout xmlCont = XmlScreenFactory.create("xml / homeApplianceXML.xml");
|
||||
swap(xmlCont);
|
||||
}
|
||||
```
|
||||
|
||||
就这样!只需两个命令,我们就可以使用 TotalCross 运行 Android XML 文件。以下是 XML 如何在 TotalCross 的模拟器上执行:
|
||||
|
||||
![TotalCross simulator running temperature application][15]
|
||||
|
||||
完成这个 PoC 还有两件事要做:添加一些事件来提供用户交互,并在树莓派上运行它。
|
||||
|
||||
### 添加事件
|
||||
|
||||
KnowCode API 提供了一种通过 ID(`getControlByID`) 获取 XML 元素并更改其行为的方法,如添加事件、更改可见性等。
|
||||
|
||||
例如,为了使用户能够改变家中或其他建筑物的温度,我们在 UI 底部放置了加号和减号按钮,并在每次单击按钮时都会出现“单击”事件,使温度升高或降低一度:
|
||||
|
||||
```
|
||||
Button plus = (Button) xmlCont.getControlByID("@+id/plus");
|
||||
Label insideTempLabel = (Label) xmlCont.getControlByID("@+id/insideTempLabel");
|
||||
plus.addPressListener(new PressListener() {
|
||||
@Override
|
||||
public void controlPressed(ControlEvent e) {
|
||||
try {
|
||||
String tempString = insideTempLabel.getText();
|
||||
int temp;
|
||||
temp = Convert.toInt(tempString);
|
||||
insideTempLabel.setText(Convert.toString(++temp));
|
||||
} catch (InvalidNumberException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 在树莓派 4 上测试
|
||||
|
||||
最后一步!我们在一台设备上运行了应用程序并检查了结果。我们只需要打包应用程序并在目标设备上部署和运行它。[VNC][19] 也可用于检查设备上的应用程序。
|
||||
|
||||
整个应用程序,包括资源(图像等)、Android XML、TotalCross 和 Knowcode API,在 Linux ARM 上大约是 8MB。
|
||||
|
||||
下面是应用程序的演示:
|
||||
|
||||
![Application demo][20]
|
||||
|
||||
在本例中,该应用程序仅为 Linux ARM 打包,但同一应用程序可以作为 Linux 桌面应用程序运行,在Android 设备 、Windows、windows CE 甚至 iOS 上运行。
|
||||
|
||||
所有示例源代码和项目都可以在 [HomeApplianceXML GitHub][21] 存储库中找到。
|
||||
|
||||
### 现有工具的新玩法
|
||||
|
||||
为嵌入式应用程序创建 GUI 并不需要像现在这样困难。这种概念证明为如何轻松地完成这项任务提供了新的视角,不仅适用于嵌入式系统,而且适用于所有主要的操作系统,所有这些系统都使用相同的代码库。
|
||||
|
||||
我们的目标不是为设计人员或开发人员创建一个新的工具来构建 UI 应用程序;我们的目标是为使用现有的最佳工具提供新的玩法。
|
||||
|
||||
你对这种新的应用程序开发方式有何看法?在下面的评论中分享你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/5/linux-arm-ui
|
||||
|
||||
作者:[Bruno Muniz][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/brunoamuniz
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_desk_home_laptop_browser.png?itok=Y3UVpY0l (Digital images of a computer desktop)
|
||||
[2]: https://totalcross.com/
|
||||
[3]: https://yourapp.totalcross.com/knowcode-app
|
||||
[4]: https://github.com/TotalCross/KnowCodeXML
|
||||
[5]: https://www.raspberrypi.org/
|
||||
[6]: https://developer.android.com/studio
|
||||
[7]: https://vscodium.com/
|
||||
[8]: https://opensource.com/sites/default/files/uploads/homeapplianceapp.png (Home appliance application to control thermostat)
|
||||
[9]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[10]: https://codelabs.developers.google.com/codelabs/constraint-layout/index.html#0
|
||||
[11]: https://developer.android.com/reference/android/widget/ImageView
|
||||
[12]: https://developer.android.com/reference/android/widget/TextView
|
||||
[13]: https://medium.com/totalcross-community/totalcross-plugin-for-vscode-4f45da146a0a
|
||||
[14]: https://opensource.com/sites/default/files/uploads/homeappliancexml.png (Home Appliance file structure)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/totalcross-simulator_0.png (TotalCross simulator running temperature application)
|
||||
[16]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+button
|
||||
[17]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+label
|
||||
[18]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[19]: https://tigervnc.org/
|
||||
[20]: https://opensource.com/sites/default/files/uploads/application.gif (Application demo)
|
||||
[21]: https://github.com/TotalCross/HomeApplianceXML
|
@ -0,0 +1,201 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13104-1.html)
|
||||
[#]: subject: (Top Arch-based User Friendly Linux Distributions That are Easier to Install and Use Than Arch Linux Itself)
|
||||
[#]: via: (https://itsfoss.com/arch-based-linux-distros/)
|
||||
[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
|
||||
|
||||
9 个易用的基于 Arch 的用户友好型 Linux 发行版
|
||||
======
|
||||
|
||||
在 Linux 社区中,[Arch Linux][1] 有一群狂热的追随者。这个轻量级的发行版以 DIY 的态度提供了最前沿的更新。
|
||||
|
||||
但是,Arch 的目标用户是那些更有经验的用户。因此,它通常被认为是那些技术不够(或耐心不够)的人所无法触及的。
|
||||
|
||||
事实上,只是最开始的步骤,[安装 Arch Linux 就足以把很多人吓跑][2]。与大多数其他发行版不同,Arch Linux 没有一个易于使用的图形安装程序。安装过程中涉及到的磁盘分区,连接到互联网,挂载驱动器和创建文件系统等只用命令行工具来操作。
|
||||
|
||||
对于那些不想经历复杂的安装和设置的人来说,有许多用户友好的基于 Arch 的发行版。
|
||||
|
||||
在本文中,我将向你展示一些 Arch 替代发行版。这些发行版附带了图形安装程序、图形包管理器和其他工具,比它们的命令行版本更容易使用。
|
||||
|
||||
### 更容易设置和使用的基于 Arch 的 Linux 发行版
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/10/112812sc42txp4eexco44x.jpg)
|
||||
|
||||
请注意,这不是一个排名列表。这些数字只是为了计数的目的。排第二的发行版不应该被认为比排第七的发行版好。
|
||||
|
||||
#### 1、Manjaro Linux
|
||||
|
||||
![][4]
|
||||
|
||||
[Manjaro][5] 不需要任何介绍。它是几年来最流行的 Linux 发行版之一,它值得拥有。
|
||||
|
||||
Manjaro 提供了 Arch Linux 的所有优点,同时注重用户友好性和可访问性。Manjaro 既适合新手,也适合有经验的 Linux 用户。
|
||||
|
||||
**对于新手**,它提供了一个用户友好的安装程序,系统本身也设计成可以在你[最喜爱的桌面环境 ][6](DE)或窗口管理器中直接“开箱即用”。
|
||||
|
||||
**对于更有经验的用户**,Manjaro 还提供多种功能,以满足每个个人的口味和喜好。[Manjaro Architect][7] 提供了安装各种 Manjaro 风格的选项,并为那些想要完全自由地塑造系统的人提供了各种桌面环境、文件系统([最近推出的 ZFS][8]) 和引导程序的选择。
|
||||
|
||||
Manjaro 也是一个滚动发布的前沿发行版。然而,与 Arch 不同的是,Manjaro 首先测试更新,然后将其提供给用户。稳定在这里也很重要。
|
||||
|
||||
#### 2、ArcoLinux
|
||||
|
||||
![][9]
|
||||
|
||||
[ArcoLinux][10](以前称为 ArchMerge)是一个基于 Arch Linux 的发行版。开发团队提供了三种变体。ArcoLinux、ArcoLinuxD 和 ArcoLinuxB。
|
||||
|
||||
ArcoLinux 是一个功能齐全的发行版,附带有 [Xfce 桌面][11]、[Openbox][12] 和 [i3 窗口管理器][13]。
|
||||
|
||||
**ArcoLinuxD** 是一个精简的发行版,它包含了一些脚本,可以让高级用户安装任何桌面和应用程序。
|
||||
|
||||
**ArcoLinuxB** 是一个让用户能够构建自定义发行版的项目,同时还开发了几个带有预配置桌面的社区版本,如 Awesome、bspwm、Budgie、Cinnamon、Deepin、GNOME、MATE 和 KDE Plasma。
|
||||
|
||||
ArcoLinux 还提供了各种视频教程,因为它非常注重学习和获取 Linux 技能。
|
||||
|
||||
#### 3、Archlabs Linux
|
||||
|
||||
![][14]
|
||||
|
||||
[ArchLabs Linux][15] 是一个轻量级的滚动版 Linux 发行版,基于最精简的 Arch Linux,带有 [Openbox][16] 窗口管理器。[ArchLabs][17] 在观感设计中受到 [BunsenLabs][18] 的影响和启发,主要考虑到中级到高级用户的需求。
|
||||
|
||||
#### 4、Archman Linux
|
||||
|
||||
![][19]
|
||||
|
||||
[Archman][20] 是一个独立的项目。Arch Linux 发行版对于没有多少 Linux 经验的用户来说通常不是理想的操作系统。要想在最小的挫折感下让事情变得更有意义,必须要有相当的背景知识。Archman Linux 的开发人员正试图改变这种评价。
|
||||
|
||||
Archman 的开发是基于对开发的理解,包括用户反馈和体验组件。根据团队过去的经验,将用户的反馈和要求融合在一起,确定路线图并完成构建工作。
|
||||
|
||||
#### 5、EndeavourOS
|
||||
|
||||
![][21]
|
||||
|
||||
当流行的基于 Arch 的发行版 [Antergos 在 2019 结束][22] 时,它留下了一个友好且非常有用的社区。Antergos 项目结束的原因是因为该系统对于开发人员来说太难维护了。
|
||||
|
||||
在宣布结束后的几天内,一些有经验的用户通过创建一个新的发行版来填补 Antergos 留下的空白,从而维护了以前的社区。这就是 [EndeavourOS][23] 的诞生。
|
||||
|
||||
[EndeavourOS][24] 是轻量级的,并且附带了最少数量的预装应用程序。一块近乎空白的画布,随时可以个性化。
|
||||
|
||||
#### 6、RebornOS
|
||||
|
||||
![][25]
|
||||
|
||||
[RebornOS][26] 开发人员的目标是将 Linux 的真正威力带给每个人,一个 ISO 提供了 15 个桌面环境可供选择,并提供无限的定制机会。
|
||||
|
||||
RebornOS 还声称支持 [Anbox][27],它可以在桌面 Linux 上运行 Android 应用程序。它还提供了一个简单的内核管理器 GUI 工具。
|
||||
|
||||
再加上 [Pacman][28]、[AUR][29],以及定制版本的 Cnchi 图形安装程序,Arch Linux 终于可以让最没有经验的用户也能够使用了。
|
||||
|
||||
#### 7、Chakra Linux
|
||||
|
||||
![][30]
|
||||
|
||||
一个社区开发的 GNU/Linux 发行版,它的亮点在 KDE 和 Qt 技术。[Chakra Linux][31] 不在特定日期安排发布,而是使用“半滚动发布”系统。
|
||||
|
||||
这意味着 Chakra Linux 的核心包被冻结,只在修复安全问题时才会更新。这些软件包是在最新版本经过彻底测试后更新的,然后再转移到永久软件库(大约每六个月更新一次)。
|
||||
|
||||
除官方软件库外,用户还可以安装 Chakra 社区软件库 (CCR) 的软件包,该库为官方存储库中未包含的软件提供用户制作的 PKGINFOs 和 [PKGBUILD][32] 脚本,其灵感来自于 Arch 用户软件库(AUR)。
|
||||
|
||||
#### 8、Artix Linux
|
||||
|
||||
![Artix Mate Edition][33]
|
||||
|
||||
[Artix Linux][34] 也是一个基于 Arch Linux 的滚动发行版,它使用 [OpenRC][35]、[runit][36] 或 [s6][37] 作为初始化工具而不是 [systemd][38]。
|
||||
|
||||
Artix Linux 有自己的软件库,但作为一个基于 `pacman` 的发行版,它可以使用 Arch Linux 软件库或任何其他衍生发行版的软件包,甚至可以使用明确依赖于 systemd 的软件包。也可以使用 [Arch 用户软件库][29](AUR)。
|
||||
|
||||
#### 9、BlackArch Linux
|
||||
|
||||
![][39]
|
||||
|
||||
BlackArch 是一个基于 Arch Linux 的 [渗透测试发行版][40],它提供了大量的网络安全工具。它是专门为渗透测试人员和安全研究人员创建的。该软件库包含 2400 多个[黑客和渗透测试工具 ][41],可以单独安装,也可以分组安装。BlackArch Linux 兼容现有的 Arch Linux 包。
|
||||
|
||||
### 想要真正的原版 Arch Linux 吗?可以使用图形化 Arch 安装程序简化安装
|
||||
|
||||
如果你想使用原版的 Arch Linux,但又被它困难的安装所难倒。幸运的是,你可以下载一个带有图形安装程序的 Arch Linux ISO。
|
||||
|
||||
Arch 安装程序基本上是 Arch Linux ISO 的一个相对容易使用的基于文本的安装程序。它比裸奔的 Arch 安装容易得多。
|
||||
|
||||
#### Anarchy Installer
|
||||
|
||||
![][42]
|
||||
|
||||
[Anarchy installer][43] 打算为新手和有经验的 Linux 用户提供一种简单而无痛苦的方式来安装 ArchLinux。在需要的时候安装,在需要的地方安装,并且以你想要的方式安装。这就是 Anarchy 的哲学。
|
||||
|
||||
启动安装程序后,将显示一个简单的 [TUI 菜单][44],列出所有可用的安装程序选项。
|
||||
|
||||
#### Zen Installer
|
||||
|
||||
![][45]
|
||||
|
||||
[Zen Installer][46] 为安装 Arch Linux 提供了一个完整的图形(点击式)环境。它支持安装多个桌面环境 、AUR 以及 Arch Linux 的所有功能和灵活性,并且易于图形化安装。
|
||||
|
||||
ISO 将引导一个临场环境,然后在你连接到互联网后下载最新稳定版本的安装程序。因此,你将始终获得最新的安装程序和更新的功能。
|
||||
|
||||
### 总结
|
||||
|
||||
对于许多用户来说,基于 Arch 的发行版会是一个很好的无忧选择,而像 Anarchy 这样的图形化安装程序至少离原版的 Arch Linux 更近了一步。
|
||||
|
||||
在我看来,[Arch Linux 的真正魅力在于它的安装过程][2],对于 Linux 爱好者来说,这是一个学习的机会,而不是麻烦。Arch Linux 及其衍生产品有很多东西需要你去折腾,但是在折腾的过程中你就会进入到开源软件的世界,这里是神奇的新世界。下次再见!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/arch-based-linux-distros/
|
||||
|
||||
作者:[Dimitrios Savvopoulos][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/dimitrios/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.archlinux.org/
|
||||
[2]: https://itsfoss.com/install-arch-linux/
|
||||
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/06/arch-based-linux-distributions.png?ssl=1
|
||||
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/manjaro-20.jpg?ssl=1
|
||||
[5]: https://manjaro.org/
|
||||
[6]: https://itsfoss.com/best-linux-desktop-environments/
|
||||
[7]: https://itsfoss.com/manjaro-architect-review/
|
||||
[8]: https://itsfoss.com/manjaro-20-release/
|
||||
[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/arcolinux.png?ssl=1
|
||||
[10]: https://arcolinux.com/
|
||||
[11]: https://www.xfce.org/
|
||||
[12]: http://openbox.org/wiki/Main_Page
|
||||
[13]: https://i3wm.org/
|
||||
[14]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/06/Archlabs.jpg?ssl=1
|
||||
[15]: https://itsfoss.com/archlabs-review/
|
||||
[16]: https://en.wikipedia.org/wiki/Openbox
|
||||
[17]: https://archlabslinux.com/
|
||||
[18]: https://www.bunsenlabs.org/
|
||||
[19]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/06/Archman.png?ssl=1
|
||||
[20]: https://archman.org/en/
|
||||
[21]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/04_endeavouros_slide.jpg?ssl=1
|
||||
[22]: https://itsfoss.com/antergos-linux-discontinued/
|
||||
[23]: https://itsfoss.com/endeavouros/
|
||||
[24]: https://endeavouros.com/
|
||||
[25]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/06/RebornOS.png?ssl=1
|
||||
[26]: https://rebornos.org/
|
||||
[27]: https://anbox.io/
|
||||
[28]: https://itsfoss.com/pacman-command/
|
||||
[29]: https://itsfoss.com/aur-arch-linux/
|
||||
[30]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/06/Chakra_Goedel_Screenshot.png?ssl=1
|
||||
[31]: https://www.chakralinux.org/
|
||||
[32]: https://wiki.archlinux.org/index.php/PKGBUILD
|
||||
[33]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/06/Artix_MATE_edition.png?ssl=1
|
||||
[34]: https://artixlinux.org/
|
||||
[35]: https://en.wikipedia.org/wiki/OpenRC
|
||||
[36]: https://en.wikipedia.org/wiki/Runit
|
||||
[37]: https://en.wikipedia.org/wiki/S6_(software)
|
||||
[38]: https://en.wikipedia.org/wiki/Systemd
|
||||
[39]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/06/BlackArch.png?ssl=1
|
||||
[40]: https://itsfoss.com/linux-hacking-penetration-testing/
|
||||
[41]: https://itsfoss.com/best-kali-linux-tools/
|
||||
[42]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/anarchy.jpg?ssl=1
|
||||
[43]: https://anarchyinstaller.org/
|
||||
[44]: https://en.wikipedia.org/wiki/Text-based_user_interface
|
||||
[45]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/zen.jpg?ssl=1
|
||||
[46]: https://sourceforge.net/projects/revenge-installer/
|
260
published/20200615 LaTeX Typesetting - Part 1 (Lists).md
Normal file
260
published/20200615 LaTeX Typesetting - Part 1 (Lists).md
Normal file
@ -0,0 +1,260 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "rakino"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13112-1.html"
|
||||
[#]: subject: "LaTeX Typesetting – Part 1 (Lists)"
|
||||
[#]: via: "https://fedoramagazine.org/latex-typesetting-part-1/"
|
||||
[#]: author: "Earl Ramirez https://fedoramagazine.org/author/earlramirez/"
|
||||
|
||||
LaTeX 排版(1):列表
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
本系列基于前文《[在 Fedora 上用 LaTex 和 TeXstudio 排版你的文档][2]》和《[LaTeX 基础][3]》,本文即系列的第一部分,是关于 LaTeX 列表的。
|
||||
|
||||
### 列表类型
|
||||
|
||||
LaTeX 中的列表是封闭的环境,列表中的每个项目可以取一行文字到一个完整的段落。在 LaTeX 中有三种列表类型:
|
||||
|
||||
* `itemize`:<ruby>无序列表<rt>unordered list</rt></ruby>/<ruby>项目符号列表<rt>bullet list</rt></ruby>
|
||||
* `enumerate`:<ruby>有序列表<rt>ordered list</rt></ruby>
|
||||
* `description`:<ruby>描述列表<rt>descriptive list</rt></ruby>
|
||||
|
||||
### 创建列表
|
||||
|
||||
要创建一个列表,需要在每个项目前加上控制序列 `\item`,并在项目清单前后分别加上控制序列 `\begin{<类型>}` 和 `\end`{<类型>}`(将其中的 `<类型>` 替换为将要使用的列表类型),如下例:
|
||||
|
||||
#### itemize(无序列表)
|
||||
|
||||
```
|
||||
\begin{itemize}
|
||||
\item Fedora
|
||||
\item Fedora Spin
|
||||
\item Fedora Silverblue
|
||||
\end{itemize}
|
||||
```
|
||||
|
||||
![][4]
|
||||
|
||||
#### enumerate(有序列表)
|
||||
|
||||
```
|
||||
\begin{enumerate}
|
||||
\item Fedora CoreOS
|
||||
\item Fedora Silverblue
|
||||
\item Fedora Spin
|
||||
\end{enumerate}
|
||||
```
|
||||
|
||||
![][5]
|
||||
|
||||
#### description(描述列表)
|
||||
|
||||
```
|
||||
\begin{description}
|
||||
\item[Fedora 6] Code name Zod
|
||||
\item[Fedora 8] Code name Werewolf
|
||||
\end{description}
|
||||
```
|
||||
|
||||
![][6]
|
||||
|
||||
### 列表项目间距
|
||||
|
||||
可以通过在导言区加入 `\usepackage{enumitem}` 来自定义默认的间距,宏包 `enumitem` 启用了选项 `noitemsep` 和控制序列 `\itemsep`,可以在列表中使用它们,如下例所示:
|
||||
|
||||
#### 使用选项 noitemsep
|
||||
|
||||
将选项 `noitemsep` 封闭在方括号内,并同下文所示放在控制序列 `\begin` 之后,该选项将移除默认的间距。
|
||||
|
||||
```
|
||||
\begin{itemize}[noitemsep]
|
||||
\item Fedora
|
||||
\item Fedora Spin
|
||||
\item Fedora Silverblue
|
||||
\end{itemize}
|
||||
```
|
||||
|
||||
![][7]
|
||||
|
||||
#### 使用控制序列 \itemsep
|
||||
|
||||
控制序列 `\itemsep` 必须以一个数字作为后缀,用以表示列表项目之间应该有多少空间。
|
||||
|
||||
```
|
||||
\begin{itemize} \itemsep0.75pt
|
||||
\item Fedora Silverblue
|
||||
\item Fedora CoreOS
|
||||
\end{itemize}
|
||||
```
|
||||
|
||||
![][8]
|
||||
|
||||
### 嵌套列表
|
||||
|
||||
LaTeX 最多最多支持四层嵌套列表,如下例:
|
||||
|
||||
#### 嵌套无序列表
|
||||
|
||||
```
|
||||
\begin{itemize}[noitemsep]
|
||||
\item Fedora Versions
|
||||
\begin{itemize}
|
||||
\item Fedora 8
|
||||
\item Fedora 9
|
||||
\begin{itemize}
|
||||
\item Werewolf
|
||||
\item Sulphur
|
||||
\begin{itemize}
|
||||
\item 2007-05-31
|
||||
\item 2008-05-13
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\item Fedora Spin
|
||||
\item Fedora Silverblue
|
||||
\end{itemize}
|
||||
```
|
||||
|
||||
![][9]
|
||||
|
||||
#### 嵌套有序列表
|
||||
|
||||
```
|
||||
\begin{enumerate}[noitemsep]
|
||||
\item Fedora Versions
|
||||
\begin{enumerate}
|
||||
\item Fedora 8
|
||||
\item Fedora 9
|
||||
\begin{enumerate}
|
||||
\item Werewolf
|
||||
\item Sulphur
|
||||
\begin{enumerate}
|
||||
\item 2007-05-31
|
||||
\item 2008-05-13
|
||||
\end{enumerate}
|
||||
\end{enumerate}
|
||||
\end{enumerate}
|
||||
\item Fedora Spin
|
||||
\item Fedora Silverblue
|
||||
\end{enumerate}
|
||||
```
|
||||
|
||||
![][10]
|
||||
|
||||
### 每种列表类型的列表样式名称
|
||||
|
||||
**enumerate(有序列表)** | **itemize(无序列表)**
|
||||
---|---
|
||||
`\alph*` (小写字母) | `$\bullet$` (●)
|
||||
`\Alph*` (大写字母) | `$\cdot$` (•)
|
||||
`\arabic*` (阿拉伯数字) | `$\diamond$` (◇)
|
||||
`\roman*` (小写罗马数字) | `$\ast$` (✲)
|
||||
`\Roman*` (大写罗马数字) | `$\circ$` (○)
|
||||
| `$-$` (-)
|
||||
|
||||
### 按嵌套深度划分的默认样式
|
||||
|
||||
**嵌套深度** | **enumerate(有序列表)** | **itemize(无序列表)**
|
||||
---|---|---
|
||||
1 | 阿拉伯数字 | (●)
|
||||
2 | 小写字母 | (-)
|
||||
3 | 小写罗马数字 | (✲)
|
||||
4 | 大写字母 | (•)
|
||||
|
||||
### 设置列表样式
|
||||
|
||||
下面的例子列举了无序列表的不同样式。
|
||||
|
||||
```
|
||||
% 无序列表样式
|
||||
\begin{itemize}
|
||||
\item[$\ast$] Asterisk
|
||||
\item[$\diamond$] Diamond
|
||||
\item[$\circ$] Circle
|
||||
\item[$\cdot$] Period
|
||||
\item[$\bullet$] Bullet (default)
|
||||
\item[--] Dash
|
||||
\item[$-$] Another dash
|
||||
\end{itemize}
|
||||
```
|
||||
|
||||
![][11]
|
||||
|
||||
有三种设置列表样式的方式,下面将按照优先级从高到低的顺序分别举例。
|
||||
|
||||
#### 方式一:为各项目单独设置
|
||||
|
||||
将需要的样式名称封闭在方括号内,并放在控制序列 `\item` 之后,如下例:
|
||||
|
||||
```
|
||||
% 方式一
|
||||
\begin{itemize}
|
||||
\item[$\ast$] Asterisk
|
||||
\item[$\diamond$] Diamond
|
||||
\item[$\circ$] Circle
|
||||
\item[$\cdot$] period
|
||||
\item[$\bullet$] Bullet (default)
|
||||
\item[--] Dash
|
||||
\item[$-$] Another dash
|
||||
\end{itemize}
|
||||
```
|
||||
|
||||
#### 方式二:为整个列表设置
|
||||
|
||||
将需要的样式名称以 `label=` 前缀并封闭在方括号内,放在控制序列 `\begin` 之后,如下例:
|
||||
|
||||
```
|
||||
% 方式二
|
||||
\begin{enumerate}[label=\Alph*.]
|
||||
\item Fedora 32
|
||||
\item Fedora 31
|
||||
\item Fedora 30
|
||||
\end{enumerate}
|
||||
```
|
||||
|
||||
#### 方式三:为整个文档设置
|
||||
|
||||
该方式将改变整个文档的默认样式。使用 `\renewcommand` 来设置项目标签的值,下例分别为四个嵌套深度的项目标签设置了不同的样式。
|
||||
|
||||
```
|
||||
% 方式三
|
||||
\renewcommand{\labelitemi}{$\ast$}
|
||||
\renewcommand{\labelitemii}{$\diamond$}
|
||||
\renewcommand{\labelitemiii}{$\bullet$}
|
||||
\renewcommand{\labelitemiv}{$-$}
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
LaTeX 支持三种列表,而每种列表的风格和间距都是可以自定义的。在以后的文章中,我们将解释更多的 LaTeX 元素。
|
||||
|
||||
关于 LaTeX 列表的延伸阅读可以在这里找到:[LaTeX List Structures][12]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/latex-typesetting-part-1/
|
||||
|
||||
作者:[Earl Ramirez][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[rakino](https://github.com/rakino)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/earlramirez/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2020/06/latex-series-816x345.png
|
||||
[2]: https://fedoramagazine.org/typeset-latex-texstudio-fedora
|
||||
[3]: https://fedoramagazine.org/fedora-classroom-latex-101-beginners
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-1.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-2.png
|
||||
[6]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-3.png
|
||||
[7]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-4.png
|
||||
[8]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-5.png
|
||||
[9]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-7.png
|
||||
[10]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-8.png
|
||||
[11]: https://fedoramagazine.org/wp-content/uploads/2020/06/image-9.png
|
||||
[12]: https://en.wikibooks.org/wiki/LaTeX/List_Structures
|
@ -0,0 +1,126 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13110-1.html)
|
||||
[#]: subject: (Give Your GNOME Desktop a Tiling Makeover With Material Shell GNOME Extension)
|
||||
[#]: via: (https://itsfoss.com/material-shell/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
使用 Material Shell 扩展将你的 GNOME 桌面打造成平铺式风格
|
||||
======
|
||||
|
||||
平铺式窗口的特性吸引了很多人的追捧。也许是因为它很好看,也许是因为它能提高 [Linux 快捷键][1] 玩家的效率。又或者是因为使用不同寻常的平铺式窗口是一种新奇的挑战。
|
||||
|
||||
![Tiling Windows in Linux | Image Source][2]
|
||||
|
||||
从 i3 到 [Sway][3],Linux 桌面拥有各种各样的平铺式窗口管理器。配置一个平铺式窗口管理器需要一个陡峭的学习曲线。
|
||||
|
||||
这就是为什么像 [Regolith 桌面][4] 这样的项目会存在,给你预先配置好的平铺桌面,让你可以更轻松地开始使用平铺窗口。
|
||||
|
||||
让我给你介绍一个类似的项目 —— Material Shell。它可以让你用上平铺式桌面,甚至比 [Regolith][5] 还简单。
|
||||
|
||||
### Material Shell 扩展:将 GNOME 桌面转变成平铺式窗口管理器
|
||||
|
||||
[Material Shell][6] 是一个 GNOME 扩展,这就是它最好的地方。这意味着你不需要注销并登录其他桌面环境。你只需要启用或关闭这个扩展就可以自如的切换你的工作环境。
|
||||
|
||||
我会列出 Material Shell 的各种特性,但是也许视频更容易让你理解:
|
||||
|
||||
- [video](https://youtu.be/Wc5mbuKrGDE)
|
||||
|
||||
这个项目叫做 Material Shell 是因为它遵循 [Material Design][8] 原则。因此这个应用拥有一个美观的界面。这就是它最重要的一个特性。
|
||||
|
||||
#### 直观的界面
|
||||
|
||||
Material Shell 添加了一个左侧面板,以便快速访问。在此面板上,你可以在底部找到系统托盘,在顶部找到搜索和工作区。
|
||||
|
||||
所有新打开的应用都会添加到当前工作区中。你也可以创建新的工作区并切换到该工作区,以将正在运行的应用分类。其实这就是工作区最初的意义。
|
||||
|
||||
在 Material Shell 中,每个工作区都可以显示为具有多个应用程序的行列,而不是包含多个应用程序的程序框。
|
||||
|
||||
#### 平铺式窗口
|
||||
|
||||
在工作区中,你可以一直在顶部看到所有打开的应用程序。默认情况下,应用程序会像在 GNOME 桌面中那样铺满整个屏幕。你可以使用右上角的布局改变器来改变布局,将其分成两半、多列或多个应用网格。
|
||||
|
||||
这段视频一目了然的显示了以上所有功能:
|
||||
|
||||
- [video](https://player.vimeo.com/video/460050750?dnt=1&app_id=122963)
|
||||
|
||||
#### 固定布局和工作区
|
||||
|
||||
Material Shell 会记住你打开的工作区和窗口,这样你就不必重新组织你的布局。这是一个很好的特性,因为如果你对应用程序的位置有要求的话,它可以节省时间。
|
||||
|
||||
#### 热建/快捷键
|
||||
|
||||
像任何平铺窗口管理器一样,你可以使用键盘快捷键在应用程序和工作区之间切换。
|
||||
|
||||
* `Super+W` 切换到上个工作区;
|
||||
* `Super+S` 切换到下个工作区;
|
||||
* `Super+A` 切换到左边的窗口;
|
||||
* `Super+D` 切换到右边的窗口;
|
||||
* `Super+1`、`Super+2` … `Super+0` 切换到某个指定的工作区;
|
||||
* `Super+Q` 关闭当前窗口;
|
||||
* `Super+[鼠标拖动]` 移动窗口;
|
||||
* `Super+Shift+A` 将当前窗口左移;
|
||||
* `Super+Shift+D` 将当前窗口右移;
|
||||
* `Super+Shift+W` 将当前窗口移到上个工作区;
|
||||
* `Super+Shift+S` 将当前窗口移到下个工作区。
|
||||
|
||||
### 安装 Material Shell
|
||||
|
||||
> 警告!
|
||||
>
|
||||
> 对于大多数用户来说,平铺式窗口可能会导致混乱。你最好先熟悉如何使用 GNOME 扩展。如果你是 Linux 新手或者你害怕你的系统发生翻天覆地的变化,你应当避免使用这个扩展。
|
||||
|
||||
Material Shell 是一个 GNOME 扩展。所以,请 [检查你的桌面环境][9],确保你运行的是 GNOME 3.34 或者更高的版本。
|
||||
|
||||
除此之外,我注意到在禁用 Material Shell 之后,它会导致 Firefox 的顶栏和 Ubuntu 的坞站消失。你可以在 GNOME 的“扩展”应用程序中禁用/启用 Ubuntu 的坞站扩展来使其变回原来的样子。我想这些问题也应该在系统重启后消失,虽然我没试过。
|
||||
|
||||
我希望你知道 [如何使用 GNOME 扩展][10]。最简单的办法就是 [在浏览器中打开这个链接][11],安装 GNOME 扩展浏览器插件,然后启用 Material Shell 扩展即可。
|
||||
|
||||
![][12]
|
||||
|
||||
如果你不喜欢这个扩展,你也可以在同样的链接中禁用它。或者在 GNOME 的“扩展”应用程序中禁用它。
|
||||
|
||||
![][13]
|
||||
|
||||
### 用不用平铺式?
|
||||
|
||||
我使用多个电脑屏幕,我发现 Material Shell 不适用于多个屏幕的情况。这是开发者将来可以改进的地方。
|
||||
|
||||
除了这个毛病以外,Material Shell 是个让你开始使用平铺式窗口的好东西。如果你尝试了 Material Shell 并且喜欢它,请 [在 GitHub 上给它一个星标或赞助它][14] 来鼓励这个项目。
|
||||
|
||||
由于某些原因,平铺窗户越来越受欢迎。最近发布的 [Pop OS 20.04][15] 也增加了平铺窗口的功能。有一个类似的项目叫 PaperWM,也是这样做的。
|
||||
|
||||
但正如我前面提到的,平铺布局并不适合所有人,它可能会让很多人感到困惑。
|
||||
|
||||
你呢?你是喜欢平铺窗口还是喜欢经典的桌面布局?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/material-shell/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/ubuntu-shortcuts/
|
||||
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/linux-ricing-example-800x450.jpg?resize=800%2C450&ssl=1
|
||||
[3]: https://itsfoss.com/sway-window-manager/
|
||||
[4]: https://itsfoss.com/regolith-linux-desktop/
|
||||
[5]: https://regolith-linux.org/
|
||||
[6]: https://material-shell.com
|
||||
[7]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
|
||||
[8]: https://material.io/
|
||||
[9]: https://itsfoss.com/find-desktop-environment/
|
||||
[10]: https://itsfoss.com/gnome-shell-extensions/
|
||||
[11]: https://extensions.gnome.org/extension/3357/material-shell/
|
||||
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/install-material-shell.png?resize=800%2C307&ssl=1
|
||||
[13]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/material-shell-gnome-extension.png?resize=799%2C497&ssl=1
|
||||
[14]: https://github.com/material-shell/material-shell
|
||||
[15]: https://itsfoss.com/pop-os-20-04-review/
|
297
published/20201013 My first day using Ansible.md
Normal file
297
published/20201013 My first day using Ansible.md
Normal file
@ -0,0 +1,297 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "MjSeven"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13079-1.html"
|
||||
[#]: subject: "My first day using Ansible"
|
||||
[#]: via: "https://opensource.com/article/20/10/first-day-ansible"
|
||||
[#]: author: "David Both https://opensource.com/users/dboth"
|
||||
|
||||
使用 Ansible 的第一天
|
||||
======
|
||||
|
||||
> 一名系统管理员分享了如何使用 Ansible 在网络中配置计算机并把其带入实际工作的信息和建议。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/03/105826sn41jj0i8evu19nn.jpg)
|
||||
|
||||
无论是第一次还是第五十次,启动并运行一台新的物理或虚拟计算机都非常耗时,而且需要大量的工作。多年来,我一直使用我创建的一系列脚本和 RPM 来安装所需的软件包,并为我喜欢的工具配置各种选项。这种方法效果很好,简化了我的工作,而且还减少了在键盘上输入命令的时间。
|
||||
|
||||
我一直在寻找更好的工作方式。近几年来,我一直在听到并且读到有关 [Ansible][2] 的信息,它是一个自动配置和管理系统的强大工具。Ansible 允许系统管理员在一个或多个<ruby>剧本<rt>playbook</rt></ruby>中为每个主机指定一个特定状态,然后执行各种必要的任务,使主机进入该状态。这包括安装或删除各种资源,例如 RPM 或 Apt 软件包、配置文件和其它文件、用户、组等等。
|
||||
|
||||
因为一些琐事,我推迟了很长一段时间学习如何使用它。直到最近,我遇到了一个我认为 Ansible 可以轻松解决的问题。
|
||||
|
||||
这篇文章并不会完整地告诉你如何入门 Ansible,相反,它只是对我遇到的问题和我在一些隐秘的地方发现的信息的做了一些记录。我在各种在线讨论和问答小组中找到的有关 Ansible 的许多信息都是错误的。错误范围包括明显的老旧信息(没有任何日期或来源的迹象),还有一些是完全错误的信息。
|
||||
|
||||
本文所介绍的内容是有用的,尽管可能还有其它方法可以完成相同的事情,但我使用的是 Ansible 2.9.13 和 [Python][3] 3.8.5。
|
||||
|
||||
### 我的问题
|
||||
|
||||
我所有的最佳学习经历都始于我需要解决的问题,这次也不例外。
|
||||
|
||||
我一直在做一个小项目,修改 [Midnight Commander][4] 文件管理器的配置文件,并将它们推送到我网络上的各种系统中进行测试。尽管我有一个脚本可以自动执行这个操作,但它仍然需要使用命令行循环来提供我想要推送新代码的系统名称。我对配置文件进行了大量的更改,这使我必须频繁推送新的配置文件。但是,就在我以为我的新配置刚刚好时,我发现了一个问题,所以我需要在修复后再进行一次推送。
|
||||
|
||||
这种环境使得很难跟踪哪些系统有新文件,哪些没有。我还有几个主机需要区别对待。我对 Ansible 的一点了解表明,它可能能够满足我的全部或大部分工作。
|
||||
|
||||
### 开始
|
||||
|
||||
我读过许多有关 Ansible 的好文章和书籍,但从来没有在“我必须现在就把这个做好!”的情况下读过。而现在 —— 好吧,就是现在!
|
||||
|
||||
在重读这些文档时,我发现它们主要是在讨论如何从 GitHub 开始安装并使用 Ansible,这很酷。但是我真的只是想尽快开始,所以我使用 DNF 和 Fedora 仓库中的版本在我的 Fedora 工作站上安装了它,非常简单。
|
||||
|
||||
但是后来我开始寻找文件位置,并尝试确定需要修改哪些配置文件、将我的剧本保存在什么位置,甚至一个剧本怎么写以及它的作用,我脑海中有一大堆(到目前为止)悬而未决的问题。
|
||||
|
||||
因此,不不需要进一步描述我的困难的情况下,以下是我发现的东西以及促使我继续前进的东西。
|
||||
|
||||
### 配置
|
||||
|
||||
Ansible 的配置文件保存在 `/etc/ansible` 中,这很有道理,因为 `/etc/` 是系统程序应该保存配置文件的地方。我需要使用的两个文件是 `ansible.cfg` 和 `hosts`。
|
||||
|
||||
#### ansible.cfg
|
||||
|
||||
在进行了从文档和线上找到的一些实践练习之后,我遇到了一些有关弃用某些较旧的 Python 文件的警告信息。因此,我在 `ansible.cfg` 中将 `deprecation_warnings` 设置为 `false`,这样那些愤怒的红色警告消息就不会出现了:
|
||||
|
||||
```
|
||||
deprecation_warnings = False
|
||||
```
|
||||
|
||||
这些警告很重要,所以我稍后将重新回顾它们,并弄清楚我需要做什么。但是现在,它们不会再扰乱屏幕,也不会让我混淆实际上需要关注的错误。
|
||||
|
||||
#### hosts 文件
|
||||
|
||||
与 `/etc/hosts` 文件不同,`hosts` 文件也被称为<ruby>清单<rt>inventory</rt></ruby>文件,它列出了网络上的主机。此文件允许将主机分组到相关集合中,例如“servers”、“workstations”和任何你所需的名称。这个文件包含帮助和大量示例,所以我在这里就不详细介绍了。但是,有些事情你必须知道。
|
||||
|
||||
主机也可以列在组之外,但是组对于识别具有一个或多个共同特征的主机很有帮助。组使用 INI 格式,所以服务器组看起来像这样:
|
||||
|
||||
```
|
||||
[servers]
|
||||
server1
|
||||
server2
|
||||
......
|
||||
```
|
||||
|
||||
这个文件中必须有一个主机名,这样 Ansible 才能对它进行操作。即使有些子命令允许指定主机名,但除非主机名在 `hosts` 文件中,否则命令会失败。一个主机也可以放在多个组中。因此,除了 `[servers]` 组之外,`server1` 也可能是 `[webservers]` 组的成员,还可以是 `[ubuntu]` 组的成员,这样以区别于 Fedora 服务器。
|
||||
|
||||
Ansible 很智能。如果 `all` 参数用作主机名,Ansible 会扫描 `hosts` 文件并在它列出的所有主机上执行定义的任务。Ansible 只会尝试在每个主机上工作一次,不管它出现在多少个组中。这也意味着不需要定义 `all` 组,因为 Ansible 可以确定文件中的所有主机名,并创建自己唯一的主机名列表。
|
||||
|
||||
另一件需要注意的事情是单个主机的多个条目。我在 DNS 文件中使用 `CNAME` 记录来创建别名,这些别名指向某些主机的 [A 记录][5],这样,我可以将一个主机称为 `host1` 或 `h1` 或 `myhost`。如果你在 `hosts` 文件中为同一主机指定多个主机名,则 Ansible 将尝试在所有这些主机名上执行其任务,它无法知道它们指向同一主机。好消息是,这并不会影响整体结果;它只是多花了一点时间,因为 Ansible 会在次要主机名上工作,它会确定所有操作均已执行。
|
||||
|
||||
### Ansible 实情
|
||||
|
||||
我阅读过 Ansible 的大多数材料都谈到了 Ansible <ruby>[实情][6]<rt>facts</rt></ruby>,它是与远程系统相关的数据,包括操作系统、IP 地址、文件系统等等。这些信息可以通过其它方式获得,如 `lshw`、`dmidecode` 或 `/proc` 文件系统等。但是 Ansible 会生成一个包含此信息的 JSON 文件。每次 Ansible 运行时,它都会生成这些实情数据。在这个数据流中,有大量的信息,都是以键值对形式出现的:`<"variable-name": "value">`。所有这些变量都可以在 Ansible 剧本中使用,理解大量可用信息的最好方法是实际显示一下:
|
||||
|
||||
```
|
||||
# ansible -m setup <hostname> | less
|
||||
```
|
||||
|
||||
明白了吗?你想知道的有关主机硬件和 Linux 发行版的所有内容都在这里,它们都可以在剧本中使用。我还没有达到需要使用这些变量的地步,但是我相信在接下来的几天中会用到。
|
||||
|
||||
### 模块
|
||||
|
||||
上面的 `ansible` 命令使用 `-m` 选项来指定 `setup` 模块。Ansible 已经内置了许多模块,所以你对这些模块不需要使用 `-m`。也可以安装许多下载的模块,但是内置模块可以完成我目前项目所需的一切。
|
||||
|
||||
### 剧本
|
||||
|
||||
<ruby>剧本<rt>playbook</rt></ruby>几乎可以放在任何地方。因为我需要以 root 身份运行,所以我将它放在了 `/root/ansible` 下。当我运行 Ansible 时,只要这个目录是当前的工作目录(PWD),它就可以找到我的剧本。Ansible 还有一个选项,用于在运行时指定不同的剧本和位置。
|
||||
|
||||
剧本可以包含注释,但是我看到的文章或书籍很少提及此。但作为一个相信记录一切的系统管理员,我发现使用注释很有帮助。这并不是说在注释中做和任务名称同样的事情,而是要确定任务组的目的,并确保我以某种方式或顺序记录我做这些事情的原因。当我可能忘记最初的想法时,这可以帮助以后解决调试问题。
|
||||
|
||||
剧本只是定义主机所需状态的任务集合。在剧本的开头指定主机名或清单组,并定义 Ansible 将在其上运行剧本的主机。
|
||||
|
||||
以下是我的一个剧本示例:
|
||||
|
||||
```
|
||||
################################################################################
|
||||
# This Ansible playbook updates Midnight commander configuration files. #
|
||||
################################################################################
|
||||
- name: Update midnight commander configuration files
|
||||
hosts: all
|
||||
|
||||
tasks:
|
||||
- name: ensure midnight commander is the latest version
|
||||
dnf:
|
||||
name: mc
|
||||
state: present
|
||||
|
||||
- name: create ~/.config/mc directory for root
|
||||
file:
|
||||
path: /root/.config/mc
|
||||
state: directory
|
||||
mode: 0755
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: create ~/.config/mc directory for dboth
|
||||
file:
|
||||
path: /home/dboth/.config/mc
|
||||
state: directory
|
||||
mode: 0755
|
||||
owner: dboth
|
||||
group: dboth
|
||||
|
||||
- name: copy latest personal skin
|
||||
copy:
|
||||
src: /root/ansible/UpdateMC/files/MidnightCommander/DavidsGoTar.ini
|
||||
dest: /usr/share/mc/skins/DavidsGoTar.ini
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: copy latest mc ini file
|
||||
copy:
|
||||
src: /root/ansible/UpdateMC/files/MidnightCommander/ini
|
||||
dest: /root/.config/mc/ini
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: copy latest mc panels.ini file
|
||||
copy:
|
||||
src: /root/ansible/UpdateMC/files/MidnightCommander/panels.ini
|
||||
dest: /root/.config/mc/panels.ini
|
||||
mode: 0644
|
||||
owner: root
|
||||
group: root
|
||||
<截断>
|
||||
```
|
||||
|
||||
剧本从它自己的名字和它将要操作的主机开始,在本文中,所有主机都在我的 `hosts` 文件中。`tasks` 部分列出了使主机达到所需状态的特定任务。这个剧本从使用 DNF 更新 Midnight Commander 开始(如果它不是最新的版本的话)。下一个任务确保创建所需的目录(如果它们不存在),其余任务将文件复制到合适的位置,这些 `file` 和 `copy` 任务还可以为目录和文件设置所有权和文件模式。
|
||||
|
||||
剧本细节超出了本文的范围,但是我对这个问题使用了一点蛮力。还有其它方法可以确定哪些用户需要更新文件,而不是对每个用户的每个文件使用一个任务。我的下一个目标是简化这个剧本,使用一些更先进的技术。
|
||||
|
||||
运行剧本很容易,只需要使用 `ansible-playbook` 命令。`.yml` 扩展名代表 YAML,我看到过它的几种不同含义,但我认为它是“<ruby>另一种标记语言<rt>Yet Another Markup Language</rt></ruby>”,尽管有些人声称 YAML 不是这种语言。
|
||||
|
||||
这个命令将会运行剧本,它会更新 Midnight Commander 文件:
|
||||
|
||||
```
|
||||
# ansible-playbook -f 10 UpdateMC.yml
|
||||
```
|
||||
|
||||
`-f` 选项指定 Ansible 使用 10 个线程来执行操作。这可以大大加快整个任务的完成速度,特别是在多台主机上工作时。
|
||||
|
||||
### 输出
|
||||
|
||||
剧本运行时会列出每个任务和执行结果。`ok` 代表任务管理的机器状态已经完成,因为在任务中定义的状态已经为真,所以 Ansible 不需要执行任何操作。
|
||||
|
||||
`changed` 表示 Ansible 已经执行了指定的任务。在这种情况下,任务中定义的机器状态不为真,所以执行指定的操作使其为真。在彩色终端上,`TASK` 行会以彩色显示。我的终端配色为“amber-on-black”,`TASK` 行显示为琥珀色,`changed` 是棕色,`ok` 为绿色,错误是红色。
|
||||
|
||||
下面的输出是我最终用于在新主机执行安装后配置的剧本:
|
||||
|
||||
```
|
||||
PLAY [Post-installation updates, package installation, and configuration]
|
||||
|
||||
TASK [Gathering Facts]
|
||||
ok: [testvm2]
|
||||
|
||||
TASK [Ensure we have connectivity]
|
||||
ok: [testvm2]
|
||||
|
||||
TASK [Install all current updates]
|
||||
changed: [testvm2]
|
||||
|
||||
TASK [Install a few command line tools]
|
||||
changed: [testvm2]
|
||||
|
||||
TASK [copy latest personal Midnight Commander skin to /usr/share]
|
||||
changed: [testvm2]
|
||||
|
||||
TASK [create ~/.config/mc directory for root]
|
||||
changed: [testvm2]
|
||||
|
||||
TASK [Copy the most current Midnight Commander configuration files to /root/.config/mc]
|
||||
changed: [testvm2] => (item=/root/ansible/PostInstallMain/files/MidnightCommander/DavidsGoTar.ini)
|
||||
changed: [testvm2] => (item=/root/ansible/PostInstallMain/files/MidnightCommander/ini)
|
||||
changed: [testvm2] => (item=/root/ansible/PostInstallMain/files/MidnightCommander/panels.ini)
|
||||
|
||||
TASK [create ~/.config/mc directory in /etc/skel]
|
||||
changed: [testvm2]
|
||||
|
||||
<截断>
|
||||
```
|
||||
|
||||
### cowsay
|
||||
|
||||
如果你的计算机上安装了 [cowsay][7] 程序,你会发现 `TASK` 的名字出现在奶牛的语音泡泡中:
|
||||
|
||||
```
|
||||
____________________________________
|
||||
< TASK [Ensure we have connectivity] >
|
||||
------------------------------------
|
||||
\ ^__^
|
||||
\ (oo)\\_______
|
||||
(__)\ )\/\
|
||||
||----w |
|
||||
|| ||
|
||||
```
|
||||
|
||||
如果你没有这个有趣的程序,你可以使用发行版的包管理器安装 Cowsay 程序。如果你有这个程序但不想要它,可以通过在 `/etc/ansible/ansible.cfg` 文件中设置 `nocows=1` 将其禁用。
|
||||
|
||||
我喜欢这头奶牛,它很有趣,但是它会占用我的一部分屏幕。因此,在它开始妨碍我使用时,我就把它禁用了。
|
||||
|
||||
### 目录
|
||||
|
||||
与我的 Midnight Commander 任务一样,经常需要安装和维护各种类型的文件。创建用于存储剧本的目录树的“最佳实践”和系统管理员一样多,至少与编写有关 Ansible 书和文章的作者数量一样多。
|
||||
|
||||
我选择了一个对我有意义的简单结构:
|
||||
|
||||
```bash
|
||||
/root/ansible
|
||||
└── UpdateMC
|
||||
├── files
|
||||
│ └── MidnightCommander
|
||||
│ ├── DavidsGoTar.ini
|
||||
│ ├── ini
|
||||
│ └── panels.ini
|
||||
└── UpdateMC.yml
|
||||
```
|
||||
|
||||
你可以使用任何结构。但是请注意,其它系统管理员可能需要使用你设置的剧本来工作,所以目录应该具有一定程度的逻辑。当我使用 RPM 和 Bash 脚本执行安装任务后,我的文件仓库有点分散,绝对没有任何逻辑结构。当我为许多管理任务创建剧本时,我将介绍一个更有逻辑的结构来管理我的目录。
|
||||
|
||||
### 多次运行剧本
|
||||
|
||||
根据需要或期望多次运行剧本是安全的。只有当主机状态与任务中指定的状态不匹配时,才会执行每个任务。这使得很容易从先前的剧本运行中遇到的错误中恢复。因为当剧本遇到错误时,它将停止运行。
|
||||
|
||||
在测试我的第一个剧本时,我犯了很多错误并改正了它们。假设我的修正正确,那么剧本每次运行,都会跳过那些状态已与指定状态匹配的任务,执行不匹配状态的任务。当我的修复程序起作用时,之前失败的任务就会成功完成,并且会执行此任务之后的任务 —— 直到遇到另一个错误。
|
||||
|
||||
这使得测试变得容易。我可以添加新任务,并且在运行剧本时,只有新任务会被执行,因为它们是唯一与测试主机期望状态不匹配的任务。
|
||||
|
||||
### 一些思考
|
||||
|
||||
有些任务不适合用 Ansible,因为有更好的方法可以实现特定的计算机状态。我想到的场景是使 VM 返回到初始状态,以便可以多次使用它来执行从已知状态开始的测试。让 VM 进入特定状态,然后对此时的计算机状态进行快照要容易得多。还原到该快照与 Ansible 将主机返回到之前状态相比,通常还原到快照通常会更容易且更快。在研究文章或测试新代码时,我每天都会做几次这样的事情。
|
||||
|
||||
在完成用于更新 Midnight Commander 的剧本之后,我创建了一个新的剧本,用于在新安装的 Fedora 主机上执行安装任务。我已经取得了不错的进步,剧本比我第一个的更加复杂,但没有那么粗暴。
|
||||
|
||||
在使用 Ansible 的第一天,我创建了一个解决问题的剧本,我还开始编写第二个剧本,它将解决安装后配置的大问题,在这个过程中我学到了很多东西。
|
||||
|
||||
尽管我真的很喜欢使用 [Bash][8] 脚本来管理任务,但是我发现 Ansible 可以完成我想要的一切,并且可以使系统保持在我所需的状态。只用了一天,我就成为了 Ansible 的粉丝。
|
||||
|
||||
### 资源
|
||||
|
||||
我找到的最完整、最有用的参考文档是 Ansible 网站上的[用户指南][9]。本文仅供参考,不作为入门文档。
|
||||
|
||||
多年来,我们已经发布了许多[有关 Ansible 的文章][10],我发现其中大多数对我的需求很有帮助。Enable Sysadmin 网站上也有很多对我有帮助 [Ansible 文章][11]。你可以通过查看本周(2020 年 10 月 13 日至 14 日)的 [AnsibleFest][12] 了解更多信息。该活动完全是线上的,可以免费注册。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/10/first-day-ansible
|
||||
|
||||
作者:[David Both][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dboth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_linux11x_cc.png?itok=XMDOouJR "People work on a computer server with devices"
|
||||
[2]: https://www.ansible.com/
|
||||
[3]: https://www.python.org/
|
||||
[4]: https://midnight-commander.org/
|
||||
[5]: https://en.wikipedia.org/wiki/List_of_DNS_record_types
|
||||
[6]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_vars_facts.html#ansible-facts
|
||||
[7]: https://en.wikipedia.org/wiki/Cowsay
|
||||
[8]: https://opensource.com/downloads/bash-cheat-sheet
|
||||
[9]: https://docs.ansible.com/ansible/latest/user_guide/index.html
|
||||
[10]: https://opensource.com/tags/ansible
|
||||
[11]: https://www.redhat.com/sysadmin/topics/ansible
|
||||
[12]: https://www.ansible.com/ansiblefest
|
@ -0,0 +1,93 @@
|
||||
GCC:优化 Linux、互联网和一切
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/22/122155ujfd62u6zbx3i4b3.jpg)
|
||||
|
||||
软件如果不能被电脑运行,那么它就是无用的。而在处理<ruby>运行时<rt>run-time</rt></ruby>性能的问题上,即使是最有才华的开发人员也会受编译器的支配 —— 因为如果没有可靠的编译器工具链,就无法构建任何重要的东西。<ruby>GNU 编译器集合<rt>GNU Compiler Collection</rt></ruby>(GCC)提供了一个健壮、成熟和高性能的工具,以帮助你充分发挥你代码的潜能。经过数十年成千上万人的开发,GCC 成为了世界上最受尊敬的编译器之一。如果你在构建应用程序是没有使用 GCC,那么你可能错过了最佳解决方案。
|
||||
|
||||
根据 LLVM.org 的说法,GCC 是“如今事实上的标准开源编译器” [^1],也是用来构建完整系统的基础 —— 从内核开始。GCC 支持超过 60 种硬件平台,包括 ARM、Intel、AMD、IBM POWER、SPARC、HP PA-RISC 和 IBM Z,以及各种操作环境,包括 GNU、Linux、Windows、macOS、FreeBSD、NetBSD、OpenBSD、DragonFly BSD、Solaris、AIX、HP-UX 和 RTEMS。它提供了高度兼容的 C/C++ 编译器,并支持流行的 C 库,如 GNU C Library(glibc)、Newlib、musl 和各种 BSD 操作系统中包含的 C 库,以及 Fortran、Ada 和 GO 语言的前端。GCC 还可以作为一个交叉编译器,可以为运行编译器的平台以外的其他平台创建可执行代码。GCC 是紧密集成的 GNU 工具链的核心组件,由 GNU 项目产生,它包括 glibc、Binutils 和 GNU 调试器(GDB)。
|
||||
|
||||
“一直以来我最喜欢的 GNU 工具是 GCC,即<ruby>GNU 编译器集合<rt>GNU Compiler Collection</rt></ruby>。在开发工具非常昂贵的时候,GCC 是第二个 GNU 工具,也是使社区能够编写和构建所有其他工具的工具。这个工具一手改变了这个行业,导致了自由软件运动的诞生,因为一个好的、自由的编译器是一个社区软件的先决条件。”—— Red Hat 开源和标准团队的 Dave Neary。[^2]
|
||||
|
||||
### 优化 Linux
|
||||
|
||||
作为 Linux 内核源代码的默认编译器,GCC 提供了可靠、稳定的性能以及正确构建内核所需的额外扩展。GCC 是流行的 Linux 发行版的标准组件,如 ArchLinux、CentOS、Debian、Fedora、openSUSE 和 Ubuntu 这些发行版中,GCC 通常用来编译支持系统的组件。这包括 Linux 使用的默认库(如 libc、libm、libintl、libssh、libssl、libcrypto、libexpat、libpthread 和 ncurses),这些库依赖于 GCC 来提供可靠性和高性能,并且使应用程序和系统程序可以访问 Linux 内核功能。发行版中包含的许多应用程序包也是用 GCC 构建的,例如 Python、Perl、Ruby、nginx、Apache HTTP 服务器、OpenStack、Docker 和 OpenShift。各个 Linux 发行版使用 GCC 构建的大量代码组成了内核、库和应用程序软件。对于 openSUSE 发行版,几乎 100% 的原生代码都是由 GCC 构建的,包括 6135 个源程序包、5705 个共享库和 38927 个可执行文件。这相当于每周编译 24540 个源代码包。[^3]
|
||||
|
||||
Linux 发行版中包含的 GCC 的基本版本用于创建定义系统<ruby>应用程序二进制接口<rt>Application Binary Interface</rt></ruby>(ABI)的内核和库。<ruby>用户空间<rt>User space</rt></ruby>开发者可以选择下载 GCC 的最新稳定版本,以获得高级功能、性能优化和可用性改进。Linux 发行版提供安装说明或预构建的工具链,用于部署最新版本的 GCC 以及其他 GNU 工具,这些工具有助于提高开发人员的工作效率和缩短部署时间。
|
||||
|
||||
### 优化互联网
|
||||
|
||||
GCC 是嵌入式系统中被广泛采用的核心编译器之一,支持为日益增长的物联网设备开发软件。GCC 提供了许多扩展功能,使其非常适合嵌入式系统软件开发,包括使用编译器的内建函数、#语法、内联汇编和以应用程序为中心的命令行选项进行精细控制。GCC 支持广泛的嵌入式体系结构,包括 ARM、AMCC、AVR、Blackfin、MIPS、RISC-V、Renesas Electronics V850、NXP 和 Freescale Power 处理器,可以生成高效、高质量的代码。GCC提供的交叉编译能力对这个社区至关重要,而预制的交叉编译工具链 [^4] 是一个主要需求。例如,GNU ARM 嵌入式工具链是经过集成和验证的软件包,其中包含 ARM 嵌入式 GCC 编译器、库和其它裸机软件开发所需的工具。这些工具链可用于在 Windows、Linux 和 macOS 主机操作系统上对流行的 ARM Cortex-R 和 Cortex-M 处理器进行交叉编译,这些处理器已装载于数百亿台支持互联网的设备中。[^5]
|
||||
|
||||
GCC 为云计算赋能,为需要直接管理计算资源的软件提供了可靠的开发平台,如数据库和 Web 服务引擎以及备份和安全软件。GCC 完全兼容 C++ 11 和 C++ 14,为 C++ 17 和 C++ 2a 提供实验支持 [^6](LCTT 译注:本文原文发布于 2018 年),可以创建性能优异的对象代码,并提供可靠的调试信息。使用 GCC 的应用程序的一些例子包括:MySQL 数据库管理系统,它需要 Linux 的 GCC [^7];Apache HTTP 服务器,它建议使用 GCC [^8];Bacula,一个企业级网络备份工具,它需要 GCC。[^9]
|
||||
|
||||
### 优化一切
|
||||
|
||||
对于<ruby>高性能计算<rt>High Performance Computing</rt></ruby>(HPC)中使用的科学代码的研究和开发,GCC 提供了成熟的 C、C++ 和 Fortran 前端,以及对 OpenMP 和 OpenACC API的支持,用于基于指令的并行编程。因为 GCC 提供了跨计算环境的可移植性,它使得代码能够更容易地在各种新的和传统的客户机和服务器平台上进行测试。GCC 为 C、C++ 和 Fortran 编译器提供了 OpenMP 4.0 的完整支持,为 C 和 C++ 编译器提供了 OpenMP 4.5 完整支持。对于 OpenACC、 GCC 支持大部分 2.5 规范和性能优化,并且是唯一提供 [OpenACC][1] 支持的非商业、非学术编译器。
|
||||
|
||||
代码性能是这个社区的一个重要参数,GCC 提供了一个坚实的性能基础。Colfax Research 于 2017 年 11 月发表的一篇论文评估了 C++ 编译器在使用 OpenMP 4.x 指令并行化编译代码的速度和编译后代码的运行速度。图 1 描绘了不同编译器编译并使用单个线程运行时计算内核的相对性能。性能值经过了归一化处理,以 G++ 的性能为 1.0。
|
||||
|
||||
![performance][3]
|
||||
|
||||
*图 1 为由不同编译器编译的每个内核的相对性能。(单线程,越高越好)。*
|
||||
|
||||
他的论文总结道:“GNU 编译器在我们的测试中也做得很好。G++ 在六种情况中的三种情况下生成的代码速度是第二快的,并且在编译时间方面是最快的编译器之一。”[^10]
|
||||
|
||||
### 谁在用 GCC?
|
||||
|
||||
在 JetBrains 2018 年的开发者生态状况调查中,在接受调查的 6000 名开发者中,66% 的 C++ 程序员和 73% 的 C 程序员经常使用 GCC。[^11] 以下简要介绍 GCC 的优点,正是这些优点使它在开发人员社区中如此受欢迎。
|
||||
|
||||
* 对于需要为各种新的和遗留的计算平台和操作环境编写代码的开发人员,GCC 提供了对最广泛的硬件和操作环境的支持。硬件供应商提供的编译器主要侧重于对其产品的支持,而其他开源编译器在所支持的硬件和操作系统方面则受到很大限制。[^12]
|
||||
* 有各种各样的基于 GCC 的预构建工具链,这对嵌入式系统开发人员特别有吸引力。这包括 GNU ARM 嵌入式工具链和 Bootlin 网站上提供的 138 个预编译交叉编译器工具链。[^13] 虽然其他开源编译器(如 Clang/LLVM)可以取代现有交叉编译工具链中的 GCC,但这些工具集需要开发者完全重新构建。[^14]
|
||||
* GCC 通过成熟的编译器平台向应用程序开发人员提供可靠、稳定的性能。《在 AMD EPYC 平台上用 GCC 8/9 与 LLVM Clang 6/7 编译器基准测试》这篇文章提供了 49 个基准测试的结果,这些测试的编译器在三个优化级别上运行。使用 `-O3 -march=native` 级别的 GCC 8.2 RC1 在 34% 的时间里排在第一位,而在相同的优化级别 LLVM Clang 6.0 在 20% 的时间里赢得了第二位。[^15]
|
||||
* GCC 为编译调试 [^16] 提供了改进的诊断方法,并为运行时调试提供了准确而有用的信息。GCC 与 GDB 紧密集成,GDB 是一个成熟且功能齐全的工具,它提供“不间断”调试,可以在断点处停止单个线程。
|
||||
* GCC 是一个得到良好支持的平台,它有一个活跃的、有责任感的社区,支持当前版本和以前的两个版本。由于每年都有发布计划,这为一个版本提供了两年的支持。
|
||||
|
||||
### GCC:仍然在继续优化
|
||||
|
||||
GCC 作为一个世界级的编译器继续向前发展。GCC 的最新版本是 8.2,于 2018 年 7 月发布(LCTT 译注:本文原文发表于 2018 年),增加了对即将推出的 Intel CPU、更多 ARM CPU 的硬件支持,并提高了 AMD 的 ZEN CPU 的性能。增加了对 C17 的初步支持,同时也对 C++2A 进行了初步工作。诊断功能继续得到增强,包括更好的发射诊断,改进了定位、定位范围和修复提示,特别是在 C++ 前端。Red Hat 的 David Malcolm 在 2018 年 3 月撰写的博客概述了 GCC 8 中的可用性改进。[^17]
|
||||
|
||||
新的硬件平台继续依赖 GCC 工具链进行软件开发,例如 RISC-V,这是一种自由开放的 ISA,机器学习、人工智能(AI)和物联网细分市场都对其感兴趣。GCC 仍然是 Linux 系统持续开发的关键组件。针对 Intel 架构的 Clear Linux 项目是一个为云、客户端和物联网用例构建的新兴发行版,它提供了一个很好的示例,说明如何使用和改进 GCC 编译器技术来提高基于 Linux 的系统的性能和安全性。GCC 还被用于微软 Azure Sphere 的应用程序开发,这是一个基于 Linux 的物联网应用程序操作系统,最初支持基于 ARM 的联发科 MT3620 处理器。在培养下一代程序员方面,GCC 也是树莓派的 Windows 工具链的核心组件,树莓派是一种运行基于 Debian 的 GNU/Linux 的低成本嵌入式板,用于促进学校和发展中国家的基础计算机科学教学。
|
||||
|
||||
GCC 由 GNU 项目的创始人<ruby>理查德•斯托曼<rt>Richard Stallman</rt></ruby>首次发布 于 1987 年 3 月 22 日,由于它是第一个作为自由软件发布的可移植的 ANSI C 优化编译器,因此它被认为是一个重大突破。GCC 由来自世界各地的程序员组成的社区在指导委员会的指导下维护,以确保对项目进行广泛的、有代表性的监督。GCC 的社区方法是它的优势之一,它形成了一个由开发人员和用户组成的庞大而多样化的社区,他们为项目做出了贡献并提供支持。根据 Open Hub 的说法,“GCC 是世界上最大的开源团队之一,在 Open Hub 上的所有项目团队中排名前 2%。”[^18]
|
||||
|
||||
关于 GCC 的许可问题,人们进行了大量的讨论,其中大多数是混淆而不是启发。GCC 在 GNU 通用公共许可证(GPL)版本 3 或更高版本下发布,但运行时库例外。这是一个左版许可,这意味着衍生作品只能在相同的许可条款下分发。GPLv3 旨在保护 GCC,防止其成为专有软件,并要求对 GCC 代码的更改可以自由公开地进行。对于“最终用户”来说,这个编译器与其他编译器完全相同;使用 GCC 对你为自己的代码所选择的任何许可都没有区别。[^19]
|
||||
|
||||
[^1]: http://clang.llvm.org/features.html#gcccompat
|
||||
[^2]: https://opensource.com/article/18/9/happy-birthday-gnu
|
||||
[^3]: 由 SUSE 基于最近的构建统计提供的信息。在 openSUSE 中还有其他不生成可执行镜像的源码包,这些不包括在统计中。
|
||||
[^4]: https://community.arm.com/tools/b/blog/posts/gnu-toolchain-performance-in-2018
|
||||
[^5]: https://www.arm.com/products/processors/cortex-m
|
||||
[^6]: https://gcc.gnu.org/projects/cxx-status.html#cxx17
|
||||
[^7]: https://mysqlserverteam.com/mysql-8-0-source-code-improvements/
|
||||
[^8]: http://httpd.apache.org/docs/2.4/install.html
|
||||
[^9]: https://blog.bacula.org/what-is-bacula/system-requirements/
|
||||
[^10]: https://colfaxresearch.com/compiler-comparison/
|
||||
[^11]: https://www.jetbrains.com/research/devecosystem-2018/
|
||||
[^12]: http://releases.llvm.org/6.0.0/tools/clang/docs/UsersManual.html
|
||||
[^13]: https://bootlin.com/blog/free-and-ready-to-use-cross-compilation-toolchains/
|
||||
[^14]: https://clang.llvm.org/docs/Toolchain.html
|
||||
[^15]: https://www.phoronix.com/scan.php?page=article&item=gcclang-epyc-summer18&num=1
|
||||
[^16]: https://gcc.gnu.org/wiki/ClangDiagnosticsComparison
|
||||
[^17]: https://developers.redhat.com/blog/2018/03/15/gcc-8-usability-improvements/
|
||||
[^18]: https://www.openhub.net/p/gcc/factoids#FactoidTeamSizeVeryLarge
|
||||
[^19]: https://www.gnu.org/licenses/gcc-exception-3.1-faq.en.html
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/2018/10/gcc-optimizing-linux-internet-and-everything
|
||||
|
||||
作者:[Margaret Lewis][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/margaret-lewis
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.openacc.org/tools
|
||||
[2]: /files/images/gccjpg-0
|
||||
[3]: https://lcom.static.linuxfound.org/sites/lcom/files/gcc_0.jpg?itok=HbGnRqWX "performance"
|
||||
[4]: https://www.linux.com/licenses/category/used-permission
|
@ -0,0 +1,436 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (stevenzdg988)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13041-1.html)
|
||||
[#]: subject: (Install Apache, MySQL, PHP \(LAMP\) Stack On Ubuntu 18.04 LTS)
|
||||
[#]: via: (https://www.ostechnix.com/install-apache-mysql-php-lamp-stack-on-ubuntu-18-04-lts/)
|
||||
[#]: author: (SK https://www.ostechnix.com/author/sk/)
|
||||
|
||||
在 Ubuntu 中安装 Apache、MySQL、PHP(LAMP)套件
|
||||
======
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2019/02/lamp-720x340.jpg)
|
||||
|
||||
**LAMP** 套件是一种流行的开源 Web 开发平台,可用于运行和部署动态网站和基于 Web 的应用程序。通常,LAMP 套件由 Apache Web 服务器、MariaDB/MySQL 数据库、PHP/Python/Perl 程序设计(脚本)语言组成。 LAMP 是 **L**inux,**M**ariaDB/**M**YSQL,**P**HP/**P**ython/**P**erl 的缩写。 本教程描述了如何在 Ubuntu 18.04 LTS 服务器中安装 Apache、MySQL、PHP(LAMP 套件)。
|
||||
|
||||
就本教程而言,我们将使用以下 Ubuntu 测试。
|
||||
|
||||
* **操作系统**:Ubuntu 18.04.1 LTS Server Edition
|
||||
* **IP 地址** :192.168.225.22/24
|
||||
|
||||
### 1. 安装 Apache Web 服务器
|
||||
|
||||
首先,利用下面命令更新 Ubuntu 服务器:
|
||||
|
||||
```
|
||||
$ sudo apt update
|
||||
$ sudo apt upgrade
|
||||
```
|
||||
|
||||
然后,安装 Apache Web 服务器(命令如下):
|
||||
|
||||
```
|
||||
$ sudo apt install apache2
|
||||
```
|
||||
|
||||
检查 Apache Web 服务器是否已经运行:
|
||||
|
||||
```
|
||||
$ sudo systemctl status apache2
|
||||
```
|
||||
|
||||
输出结果大概是这样的:
|
||||
|
||||
```
|
||||
● apache2.service - The Apache HTTP Server
|
||||
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: en
|
||||
Drop-In: /lib/systemd/system/apache2.service.d
|
||||
└─apache2-systemd.conf
|
||||
Active: active (running) since Tue 2019-02-05 10:48:03 UTC; 1min 5s ago
|
||||
Main PID: 2025 (apache2)
|
||||
Tasks: 55 (limit: 2320)
|
||||
CGroup: /system.slice/apache2.service
|
||||
├─2025 /usr/sbin/apache2 -k start
|
||||
├─2027 /usr/sbin/apache2 -k start
|
||||
└─2028 /usr/sbin/apache2 -k start
|
||||
|
||||
Feb 05 10:48:02 ubuntuserver systemd[1]: Starting The Apache HTTP Server...
|
||||
Feb 05 10:48:03 ubuntuserver apachectl[2003]: AH00558: apache2: Could not reliably
|
||||
Feb 05 10:48:03 ubuntuserver systemd[1]: Started The Apache HTTP Server.
|
||||
```
|
||||
|
||||
祝贺你! Apache 服务已经启动并运行了!!
|
||||
|
||||
#### 1.1 调整防火墙允许 Apache Web 服务器
|
||||
|
||||
默认情况下,如果你已在 Ubuntu 中启用 UFW 防火墙,则无法从远程系统访问 Apache Web 服务器。 必须按照以下步骤开启 `http` 和 `https` 端口。
|
||||
|
||||
首先,使用以下命令列出 Ubuntu 系统上可用的应用程序配置文件:
|
||||
|
||||
```
|
||||
$ sudo ufw app list
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
```
|
||||
Available applications:
|
||||
Apache
|
||||
Apache Full
|
||||
Apache Secure
|
||||
OpenSSH
|
||||
```
|
||||
|
||||
如你所见,Apache 和 OpenSSH 应用程序已安装 UFW 配置文件。你可以使用 `ufw app info "Profile Name"` 命令列出有关每个配置文件及其包含的规则的信息。
|
||||
|
||||
让我们研究一下 “Apache Full” 配置文件。 为此,请运行:
|
||||
|
||||
```
|
||||
$ sudo ufw app info "Apache Full"
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
```
|
||||
Profile: Apache Full
|
||||
Title: Web Server (HTTP,HTTPS)
|
||||
Description: Apache v2 is the next generation of the omnipresent Apache web
|
||||
server.
|
||||
|
||||
Ports:
|
||||
80,443/tcp
|
||||
```
|
||||
|
||||
如你所见,“Apache Full” 配置文件包含了启用经由端口 **80** 和 **443** 的传输规则:
|
||||
|
||||
现在,运行以下命令配置允许 HTTP 和 HTTPS 传入通信:
|
||||
|
||||
```
|
||||
$ sudo ufw allow in "Apache Full"
|
||||
Rules updated
|
||||
Rules updated (v6)
|
||||
```
|
||||
|
||||
如果你不想允许 HTTP 通信,而只允许 HTTP(80) 通信,请运行:
|
||||
|
||||
```
|
||||
$ sudo ufw app info "Apache"
|
||||
```
|
||||
|
||||
#### 1.2 测试 Apache Web 服务器
|
||||
|
||||
现在,打开 Web 浏览器并导航到 <http://localhost/> 或 <http://IP-Address/> 来访问 Apache 测试页。
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2016/06/apache-2.png)
|
||||
|
||||
如果看到上面类似的显示内容,那就成功了。 Apache 服务器正在工作!
|
||||
|
||||
### 2. 安装 MySQL
|
||||
|
||||
在 Ubuntu 安装 MySQL 请运行:
|
||||
|
||||
```
|
||||
$ sudo apt install mysql-server
|
||||
```
|
||||
|
||||
使用以下命令验证 MySQL 服务是否正在运行:
|
||||
|
||||
```
|
||||
$ sudo systemctl status mysql
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
```
|
||||
● mysql.service - MySQL Community Server
|
||||
Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enab
|
||||
Active: active (running) since Tue 2019-02-05 11:07:50 UTC; 17s ago
|
||||
Main PID: 3423 (mysqld)
|
||||
Tasks: 27 (limit: 2320)
|
||||
CGroup: /system.slice/mysql.service
|
||||
└─3423 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid
|
||||
|
||||
Feb 05 11:07:49 ubuntuserver systemd[1]: Starting MySQL Community Server...
|
||||
Feb 05 11:07:50 ubuntuserver systemd[1]: Started MySQL Community Server.
|
||||
```
|
||||
|
||||
MySQL 正在运行!
|
||||
|
||||
#### 2.1 配置数据库管理用户(root)密码
|
||||
|
||||
默认情况下,MySQL root 用户密码为空。你需要通过运行以下脚本使你的 MySQL 服务器安全:
|
||||
|
||||
```
|
||||
$ sudo mysql_secure_installation
|
||||
```
|
||||
|
||||
系统将询问你是否要安装 “VALIDATE PASSWORD plugin(密码验证插件)”。该插件允许用户为数据库配置强密码凭据。如果启用,它将自动检查密码的强度并强制用户设置足够安全的密码。**禁用此插件是安全的**。但是,必须为数据库使用唯一的强密码凭据。如果不想启用此插件,只需按任意键即可跳过密码验证部分,然后继续其余步骤。
|
||||
|
||||
如果回答是 `y`,则会要求你选择密码验证级别。
|
||||
|
||||
```
|
||||
Securing the MySQL server deployment.
|
||||
|
||||
Connecting to MySQL using a blank password.
|
||||
|
||||
VALIDATE PASSWORD PLUGIN can be used to test passwords
|
||||
and improve security. It checks the strength of password
|
||||
and allows the users to set only those passwords which are
|
||||
secure enough. Would you like to setup VALIDATE PASSWORD plugin?
|
||||
|
||||
Press y|Y for Yes, any other key for No y
|
||||
```
|
||||
|
||||
可用的密码验证有 “low(低)”、 “medium(中)” 和 “strong(强)”。只需输入适当的数字(0 表示低,1 表示中,2 表示强密码)并按回车键。
|
||||
|
||||
```
|
||||
There are three levels of password validation policy:
|
||||
|
||||
LOW Length >= 8
|
||||
MEDIUM Length >= 8, numeric, mixed case, and special characters
|
||||
STRONG Length >= 8, numeric, mixed case, special characters and dictionary file
|
||||
|
||||
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG:
|
||||
```
|
||||
|
||||
现在,输入 MySQL root 用户的密码。请注意,必须根据上一步中选择的密码策略,为 MySQL root 用户使用密码。如果你未启用该插件,则只需使用你选择的任意强度且唯一的密码即可。
|
||||
|
||||
```
|
||||
Please set the password for root here.
|
||||
|
||||
New password:
|
||||
|
||||
Re-enter new password:
|
||||
|
||||
Estimated strength of the password: 50
|
||||
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
|
||||
```
|
||||
|
||||
两次输入密码后,你将看到密码强度(在此示例情况下为 50)。如果你确定可以,请按 `y` 继续提供的密码。如果对密码长度不满意,请按其他任意键并设置一个强密码。我现在的密码可以,所以我选择了`y`。
|
||||
|
||||
对于其余的问题,只需键入 `y` 并按回车键。这将删除匿名用户、禁止 root 用户远程登录并删除 `test`(测试)数据库。
|
||||
|
||||
```
|
||||
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
|
||||
Success.
|
||||
|
||||
Normally, root should only be allowed to connect from
|
||||
'localhost'. This ensures that someone cannot guess at
|
||||
the root password from the network.
|
||||
|
||||
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
|
||||
Success.
|
||||
|
||||
By default, MySQL comes with a database named 'test' that
|
||||
anyone can access. This is also intended only for testing,
|
||||
and should be removed before moving into a production
|
||||
environment.
|
||||
|
||||
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
|
||||
- Dropping test database...
|
||||
Success.
|
||||
|
||||
- Removing privileges on test database...
|
||||
Success.
|
||||
|
||||
Reloading the privilege tables will ensure that all changes
|
||||
made so far will take effect immediately.
|
||||
|
||||
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
|
||||
Success.
|
||||
|
||||
All done!
|
||||
```
|
||||
|
||||
以上就是为 MySQL root 用户设置密码。
|
||||
|
||||
#### 2.2 更改 MySQL 超级用户的身份验证方法
|
||||
|
||||
默认情况下,Ubuntu 系统的 MySQL root 用户为 MySQL 5.7 版本及更新的版本使用插件 `auth_socket` 设置身份验证。尽管它增强了安全性,但是当你使用任何外部程序(例如 phpMyAdmin)访问数据库服务器时,也会变得更困难。要解决此问题,你需要将身份验证方法从 `auth_socket` 更改为 `mysql_native_password`。为此,请使用以下命令登录到你的 MySQL 提示符下:
|
||||
|
||||
```
|
||||
$ sudo mysql
|
||||
```
|
||||
|
||||
在 MySQL 提示符下运行以下命令,找到所有 MySQL 当前用户帐户的身份验证方法:
|
||||
|
||||
```
|
||||
SELECT user,authentication_string,plugin,host FROM mysql.user;
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
```
|
||||
+------------------|-------------------------------------------|-----------------------|-----------+
|
||||
| user | authentication_string | plugin | host |
|
||||
+------------------|-------------------------------------------|-----------------------|-----------+
|
||||
| root | | auth_socket | localhost |
|
||||
| mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
|
||||
| mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
|
||||
| debian-sys-maint | *F126737722832701DD3979741508F05FA71E5BA0 | mysql_native_password | localhost |
|
||||
+------------------|-------------------------------------------|-----------------------|-----------+
|
||||
4 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
![][2]
|
||||
|
||||
如你所见,Mysql root 用户使用 `auth_socket` 插件进行身份验证。
|
||||
|
||||
要将此身份验证更改为 `mysql_native_password` 方法,请在 MySQL 提示符下运行以下命令。 别忘了用你选择的强大唯一的密码替换 `password`。 如果已启用 VALIDATION 插件,请确保已根据当前策略要求使用了强密码。
|
||||
|
||||
```
|
||||
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
|
||||
```
|
||||
|
||||
使用以下命令更新数据库:
|
||||
|
||||
```
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
使用命令再次检查身份验证方法是否已更改:
|
||||
|
||||
```
|
||||
SELECT user,authentication_string,plugin,host FROM mysql.user;
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
![][3]
|
||||
|
||||
好!MySQL root 用户就可以使用密码进行身份验证来访问 `mysql shell`。
|
||||
|
||||
从 MySQL 提示符下退出:
|
||||
|
||||
```
|
||||
exit
|
||||
```
|
||||
|
||||
### 3. 安装 PHP
|
||||
|
||||
安装 PHP 请运行:
|
||||
|
||||
```
|
||||
$ sudo apt install php libapache2-mod-php php-mysql
|
||||
```
|
||||
|
||||
安装 PHP 后,在 Apache 文档根目录中创建 `info.php` 文件。通常,在大多数基于 Debian 的 Linux 发行版中,Apache 文档根目录为 `/var/www/html/` 或 `/var/www/`。Ubuntu 18.04 LTS 系统下,文档根目录是 `/var/www/html/`。
|
||||
|
||||
在 Apache 根目录中创建 `info.php` 文件:
|
||||
|
||||
```
|
||||
$ sudo vi /var/www/html/info.php
|
||||
```
|
||||
|
||||
在此文件中编辑如下内容:
|
||||
|
||||
```
|
||||
<?php
|
||||
phpinfo();
|
||||
?>
|
||||
```
|
||||
|
||||
然后按下 `ESC` 键并且输入 `:wq` 保存并退出此文件。重新启动 Apache 服务使更改生效。
|
||||
|
||||
```
|
||||
$ sudo systemctl restart apache2
|
||||
```
|
||||
|
||||
#### 3.1 测试 PHP
|
||||
|
||||
打开 Web 浏览器,然后导航到 URL <http://IP地址/info.php>。
|
||||
|
||||
你就将看到 PHP 测试页面。
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2019/02/php-test-page.png)
|
||||
|
||||
通常,当用户向 Web 服务器发出请求时,Apache 首先会在文档根目录中查找名为 `index.html` 的文件。如果你想将 Apache 更改为 `php` 文件提供服务而不是其他文件,请将 `dir.conf` 配置文件中的 `index.php` 移至第一个位置,如下所示:
|
||||
|
||||
```
|
||||
$ sudo vi /etc/apache2/mods-enabled/dir.conf
|
||||
```
|
||||
|
||||
上面的配置文件(`dir.conf`) 内容如下:
|
||||
|
||||
```
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
|
||||
</IfModule>
|
||||
|
||||
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
|
||||
```
|
||||
|
||||
将 `index.php` 移动到最前面。更改后,`dir.conf` 文件内容看起来如下所示。
|
||||
|
||||
```
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
|
||||
</IfModule>
|
||||
|
||||
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
|
||||
```
|
||||
|
||||
然后按下 `ESC` 键并且输入 `:wq` 保存并关闭此文件。重新启动 Apache 服务使更改生效。
|
||||
|
||||
```
|
||||
$ sudo systemctl restart apache2
|
||||
```
|
||||
|
||||
#### 3.2 安装 PHP 模块
|
||||
|
||||
为了增加 PHP 的功能,可以安装一些其他的 PHP 模块。
|
||||
|
||||
要列出可用的 PHP 模块,请运行:
|
||||
|
||||
```
|
||||
$ sudo apt-cache search php- | less
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
![][4]
|
||||
|
||||
使用方向键浏览结果。要退出,请输入 `q` 并按下回车键。
|
||||
|
||||
要查找任意 `php` 模块的详细信息,例如 `php-gd`,请运行:
|
||||
|
||||
```
|
||||
$ sudo apt-cache show php-gd
|
||||
```
|
||||
|
||||
安装 PHP 模块请运行:
|
||||
|
||||
```
|
||||
$ sudo apt install php-gd
|
||||
```
|
||||
|
||||
安装所有的模块(虽然没有必要),请运行:
|
||||
|
||||
```
|
||||
$ sudo apt-get install php*
|
||||
```
|
||||
|
||||
安装任何 `php` 模块后,请不要忘记重新启动 Apache 服务。要检查模块是否已加载,请在浏览器中打开 `info.php` 文件并检查是否存在。
|
||||
|
||||
接下来,你可能需要安装数据库管理工具,以通过 Web 浏览器轻松管理数据库。如果是这样,请按照以下链接中的说明安装 `phpMyAdmin`。
|
||||
|
||||
祝贺你!我们已经在 Ubuntu 服务器中成功配置了 LAMP 套件。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/install-apache-mysql-php-lamp-stack-on-ubuntu-18-04-lts/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[stevenzdg988](https://github.com/stevenzdg988)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[2]: http://www.ostechnix.com/wp-content/uploads/2019/02/mysql-1.png
|
||||
[3]: http://www.ostechnix.com/wp-content/uploads/2019/02/mysql-2.png
|
||||
[4]: http://www.ostechnix.com/wp-content/uploads/2016/06/php-modules.png
|
@ -0,0 +1,261 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (stevenzdg988)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13052-1.html)
|
||||
[#]: subject: (Make websites more readable with a shell script)
|
||||
[#]: via: (https://opensource.com/article/19/2/make-websites-more-readable-shell-script)
|
||||
[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
|
||||
|
||||
利用 Shell 脚本让网站更具可读性
|
||||
======
|
||||
|
||||
> 测算网站的文本和背景之间的对比度,以确保站点易于阅读。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/25/231152ce5ufhjtufxj1eeu.jpg)
|
||||
|
||||
如果希望人们发现你的网站实用,那么他们需要能够阅读它。为文本选择的颜色可能会影响网站的可读性。不幸的是,网页设计中的一种流行趋势是在打印输出文本时使用低对比度的颜色,就像在白色背景上的灰色文本。对于 Web 设计师来说,这也许看起来很酷,但对于许多阅读它的人来说确实很困难。
|
||||
|
||||
W3C 提供了《<ruby>Web 内容可访问性指南<rt>Web Content Accessibility Guidelines</rt></ruby>》,其中包括帮助 Web 设计人员选择易于区分文本和背景色的指导。z这就是所谓的“<ruby>对比度<rt>contrast ratio</rt></ruby>”。 W3C 定义的对比度需要进行一些计算:给定两种颜色,首先计算每种颜色的相对亮度,然后计算对比度。对比度在 1 到 21 的范围内(通常写为 1:1 到 21:1)。对比度越高,文本在背景下的突出程度就越高。例如,白色背景上的黑色文本非常醒目,对比度为 21:1。对比度为 1:1 的白色背景上的白色文本不可读。
|
||||
|
||||
[W3C 说,正文][1] 的对比度至少应为 4.5:1,标题至少应为 3:1。但这似乎是最低限度的要求。W3C 还建议正文至少 7:1,标题至少 4.5:1。
|
||||
|
||||
计算对比度可能比较麻烦,因此最好将其自动化。我已经用这个方便的 Bash 脚本做到了这一点。通常,脚本执行以下操作:
|
||||
|
||||
1. 获取文本颜色和背景颜色
|
||||
2. 计算相对亮度
|
||||
3. 计算对比度
|
||||
|
||||
### 获取颜色
|
||||
|
||||
你可能知道显示器上的每种颜色都可以用红色、绿色和蓝色(R、G 和 B)来表示。要计算颜色的相对亮度,脚本需要知道颜色的红、绿和蓝的各个分量。理想情况下,脚本会将这些信息读取为单独的 R、G 和 B 值。 Web 设计人员可能知道他们喜欢的颜色的特定 RGB 代码,但是大多数人不知道不同颜色的 RGB 值。作为一种替代的方法是,大多数人通过 “red” 或 “gold” 或 “maroon” 之类的名称来引用颜色。
|
||||
|
||||
幸运的是,GNOME 的 [Zenity][2] 工具有一个颜色选择器应用程序,可让你使用不同的方法选择颜色,然后用可预测的格式 `rgb(R,G,B)` 返回 RGB 值。使用 Zenity 可以轻松获得颜色值:
|
||||
|
||||
```
|
||||
color=$( zenity --title 'Set text color' --color-selection --color='black' )
|
||||
```
|
||||
|
||||
如果用户(意外地)单击 “Cancel(取消)” 按钮,脚本将假定一种颜色:
|
||||
|
||||
```
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo '** color canceled .. assume black'
|
||||
color='rgb(0,0,0)'
|
||||
fi
|
||||
```
|
||||
|
||||
脚本对背景颜色值也执行了类似的操作,将其设置为 `$background`。
|
||||
|
||||
### 计算相对亮度
|
||||
|
||||
一旦你在 `$color` 中设置了前景色,并在 `$background` 中设置了背景色,下一步就是计算每种颜色的相对亮度。 [W3C 提供了一个算法][3] 用以计算颜色的相对亮度。
|
||||
|
||||
> 对于 sRGB 色彩空间,一种颜色的相对亮度定义为:
|
||||
>
|
||||
> L = 0.2126 * R + 0.7152 * G + 0.0722 * B
|
||||
>
|
||||
> R、G 和 B 定义为:
|
||||
>
|
||||
> if $R_{sRGB}$ <= 0.03928 then R = $R_{sRGB}$/12.92
|
||||
>
|
||||
> else R = (($R_{sRGB}$+0.055)/1.055) $^{2.4}$
|
||||
>
|
||||
> if $G_{sRGB}$ <= 0.03928 then G = $G_{sRGB}$/12.92
|
||||
>
|
||||
> else G = (($G_{sRGB}$+0.055)/1.055) $^{2.4}$
|
||||
>
|
||||
> if $B_{sRGB}$ <= 0.03928 then B = $B_{sRGB}$/12.92
|
||||
>
|
||||
> else B = (($B_{sRGB}$+0.055)/1.055) $^{2.4}$
|
||||
>
|
||||
> $R_{sRGB}$、$G_{sRGB}$ 和 $B_{sRGB}$ 定义为:
|
||||
>
|
||||
> $R_{sRGB}$ = $R_{8bit}$/255
|
||||
>
|
||||
> $G_{sRGB}$ = $G_{8bit}$/255
|
||||
>
|
||||
> $B_{sRGB}$ = $B_{8bit}$/255
|
||||
|
||||
由于 Zenity 以 `rgb(R,G,B)` 的格式返回颜色值,因此脚本可以轻松拉取分隔开的 R、B 和 G 的值以计算相对亮度。AWK 可以使用逗号作为字段分隔符(`-F,`),并使用 `substr()` 字符串函数从 `rgb(R,G,B)` 中提取所要的颜色值:
|
||||
|
||||
```
|
||||
R=$( echo $color | awk -F, '{print substr($1,5)}' )
|
||||
G=$( echo $color | awk -F, '{print $2}' )
|
||||
B=$( echo $color | awk -F, '{n=length($3); print substr($3,1,n-1)}' )
|
||||
```
|
||||
|
||||
*有关使用 AWK 提取和显示数据的更多信息,[查看 AWK 备忘表][4]*
|
||||
|
||||
最好使用 BC 计算器来计算最终的相对亮度。BC 支持计算中所需的简单 `if-then-else`,这使得这一过程变得简单。但是由于 BC 无法使用非整数指数直接计算乘幂,因此需要使用自然对数替代它做一些额外的数学运算:
|
||||
|
||||
```
|
||||
echo "scale=4
|
||||
rsrgb=$R/255
|
||||
gsrgb=$G/255
|
||||
bsrgb=$B/255
|
||||
if ( rsrgb <= 0.03928 ) r = rsrgb/12.92 else r = e( 2.4 * l((rsrgb+0.055)/1.055) )
|
||||
if ( gsrgb <= 0.03928 ) g = gsrgb/12.92 else g = e( 2.4 * l((gsrgb+0.055)/1.055) )
|
||||
if ( bsrgb <= 0.03928 ) b = bsrgb/12.92 else b = e( 2.4 * l((bsrgb+0.055)/1.055) )
|
||||
0.2126 * r + 0.7152 * g + 0.0722 * b" | bc -l
|
||||
```
|
||||
|
||||
这会将一些指令传递给 BC,包括作为相对亮度公式一部分的 `if-then-else` 语句。接下来 BC 打印出最终值。
|
||||
|
||||
### 计算对比度
|
||||
|
||||
利用文本颜色和背景颜色的相对亮度,脚本就可以计算对比度了。 [W3C 确定对比度][5] 是使用以下公式:
|
||||
|
||||
> (L1 + 0.05) / (L2 + 0.05),这里的
|
||||
> L1 是颜色较浅的相对亮度,
|
||||
> L2 是颜色较深的相对亮度。
|
||||
|
||||
给定两个相对亮度值 `$r1` 和 `$r2`,使用 BC 计算器很容易计算对比度:
|
||||
|
||||
```
|
||||
echo "scale=2
|
||||
if ( $r1 > $r2 ) { l1=$r1; l2=$r2 } else { l1=$r2; l2=$r1 }
|
||||
(l1 + 0.05) / (l2 + 0.05)" | bc
|
||||
```
|
||||
|
||||
使用 `if-then-else` 语句确定哪个值(`$r1` 或 `$r2`)是较浅还是较深的颜色。BC 执行结果计算并打印结果,脚本可以将其存储在变量中。
|
||||
|
||||
### 最终脚本
|
||||
|
||||
通过以上内容,我们可以将所有内容整合到一个最终脚本。 我使用 Zenity 在文本框中显示最终结果:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
# script to calculate contrast ratio of colors
|
||||
|
||||
# read color and background color:
|
||||
# zenity returns values like 'rgb(255,140,0)' and 'rgb(255,255,255)'
|
||||
|
||||
color=$( zenity --title 'Set text color' --color-selection --color='black' )
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo '** color canceled .. assume black'
|
||||
color='rgb(0,0,0)'
|
||||
fi
|
||||
|
||||
background=$( zenity --title 'Set background color' --color-selection --color='white' )
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo '** background canceled .. assume white'
|
||||
background='rgb(255,255,255)'
|
||||
fi
|
||||
|
||||
# compute relative luminance:
|
||||
|
||||
function luminance()
|
||||
{
|
||||
R=$( echo $1 | awk -F, '{print substr($1,5)}' )
|
||||
G=$( echo $1 | awk -F, '{print $2}' )
|
||||
B=$( echo $1 | awk -F, '{n=length($3); print substr($3,1,n-1)}' )
|
||||
|
||||
echo "scale=4
|
||||
rsrgb=$R/255
|
||||
gsrgb=$G/255
|
||||
bsrgb=$B/255
|
||||
if ( rsrgb <= 0.03928 ) r = rsrgb/12.92 else r = e( 2.4 * l((rsrgb+0.055)/1.055) )
|
||||
if ( gsrgb <= 0.03928 ) g = gsrgb/12.92 else g = e( 2.4 * l((gsrgb+0.055)/1.055) )
|
||||
if ( bsrgb <= 0.03928 ) b = bsrgb/12.92 else b = e( 2.4 * l((bsrgb+0.055)/1.055) )
|
||||
0.2126 * r + 0.7152 * g + 0.0722 * b" | bc -l
|
||||
}
|
||||
|
||||
lum1=$( luminance $color )
|
||||
lum2=$( luminance $background )
|
||||
|
||||
# compute contrast
|
||||
|
||||
function contrast()
|
||||
{
|
||||
echo "scale=2
|
||||
if ( $1 > $2 ) { l1=$1; l2=$2 } else { l1=$2; l2=$1 }
|
||||
(l1 + 0.05) / (l2 + 0.05)" | bc
|
||||
}
|
||||
|
||||
rel=$( contrast $lum1 $lum2 )
|
||||
|
||||
# print results
|
||||
|
||||
( cat<<EOF
|
||||
Color is $color on $background
|
||||
|
||||
Contrast ratio is $rel
|
||||
Contrast ratios can range from 1 to 21 (commonly written 1:1 to 21:1).
|
||||
|
||||
EOF
|
||||
|
||||
if [ ${rel%.*} -ge 4 ] ; then
|
||||
echo "Ok for body text"
|
||||
else
|
||||
echo "Not good for body text"
|
||||
fi
|
||||
if [ ${rel%.*} -ge 3 ] ; then
|
||||
echo "Ok for title text"
|
||||
else
|
||||
echo "Not good for title text"
|
||||
fi
|
||||
|
||||
cat<<EOF
|
||||
|
||||
W3C 说明:
|
||||
|
||||
1.4.3 对比度(最小值):文本和文本图像的视觉呈现方式的对比度至少为 4.5:1,但以下情况除外:(AA 级)
|
||||
|
||||
大文本:大文本和大文本图像的对比度至少为 3:1;
|
||||
|
||||
附带说明:作为非活动用户界面组件一部分,纯装饰的,任何人都不可见或图片的一部分包含特定的其他可视内容的文本或文本图像没有对比度要求。
|
||||
|
||||
小示意图:徽标或商标名称中的文本没有最低对比度要求。
|
||||
|
||||
1.4.6 对比度(增强):文本和文本图像的视觉表示具有至少 7:1 的对比度,但以下情况除外:(AAA 级)
|
||||
|
||||
大文本:大文本和大文本图像的对比度至少为 4.5:1;
|
||||
|
||||
附带说明:作为非活动用户界面组件一部分,纯装饰的,任何人都不可见或图片的一部分包含特定的其他可视内容的文本或文本图像没有对比度要求。
|
||||
|
||||
小示意图:徽标或商标名称中的文本没有最低对比度要求。
|
||||
EOF
|
||||
) | zenity --text-info --title='Relative Luminance' --width=800 --height=600
|
||||
```
|
||||
|
||||
最后,我希望提供有关 W3C 建议的参考信息,以提醒自己。
|
||||
|
||||
Zenity 颜色选择器完成了所有解释颜色的艰苦工作,用户可以通过单击色轮或输入值来选择颜色。 Zenity 接受网站上使用的标准十六进制颜色值,例如 `#000000` 或 `#000`或 `rgb(0,0,0)`(所有这些均为黑色)。这是白色背景上的黑色文本的示例计算:
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/zenity_screenshot1-a.png)
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/zenity_screenshot1-b.png)
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/relativeluminescence1-result.png)
|
||||
|
||||
Zenity 还识别标准的颜色名称,如“cadetblue”、“orange”或“gold”。在Zenity 中输入颜色名称,然后点击 `Tab` 键,Zenity 会将颜色名称转换为十六进制颜色值,如以下示例中对金色背景上的黑色文本的计算:
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/zenity_screenshot2-a-name.png)
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/zenity_screenshot2-a-value.png)
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/zenity_screenshot2-b-name.png)
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/zenity_screenshot2-b-value.png)
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/relativeluminescence2-result.png)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/2/make-websites-more-readable-shell-script
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[stevenzdg988](https://github.com/stevenzdg988)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast
|
||||
[2]: https://wiki.gnome.org/Projects/Zenity
|
||||
[3]: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
|
||||
[4]: https://opensource.com/article/18/7/cheat-sheet-awk
|
||||
[5]: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
|
@ -0,0 +1,391 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (stevenzdg988)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13037-1.html)
|
||||
[#]: subject: (Integrate online documents editors, into a Python web app using ONLYOFFICE)
|
||||
[#]: via: (https://opensourceforu.com/2019/09/integrate-online-documents-editors-into-a-python-web-app-using-onlyoffice/)
|
||||
[#]: author: (Aashima Sharma https://opensourceforu.com/author/aashima-sharma/)
|
||||
|
||||
利用 ONLYOFFICE 将在线文档编辑器集成到 Python Web 应用程序中
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
[ONLYOFFICE][3] 是根据 GNU AGPL v.3 许可证条款分发的开源协作办公套件。它包含三个用于文本文档、电子表格和演示文稿的编辑器,并具有以下功能:
|
||||
|
||||
* 查看,编辑和协同编辑 `.docx`、`.xlsx`、`.pptx` 文件。OOXML 作为一种核心格式,可确保与 Microsoft Word、Excel 和 PowerPoint 文件的高度兼容性。
|
||||
* 通过内部转换为 OOXML,编辑其他流行格式(`.odt`、`.rtf`、`.txt`、`.html`、`.ods`、`.csv`、`.odp`)。
|
||||
* 熟悉的选项卡式界面。
|
||||
* 协作工具:两种协同编辑模式(快速和严谨),跟踪更改,评论和集成聊天。
|
||||
* 灵活的访问权限管理:完全访问权限、只读、审阅、表单填写和评论。
|
||||
* 使用 API 构建附加组件。
|
||||
* 250 种可用语言和象形字母表。
|
||||
|
||||
通过 API,开发人员可以将 ONLYOFFICE 编辑器集成到网站和利用程序设计语言编写的应用程序中,并能配置和管理编辑器。
|
||||
|
||||
要集成 ONLYOFFICE 编辑器,我们需要一个集成应用程序来连接编辑器(ONLYOFFICE 文档服务器)和服务。 要在你的界面中使用编辑器,因该授予 ONLYOFFICE 以下权限:
|
||||
|
||||
* 添加并执行自定义代码。
|
||||
* 用于下载和保存文件的匿名访问权限。这意味着编辑器仅与服务器端的服务通信,而不包括客户端的任何用户授权数据(浏览器 cookies)。
|
||||
* 在用户界面添加新按钮(例如,“在 ONLYOFFICE 中打开”、“在 ONLYOFFICE 中编辑”)。
|
||||
* 开启一个新页面,ONLYOFFICE 可以在其中执行脚本以添加编辑器。
|
||||
* 能够指定文档服务器连接设置。
|
||||
|
||||
流行的协作解决方案的成功集成案例有很多,如 Nextcloud、ownCloud、Alfresco、Confluence 和 SharePoint,都是通过 ONLYOFFICE 提供的官方即用型连接器实现的。
|
||||
|
||||
实际的集成案例之一是 ONLYOFFICE 编辑器与以 C# 编写的开源协作平台的集成。该平台具有文档和项目管理、CRM、电子邮件聚合器、日历、用户数据库、博客、论坛、调查、Wiki 和即时通讯程序的功能。
|
||||
|
||||
将在线编辑器与 CRM 和项目模块集成,你可以:
|
||||
|
||||
* 文档关联到 CRM 时机和容器、项目任务和讨论,甚至创建一个单独的文件夹,其中包含与项目相关的文档、电子表格和演示文稿。
|
||||
* 直接在 CRM 或项目模块中创建新的文档、工作表和演示文稿。
|
||||
* 打开和编辑关联的文档,或者下载和删除。
|
||||
* 将联系人从 CSV 文件批量导入到 CRM 中,并将客户数据库导出为 CSV 文件。
|
||||
|
||||
在“邮件”模块中,你可以关联存储在“文档模块”中的文件,或者将指向所需文档的链接插入到邮件正文中。 当 ONLYOFFICE 用户收到带有附件的文档的消息时,他们可以:下载附件、在浏览器中查看文件、打开文件进行编辑或将其保存到“文档模块”。 如上所述,如果格式不同于 OOXML ,则文件将自动转换为 `.docx`、`.xlsx`、`.pptx`,并且其副本也将以原始格式保存。
|
||||
|
||||
在本文中,你将看到 ONLYOFFICE 与最流行的编程语言之一的 Python 编写的文档管理系统的集成过程。 以下步骤将向你展示如何创建所有必要的部分,以使在 DMS(<ruby>文档管理系统<rt>Document Management System</rt></ruby>)界面内的文档中可以进行协同工作成为可能:查看、编辑、协同编辑、保存文件和用户访问管理,并可以作为服务的示例集成到 Python 应用程序中。
|
||||
|
||||
### 1、前置需求
|
||||
|
||||
首先,创建集成过程的关键组件:[ONLYOFFICE 文档服务器][4] 和用 Python 编写的文件管理系统。
|
||||
|
||||
#### 1.1、ONLYOFFICE 文档服务器
|
||||
|
||||
要安装 ONLYOFFICE 文档服务器,你可以从多个安装选项中进行选择:编译 GitHub 上可用的源代码,使用 `.deb` 或 `.rpm` 软件包亦或 Docker 镜像。
|
||||
|
||||
我们推荐使用下面这条命令利用 Docker 映像安装文档服务器和所有必需的依赖。请注意,选择此方法,你需要安装最新的 Docker 版本。
|
||||
|
||||
```
|
||||
docker run -itd -p 80:80 onlyoffice/documentserver-de
|
||||
```
|
||||
|
||||
#### 1.2、利用 Python 开发 DMS
|
||||
|
||||
如果已经拥有一个,请检查它是否满足以下条件:
|
||||
|
||||
* 包含需要打开以查看/编辑的保留文件
|
||||
* 允许下载文件
|
||||
|
||||
对于该应用程序,我们将使用 Bottle 框架。我们将使用以下命令将其安装在工作目录中:
|
||||
|
||||
```
|
||||
pip install bottle
|
||||
```
|
||||
|
||||
然后我们创建应用程序代码 `main.py` 和模板 `index.tpl`。
|
||||
|
||||
我们将以下代码添加到 `main.py` 文件中:
|
||||
|
||||
```
|
||||
from bottle import route, run, template, get, static_file # connecting the framework and the necessary components
|
||||
@route('/') # setting up routing for requests for /
|
||||
def index():
|
||||
return template('index.tpl') # showing template in response to request
|
||||
|
||||
run(host="localhost", port=8080) # running the application on port 8080
|
||||
```
|
||||
|
||||
一旦我们运行该应用程序,点击 <http://localhost:8080> 就会在浏览器上呈现一个空白页面 。
|
||||
为了使文档服务器能够创建新文档,添加默认文件并在模板中生成其名称列表,我们应该创建一个文件夹 `files` 并将3种类型文件(`.docx`、`.xlsx` 和 `.pptx`)放入其中。
|
||||
|
||||
要读取这些文件的名称,我们使用 `listdir` 组件(模块):
|
||||
|
||||
```
|
||||
from os import listdir
|
||||
```
|
||||
|
||||
现在让我们为文件夹中的所有文件名创建一个变量:
|
||||
|
||||
```
|
||||
sample_files = [f for f in listdir('files')]
|
||||
```
|
||||
|
||||
要在模板中使用此变量,我们需要通过 `template` 方法传递它:
|
||||
|
||||
```
|
||||
def index():
|
||||
return template('index.tpl', sample_files=sample_files)
|
||||
```
|
||||
|
||||
这是模板中的这个变量:
|
||||
|
||||
```
|
||||
% for file in sample_files:
|
||||
<div>
|
||||
<span>{{file}}</span>
|
||||
</div>
|
||||
% end
|
||||
```
|
||||
|
||||
我们重新启动应用程序以查看页面上的文件名列表。
|
||||
|
||||
使这些文件可用于所有应用程序用户的方法如下:
|
||||
|
||||
```
|
||||
@get("/files/<filepath:re:.*\.*>")
|
||||
def show_sample_files(filepath):
|
||||
return static_file(filepath, root="files")
|
||||
```
|
||||
|
||||
### 2、查看文档
|
||||
|
||||
所有组件准备就绪后,让我们添加函数以使编辑者可以利用应用接口操作。
|
||||
|
||||
第一个选项使用户可以打开和查看文档。连接模板中的文档编辑器 API :
|
||||
|
||||
```
|
||||
<script type="text/javascript" src="editor_url/web-apps/apps/api/documents/api.js"></script>
|
||||
```
|
||||
|
||||
`editor_url` 是文档编辑器的链接接口。
|
||||
|
||||
打开每个文件以供查看的按钮:
|
||||
|
||||
```
|
||||
<button onclick="view('files/{{file}}')">view</button>
|
||||
```
|
||||
|
||||
现在我们需要添加带有 `id` 的 `div` 标签,打开文档编辑器:
|
||||
|
||||
```
|
||||
<div id="editor"></div>
|
||||
```
|
||||
|
||||
要打开编辑器,必须调用调用一个函数:
|
||||
|
||||
```
|
||||
<script>
|
||||
function view(filename) {
|
||||
if (/docx$/.exec(filename)) {
|
||||
filetype = "text"
|
||||
}
|
||||
if (/xlsx$/.exec(filename)) {
|
||||
filetype = "spreadsheet"
|
||||
}
|
||||
if (/pptx$/.exec(filename)) {
|
||||
filetype = "presentation",
|
||||
title: filename
|
||||
}
|
||||
|
||||
new DocsAPI.DocEditor("editor",
|
||||
{
|
||||
documentType: filetype,
|
||||
document: {
|
||||
url: "host_url" + '/' + filename,
|
||||
title: filename
|
||||
},
|
||||
editorConfig: {mode: 'view'}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
DocEditor 函数有两个参数:将在其中打开编辑器的元素 `id` 和带有编辑器设置的 `JSON`。
|
||||
在此示例中,使用了以下必需参数:
|
||||
|
||||
* `documentType` 由其格式标识(`.docx`、`.xlsx`、`.pptx` 用于相应的文本、电子表格和演示文稿)
|
||||
* `document.url` 是你要打开的文件链接。
|
||||
* `editorConfig.mode`。
|
||||
|
||||
我们还可以添加将在编辑器中显示的 `title`。
|
||||
|
||||
接下来,我们可以在 Python 应用程序中查看文档。
|
||||
|
||||
### 3、编辑文档
|
||||
|
||||
首先,添加 “Edit”(编辑)按钮:
|
||||
|
||||
```
|
||||
<button onclick="edit('files/{{file}}')">edit</button>
|
||||
```
|
||||
|
||||
然后创建一个新功能,打开文件进行编辑。类似于查看功能。
|
||||
|
||||
现在创建 3 个函数:
|
||||
|
||||
```
|
||||
<script>
|
||||
var editor;
|
||||
function view(filename) {
|
||||
if (editor) {
|
||||
editor.destroyEditor()
|
||||
}
|
||||
editor = new DocsAPI.DocEditor("editor",
|
||||
{
|
||||
documentType: get_file_type(filename),
|
||||
document: {
|
||||
url: "host_url" + '/' + filename,
|
||||
title: filename
|
||||
},
|
||||
editorConfig: {mode: 'view'}
|
||||
});
|
||||
}
|
||||
|
||||
function edit(filename) {
|
||||
if (editor) {
|
||||
editor.destroyEditor()
|
||||
}
|
||||
editor = new DocsAPI.DocEditor("editor",
|
||||
{
|
||||
documentType: get_file_type(filename),
|
||||
document: {
|
||||
url: "host_url" + '/' + filename,
|
||||
title: filename
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function get_file_type(filename) {
|
||||
if (/docx$/.exec(filename)) {
|
||||
return "text"
|
||||
}
|
||||
if (/xlsx$/.exec(filename)) {
|
||||
return "spreadsheet"
|
||||
}
|
||||
if (/pptx$/.exec(filename)) {
|
||||
return "presentation"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
`destroyEditor` 被调用以关闭一个打开的编辑器。
|
||||
|
||||
你可能会注意到,`edit()` 函数中缺少 `editorConfig` 参数,因为默认情况下它的值是:`{"mode":"edit"}`。
|
||||
|
||||
现在,我们拥有了打开文档以在 Python 应用程序中进行协同编辑的所有功能。
|
||||
|
||||
### 4、如何在 Python 应用中利用 ONLYOFFICE 协同编辑文档
|
||||
|
||||
通过在编辑器中设置对同一文档使用相同的 `document.key` 来实现协同编辑。 如果没有此键值,则每次打开文件时,编辑器都会创建编辑会话。
|
||||
|
||||
为每个文档设置唯一键,以使用户连接到同一编辑会话时进行协同编辑。 密钥格式应为以下格式:`filename +"_key"`。下一步是将其添加到当前文档的所有配置中。
|
||||
|
||||
```
|
||||
document: {
|
||||
url: "host_url" + '/' + filepath,
|
||||
title: filename,
|
||||
key: filename + '_key'
|
||||
},
|
||||
```
|
||||
|
||||
### 5、如何在 Python 应用中利用 ONLYOFFICE 保存文档
|
||||
|
||||
每次我们更改并保存文件时,ONLYOFFICE 都会存储其所有版本。 让我们仔细看看它是如何工作的。 关闭编辑器后,文档服务器将构建要保存的文件版本并将请求发送到 `callbackUrl` 地址。 该请求包含 `document.key`和指向刚刚构建的文件的链接。
|
||||
|
||||
`document.key` 用于查找文件的旧版本并将其替换为新版本。 由于这里没有任何数据库,因此仅使用 `callbackUrl` 发送文件名。
|
||||
|
||||
在 `editorConfig.callbackUrl` 的设置中指定 `callbackUrl` 参数并将其添加到 `edit()` 方法中:
|
||||
|
||||
```
|
||||
function edit(filename) {
|
||||
const filepath = 'files/' + filename;
|
||||
if (editor) {
|
||||
editor.destroyEditor()
|
||||
}
|
||||
editor = new DocsAPI.DocEditor("editor",
|
||||
{
|
||||
documentType: get_file_type(filepath),
|
||||
document: {
|
||||
url: "host_url" + '/' + filepath,
|
||||
title: filename,
|
||||
key: filename + '_key'
|
||||
}
|
||||
,
|
||||
editorConfig: {
|
||||
mode: 'edit',
|
||||
callbackUrl: "host_url" + '/callback' + '&filename=' + filename // add file name as a request parameter
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
编写一种方法,在获取到 POST 请求发送到 `/callback` 地址后将保存文件:
|
||||
|
||||
```
|
||||
@post("/callback") # processing post requests for /callback
|
||||
def callback():
|
||||
if request.json['status'] == 2:
|
||||
file = requests.get(request.json['url']).content
|
||||
with open('files/' + request.query['filename'], 'wb') as f:
|
||||
f.write(file)
|
||||
return "{\"error\":0}"
|
||||
|
||||
```
|
||||
|
||||
`# status 2` 是已生成的文件,当我们关闭编辑器时,新版本的文件将保存到存储器中。
|
||||
|
||||
### 6、管理用户
|
||||
|
||||
如果应用中有用户,并且你需要查看谁在编辑文档,请在编辑器的配置中输入其标识符(`id`和`name`)。
|
||||
|
||||
在界面中添加选择用户的功能:
|
||||
|
||||
```
|
||||
<select id="user_selector" onchange="pick_user()">
|
||||
<option value="1" selected="selected">JD</option>
|
||||
<option value="2">Turk</option>
|
||||
<option value="3">Elliot</option>
|
||||
<option value="4">Carla</option>
|
||||
</select>
|
||||
```
|
||||
|
||||
如果在标记 `<script>` 的开头添加对函数 `pick_user()` 的调用,负责初始化函数自身 `id` 和 `name` 变量。
|
||||
|
||||
```
|
||||
function pick_user() {
|
||||
const user_selector = document.getElementById("user_selector");
|
||||
this.current_user_name = user_selector.options[user_selector.selectedIndex].text;
|
||||
this.current_user_id = user_selector.options[user_selector.selectedIndex].value;
|
||||
}
|
||||
```
|
||||
|
||||
使用 `editorConfig.user.id` 和 `editorConfig.user.name` 来配置用户设置。将这些参数添加到文件编辑函数中的编辑器配置中。
|
||||
|
||||
```
|
||||
function edit(filename) {
|
||||
const filepath = 'files/' + filename;
|
||||
if (editor) {
|
||||
editor.destroyEditor()
|
||||
}
|
||||
editor = new DocsAPI.DocEditor("editor",
|
||||
{
|
||||
documentType: get_file_type(filepath),
|
||||
document: {
|
||||
url: "host_url" + '/' + filepath,
|
||||
title: filename
|
||||
},
|
||||
editorConfig: {
|
||||
mode: 'edit',
|
||||
callbackUrl: "host_url" + '/callback' + '?filename=' + filename,
|
||||
user: {
|
||||
id: this.current_user_id,
|
||||
name: this.current_user_name
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
使用这种方法,你可以将 ONLYOFFICE 编辑器集成到用 Python 编写的应用程序中,并获得用于在文档上进行协同工作的所有必要工具。有关更多集成示例(Java、Node.js、PHP、Ruby),请参考官方的 [API 文档][5]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensourceforu.com/2019/09/integrate-online-documents-editors-into-a-python-web-app-using-onlyoffice/
|
||||
|
||||
作者:[Aashima Sharma][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[stevenzdg988](https://github.com/stevenzdg988)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensourceforu.com/author/aashima-sharma/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2016/09/Typist-composing-text-in-laptop.jpg?resize=696%2C420&ssl=1 (Typist composing text in laptop)
|
||||
[2]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2016/09/Typist-composing-text-in-laptop.jpg?fit=900%2C543&ssl=1
|
||||
[3]: https://www.onlyoffice.com/en/
|
||||
[4]: https://www.onlyoffice.com/en/developer-edition.aspx
|
||||
[5]: https://api.onlyoffice.com/editors/basic
|
@ -0,0 +1,53 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "sthwhl"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13049-1.html"
|
||||
[#]: subject: "The biggest risk to uptime? Your staff"
|
||||
[#]: via: "https://www.networkworld.com/article/3444762/the-biggest-risk-to-uptime-your-staff.html"
|
||||
[#]: author: "Andy Patrizio https://www.networkworld.com/author/Andy-Patrizio/"
|
||||
|
||||
计算机正常运行最大的威胁是什么?是员工
|
||||
======
|
||||
|
||||
> 一项新研究发现,人为失误是引发停机时间的首要原因。你想象一下那是什么场景。
|
||||
|
||||
![](https://images.idgesg.net/images/article/2018/07/9_how-well-do-you-know-your-staff_head-in-sand-100765388-large.jpg)
|
||||
|
||||
之前有一个很老的笑话:“是人都会犯错,但是要真正把事情搞砸,你还缺台计算机。” 现在情况正好相反了,现如今,数据中心设备的可靠性已经得到了极大的提升,反而是使用设备的人员素质没能跟上,从而给计算机正常运行带来了很大的威胁。
|
||||
|
||||
<ruby>正常运行时间协会<rt>Uptime Institute</rt></ruby>对数千名 IT 专业人员一整年发生的故障事件进行了调查,得出结论表示绝大多数的数据中心故障是由于人为错误造成的,人为错误导致的故障率为 70%-75%。
|
||||
|
||||
而且有些故障很严重。调查发现,超过 30% 的 IT 服务与数据中心运营商经历了他们称之为是“严重服务退化”的停机事故。2019 年有 10% 的受访者称他们最近的事故造成的损失超过 100 万美元。
|
||||
|
||||
在正常运行时间协会在 2019 年 4 月的调查中,60% 的受访者认为,对于最近发生的重大停机事件,他们本可以通过更好的管理/流程或配置进行防止。而对于损失超过 100 万美元的故障事件,这一数字跃升至 74%。
|
||||
|
||||
正常运行时间协会认为,导致故障事件发生的最终的错误不一定是员工,而是令人失望的管理。
|
||||
|
||||
“这个行业仍然严重依赖于人工去完成一些最基础和最重要的工作,易受人为错误的影响,这一点无法避免,也许可做的防错/防灾措施很有限。”正常运行时间协会期刊的主编 Kevin Heslin 在一篇[博客文章][4]中写道。
|
||||
|
||||
“然而,对这些故障问题的快速调查发现,故障持续存在的主要原因不是人为失误,而是由于管理失误导致,如针对员工培训投资不足,相关政策执行不力,管理程序老旧,低估一名合格员工的重要性,这一系列的管理问题导致了故障停机。” Heslin 继续写道。
|
||||
|
||||
正常运行时间协会指出,公司的 IT 基础设施越复杂,特别是分布式特性基础设施,可能会越容易增加简单的错误层出不穷而导致业务中断的风险。同时指出公司需要意识到基础设施越复杂所涉及的风险就越大。
|
||||
|
||||
并警告说,在人员配备方面,不要以超过公司吸引和应用资源来管理基础设施的速度扩大关键 IT 能力,并在影响关键任务操作之前意识到任何人员和技能短缺。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3444762/the-biggest-risk-to-uptime-your-staff.html
|
||||
|
||||
作者:[Andy Patrizio][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[sthwhl](https://github.com/sthwhl)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Andy-Patrizio/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.networkworld.com/article/3223692/what-is-a-data-centerhow-its-changed-and-what-you-need-to-know.html
|
||||
[2]: https://www.networkworld.com/newsletters/signup.html
|
||||
[3]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE20773&utm_content=sidebar " Take the Intelligent Route with Consumption-Based Storage"
|
||||
[4]: https://journal.uptimeinstitute.com/how-to-avoid-outages-try-harder/
|
||||
[5]: https://www.facebook.com/NetworkWorld/
|
||||
[6]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,61 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13053-1.html)
|
||||
[#]: subject: (Making trade-offs when writing Python code)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-trade-offs)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
编写 Python 代码时要有所取舍
|
||||
======
|
||||
|
||||
> 本文是 Python 之禅特别系列的一部分,重点此篇着眼于第七、八、九条原则:可读性、特殊情况和实用性。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/26/105645c1looxqxns12loen.jpg)
|
||||
|
||||
软件开发是一门充满了取舍的学科。每一个选择,都有一个同样合理但相反的选择。将一个方法私有化?你在鼓励复制粘贴。将一个方法公开?你在过早地对一个接口做出承诺。
|
||||
|
||||
软件开发者每时每刻都在做艰难的选择。虽然 [Python 之禅][2] 中的所有原则都在一定程度上涵盖了权衡,但下面的原则对一些权衡进行了最艰难、最冷酷的审视。
|
||||
|
||||
### <ruby>可读性很重要<rt>Readability counts</rt></ruby>
|
||||
|
||||
从某种意义上说,这一中间原则确实是整个 Python 之禅的中心。这条原则与编写高效的程序无关。在大多数情况下,它甚至与编写健壮的程序也无关。它讲的是编写出*别人能读懂的程序*。
|
||||
|
||||
阅读代码,就其本质而言,发生在代码被添加到系统中之后。通常,它会发生在很久很久以后。忽略可读性是最简单的选择,因为它对现在没有伤害。无论添加新代码的原因是什么,它都会对现在造成影响,无论是一个令人痛苦的 bug 还是一个被强烈要求的功能。
|
||||
|
||||
如果面对巨大的压力,把可读性扔到一边,只管“解决问题”,而 Python 之禅提醒我们:可读性很重要。编写代码让它适合阅读,无论是对自己还是他人,都是一种慈悲。
|
||||
|
||||
### <ruby>特殊情况不足以违反规则<rt>Special cases aren't special enough to break the rules</rt></ruby>
|
||||
|
||||
总是有各种借口:这个 bug 特别麻烦,先简单处理一下吧;这个功能特别紧急,别管美观了;这种情况下所涉及的领域规则特别复杂,嵌套深点也没关系。
|
||||
|
||||
一旦我们对特例的借口妥协,大坝就会破裂,就丧失了原则;事情就会演变成一个疯狂麦克斯的荒诞症,每个程序员都会为自己试图找到最好的借口。
|
||||
|
||||
纪律需要承诺。只有当事情艰辛、有强烈的诱惑时,才是对一个软件开发人员的考验。总是有合理的借口来破坏规则,这就是为什么必须坚守规矩的原因。纪律就是向例外说不的艺术。没有任何解释可以改变这一点。
|
||||
|
||||
### <ruby>虽然,实用性胜过纯洁性<rt>Although, practicality beats purity</rt></ruby>
|
||||
|
||||
> “如果你只想着击打、弹跳、撞击、触碰敌人,你将无法真正打倒他。”
|
||||
> —— 《宫本武藏:[水之卷][3]》
|
||||
|
||||
归根结底,软件开发是一门实用的学科。它的目标是解决真实的人所面临的实际问题。实用性比纯粹性更重要:首先,我们必须*解决问题*。如果我们只考虑可读性、简单性或美观性,我们将无法真正*解决问题*。
|
||||
|
||||
正如宫本武藏所说的,每一次代码修改的首要目标应该是*解决问题*。这个问题需要我们心心念念地去解决它。如果我们不以解决问题为目标,只想着 Python 之禅,我们就辜负了这些原则。这是 Python 之禅所固有的另一种矛盾。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/zen-python-trade-offs
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxys)
|
||||
校对:[wxy](https://github.com/wxys)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/devops_confusion_wall_questions.png?itok=zLS7K2JG (Brick wall between two people, a developer and an operations manager)
|
||||
[2]: https://www.python.org/dev/peps/pep-0020/
|
||||
[3]: https://en.wikipedia.org/wiki/The_Book_of_Five_Rings#The_Book_of_Water
|
@ -0,0 +1,57 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13058-1.html)
|
||||
[#]: subject: (How the Zen of Python handles errors)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-errors)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
Python 处理错误的原则
|
||||
======
|
||||
|
||||
> 这是 Python 之禅特别系列的一部分,重点是第十和第十一条原则:沉默的错误(或不沉默)。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/27/223251q261j2ndoccajc16.jpg)
|
||||
|
||||
处理“异常情况”是编程中争论最多的问题之一。这可能是因为风险很大:处理不当的错误值甚至可以使庞大的系统瘫痪。由于“异常情况”从本质上来说,是测试不足的,但发生的频率却令人不快,因此,是否正确处理它们往往可以将一个噩梦般的系统与一个“可以工作”的系统区分开来。
|
||||
|
||||
从 Java 的 `checked` 异常,到 Erlang 的故障隔离,再到 Haskell 的 `Maybe`,不同的语言对错误处理的态度截然不同。
|
||||
|
||||
这两条 [Python 之禅][2]是 Python 对这个话题的冥思。
|
||||
|
||||
### <ruby>错误绝不应该悄悄传递...<rt>Errors should never pass silently…</rt></ruby>
|
||||
|
||||
当 Python 之禅在 Tim Peters 眼里闪烁而出之前,在维基百科被俗称为“维基”之前,第一个维基网站 [C2][3] 就已经存在了,它是一个编程指南的宝库。这些原则大多来自于 [Smalltalk][4] 编程社区。Smalltalk 的思想影响了许多面向对象的语言,包括 Python。
|
||||
|
||||
C2 维基定义了<ruby>武士原则<rt>Samurai Principle</rt></ruby>:“胜利归来,要么不归。”用 Python 人的术语来说,它鼓励摒弃<ruby>哨兵值<rt>sentinel value</rt></ruby>,比如用返回 `None` 或 `-1` 来表示无法完成任务,而是采用引发异常的方式。一个 `None` 是无声的:它看起来像一个值,可以放在一个变量中,然后到处传递。有时,它甚至是一个*有效*的返回值。
|
||||
|
||||
这里的原则是,如果一个函数不能完成它的契约,它应该“高调失败”:引发一个异常。所引发的异常永远不会看起来像是一个可能的值。它将跳过 `returned_value = call_to_function(parameter)` 行,并上升到调用栈中,可能使程序崩溃。
|
||||
|
||||
崩溃的调试是很直接的:有一个堆栈跟踪来指示问题以及调用堆栈。崩溃可能意味着程序的必要条件没有满足,需要人为干预。它可能意味着程序的逻辑有问题。无论是哪种情况,高调失败都比一个隐藏的、“缺失”的值要好。用 `None` 来感染程序的有效数据,直到它被用在某个地方,就如你可能已经知道的,错误信息会说 “**None 没有方法进行拆分**”。
|
||||
|
||||
### <ruby>除非显式消除<rt>Unless explicitly silenced</rt></ruby>
|
||||
|
||||
有时需要显式地捕获异常。我们可能会预见到文件中的某些行格式错误,并希望以特殊的方式来处理它们,也许可以把它们放在一个“需要人来看看的行”的文件中,而不是让整个程序崩溃。
|
||||
|
||||
Python 允许我们用 `except` 来捕获异常。这意味着错误可以被*显式*消除。这种明确性意味着 `except` 行在代码审查中是可见的。质疑为什么应该在这里显式消除异常并从异常中恢复,是有意义的。自问一下我们是否捕获了太多或太少的异常也是有意义的。
|
||||
|
||||
因为这些全都是明确的,所以有人可以阅读代码并了解哪些异常是可以恢复的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/zen-python-errors
|
||||
|
||||
作者:[Moshe Zadka][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/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/checklist_hands_team_collaboration.png?itok=u82QepPk (a checklist for a team)
|
||||
[2]: https://www.python.org/dev/peps/pep-0020/
|
||||
[3]: https://wiki.c2.com/
|
||||
[4]: https://en.wikipedia.org/wiki/Smalltalk
|
@ -0,0 +1,115 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (stevenzdg988)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13055-1.html)
|
||||
[#]: subject: (5 Python scripts for automating basic community management tasks)
|
||||
[#]: via: (https://opensource.com/article/20/3/automating-community-management-python)
|
||||
[#]: author: (Rich Bowen https://opensource.com/users/rbowen)
|
||||
|
||||
用于基本社区管理任务自动化的 5 个 Python 脚本
|
||||
======
|
||||
|
||||
> 如果某些事情不得不重复做三遍,尝试使其自动化。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/27/000544aakdc4mnmn6tzj8y.jpg)
|
||||
|
||||
我 [之前写过关于社区管理员的工作][2],如果你问 10 位社区管理员,你会得到 12 个不同的答案。不过,大多数情况下,你做的是社区需要你在任何特定时刻做的事情。而且很多事情可能是重复的。
|
||||
|
||||
当我还是系统管理员时,我遵循一个规则:如果某些事必须做三遍,我会尝试使其自动化。当然,如今,使用诸如 Ansible 这样的强大工具,就有了一整套科学的方法。
|
||||
|
||||
我每天或每周要做的一些事情涉及在一些地方查找内容,然后生成信息的摘要或报告,然后发布到别处。这样的任务是自动化的理想选择。这些并不是什么 [难事][3],当我与同事共享其中一些脚本时,总是至少有一个能证明这是有用的。
|
||||
|
||||
[在 GitHub][4] 上,我有几个每周都要使用的脚本。它们都不是很复杂,但每次都为我节省几分钟。其中一些是用 Perl 写的,因为我快 50 岁了(这些是我早些年写的)。有些是用 Python 写的,因为几年前,我决定要学习 Python。
|
||||
|
||||
以下是概述:
|
||||
|
||||
### tshirts.py
|
||||
|
||||
这个简单的 [tshirts.py 脚本][5]会根据你要定制的活动 T 恤的数量,然后告诉你尺寸分布是什么。它将这些尺寸分布在一条正态曲线(也称为 “钟形曲线”)上,以我的经验,这和一个正常的会议观众的实际需求非常吻合。如果在美国使用,则可能需要将脚本中的值调整的稍大一些;如果在欧洲使用,则可能需要将脚本中的值稍稍缩小一些。你的情况也许不同。
|
||||
|
||||
用法:
|
||||
|
||||
```
|
||||
[rbowen@sasha:community-tools/scripts]$ ./tshirts.py
|
||||
How many shirts? 300
|
||||
For a total of 300 shirts, order:
|
||||
|
||||
30.0 small
|
||||
72.0 medium
|
||||
96.0 large
|
||||
72.0 xl
|
||||
30.0 2xl
|
||||
```
|
||||
|
||||
### followers.py
|
||||
|
||||
[followers.py 脚本][6]为我提供了我关心的 Twitter 账号的关注者数量。
|
||||
|
||||
该脚本只有 14 行,没什么复杂的,但是它可能节省我十分钟的加载网页和查找数字的时间。
|
||||
|
||||
你需要编辑 `feed` 数组以添加你关心的帐户:
|
||||
|
||||
```
|
||||
feeds = [
|
||||
'centosproject',
|
||||
'centos'
|
||||
];
|
||||
```
|
||||
|
||||
注意:如果你在英语国家以外的地方运行它,则可能无法正常工作,因为它只是一个简单的屏幕抓取脚本,它读取 HTML 并查找其中包含的特定信息。因此,当输出使用其他语言时,正则表达式可能不匹配。
|
||||
|
||||
用法:
|
||||
|
||||
```
|
||||
[rbowen@sasha:community-tools/scripts]$ ./followers.py
|
||||
centosproject: 11,479 Followers
|
||||
centos: 18,155 Followers
|
||||
```
|
||||
|
||||
### get_meetups
|
||||
|
||||
[get_meetups 脚本][7]S 另一种类别的脚本 —— API脚本。这个特定的脚本使用 [meetup.com][8] 网站的 API 来寻找在特定区域和时间范围内特定主题的聚会,以便我可以将它报告给我的社区。你所依赖的许多服务都提供了 API,因此你的脚本可以查找信息,而无需手动查找网页。学习如何使用这些 API 既令人沮丧又耗时,但是最终将获得可以节省大量时间的技能。
|
||||
|
||||
_免责声明:[meetup.com][8] 已于 2019 年 8 月更改了他们的 API,我还没有将这个脚本更新到新的API,所以它现在实际上并没有工作。在接下来的几周内请关注此版本的修复版本。_
|
||||
|
||||
### centos-announcements.pl
|
||||
|
||||
[centos-announcements.pl 脚本][9]要复杂得多,而且对我的用例来说非常特殊,但你可能有类似的情况。在本例中该脚本查看邮件列表存档(`centos-announce` 邮件列表),并查找具有特定格式的邮件,然后生成这些邮件的报告。报告有两种不同的格式:一种用于我的每月新闻通讯,另一种用于安排 Twitter 信息(借助于 Hootsuite)。
|
||||
|
||||
我使用 Hootsuite 为 Twitter 安排内容,它们具有便捷的 CSV(逗号分隔值)格式,你可以一次批量安排整整一周的推文。从各种数据源(比如:邮件列表、博客、其他网页)自动生成 CSV 格式可以节省大量时间。但是请注意,这可能只应该用于初稿,然后你可以对其进行检查和编辑,以便最终不会自动发布你不想要内容的推文。
|
||||
|
||||
### reporting.pl
|
||||
|
||||
[reporting.pl 脚本][10]也是相当特定的,以满足我的特殊需求,但是这个概念本身是通用的。我每月向 [CentOS SIG][11](特殊兴趣小组)发送邮件,这些邮件计划在给定的月份报告。该脚本只是告诉我本月有哪些 SIG,并记录需要发送给他们的电子邮件。
|
||||
|
||||
但是,因以下两个原因,实际上并未发送该电子邮件。第一,我希望在消息发送之前对其进行编辑。第二,虽然发送电子邮件的脚本在过去很有效,但如今,很可能被当做垃圾邮件而被过滤。
|
||||
|
||||
### 总结
|
||||
|
||||
在这个存储库中还有一些其他脚本,这些脚本或多或少是针对我的特定需求的,但是我希望其中至少有一个脚本对你有用,并且希望这些脚本的多样性能激励你去自动化一些你自己的东西。我也希望看到你的自动化脚本存储库;在评论中链接他们!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/automating-community-management-python
|
||||
|
||||
作者:[Rich Bowen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[stevenzdg988](https://github.com/stevenzdg988)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/rbowen
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/Open%20Pharma.png?itok=GP7zqNZE (shapes of people symbols)
|
||||
[2]: http://drbacchus.com/what-does-a-community-manager-do/
|
||||
[3]: https://6dollarshirts.com/rocket-surgery
|
||||
[4]: https://github.com/rbowen/centos-community-tools/tree/master/scripts
|
||||
[5]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/tshirts.py
|
||||
[6]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/followers.py
|
||||
[7]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/get_meetups
|
||||
[8]: http://meetup.com
|
||||
[9]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/centos-announcements.pl
|
||||
[10]: https://github.com/rbowen/centos-community-tools/blob/master/scripts/sig_reporting/reporting.pl
|
||||
[11]: https://wiki.centos.org/SpecialInterestGroup
|
@ -0,0 +1,453 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (stevenzdg988)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13047-1.html)
|
||||
[#]: subject: (A beginner's guide to web scraping with Python)
|
||||
[#]: via: (https://opensource.com/article/20/5/web-scraping-python)
|
||||
[#]: author: (Julia Piaskowski https://opensource.com/users/julia-piaskowski)
|
||||
|
||||
利用 Python 爬取网站的新手指南
|
||||
======
|
||||
|
||||
> 通过基本的 Python 工具获得爬取完整 HTML 网站的实践经验。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/24/093527skakhvc3kalnuxa1.jpg)
|
||||
|
||||
有很多很棒的书可以帮助你学习 Python ,但是谁真正读了这那些大部头呢?(剧透:反正不是我)。
|
||||
|
||||
许多人觉得教学书籍很有用,但我通常不会从头到尾地阅读一本书来学习。我是通过做一个项目,努力的弄清楚一些内容,然后再读另一本书来学习。因此,暂时丢掉书,让我们一起学习 Python。
|
||||
|
||||
接下来是我的第一个 Python 爬取项目的指南。它对 Python 和 HTML 的假定知识要求很低。这篇文章旨在说明如何使用 Python 的 [requests][2] 库访问网页内容,并使用 [BeatifulSoup4][3] 库以及 JSON 和 [pandas][4] 库解析网页内容。我将简要介绍 [Selenium][5] 库,但我不会深入研究如何使用该库——这个主题值得有自己的教程。最终,我希望向你展示一些技巧和小窍门,以减少网页爬取过程中遇到的问题。
|
||||
|
||||
### 安装依赖
|
||||
|
||||
我的 [GitHub 存储库][6] 中提供了本指南的所有资源。如果需要安装 Python3 的帮助,请查看 [Linux][7]、[Windows][8] 和 [Mac][9] 的教程。
|
||||
|
||||
```
|
||||
$ python3 -m venv
|
||||
$ source venv/bin/activate
|
||||
$ pip install requests bs4 pandas
|
||||
```
|
||||
|
||||
如果你喜欢使用 JupyterLab ,则可以使用 [notebook][10] 运行所有代码。[安装 JupyterLab][11] 有很多方法,这是其中一种:
|
||||
|
||||
```
|
||||
# from the same virtual environment as above, run:
|
||||
$ pip install jupyterlab
|
||||
```
|
||||
|
||||
### 为网站抓取项目设定目标
|
||||
|
||||
现在我们已经安装了依赖项,但是爬取网页需要做什么?
|
||||
|
||||
让我们退一步,确保使目标清晰。下面是成功完成网页爬取项目需求列表:
|
||||
|
||||
* 我们收集的信息,是值得我们花大力气去建立一个有效的网页爬取器的。
|
||||
* 我们所下载的信息是可以通过网页爬取器合法和道德地收集的。
|
||||
* 对如何在 HTML 代码中找到目标信息有一定的了解。
|
||||
* 利用恰当的工具:在此情况下,需要使用 BeautifulSoup 库和 requests 库。
|
||||
* 知道(或愿意去学习)如何解析 JSON 对象。
|
||||
* 有足够的 pandas 数据处理技能。
|
||||
|
||||
关于 HTML 的备注:HTML 是运行在互联网上的“猛兽”,但我们最需要了解的是标签的工作方式。标签是一对由尖括号包围关键词(一般成对出现,其内容在两个标签中间)。比如,这是一个假装的标签,称为 `pro-tip`:
|
||||
|
||||
```
|
||||
<pro-tip> All you need to know about html is how tags work </pro-tip>
|
||||
```
|
||||
|
||||
我们可以通过调用标签 `pro-tip` 来访问其中的信息(`All you need to know…`)。本教程将进一步介绍如何查找和访问标签。要进一步了解 HTML 基础知识,请查看 [本文][12]。
|
||||
|
||||
### 网站爬取项目中要找的是什么
|
||||
|
||||
有些数据利用网站爬取采集比利用其他方法更合适。以下是我认为合适项目的准则:
|
||||
|
||||
没有可用于数据(处理)的公共 API。通过 API 抓取结构化数据会容易得多,(所以没有 API )有助于澄清收集数据的合法性和道德性。而有相当数量的结构化数据,并有规律的、可重复的格式,才能证明这种努力的合理性。网页爬取可能会很痛苦。BeautifulSoup(bs4)使操作更容易,但无法避免网站的个别特殊性,需要进行定制。数据的相同格式化不是必须的,但这确实使事情变得更容易。存在的 “边际案例”(偏离规范)越多,爬取就越复杂。
|
||||
|
||||
免责声明:我没有参加过法律培训;以下内容无意作为正式的法律建议。
|
||||
|
||||
关于合法性,访问大量有价值信息可能令人兴奋,但仅仅因为它是可能的,并不意味着应该这样做。
|
||||
|
||||
值得庆幸的是,有一些公共信息可以指导我们的道德规范和网页爬取工具。大多数网站都有与该网站关联的 [robots.txt][13] 文件,指出允许哪些爬取活动,哪些不被允许。它主要用于与搜索引擎(网页抓取工具的终极形态)进行交互。然而,网站上的许多信息都被视为公共信息。因此,有人将 `robots.txt` 文件视为一组建议,而不是具有法律约束力的文档。 `robots.txt` 文件并不涉及数据的道德收集和使用等主题。
|
||||
|
||||
在开始爬取项目之前,问自己以下问题:
|
||||
|
||||
* 我是否在爬取版权材料?
|
||||
* 我的爬取活动会危害个人隐私吗?
|
||||
* 我是否发送了大量可能会使服务器超载或损坏的请求?
|
||||
* 爬取是否会泄露出我不拥有的知识产权?
|
||||
* 是否有规范网站使用的服务条款,我是否遵循了这些条款?
|
||||
* 我的爬取活动会减少原始数据的价值吗?(例如,我是否打算按原样重新打包数据,或者可能从原始来源中抽取网站流量)?
|
||||
|
||||
当我爬取一个网站时,请确保可以对所有这些问题回答 “否”。
|
||||
|
||||
要深入了解这些法律问题,请参阅 2018 年出版的 Krotov 和 Silva 撰写的[《Web 爬取的合法性和道德性》][14] 和 Sellars 的[《二十年 Web 爬取和计算机欺诈与滥用法案》][15]。
|
||||
|
||||
### 现在开始爬取网站
|
||||
|
||||
经过上述评估,我想出了一个项目。我的目标是爬取爱达荷州所有 Family Dollar 商店的地址。 这些商店在农村地区规模很大,因此我想了解有多少家这样的商店。
|
||||
|
||||
起点是 [Family Dollar 的位置页面][16]
|
||||
|
||||
![爱达荷州 Family Dollar 所在地页面][17]
|
||||
|
||||
首先,让我们在 Python 虚拟环境中加载先决条件。此处的代码将被添加到一个 Python 文件(如果你想要个名称,则为 `scraper.py`)或在 JupyterLab 的单元格中运行。
|
||||
|
||||
```
|
||||
import requests # for making standard html requests
|
||||
from bs4 import BeautifulSoup # magical tool for parsing html data
|
||||
import json # for parsing data
|
||||
from pandas import DataFrame as df # premier library for data organization
|
||||
```
|
||||
|
||||
接下来,我们从目标 URL 中请求数据。
|
||||
|
||||
```
|
||||
page = requests.get("https://locations.familydollar.com/id/")
|
||||
soup = BeautifulSoup(page.text, 'html.parser')
|
||||
```
|
||||
|
||||
BeautifulSoup 将 HTML 或 XML 内容转换为复杂树对象。这是我们将使用的几种常见对象类型。
|
||||
|
||||
* `BeautifulSoup` —— 解析的内容
|
||||
* `Tag` —— 标准 HTML 标记,这是你将遇到的 `bs4` 元素的主要类型
|
||||
* `NavigableString` —— 标签内的文本字符串
|
||||
* `Comment` —— NavigableString 的一种特殊类型
|
||||
|
||||
当我们查看 `requests.get()` 输出时,还有更多要考虑的问题。我仅使用 `page.text()` 将请求的页面转换为可读的内容,但是还有其他输出类型:
|
||||
|
||||
* `page.text()` 文本(最常见)
|
||||
* `page.content()` 逐字节输出
|
||||
* `page.json()` JSON 对象
|
||||
* `page.raw()` 原始套接字响应(对你没啥用)
|
||||
|
||||
我只在使用拉丁字母的纯英语网站上操作。 `requests` 中的默认编码设置可以很好地解决这一问题。然而,除了纯英语网站之外,就是更大的互联网世界。为了确保 `requests` 正确解析内容,你可以设置文本的编码:
|
||||
|
||||
```
|
||||
page = requests.get(URL)
|
||||
page.encoding = 'ISO-885901'
|
||||
soup = BeautifulSoup(page.text, 'html.parser')
|
||||
```
|
||||
|
||||
仔细研究 `BeautifulSoup` 标签,我们看到:
|
||||
|
||||
* `bs4` 元素 `tag` 捕获的是一个 HTML 标记。
|
||||
* 它具有名称和属性,可以像字典一样访问:`tag['someAttribute']`。
|
||||
* 如果标签具有相同名称的多个属性,则仅访问第一个实例。
|
||||
* 可通过 `tag.contents` 访问子标签。
|
||||
* 所有标签后代都可以通过 `tag.contents` 访问。
|
||||
* 你始终可以使用以下字符串:`re.compile("your_string")` 访问一个字符串的所有内容,而不是浏览 HTML 树。
|
||||
|
||||
### 确定如何提取相应内容
|
||||
|
||||
警告:此过程可能令人沮丧。
|
||||
|
||||
网站爬取过程中的提取可能是一个令人生畏的充满了误区的过程。我认为解决此问题的最佳方法是从一个有代表性的示例开始然后进行扩展(此原理对于任何编程任务都是适用的)。查看页面的 HTML 源代码至关重要。有很多方法可以做到这一点。
|
||||
|
||||
你可以在终端中使用 Python 查看页面的整个源代码(不建议使用)。运行此代码需要你自担风险:
|
||||
|
||||
```
|
||||
print(soup.prettify())
|
||||
```
|
||||
|
||||
虽然打印出页面的整个源代码可能适用于某些教程中显示的玩具示例,但大多数现代网站的页面上都有大量内容。甚至 404 页面也可能充满了页眉、页脚等代码。
|
||||
|
||||
通常,在你喜欢的浏览器中通过 “查看页面源代码” 来浏览源代码是最容易的(单击右键,然后选择 “查看页面源代码” )。这是找到目标内容的最可靠方法(稍后我将解释原因)。
|
||||
|
||||
![Family Dollar 页面源代码][18]
|
||||
|
||||
在这种情况下,我需要在这个巨大的 HTML 海洋中找到我的目标内容 —— 地址、城市、州和邮政编码。通常,对页面源(`ctrl+F`)的简单搜索就会得到目标位置所在的位置。一旦我实际看到目标内容的示例(至少一个商店的地址),便会找到将该内容与其他内容区分开的属性或标签。
|
||||
|
||||
首先,我需要在爱达荷州 Family Dollar 商店中收集不同城市的网址,并访问这些网站以获取地址信息。这些网址似乎都包含在 `href` 标记中。太棒了!我将尝试使用 `find_all` 命令进行搜索:
|
||||
|
||||
```
|
||||
dollar_tree_list = soup.find_all('href')
|
||||
dollar_tree_list
|
||||
```
|
||||
|
||||
搜索 `href` 不会产生任何结果,该死。这可能是因为 `href` 嵌套在 `itemlist` 类中而失败。对于下一次尝试,请搜索 `item_list`。由于 `class` 是 Python 中的保留字,因此使用 `class_` 来作为替代。`soup.find_all()` 原来是 `bs4` 函数的瑞士军刀。
|
||||
|
||||
```
|
||||
dollar_tree_list = soup.find_all(class_ = 'itemlist')
|
||||
for i in dollar_tree_list[:2]:
|
||||
print(i)
|
||||
```
|
||||
|
||||
有趣的是,我发现搜索一个特定类的方法一般是一种成功的方法。通过找出对象的类型和长度,我们可以了解更多有关对象的信息。
|
||||
|
||||
```
|
||||
type(dollar_tree_list)
|
||||
len(dollar_tree_list)
|
||||
```
|
||||
|
||||
可以使用 `.contents` 从 BeautifulSoup “结果集” 中提取内容。这也是创建单个代表性示例的好时机。
|
||||
|
||||
```
|
||||
example = dollar_tree_list[2] # a representative example
|
||||
example_content = example.contents
|
||||
print(example_content)
|
||||
```
|
||||
|
||||
使用 `.attr` 查找该对象内容中存在的属性。注意:`.contents` 通常会返回一个项目的精确的列表,因此第一步是使用方括号符号为该项目建立索引。
|
||||
|
||||
```
|
||||
example_content = example.contents[0]
|
||||
example_content.attrs
|
||||
```
|
||||
|
||||
现在,我可以看到 `href` 是一个属性,可以像字典项一样提取它:
|
||||
|
||||
```
|
||||
example_href = example_content['href']
|
||||
print(example_href)
|
||||
```
|
||||
|
||||
### 整合网站抓取工具
|
||||
|
||||
所有的这些探索为我们提供了前进的路径。这是厘清上面逻辑的一个清理版本。
|
||||
|
||||
```
|
||||
city_hrefs = [] # initialise empty list
|
||||
|
||||
for i in dollar_tree_list:
|
||||
cont = i.contents[0]
|
||||
href = cont['href']
|
||||
city_hrefs.append(href)
|
||||
|
||||
# check to be sure all went well
|
||||
for i in city_hrefs[:2]:
|
||||
print(i)
|
||||
```
|
||||
|
||||
输出的内容是一个关于抓取爱达荷州 Family Dollar 商店 URL 的列表。
|
||||
|
||||
也就是说,我仍然没有获得地址信息!现在,需要抓取每个城市的 URL 以获得此信息。因此,我们使用一个具有代表性的示例重新开始该过程。
|
||||
|
||||
```
|
||||
page2 = requests.get(city_hrefs[2]) # again establish a representative example
|
||||
soup2 = BeautifulSoup(page2.text, 'html.parser')
|
||||
```
|
||||
|
||||
![Family Dollar 地图和代码][19]
|
||||
|
||||
地址信息嵌套在 `type="application/ld+json"` 里。经过大量的地理位置抓取之后,我开始认识到这是用于存储地址信息的一般结构。幸运的是,`soup.find_all()` 开启了利用 `type` 搜索。
|
||||
|
||||
```
|
||||
arco = soup2.find_all(type="application/ld+json")
|
||||
print(arco[1])
|
||||
```
|
||||
|
||||
地址信息在第二个列表成员中!原来如此!
|
||||
|
||||
使用 `.contents` 提取(从第二个列表项中)内容(这是过滤后的合适的默认操作)。同样,由于输出的内容是一个列表,因此我为该列表项建立了索引:
|
||||
|
||||
```
|
||||
arco_contents = arco[1].contents[0]
|
||||
arco_contents
|
||||
```
|
||||
|
||||
喔,看起来不错。此处提供的格式与 JSON 格式一致(而且,该类型的名称中确实包含 “json”)。 JSON 对象的行为就像是带有嵌套字典的字典。一旦你熟悉利用其去工作,它实际上是一种不错的格式(当然,它比一长串正则表达式命令更容易编程)。尽管从结构上看起来像一个 JSON 对象,但它仍然是 `bs4` 对象,需要通过编程方式转换为 JSON 对象才能对其进行访问:
|
||||
|
||||
```
|
||||
arco_json = json.loads(arco_contents)
|
||||
```
|
||||
|
||||
```
|
||||
type(arco_json)
|
||||
print(arco_json)
|
||||
```
|
||||
|
||||
在该内容中,有一个被调用的 `address` 键,该键要求地址信息在一个比较小的嵌套字典里。可以这样检索:
|
||||
|
||||
```
|
||||
arco_address = arco_json['address']
|
||||
arco_address
|
||||
```
|
||||
|
||||
好吧,请大家注意。现在我可以遍历存储爱达荷州 URL 的列表:
|
||||
|
||||
```
|
||||
locs_dict = [] # initialise empty list
|
||||
|
||||
for link in city_hrefs:
|
||||
locpage = requests.get(link) # request page info
|
||||
locsoup = BeautifulSoup(locpage.text, 'html.parser')
|
||||
# parse the page's content
|
||||
locinfo = locsoup.find_all(type="application/ld+json")
|
||||
# extract specific element
|
||||
loccont = locinfo[1].contents[0]
|
||||
# get contents from the bs4 element set
|
||||
locjson = json.loads(loccont) # convert to json
|
||||
locaddr = locjson['address'] # get address
|
||||
locs_dict.append(locaddr) # add address to list
|
||||
```
|
||||
|
||||
### 用 Pandas 整理我们的网站抓取结果
|
||||
|
||||
我们在字典中装载了大量数据,但是还有一些额外的无用项,它们会使重用数据变得比需要的更为复杂。要执行最终的数据组织,我们需要将其转换为 Pandas 数据框架,删除不需要的列 `@type` 和 `country`,并检查前五行以确保一切正常。
|
||||
|
||||
```
|
||||
locs_df = df.from_records(locs_dict)
|
||||
locs_df.drop(['@type', 'addressCountry'], axis = 1, inplace = True)
|
||||
locs_df.head(n = 5)
|
||||
```
|
||||
|
||||
确保保存结果!!
|
||||
|
||||
```
|
||||
df.to_csv(locs_df, "family_dollar_ID_locations.csv", sep = ",", index = False)
|
||||
```
|
||||
|
||||
我们做到了!所有爱达荷州 Family Dollar 商店都有一个用逗号分隔的列表。多令人兴奋。
|
||||
|
||||
### Selenium 和数据抓取的一点说明
|
||||
|
||||
[Selenium][5] 是用于与网页自动交互的常用工具。为了解释为什么有时必须使用它,让我们来看一个使用 Walgreens 网站的示例。 “检查元素” 提供了浏览器显示内容的代码:
|
||||
|
||||
![Walgreens 位置页面和代码][20]
|
||||
|
||||
虽然 “查看页面源代码” 提供了有关 `requests` 将获得什么内容的代码:
|
||||
|
||||
![Walgreens 源代码][21]
|
||||
|
||||
如果这两个不一致,是有一些插件可以修改源代码 —— 因此,应在将页面加载到浏览器后对其进行访问。`requests` 不能做到这一点,但是 Selenium 可以做到。
|
||||
|
||||
Selenium 需要 Web 驱动程序来检索内容。实际上,它会打开 Web 浏览器,并收集此页面的内容。Selenium 功能强大 —— 它可以通过多种方式与加载的内容进行交互(请阅读文档)。使用 Selenium 获取数据后,继续像以前一样使用 BeautifulSoup:
|
||||
|
||||
```
|
||||
url = "https://www.walgreens.com/storelistings/storesbycity.jsp?requestType=locator&state=ID"
|
||||
driver = webdriver.Firefox(executable_path = 'mypath/geckodriver.exe')
|
||||
driver.get(url)
|
||||
soup_ID = BeautifulSoup(driver.page_source, 'html.parser')
|
||||
store_link_soup = soup_ID.find_all(class_ = 'col-xl-4 col-lg-4 col-md-4')
|
||||
```
|
||||
|
||||
对于 Family Dollar 这种情形,我不需要 Selenium,但是当呈现的内容与源代码不同时,我确实会保留使用 Selenium。
|
||||
|
||||
### 小结
|
||||
|
||||
总之,使用网站抓取来完成有意义的任务时:
|
||||
|
||||
* 耐心一点
|
||||
* 查阅手册(它们非常有帮助)
|
||||
|
||||
如果你对答案感到好奇:
|
||||
|
||||
![Family Dollar 位置图][23]
|
||||
|
||||
美国有很多 Family Dollar 商店。
|
||||
|
||||
完整的源代码是:
|
||||
|
||||
```
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import json
|
||||
from pandas import DataFrame as df
|
||||
|
||||
page = requests.get("https://www.familydollar.com/locations/")
|
||||
soup = BeautifulSoup(page.text, 'html.parser')
|
||||
|
||||
# find all state links
|
||||
state_list = soup.find_all(class_ = 'itemlist')
|
||||
|
||||
state_links = []
|
||||
|
||||
for i in state_list:
|
||||
cont = i.contents[0]
|
||||
attr = cont.attrs
|
||||
hrefs = attr['href']
|
||||
state_links.append(hrefs)
|
||||
|
||||
# find all city links
|
||||
city_links = []
|
||||
|
||||
for link in state_links:
|
||||
page = requests.get(link)
|
||||
soup = BeautifulSoup(page.text, 'html.parser')
|
||||
familydollar_list = soup.find_all(class_ = 'itemlist')
|
||||
for store in familydollar_list:
|
||||
cont = store.contents[0]
|
||||
attr = cont.attrs
|
||||
city_hrefs = attr['href']
|
||||
city_links.append(city_hrefs)
|
||||
# to get individual store links
|
||||
store_links = []
|
||||
|
||||
for link in city_links:
|
||||
locpage = requests.get(link)
|
||||
locsoup = BeautifulSoup(locpage.text, 'html.parser')
|
||||
locinfo = locsoup.find_all(type="application/ld+json")
|
||||
for i in locinfo:
|
||||
loccont = i.contents[0]
|
||||
locjson = json.loads(loccont)
|
||||
try:
|
||||
store_url = locjson['url']
|
||||
store_links.append(store_url)
|
||||
except:
|
||||
pass
|
||||
|
||||
# get address and geolocation information
|
||||
stores = []
|
||||
|
||||
for store in store_links:
|
||||
storepage = requests.get(store)
|
||||
storesoup = BeautifulSoup(storepage.text, 'html.parser')
|
||||
storeinfo = storesoup.find_all(type="application/ld+json")
|
||||
for i in storeinfo:
|
||||
storecont = i.contents[0]
|
||||
storejson = json.loads(storecont)
|
||||
try:
|
||||
store_addr = storejson['address']
|
||||
store_addr.update(storejson['geo'])
|
||||
stores.append(store_addr)
|
||||
except:
|
||||
pass
|
||||
|
||||
# final data parsing
|
||||
stores_df = df.from_records(stores)
|
||||
stores_df.drop(['@type', 'addressCountry'], axis = 1, inplace = True)
|
||||
stores_df['Store'] = "Family Dollar"
|
||||
|
||||
df.to_csv(stores_df, "family_dollar_locations.csv", sep = ",", index = False)
|
||||
```
|
||||
|
||||
作者注释:本文改编自 2020 年 2 月 9 日在俄勒冈州波特兰的[我在 PyCascades 的演讲][24]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/5/web-scraping-python
|
||||
|
||||
作者:[Julia Piaskowski][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[stevenzdg988](https://github.com/stevenzdg988)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/julia-piaskowski
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bus_html_code.png?itok=VjUmGsnl (HTML code)
|
||||
[2]: https://requests.readthedocs.io/en/master/
|
||||
[3]: https://beautiful-soup-4.readthedocs.io/en/latest/
|
||||
[4]: https://pandas.pydata.org/
|
||||
[5]: https://www.selenium.dev/
|
||||
[6]: https://github.com/jpiaskowski/pycas2020_web_scraping
|
||||
[7]: https://opensource.com/article/20/4/install-python-linux
|
||||
[8]: https://opensource.com/article/19/8/how-install-python-windows
|
||||
[9]: https://opensource.com/article/19/5/python-3-default-mac
|
||||
[10]: https://github.com/jpiaskowski/pycas2020_web_scraping/blob/master/example/Familydollar_location_scrape-all-states.ipynb
|
||||
[11]: https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html
|
||||
[12]: https://opensource.com/article/20/4/build-websites
|
||||
[13]: https://www.contentkingapp.com/academy/robotstxt/
|
||||
[14]: https://www.researchgate.net/publication/324907302_Legality_and_Ethics_of_Web_Scraping
|
||||
[15]: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3221625
|
||||
[16]: https://locations.familydollar.com/id/
|
||||
[17]: https://opensource.com/sites/default/files/uploads/familydollar1.png (Family Dollar Idaho locations page)
|
||||
[18]: https://opensource.com/sites/default/files/uploads/familydollar2.png (Family Dollar page source code)
|
||||
[19]: https://opensource.com/sites/default/files/uploads/familydollar3.png (Family Dollar map and code)
|
||||
[20]: https://opensource.com/sites/default/files/uploads/walgreens1.png (Walgreens location page and code)
|
||||
[21]: https://opensource.com/sites/default/files/uploads/walgreens2.png (Walgreens source code)
|
||||
[22]: https://www.walgreens.com/storelistings/storesbycity.jsp?requestType=locator\&state=ID
|
||||
[23]: https://opensource.com/sites/default/files/uploads/family_dollar_locations.png (Family Dollar locations map)
|
||||
[24]: https://2020.pycascades.com/talks/adventures-in-babysitting-webscraping-for-python-and-html-novices/
|
@ -0,0 +1,228 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (mengxinayan)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13069-1.html)
|
||||
[#]: subject: (Understanding 52-bit virtual address support in the Arm64 kernel)
|
||||
[#]: via: (https://opensource.com/article/20/12/52-bit-arm64-kernel)
|
||||
[#]: author: (Bhupesh Sharma https://opensource.com/users/bhsharma)
|
||||
|
||||
理解 ARM64 内核中对 52 位虚拟地址的支持
|
||||
======
|
||||
|
||||
> 随着 64 位硬件的引入,增加了处理更大地址空间的需求。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/30/170448rynbm9b6nmb90403.jpg)
|
||||
|
||||
当 64 位硬件变得可用之后,处理更大地址空间(大于 2^32 字节)的需求变得显而易见。现如今一些公司已经提供 64TiB 或更大内存的服务器,x86_64 架构和 arm64 架构现在允许寻址的地址空间大于 2^48 字节(可以使用默认的 48 位地址支持)。
|
||||
|
||||
x86_64 架构通过让硬件和软件启用五级页表以支持这些用例。它允许寻址的地址空间等于 2^57 字节(详情见 [x86:在 4.12 内核中启用 5 级页表][2])。它突破了过去虚拟地址空间 128PiB 和物理地址空间 4PiB 的上限。
|
||||
|
||||
arm64 架构通过引入两个新的体系结构 —— ARMv8.2 LVA(更大的虚拟寻址) 和 ARMv8.2 LPA(更大的物理地址寻址) —— 拓展来实现相同的功能。这允许使用 4PiB 的虚拟地址空间和 4PiB 的物理地址空间(即分别为 2^52 位)。
|
||||
|
||||
随着新的 arm64 CPU 中支持了 ARMv8.2 体系结构拓展,同时现在开源软件也支持了这两种新的硬件拓展。
|
||||
|
||||
从 Linux 5.4 内核开始, arm64 架构中的 52 位(大)虚拟地址(VA)和物理地址(PA)得到支持。尽管[内核文档][3]描述了这些特性和新的内核运行时对旧的 CPU(硬件层面不支持 52 位虚拟地址拓展)和新的 CPU(硬件层面支持 52 位虚拟地址拓展)的影响,但对普通用户而言,理解这些并且如何 “选择使用” 52 位的地址空间可能会很复杂。
|
||||
|
||||
因此,我会在本文中介绍下面这些比较新的概念:
|
||||
|
||||
1. 在增加了对这些功能的支持后,内核的内存布局如何“翻转”到 Arm64 架构
|
||||
2. 对用户态应用的影响,尤其是对提供调试支持的程序(例如:kexec-tools、 makedumpfile 和 crash-utility)
|
||||
3. 如何通过指定大于 48 位的 mmap 参数,使用户态应用“选择”从 52 位地址空间接受 VA?
|
||||
|
||||
### ARMv8.2 架构的 LVA 和 LPA 拓展
|
||||
|
||||
ARMv8.2 架构提供两种重要的拓展:大虚拟寻址(LVA)和大物理寻址(LPA)。
|
||||
|
||||
当使用 64 KB 转换粒度时,ARMv8.2-LVA 为每个翻译表基地址寄存器提供了一个更大的 52 位虚拟地址空间。
|
||||
|
||||
在 ARMv8.2-LVA 中允许:
|
||||
|
||||
* 当使用 64 KB 转换粒度时,中间物理地址(IPA)和物理地址空间拓展为 52 位。
|
||||
* 如果使用 64 KB 转换粒度来实现对 52 位物理地址的支持,那么一级块将会覆盖 4TB 的地址空间。
|
||||
|
||||
_需要注意的是这些特性仅在 AArch64 架构中支持。_
|
||||
|
||||
目前下列的 Arm64 Cortex-A 处理器支持 ARMv8.2 拓展:
|
||||
|
||||
* Cortex-A55
|
||||
* Cortex-A75
|
||||
* Cortex-A76
|
||||
|
||||
更多细节请参考 [Armv8 架构参考手册][4]。
|
||||
|
||||
### Arm64 的内核内存布局
|
||||
|
||||
伴随着 ARMv8.2 拓展增加了对 LVA 地址的支持(仅当以页大小为 64 KB 运行时可用),在第一级转换中,描述符的数量会增加。
|
||||
|
||||
用户地址将 63-48 位位置为 0,然而内核地址将这些位设置为 1。TTBRx 的选择由虚拟地址的 63 位决定。`swapper_pg_dir` 仅包含内核(全局)映射,然而 `pgd` 仅包含用户(非全局)的映射。`swapper_pg_dir` 地址会写入 TTBR1,且永远不会写入 TTBR0。
|
||||
|
||||
**页面大小为 64 KB 和三个级别的(具有 52 位硬件支持)的 AArch64 架构下 Linux 内存布局如下:**
|
||||
|
||||
```
|
||||
开始 结束 大小 用途
|
||||
-----------------------------------------------------------------------
|
||||
0000000000000000 000fffffffffffff 4PB 用户
|
||||
fff0000000000000 fff7ffffffffffff 2PB 内核逻辑内存映射
|
||||
fff8000000000000 fffd9fffffffffff 1440TB [间隙]
|
||||
fffda00000000000 ffff9fffffffffff 512TB Kasan 阴影区
|
||||
ffffa00000000000 ffffa00007ffffff 128MB bpf jit 区域
|
||||
ffffa00008000000 ffffa0000fffffff 128MB 模块
|
||||
ffffa00010000000 fffff81ffffeffff ~88TB vmalloc 区
|
||||
fffff81fffff0000 fffffc1ffe58ffff ~3TB [保护区域]
|
||||
fffffc1ffe590000 fffffc1ffe9fffff 4544KB 固定映射
|
||||
fffffc1ffea00000 fffffc1ffebfffff 2MB [保护区域]
|
||||
fffffc1ffec00000 fffffc1fffbfffff 16MB PCI I/O 空间
|
||||
fffffc1fffc00000 fffffc1fffdfffff 2MB [保护区域]
|
||||
fffffc1fffe00000 ffffffffffdfffff 3968GB vmemmap
|
||||
ffffffffffe00000 ffffffffffffffff 2MB [保护区域]
|
||||
```
|
||||
|
||||
**4 KB 页面的转换查询表如下:**
|
||||
|
||||
```
|
||||
+--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
|
||||
+--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
| | | | | |
|
||||
| | | | | v
|
||||
| | | | | [11:0] 页内偏移量
|
||||
| | | | +-> [20:12] L3 索引
|
||||
| | | +-----------> [29:21] L2 索引
|
||||
| | +---------------------> [38:30] L1 索引
|
||||
| +-------------------------------> [47:39] L0 索引
|
||||
+-------------------------------------------------> [63] TTBR0/1
|
||||
```
|
||||
|
||||
**64 KB 页面的转换查询表如下:**
|
||||
|
||||
```
|
||||
+--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
|
||||
+--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
| | | | |
|
||||
| | | | v
|
||||
| | | | [15:0] 页内偏移量
|
||||
| | | +----------> [28:16] L3 索引
|
||||
| | +--------------------------> [41:29] L2 索引
|
||||
| +-------------------------------> [47:42] L1 索引 (48 位)
|
||||
| [51:42] L1 索引 (52 位)
|
||||
+-------------------------------------------------> [63] TTBR0/1
|
||||
```
|
||||
|
||||
![][5]
|
||||
|
||||
### 内核对 52 位虚拟地址的支持
|
||||
|
||||
因为支持 LVA 的较新的内核应该可以在旧的 CPU(硬件不支持 LVA 拓展)和新的 CPU(硬件支持 LVA 拓展)上都正常运行,因此采用的设计方法是使用单个二进制文件来支持 52 位(如果硬件不支持该特性,则必须在刚开始启动时能回退到 48 位)。也就是说,为了满足 52 位的虚拟地址以及固定大小的 `PAGE_OFFSET`,`VMEMMAP` 必须设置得足够大。
|
||||
|
||||
这样的设计方式要求内核为了新的虚拟地址空间而支持下面的变量:
|
||||
|
||||
```
|
||||
VA_BITS 常量 *最大的* 虚拟地址空间大小
|
||||
|
||||
vabits_actual 变量 *实际的* 虚拟地址空间大小
|
||||
```
|
||||
|
||||
因此,尽管 `VA_BITS` 设置了最大的虚拟地址空间大小,但实际上支持的虚拟地址空间大小由 `vabits_actual` 确定(具体取决于启动时的切换)。
|
||||
|
||||
#### 翻转内核内存布局
|
||||
|
||||
保持一个单一内核二进制文件的设计方法要求内核的 `.text` 位于高位地址中,因此它们对于 48/52 位虚拟地址是不变的。因为内核地址检测器(KASAN)区域仅占整个内核虚拟地址空间的一小部分,因此对于 48 位或 52 位的虚拟地址空间,KASAN 区域的末尾也必须在内核虚拟地址空间的上半部分。(从 48 位切换到 52 位,KASAN 区域的末尾是不变的,且依赖于 `~0UL`,而起始地址将“增长”到低位地址)
|
||||
|
||||
为了优化 `phys_to_virt()` 和 `virt_to_phys()`,页偏移量将被保持在 `0xFFF0000000000000` (对应于 52 位),这消除了读取额外变量的需求。在早期启动时将会计算 `physvirt` 和 `vmemmap` 偏移量以启用这个逻辑。
|
||||
|
||||
考虑下面的物理和虚拟 RAM 地址空间的转换:
|
||||
|
||||
```
|
||||
/*
|
||||
* 内核线性地址开始于虚拟地址空间的底部
|
||||
* 测试区域开始处的最高位已经是一个足够的检查,并且避免了担心标签的麻烦
|
||||
*/
|
||||
|
||||
#define virt_to_phys(addr) ({ \
|
||||
if (!(((u64)addr) & BIT(vabits_actual - 1))) \
|
||||
(((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
|
||||
})
|
||||
|
||||
#define phys_to_virt(addr) ((unsigned long)((addr) - PHYS_OFFSET) | PAGE_OFFSET)
|
||||
|
||||
在上面的代码中:
|
||||
PAGE_OFFSET — 线性映射的虚拟地址的起始位置位于 TTBR1 地址空间
|
||||
PHYS_OFFSET — 物理地址的起始位置以及 vabits_actual — *实际的*虚拟地址空间大小
|
||||
```
|
||||
|
||||
### 对用于调试内核的用户态程序的影响
|
||||
|
||||
有几个用户空间应用程序可以用于调试正在运行的/活动中的内核或者分析系统崩溃时的 vmcore 转储(例如确定内核奔溃的根本原因):kexec-tools、makedumpfile 和 crash-utility。
|
||||
|
||||
当用它们来调试 Arm64 内核时,因为 Arm64 内核内存映射被“翻转”,因此也会对它们产生影响。这些应用程序还需要遍历转换表以确定与虚拟地址相应的物理地址(类似于内核中的完成方式)。
|
||||
|
||||
相应地,在将“翻转”引入内核内存映射之后,由于上游破坏了用户态应用程序,因此必须对其进行修改。
|
||||
|
||||
我已经提议了对三个受影响的用户态应用程序的修复;有一些已经被上游接受,但其他仍在等待中:
|
||||
|
||||
* [提议 makedumpfile 上游的修复][6]
|
||||
* [提议 kexec-tools 上游的修复][7]
|
||||
* [已接受的 crash-utility 的修复][8]
|
||||
|
||||
除非在用户空间应用程序进行了这些修改,否则它们将仍然无法调试运行/活动中的内核或分析系统崩溃时的 vmcore 转储。
|
||||
|
||||
### 52 位用户态虚拟地址
|
||||
|
||||
为了保持与依赖 ARMv8.0 虚拟地址空间的最大为 48 位的用户空间应用程序的兼容性,在默认情况下内核会将虚拟地址从 48 位范围返回给用户空间。
|
||||
|
||||
通过指定大于 48 位的 mmap 提示参数,用户态程序可以“选择”从 52 位空间接收虚拟地址。
|
||||
|
||||
例如:
|
||||
|
||||
```
|
||||
.mmap_high_addr.c
|
||||
----
|
||||
|
||||
maybe_high_address = mmap(~0UL, size, prot, flags,...);
|
||||
```
|
||||
|
||||
通过启用以下的内核配置选项,还可以构建一个从 52 位空间返回地址的调试内核:
|
||||
|
||||
```
|
||||
CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y
|
||||
```
|
||||
|
||||
_请注意此选项仅用于调试应用程序,不应在实际生产中使用。_
|
||||
|
||||
### 结论
|
||||
|
||||
总结一下:
|
||||
|
||||
1. 内核版本从 5.14 开始,新的 Armv8.2 硬件拓展 LVA 和 LPA 在内核中得到良好支持。
|
||||
2. 像 kexec-tools 和 makedumpfile 被用来调试内核的用户态应用程序现在无法支持新拓展,仍在等待上游接受修补。
|
||||
3. 过去的用户态应用程序依赖于 Arm64 内核提供的 48 位虚拟地址将继续原样工作,而较新的用户态应用程序通构指定超过 48 位更大的 mmap 提示参数来 “选择加入”已接受来自 52 位的虚拟地址。
|
||||
|
||||
* * *
|
||||
|
||||
_这篇文章参考了 [AArch64 架构下的 Linux 内存布局][9] 和 [Linux 5.9.12 内核文档][10]。它们均为 GPLv2.0 许可。_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/52-bit-arm64-kernel
|
||||
|
||||
作者:[Bhupesh Sharma][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[萌新阿岩](https://github.com/mengxinayan)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/bhsharma
|
||||
[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://lwn.net/Articles/716916/
|
||||
[3]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm64/memory.rst
|
||||
[4]: https://developer.arm.com/documentation/ddi0487/latest/
|
||||
[5]: https://opensource.com/sites/default/files/arm64-multi-level-translation_0.png (arm64 Multi-level Translation)
|
||||
[6]: http://lists.infradead.org/pipermail/kexec/2020-September/021372.html
|
||||
[7]: http://lists.infradead.org/pipermail/kexec/2020-September/021333.html
|
||||
[8]: https://github.com/crash-utility/crash/commit/1c45cea02df7f947b4296c1dcaefa1024235ef10
|
||||
[9]: https://www.kernel.org/doc/html/latest/arm64/memory.html
|
||||
[10]: https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/memory.h
|
148
published/202101/20201230 Choose between Btrfs and LVM-ext4.md
Normal file
148
published/202101/20201230 Choose between Btrfs and LVM-ext4.md
Normal file
@ -0,0 +1,148 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13043-1.html)
|
||||
[#]: subject: (Choose between Btrfs and LVM-ext4)
|
||||
[#]: via: (https://fedoramagazine.org/choose-between-btrfs-and-lvm-ext4/)
|
||||
[#]: author: (Troy Curtis Jr https://fedoramagazine.org/author/troycurtisjr/)
|
||||
|
||||
Btrfs 和 LVM-ext4 该如何选择?
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/23/133137m2wfkiq8ykyvwyhv.jpg)
|
||||
|
||||
[Fedora 33][4] 在其各类桌面版本中引入了新的默认文件系统 [Btrfs][5]。多年以来,Fedora 一直在 <ruby>[逻辑卷管理][7]<rt>Logical Volume Manager</rt></ruby>(LVM) 卷之上使用 [ext4][6],引入 Brtfs 对 Fedora 来说是一个很大的转变。更改默认文件系统需要 [令人信服的原因][8]。虽然 Btrfs 是令人兴奋的下一代文件系统,但 LVM 上的 ext4 是成熟而稳定的。本指南旨在探索各自的高级特性,使得更容易在 Btrfs 和 LVM-ext4 之间进行选择。
|
||||
|
||||
### 先说结论
|
||||
|
||||
最简单的建议是坚持使用默认值。全新安装的 Fedora 33 环境默认为 Btrfs,升级之前的 Fedora 版本将继续使用最初安装的设置,通常是 LVM-ext4。对于现有的 Fedora 用户来说,获取 Btrfs 的最简单方式是全新安装。然而,全新安装比简单升级更具破坏性。除非有特殊需要,否则这种干扰可能是不必要的。Fedora 开发团队仔细考虑了这两个默认值,因此对任何一个选择都要有信心。
|
||||
|
||||
### 那么其他文件系统呢?
|
||||
|
||||
现在有很多 [Linux 系统的文件系统][9]。在加上卷管理器、加密方法和存储机制的组合后,这一数字呈爆炸式增长。那么,为什么要关注 btrfs 和 LVM-ext4 呢?对于 Fedora 的用户来说,这两种设置可能是最常见的。在 Fedora 11 中,LVM 之上的 ext4 成为了默认磁盘布局,在此之前则使用的是 ext3。
|
||||
|
||||
既然 Btrfs 是 Fedora 33 的默认设置,那么绝大多数现有用户会考虑是应该原地踏步还是向前跳跃。面对全新安装的 Fedora 33 环境,有经验的 Linux 用户可能会想知道是使用这个新的文件系统,还是退回到他们熟悉的文件系统。因此,在众多可能的存储选项中,许多 Fedora 用户会想知道如何在 Btrfs 和 LVM-ext4 之间进行选择。
|
||||
|
||||
### 两者的共性
|
||||
|
||||
尽管两个文件系统之间存在核心差异,但 Btrfs 和 LVM-ext4 实际上有很多共同之处。两者都是成熟且经过充分测试的存储技术。从 Fedora Core 的早期开始,就一直在使用 LVM,而 ext4 在 [2009 年成为 Fedora 11 的默认设置][10]。Btrfs 在 2009 年并入 Linux 主线内核,并且 [Facebook 广泛使用了该文件系统][11]。SUSE Linux Enterprise 12 [在 2014 年使其成为默认文件系统][12]。因此,它在生产环境中也有着长久的运行时间。
|
||||
|
||||
这两个系统都能很好地防止因意外停电而导致的文件系统损坏,尽管它们的实现方式不同。它们支持的配置包括使用单盘设置和跨越多个设备,并且这两种配置都能够创建近乎即时的快照。有各种工具可以帮助管理这两种系统,包括命令行和图形界面。这两种解决方案在家用台式机和高端服务器上都同样有效。
|
||||
|
||||
### LVM-ext4 的优势
|
||||
|
||||
![LVM 上 ext4 的结构][13]
|
||||
|
||||
[ext4 文件系统][14] 专注于高性能和可伸缩性,没有太多额外的花哨之处。它能有效地防止长时间后的碎片化,并当碎片化出现后提供了 [很好的工具][15]。ext4 之所以坚如磐石,是因为它构建在前代的 ext3 文件系统之上,带来了多年的系统内测试和错误修复。
|
||||
|
||||
LVM-ext4 环境中的大多数高级功能都来自 LVM 本身。LVM 位于文件系统的“下方”,这意味着它支持任何文件系统。<ruby>逻辑卷<rt>Logical volume</rt></ruby>(LV)是通用的块设备,因此 [虚拟机可以直接使用它们][16]。这种灵活性使得每个逻辑卷都可以使用合适的文件系统,用合适的选项应对各种情况。这种分层方法还遵循了“小工具协同工作”的 Unix 哲学。
|
||||
|
||||
从硬件抽象出来的<ruby>[卷组][17]<rt>volume group</rt></ruby>(VG)允许 LVM 创建灵活的逻辑卷。每个逻辑卷都提取自同一个存储池,但具有自己的设置。调整卷的大小比调整物理分区的大小容易得多,因为没有数据有序放置的限制。LVM <ruby>[物理卷][18]<rt>physical volume</rt></ruby>(PV)可以是任意数量的分区,甚至可以在系统运行时在设备之间移动。
|
||||
|
||||
LVM 支持只读和读写的 [快照][19],这使得从活动系统创建一致的备份变得很容易。每个快照都有一个定义的大小,更改源卷或快照卷将占用其中的空间。又或者,逻辑卷也可以是<ruby>[稀疏配置池][20]<rt>thinly provisioned pool</rt></ruby>的一部分。这允许快照自动使用池中的数据,而不是使用在创建卷时定义的固定大小的块。
|
||||
|
||||
#### 有多个磁盘驱动器的 LVM
|
||||
|
||||
当有多个设备时,LVM 才真正大放异彩。它原生支持大多数 [RAID 级别][21],每个逻辑卷可以具有不同的 RAID 级别。LVM 将自动为 RAID 配置选择适当的物理设备,或者用户可以直接指定它。基本的 RAID 支持包括用于性能的数据条带化([RAID0][22])和用于冗余的镜像([RAID1][23])。逻辑卷也可以使用 [RAID5][24]、[RAID6][25] 和 [RAID10][26] 等高级设置。LVM RAID 支持已经成熟,因为 LVM 在底层使用的 [设备映射器(dm)][27] 和 [多设备(md)][28] 内核支持, 与 [mdadm][29] 使用的一样。
|
||||
|
||||
对于具有快速和慢速驱动器的系统,逻辑卷也可以是 [缓存卷][30]。经典示例是 SSD 和传统磁盘驱动器的组合。缓存卷使用较快的驱动器来存储更频繁访问的数据(或用作写缓存),而慢速的驱动器则用于处理大量数据。
|
||||
|
||||
LVM 中大量稳定的功能以及 ext4 的可靠性在既往的使用中早已被证明了。当然,功能越多就越复杂。在配置 LVM 时,要找到合适的功能选项是很有挑战性的。对于单驱动器的台式机系统,LVM 的功能(例如 RAID 和缓存卷)不适用。但是,逻辑卷比物理分区更灵活,快照也很有用。对于正常的桌面使用,LVM 的复杂性会成为典型的用户可能遇到的问题恢复的障碍。
|
||||
|
||||
### Btrfs 的优势
|
||||
|
||||
![Btrfs 结构][31]
|
||||
|
||||
从前几代文件系统中学到的经验指导了构建到 [Btrfs][5] 的功能设计。与 ext4 不同,它可以直接跨越多个设备,因此它具有通常仅在卷管理器中才能找到的功能。它还具有 Linux 文件系统空间中独有的功能([ZFS][32] 具有相似的功能集,但[不要指望它在 Linux 内核中出现][33])。
|
||||
|
||||
#### Btrfs 的主要功能
|
||||
|
||||
也许最重要的功能是对所有数据进行<ruby>校验和<rt>checksumming</rt></ruby>。校验和与<ruby>[写时复制][37]<rt>copy-on-write</rt></ruby>(COW)一起,提供了在意外断电后确保文件系统完整性的 [关键方法][34]。更独特的是,校验和可以检测数据本身中的错误。悄然的数据损坏(有时也称为 [bitrot][35])比大多数人意识到的更常见。如果没有主动验证,损坏最终可能会传播到所有可用的备份中。这使得用户没有有效的副本。通过透明地校验所有数据,Btrfs 能够立即检测到任何此类损坏。启用正确的 [dup 或 raid 选项][36],文件系统也可以透明地修复损坏。
|
||||
|
||||
写时复制也是 Btrfs 的基本功能,因为它在提供文件系统完整性和即时子卷快照方面至关重要。从公共子卷创建快照后,快照会自动共享底层数据。另外,事后的<ruby>[重复数据删除][38]<rt>deduplication</rt></ruby> 使用相同的技术来消除相同的数据块。单个文件可以通过使用 `cp` 的 [reflink 选项][39] 来使用 COW 功能。reflink 副本对于复制大型文件(例如虚拟机镜像)特别有用,这些文件往往随着时间的推移具有大部分相同的数据。
|
||||
|
||||
Btrfs 支持跨越多个设备,而无需卷管理器。多设备支持可提供数据镜像功能以实现冗余和条带化以提高性能。此外,还实验性地支持更高级的 RAID 级别,例如 [RAID 5][24] 和 [RAID 6][25]。与标准 RAID 设置不同,Btrfs 的 RAID1 实际上允许奇数个设备。例如,它可以使用 3 个设备,即使它们的大小不同。
|
||||
|
||||
所有 RAID 和 dup 选项都是在文件系统级别指定的。因此,各个子卷不能使用不同的选项。请注意,使用多设备的 RAID1 选项意味着即使一个设备发生故障,卷中的所有数据都是可用的,并且校验功能可以保持数据本身的完整性。这超出了当前典型的 RAID 设置所能提供的范围。
|
||||
|
||||
#### 附加功能
|
||||
|
||||
Btrfs 还支持快速简便的远程备份。子卷快照可以 [发送到远程系统][40] 进行存储。通过利用文件系统中固有的 COW 元数据,这些传输通过仅发送先前发送的快照中的增量更改而非常有效。诸如 [snapper][41] 之类的用户应用程序使管理这些快照变得容易。
|
||||
|
||||
另外,Btrfs 卷可以具有 [透明压缩][42] 功能,并且 [chattr +c][43] 可以标记进行压缩的单个文件或目录。压缩不仅可以减少数据消耗的空间,还可以通过减少写入操作量来帮助延长 SSD 的寿命。压缩当然会带来额外的 CPU 开销,但是有很多选项就可以权衡取舍。
|
||||
|
||||
Btrfs 集成了文件系统和卷管理器功能,这意味着总体维护比 LVM-ext4 更简单。当然,这种集成的灵活性较低,但是对于大多数台式机甚至服务器而言,设置已足够。
|
||||
|
||||
### LVM 上使用 Btrfs
|
||||
|
||||
Btrfs 可以 [就地转换 ext3/ext4 文件系统][44]。就地转换意味着无需将数据复制出来然后再复制回去。数据块本身甚至都不需要修改。因此,对于现有的 LVM-ext4 系统,一种选择是将 LVM 保留在原处,然后简单地将 ext4 转换为 Btrfs。虽然可行且受支持,但有一些原因使它不是最佳选择。
|
||||
|
||||
Btrfs 的吸引力之一是与卷管理器集成的文件系统所带来的更轻松的管理。要是在 LVM 之上运行,对于系统维护,仍然要对额外的卷管理器进行一些设置。同样,LVM 设置通常具有多个固定大小的逻辑卷,并具有独立文件系统。虽然 Btrfs 支持给定的计算机上的多个卷,但是许多不错的功能都需要单一卷具有多个子卷。如果每个 LVM 卷都有一个独立的 Btrfs 卷,则用户仍然需要手动管理固定大小的 LVM 卷。虽然能够收缩挂载的 Btrfs 文件系统的能力确实使处理固定大小的卷的工作变得更轻松。通过在线收缩功能,就无需启动 [实时镜像][45] 了。
|
||||
|
||||
在使用 Btrfs 的多设备支持时,必须仔细考虑逻辑卷的物理位置。对于 Btrfs 而言,每个逻辑卷都是一个单独的物理设备,如果实际情况并非如此,则某些数据可用性功能可能会做出错误的决定。例如,如果单个驱动器发生故障,对数据使用 RAID1 通常可以提供保护。如果实际逻辑卷在同一物理设备上,则没有冗余。
|
||||
|
||||
如果强烈需要某些特定的 LVM 功能,例如原始块设备或高速缓存的逻辑卷,则在 LVM 之上运行 Btrfs 是有意义的。在这种配置下,Btrfs 仍然提供其大多数优点,例如校验和和易于发送的增量快照。尽管使用 LVM 会产生一些操作开销,但 Btrfs 的这种开销并不比任何其他文件系统大。
|
||||
|
||||
### 总结
|
||||
|
||||
当尝试在 Btrfs 和 LVM-ext4 之间进行选择时,没有一个正确的答案。每个用户都有独特的要求,并且同一用户可能拥有具有不同需求的不同系统。看一下每个配置的功能集,并确定是否有令人心动的功能。如果没有,坚持默认值没有错。选择这两种设置都有很好的理由。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/choose-between-btrfs-and-lvm-ext4/
|
||||
|
||||
作者:[Troy Curtis Jr][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[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/12/btrfs-lvm-ext4-816x345.jpg
|
||||
[2]: https://unsplash.com/@raulpetri?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
[3]: https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
[4]: https://fedoramagazine.org/announcing-fedora-33/
|
||||
[5]: https://btrfs.wiki.kernel.org/index.php/Main_Page
|
||||
[6]: https://ext4.wiki.kernel.org/index.php/Main_Page
|
||||
[7]: https://man7.org/linux/man-pages/man8/lvm.8.html
|
||||
[8]: https://fedoraproject.org/wiki/Changes/BtrfsByDefault
|
||||
[9]: https://man7.org/linux/man-pages/man5/filesystems.5.html
|
||||
[10]: https://docs.fedoraproject.org/en-US/Fedora/11/html/Release_Notes/index.html#sect-Release_Notes-Fedora_11_Overview
|
||||
[11]: https://facebookmicrosites.github.io/btrfs/docs/btrfs-facebook.html
|
||||
[12]: https://www.suse.com/releasenotes/x86_64/SUSE-SLES/12/#fate-317221
|
||||
[13]: https://fedoramagazine.org/wp-content/uploads/2020/12/ext4-on-LVM.jpg
|
||||
[14]: https://opensource.com/article/18/4/ext4-filesystem
|
||||
[15]: https://man7.org/linux/man-pages/man8/e4defrag.8.html
|
||||
[16]: https://libvirt.org/storage.html#StorageBackendLogical
|
||||
[17]: https://www.redhat.com/sysadmin/create-volume-group
|
||||
[18]: https://www.redhat.com/sysadmin/create-physical-volume
|
||||
[19]: https://tldp.org/HOWTO/LVM-HOWTO/snapshotintro.html
|
||||
[20]: https://man7.org/linux/man-pages/man7/lvmthin.7.html
|
||||
[21]: https://rhea.dev/articles/2018-08/LVM-RAID-on-Fedora
|
||||
[22]: https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_0
|
||||
[23]: https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_1
|
||||
[24]: https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_5
|
||||
[25]: https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_6
|
||||
[26]: https://en.wikipedia.org/wiki/Non-standard_RAID_levels#Linux_MD_RAID_10
|
||||
[27]: https://man7.org/linux/man-pages/man8/dmsetup.8.html
|
||||
[28]: https://man7.org/linux/man-pages/man4/md.4.html
|
||||
[29]: https://fedoramagazine.org/managing-raid-arrays-with-mdadm/
|
||||
[30]: https://man7.org/linux/man-pages/man7/lvmcache.7.html
|
||||
[31]: https://fedoramagazine.org/wp-content/uploads/2020/12/Btrfs-Volume.jpg
|
||||
[32]: https://en.wikipedia.org/wiki/ZFS
|
||||
[33]: https://itsfoss.com/linus-torvalds-zfs/
|
||||
[34]: https://btrfs.wiki.kernel.org/index.php/FAQ#Can_I_have_nodatacow_.28or_chattr_.2BC.29_but_still_have_checksumming.3F
|
||||
[35]: https://arstechnica.com/information-technology/2014/01/bitrot-and-atomic-cows-inside-next-gen-filesystems/
|
||||
[36]: https://man7.org/linux/man-pages/man8/mkfs.btrfs.8.html#DUP_PROFILES_ON_A_SINGLE_DEVICE
|
||||
[37]: https://en.wikipedia.org/wiki/Copy-on-write
|
||||
[38]: https://btrfs.wiki.kernel.org/index.php/Deduplication
|
||||
[39]: https://btrfs.wiki.kernel.org/index.php/UseCases#How_do_I_copy_a_large_file_and_utilize_COW_to_keep_it_from_actually_being_copied.3F
|
||||
[40]: https://fedoramagazine.org/btrfs-snapshots-backup-incremental/
|
||||
[41]: http://snapper.io/
|
||||
[42]: https://btrfs.wiki.kernel.org/index.php/Compression
|
||||
[43]: https://www.man7.org/linux/man-pages/man1/chattr.1.html
|
||||
[44]: https://btrfs.wiki.kernel.org/index.php/Conversion_from_Ext3
|
||||
[45]: https://fedoramagazine.org/reclaim-hard-drive-space-with-lvm/
|
306
published/202101/20201231 Build your own text editor in Java.md
Normal file
306
published/202101/20201231 Build your own text editor in Java.md
Normal file
@ -0,0 +1,306 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13038-1.html)
|
||||
[#]: subject: (Build your own text editor in Java)
|
||||
[#]: via: (https://opensource.com/article/20/12/write-your-own-text-editor)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
使用 Java 构建你自己的文本编辑器
|
||||
======
|
||||
|
||||
> 有时候,除你自己外,没有人能制作你所梦想的工具。以下是如何开始构建你自己的文本编辑器。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/21/134710uzumn6ej36u7t79j.jpg)
|
||||
|
||||
有很多文本编辑器。有运行在终端中、运行在 GUI 中、运行在浏览器和浏览器引擎中的。有很多是还不错,有一些则是极好的。但是有时候,毫无疑问,最令人满意的就是你自己构建的编辑器。
|
||||
|
||||
毫无疑问:构建一个真正优秀的文本编辑器比表面上看上去要困难得多。但话说回来,建立一个基本的文本编辑器也不像你担心的那样难。事实上,大多数编程工具包已经为你准备好了文本编辑器的大部分组件。围绕文本编辑的组件,例如菜单条,文件选择对话框等等,是很容易落到实处。因此,虽然是中级的编程课程,但构建一个基本的文本编辑器是出乎意料的有趣和简明。你可能会发现自己渴望使用一个自己构造的工具,而且你使用得越多,你可能会有更多的灵感来增加它的功能,从而更多地学习你正在使用的编程语言。
|
||||
|
||||
为了使这个练习切合实际,最好选择一种具有令人满意的 GUI 工具箱的语言。有很多种选择,包括 Qt 、FLTK 或 GTK ,但是一定要先评审一下它的文档,以确保它有你所期待的功能。对于这篇文章来说,我使用 Java 以及其内置的 Swing 小部件集。如果你想使用一种不同的语言或者一种不同的工具集,这篇文章在如何帮你处理这种问题的方面也仍然是有用的。
|
||||
|
||||
不管你选择哪一种,在任何主要的工具箱中编写一个文本编辑器都是惊人的相似。如果你是 Java 新手,需要更多关于开始的信息,请先阅读我的 [猜谜游戏文章][2] 。
|
||||
|
||||
### 工程设置
|
||||
|
||||
通常,我使用并推荐像 [Netbeans][3] 或 Eclipse 这样的 IDE,但我发现,当学习一种新的语言时,手工做一些工作是很有帮助的,这样你就能更好地理解使用 IDE 时被隐藏起来的东西。在这篇文章中,我假设你正在使用文本编辑器和终端进行编程。
|
||||
|
||||
在开始前,为你自己的工程创建一个工程目录。在工程文件夹中,创建一个名称为 `src` 的目录来容纳你的源文件。
|
||||
|
||||
```
|
||||
$ mkdir -p myTextEditor/src
|
||||
$ cd myTextEditor
|
||||
```
|
||||
|
||||
在你的 `src` 目录中创建一个名称为 `TextEdit.java` 的空白的文件:
|
||||
|
||||
```
|
||||
$ touch src/TextEditor.java
|
||||
```
|
||||
|
||||
在你最喜欢的文本编辑器中打开这个空白的文件(我的意思是除你自己编写之外的最喜欢的一款文本编辑器),然后准备好编码吧!
|
||||
|
||||
### 包和导入
|
||||
|
||||
为确保你的 Java 应用程序有一个唯一的标识符,你必须声明一个 `package` 名称。典型的格式是使用一个反向的域名,如果你真的有一个域名的话,这就特别容易了。如果你没有域名的话,你可以使用 `local` 作为最顶层。像 Java 和很多语言一样,行以分号结尾。
|
||||
|
||||
在命名你的 Java 的 `package` 后,你必须告诉 Java 编译器(`javac`)使用哪些库来构建你的代码。事实上,这通常是你边编写代码边添加的内容,因为你很少事先知道你自己所需要的库。然而,这里有一些库是显而易见的。例如,你知道这个文本编辑器是基于 Swing GUI 工具箱的,因此,导入 `javax.swing.JFrame` 和`javax.swing.UIManager` 和其它相关的特定库。
|
||||
|
||||
```
|
||||
package com.example.textedit;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Scanner;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
```
|
||||
|
||||
对于这个练习的目标,你可以提前预知你所需要的所有的库。在真实的生活中,不管你喜欢哪一种语言,你都将在研究如何解决一些问题的时候发现库,然后,你将它导入到你的代码中,并使用它。不需要担心 —— 如果你忘记包含一个库,你的编译器或解释器将警告你!
|
||||
|
||||
### 主窗口
|
||||
|
||||
这是一个单窗口应用程序,因此这个应用程序的主类是一个 `JFrame` ,其附带有一个捕捉菜单事件的 `ActionListener` 。在 Java 中,当你使用一个现有的小部件元素时,你可以使用你的代码“扩展”它。这个主窗口需要三个字段:窗口本身(一个 `JFrame` 的实例)、一个用于文件选择器返回值的标识符和文本编辑器本身(`JTextArea`)。
|
||||
|
||||
```
|
||||
public final class TextEdit extends JFrame implements ActionListener {
|
||||
private static JTextArea area;
|
||||
private static JFrame frame;
|
||||
private static int returnValue = 0;
|
||||
```
|
||||
|
||||
令人惊奇的是,这数行代码完成了实现一个基本文本编辑器的 80% 的工作,因为 `JtextArea` 是 Java 的文本输入字段。剩下的 80 行代码大部分用于处理辅助功能,比如保存和打开文件。
|
||||
|
||||
### 构建一个菜单
|
||||
|
||||
`JMenuBar` 小部件被设计到 JFrame 的顶部,它为你提供你想要的很多菜单项。Java 不是一种
|
||||
拖放式的编程语言,因此,对于你所添加的每一个菜单,你都还必须编写一个函数。为保持这个工程的可控性,我提供了四个函数:创建一个新的文件,打开一个现有的文件,保存文本到一个文件,和关闭应用程序。
|
||||
|
||||
在大多数流行的工具箱中,创建一个菜单的过程基本相同。首先,你创建菜单条本身,然后创建一个顶级菜单(例如 “File” ),再然后创建子菜单项(例如,“New”、“Save” 等)。
|
||||
|
||||
```
|
||||
public TextEdit() { run(); }
|
||||
|
||||
public void run() {
|
||||
frame = new JFrame("Text Edit");
|
||||
|
||||
// Set the look-and-feel (LNF) of the application
|
||||
// Try to default to whatever the host system prefers
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
|
||||
Logger.getLogger(TextEdit.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
// Set attributes of the app window
|
||||
area = new JTextArea();
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.add(area);
|
||||
frame.setSize(640, 480);
|
||||
frame.setVisible(true);
|
||||
|
||||
// Build the menu
|
||||
JMenuBar menu_main = new JMenuBar();
|
||||
|
||||
JMenu menu_file = new JMenu("File");
|
||||
|
||||
JMenuItem menuitem_new = new JMenuItem("New");
|
||||
JMenuItem menuitem_open = new JMenuItem("Open");
|
||||
JMenuItem menuitem_save = new JMenuItem("Save");
|
||||
JMenuItem menuitem_quit = new JMenuItem("Quit");
|
||||
|
||||
menuitem_new.addActionListener(this);
|
||||
menuitem_open.addActionListener(this);
|
||||
menuitem_save.addActionListener(this);
|
||||
menuitem_quit.addActionListener(this);
|
||||
|
||||
menu_main.add(menu_file);
|
||||
|
||||
menu_file.add(menuitem_new);
|
||||
menu_file.add(menuitem_open);
|
||||
menu_file.add(menuitem_save);
|
||||
menu_file.add(menuitem_quit);
|
||||
|
||||
frame.setJMenuBar(menu_main);
|
||||
}
|
||||
```
|
||||
|
||||
现在,所有剩余的工作是实施菜单项所描述的功能。
|
||||
|
||||
### 编程菜单动作
|
||||
|
||||
你的应用程序响应菜单选择,是因为你的 `JFrame` 有一个附属于它的 `ActionListener` 。在 Java 中,当你实施一个事件处理程序时,你必须“重写”其内建的函数。这只是听起来可怕。你不是在重写 Java;你只是在实现已经被定义但尚未实施事件处理程序的函数。
|
||||
|
||||
在这种情况下,你必须重写 `actionPerformed`方法。因为在 “File” 菜单中的所有条目都与处理文件有关,所以在我的代码中很早就定义了一个 `JFileChooser` 。代码其它部分被划分到一个 `if` 语句的子语句中,这起来像接收到什么事件就相应地执行什么动作。每个子语句都与其它的子语句完全不同,因为每个项目都标示着一些完全唯一的东西。最相似的是 “Open” 和 “Save”,因为它们都使用 `JFileChooser` 选择文件系统中的一个位置来获取或放置数据。
|
||||
|
||||
“New” 菜单会在没有警告的情况下清理 JTextArea ,“Quit” 菜单会在没有警告的情况下关闭应用程序。这两个 “功能” 都是不安全的,因此你应该想对这段代码进行一点改善,这是一个很好的开始。在内容还没有被保存前,一个友好的警告是任何一个好的文本编辑器都必不可少的一个功能,但是在这里为了简单,这是未来的一个功能。
|
||||
|
||||
```
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String ingest = null;
|
||||
JFileChooser jfc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
|
||||
jfc.setDialogTitle("Choose destination.");
|
||||
jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
|
||||
String ae = e.getActionCommand();
|
||||
if (ae.equals("Open")) {
|
||||
returnValue = jfc.showOpenDialog(null);
|
||||
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
||||
File f = new File(jfc.getSelectedFile().getAbsolutePath());
|
||||
try{
|
||||
FileReader read = new FileReader(f);
|
||||
Scanner scan = new Scanner(read);
|
||||
while(scan.hasNextLine()){
|
||||
String line = scan.nextLine() + "\n";
|
||||
ingest = ingest + line;
|
||||
}
|
||||
area.setText(ingest);
|
||||
}
|
||||
catch ( FileNotFoundException ex) { ex.printStackTrace(); }
|
||||
}
|
||||
// 保存
|
||||
} else if (ae.equals("Save")) {
|
||||
returnValue = jfc.showSaveDialog(null);
|
||||
try {
|
||||
File f = new File(jfc.getSelectedFile().getAbsolutePath());
|
||||
FileWriter out = new FileWriter(f);
|
||||
out.write(area.getText());
|
||||
out.close();
|
||||
} catch (FileNotFoundException ex) {
|
||||
Component f = null;
|
||||
JOptionPane.showMessageDialog(f,"File not found.");
|
||||
} catch (IOException ex) {
|
||||
Component f = null;
|
||||
JOptionPane.showMessageDialog(f,"Error.");
|
||||
}
|
||||
} else if (ae.equals("New")) {
|
||||
area.setText("");
|
||||
} else if (ae.equals("Quit")) { System.exit(0); }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
从技术上来说,这就是这个文本编辑器的全部。当然,并没有真正做什么,除此之外,在这里仍然有测试和打包步骤,因此仍然有很多时间来发现缺少的必需品。假设你没有注意到提示:在这段代码中 _肯定_ 缺少一些东西。你现在知道缺少的是什么吗?(在 [猜谜游戏文章][4] 中被大量的提到。)
|
||||
|
||||
### 测试
|
||||
|
||||
你现在可以测试你的应用程序。从终端中启动你所编写的文本编辑器:
|
||||
|
||||
```
|
||||
$ java ./src/TextEdit.java
|
||||
error: can’t find main(String[]) method in class: com.example.textedit.TextEdit
|
||||
```
|
||||
|
||||
它看起来像在代码中没有获得 `main` 方法。这里有一些方法来修复这个问题:你可以在 `TextEdit.java` 中创建一个 `main` 方法,并让它运行一个 `TextEdit` 类实例,或者你可以创建一个单独的包含 `main` 方法的文件。两种方法都可以工作,但从大型工程的预期来看,使用后者更为明智,因此,使用单独的文件与其一起工作使之成为一个完整的应用程序的方法是值得使用的。
|
||||
|
||||
在 `src` 中创建一个 `Main.java` 文件,并在最喜欢的编辑器中打开:
|
||||
|
||||
```
|
||||
package com.example.textedit;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
TextEdit runner = new TextEdit();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你可以再次尝试,但是现在有两个相互依赖的文件要运行,因此你必须编译代码。Java 使用 `javac` 编译器,并且你可以使用 `-d` 选项来设置目标目录:
|
||||
|
||||
```
|
||||
$ javac src/*java -d .
|
||||
```
|
||||
|
||||
这会在你的软件包名称 `com/example/textedit` 后创建一个准确地模型化的新的目录结构。这个新的类路径包含文件 `Main.class` 和 `TextEdit.class` ,这两个文件构成了你的应用程序。你可以使用 `java` 并通过引用你的 Main 类的位置和 _名称_(非文件名称)来运行它们:
|
||||
|
||||
```
|
||||
$ java info/slackermedia/textedit/Main`
|
||||
```
|
||||
|
||||
你的文本编辑器打开了,你可以在其中输入文字,打开文件,甚至保存你的工作。
|
||||
|
||||
![带有单个下拉菜单的白色文本编辑器框,有 File、New、Open、Save 和 Quit 菜单][5]
|
||||
|
||||
### 以 Java 软件包的形式分享你的工作
|
||||
|
||||
虽然一些程序员似乎看起来认可以各种各样的源文件的形式分发软件包,并鼓励其他人来学习如何运行它,但是,Java 让打包应用程序变得真地很容易,以至其他人可以很容易的运行它。你已经有了必备的大部分结构体,但是你仍然需要一些元数据到一个 `Manifest.txt` 文件中:
|
||||
|
||||
```
|
||||
$ echo "Manifest-Version: 1.0" > Manifest.txt
|
||||
```
|
||||
|
||||
用于打包的 `jar` 命令,与 [tar][6] 命令非常相似,因此很多选项对你来说可能会很熟悉。要创建一个 JAR 文件:
|
||||
|
||||
```
|
||||
$ jar cvfme TextEdit.jar
|
||||
Manifest.txt
|
||||
com.example.textedit.Main
|
||||
com/example/textedit/*.class
|
||||
```
|
||||
|
||||
根据命令的语法,你可以推测出它会创建一个新的名称为 `TextEdit.jar` 的 JAR 文件,它所需要的清单数据位于 `Manifest.txt` 中。它的主类被定义为软件包名称的一个扩展,并且类自身是 `com/example/textedit/Main.class` 。
|
||||
|
||||
你可以查看 JAR 文件的内容:
|
||||
|
||||
```
|
||||
$ jar tvf TextEdit.jar
|
||||
0 Wed Nov 25 META-INF/
|
||||
105 Wed Nov 25 META-INF/MANIFEST.MF
|
||||
338 Wed Nov 25 com/example/textedit/textedit/Main.class
|
||||
4373 Wed Nov 25 com/example/textedit/textedit/TextEdit.class
|
||||
```
|
||||
|
||||
如果你想看看你的元数据是如何被集成到 `MANIFEST.MF` 文件中的,你甚至可以使用 `xvf` 选项来提取它。
|
||||
|
||||
使用 `java` 命令来运行你的 JAR 文件:
|
||||
|
||||
```
|
||||
$ java -jar TextEdit.jar
|
||||
```
|
||||
|
||||
你甚至可以 [创建一个桌面文件][7] ,这样,在单击应用程序菜单中的图标时,应用程序就会启动。
|
||||
|
||||
### 改进它
|
||||
|
||||
在当前状态下,这是一个非常基本的文本编辑器,最适合做快速笔记或简短自述文档。一些改进(比如添加垂直滚动条)只要稍加研究就能快速简单地完成,而另一些改进(比如实现一个广泛的偏好系统)则需要真正的工作。
|
||||
|
||||
但如果你一直在想学一种新的语言,这可能是一个完美的自我学习实用工程。创建一个文本编辑器,如你所见,它在代码方面并不难对付,它在一定范围是可控的。如果你经常使用文本编辑器,那么编写你自己的文本编辑器可能会使你满意和乐趣。因此打开你最喜欢的文本编辑器(你写的那个),开始添加功能吧!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/write-your-own-text-editor
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [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/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
|
||||
[2]: https://opensource.com/article/20/12/learn-java
|
||||
[3]: https://opensource.com/article/20/12/netbeans
|
||||
[4]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+component
|
||||
[5]: https://opensource.com/sites/default/files/uploads/this-time-its-personal-31_days_yourself-opensource.png (White text editor box with single drop down menu with options File, New, Open, Save, and Quit)
|
||||
[6]: https://opensource.com/article/17/7/how-unzip-targz-file
|
||||
[7]: https://opensource.com/article/18/1/how-install-apps-linux
|
@ -1,22 +1,22 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13046-1.html)
|
||||
[#]: subject: (4 lines of code to improve your Ansible play)
|
||||
[#]: via: (https://opensource.com/article/21/1/improve-ansible-play)
|
||||
[#]: author: (Jeff Warncia https://opensource.com/users/jeffwarncia)
|
||||
|
||||
4 行代码提高你的 Ansible 剧本
|
||||
改进你的 Ansible 剧本的 4 行代码
|
||||
======
|
||||
|
||||
> 只要付出一点点努力,你就可以帮助下一个人,不只是绘制出安全路径,还可以留下危险的警告。
|
||||
|
||||
![一个人编程][1]
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/23/225612fowskoyyk1gtwtog.jpg)
|
||||
|
||||
在博客圈里,人们对基础架构即代码、持续集成/持续交付(CI/CD)管道、代码审查和测试制度赞不绝口,但人们很容易忘记,这种精心设计的象牙塔只是一种理想,而不是现实。虽然不完美的系统困扰着我们,但我们必须交付一些东西。
|
||||
|
||||
在系统自动化的过程中,很少有比那些通过粘合 API 创建的象牙塔更脆弱的塔。这是一个脆弱的世界。要让它“工作起来”,交付它,然后继续前进,压力是巨大的。
|
||||
在系统自动化的过程中,很少有比那些通过粘合 API 创建的象牙塔更脆弱的塔。这是一个脆弱的世界。要让它“工作起来”,交付它,然后继续前进,压力巨大。
|
||||
|
||||
### 要解决的问题
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
_query: "name={{ vlan_parent_view_name }}"
|
||||
```
|
||||
|
||||
最终,它进行了一个 REST 调用。这将“返回” 一个 JSON,按照惯例,为了便于在角色外访问,我把它填充进了`_otherthing_search_result` 中,。`search_for.yml` 的实现是抽象的,它总是返回一个包含零或多个结果的字典。
|
||||
最终,它进行了一个 REST 调用。这将“返回” 一个 JSON,按照惯例,为了便于在角色外访问,我把它填充进了 `_otherthing_search_result` 中,。`search_for.yml` 的实现是抽象的,它总是返回一个包含零或多个结果的字典。
|
||||
|
||||
正如我读过的几乎所有真实世界的 Ansible 代码所证明的那样,大多数 Ansible 开发者将会继续前进,好像一切都很好,并且可以直接访问预期的单个结果:
|
||||
|
||||
@ -86,7 +86,7 @@ _“好吧,不要这样做。这是一个没有哑巴的场所。不要那么
|
||||
|
||||
而如果我出门了呢?如果我把代码交给了一个运维团队,也许是一个实习生通过 [Tower][3] 来运行,把 `vlan_view_name` 手动输入到表单之类的东西呢?那第 30 行出的问题是对他们没有帮助的。
|
||||
|
||||
你说,加注释吧! 嗯,是的。我可以在代码中写一些梗概,以帮助下周或下个月的开发人员。这对运行代码的人没有帮助,他的工作刚刚失败,当然对于企业也无济于事。
|
||||
你说,加注释吧! 嗯,是的。我可以在代码中写一些梗概,以帮助下周或下个月的开发人员。这对运行代码的人没有帮助,他的“工作”刚刚失败,当然对于企业也无济于事。
|
||||
|
||||
记住,我们此刻无所不能。在写代码或者跳过写代码的时候,我们是站在实力和知识的立场上进行的。我们花了几个小时,甚至几天的时间,研究了文档、现实、其他 bug、其他问题,我们留下了代码、注释,甚至可能还有文档。我们写的代码是分享成功的,而成功正是我们用户想要的。但是在这种学习中也有很多失败的地方,我们也可以留下这些。
|
||||
|
@ -1,48 +1,50 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13033-1.html)
|
||||
[#]: subject: (Improve your productivity with this lightweight Linux desktop)
|
||||
[#]: via: (https://opensource.com/article/21/1/elementary-linux)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
使用这个轻量级 Linux 桌面提高你的工作效率
|
||||
ElementaryOS:使用这个轻量级 Linux 桌面提高你的工作效率
|
||||
======
|
||||
ElementaryOS 提供了一个快速、轻量、高效的桌面,让你在新的一年里保持工作效率。
|
||||
![Business woman on laptop sitting in front of window][1]
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第一天。
|
||||
> ElementaryOS 提供了一个快速、轻量、高效的桌面,让你在新的一年里保持工作效率。
|
||||
|
||||
当寻求提高生产率的工具时,很容易将几乎可以但不能完全很好地发挥作用的应用集合在一起。在过去的几年里,我们已经谈到了单个的电子邮件应用、日历应用、记事本应用等等。不过,总会有些麻烦。要么需要自定义脚本,要么需要复杂的导出/导入步骤来使一个工具工作。
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/19/235403miy29qe6rqvv2vl3.jpg)
|
||||
|
||||
在前几年,这个年度系列报道了各个应用程序。今年,我们将在 2021 年寻求帮助的策略之外,还将关注一站式解决方案。欢迎来到 2021 年 21 天生产力的第一天。
|
||||
|
||||
当寻求提高生产率的工具时,很容易将几乎能用但不能完全很好地发挥作用的应用集合在一起。在过去的几年里,我们已经谈到了单个的电子邮件应用、日历应用、记事本应用等等。不过,总会有些麻烦。要么需要自定义脚本,要么需要复杂的导出/导入步骤才能使一个工具工作。
|
||||
|
||||
[ElementaryOS][2] 是一个完整的桌面,具有美观、实用、高效的环境。
|
||||
|
||||
![Linux ElementaryOS Desktop][3]
|
||||
|
||||
ElementaryOS 桌面 (Kevin Sonney, [CC BY-SA 4.0][4])
|
||||
*ElementaryOS 桌面 (Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
ElementaryOS 是一个基于流行的 Ubuntu Linux 发行版的“按需付费”开源项目。对于过去安装过 Ubuntu 的人来说,最初的设置和安装会非常熟悉。然而,一旦登录,体验就会很不一样。
|
||||
ElementaryOS 是一个基于流行的 Ubuntu Linux 发行版的“按需付费”开源项目。对于过去安装过 Ubuntu 的人来说,初始设置和安装会非常熟悉。然而,一旦登录,体验就会很不一样。
|
||||
|
||||
ElementaryOS 使用 [Gala 窗口管理器][5]和 Pantheon shell。这两个都是专门为 Elementary 开发的。安装后,桌面非常简单,它只提供了少量的轻量级应用。这些应用包括网络浏览器、终端、邮件客户端和日历客户端。它还有一个应用中心,允许你安装 Elementary 团队策划的免费和商业应用。
|
||||
ElementaryOS 使用 [Gala 窗口管理器][5]和 Pantheon shell。这两个都是专门为 Elementary 开发的。安装后,桌面非常精简,它只提供了少量的轻量级应用。这些应用包括 Web 浏览器、终端、邮件客户端和日历客户端。它还有一个应用中心,允许你安装 Elementary 团队策划的免费和商业应用。
|
||||
|
||||
![Linux ElementaryOS Mail and calendar][6]
|
||||
|
||||
ElementaryOS 的邮件和日历应用(Kevin Sonney, [CC BY-SA 4.0][4])
|
||||
*ElementaryOS 的邮件和日历应用(Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
[邮件][7]和[日历][8]这两个应用看起来很熟悉,因为这两个应用已经被其他发行版使用了一段时间。邮件是作为 [Geary][9] 的分支开始的,而日历在其他地方则被称为 [Maya][10]。两者的设置非常简单。两款应用默认只用用户名/密码认证,所以需要双因素认证的用户需要一些额外的步骤。两者的界面都异常轻巧快速。
|
||||
[邮件][7]和[日历][8]这两个应用看起来很熟悉,因为这两个应用已经被其他发行版使用了一段时间。邮件是作为 [Geary][9] 的复刻分支开始的,而日历在其他地方则被称为 [Maya][10]。两者的设置非常简单。两款应用默认仅使用用户名/密码认证,所以需要双因素认证的用户需要一些额外的步骤。两者的界面都异常轻巧快速。
|
||||
|
||||
![Linux ElementaryOS app center][11]
|
||||
|
||||
应用中心(Kevin Sonney,[CC BY-SA 4.0][4])
|
||||
*应用中心(Kevin Sonney,[CC BY-SA 4.0][4])*
|
||||
|
||||
ElementaryOS 默认不包含待办事项或记事本应用。这时,应用中心就可以发挥作用了。在应用中心中,有大量的应用可以填补空白。其中有两款应用真的很突出。第一个是 [Planner][12],一款简洁、轻量级的待办事项管理器。它支持多个列表、计划和重复性任务、项目和子项目。它还可以与流行的在线应用 [Todoist][13] 同步,但这不是必需的。
|
||||
ElementaryOS 默认不包含待办事项或记事本应用。这时,应用中心就可以发挥作用了。在应用中心中,有大量的应用可以填补空白。其中有两款应用真的很出色。第一个是 [Planner][12],一款简洁、轻量级的待办事项管理器。它支持多个列表、计划和重复性任务、项目和子项目。它还可以与流行的在线应用 [Todoist][13] 同步,但这不是必需的。
|
||||
|
||||
应用中心的第二款应用是 [Notes-Up][14],这是一款使用 Markdown 写富文本的笔记应用。它允许用户在多个笔记本中创建多个笔记,并且有”查看“和”编辑“选项,这样你就可以预览最终文档的样子。同样,这款应用快速、轻量而且非常简约,与 ElementaryOS 的整体外观和感觉保持一致。
|
||||
应用中心的第二款应用是 [Notes-Up][14],这是一款使用 Markdown 写富文本格式的笔记应用。它允许用户在多个笔记本中创建多个笔记,并且有“查看”和“编辑”选项,这样你就可以预览最终文档的样子。同样,这款应用快速、轻量而且非常简约,与 ElementaryOS 的整体外观和感觉保持一致。
|
||||
|
||||
![ElementaryOS Planner and Notes-up][15]
|
||||
|
||||
Planner 和 Notes-up (Kevin Sonney,[CC BY-SA 4.0][4])
|
||||
*Planner 和 Notes-up (Kevin Sonney,[CC BY-SA 4.0][4])*
|
||||
|
||||
如果你不喜欢默认应用,Elementary 基于 Ubuntu LTS,因此如果你需要使用其他应用,整个 Ubuntu 应用生态系统都可以使用。不过总的来说,ElementaryOS 默认提供了一个快速、轻量、高效的桌面,让你在新的一年里保持高效。
|
||||
|
||||
@ -53,7 +55,7 @@ via: https://opensource.com/article/21/1/elementary-linux
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,59 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13044-1.html)
|
||||
[#]: subject: (3 email rules to live by in 2021)
|
||||
[#]: via: (https://opensource.com/article/21/1/email-rules)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
2021 年要遵守的 3 条电子邮件规则
|
||||
======
|
||||
|
||||
> 电子邮件不是即时通讯。通过遵循这些规则来防止电子邮件不断地打断你的工作。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/23/141931hsgz7762jn960nmh.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个应用程序。今年,我们除了关注有助于 2021 年的策略外,还将关注一体化解决方案。欢迎来到“2021 年 21 天生产力”的第二天。
|
||||
|
||||
和许多人一样,我对电子邮件也是爱恨交加。电子邮件是早期互联网、企业局域网和拨号 BBS 生态系统中最早的通信手段之一。电子邮件过去是、现在仍然是电子通信的主要手段之一。它被用于商业通信、商务、通知、协作和一堆有用的东西。
|
||||
|
||||
![Mutt 电子邮件客户端][2]
|
||||
|
||||
*Mutt 邮件客户端, [CC BY-SA 4.0][3] by Kevin Sonney*
|
||||
|
||||
很多人对电子邮件有着不正确的认识。电子邮件不是一个即时通讯平台。有时候,当一个人发送一条信息,几乎立刻就会出现在世界的另一端,然后在几分钟内就会有回应,这看起来就像是电子邮件是即时通讯。正因为如此,我们可能会陷入一种思维定势,即我们需要随时激活电子邮件程序,一旦有东西进来,我们需要马上看一下,然后马上回复。
|
||||
|
||||
电子邮件的设计原则是:一个人发送一条信息,收件人会在方便的时候回复。是的,有高优先级和紧急邮件的标志,我们的电子邮件程序也有通知来告诉我们新邮件何时到达,但它们真的不是为了给今天的许多人造成压力。
|
||||
|
||||
![太多的电子邮件][4]
|
||||
|
||||
*太!多!电子邮件了! [CC BY-SA 4.0][3] by Kevin Sonney*
|
||||
|
||||
一般说来,一个人每受到一次干扰,至少需要 15 分钟的时间让他们的思维过程重新集中到被打断的任务上。在工作场所(以及在家里!),电子邮件成为了这些中断之一已经是一种普遍现象。它不需要这样,也不是设计成这样的。我采用了一些规则来防止电子邮件成为让我无法完成任务的干扰。
|
||||
|
||||
**规则 1**:电子邮件不是一个警报平台。在技术领域,人们通常会配置监控和警报平台,将所有的通知发送到电子邮件。在过去的 15 年里,我几乎在每一个工作场所都遇到过这种情况,我会先花了几个月的时间来改变它。有很多好的平台和服务来管理警报。电子邮件不是其中之一。
|
||||
|
||||
**规则 2**:至少不要指望在 24 小时内得到答复。我们有多少人接到过电话,问我们是否收到电子邮件,并问我们是否有任何问题?我就遇到过。尽量在工作场所或与你经常发邮件的人设定一个期望值,回复有时会很快,有时不会。如果事情真的很紧急,他们应该使用其他的沟通方式。
|
||||
|
||||
**规则 3**:每隔几个小时检查一次电子邮件,而不是不断地检查。我承认这一条很难,但它能给我带来最安心的感觉。当我在工作或试图专注于写作等事情时,我会关闭我的电子邮件程序(或浏览器标签),并忽略它,直到我完成。没有通知,没有 20 条新邮件正在等待的指示,没有干扰。当我开始这样做的时候,我花了一些努力来克服我的 FOMO(害怕错过),但随着时间的推移,这已经变得容易了。我发现,当我再次打开我的电子邮件时,我可以专注于它,而不是担心我可以做什么,或应该做什么来代替。
|
||||
|
||||
希望这三条规则能像帮助我一样帮助你。在接下来的日子里,我会有更多可以帮助我处理电子邮件的方法分享给你。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/email-rules
|
||||
|
||||
作者:[Kevin Sonney][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/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/newsletter_email_mail_web_browser.jpg?itok=Lo91H9UH (email or newsletters via inbox and browser)
|
||||
[2]: https://opensource.com/sites/default/files/pictures/mutt-email-client.png (Mutt email client)
|
||||
[3]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[4]: https://opensource.com/sites/default/files/pictures/so-many-emails.png (So many emails)
|
@ -0,0 +1,104 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13067-1.html)
|
||||
[#]: subject: (Super Productivity: A Super Cool Open Source To-Do List App with GitHub Integration)
|
||||
[#]: via: (https://itsfoss.com/super-productivity/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
超级生产力:一款集成了 GitHub 的超酷开源待办事项列表应用
|
||||
======
|
||||
|
||||
> “超级生产力”是一款很棒的开源待办事项应用,可以帮助你管理任务、跟踪事务和管理时间。
|
||||
|
||||
无论你做什么,提高工作效率是大多数人的共同目标。通常,你总会尝试各种[待办事项列表应用][1]或者[记事应用][2]来帮助自己组织和提醒事情,从而高效地跟上工作进度。
|
||||
|
||||
当然,你可以看看那些清单,根据自己的喜好去尝试其中的一些。在这里,我遇到了一些独特的东西,如果你想要一个具有可靠的用户界面、GitHub/GitLab 集成以及一系列基本功能的桌面待办事项应用,你也许可以尝试一下。
|
||||
|
||||
<ruby>超级生产力<rt>Super Productivity</rt></ruby>看起来是一个令人印象深刻的待办事项列表应用,并提供一些独特的功能。在本文中,我将让你简单了解它的一切。
|
||||
|
||||
### 超级生产力:一个简单的而有吸引力的开源待办事项应用程序
|
||||
|
||||
![][3]
|
||||
|
||||
“超级生产力”是一款开源应用,它由 [Johannes Millan][4] 在 GitHub 上积极维护。
|
||||
|
||||
对我来说,用户体验是最重要的,“超级生产力”提供的用户界面给我留下了十分深刻的印象。
|
||||
|
||||
它还提供了一堆基本功能以及一些有趣的选项。让我们来看看它们。
|
||||
|
||||
### “超级生产力”的功能
|
||||
|
||||
![][5]
|
||||
|
||||
* 添加待办事项、说明
|
||||
* 追踪花费在任务和休息上的时间
|
||||
* 项目管理(与 JIRA、GitHub 和 GitLab 整合)
|
||||
* 安排任务的能力
|
||||
* 语言选择选项
|
||||
* 同步到 Dropbox、Google Drive 或任何其他 WebDAV 存储位置
|
||||
* 导入/导出功能
|
||||
* 自动备份功能
|
||||
* 能够调整定时器和计数器的行为
|
||||
* 黑暗模式
|
||||
* 在任务中添加附件
|
||||
* 完全免费的重复任务
|
||||
* 跨平台支持
|
||||
|
||||
除了我提到的功能外,你还会发现更多详细的设置和调整配置。
|
||||
|
||||
尤其是与 [JIRA][6]、[GitHub][7] 和 [GitLab][8] 的整合。你可以自动分配要进行的工作任务,而不需要检查你的电子邮件以了解问题跟踪器或议题的最近更新。
|
||||
|
||||
与我目前使用过的许多收费版的待办事项 Web 服务相比,你会惊讶地发现许多有用的功能完全免费。
|
||||
|
||||
### 在 Linux 上安装“超级生产力”
|
||||
|
||||
![][9]
|
||||
|
||||
它有各种安装方式。我下载了 AppImage 文件测试了一下。但是,你也可以得到基于 Debian 的发行版的 deb 包。
|
||||
|
||||
它也可以作为一个 [snap][10] 来安装。你可以在 [GitHub 的发布部分][11]中找到所有的包。
|
||||
|
||||
如果你感兴趣,可以查看它的 [GitHub 页面][12]来了解它的更多信息。
|
||||
|
||||
- [下载超级生产力](https://github.com/johannesjo/super-productivity/releases)
|
||||
|
||||
### 总结
|
||||
|
||||
我发现“超级生产力”的用户体验非常棒。所提供的功能非常有用,考虑到你可以获得一些你通常从收费版的待办事项 Web 服务中才能获得的高级功能,它可以成为大多数用户的完美替代品。
|
||||
|
||||
你可以简单地使用 Google Drive、Dropbox 或任何其他 WebDAV 存储位置同步数据。
|
||||
|
||||
它也可以取代像 [ActivityWatch][13] 这样的服务,帮助你追踪你工作任务和保持闲置的时间。所以,它可以成为你提高生产力的一体化解决方案!
|
||||
|
||||
听起来很不错,对吧?
|
||||
|
||||
你对“超级生产力”有什么看法?请在下面的评论区告诉我你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/super-productivity/
|
||||
|
||||
作者:[Ankush Das][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://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/to-do-list-apps-linux/
|
||||
[2]: https://itsfoss.com/note-taking-apps-linux/
|
||||
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/super-productivity.jpg?resize=800%2C569&ssl=1
|
||||
[4]: https://github.com/johannesjo
|
||||
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/super-productivity-2.jpg?resize=800%2C575&ssl=1
|
||||
[6]: https://www.atlassian.com/software/jira
|
||||
[7]: https://github.com/
|
||||
[8]: https://about.gitlab.com
|
||||
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/super-productivity-1.jpg?resize=800%2C574&ssl=1
|
||||
[10]: https://snapcraft.io/superproductivity
|
||||
[11]: https://github.com/johannesjo/super-productivity/releases
|
||||
[12]: https://github.com/johannesjo/super-productivity
|
||||
[13]: https://itsfoss.com/activitywatch/
|
@ -0,0 +1,160 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13036-1.html)
|
||||
[#]: subject: (How to get Battery status notification when a battery is full or low)
|
||||
[#]: via: (https://www.2daygeek.com/linux-low-full-charge-discharge-battery-notification/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
如何在电池充满或低电量时获得电池状态通知
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/20/231310avo3kzv67vkm3tz7.jpg)
|
||||
|
||||
对于类 Unix 用户来说,Linux 笔记本是不错的选择,但它经常会耗尽电池。我试过很多 Linux 操作系统,但没有像 Windows 那样电池寿命长。
|
||||
|
||||
充电时间长了会对电池造成损害,所以在电池 100% 充满时要拔掉电源线。电池充电或放电时没有默认的应用程序来通知,需要安装第三方应用来通知你。
|
||||
|
||||
为此,我通常会安装 [Battery Monitor][1],但它已经被废弃,所以我创建了一个 shell 脚本来获取通知。
|
||||
|
||||
笔记本电池充放电状态可以通过以下两个命令来识别。
|
||||
|
||||
使用 `acpi` 命令。
|
||||
|
||||
```
|
||||
$ acpi -b
|
||||
Battery 0: Discharging, 71%, 00:58:39 remaining
|
||||
```
|
||||
|
||||
使用 `upower` 命令。
|
||||
|
||||
```
|
||||
$ upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -w 'state|percentage' | awk '{print $2}'
|
||||
discharging
|
||||
64%
|
||||
```
|
||||
|
||||
### 方法 1:当电池电量高于 95% 或低于 20% 时,用 Shell 脚本发送警报
|
||||
|
||||
这个脚本在启动时在后台运行,每分钟检查一次电池状态,然后在电池电量超过 95% 或放电时电量低于 20% 时发送通知。
|
||||
|
||||
警报会直到你的电池电量超过 20% 或低于 95% 时才会停止。
|
||||
|
||||
```
|
||||
$ sudo vi /opt/scripts/battery-status.sh
|
||||
```
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
while true
|
||||
do
|
||||
battery_level=`acpi -b | grep -P -o '[0-9]+(?=%)'`
|
||||
if [ $battery_level -ge 95 ]; then
|
||||
notify-send "Battery Full" "Level: ${battery_level}%"
|
||||
paplay /usr/share/sounds/freedesktop/stereo/suspend-error.oga
|
||||
elif [ $battery_level -le 20 ]; then
|
||||
notify-send --urgency=CRITICAL "Battery Low" "Level: ${battery_level}%"
|
||||
paplay /usr/share/sounds/freedesktop/stereo/suspend-error.oga
|
||||
fi
|
||||
sleep 60
|
||||
done
|
||||
```
|
||||
|
||||
脚本完成后,设置可执行权限:
|
||||
|
||||
```
|
||||
$ sudo chmod +x /opt/scripts/battery-status.sh
|
||||
```
|
||||
|
||||
最后,将该脚本添加到用户配置文件的底部。对于全局范围来说,你需要在 `/etc/profile` 文件中添加该脚本。
|
||||
|
||||
```
|
||||
$ vi /home/magi/.profile
|
||||
|
||||
/opt/scripts/battery-status.sh &
|
||||
```
|
||||
|
||||
[重启你的 Linux 系统][2]来检查这点。
|
||||
|
||||
```
|
||||
$ sudo reboot
|
||||
```
|
||||
|
||||
### 方法 2:当电池充电(高于 95%)或放电(低于 20%)时发送通知的 Shell 脚本
|
||||
|
||||
这个脚本与上面的脚本类似,但它是由交流适配器负责。
|
||||
|
||||
如果你插上了交流适配器,而且电池的电量超过 95%,它就会发出一个带有声音的通知,但是这个通知不会停止,直到你拔掉交流适配器。
|
||||
|
||||
![][3]
|
||||
|
||||
如果你拔掉交流适配器,你将永远不会再看到通知,直到你的电池电量下降到 20%。
|
||||
|
||||
![][5]
|
||||
|
||||
```
|
||||
$ sudo vi /opt/scripts/battery-status-1.sh
|
||||
```
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
while true
|
||||
do
|
||||
export DISPLAY=:0.0
|
||||
battery_level=`acpi -b | grep -P -o '[0-9]+(?=%)'`
|
||||
if on_ac_power; then
|
||||
if [ $battery_level -ge 95 ]; then
|
||||
notify-send "Battery Full" "Level: ${battery_level}% "
|
||||
paplay /usr/share/sounds/freedesktop/stereo/suspend-error.oga
|
||||
fi
|
||||
else
|
||||
if [ $battery_level -le 20 ]; then
|
||||
notify-send --urgency=CRITICAL "Battery Low" "Level: ${battery_level}%"
|
||||
paplay /usr/share/sounds/freedesktop/stereo/suspend-error.oga
|
||||
fi
|
||||
fi
|
||||
sleep 60
|
||||
done
|
||||
```
|
||||
|
||||
脚本完成后,设置执行权限:
|
||||
|
||||
```
|
||||
$ sudo chmod +x /opt/scripts/battery-status-1.sh
|
||||
```
|
||||
|
||||
最后将脚本添加到用户配置文件的底部。对于全局范围来说,你需要在 `/etc/profile` 文件中添加该脚本。
|
||||
|
||||
```
|
||||
$ vi /home/magi/.profile
|
||||
|
||||
/opt/scripts/battery-status-1.sh &
|
||||
```
|
||||
|
||||
重启系统来检查:
|
||||
|
||||
```
|
||||
$ sudo reboot
|
||||
```
|
||||
|
||||
参考: [stackexchange][4]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/linux-low-full-charge-discharge-battery-notification/
|
||||
|
||||
作者:[Magesh Maruthamuthu][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://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/category/battery-monitor/
|
||||
[2]: https://www.2daygeek.com/6-commands-to-shutdown-halt-poweroff-reboot-the-linux-system/
|
||||
[3]: https://i0.wp.com/www.2daygeek.com/wp-content/uploads/2021/01/linux-low-full-battery-notification-2.png?w=1046&ssl=1
|
||||
[4]: https://unix.stackexchange.com/questions/60778/how-can-i-get-an-alert-when-my-battery-is-about-to-die-in-linux-mint
|
||||
[5]: https://i1.wp.com/www.2daygeek.com/wp-content/uploads/2021/01/linux-low-full-battery-notification-3.png?w=1029&ssl=1
|
78
published/202101/20210115 3 plain text note-taking tools.md
Normal file
78
published/202101/20210115 3 plain text note-taking tools.md
Normal file
@ -0,0 +1,78 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13056-1.html)
|
||||
[#]: subject: (3 plain text note-taking tools)
|
||||
[#]: via: (https://opensource.com/article/21/1/plain-text)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
3 个纯文本记事工具
|
||||
======
|
||||
|
||||
> 记笔记很重要,而纯文本是一种简单、中性的方式。这里有三个工具,你可以在不失去纯文本的简易和便携性的前提下,给你的笔记加点东西。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/27/153329o0waw16448hq0avf.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第五天。
|
||||
|
||||
纯文本是最具弹性的文档格式。纯文本文档体积小,可以在机器之间快速传输,并且可以在*任意*设备上阅读。因此,在纯文本文档中做笔记是很有意义的。
|
||||
|
||||
然而,纯文本也仅是纯文本。我们生活在一个富文本世界中,我们仍然需要标题、列表以及区分一个章节和另一个章节的方法。幸运的是,我们有几种方法可以添加这些元素,而不需要在纯文本文档中添加复杂的标记。
|
||||
|
||||
### Markdown
|
||||
|
||||
![Markdown][2]
|
||||
|
||||
*Markdown (Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
由 Aaron Schwartz 和 John Gruber 创建的 [Markdown][4],是我如今每天使用最多的格式。从读写 README 文件、文档、记笔记,甚至源代码注释,Markdown 让我可以在不牺牲轻松阅读文档的能力的情况下添加格式。
|
||||
|
||||
此外,Markdown 还有几个“扩展版本”,以允许那些不属于原始设计的项目。特别是,[GitHub 风格的 Markdown][5] 由于其在同名的源码控制网站中的使用而异常流行。
|
||||
|
||||
许多文件编辑器都支持 Markdown 高亮显示,不需要额外的附加组件或工作。
|
||||
|
||||
### AsciiDoc
|
||||
|
||||
![AsciiDoc][6]
|
||||
|
||||
*AsciiDoc (Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
由 Stuart Rackham 创建的 [AsciiDoc][7] 是向纯文本文档添加富文本元素的另一种方式。AsciiDoc 有许多生成文档、书籍和论文的功能。然而,这并不意味着它不能被用来做笔记。有很多环境(特别是在教育和研究领域),能够快速将笔记转换为更“正式”的格式是很有帮助的。
|
||||
|
||||
AsciiDoc 也有很多工具可以将文本转换为其他格式进行协作。还有一些附加组件可以从不同的源导入数据,并将其放入最终的文档中,或者处理特殊的格式,如 MathML 或 LaTeX。
|
||||
|
||||
### Org 模式
|
||||
|
||||
![ORG-Mode][8]
|
||||
|
||||
*ORG-Mode (Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
说到文本格式,我不能不提 [Org 模式][9]。它最初是为 [GNU Emacs][10] 设计的,现在已经成为笔记、待办事项、文档等常用的纯文本格式之一。Org 模式可以在包括 [Vim][11] 在内的众多文本编辑器中编写和使用。Org 模式简单、易学,是我最喜欢的笔记文本格式之一。
|
||||
|
||||
最后,选择 Markdown、AsciiDoc 或 Org 模式作为纯文本笔记,是确保它们可以在任何地方被阅读和更新的一种方式。如果你和我一样,你会发现自己在做纸质笔记的时候,也会使用同样的语法!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/plain-text
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/typewriter-hands.jpg?itok=oPugBzgv (Typewriter with hands)
|
||||
[2]: https://opensource.com/sites/default/files/pictures/markdown.png (Markdown)
|
||||
[3]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[4]: https://opensource.com/article/19/9/introduction-markdown
|
||||
[5]: https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown
|
||||
[6]: https://opensource.com/sites/default/files/pictures/asciidoc.png (AsciiDoc)
|
||||
[7]: https://asciidoc.org/
|
||||
[8]: https://opensource.com/sites/default/files/pictures/org-mode.png (ORG-Mode)
|
||||
[9]: https://orgmode.org/
|
||||
[10]: https://www.gnu.org/software/emacs/
|
||||
[11]: https://opensource.com/article/19/1/productivity-tool-org-mode
|
@ -0,0 +1,76 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13059-1.html)
|
||||
[#]: subject: (How to use KDE's productivity suite, Kontact)
|
||||
[#]: via: (https://opensource.com/article/21/1/kde-kontact)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
如何使用 KDE 的生产力套件 Kontact
|
||||
======
|
||||
|
||||
> KDE 很棒,但当你使用这个统一个人信息管理器 Kontact 时,它才真正发挥了作用。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/28/094146fyx79l7zwbwej7ym.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第六天。
|
||||
|
||||
在很久很久以前,当编译内核还是获取 WiFi 驱动的唯一途径时,图形环境主要是用来运行网页浏览器和打开大量终端窗口。其外观和感觉是由程序作者选择使用的各种工具箱组成的大杂烩。然后,在 1996 年 [Matthias Ettrich][2] 提出并随后发布了第一个版本的 [KDE][3]。它是基于当时专有的 [Qt][4] 工具箱(后来成为自由而开源的)。这个版本引发了 Linux 上的桌面革命,同一时期出现的还有使用当时的自由开源软件 GTK 工具包所创建的 [GNOME 桌面][5] 。不管是 KDE 还是 GNOME,Linux 从一个*只有电脑操作人员使用的 Linux 操作系统*变成了一个人人都能使用的强大桌面环境。
|
||||
|
||||
![Fedora KDE Spin Default Desktop][6]
|
||||
|
||||
*Fedora KDE 版的默认桌面 (Kevin Sonney, [CC BY-SA 4.0][7])*
|
||||
|
||||
KDE Plasma 5 是最新的 KDE 版本,它的功能非常丰富,可以提高你的工作效率。它包括了 Konqueror 网页浏览器、Dolphin 文件管理器和 Konsole 终端模拟器,所有这些都为这个桌面环境提供了一个很好的坚实基础,但是 KDE 真正提高生产力的方法是这个统一个人信息管理器:[Kontact][8]。
|
||||
|
||||
Kontact 为其他几个 KDE 程序提供了一个单一的界面,包括:KMail(电子邮件)、KOrganizer(日历、待办事项和日记)、KAddressBook(地址簿)、KNotes(笔记)、Akregator(RSS/ATOM 订阅阅读器)等。第一次启动时,Kontact 会引导你完成电子邮件提供商的设置,它支持本地和远程邮件配置。然后,Kontact 会进入一个仪表板,默认情况下,该仪表板会显示最近的电子邮件、日历事件、计划任务和最近的笔记。
|
||||
|
||||
![Kontact Summary screen][9]
|
||||
|
||||
*Kontact 概览页面 (Kevin Sonney, [CC BY-SA 4.0][7])*
|
||||
|
||||
设置“流程”看起来有点奇怪,因为在内置的本地账户之外没有配置统一的单一账户。在 Kontact(通过 KMail)引导你完成邮件设置后,你就可以进入日历页面添加你的日历,这里也配置了待办事项和日记应用(对于某些提供商,还可以配置通讯录)。
|
||||
|
||||
邮件和日历组件非常简单明了,可以如你期望地正常工作。待办事项页面和日记是与日历绑定的,这对于一些不完全支持所有日历类型的日历提供商来说可能是个问题(Google,我说的是你)。如果你使用的是这些提供商中的一个,你将需要为日记和待办事项创建一个特定的本地日历。
|
||||
|
||||
![Kontact Calendar][10]
|
||||
|
||||
*Kontact Calendar (Kevin Sonney, [CC BY-SA 4.0][7])*
|
||||
|
||||
待办事项列表有很多功能。虽然它可以作为一个简单的任务清单与提醒,它也支持一些轻量级的项目管理功能。它有一个完成百分比的滑块,可以从主列表视图中更新,这样你就可以跟踪进度。它能够附加文件和分配 1-10 的优先级。最后,它可以像其他日历约会一样将用户添加到任务中。
|
||||
|
||||
创建一个日记条目本质上是在日历上给自己创建一个笔记。它是一段形式自由的文本,就像写在实体笔记本和计划手册的某一天上那样。如果你要记录工作,写下每天的日记,或只是需要个地方记录会议记录,这个功能是非常*方便*的(本系列后面有更多关于这个的内容)。
|
||||
|
||||
![Kontact Journal][11]
|
||||
|
||||
*Kontact Journal (Kevin Sonney, [CC BY-SA 4.0][7])*
|
||||
|
||||
构成 Kontact 的这些程序非常强大,如果你愿意的话,也可以作为单独的应用运行。Kontact 通过给你提供一个集中的地方,在一个应用内找到你所有的信息,从而提升了它们的实用性。
|
||||
|
||||
大多数发行版都允许你在没有 KDE 的情况下安装 Kontact 和它所使用的组件,但当它作为 KDE 桌面的一部分使用时,它才会真正发挥其作用。KDE 在 Fedora KDE 版、KUbuntu、KDE Neon(基于 Ubuntu LTS)和其他几个发行版中都是默认桌面。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/kde-kontact
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/team_dev_email_chat_video_work_wfm_desk_520.png?itok=6YtME4Hj (Working on a team, busy worklife)
|
||||
[2]: https://en.wikipedia.org/wiki/Matthias_Ettrich
|
||||
[3]: https://kde.org/
|
||||
[4]: https://en.wikipedia.org/wiki/Qt_(software)
|
||||
[5]: https://www.gnome.org/
|
||||
[6]: https://opensource.com/sites/default/files/pictures/fedora-kde-spin-default-desktop.png (Fedora KDE Spin Default Desktop)
|
||||
[7]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[8]: https://kontact.kde.org/
|
||||
[9]: https://opensource.com/sites/default/files/pictures/kontact-summary-screen_0.png (Kontact Summary screen)
|
||||
[10]: https://opensource.com/sites/default/files/pictures/kontact-calendar.png (Kontact Calendar)
|
||||
[11]: https://opensource.com/sites/default/files/pictures/kontact-journal.png (Kontact Journal)
|
@ -0,0 +1,92 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13050-1.html)
|
||||
[#]: subject: (Haruna Video Player: An Open-Source Qt-based MPV GUI Front-end for Linux)
|
||||
[#]: via: (https://itsfoss.com/haruna-video-player/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
Haruna 视频播放器:一个 MPV GUI 前端
|
||||
======
|
||||
|
||||
> 一个基于 Qt 的 Linux 视频播放器,它可作为 mpv 的前端,并能使用 youtube-dl。
|
||||
|
||||
### Haruna 视频播放器:一个基于 Qt 的免费视频播放器
|
||||
|
||||
![Haruna Video Player][1]
|
||||
|
||||
如果你还不知道 [mpv][2],它是一个基于命令行的自由开源的媒体播放器。好吧,它有一个[简约的 MPV GUI][3],但核心是命令行。
|
||||
|
||||
你可能还会找到几个[开源视频播放器][4],它们基本上就是 mpv 的 GUI 前端。
|
||||
|
||||
Haruna 视频播放器就是其中之一,同时还可以[使用 youtube-dl][5]。你可以轻松播放本地媒体文件以及 YouTube 内容。
|
||||
|
||||
让我给你介绍一下这个播放器提供的功能。
|
||||
|
||||
### Haruna 视频播放器的功能
|
||||
|
||||
![][6]
|
||||
|
||||
你可能会发现它与其他一些视频播放器有些不同。以下是你可以从 Haruna 视频播放器 获得的:
|
||||
|
||||
* 能够直接使用 URL 播放 YouTube 视频
|
||||
* 支持播放列表,并且你可以轻松控制它们
|
||||
* 能够根据字幕中的某些词语自动跳过
|
||||
* 控制播放速度
|
||||
* 使用 [youtube-dl][7] 改变播放格式(音频/视频)
|
||||
* 大量的键盘快捷键
|
||||
* 轻松地从视频中截屏
|
||||
* 添加主要和次要字幕的选项
|
||||
* 改变截图的文件格式
|
||||
* 支持硬件解码
|
||||
* 色彩调整以提高你的观看质量。
|
||||
* 能够调整鼠标和键盘的快捷键,以便能够快速浏览和做你想做的事情
|
||||
* 调整 UI(字体、主题)
|
||||
|
||||
### 在 Linux 上安装 Haruna 视频播放器
|
||||
|
||||
![][8]
|
||||
|
||||
不幸的是(或者不是,取决于你的偏好),你只能[使用 Flatpak][9] 安装它。你可以使用 [Flatpak 包][10]在任何 Linux 发行版上安装它。
|
||||
|
||||
如果你使用的是基于 Arch 的系统,你也可以在 [AUR][11] 中找到它。
|
||||
|
||||
但是,如果你不喜欢这样,你可以查看 [GitHub][12] 上的源代码,看看你是否可以像普通的 Gentoo 用户一样自己构建它。
|
||||
|
||||
- [Haruna 视频播放器][12]
|
||||
|
||||
### 总结
|
||||
|
||||
Haruna 视频播放器是一款简单实用的在 [libmpv][13] 之上的 GUI。能够在系统上播放 YouTube 视频以及各种文件格式绝对是很多用户所希望的。
|
||||
|
||||
用户界面很容易上手,它也提供了一些重要的自定义选项。
|
||||
|
||||
你尝试过这款视频播放器了吗?在下面的评论中让我知道你对它的看法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/haruna-video-player/
|
||||
|
||||
作者:[Ankush Das][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://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/haruna-video-player-dark.jpg?resize=800%2C512&ssl=1
|
||||
[2]: https://mpv.io/
|
||||
[3]: https://itsfoss.com/mpv-video-player/
|
||||
[4]: https://itsfoss.com/video-players-linux/
|
||||
[5]: https://itsfoss.com/download-youtube-linux/
|
||||
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/haruna-video-player-1.png?resize=800%2C503&ssl=1
|
||||
[7]: https://github.com/ytdl-org/youtube-dl
|
||||
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/haruna-player-garuda-linux.png?resize=800%2C506&ssl=1
|
||||
[9]: https://itsfoss.com/flatpak-guide/
|
||||
[10]: https://flathub.org/apps/details/com.georgefb.haruna
|
||||
[11]: https://itsfoss.com/aur-arch-linux/
|
||||
[12]: https://github.com/g-fb/haruna
|
||||
[13]: https://github.com/mpv-player/mpv/tree/master/libmpv
|
@ -0,0 +1,70 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13062-1.html)
|
||||
[#]: subject: (Organize your task list using labels)
|
||||
[#]: via: (https://opensource.com/article/21/1/labels)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
使用标签组织你的任务列表
|
||||
======
|
||||
|
||||
> 文件夹的用途是存储信息和任务。使用标签来帮助你更好地组织这些文件夹中的内容。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/29/150011k9sz3n0q99mmkems.jpg)
|
||||
|
||||
在前几年,这个年度系列报道了诸如 Notmuch 和 Syncthing 之类的开源的组织应用程序。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第九天。
|
||||
|
||||
我用我的电子邮件、待办列表和笔记来做这件事,有一天我决定我要把这些“组织起来”,重新安排我保存东西的方式和位置。有时我发现了一个新的程序,我必须(再次)从头开始配置。有时,当前的方法已经花了很多时间,与我使用系统的时间相比,我花了更多的时间在保持存储顺序最新。我去年测试一些待办列表软件时,最后一个软件让我有了一个非常重要的认识。
|
||||
|
||||
![List of labels][4]
|
||||
|
||||
*所有事情都有存放的地方(Kevin Sonney, [CC BY-SA 4.0][5])*
|
||||
|
||||
让我打个比方。一个任务(或电子邮件或笔记)就像你在一次活动中收到的那件很酷的 T 恤。它是黑色的,有一个很棒的图案,后面有一个标签,上面写着尺寸,领口有一个标签,上面写着洗涤说明。到了该收起来的时候,它该放在哪里呢?是和黑色的 T 恤放在一起吗?是和类似主题的衬衫放在一起吗?是按尺码放吗?是按需要洗涤的方式?还是按材质?
|
||||
|
||||
一件 T 恤只能放在*一*个地方,即使它可以有多种特质。我们需要以同样的方式对待任务、电子邮件和笔记。大型[电子邮件提供商][6]已经允许我们把一个标签当作一个文件夹。一封邮件(或一个文档或一个任务)可以同时在两个文件夹中!或者三个!甚至 11 个!
|
||||
|
||||
![Guitar volume 11][7]
|
||||
|
||||
*它高达 11 个(Seth Kenlon, [CC BY-SA 4.0][5])*
|
||||
|
||||
我必须明智地决定不再这样做。文件夹不是标签,标签也不是文件夹。这让我找到了我目前整理待办事项清单(和笔记,以及电子邮件)的规则:
|
||||
|
||||
1. 一个任务只应该在一个文件夹里。文件夹是以“大事”来命名的,比如一个地方或组织。我目前有三个文件夹来存放任务。“工作”、“家庭”和 “爱好”。当我专注于其中一个领域时,我知道我在看什么任务。
|
||||
2. 一个任务可以有任意个我需要的标签。我尽量保持在三个左右或更少。
|
||||
3. 一个任务应该有一个明确的意义。也许是你要写的程序的名字。也许是一些通用的东西,比如“要读的书”或“账单”。但如果你记不起 “4rg8sn5” 就是“要支付的账单”,这就对你没有帮助。
|
||||
|
||||
利用这些规则,如果我有一个“写第 9 天文章”的任务,它就会进入”爱好“文件夹,我给它打上 “OSDC”、“文章”、“2021” 的标签。如果我想在我的 [Elementary Planner][8] 中看到我所有的 2021 年的任务,我可以搜索这个标签。任务最终会出现在 “OSDC” 的搜索中,其中可能还包括一个对文章发表评论的待办事项,一个开始规划 2022 年系列的待办事项,还有一个跟进我认为有好文章想法的人。
|
||||
|
||||
我的“工作”文件夹里的东西通常是按项目标记的。“完成管理 CLI 文档”可能会被分为 “github”、“prod” 和 “admin”。“docs” 标签包含了“工作”和”爱好“文件夹中的项目,因为写文档是这两个文件夹都需要做的事情。
|
||||
|
||||
![Linux Elementary planner][9]
|
||||
|
||||
*文件夹和标签(Kevin Sonney, [CC BY-SA 4.0][5])*
|
||||
|
||||
将“标签”和“文件夹”进行心理分离,帮助我将任务进行分组和分类,而不至于过度。这也意味着我可以更快地找到事情,花更少的时间去维护我的待办事项清单,而花更多的时间去做清单上的事情。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/labels
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/kanban_trello_organize_teams_520.png?itok=ObNjCpxt (Kanban-style organization action)
|
||||
[2]: https://opensource.com/article/20/1/organize-email-notmuch
|
||||
[3]: https://opensource.com/article/20/1/sync-files-syncthing
|
||||
[4]: https://opensource.com/sites/default/files/pictures/day9-image1.png (List of labels)
|
||||
[5]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[6]: https://opensource.com/alternatives/gmail
|
||||
[7]: https://opensource.com/sites/default/files/pictures/guitar-11.jpg (Guitar volume 11)
|
||||
[8]: https://opensource.com/article/21/1/elementary-linux
|
||||
[9]: https://opensource.com/sites/default/files/pictures/elementary-planner.png (Linux Elementary planner)
|
@ -0,0 +1,70 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13070-1.html)
|
||||
[#]: subject: (Why keeping a journal improves productivity)
|
||||
[#]: via: (https://opensource.com/article/21/1/open-source-journal)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
为什么写日记能提高效率
|
||||
======
|
||||
|
||||
> 写日记有着悠久的历史。这里有三个开源工具,可以帮助你写日记变得更轻松。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/31/082622p6wgh7szzuvevug4.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十天。
|
||||
|
||||
在我的小学时代,商业互联网还没有出现,老师经常会给我们班级布置一个让我们写日记的作业。有时会针对一些特定的内容,例如特定格式的虫子列表和说明,或者是公民课的每周新闻摘要。
|
||||
|
||||
几个世纪以来,人们一直在写日记。它们是一种方便的信息保存方式。它们有很多形式,比如意大利的 [Zibaldone][2]、[备忘录][3],或者记录今天做了什么的事件日记。
|
||||
|
||||
![Notebook folders][4]
|
||||
|
||||
*(Kevin Sonney, [CC BY-SA 4.0][5])*
|
||||
|
||||
为什么我们要写某种日记呢?第一个原因是为了让我们不至于把所有的事情都记在脑子里。我们中没有多少人有<ruby>[遗觉记忆][6]<rt>Eidetic memory</rt></ruby>,维护运行日记或一组笔记可以让我们更容易地参考我们之前做的一些事情。日记也更容易分享,因为它们可以在聊天、邮件中复制/粘贴。正如 [Robert Boyce][7] 的名言:“知识就是力量。知识共享使力量倍增。”知识的共享是开源的一个内在组成部分。
|
||||
|
||||
![Today's journal][8]
|
||||
|
||||
*今天的日记 (Kevin Sonney, [CC BY-SA 4.0][5])*
|
||||
|
||||
在写事件日记的时候,有一个很关键的点就是要快速、简单、方便。最简单的方法是打开文档,添加一行当前日期和备注,然后保存。
|
||||
|
||||
有几个程序或附加软件可以让这一切变得更简单。[GNote 的 Note of the Day 插件][9]会自动创建一个以日期为标题的笔记,可以用来保存当天的内容。
|
||||
|
||||
Emacs Org 模式有一个热键组合,可以“捕捉”事物并将其放入文档中。结合 [org-journal][10] 附加组件,这将在文档中创建当天的条目。
|
||||
|
||||
Kontact 的 KNotes 组件会自动将日期和时间添加到新笔记中。
|
||||
|
||||
![Finding a note][11]
|
||||
|
||||
*查找笔记 (Kevin Sonney, [CC BY-SA 4.0][5])*
|
||||
|
||||
写日记或记录事情是一种方便的方法,可以记录做了什么和怎么做的。它的作用不仅仅是“我做了什么”,它还可以包括阅读的书籍、吃过的食物、去过的地方,以及一大堆对未来有用的信息。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/open-source-journal
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/note-taking.jpeg?itok=fiF5EBEb (Note taking hand writing)
|
||||
[2]: https://en.wikipedia.org/wiki/Zibaldone
|
||||
[3]: https://en.wikipedia.org/wiki/Commonplace_book
|
||||
[4]: https://opensource.com/sites/default/files/pictures/day10-image1.png (Notebook folders)
|
||||
[5]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[6]: https://en.wikipedia.org/wiki/Eidetic_memory
|
||||
[7]: https://en.wikipedia.org/wiki/Robert_Boyce
|
||||
[8]: https://opensource.com/sites/default/files/pictures/day10-image2.png (Today's journal)
|
||||
[9]: https://help.gnome.org/users/gnote/unstable/addin-noteoftheday.html.en
|
||||
[10]: https://github.com/bastibe/org-journal
|
||||
[11]: https://opensource.com/sites/default/files/pictures/day10-image3.png (Finding a note)
|
@ -0,0 +1,89 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (AnyISalIn)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13063-1.html)
|
||||
[#]: subject: (How to implement a DevOps toolchain)
|
||||
[#]: via: (https://opensource.com/article/21/1/devops-tool-chain)
|
||||
[#]: author: (Tereza Denkova https://opensource.com/users/tereza-denkova)
|
||||
|
||||
如何实现 DevOps 工具链
|
||||
======
|
||||
|
||||
> 一套完整启用的 DevOps 工具链可推动你的创新计划,实现快速部署并节约成本。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/29/153905o35h8u9zy5k58bll.jpg)
|
||||
|
||||
不同规模和不同行业组织都致力于为提高软件交付的速度和质量提供解决方案。这不仅保证了他们的生存,还令他们在全球市场取得了成功。DevOps 可以帮助他们规划出一条最佳路线。
|
||||
|
||||
DevOps 是一个系统,通过引入不同的工具链连接不同工作流程,以便及时交付项目并降低所需的开销。
|
||||
|
||||
在我工作的 IT 服务公司 [Accedia][2],我们会帮助客户落地一套完整的 DevOps 工具链,这套工具链能帮助他们达到甚至超越他们的业务目标。在这篇文章,我会分享目前为止从 DevOps 项目中汲取的经验。
|
||||
|
||||
### DevOps 工具链是什么?
|
||||
|
||||
一套完善的 DevOps 工具链可以在不同阶段中使用不同的 DevOps 工具来解决特定的业务带来的挑战。一条工具链能保证前端和后端开发者、质量测试人员、客户都能够从中获得收益。构建工具链的目的是为了自动化开发和部署过程,以确保快速、可靠、预算友好地交付与创新。
|
||||
|
||||
我们发现成功构建一套 DevOps 工具链不是一个简单的事情。它需要实验和不断的完善,保证必要的流程是完全自动化的。
|
||||
|
||||
### 为什么你需要 DevOps 工具链
|
||||
|
||||
DevOps 工具链自动化了工作流中的所有技术元素。它能让不同团队在一个平台上进行工作,因此可以使你专注于业务战略以推动组织走向未来。
|
||||
|
||||
我们总结了五个实现 DevOps 工具链所带来的好处。你可以让管理层相信,是值得为 DevOps 工具链的开发投入资源和时间的。
|
||||
|
||||
1. **更快、更高效的生产部署**:DevOps 工具自动化了大部分软件开发进程。这会使产品开发专注于创新,交付更加敏捷,更领先于竞争对手。
|
||||
2. **预算和时间优化**:将手动的任务转变为自动化会使你的组织节省时间和资源。当没有人为的错误和时间管理不足带来的额外支出,预算自然会得到优化。
|
||||
3. **高效的开发**:DevOps 工具链会减少开发工作中不必要的延时,提高开发效率。前端、后端、质量测试人员的工作是一致的,所以没有人需要协调不同团队之间人员的交付。
|
||||
4. **更快的部署意味着更高的质量**:DevOps 工具链保证了缺陷能够很快被解决,并且迅速完成高质量的部署进程。怎么样?它可以生成有针对性的告警,并将重要的事件通知给你的团队。这会让你主动地发现并解决潜在的问题,从而规避故障的不断的升级从而导致的客户服务不可用。
|
||||
5. **及时事件管理**:DevOps 工具链有助于优化事件管理记录。它能够识别 IT 事件并且逐渐升级事件级别,通知给指定团队的成员,直到问题被解决。这意味着消息的接受和处理会更加的迅速,因为它们发送给了正确的目标。
|
||||
|
||||
### DevOps 工具链的实践
|
||||
|
||||
对我的团队来说,DevOps 并不新鲜。我们已经敏捷开发很长时间了,并且我们总是热衷于探索最优的工作流。在我们的实践中,往往都是应用复杂性增加从而带来了自动化的需求。
|
||||
|
||||
这是我们为一个客户配置的工具链。这个项目包含了移动运营方案,连接了金融交易的所有参与者 (卖方、买方、银行)。这个客户需要动态响应用户反馈并且将故障时间缩短到最小,从而来提高用户体验。我的团队设计了一套工具链用于自动化应用的维护和部署新功能。
|
||||
|
||||
![Accedia's DevOps toolchain][3]
|
||||
|
||||
*(Accedia, [CC BY-NC-SA 4.0][4])*
|
||||
|
||||
1. 首先,我们团队编写了自动化测试,可以立即识别应用程序的变更。
|
||||
2. 当新版本已经准备就绪的时候,代码将被提交到 Gitlab 中。
|
||||
3. 通过 Gitlab,提交会自动触发 Jenkins 构建。
|
||||
4. 在 **持续集成中**,新的代码版本通过 [Chai][5] 和 [Mocha][6] 进行了测试,以检测是否运行正常。
|
||||
5. 当测试通过,**持续部署阶段** 将会开始并创建一个可用的 Docker 镜像并上传到 Sonatype 的 [Nexus][7]。(这是 Sonatype 公司的的一个开源工具)
|
||||
6. 最后,新版本应用会通过 Nexus 下载并且部署到线上环境中,例如 [Docker][8] 容器 (**持续部署阶段**)
|
||||
|
||||
简而言之,每当有人在仓库中创建一个新的提交,又或者团队上传新的代码版本、功能、升级、缺陷修复等,应用程序包都会自动更新并且交付给客户。
|
||||
|
||||
这套系统拥有良好的事故控制能力以保证快速部署,但不以牺牲质量为代价。它对于用户的反馈是动态的,意味着新功能和旧功能的和更新只需要之前一半的时间,同时将故障时间降低到最低。
|
||||
|
||||
### 把它封装起来
|
||||
|
||||
一套完整并且正确实施的 DevOps 工具链可以从始至终推动你的创新计划并且加速部署。
|
||||
|
||||
根据你的需求,你的工具链可能看起来和这些不一样,但是我希望我们的工作流能够让你了解如何将自动化作为一种解决方案。
|
||||
|
||||
-------------------------------------------------- -----------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/devops-tool-chain
|
||||
|
||||
作者:[Tereza Denkova][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[AnyISalIn](https://github.com/AnyISalIn)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/tereza-denkova
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/tools_osyearbook2016_sysadmin_cc.png?itok=Y1AHCKI4 (Wratchet set tools)
|
||||
[2]: https://accedia.com/services/operations/devops/
|
||||
[3]: https://opensource.com/sites/default/files/uploads/devopstoolchain.png (Accedia's DevOps toolchain)
|
||||
[4]: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
[5]: https://www.chaijs.com/
|
||||
[6]: https://mochajs.org/
|
||||
[7]: https://www.sonatype.com/nexus/repository-oss
|
||||
[8]: https://opensource.com/resources/what-docker
|
||||
[9]: https://accedia.com/blog/5-good-reasons-why-you-need-a-devops-toolchain/
|
@ -0,0 +1,69 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13090-1.html)
|
||||
[#]: subject: (7 Bash tutorials to enhance your command line skills in 2021)
|
||||
[#]: via: (https://opensource.com/article/21/1/bash)
|
||||
[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
|
||||
|
||||
7 个 Bash 教程,提高你的命令行技能(2021 版)
|
||||
======
|
||||
|
||||
> Bash 是大多数 Linux 系统上的默认命令行 shell。所以你为什么不试着学习如何最大限度地利用它呢?
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/06/001837cujo0ql3utfobrrj.jpg)
|
||||
|
||||
Bash 是大多数 Linux 系统上的默认命令行 shell。所以你为什么不试着学习如何最大限度地利用它呢?今年,我们推荐了许多很棒的文章来帮助你充分利用 Bash shell 的强大功能。以下是一些关于 Bash 阅读次数最多的文章:
|
||||
|
||||
### 《通过重定向在 Linux 终端任意读写数据》
|
||||
|
||||
输入和输出重定向是任何编程或脚本语言的基础功能。从技术上讲,只要你与电脑互动,它就会自然而然地发生。输入从 stdin(标准输入,通常是你的键盘或鼠标)读取,输出到 stdout(标准输出,一般是文本或数据流),而错误被发送到 stderr(标准错误,一般和标准输出是一个位置)。了解这些数据流的存在,使你能够在使用 Bash 等 shell 时控制信息的去向。Seth Kenlon [分享][2]了这些很棒的技巧,可以让你在不需要大量鼠标移动和按键的情况下从一个地方获取数据。你可能不经常使用重定向,但学习使用它可以为你节省大量不必要的打开文件和复制粘贴数据的时间。
|
||||
|
||||
### 《系统管理员 Bash 脚本入门》
|
||||
|
||||
Bash 是自由开源软件,所以任何人都可以安装它,不管他们运行的是 Linux、BSD、OpenIndiana、Windows 还是 macOS。Seth Kenlon [帮助][3]你学习如何使用 Bash 的命令和特性,使其成为最强大的 shell 之一。
|
||||
|
||||
### 《针对大型文件系统可以试试此 Bash 脚本》
|
||||
|
||||
你是否曾经想列出一个目录中的所有文件,只显示其中的文件,不包括其他内容?或者只显示目录?如果你有,那么 Nick Clifton 的[文章][4]可能正是你正在寻找的。Nick 分享了一个漂亮的 Bash 脚本,它可以列出目录、文件、链接或可执行文件。该脚本使用 `find` 命令进行搜索,然后运行 `ls` 显示详细信息。对于管理大型 Linux 系统的人来说,这是一个漂亮的解决方案。
|
||||
|
||||
### 《用 Bash 工具对你的 Linux 系统配置进行快照》
|
||||
|
||||
你可能想与他人分享你的 Linux 配置,原因有很多。你可能需要帮助排除系统上的一个问题,或者你对自己创建的环境非常自豪,想向其他开源爱好者展示它。Don Watkins 向我们[展示][5]了 screenFetch 和 Neofetch 来捕获和分享你的系统配置。
|
||||
|
||||
### 《6 个方便的 Git 脚本》
|
||||
|
||||
Git 已经成为一个无处不在的代码管理系统。了解如何管理 Git 存储库可以简化你的开发体验。Bob Peterson [分享][6]了 6 个 Bash 脚本,它们将使你在使用 Git 存储库时更加轻松。`gitlog` 打印当前补丁的简略列表,并与主版本相对照。这个脚本的不同版本可以显示补丁的 SHA1 id 或在一组补丁中搜索字符串。
|
||||
|
||||
### 《改进你 Bash 脚本的 5 种方法》
|
||||
|
||||
系统管理员通常编写各种或长或短的 Bash 脚本,以完成各种任务。Alan Formy-Duval [解释][7]了如何使 Bash 脚本更简单、更健壮、更易于阅读和调试。我们可能会考虑到我们需要使用诸如 Python、C 或 Java 之类的语言来实现更高的功能,但其实也不一定需要。因为 Bash 脚本语言就已经非常强大。要最大限度地发挥它的效用,还有很多东西要学。
|
||||
|
||||
### 《我珍藏的 Bash 秘籍》
|
||||
|
||||
Katie McLaughlin 帮助你提高你的工作效率,用别名和其他快捷方式解决你经常忘记的事情。当你整天与计算机打交道时,找到可重复的命令并标记它们以方便以后使用是非常美妙的。Katie [总结][8]了一些有用的 Bash 特性和帮助命令,可以节省你的时间。
|
||||
|
||||
这些 Bash 小技巧将一个已经很强大的 shell 提升到一个全新的级别。也欢迎分享你自己的建议。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/bash
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/terminal_command_linux_desktop_code.jpg?itok=p5sQ6ODE (Terminal command prompt on orange background)
|
||||
[2]: https://linux.cn/article-12385-1.html
|
||||
[3]: https://opensource.com/article/20/4/bash-sysadmins-ebook
|
||||
[4]: https://linux.cn/article-12025-1.html
|
||||
[5]: https://opensource.com/article/20/1/screenfetch-neofetch
|
||||
[6]: https://linux.cn/article-11797-1.html
|
||||
[7]: https://opensource.com/article/20/1/improve-bash-scripts
|
||||
[8]: https://linux.cn/article-11841-1.html
|
@ -0,0 +1,229 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "MjSeven"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13126-1.html"
|
||||
[#]: subject: "How to Create and Manage Archive Files in Linux"
|
||||
[#]: via: "https://training.linuxfoundation.org/announcements/how-to-create-and-manage-archive-files-in-linux/"
|
||||
[#]: author: "Matt Zand,Kevin Downs https://training.linuxfoundation.org/announcements/how-to-create-and-manage-archive-files-in-linux/"
|
||||
|
||||
如何在 Linux 中创建和管理归档文件
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/17/121000c7282pf7mv2sc78m.jpg)
|
||||
|
||||
简而言之,归档是一个包含一系列文件和(或)目录的单一文件。归档文件通常用于在本地或互联网上传输,或作为一个一系列文件和目录的备份副本,从而允许你使用一个文件来工作(如果压缩,则其大小会小于所有文件的总和)。同样的,归档也用于软件应用程序打包。为了方便传输,可以很容易地压缩这个单一文件,而存档中的文件会保留原始结构和权限。
|
||||
|
||||
我们可以使用 `tar` 工具来创建、列出和提取归档中的文件。用 `tar` 生成的归档通常称为“tar 文件”、“tar 归档”或者“压缩包”(因为所有已归档的文件被合成了一个文件)。
|
||||
|
||||
本教程会展示如何使用 `tar` 创建、列出和提取归档中的内容。这三个操作都会使用两个公共选项 `-f` 和 `-v`:使用 `-f` 指定归档文件的名称,使用 `-v`(“冗余”)选项使 `tar` 在处理文件时输出文件名。虽然 `-v` 选项不是必需的,但是它可以让你观察 `tar` 操作的过程。
|
||||
|
||||
在本教程的下面部分中,会涵盖 3 个主题:1、创建一个归档文件;2、列出归档文件内容;3、提取归档文件内容。另外我们会回答归档文件管理的 6 个实际问题来结束本教程。你从本教程学到的内容对于执行与[网络安全][1]和[云技术][2]相关的任务至关重要。
|
||||
|
||||
### 1、创建一个归档文件
|
||||
|
||||
要使用 `tar` 创建一个归档文件,使用 `-c`(“创建”)选项,然后用 `-f` 选项指定要创建的归档文件名。通常的做法是使用带有 `.tar` 扩展名的名称,例如 `my-backup.tar`。注意,除非另有特别说明,否则本文其余部分中使用的所有命令和参数都以小写形式使用。记住,在你的终端上输入本文的命令时,无需输入每个命令行开头的 `$` 提示符。
|
||||
|
||||
输入要归档的文件名作为参数;如果要创建一个包含所有文件及其子目录的归档文件,提供目录名称作为参数。
|
||||
|
||||
要归档 `project` 目录内容,输入:
|
||||
|
||||
```
|
||||
$ tar -cvf project.tar project
|
||||
```
|
||||
|
||||
这个命令将创建一个名为 `project.tar` 的归档文件,包含 `project` 目录的所有内容,而原目录 `project` 将保持不变。
|
||||
|
||||
使用 `-z` 选项可以对归档文件进行压缩,这样产生的输出与创建未压缩的存档然后用 `gzip` 压缩是一样的,但它省去了额外的步骤。
|
||||
|
||||
要从 `project` 目录创建一个 `project.tar.gz` 的压缩包,输入:
|
||||
|
||||
```
|
||||
$ tar -zcvf project.tar.gz project
|
||||
```
|
||||
|
||||
这个命令将创建一个 `project.tar.gz` 的压缩包,包含 `project` 目录的所有内容,而原目录 `project` 将保持不变。
|
||||
|
||||
**注意:** 在使用 `-z` 选项时,你应该使用 `.tar.gz` 扩展名而不是 `.tar` 扩展名,这样表示已压缩。虽然不是必须的,但这是一个很好的实践。
|
||||
|
||||
gzip 不是唯一的压缩形式,还有 bzip2 和 xz。当我们看到扩展名为 `.xz` 的文件时,我们知道该文件是使用 `xz` 压缩的,扩展名为 `.bz2` 的文件是用 `bzip2` 压缩的。随着 bzip2 不再维护,我们将远离它而关注 xz。使用 `xz` 压缩时,需要花费更长的时间。然而,等待通常是值得的,因为压缩效果要好的多,这意味着压缩包通常比使用其它压缩形式要小。更好的是,不同压缩形式之间的解压缩或提取文件并没有太大区别。下面我们将看到一个使用 `tar` 压缩文件时如何使用 xz 的示例:
|
||||
|
||||
```
|
||||
$ tar -Jcvf project.tar.xz project
|
||||
```
|
||||
|
||||
我们只需将 `gzip` 的 `-z` 选项转换为 `xz` 的大写 `-J` 即可。以下是一些输出,显示压缩形式之间的差异:
|
||||
|
||||
![][3]
|
||||
|
||||
![][4]
|
||||
|
||||
如你所见,`xz` 的压缩时间最长。但是,它在减小文件大小方面做的最好,所以值得等待。文件越大,压缩效果也越好。
|
||||
|
||||
### 2、列出归档文件的内容
|
||||
|
||||
要列出 tar 归档文件的内容但不提取,使用 `-t` 选项。
|
||||
|
||||
要列出 `project.tar` 的内容,输入:
|
||||
|
||||
```
|
||||
$ tar -tvf project.tar
|
||||
```
|
||||
|
||||
这个命令列出了 `project.tar` 归档的内容。`-v` 和 `-t` 选项一起使用会输出每个文件的权限和修改时间,以及文件名。这与 `ls` 命令使用 `-l` 选项时使用的格式相同。
|
||||
|
||||
要列出 `project.tar.gz` 压缩包的内容,输入:
|
||||
|
||||
```
|
||||
$ tar -tzvf project.tar.gz
|
||||
```
|
||||
|
||||
### 3、从归档中提取内容
|
||||
|
||||
要提取(解压)tar 归档文件中的内容,使用 `-x`(“提取”)选项。
|
||||
|
||||
要提取 `project.tar` 归档的内容,输入:
|
||||
|
||||
```
|
||||
$ tar -xvf project.tar
|
||||
```
|
||||
|
||||
这个命令会将 `project.tar` 归档的内容提取到当前目录。
|
||||
|
||||
如果一个归档文件被压缩,通常来说它的扩展名为 `.tar.gz` 或 `.tgz`,请包括 "-z" 选项。
|
||||
|
||||
要提取 `project.tar.gz` 压缩包的内容,输入:
|
||||
|
||||
```
|
||||
$ tar -zxvf project.tar.gz
|
||||
```
|
||||
|
||||
**注意**: 如果当前目录中有文件或子目录与归档文件中的内容同名,那么在提取归档文件时,这些文件或子目录将被覆盖。如果你不知道归档中包含哪些文件,请考虑先查看归档文件的内容。
|
||||
|
||||
在提取归档内容之前列出其内容的另一个原因是,确定归档中的内容是否包含在目录中。如果没有,而当前目录中包含许多不相关的文件,那么你可能将它们与归档中提取的文件混淆。
|
||||
|
||||
要将文件提取到它们自己的目录中,新建一个目录,将归档文件移到该目录,然后你就可以在新目录中提取文件。
|
||||
|
||||
### FAQ
|
||||
|
||||
现在我们已经学习了如何创建归档文件并列出和提取其内容,接下来我们可以继续讨论 Linux 专业人员经常被问到的 9 个实用问题。
|
||||
|
||||
#### 可以在不解压缩的情况下添加内容到压缩包中吗?
|
||||
|
||||
很不幸,一旦文件将被压缩,就无法向其添加内容。你需要解压缩或提取其内容,然后编辑或添加内容,最后再次压缩文件。如果文件很小,这个过程不会花费很长时间,否则请等待一会。
|
||||
|
||||
#### 可以在不解压缩的情况下删除归档文件中的内容吗?
|
||||
|
||||
这取决压缩时使用的 tar 版本。较新版本的 `tar` 支持 `-delete` 选项。
|
||||
|
||||
例如,假设归档文件中有 `file1` 和 `file2`,可以使用以下命令将它们从 `file.tar` 中删除:
|
||||
|
||||
|
||||
```
|
||||
$ tar -vf file.tar –delete file1 file2
|
||||
```
|
||||
|
||||
删除目录 `dir1`:
|
||||
|
||||
```
|
||||
$ tar -f file.tar –delete dir1/*
|
||||
```
|
||||
|
||||
#### 压缩和归档之间有什么区别?
|
||||
|
||||
查看归档和压缩之间差异最简单的方法是查看其解压大小。归档文件时,会将多个文件合并为一个。所以,如果我们归档 10 个 100kb 文件,则最终会得到一个 100kb 大小的文件。而如果压缩这些文件,则最终可能得到一个只有几 kb 或接近 100kb 的文件。
|
||||
|
||||
#### 如何压缩归档文件?
|
||||
|
||||
如上所说,你可以使用带有 `cvf` 选项的 `tar` 命令来创建和归档文件。要压缩归档文件,有两个选择:通过压缩程序(例如 `gzip`)运行归档文件,或在使用 `tar` 命令时使用压缩选项。最常见的压缩标志 `-z` 表示 `gzip`,`-j` 表示 `bzip`,`-J` 表示 `xz`。例如:
|
||||
|
||||
```
|
||||
$ gzip file.tar
|
||||
```
|
||||
|
||||
或者,我们可以在使用 `tar` 命令时使用压缩标志,以下命令使用 `gzip` 标志 `z`:
|
||||
|
||||
```
|
||||
$ tar -cvzf file.tar /some/directory
|
||||
```
|
||||
|
||||
#### 如何一次创建多个目录和/或文件的归档?
|
||||
|
||||
一次要归档多个文件,这种情况并不少见。一次归档多个文件和目录并不像你想的那么难,你只需要提供多个文件或目录作为 tar 的参数即可:
|
||||
|
||||
```
|
||||
$ tar -cvzf file.tar file1 file2 file3
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
$ tar -cvzf file.tar /some/directory1 /some/directory2
|
||||
```
|
||||
|
||||
#### 创建归档时如何跳过目录和/或文件?
|
||||
|
||||
你可能会遇到这样的情况:要归档一个目录或文件,但不是所有文件,这种情况下可以使用 `--exclude` 选项:
|
||||
|
||||
```
|
||||
$ tar –exclude ‘/some/directory’ -cvf file.tar /home/user
|
||||
```
|
||||
|
||||
在示例中,`/home/user` 目录中除了 `/some/directory` 之外都将被归档。将 `--exclude` 选项放在源和目标之前,并用单引号将要排除的文件或目录引起来,这一点很重要。
|
||||
|
||||
### 总结
|
||||
|
||||
`tar` 命令对展示不需要的文件创建备份或压缩文件很有用。在更改文件之前备份它们是一个很好的做法。如果某些东西在更改后没有按预期正常工作,你始终可以还原到旧文件。压缩不再使用的文件有助于保持系统干净,并降低磁盘空间使用率。还有其它实用程序可以归档或压缩,但是 `tar` 因其多功能、易用性和受欢迎程度而独占鳌头。
|
||||
|
||||
### 资源
|
||||
|
||||
如果你想了解有关 Linux 的更多信息,强烈建议阅读以下文章和教程:
|
||||
|
||||
* [Linux 文件系统架构和管理综述][5]
|
||||
* [Linux 文件和目录系统工作原理的全面回顾][6]
|
||||
* [所有 Linux 系统发行版的综合列表][7]
|
||||
* [特殊用途 Linux 发行版的综合列表][8]
|
||||
* [Linux 系统管理指南 - 制作和管理备份操作的最佳实践][9]
|
||||
* [Linux 系统管理指南 - Linux 虚拟内存和磁盘缓冲区缓存概述][10]
|
||||
* [Linux 系统管理指南 - 监控 Linux 的最佳实践][11]
|
||||
* [Linux 系统管理指南 - Linux 启动和关闭的最佳实践][12]
|
||||
|
||||
### 关于作者
|
||||
|
||||
**Matt Zand** 是一位创业者,也是 3 家科技创业公司的创始人: [DC Web Makers][13]、[Coding Bootcamps][14] 和 [High School Technology Services][15]。他也是 [使用 Hyperledger Fabric 进行智能合约开发][16] 一书的主要作者。他为 Hyperledger、以太坊和 Corda R3 平台编写了 100 多篇关于区块链开发的技术文章和教程。在 DC Web Makers,他领导了一个区块链专家团队,负责咨询和部署企业去中心化应用程序。作为首席架构师,他为编码训练营设计和开发了区块链课程和培训项目。他拥有马里兰大学工商管理硕士学位。在区块链开发和咨询之前,他曾担任一些初创公司的高级网页和移动应用程序开发和顾问、天使投资人和业务顾问。你可以通过以下这个网址和他取得联系: <https://www.linkedin.com/in/matt-zand-64047871>。
|
||||
|
||||
**Kevin Downs** 是 Red Hat 认证的系统管理员和 RHCSA。他目前在 IBM 担任系统管理员,负责管理数百台运行在不同 Linux 发行版上的服务器。他是[编码训练营][17]的首席 Linux 讲师,并且他会讲授 [5 个自己的课程][18]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/news/how-to-create-and-manage-archive-files-in-linux-2/
|
||||
|
||||
作者:[LF Training][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://training.linuxfoundation.org/announcements/how-to-create-and-manage-archive-files-in-linux/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://learn.coding-bootcamps.com/p/essential-practical-guide-to-cybersecurity-for-system-admin-and-developers
|
||||
[2]: https://learn.coding-bootcamps.com/p/introduction-to-cloud-technology
|
||||
[3]: https://training.linuxfoundation.org/wp-content/uploads/2020/12/Linux1-300x94.png
|
||||
[4]: https://training.linuxfoundation.org/wp-content/uploads/2020/12/Linux2-300x110.png
|
||||
[5]: https://blockchain.dcwebmakers.com/blog/linux-os-file-system-architecture-and-management.html
|
||||
[6]: https://coding-bootcamps.com/linux/filesystem/index.html
|
||||
[7]: https://myhsts.org/tutorial-list-of-all-linux-operating-system-distributions.php
|
||||
[8]: https://coding-bootcamps.com/list-of-all-special-purpose-linux-distributions.html
|
||||
[9]: https://myhsts.org/tutorial-system-admin-best-practices-for-managing-backup-operations.php
|
||||
[10]: https://myhsts.org/tutorial-how-linux-virtual-memory-and-disk-buffer-cache-work.php
|
||||
[11]: https://myhsts.org/tutorial-system-admin-best-practices-for-monitoring-linux-systems.php
|
||||
[12]: https://myhsts.org/tutorial-best-practices-for-performing-linux-boots-and-shutdowns.php
|
||||
[13]: https://blockchain.dcwebmakers.com/
|
||||
[14]: http://coding-bootcamps.com/
|
||||
[15]: https://myhsts.org/
|
||||
[16]: https://www.oreilly.com/library/view/hands-on-smart-contract/9781492086116/
|
||||
[17]: https://coding-bootcamps.com/
|
||||
[18]: https://learn.coding-bootcamps.com/courses/author/758905
|
||||
[19]: https://training.linuxfoundation.org/announcements/how-to-create-and-manage-archive-files-in-linux/
|
||||
[20]: https://training.linuxfoundation.org/
|
@ -0,0 +1,125 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (mengxinayan)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13132-1.html)
|
||||
[#]: subject: (10 ways to get started with open source in 2021)
|
||||
[#]: via: (https://opensource.com/article/21/1/getting-started-open-source)
|
||||
[#]: author: (Lauren Maffeo https://opensource.com/users/lmaffeo)
|
||||
|
||||
2021 年开始使用开源的 10 种方式
|
||||
======
|
||||
|
||||
> 如果你刚开始接触开源,那么下面的 2020 年十篇好文章有助于指导你的发展之路。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/19/110943di1i609a9spys1i1.jpg)
|
||||
|
||||
我们存在的意义是为了向世界宣传开源的一切,从新工具到框架拓展到社区。我们的目标是让想要使用开源或为开源做贡献的人更容易参与其中。
|
||||
|
||||
入门开源可能很难,所以我们定期分享如何参与其中的提示和建议。如果你想要学习 Python,帮助抗击 COVID-19,或者加入 K8s 设置,我们将为你服务。
|
||||
|
||||
为了帮助你开始,我们总结了 2020 年发布的 10 篇最流行的开源入门文章。希望它们能激发你在 2021 年学习一些新知识。
|
||||
|
||||
### 《利用 Python 爬取网站的新手指南》
|
||||
|
||||
你是否想通过实践而不是阅读来学习 Python?在本教程中,Julia Piaskowski 将会指导你完成她的第一个[Python 网页爬取项目][2]。她具体展示了如何使用 Python 的 `requests` 库访问网页内容。
|
||||
|
||||
Julia 详细介绍了每一步,从安装 Python3 到使用 Pandas 来清理 Web 抓取结果。她利用了大量截图解释了如何以最终目标为目的进行爬取。
|
||||
|
||||
有关爬取相关内容的部分特别有用;当遇到困难处时,她会详细解释。但是,与本文的其余部分一样,她会指导你完成每个步骤。
|
||||
|
||||
### 《在 Linux 上使用 SSH 进行远程连接的初学者指南》
|
||||
|
||||
如果你之前从未使用过安全 shell(SSH),那么你在第一次使用时可能会感到困惑。在本教程中,Seth Kenlon 展示了[如何为两台计算机之间配置 SSH 连接][3],以及如何不使用密码而安全地进行连接。
|
||||
|
||||
Seth 解释了建立 SSH 连接的每个步骤,从你应该了解的四个关键术语到在每个主机上激活 SSH 的步骤。他还提供了有关查找计算机 IP 地址、创建 SSH 密钥以及对远程计算机的远程访问权限的建议。
|
||||
|
||||
### 《五步学会任何编程语言》
|
||||
|
||||
如果你已经掌握了一种编程语言,你就能[学习所有的语言][4]。这是 Seth Kenlon 编写本文的前提,他认为了解一些基本编程逻辑便可以跨语言拓展。
|
||||
|
||||
Seth 分享了程序员在学习一种新的编程语言或编码方式时所需要的五种东西。语法、内置函数和解析器是这五种之一,他对每一种都附上了行动步骤。
|
||||
|
||||
那么将它们统一起来的关键方式是?一旦了解了代码工作原理,你就可以跨语言拓展。对你来说,没有什么是太难学的。
|
||||
|
||||
### 《为 COVID-19 贡献开源医疗项目》
|
||||
|
||||
你是否知道一家意大利医院通过 3D 打印机设备挽救了 COVID-19 患者的生命?这是开源贡献者为 2020 年 COVID-19 大流行[建立的众多解决方案之一][5]。
|
||||
|
||||
在本文中,Joshua Pearce 分享了针对 COVID-19 的开源志愿服务项目。虽然 Open Air 是最大的项目,但 Joshua 解释了如何为开源呼吸机的维基工作,编写开源 COVID-19 医疗供应要求,测试开源氧气浓缩机原型等。
|
||||
|
||||
### 《GNOME 入门建议》
|
||||
|
||||
GNOME 是最受欢迎的 Linux 桌面之一,但是它适合你吗?本文分享了[来自 GNOME 用户的建议][6],以及有关此主题的文章。
|
||||
|
||||
想要在配置桌面上寻找一些灵感吗?本文包含了有关 GNOME 扩展入门,将 Dash 安装到 Dock,使用 GNOME Tweak 工具等的链接。
|
||||
|
||||
不过,你仍然可能会认为 GNOME 不适合你——不用担心,最后你将找到指向其他 Linux 桌面和窗口管理器的链接。
|
||||
|
||||
### 《现在开始为开源做贡献的 3 个理由》
|
||||
|
||||
截至到 2020 年 6 月,Github 托管了超过 180,000 个公共仓库。现如今加入开源社区比过去更容易,但这是否意味着你应该加入开源?在本文中,Jason Blais [分享了三个投身开源的原因][7]。
|
||||
|
||||
为开源做贡献可以增强你的信心、简历和专业网络。Jason 还解释了如何利用有用的信息,从如何在领英个人资料中添加开源信息,到如何将这些贡献转变为付费角色。最后还列出了供初学者参与的出色项目。
|
||||
|
||||
### 《作为 Linux 系统管理员为开源做贡献的 4 种方法》
|
||||
|
||||
系统管理员是开源的无名英雄。他们在代码背后做了大量工作,这些代码非常有价值,但通常是看不见的。
|
||||
|
||||
在本文中,Elizabeth K. Joseph 介绍了她如何以 Linux 系统管理员的身份[来改善开源项目][8]。用户支持、托管项目资源、寻找新的网站环境是让社区比她发现时变得更好的几种方式。
|
||||
|
||||
也许最重要的贡献是什么?文档!Elizabeth 在开源领域的起步是她为使用的项目重写了快速入门指南。向你经常使用的项目提交错误和补丁报告是参与其中的理想方法。
|
||||
|
||||
### 《为 Slack 的开源替代品做出贡献的 6 种方法》
|
||||
|
||||
Mattermost 是一个很受欢迎的平台,适合那些想要一个开源消息传递系统的团队的平台。其活跃、充满活力的社区是让用户保持忠诚度的关键因素,尤其是对那些具有 Go、React 和 DevOps 经验的用户。
|
||||
|
||||
如果你想[为 Mattermost 做出贡献][9],Jason Blais 具体介绍了如何参与其中。将本文视为你的入门文档:Blais 分享了你要采取的步骤,并介绍了你可以做出的六种贡献。
|
||||
|
||||
无论你是要构建一个集成还是本地化你的语言,本文都将介绍如何进行。
|
||||
|
||||
### 《如何为 Kubernetes 做贡献》
|
||||
|
||||
当我走进 2018 年温哥华青年开源峰会时,还很年轻,对 Kubernetes 一无所知。主题演讲结束后,我离开会场后依然是一个有所改变而依然困惑的女人。毫不夸张地说,Kubernetes 已经彻底改变了开源,这并不夸张:很难找到一个更受欢迎、更有影响力的项目。
|
||||
|
||||
如果你想做出贡献,那么 IBM 工程师 Tara Gu 介绍了[她是如何开始的][10]。本文介绍了她在 All Things Open 2019 会议上的闪电演讲的回顾以及包括她亲自演讲的视频。还记得吗?
|
||||
|
||||
### 《任何人如何在工作中为开源软件做出贡献》
|
||||
|
||||
需求是发明之母,尤其是在开源领域。许多人针对自己遇到的问题构建开源解决方案。但是如果开发人员在没有收集目标用户反馈的情况下通过构建产品而错过了目标,会发生什么呢?
|
||||
|
||||
在企业中,产品和设计团队通常会填补这一空白。如果开源团队中不存在这样的角色,开发人员应该怎么做?
|
||||
|
||||
在本文中,Catherine Robson 介绍了开源团队如何从目标用户那里[收集反馈][11]。它为希望与开发人员分享他们的工作经验,从而将他们的反馈贡献到开源项目的人们而编写。
|
||||
|
||||
Catherine 概述的步骤将帮助你与开源团队分享你的见解,并在帮助团队开发更好的产品方面发挥关键作用。
|
||||
|
||||
### 你想要学习什么?
|
||||
|
||||
你想了解开源入门哪些方面的知识?请在评论中分享你对文章主题的建议。同时如果你有故事可以分享,以帮助他人开始使用开源软件,请考虑[撰写文章][12]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/getting-started-open-source
|
||||
|
||||
作者:[Lauren Maffeo][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[萌新阿岩](https://github.com/mengxinayan)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/lmaffeo
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/career_journey_road_gps_path_map_520.png?itok=PpL6jJgY (Looking at a map for career journey)
|
||||
[2]: https://linux.cn/article-13047-1.html
|
||||
[3]: https://opensource.com/article/20/9/ssh
|
||||
[4]: https://linux.cn/article-12842-1.html
|
||||
[5]: https://opensource.com/article/20/3/volunteer-covid19
|
||||
[6]: https://opensource.com/article/20/6/gnome-users
|
||||
[7]: https://opensource.com/article/20/6/why-contribute-open-source
|
||||
[8]: https://opensource.com/article/20/7/open-source-sysadmin
|
||||
[9]: https://opensource.com/article/20/7/mattermost
|
||||
[10]: https://opensource.com/article/20/1/contributing-kubernetes-all-things-open-2019
|
||||
[11]: https://opensource.com/article/20/10/open-your-job
|
||||
[12]: https://opensource.com/how-submit-article
|
@ -0,0 +1,286 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "amwps290"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13087-1.html"
|
||||
[#]: subject: "Learn JavaScript by writing a guessing game"
|
||||
[#]: via: "https://opensource.com/article/21/1/learn-javascript"
|
||||
[#]: author: "Mandy Kendall https://opensource.com/users/mkendall"
|
||||
|
||||
通过编写一个简单的游戏学习 JavaScript
|
||||
======
|
||||
|
||||
> 通过使用一个简单的游戏来练习一些基本的 JavaScript 概念,迈出创建交互性动态 Web 内容的第一步。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/05/151531z6fzqx8vk8tdan81.jpg)
|
||||
|
||||
可以肯定地说,没有 [JavaScript][2],大多数现代 Web 都将不存在。它是三种标准 Web 技术(以及 HTML 和 CSS )之一,它使任何人都可以创建我们在万维网体验中所期待的交互式、动态内容。从 [React][3] 这样的框架到 [D3][4] 这样的数据可视化库,很难想象没有它的 Web。
|
||||
|
||||
现在有很多东西要学习,开始学习这种流行语言的好方法是编写一个简单的应用程序以熟悉某些概念。 最近,一些人写了关于如何通过编写简单的猜谜游戏来学习自己喜欢的语言的文章,因此这是一个很好的起点!
|
||||
|
||||
### 现在开始吧
|
||||
|
||||
JavaScript 有许多种风格,但我将从最基本的开始,通常称为 “普通 JavaScript”。 JavaScript 主要是一种客户端脚本语言,因此它可以在任何标准浏览器中运行,而无需安装任何程序。你只需要一个代码编辑器([Brackets][5] 就是一个不错的选择)和一个 Web 浏览器。
|
||||
|
||||
### HTML 用户界面
|
||||
|
||||
JavaScript 在 Web 浏览器中运行,并与其他标准 Web 技术 HTML 和 CSS 交互。要创建此游戏,你首先需要使用 HTML(超文本标记语言)来创建供玩家使用的简单界面。如果你不清楚,HTML 是一种标记语言,用于为 Web 内容提供结构。
|
||||
|
||||
首先,先创建一个 HTML 文件。该文件应具有 `.html` 扩展名,以使浏览器知道它是 HTML 文档。你可以将文件命名为 `guessingGame.html`。
|
||||
|
||||
在此文件中使用一些基本的 HTML 标签来显示游戏的标题、玩法说明,供玩家用来输入和提交其猜测的交互式元素以及用于向玩家提供反馈的占位符:
|
||||
|
||||
```
|
||||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title> JavaScript Guessing Game </title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Guess the Number!</h1>
|
||||
<p>I am thinking of a number between 1 and 100. Can you guess what it is?</p>
|
||||
|
||||
<label for="guess">My Guess</label>
|
||||
<input type="number" id="guess">
|
||||
<input type="submit" id="submitGuess" value="Check My Guess">
|
||||
|
||||
<p id="feedback"></p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
`<h1>` 和 `<p>` 元素使浏览器知道在页面上显示什么类型的文本。标签对 `<h1></h1>` 表示标签之间的文本(`Guess the Number!`)是标题。后面的一组 `<p>` 标签表示带有说明的短文本是一个段落。此代码块末尾的空 `<p>` 标签用作占位符,用于根据用户的输入提供一些反馈。
|
||||
|
||||
### `<script>` 标签
|
||||
|
||||
在网页中包含 JavaScript 的方法有很多种,但是对于像这样的简短脚本,可以使用一组 `<script>` 标签并将 JavaScript 直接写在 HTML 文件中。 这些 `<script>` 标签应位于 HTML 文件末尾附近的 `</body>` 标签之前。
|
||||
|
||||
现在,你可以开始在这两个脚本标签之间编写 JavaScript。 最终文件如下所示:
|
||||
|
||||
```
|
||||
<!DOCTYPE>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title> JavaScript Guessing Game </title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Guess the Number!</h1>
|
||||
<p>I am thinking of a number between 1 and 100. Can you guess what it is?</p>
|
||||
|
||||
<form>
|
||||
<label for="guess">My Guess</label>
|
||||
<input type="number" id="guess">
|
||||
<input type="submit" id="submitGuess" value="Check My Guess">
|
||||
</form>
|
||||
|
||||
<p id="feedback"></p>
|
||||
|
||||
<script>
|
||||
const randomNumber = Math.floor(Math.random() * 100) + 1
|
||||
console.log('Random Number', randomNumber)
|
||||
|
||||
function checkGuess() {
|
||||
let myGuess = guess.value
|
||||
if (myGuess === randomNumber) {
|
||||
feedback.textContent = "You got it right!"
|
||||
} else if (myGuess > randomNumber) {
|
||||
feedback.textContent = "Your guess was " + myGuess + ". That's too high. Try Again!"
|
||||
} else if (myGuess < randomNumber) {
|
||||
feedback.textContent = "Your guess was " + myGuess + ". That's too low. Try Again!"
|
||||
}
|
||||
}
|
||||
submitGuess.addEventListener('click', checkGuess)
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
要在浏览器中运行此文件,请双击文件或打开你喜欢的浏览器,点击菜单,然后选择**文件->打开文件**。(如果使用 Brackets 软件,也可以使用角落处的闪电图标在浏览器中打开文件)。
|
||||
|
||||
### 生成伪随机数
|
||||
|
||||
猜谜游戏的第一步是为玩家生成一个数字供玩家猜测。JavaScript 包含几个内置的全局对象,可帮助你编写代码。要生成随机数,请使用 `Math` 对象。
|
||||
|
||||
JavaScript中的 [Math][17] 具有处理和数学相关的属性和功能。你将使用两个数学函数来生成随机数,供你的玩家猜测。
|
||||
|
||||
[Math.random()][18],会将生成一个介于 0 和 1 之间的伪随机数。(`Math.random` 包含 0 但不包含 1。这意味着该函数可以生成 0 ,永远不会产生 1)
|
||||
|
||||
对于此游戏,请将随机数设置在 1 到 100 之间以缩小玩家的选择范围。取刚刚生成的小数,然后乘以 100,以产生一个介于 0 到……甚至不是 100 之间的小数。至此,你将需要其他步骤来解决这个问题。
|
||||
|
||||
现在,你的数字仍然是小数,但你希望它是一个整数。为此,你可以使用属于 `Math` 对象的另一个函数 [Math.floor()][19]。`Math.floor()` 的目的是返回小于或等于你作为参数指定的数字的最大整数,这意味着它会四舍五入为最接近的整数:
|
||||
|
||||
```
|
||||
Math.floor(Math.random() * 100)
|
||||
```
|
||||
|
||||
这样你将得到 0 到 99 之间的整数,这不是你想要的范围。你可以在最后一步修复该问题,即在结果中加 1。瞧!现在,你有一个(有点)随机生成的数字,介于 1 到 100 之间:
|
||||
|
||||
```
|
||||
Math.floor(Math.random() * 100) + 1
|
||||
```
|
||||
|
||||
### 变量
|
||||
|
||||
现在,你需要存储随机生成的数字,以便可以将其与玩家的猜测进行比较。为此,你可以将其存储到一个 **变量**。
|
||||
|
||||
JavaScript 具有不同类型的变量,你可以选择这些类型,具体取决于你要如何使用该变量。对于此游戏,请使用 `const` 和 `let`。
|
||||
|
||||
* `let` 用于指示变量在整个程序中可以改变。
|
||||
* `const` 用于指示变量不应该被修改。
|
||||
|
||||
`const` 和 `let` 还有很多要说的,但现在知道这些就足够了。
|
||||
|
||||
随机数在游戏中仅生成一次,因此你将使用 `const` 变量来保存该值。你想给变量起一个清楚地表明要存储什么值的名称,因此将其命名为 `randomNumber`:
|
||||
|
||||
```
|
||||
const randomNumber
|
||||
```
|
||||
|
||||
有关命名的注意事项:JavaScript 中的变量和函数名称以驼峰形式编写。如果只有一个单词,则全部以小写形式书写。如果有多个单词,则第一个单词均为小写,其他任何单词均以大写字母开头,且单词之间没有空格。
|
||||
|
||||
### 打印到控制台
|
||||
|
||||
通常,你不想向任何人显示随机数,但是开发人员可能想知道生成的数字以使用它来帮助调试代码。 使用 JavaScript,你可以使用另一个内置函数 [console.log()][20] 将数字输出到浏览器的控制台。
|
||||
|
||||
大多数浏览器都包含开发人员工具,你可以通过按键盘上的 `F12` 键来打开它们。从那里,你应该看到一个 **控制台** 标签。打印到控制台的所有信息都将显示在此处。由于到目前为止编写的代码将在浏览器加载后立即运行,因此,如果你查看控制台,你应该会看到刚刚生成的随机数!
|
||||
|
||||
![Javascript game with console][21]
|
||||
|
||||
### 函数
|
||||
|
||||
接下来,你需要一种方法来从数字输入字段中获得玩家的猜测,将其与你刚刚生成的随机数进行比较,并向玩家提供反馈,让他们知道他们是否正确猜到了。为此,编写一个函数。 **函数** 是执行一定任务的代码块。函数是可以重用的,这意味着如果你需要多次运行相同的代码,则可以调用函数,而不必重写执行任务所需的所有步骤。
|
||||
|
||||
根据你使用的 JavaScript 版本,有许多不同的方法来编写或声明函数。由于这是该语言的基础入门,因此请使用基本函数语法声明函数。
|
||||
|
||||
以关键字 `function` 开头,然后起一个函数名。好的做法是使用一个描述该函数的功能的名称。在这个例子中,你正在检查玩家的猜测的数,因此此函数的名字可以是 `checkGuess`。在函数名称之后,写上一组小括号,然后写上一组花括号。 你将在以下花括号之间编写函数的主体:
|
||||
|
||||
```
|
||||
function checkGuess() {}
|
||||
```
|
||||
|
||||
### 使用 DOM
|
||||
|
||||
JavaScript 的目的之一是与网页上的 HTML 交互。它通过文档对象模型(DOM)进行此操作,DOM 是 JavaScript 用于访问和更改网页信息的对象。现在,你需要从 HTML 中获取数字输入字段中玩家的猜测。你可以使用分配给 HTML 元素的 `id` 属性(在这种情况下为 `guess`)来做到这一点:
|
||||
|
||||
```
|
||||
<input type="number" id="guess">
|
||||
```
|
||||
|
||||
JavaScript 可以通过访问玩家输入到数字输入字段中的数来获取其值。你可以通过引用元素的 ID 并在末尾添加 `.value` 来实现。这次,使用 `let` 定义的变量来保存用户的猜测值:
|
||||
|
||||
```
|
||||
let myGuess = guess.value
|
||||
```
|
||||
|
||||
玩家在数字输入字段中输入的任何数字都将被分配给 `checkGuess` 函数中的 `myGuess` 变量。
|
||||
|
||||
### 条件语句
|
||||
|
||||
下一步是将玩家的猜测与游戏产生的随机数进行比较。你还想给玩家反馈,让他们知道他们的猜测是太高,太低还是正确。
|
||||
|
||||
你可以使用一系列条件语句来决定玩家将收到的反馈。**条件语句** 在运行代码块之前检查是否满足条件。如果不满足条件,则代码停止,继续检查下一个条件,或者继续执行其余代码,而无需执行条件块中的代码:
|
||||
|
||||
```
|
||||
if (myGuess === randomNumber){
|
||||
feedback.textContent = "You got it right!"
|
||||
}
|
||||
else if(myGuess > randomNumber) {
|
||||
feedback.textContent = "Your guess was " + myGuess + ". That's too high. Try Again!"
|
||||
}
|
||||
else if(myGuess < randomNumber) {
|
||||
feedback.textContent = "Your guess was " + myGuess + ". That's too low. Try Again!"
|
||||
}
|
||||
```
|
||||
|
||||
第一个条件块使用比较运算符 `===` 将玩家的猜测与游戏生成的随机数进行比较。比较运算符检查右侧的值,将其与左侧的值进行比较,如果匹配则返回布尔值 `true`,否则返回布尔值 `false`。
|
||||
|
||||
如果数字匹配(猜对了!),为了让玩家知道。通过将文本添加到具有 `id` 属性 `feedback` 的 `<p>` 标记中来操作 DOM。就像上面的 `guess.value` 一样,除了不是从 DOM 获取信息,而是更改其中的信息。`<p>` 元素没有像 `<input>` 元素那样的值,而是具有文本,因此请使用 `.textContent` 访问元素并设置要显示的文本:
|
||||
|
||||
```
|
||||
feedback.textContent = "You got it right!"
|
||||
```
|
||||
|
||||
当然,玩家很有可能在第一次尝试时就猜错了,因此,如果 `myGuess` 和 `randomNumber` 不匹配,请给玩家一个线索,以帮助他们缩小猜测范围。如果第一个条件失败,则代码将跳过该 `if` 语句中的代码块,并检查下一个条件是否为 `true`。 这使你进入 `else if` 块:
|
||||
|
||||
```
|
||||
else if(myGuess > randomNumber) {
|
||||
feedback.textContent = "Your guess was " + myGuess + ". That's too high. Try Again!"
|
||||
}
|
||||
```
|
||||
|
||||
如果你将其作为句子阅读,则可能是这样的:“如果玩家的猜测等于随机数,请让他们知道他们猜对了。否则,请检查玩家的猜测是否大于 `randomNumber`,如果是,则显示玩家的猜测并告诉他们太高了。”
|
||||
|
||||
最后一种可能性是玩家的猜测低于随机数。 要检查这一点,再添加一个 `else if` 块:
|
||||
|
||||
```
|
||||
else if(myGuess < randomNumber) {
|
||||
feedback.textContent = "Your guess was " + myGuess + ". That's too low. Try Again!"
|
||||
}
|
||||
```
|
||||
|
||||
### 用户事件和事件监听器
|
||||
|
||||
如果你看上面的代码,则会看到某些代码在页面加载时自动运行,但有些则不会。你想在玩游戏之前生成随机数,但是你不想在玩家将数字输入到数字输入字段并准备检查它之前检查其猜测。
|
||||
|
||||
生成随机数并将其打印到控制台的代码不在函数的范围内,因此它将在浏览器加载脚本时自动运行。 但是,要使函数内部的代码运行,你必须对其进行调用。
|
||||
|
||||
调用函数有几种方法。在此,你希望该函数在用户单击 “Check My Guess” 按钮时运行。单击按钮将创建一个用户事件,然后 JavaScript 可以 “监听” 这个事件,以便知道何时需要运行函数。
|
||||
|
||||
代码的最后一行将事件侦听器添加到按钮上,以在单击按钮时调用函数。当它“听到”该事件时,它将运行分配给事件侦听器的函数:
|
||||
|
||||
```
|
||||
submitGuess.addEventListener('click', checkGuess)
|
||||
```
|
||||
|
||||
就像访问 DOM 元素的其他实例一样,你可以使用按钮的 ID 告诉 JavaScript 与哪个元素进行交互。 然后,你可以使用内置的 `addEventListener` 函数来告诉 JavaScript 要监听的事件。
|
||||
|
||||
你已经看到了带有参数的函数,但花点时间看一下它是如何工作的。参数是函数执行其任务所需的信息。并非所有函数都需要参数,但是 `addEventListener` 函数需要两个参数。它采用的第一个参数是将为其监听的用户事件的名称。用户可以通过多种方式与 DOM 交互,例如键入、移动鼠标,键盘上的 `TAB` 键和粘贴文本。在这种情况下,你正在监听的用户事件是单击按钮,因此第一个参数将是 `click`。
|
||||
|
||||
`addEventListener`的第二个所需的信息是用户单击按钮时要运行的函数的名称。 这里我们需要 `checkGuess` 函数。
|
||||
|
||||
现在,当玩家按下 “Check My Guess” 按钮时,`checkGuess` 函数将获得他们在数字输入字段中输入的值,将其与随机数进行比较,并在浏览器中显示反馈,以使玩家知道他们猜的怎么样。 太棒了!你的游戏已准备就绪。
|
||||
|
||||
### 学习 JavaScript 以获取乐趣和收益
|
||||
|
||||
这一点点的平凡无奇的 JavaScript 只是这个庞大的生态系统所提供功能的一小部分。这是一种值得花时间投入学习的语言,我鼓励你继续挖掘并学习更多。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/learn-javascript
|
||||
|
||||
作者:[Mandy Kendall][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[amwps290](https://github.com/amwps290)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mkendall
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_javascript.jpg?itok=60evKmGl "Javascript code close-up with neon graphic overlay"
|
||||
[2]: https://opensource.com/tags/javascript
|
||||
[3]: https://opensource.com/article/20/11/reactjs-tutorial
|
||||
[4]: https://opensource.com/article/18/9/open-source-javascript-chart-libraries
|
||||
[5]: https://opensource.com/article/20/12/brackets
|
||||
[6]: http://december.com/html/4/element/html.html
|
||||
[7]: http://december.com/html/4/element/head.html
|
||||
[8]: http://december.com/html/4/element/meta.html
|
||||
[9]: http://december.com/html/4/element/title.html
|
||||
[10]: http://december.com/html/4/element/body.html
|
||||
[11]: http://december.com/html/4/element/h1.html
|
||||
[12]: http://december.com/html/4/element/p.html
|
||||
[13]: http://december.com/html/4/element/label.html
|
||||
[14]: http://december.com/html/4/element/input.html
|
||||
[15]: http://december.com/html/4/element/form.html
|
||||
[16]: http://december.com/html/4/element/script.html
|
||||
[17]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math
|
||||
[18]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
|
||||
[19]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor
|
||||
[20]: https://developer.mozilla.org/en-US/docs/Web/API/Console/log
|
||||
[21]: https://opensource.com/sites/default/files/javascript-game-with-console.png "Javascript game with console"
|
@ -0,0 +1,70 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13077-1.html)
|
||||
[#]: subject: (How Nextcloud is the ultimate open source productivity suite)
|
||||
[#]: via: (https://opensource.com/article/21/1/nextcloud-productivity)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
Nextcloud 是如何成为终极开源生产力套件的
|
||||
======
|
||||
|
||||
> Nextcloud 可以取代你用于协作、组织和任务管理的许多在线应用。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/02/121553uhl3pjljjkhj0h8p.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十一天。
|
||||
|
||||
基于 Web 的服务几乎可以在任何地方访问你的数据,它们每小时可以支持数百万用户。不过对于我们中的一些人来说,由于各种原因,运行自己的服务比使用大公司的服务更可取。也许我们的工作是受监管的或有明确安全要求。也许我们有隐私方面的考虑,或者只是喜欢能够自己构建、运行和修复事物。不管是什么情况,[Nextcloud][2] 都可以提供你所需要的大部分服务,但是是在你自己的硬件上。
|
||||
|
||||
![NextCloud Dashboard displaying service options][3]
|
||||
|
||||
*Nextcloud 控制面板(Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
大多数时候,当我们想到 Nextcloud 时,我们会想到文件共享和同步,类似于 Dropbox、OneDrive 和 Google Drive 等商业产品。然而,如今,它是一个完整的生产力套件,拥有电子邮件客户端、日历、任务和笔记本。
|
||||
|
||||
有几种方法可以安装和运行 Nextcloud。你可以把它安装到裸机服务器上、在 Docker 容器中运行,或者作为虚拟机运行。如果可以考虑,还有一些托管服务将为你运行 Nextcloud。最后,有适用于所有主流操作系统的应用,包括移动应用,以便随时访问。
|
||||
|
||||
![Nextcloud virtual machine][5]
|
||||
|
||||
*Nextcloud 虚拟机(Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
默认情况下,Nextcloud 会安装文件共享和其他一些相关应用(或附加组件)。你可以在管理界面中找到“应用”页面,这里允许你安装单个附加组件和一些预定义的相关应用捆绑。对我而言,我选择了 “Groupware Bundle”,其中包括“邮件”、“日历”、“联系人”和 “Deck”。“Deck” 是一个轻量级的看板,用于处理任务。我也安装了“记事本”和“任务”应用。
|
||||
|
||||
Nextcloud “邮件” 是一个非常直白的 IMAP 邮件客户端。虽然 Nextcloud 没有将 IMAP 或 SMTP 服务器作为软件包的一部分,但你可以很容易地在操作系统中添加一个或使用远程服务。“日历”应用是相当标准的,也允许你订阅远程日历。有一个缺点是,远程日历(例如,来自大型云提供商)是只读的,所以你可以查看但不能修改它们。
|
||||
|
||||
![NextCoud App Interface][6]
|
||||
|
||||
*Nextcloud 应用界面 (Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
“记事本” 是一个简单的文本记事本,允许你创建和更新简短的笔记、日记和相关的东西。“任务” 是一款待办事项应用,支持多个列表、任务优先级、完成百分比以及其他一些用户期待的标准功能。如果你安装了 “Deck”,它的任务卡也会被列出来。每个看板都会显示自己的列表,所以你可以使用 “Deck” 或 “任务” 来跟踪完成的内容。
|
||||
|
||||
“Deck” 本身就是一个看板应用,将任务以卡片的形式呈现在流程中。如果你喜欢看板流程,它是一个追踪进度的优秀应用。
|
||||
|
||||
![Taking notes][7]
|
||||
|
||||
*做笔记 (Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
Nextcloud 中所有的应用都原生支持通过标准协议进行共享。与一些类似的解决方案不同,它的分享并不是为了完成功能列表中的一项而加上去的。分享是 Nextcloud 存在的主要原因之一,所以使用起来非常简单。你还可以将链接分享到社交媒体、通过电子邮件分享等。你可以用一个 Nextcloud 取代多个在线服务,它在任何地方都可以访问,以协作为先。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/nextcloud-productivity
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/team_dev_email_chat_video_work_wfm_desk_520.png?itok=6YtME4Hj (Working on a team, busy worklife)
|
||||
[2]: https://nextcloud.com/
|
||||
[3]: https://opensource.com/sites/default/files/day11-image1_0.png
|
||||
[4]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[5]: https://opensource.com/sites/default/files/pictures/nextcloud-vm.png (Nextcloud virtual machine)
|
||||
[6]: https://opensource.com/sites/default/files/pictures/nextcloud-app-interface.png (NextCoud App Interface)
|
||||
[7]: https://opensource.com/sites/default/files/day11-image3.png (Taking notes in Nextcloud)
|
@ -0,0 +1,60 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13073-1.html)
|
||||
[#]: subject: (3 tips for automating your email filters)
|
||||
[#]: via: (https://opensource.com/article/21/1/email-filter)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
3 个自动化电子邮件过滤器的技巧
|
||||
======
|
||||
|
||||
> 通过这些简单的建议,减少你的电子邮件并让你的生活更轻松。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/01/103638ozdejmy6eycm6omx.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十二天。
|
||||
|
||||
如果有一件事是我喜欢的,那就是自动化。只要有机会,我就会把小任务进行自动化。早起打开鸡舍的门?我买了一扇门,可以在日出和日落时开门和关门。每天从早到晚实时监控鸡群?用 Node-RED 和 [OBS-Websockets][2] 稍微花点时间,就能搞定。
|
||||
|
||||
我们还有电子邮件。几天前,我写过关于处理邮件的文章,也写过关于标签和文件夹的文章。只要做一点前期的工作,你就可以在邮件进来的时候,你就可以自动摆脱掉大量管理邮件的开销。
|
||||
|
||||
![Author has 480 filters][3]
|
||||
|
||||
*是的,我有很多过滤器。(Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
有两种主要方式来过滤你的电子邮件:在服务端或者客户端上。我更喜欢在服务端上做,因为我不断地在尝试新的和不同的电子邮件客户端。(不,真的,我光这个星期就已经使用了五个不同的客户端。我可能有问题。)
|
||||
|
||||
无论哪种方式,我都喜欢用电子邮件过滤规则做几件事,以使我的电子邮件更容易浏览,并保持我的收件箱不混乱。
|
||||
|
||||
1. 将不紧急的邮件移到“稍后阅读”文件夹中。对我而言,这包括来自社交网络、新闻简报和邮件列表的通知。
|
||||
2. 按列表或主题给消息贴上标签。我属于几个组织,虽然它们经常会被放在“稍后阅读”文件夹中,但我会添加第二个或第三个标签,以说明该来源或项目的内容,以帮助搜索时找到相关的东西。
|
||||
3. 不要把规则搞得太复杂。这个想法让我困难了一段时间。我想把邮件发送到某个文件夹的所有可能情况都加到一个规则里。如果有什么问题或需要添加或删除的东西,有一个大规则只是让它更难修复。
|
||||
|
||||
![Unsubscribe from email][5]
|
||||
|
||||
*点击它,点击它就行!(Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
说了这么多,还有一件事我一直在做,它有助于减少我花在电子邮件上的时间:退订邮件。两年前我感兴趣的那个邮件列表已经不感兴趣了,所以就不订阅了。产品更新通讯是我去年停止使用的商品?退订!这一直在积极解放我。我每年都会试着评估几次列表中的邮件信息是否(仍然)有用。
|
||||
|
||||
过滤器和规则可以是非常强大的工具,让你的电子邮件保持集中,减少花在它们身上的时间。而点击取消订阅按钮是一种解放。试试就知道了!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/email-filter
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/innovation_lightbulb_gears_devops_ansible.png?itok=TSbmp3_M (gears and lightbulb to represent innovation)
|
||||
[2]: https://opensource.com/article/20/6/obs-websockets-streaming
|
||||
[3]: https://opensource.com/sites/default/files/day12-image1_0.png
|
||||
[4]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[5]: https://opensource.com/sites/default/files/day12-image2_0.png
|
@ -0,0 +1,635 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13074-1.html)
|
||||
[#]: subject: (Explore binaries using this full-featured Linux tool)
|
||||
[#]: via: (https://opensource.com/article/21/1/linux-radare2)
|
||||
[#]: author: (Gaurav Kamathe https://opensource.com/users/gkamathe)
|
||||
|
||||
全功能的二进制文件分析工具 Radare2 指南
|
||||
======
|
||||
|
||||
> Radare2 是一个为二进制分析定制的开源工具。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/01/112611baw4gpqlch10ps1c.jpg)
|
||||
|
||||
在《[Linux 上分析二进制文件的 10 种方法][2]》中,我解释了如何使用 Linux 上丰富的原生工具集来分析二进制文件。但如果你想进一步探索你的二进制文件,你需要一个为二进制分析定制的工具。如果你是二进制分析的新手,并且大多使用的是脚本语言,这篇文章《[GNU binutils 里的九种武器][3]》可以帮助你开始学习编译过程和什么是二进制。
|
||||
|
||||
### 为什么我需要另一个工具?
|
||||
|
||||
如果现有的 Linux 原生工具也能做类似的事情,你自然会问为什么需要另一个工具。嗯,这和你用手机做闹钟、做笔记、做相机、听音乐、上网、偶尔打电话和接电话的原因是一样的。以前,使用单独的设备和工具处理这些功能 —— 比如拍照的实体相机,记笔记的小记事本,起床的床头闹钟等等。对用户来说,有一个设备来做多件(但相关的)事情是*方便的*。另外,杀手锏就是独立功能之间的*互操作性*。
|
||||
|
||||
同样,即使许多 Linux 工具都有特定的用途,但在一个工具中捆绑类似(和更好)的功能是非常有用的。这就是为什么我认为 [Radare2][4] 应该是你需要处理二进制文件时的首选工具。
|
||||
|
||||
根据其 [GitHub 简介][5],Radare2(也称为 r2)是一个“类 Unix 系统上的逆向工程框架和命令行工具集”。它名字中的 “2” 是因为这个版本从头开始重写的,使其更加模块化。
|
||||
|
||||
### 为什么选择 Radare2?
|
||||
|
||||
有大量(非原生的)Linux 工具可用于二进制分析,为什么要选择 Radare2 呢?我的理由很简单。
|
||||
|
||||
首先,它是一个开源项目,有一个活跃而健康的社区。如果你正在寻找新颖的功能或提供着 bug 修复的工具,这很重要。
|
||||
|
||||
其次,Radare2 可以在命令行上使用,而且它有一个功能丰富的图形用户界面(GUI)环境,叫做 Cutter,适合那些对 GUI 比较熟悉的人。作为一个长期使用 Linux 的用户,我对习惯于在 shell 上输入。虽然熟悉 Radare2 的命令稍微有一点学习曲线,但我会把它比作 [学习 Vim][6]。你可以先学习基本的东西,一旦你掌握了它们,你就可以继续学习更高级的东西。很快,它就变成了肌肉记忆。
|
||||
|
||||
第三,Radare2 通过插件可以很好的支持外部工具。例如,最近开源的 [Ghidra][7] 二进制分析和<ruby>逆向工具<rt>reversing tool</rt></ruby>很受欢迎,因为它的反编译器功能是逆向软件的关键要素。你可以直接从 Radare2 控制台安装 Ghidra 反编译器并使用,这很神奇,让你两全其美。
|
||||
|
||||
### 开始使用 Radare2
|
||||
|
||||
要安装 Radare2,只需克隆其存储库并运行 `user.sh` 脚本。如果你的系统上还没有一些预备软件包,你可能需要安装它们。一旦安装完成,运行 `r2 -v` 命令来查看 Radare2 是否被正确安装:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/radareorg/radare2.git
|
||||
$ cd radare2
|
||||
$ ./sys/user.sh
|
||||
|
||||
# version
|
||||
|
||||
$ r2 -v
|
||||
radare2 4.6.0-git 25266 @ linux-x86-64 git.4.4.0-930-g48047b317
|
||||
commit: 48047b3171e6ed0480a71a04c3693a0650d03543 build: 2020-11-17__09:31:03
|
||||
$
|
||||
```
|
||||
|
||||
#### 获取二进制测试样本
|
||||
|
||||
现在 `r2` 已经安装好了,你需要一个样本二进制程序来试用它。你可以使用任何系统二进制文件(`ls`、`bash` 等),但为了使本教程的内容简单,请编译以下 C 程序:
|
||||
|
||||
```
|
||||
$ cat adder.c
|
||||
```
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
int adder(int num) {
|
||||
return num + 1;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int res, num1 = 100;
|
||||
res = adder(num1);
|
||||
printf("Number now is : %d\n", res);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
$ gcc adder.c -o adder
|
||||
$ file adder
|
||||
adder: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=9d4366f7160e1ffb46b14466e8e0d70f10de2240, not stripped
|
||||
$ ./adder
|
||||
Number now is : 101
|
||||
```
|
||||
|
||||
#### 加载二进制文件
|
||||
|
||||
要分析二进制文件,你必须在 Radare2 中加载它。通过提供文件名作为 `r2` 命令的一个命令行参数来加载它。你会进入一个独立的 Radare2 控制台,这与你的 shell 不同。要退出控制台,你可以输入 `Quit` 或 `Exit` 或按 `Ctrl+D`:
|
||||
|
||||
```
|
||||
$ r2 ./adder
|
||||
-- Learn pancake as if you were radare!
|
||||
[0x004004b0]> quit
|
||||
$
|
||||
```
|
||||
|
||||
#### 分析二进制
|
||||
|
||||
在你探索二进制之前,你必须让 `r2` 为你分析它。你可以通过在 `r2` 控制台中运行 `aaa` 命令来实现:
|
||||
|
||||
```
|
||||
$ r2 ./adder
|
||||
-- Sorry, radare2 has experienced an internal error.
|
||||
[0x004004b0]>
|
||||
[0x004004b0]>
|
||||
[0x004004b0]> aaa
|
||||
[x] Analyze all flags starting with sym. and entry0 (aa)
|
||||
[x] Analyze function calls (aac)
|
||||
[x] Analyze len bytes of instructions for references (aar)
|
||||
[x] Check for vtables
|
||||
[x] Type matching analysis for all functions (aaft)
|
||||
[x] Propagate noreturn information
|
||||
[x] Use -AA or aaaa to perform additional experimental analysis.
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
这意味着每次你选择一个二进制文件进行分析时,你必须在加载二进制文件后输入一个额外的命令 `aaa`。你可以绕过这一点,在命令后面跟上 `-A` 来调用 `r2`;这将告诉 `r2` 为你自动分析二进制:
|
||||
|
||||
```
|
||||
$ r2 -A ./adder
|
||||
[x] Analyze all flags starting with sym. and entry0 (aa)
|
||||
[x] Analyze function calls (aac)
|
||||
[x] Analyze len bytes of instructions for references (aar)
|
||||
[x] Check for vtables
|
||||
[x] Type matching analysis for all functions (aaft)
|
||||
[x] Propagate noreturn information
|
||||
[x] Use -AA or aaaa to perform additional experimental analysis.
|
||||
-- Already up-to-date.
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
#### 获取一些关于二进制的基本信息
|
||||
|
||||
在开始分析一个二进制文件之前,你需要一些背景信息。在许多情况下,这可以是二进制文件的格式(ELF、PE 等)、二进制的架构(x86、AMD、ARM 等),以及二进制是 32 位还是 64 位。方便的 `r2` 的 `iI` 命令可以提供所需的信息:
|
||||
|
||||
```
|
||||
[0x004004b0]> iI
|
||||
arch x86
|
||||
baddr 0x400000
|
||||
binsz 14724
|
||||
bintype elf
|
||||
bits 64
|
||||
canary false
|
||||
class ELF64
|
||||
compiler GCC: (GNU) 8.3.1 20190507 (Red Hat 8.3.1-4)
|
||||
crypto false
|
||||
endian little
|
||||
havecode true
|
||||
intrp /lib64/ld-linux-x86-64.so.2
|
||||
laddr 0x0
|
||||
lang c
|
||||
linenum true
|
||||
lsyms true
|
||||
machine AMD x86-64 architecture
|
||||
maxopsz 16
|
||||
minopsz 1
|
||||
nx true
|
||||
os linux
|
||||
pcalign 0
|
||||
pic false
|
||||
relocs true
|
||||
relro partial
|
||||
rpath NONE
|
||||
sanitiz false
|
||||
static false
|
||||
stripped false
|
||||
subsys linux
|
||||
va true
|
||||
|
||||
[0x004004b0]>
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
### 导入和导出
|
||||
|
||||
通常情况下,当你知道你要处理的是什么样的文件后,你就想知道二进制程序使用了什么样的标准库函数,或者了解程序的潜在功能。在本教程中的示例 C 程序中,唯一的库函数是 `printf`,用来打印信息。你可以通过运行 `ii` 命令看到这一点,它显示了该二进制所有导入的库:
|
||||
|
||||
```
|
||||
[0x004004b0]> ii
|
||||
[Imports]
|
||||
nth vaddr bind type lib name
|
||||
―――――――――――――――――――――――――――――――――――――
|
||||
1 0x00000000 WEAK NOTYPE _ITM_deregisterTMCloneTable
|
||||
2 0x004004a0 GLOBAL FUNC printf
|
||||
3 0x00000000 GLOBAL FUNC __libc_start_main
|
||||
4 0x00000000 WEAK NOTYPE __gmon_start__
|
||||
5 0x00000000 WEAK NOTYPE _ITM_registerTMCloneTable
|
||||
```
|
||||
|
||||
该二进制也可以有自己的符号、函数或数据。这些函数通常显示在 `Exports` 下。这个测试的二进制导出了两个函数:`main` 和 `adder`。其余的函数是在编译阶段,当二进制文件被构建时添加的。加载器需要这些函数来加载二进制文件(现在不用太关心它们):
|
||||
|
||||
```
|
||||
[0x004004b0]>
|
||||
[0x004004b0]> iE
|
||||
[Exports]
|
||||
|
||||
nth paddr vaddr bind type size lib name
|
||||
――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||
82 0x00000650 0x00400650 GLOBAL FUNC 5 __libc_csu_fini
|
||||
85 ---------- 0x00601024 GLOBAL NOTYPE 0 _edata
|
||||
86 0x00000658 0x00400658 GLOBAL FUNC 0 _fini
|
||||
89 0x00001020 0x00601020 GLOBAL NOTYPE 0 __data_start
|
||||
90 0x00000596 0x00400596 GLOBAL FUNC 15 adder
|
||||
92 0x00000670 0x00400670 GLOBAL OBJ 0 __dso_handle
|
||||
93 0x00000668 0x00400668 GLOBAL OBJ 4 _IO_stdin_used
|
||||
94 0x000005e0 0x004005e0 GLOBAL FUNC 101 __libc_csu_init
|
||||
95 ---------- 0x00601028 GLOBAL NOTYPE 0 _end
|
||||
96 0x000004e0 0x004004e0 GLOBAL FUNC 5 _dl_relocate_static_pie
|
||||
97 0x000004b0 0x004004b0 GLOBAL FUNC 47 _start
|
||||
98 ---------- 0x00601024 GLOBAL NOTYPE 0 __bss_start
|
||||
99 0x000005a5 0x004005a5 GLOBAL FUNC 55 main
|
||||
100 ---------- 0x00601028 GLOBAL OBJ 0 __TMC_END__
|
||||
102 0x00000468 0x00400468 GLOBAL FUNC 0 _init
|
||||
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
### 哈希信息
|
||||
|
||||
如何知道两个二进制文件是否相似?你不能只是打开一个二进制文件并查看里面的源代码。在大多数情况下,二进制文件的哈希值(md5sum、sha1、sha256)是用来唯一识别它的。你可以使用 `it` 命令找到二进制的哈希值:
|
||||
|
||||
```
|
||||
[0x004004b0]> it
|
||||
md5 7e6732f2b11dec4a0c7612852cede670
|
||||
sha1 d5fa848c4b53021f6570dd9b18d115595a2290ae
|
||||
sha256 13dd5a492219dac1443a816ef5f91db8d149e8edbf26f24539c220861769e1c2
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
### 函数
|
||||
|
||||
代码按函数分组;要列出二进制中存在的函数,请运行 `afl` 命令。下面的列表显示了 `main` 函数和 `adder` 函数。通常,以 `sym.imp` 开头的函数是从标准库(这里是 glibc)中导入的:
|
||||
|
||||
```
|
||||
[0x004004b0]> afl
|
||||
0x004004b0 1 46 entry0
|
||||
0x004004f0 4 41 -> 34 sym.deregister_tm_clones
|
||||
0x00400520 4 57 -> 51 sym.register_tm_clones
|
||||
0x00400560 3 33 -> 32 sym.__do_global_dtors_aux
|
||||
0x00400590 1 6 entry.init0
|
||||
0x00400650 1 5 sym.__libc_csu_fini
|
||||
0x00400658 1 13 sym._fini
|
||||
0x00400596 1 15 sym.adder
|
||||
0x004005e0 4 101 loc..annobin_elf_init.c
|
||||
0x004004e0 1 5 loc..annobin_static_reloc.c
|
||||
0x004005a5 1 55 main
|
||||
0x004004a0 1 6 sym.imp.printf
|
||||
0x00400468 3 27 sym._init
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
### 交叉引用
|
||||
|
||||
在 C 语言中,`main` 函数是一个程序开始执行的地方。理想情况下,其他函数都是从 `main` 函数调用的,在退出程序时,`main` 函数会向操作系统返回一个退出状态。这在源代码中是很明显的,然而,二进制程序呢?如何判断 `adder` 函数的调用位置呢?
|
||||
|
||||
你可以使用 `axt` 命令,后面加上函数名,看看 `adder` 函数是在哪里调用的;如下图所示,它是从 `main` 函数中调用的。这就是所谓的<ruby>交叉引用<rt>cross-referencing</rt></ruby>。但什么调用 `main` 函数本身呢?从下面的 `axt main` 可以看出,它是由 `entry0` 调用的(关于 `entry0` 的学习我就不说了,留待读者练习)。
|
||||
|
||||
```
|
||||
[0x004004b0]> axt sym.adder
|
||||
main 0x4005b9 [CALL] call sym.adder
|
||||
[0x004004b0]>
|
||||
[0x004004b0]> axt main
|
||||
entry0 0x4004d1 [DATA] mov rdi, main
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
### 寻找定位
|
||||
|
||||
在处理文本文件时,你经常通过引用行号和行或列号在文件内移动;在二进制文件中,你需要使用地址。这些是以 `0x` 开头的十六进制数字,后面跟着一个地址。要找到你在二进制中的位置,运行 `s` 命令。要移动到不同的位置,使用 `s` 命令,后面跟上地址。
|
||||
|
||||
函数名就像标签一样,内部用地址表示。如果函数名在二进制中(未剥离的),可以使用函数名后面的 `s` 命令跳转到一个特定的函数地址。同样,如果你想跳转到二进制的开始,输入 `s 0`:
|
||||
|
||||
```
|
||||
[0x004004b0]> s
|
||||
0x4004b0
|
||||
[0x004004b0]>
|
||||
[0x004004b0]> s main
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> s
|
||||
0x4005a5
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> s sym.adder
|
||||
[0x00400596]>
|
||||
[0x00400596]> s
|
||||
0x400596
|
||||
[0x00400596]>
|
||||
[0x00400596]> s 0
|
||||
[0x00000000]>
|
||||
[0x00000000]> s
|
||||
0x0
|
||||
[0x00000000]>
|
||||
```
|
||||
|
||||
### 十六进制视图
|
||||
|
||||
通常情况下,原始二进制没有意义。在十六进制模式下查看二进制及其等效的 ASCII 表示法会有帮助:
|
||||
|
||||
```
|
||||
[0x004004b0]> s main
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> px
|
||||
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
|
||||
0x004005a5 5548 89e5 4883 ec10 c745 fc64 0000 008b UH..H....E.d....
|
||||
0x004005b5 45fc 89c7 e8d8 ffff ff89 45f8 8b45 f889 E.........E..E..
|
||||
0x004005c5 c6bf 7806 4000 b800 0000 00e8 cbfe ffff ..x.@...........
|
||||
0x004005d5 b800 0000 00c9 c30f 1f40 00f3 0f1e fa41 .........@.....A
|
||||
0x004005e5 5749 89d7 4156 4989 f641 5541 89fd 4154 WI..AVI..AUA..AT
|
||||
0x004005f5 4c8d 2504 0820 0055 488d 2d04 0820 0053 L.%.. .UH.-.. .S
|
||||
0x00400605 4c29 e548 83ec 08e8 57fe ffff 48c1 fd03 L).H....W...H...
|
||||
0x00400615 741f 31db 0f1f 8000 0000 004c 89fa 4c89 t.1........L..L.
|
||||
0x00400625 f644 89ef 41ff 14dc 4883 c301 4839 dd75 .D..A...H...H9.u
|
||||
0x00400635 ea48 83c4 085b 5d41 5c41 5d41 5e41 5fc3 .H...[]A\A]A^A_.
|
||||
0x00400645 9066 2e0f 1f84 0000 0000 00f3 0f1e fac3 .f..............
|
||||
0x00400655 0000 00f3 0f1e fa48 83ec 0848 83c4 08c3 .......H...H....
|
||||
0x00400665 0000 0001 0002 0000 0000 0000 0000 0000 ................
|
||||
0x00400675 0000 004e 756d 6265 7220 6e6f 7720 6973 ...Number now is
|
||||
0x00400685 2020 3a20 2564 0a00 0000 0001 1b03 3b44 : %d........;D
|
||||
0x00400695 0000 0007 0000 0000 feff ff88 0000 0020 ...............
|
||||
[0x004005a5]>
|
||||
```
|
||||
|
||||
### 反汇编
|
||||
|
||||
如果你使用的是编译后的二进制文件,则无法查看源代码。编译器将源代码转译成 CPU 可以理解和执行的机器语言指令;其结果就是二进制或可执行文件。然而,你可以查看汇编指令(的助记词)来理解程序正在做什么。例如,如果你想查看 `main` 函数在做什么,你可以使用 `s main` 寻找 `main` 函数的地址,然后运行 `pdf` 命令来查看反汇编的指令。
|
||||
|
||||
要理解汇编指令,你需要参考体系结构手册(这里是 x86),它的应用二进制接口(ABI,或调用惯例),并对堆栈的工作原理有基本的了解:
|
||||
|
||||
```
|
||||
[0x004004b0]> s main
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> s
|
||||
0x4005a5
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> pdf
|
||||
; DATA XREF from entry0 @ 0x4004d1
|
||||
┌ 55: int main (int argc, char **argv, char **envp);
|
||||
│ ; var int64_t var_8h @ rbp-0x8
|
||||
│ ; var int64_t var_4h @ rbp-0x4
|
||||
│ 0x004005a5 55 push rbp
|
||||
│ 0x004005a6 4889e5 mov rbp, rsp
|
||||
│ 0x004005a9 4883ec10 sub rsp, 0x10
|
||||
│ 0x004005ad c745fc640000. mov dword [var_4h], 0x64 ; 'd' ; 100
|
||||
│ 0x004005b4 8b45fc mov eax, dword [var_4h]
|
||||
│ 0x004005b7 89c7 mov edi, eax
|
||||
│ 0x004005b9 e8d8ffffff call sym.adder
|
||||
│ 0x004005be 8945f8 mov dword [var_8h], eax
|
||||
│ 0x004005c1 8b45f8 mov eax, dword [var_8h]
|
||||
│ 0x004005c4 89c6 mov esi, eax
|
||||
│ 0x004005c6 bf78064000 mov edi, str.Number_now_is__:__d ; 0x400678 ; "Number now is : %d\n" ; const char *format
|
||||
│ 0x004005cb b800000000 mov eax, 0
|
||||
│ 0x004005d0 e8cbfeffff call sym.imp.printf ; int printf(const char *format)
|
||||
│ 0x004005d5 b800000000 mov eax, 0
|
||||
│ 0x004005da c9 leave
|
||||
└ 0x004005db c3 ret
|
||||
[0x004005a5]>
|
||||
```
|
||||
|
||||
这是 `adder` 函数的反汇编结果:
|
||||
|
||||
```
|
||||
[0x004005a5]> s sym.adder
|
||||
[0x00400596]>
|
||||
[0x00400596]> s
|
||||
0x400596
|
||||
[0x00400596]>
|
||||
[0x00400596]> pdf
|
||||
; CALL XREF from main @ 0x4005b9
|
||||
┌ 15: sym.adder (int64_t arg1);
|
||||
│ ; var int64_t var_4h @ rbp-0x4
|
||||
│ ; arg int64_t arg1 @ rdi
|
||||
│ 0x00400596 55 push rbp
|
||||
│ 0x00400597 4889e5 mov rbp, rsp
|
||||
│ 0x0040059a 897dfc mov dword [var_4h], edi ; arg1
|
||||
│ 0x0040059d 8b45fc mov eax, dword [var_4h]
|
||||
│ 0x004005a0 83c001 add eax, 1
|
||||
│ 0x004005a3 5d pop rbp
|
||||
└ 0x004005a4 c3 ret
|
||||
[0x00400596]>
|
||||
```
|
||||
|
||||
### 字符串
|
||||
|
||||
查看二进制中存在哪些字符串可以作为二进制分析的起点。字符串是硬编码到二进制中的,通常会提供重要的提示,可以让你将重点转移到分析某些区域。在二进制中运行 `iz` 命令来列出所有的字符串。这个测试二进制中只有一个硬编码的字符串:
|
||||
|
||||
```
|
||||
[0x004004b0]> iz
|
||||
[Strings]
|
||||
nth paddr vaddr len size section type string
|
||||
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||
0 0x00000678 0x00400678 20 21 .rodata ascii Number now is : %d\n
|
||||
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
### 交叉引用字符串
|
||||
|
||||
和函数一样,你可以交叉引用字符串,看看它们是从哪里被打印出来的,并理解它们周围的代码:
|
||||
|
||||
```
|
||||
[0x004004b0]> ps @ 0x400678
|
||||
Number now is : %d
|
||||
|
||||
[0x004004b0]>
|
||||
[0x004004b0]> axt 0x400678
|
||||
main 0x4005c6 [DATA] mov edi, str.Number_now_is__:__d
|
||||
[0x004004b0]>
|
||||
```
|
||||
|
||||
### 可视模式
|
||||
|
||||
当你的代码很复杂,有多个函数被调用时,很容易迷失方向。如果能以图形或可视化的方式查看哪些函数被调用,根据某些条件采取了哪些路径等,会很有帮助。在移动到感兴趣的函数后,可以通过 `VV` 命令来探索 `r2` 的可视化模式。例如,对于 `adder` 函数:
|
||||
|
||||
```
|
||||
[0x004004b0]> s sym.adder
|
||||
[0x00400596]>
|
||||
[0x00400596]> VV
|
||||
```
|
||||
|
||||
![Radare2 Visual mode][8]
|
||||
|
||||
*(Gaurav Kamathe, [CC BY-SA 4.0][9])*
|
||||
|
||||
### 调试器
|
||||
|
||||
到目前为止,你一直在做的是静态分析 —— 你只是在看二进制文件中的东西,而没有运行它,有时你需要执行二进制文件,并在运行时分析内存中的各种信息。`r2` 的内部调试器允许你运行二进制文件、设置断点、分析变量的值、或者转储寄存器的内容。
|
||||
|
||||
用 `-d` 标志启动调试器,并在加载二进制时添加 `-A` 标志进行分析。你可以通过使用 `db <function-name>` 命令在不同的地方设置断点,比如函数或内存地址。要查看现有的断点,使用 `dbi` 命令。一旦你放置了断点,使用 `dc` 命令开始运行二进制文件。你可以使用 `dbt` 命令查看堆栈,它可以显示函数调用。最后,你可以使用 `drr` 命令转储寄存器的内容:
|
||||
|
||||
```
|
||||
$ r2 -d -A ./adder
|
||||
Process with PID 17453 started...
|
||||
= attach 17453 17453
|
||||
bin.baddr 0x00400000
|
||||
Using 0x400000
|
||||
asm.bits 64
|
||||
[x] Analyze all flags starting with sym. and entry0 (aa)
|
||||
[x] Analyze function calls (aac)
|
||||
[x] Analyze len bytes of instructions for references (aar)
|
||||
[x] Check for vtables
|
||||
[x] Type matching analysis for all functions (aaft)
|
||||
[x] Propagate noreturn information
|
||||
[x] Use -AA or aaaa to perform additional experimental analysis.
|
||||
-- git checkout hamster
|
||||
[0x7f77b0a28030]>
|
||||
[0x7f77b0a28030]> db main
|
||||
[0x7f77b0a28030]>
|
||||
[0x7f77b0a28030]> db sym.adder
|
||||
[0x7f77b0a28030]>
|
||||
[0x7f77b0a28030]> dbi
|
||||
0 0x004005a5 E:1 T:0
|
||||
1 0x00400596 E:1 T:0
|
||||
[0x7f77b0a28030]>
|
||||
[0x7f77b0a28030]> afl | grep main
|
||||
0x004005a5 1 55 main
|
||||
[0x7f77b0a28030]>
|
||||
[0x7f77b0a28030]> afl | grep sym.adder
|
||||
0x00400596 1 15 sym.adder
|
||||
[0x7f77b0a28030]>
|
||||
[0x7f77b0a28030]> dc
|
||||
hit breakpoint at: 0x4005a5
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> dbt
|
||||
0 0x4005a5 sp: 0x0 0 [main] main sym.adder+15
|
||||
1 0x7f77b0687873 sp: 0x7ffe35ff6858 0 [??] section..gnu.build.attributes-1345820597
|
||||
2 0x7f77b0a36e0a sp: 0x7ffe35ff68e8 144 [??] map.usr_lib64_ld_2.28.so.r_x+65034
|
||||
[0x004005a5]> dc
|
||||
hit breakpoint at: 0x400596
|
||||
[0x00400596]> dbt
|
||||
0 0x400596 sp: 0x0 0 [sym.adder] rip entry.init0+6
|
||||
1 0x4005be sp: 0x7ffe35ff6838 0 [main] main+25
|
||||
2 0x7f77b0687873 sp: 0x7ffe35ff6858 32 [??] section..gnu.build.attributes-1345820597
|
||||
3 0x7f77b0a36e0a sp: 0x7ffe35ff68e8 144 [??] map.usr_lib64_ld_2.28.so.r_x+65034
|
||||
[0x00400596]>
|
||||
[0x00400596]>
|
||||
[0x00400596]> dr
|
||||
rax = 0x00000064
|
||||
rbx = 0x00000000
|
||||
rcx = 0x7f77b0a21738
|
||||
rdx = 0x7ffe35ff6948
|
||||
r8 = 0x7f77b0a22da0
|
||||
r9 = 0x7f77b0a22da0
|
||||
r10 = 0x0000000f
|
||||
r11 = 0x00000002
|
||||
r12 = 0x004004b0
|
||||
r13 = 0x7ffe35ff6930
|
||||
r14 = 0x00000000
|
||||
r15 = 0x00000000
|
||||
rsi = 0x7ffe35ff6938
|
||||
rdi = 0x00000064
|
||||
rsp = 0x7ffe35ff6838
|
||||
rbp = 0x7ffe35ff6850
|
||||
rip = 0x00400596
|
||||
rflags = 0x00000202
|
||||
orax = 0xffffffffffffffff
|
||||
[0x00400596]>
|
||||
```
|
||||
|
||||
### 反编译器
|
||||
|
||||
能够理解汇编是二进制分析的前提。汇编语言总是与二进制建立和预期运行的架构相关。一行源代码和汇编代码之间从来没有 1:1 的映射。通常,一行 C 源代码会产生多行汇编代码。所以,逐行读取汇编代码并不是最佳的选择。
|
||||
|
||||
这就是反编译器的作用。它们试图根据汇编指令重建可能的源代码。这与用于创建二进制的源代码绝不完全相同,它是基于汇编的源代码的近似表示。另外,要考虑到编译器进行的优化,它会生成不同的汇编代码以加快速度,减小二进制的大小等,会使反编译器的工作更加困难。另外,恶意软件作者经常故意混淆代码,让恶意软件的分析人员望而却步。
|
||||
|
||||
Radare2 通过插件提供反编译器。你可以安装任何 Radare2 支持的反编译器。使用 `r2pm -l` 命令可以查看当前插件。使用 `r2pm install` 命令来安装一个示例的反编译器 `r2dec`:
|
||||
|
||||
```
|
||||
$ r2pm -l
|
||||
$
|
||||
$ r2pm install r2dec
|
||||
Cloning into 'r2dec'...
|
||||
remote: Enumerating objects: 100, done.
|
||||
remote: Counting objects: 100% (100/100), done.
|
||||
remote: Compressing objects: 100% (97/97), done.
|
||||
remote: Total 100 (delta 18), reused 27 (delta 1), pack-reused 0
|
||||
Receiving objects: 100% (100/100), 1.01 MiB | 1.31 MiB/s, done.
|
||||
Resolving deltas: 100% (18/18), done.
|
||||
Install Done For r2dec
|
||||
gmake: Entering directory '/root/.local/share/radare2/r2pm/git/r2dec/p'
|
||||
[CC] duktape/duktape.o
|
||||
[CC] duktape/duk_console.o
|
||||
[CC] core_pdd.o
|
||||
[CC] core_pdd.so
|
||||
gmake: Leaving directory '/root/.local/share/radare2/r2pm/git/r2dec/p'
|
||||
$
|
||||
$ r2pm -l
|
||||
r2dec
|
||||
$
|
||||
```
|
||||
|
||||
### 反编译器视图
|
||||
|
||||
要反编译一个二进制文件,在 `r2` 中加载二进制文件并自动分析它。在本例中,使用 `s sym.adder` 命令移动到感兴趣的 `adder` 函数,然后使用 `pdda` 命令并排查看汇编和反编译后的源代码。阅读这个反编译后的源代码往往比逐行阅读汇编更容易:
|
||||
|
||||
```
|
||||
$ r2 -A ./adder
|
||||
[x] Analyze all flags starting with sym. and entry0 (aa)
|
||||
[x] Analyze function calls (aac)
|
||||
[x] Analyze len bytes of instructions for references (aar)
|
||||
[x] Check for vtables
|
||||
[x] Type matching analysis for all functions (aaft)
|
||||
[x] Propagate noreturn information
|
||||
[x] Use -AA or aaaa to perform additional experimental analysis.
|
||||
-- What do you want to debug today?
|
||||
[0x004004b0]>
|
||||
[0x004004b0]> s sym.adder
|
||||
[0x00400596]>
|
||||
[0x00400596]> s
|
||||
0x400596
|
||||
[0x00400596]>
|
||||
[0x00400596]> pdda
|
||||
; assembly | /* r2dec pseudo code output */
|
||||
| /* ./adder @ 0x400596 */
|
||||
| #include <stdint.h>
|
||||
|
|
||||
; (fcn) sym.adder () | int32_t adder (int64_t arg1) {
|
||||
| int64_t var_4h;
|
||||
| rdi = arg1;
|
||||
0x00400596 push rbp |
|
||||
0x00400597 mov rbp, rsp |
|
||||
0x0040059a mov dword [rbp - 4], edi | *((rbp - 4)) = edi;
|
||||
0x0040059d mov eax, dword [rbp - 4] | eax = *((rbp - 4));
|
||||
0x004005a0 add eax, 1 | eax++;
|
||||
0x004005a3 pop rbp |
|
||||
0x004005a4 ret | return eax;
|
||||
| }
|
||||
[0x00400596]>
|
||||
```
|
||||
|
||||
### 配置设置
|
||||
|
||||
随着你对 Radare2 的使用越来越熟悉,你会想改变它的配置,以适应你的工作方式。你可以使用 `e` 命令查看 `r2` 的默认配置。要设置一个特定的配置,在 `e` 命令后面添加 `config = value`:
|
||||
|
||||
```
|
||||
[0x004005a5]> e | wc -l
|
||||
593
|
||||
[0x004005a5]> e | grep syntax
|
||||
asm.syntax = intel
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> e asm.syntax = att
|
||||
[0x004005a5]>
|
||||
[0x004005a5]> e | grep syntax
|
||||
asm.syntax = att
|
||||
[0x004005a5]>
|
||||
```
|
||||
|
||||
要使配置更改永久化,请将它们放在 `r2` 启动时读取的名为 `.radare2rc` 的启动文件中。这个文件通常在你的主目录下,如果没有,你可以创建一个。一些示例配置选项包括:
|
||||
|
||||
```
|
||||
$ cat ~/.radare2rc
|
||||
e asm.syntax = att
|
||||
e scr.utf8 = true
|
||||
eco solarized
|
||||
e cmd.stack = true
|
||||
e stack.size = 256
|
||||
$
|
||||
```
|
||||
|
||||
### 探索更多
|
||||
|
||||
你已经看到了足够多的 Radare2 功能,对这个工具有了一定的了解。因为 Radare2 遵循 Unix 哲学,即使你可以从它的主控台做各种事情,它也会在下面使用一套独立的二进制来完成它的任务。
|
||||
|
||||
探索下面列出的独立二进制文件,看看它们是如何工作的。例如,用 `iI` 命令在控制台看到的二进制信息也可以用 `rabin2 <binary>` 命令找到:
|
||||
|
||||
```
|
||||
$ cd bin/
|
||||
$
|
||||
$ ls
|
||||
prefix r2agent r2pm rabin2 radiff2 ragg2 rarun2 rasm2
|
||||
r2 r2-indent r2r radare2 rafind2 rahash2 rasign2 rax2
|
||||
$
|
||||
```
|
||||
|
||||
你觉得 Radare2 怎么样?请在评论中分享你的反馈。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/linux-radare2
|
||||
|
||||
作者:[Gaurav Kamathe][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/gkamathe
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/binary_code_computer_screen.png?itok=7IzHK1nn (Binary code on a computer screen)
|
||||
[2]: https://linux.cn/article-12187-1.html
|
||||
[3]: https://linux.cn/article-11441-1.html
|
||||
[4]: https://rada.re/n/
|
||||
[5]: https://github.com/radareorg/radare2
|
||||
[6]: https://opensource.com/article/19/3/getting-started-vim
|
||||
[7]: https://ghidra-sre.org/
|
||||
[8]: https://opensource.com/sites/default/files/uploads/radare2_visual-mode_0.png (Radare2 Visual mode)
|
||||
[9]: https://creativecommons.org/licenses/by-sa/4.0/
|
63
published/20210125 Use Joplin to find your notes faster.md
Normal file
63
published/20210125 Use Joplin to find your notes faster.md
Normal file
@ -0,0 +1,63 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13080-1.html)
|
||||
[#]: subject: (Use Joplin to find your notes faster)
|
||||
[#]: via: (https://opensource.com/article/21/1/notes-joplin)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
使用 Joplin 更快地找到你的笔记
|
||||
======
|
||||
|
||||
> 在多个手写和数字平台上整理笔记是一个严峻的挑战。这里有一个小技巧,可以更好地组织你的笔记,并快速找到你需要的东西。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/03/120141dkiqil1vlqiz6wql.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十五天。
|
||||
|
||||
保持生产力也意味着(在某种程度上)要有足够的组织能力,以便找到笔记并在需要时参考它们。这不仅是对我自己的挑战,也是与我交谈的很多人的挑战。
|
||||
|
||||
多年来,我在应用中单独或使用数字笔记、纸质笔记、便签、数字便签、Word 文档、纯文本文件以及一堆我忘记的其他格式的组合。这不仅让寻找笔记变得困难,而且知道把它们放在哪里是一个更大的挑战。
|
||||
|
||||
![Stacks of paper notes on a desk][2]
|
||||
|
||||
*一堆笔记 (Jessica Cherry, [CC BY-SA 4.0][3])*
|
||||
|
||||
还有就是做笔记最重要的一点:如果你以后找不到它,笔记就没有任何价值。知道含有你所需信息的笔记存在于你保存笔记的*某处*,根本没有任何帮助。
|
||||
|
||||
我是如何为自己解决这个问题的呢?正如他们所说,这是一个过程,我希望这也是一个对其他人有效的过程。
|
||||
|
||||
我首先看了看自己所做的笔记种类。不同的主题需要用不同的方式保存吗?由于我为我的播客手写笔记,而几乎所有其他的东西都使用纯文本笔记,我需要两种不同的方式来维护它们。对于手写的笔记,我把它们都放在一个文件夹里,方便我参考。
|
||||
|
||||
![Man holding a binder full of notes][4]
|
||||
|
||||
*三年多的笔记 (Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
为了保存我的数字笔记,我需要将它们全部集中到一个地方。这个工具需要能够从多种设备上访问,具有有用的搜索功能,并且能够导出或共享我的笔记。在尝试了很多很多不同的选项之后,我选择了 [Joplin][5]。Joplin 可以让我用 Markdown 写笔记,有一个相当不错的搜索功能,有适用于所有操作系统(包括手机)的应用,并支持几种不同的设备同步方式。另外,它还有文件夹*和*标签,因此我可以按照对我有意义的方式将笔记分组。
|
||||
|
||||
![Organized Joplin notes management page][6]
|
||||
|
||||
*我的 Joplin*
|
||||
|
||||
我花了一些时间才把所有的东西都放在我想要的地方,但最后,这真的是值得的。现在,我可以找到我所做的笔记,而不是让它们散落在我的办公室、不同的机器和各种服务中。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/notes-joplin
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
|
||||
[2]: https://opensource.com/sites/default/files/day15-image1.jpg
|
||||
[3]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[4]: https://opensource.com/sites/default/files/day15-image2.png
|
||||
[5]: https://joplinapp.org/
|
||||
[6]: https://opensource.com/sites/default/files/day15-image3.png
|
201
published/20210125 Why you need to drop ifconfig for ip.md
Normal file
201
published/20210125 Why you need to drop ifconfig for ip.md
Normal file
@ -0,0 +1,201 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "MjSeven"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13089-1.html"
|
||||
[#]: subject: "Why you need to drop ifconfig for ip"
|
||||
[#]: via: "https://opensource.com/article/21/1/ifconfig-ip-linux"
|
||||
[#]: author: "Rajan Bhardwaj https://opensource.com/users/rajabhar"
|
||||
|
||||
放弃 ifconfig,拥抱 ip 命令
|
||||
======
|
||||
|
||||
> 开始使用现代方法配置 Linux 网络接口。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/05/233847lpg1lnz7kl2czgfj.jpg)
|
||||
|
||||
在很长一段时间内,`ifconfig` 命令是配置网络接口的默认方法。它为 Linux 用户提供了很好的服务,但是网络很复杂,所以配置网络的命令必须健壮。`ip` 命令是现代系统中新的默认网络命令,在本文中,我将向你展示如何使用它。
|
||||
|
||||
`ip` 命令工作在 [OSI 网络栈][2] 的两个层上:第二层(数据链路层)和第三层(网络 或 IP)层。它做了之前 `net-tools` 包的所有工作。
|
||||
|
||||
### 安装 ip
|
||||
|
||||
`ip` 命令包含在 `iproute2util` 包中,它可能已经在你的 Linux 发行版中安装了。如果没有,你可以从发行版的仓库中进行安装。
|
||||
|
||||
### ifconfig 和 ip 使用对比
|
||||
|
||||
`ip` 和 `ifconfig` 命令都可以用来配置网络接口,但它们做事方法不同。接下来,作为对比,我将用它们来执行一些常见的任务。
|
||||
|
||||
#### 查看网口和 IP 地址
|
||||
|
||||
如果你想查看主机的 IP 地址或网络接口信息,`ifconfig` (不带任何参数)命令提供了一个很好的总结。
|
||||
|
||||
```
|
||||
$ ifconfig
|
||||
|
||||
eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
|
||||
ether bc:ee:7b:5e:7d:d8 txqueuelen 1000 (Ethernet)
|
||||
RX packets 0 bytes 0 (0.0 B)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 0 bytes 0 (0.0 B)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
|
||||
inet 127.0.0.1 netmask 255.0.0.0
|
||||
inet6 ::1 prefixlen 128 scopeid 0x10<host>
|
||||
loop txqueuelen 1000 (Local Loopback)
|
||||
RX packets 41 bytes 5551 (5.4 KiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 41 bytes 5551 (5.4 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 10.1.1.6 netmask 255.255.255.224 broadcast 10.1.1.31
|
||||
inet6 fdb4:f58e:49f:4900:d46d:146b:b16:7212 prefixlen 64 scopeid 0x0<global>
|
||||
inet6 fe80::8eb3:4bc0:7cbb:59e8 prefixlen 64 scopeid 0x20<link>
|
||||
ether 08:71:90:81:1e:b5 txqueuelen 1000 (Ethernet)
|
||||
RX packets 569459 bytes 779147444 (743.0 MiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 302882 bytes 38131213 (36.3 MiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
```
|
||||
|
||||
新的 `ip` 命令提供了类似的结果,但命令是 `ip address show`,或者简写为 `ip a`:
|
||||
|
||||
```
|
||||
$ ip a
|
||||
|
||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
|
||||
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||
inet 127.0.0.1/8 scope host lo
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 ::1/128 scope host
|
||||
valid_lft forever preferred_lft forever
|
||||
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
|
||||
link/ether bc:ee:7b:5e:7d:d8 brd ff:ff:ff:ff:ff:ff
|
||||
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
|
||||
link/ether 08:71:90:81:1e:b5 brd ff:ff:ff:ff:ff:ff
|
||||
inet 10.1.1.6/27 brd 10.1.1.31 scope global dynamic wlan0
|
||||
valid_lft 83490sec preferred_lft 83490sec
|
||||
inet6 fdb4:f58e:49f:4900:d46d:146b:b16:7212/64 scope global noprefixroute dynamic
|
||||
valid_lft 6909sec preferred_lft 3309sec
|
||||
inet6 fe80::8eb3:4bc0:7cbb:59e8/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
```
|
||||
|
||||
#### 添加 IP 地址
|
||||
|
||||
使用 `ifconfig` 命令添加 IP 地址命令为:
|
||||
|
||||
```
|
||||
$ ifconfig eth0 add 192.9.203.21
|
||||
```
|
||||
|
||||
`ip` 类似:
|
||||
|
||||
```
|
||||
$ ip address add 192.9.203.21 dev eth0
|
||||
```
|
||||
|
||||
`ip` 中的子命令可以缩短,所以下面这个命令同样有效:
|
||||
|
||||
```
|
||||
$ ip addr add 192.9.203.21 dev eth0
|
||||
```
|
||||
|
||||
你甚至可以更短些:
|
||||
|
||||
```
|
||||
$ ip a add 192.9.203.21 dev eth0
|
||||
```
|
||||
|
||||
#### 移除一个 IP 地址
|
||||
|
||||
添加 IP 地址与删除 IP 地址正好相反。
|
||||
|
||||
使用 `ifconfig`,命令是:
|
||||
|
||||
```
|
||||
$ ifconfig eth0 del 192.9.203.21
|
||||
```
|
||||
|
||||
`ip` 命令的语法是:
|
||||
|
||||
```
|
||||
$ ip a del 192.9.203.21 dev eth0
|
||||
```
|
||||
|
||||
#### 启用或禁用组播
|
||||
|
||||
使用 `ifconfig` 接口来启用或禁用 <ruby>[组播][3]<rt>multicast</rt></ruby>:
|
||||
|
||||
```
|
||||
# ifconfig eth0 multicast
|
||||
```
|
||||
|
||||
对于 `ip`,使用 `set` 子命令与设备(`dev`)以及一个布尔值和 `multicast` 选项:
|
||||
|
||||
```
|
||||
# ip link set dev eth0 multicast on
|
||||
```
|
||||
|
||||
#### 启用或禁用网络
|
||||
|
||||
每个系统管理员都熟悉“先关闭,然后打开”这个技巧来解决问题。对于网络接口来说,即打开或关闭网络。
|
||||
|
||||
`ifconfig` 命令使用 `up` 或 `down` 关键字来实现:
|
||||
|
||||
```
|
||||
# ifconfig eth0 up
|
||||
```
|
||||
|
||||
或者你可以使用一个专用命令:
|
||||
|
||||
```
|
||||
# ifup eth0
|
||||
```
|
||||
|
||||
`ip` 命令使用 `set` 子命令将网络设置为 `up` 或 `down` 状态:
|
||||
|
||||
```
|
||||
# ip link set eth0 up
|
||||
```
|
||||
|
||||
#### 开启或关闭地址解析功能(ARP)
|
||||
|
||||
使用 `ifconfig`,你可以通过声明它来启用:
|
||||
|
||||
```
|
||||
# ifconfig eth0 arp
|
||||
```
|
||||
|
||||
使用 `ip`,你可以将 `arp` 属性设置为 `on` 或 `off`:
|
||||
|
||||
```
|
||||
# ip link set dev eth0 arp on
|
||||
```
|
||||
|
||||
### ip 和 ipconfig 的优缺点
|
||||
|
||||
`ip` 命令比 `ifconfig` 更通用,技术上也更有效,因为它使用的是 `Netlink` 套接字,而不是 `ioctl` 系统调用。
|
||||
|
||||
`ip` 命令可能看起来比 `ifconfig` 更详细、更复杂,但这是它拥有更多功能的一个原因。一旦你开始使用它,你会了解它的内部逻辑(例如,使用 `set` 而不是看起来随意混合的声明或设置)。
|
||||
|
||||
最后,`ifconfig` 已经过时了(例如,它缺乏对网络命名空间的支持),而 `ip` 是为现代网络而生的。尝试并学习它,使用它,你会由衷高兴的!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/ifconfig-ip-linux
|
||||
|
||||
作者:[Rajan Bhardwaj][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/rajabhar
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/gears_devops_learn_troubleshooting_lightbulb_tips_520.png?itok=HcN38NOk "Tips and gears turning"
|
||||
[2]: https://en.wikipedia.org/wiki/OSI_model
|
||||
[3]: https://en.wikipedia.org/wiki/Multicast
|
@ -0,0 +1,75 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13084-1.html)
|
||||
[#]: subject: (Use your Raspberry Pi as a productivity powerhouse)
|
||||
[#]: via: (https://opensource.com/article/21/1/raspberry-pi-productivity)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
将你的树莓派用作生产力源泉
|
||||
======
|
||||
|
||||
> 树莓派已经从主要为黑客和业余爱好者服务,成为了小型生产力工作站的可靠选择。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/04/103826pjbxb7j1m8ok6ezf.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十六天。
|
||||
|
||||
[树莓派][2]是一台相当棒的小电脑。它体积小,功能却出奇的强大,而且非常容易设置和使用。我曾将它们用于家庭自动化项目、面板和专用媒体播放器。但它也能成为生产力的动力源泉么?
|
||||
|
||||
答案相当简单:是的。
|
||||
|
||||
![Geary and Calendar apps on the Raspberry Pi][3]
|
||||
|
||||
*Geary 和 Calendar 应用 (Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
基本的 [Raspbian][5] 安装包括 [Claw Mail][6],这是一个轻量级的邮件客户端。它的用户界面有点过时了,而且非常的简陋。如果你是一个 [Mutt 用户][7],它可能会满足你的需求。
|
||||
|
||||
我更喜欢安装 [Geary][8],因为它也是轻量级的,而且有一个现代化的界面。另外,与 Claws 不同的是,Geary 默认支持富文本 (HTML) 邮件。我不喜欢富文本电子邮件,但它已经成为必要的,所以对它有良好的支持是至关重要的。
|
||||
|
||||
默认的 Raspbian 安装不包含日历,所以我添加了 [GNOME 日历][9] ,因为它可以与远程服务通信(因为我的几乎所有日历都在云提供商那里)。
|
||||
|
||||
![GTG and GNote open on Raspberry Pi][10]
|
||||
|
||||
*GTG 和 GNote(Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
那笔记和待办事项清单呢?有很多选择,但我喜欢用 [GNote][11] 来做笔记,用 [Getting-Things-GNOME!][12] 来做待办事项。两者都相当轻量级,并且可以相互同步,也可以同步到其他服务。
|
||||
|
||||
你会注意到,我在这里使用了不少 GNOME 应用。为什么不直接安装完整的 GNOME 桌面呢?在内存为 4Gb(或 8Gb)的树莓派 4 上,GNOME 工作得很好。你需要采取一些额外的步骤来禁用 Raspbian 上的默认 wifi 设置,并用 Network Manager 来代替它,但这个在网上有很好的文档,而且真的很简单。
|
||||
|
||||
GNOME 中包含了 [Evolution][13],它将邮件、日历、笔记、待办事项和联系人管理整合到一个应用中。与 Geary 和 GNOME Calendar 相比,它有点重,但在树莓派 4 上却很稳定。这让我很惊讶,因为我习惯了 Evolution 有点消耗资源,但树莓派 4 却和我的品牌笔记本一样运行良好,而且资源充足。
|
||||
|
||||
![Evolution on Raspbian][14]
|
||||
|
||||
*Raspbian 上的 Evolution (Kevin Sonney, [CC BY-SA 4.0][4])*
|
||||
|
||||
树莓派在过去的几年里进步很快,已经从主要为黑客和业余爱好者服务,成为了小型生产力工作站的可靠选择。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/raspberry-pi-productivity
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/todo_checklist_team_metrics_report.png?itok=oB5uQbzf (Team checklist and to dos)
|
||||
[2]: https://www.raspberrypi.org/
|
||||
[3]: https://opensource.com/sites/default/files/day16-image1.png
|
||||
[4]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[5]: https://www.raspbian.org/
|
||||
[6]: https://www.claws-mail.org/
|
||||
[7]: http://www.mutt.org/
|
||||
[8]: https://wiki.gnome.org/Apps/Geary
|
||||
[9]: https://wiki.gnome.org/Apps/Calendar
|
||||
[10]: https://opensource.com/sites/default/files/day16-image2.png
|
||||
[11]: https://wiki.gnome.org/Apps/Gnote
|
||||
[12]: https://wiki.gnome.org/Apps/GTG
|
||||
[13]: https://opensource.com/business/18/1/desktop-email-clients
|
||||
[14]: https://opensource.com/sites/default/files/day16-image3.png
|
@ -0,0 +1,234 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (amwps290)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13093-1.html)
|
||||
[#]: subject: (Write GIMP scripts to make image processing faster)
|
||||
[#]: via: (https://opensource.com/article/21/1/gimp-scripting)
|
||||
[#]: author: (Cristiano L. Fontana https://opensource.com/users/cristianofontana)
|
||||
|
||||
编写 GIMP 脚本使图像处理更快
|
||||
======
|
||||
|
||||
> 通过向一批图像添加效果来学习 GIMP 的脚本语言 Script-Fu。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/06/231011c0xhvxitxjv899qv.jpg)
|
||||
|
||||
前一段时间,我想给方程图片加一个黑板式的外观。我开始是使用 [GIMP][2] 来处理的,我对结果很满意。问题是我必须对图像执行几个操作,当我想再次使用此样式,不想对所有图像重复这些步骤。此外,我确信我会很快忘记这些步骤。
|
||||
|
||||
![Fourier transform equations][3]
|
||||
|
||||
*傅立叶变换方程式(Cristiano Fontana,[CC BY-SA 4.0] [4])*
|
||||
|
||||
GIMP 是一个很棒的开源图像编辑器。尽管我已经使用了多年,但从未研究过其批处理功能或 [Script-Fu][5] 菜单。这是探索它们的绝好机会。
|
||||
|
||||
### 什么是 Script-Fu?
|
||||
|
||||
[Script-Fu][6] 是 GIMP 内置的脚本语言。是一种基于 [Scheme][7] 的编程语言。如果你从未使用过 Scheme,请尝试一下,因为它可能非常有用。我认为 Script-Fu 是一个很好的入门方法,因为它对图像处理具有立竿见影的效果,所以你可以很快感觉到自己的工作效率的提高。你也可以使用 [Python][8] 编写脚本,但是 Script-Fu 是默认选项。
|
||||
|
||||
为了帮助你熟悉 Scheme,GIMP 的文档提供了深入的 [教程][9]。Scheme 是一种类似于 [Lisp][10] 的语言,因此它的主要特征是使用 [前缀][11] 表示法和 [许多括号][12]。函数和运算符通过前缀应用到操作数列表中:
|
||||
|
||||
```
|
||||
(函数名 操作数 操作数 ...)
|
||||
|
||||
(+ 2 3)
|
||||
↳ 返回 5
|
||||
|
||||
(list 1 2 3 5)
|
||||
↳ 返回一个列表,包含 1、 2、 3 和 5
|
||||
```
|
||||
|
||||
我花了一些时间才找到完整的 GIMP 函数列表文档,但实际上很简单。在 **Help** 菜单中,有一个 **Procedure Browser**,其中包含所有可用的函数的丰富详尽文档。
|
||||
|
||||
![GIMP Procedure Browser][13]
|
||||
|
||||
### 使用 GIMP 的批处理模式
|
||||
|
||||
你可以使用 `-b` 选项以批处理的方式启动 GIMP。`-b` 选项的参数可以是你想要运行的脚本,或者用一个 `-` 来让 GIMP 进入交互模式而不是命令行模式。正常情况下,当你启动 GIMP 的时候,它会启动图形界面,但是你可以使用 `-i` 选项来禁用它。
|
||||
|
||||
### 开始编写你的第一个脚本
|
||||
|
||||
创建一个名为 `chalk.scm` 的文件,并把它保存在 **Preferences** 窗口中 **Folders** 选项下的 **Script** 中指定的 `script` 文件夹下。就我而言,是在 `$HOME/.config/GIMP/2.10/scripts`。
|
||||
|
||||
在 `chalk.scm` 文件中,写入下面的内容:
|
||||
|
||||
```
|
||||
(define (chalk filename grow-pixels spread-amount percentage)
|
||||
(let* ((image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
|
||||
(drawable (car (gimp-image-get-active-layer image)))
|
||||
(new-filename (string-append "modified_" filename)))
|
||||
(gimp-image-select-color image CHANNEL-OP-REPLACE drawable '(0 0 0))
|
||||
(gimp-selection-grow image grow-pixels)
|
||||
(gimp-context-set-foreground '(0 0 0))
|
||||
(gimp-edit-bucket-fill drawable BUCKET-FILL-FG LAYER-MODE-NORMAL 100 255 TRUE 0 0)
|
||||
(gimp-selection-none image)
|
||||
(plug-in-spread RUN-NONINTERACTIVE image drawable spread-amount spread-amount)
|
||||
(gimp-drawable-invert drawable TRUE)
|
||||
(plug-in-randomize-hurl RUN-NONINTERACTIVE image drawable percentage 1 TRUE 0)
|
||||
(gimp-file-save RUN-NONINTERACTIVE image drawable new-filename new-filename)
|
||||
(gimp-image-delete image)))
|
||||
```
|
||||
|
||||
### 定义脚本变量
|
||||
|
||||
在脚本中, `(define (chalk filename grow-pixels spread-amound percentage) ...)` 函数定义了一个名叫 `chalk` 的新函数。它的函数参数是 `filename`、`grow-pixels`、`spread-amound` 和 `percentage`。在 `define` 中的所有内容都是 `chalk` 函数的主体。你可能已经注意到,那些名字比较长的变量中间都有一个破折号来分割。这是类 Lisp 语言的惯用风格。
|
||||
|
||||
`(let* ...)` 函数是一个特殊<ruby>过程<rt>procedure</rt></ruby>,可以让你定义一些只有在这个函数体中才有效的临时变量。临时变量有 `image`、`drawable` 以及 `new-filename`。它使用 `gimp-file-load` 来载入图片,这会返回它所包含的图片的一个列表。并通过 `car` 函数来选取第一项。然后,它选择第一个活动层并将其引用存储在 `drawable` 变量中。最后,它定义了包含图像新文件名的字符串。
|
||||
|
||||
为了帮助你更好地了解该过程,我将对其进行分解。首先,启动带 GUI 的 GIMP,然后你可以通过依次点击 **Filters → Script-Fu → Console** 来打开 Script-Fu 控制台。 在这种情况下,不能使用 `let *`,因为变量必须是持久的。使用 `define` 函数定义 `image` 变量,并为其提供查找图像的正确路径:
|
||||
|
||||
```
|
||||
(define image (car (gimp-file-load RUN-NONINTERACTIVE "Fourier.png" "Fourier.png")))
|
||||
```
|
||||
|
||||
似乎在 GUI 中什么也没有发生,但是图像已加载。 你需要通过以下方式来让图像显示:
|
||||
|
||||
```
|
||||
(gimp-display-new image)
|
||||
```
|
||||
|
||||
![GUI with the displayed image][14]
|
||||
|
||||
现在,获取活动层并将其存储在 `drawable` 变量中:
|
||||
|
||||
```
|
||||
(define drawable (car (gimp-image-get-active-layer image)))
|
||||
```
|
||||
|
||||
最后,定义图像的新文件名:
|
||||
|
||||
```
|
||||
(define new-filename "modified_Fourier.png")
|
||||
```
|
||||
|
||||
运行命令后,你将在 Script-Fu 控制台中看到以下内容:
|
||||
|
||||
![Script-Fu console][15]
|
||||
|
||||
在对图像执行操作之前,需要定义将在脚本中作为函数参数的变量:
|
||||
|
||||
```
|
||||
(define grow-pixels 2)
|
||||
(define spread-amount 4)
|
||||
(define percentage 3)
|
||||
```
|
||||
|
||||
### 处理图片
|
||||
|
||||
现在,所有相关变量都已定义,你可以对图像进行操作了。 脚本的操作可以直接在控制台上执行。第一步是在活动层上选择黑色。颜色被写成一个由三个数字组成的列表,即 `(list 0 0 0)` 或者是 `'(0 0 0)`:
|
||||
|
||||
```
|
||||
(gimp-image-select-color image CHANNEL-OP-REPLACE drawable '(0 0 0))
|
||||
```
|
||||
|
||||
![Image with the selected color][16]
|
||||
|
||||
扩大选取两个像素:
|
||||
|
||||
```
|
||||
(gimp-selection-grow image grow-pixels)
|
||||
```
|
||||
|
||||
![Image with the selected color][17]
|
||||
|
||||
将前景色设置为黑色,并用它填充选区:
|
||||
|
||||
```
|
||||
(gimp-context-set-foreground '(0 0 0))
|
||||
(gimp-edit-bucket-fill drawable BUCKET-FILL-FG LAYER-MODE-NORMAL 100 255 TRUE 0 0)
|
||||
```
|
||||
|
||||
![Image with the selection filled with black][18]
|
||||
|
||||
删除选区:
|
||||
|
||||
```
|
||||
(gimp-selection-none image)
|
||||
```
|
||||
|
||||
![Image with no selection][19]
|
||||
|
||||
随机移动像素:
|
||||
|
||||
```
|
||||
(plug-in-spread RUN-NONINTERACTIVE image drawable spread-amount spread-amount)
|
||||
```
|
||||
|
||||
![Image with pixels moved around][20]
|
||||
|
||||
反转图像颜色:
|
||||
|
||||
```
|
||||
(gimp-drawable-invert drawable TRUE)
|
||||
```
|
||||
|
||||
![Image with pixels moved around][21]
|
||||
|
||||
随机化像素:
|
||||
|
||||
```
|
||||
(plug-in-randomize-hurl RUN-NONINTERACTIVE image drawable percentage 1 TRUE 0)
|
||||
```
|
||||
|
||||
![Image with pixels moved around][22]
|
||||
|
||||
将图像保存到新文件:
|
||||
|
||||
```
|
||||
(gimp-file-save RUN-NONINTERACTIVE image drawable new-filename new-filename)
|
||||
```
|
||||
|
||||
![Equations of the Fourier transform and its inverse][23]
|
||||
|
||||
*傅立叶变换方程 (Cristiano Fontana, [CC BY-SA 4.0][4])*
|
||||
|
||||
### 以批处理模式运行脚本
|
||||
|
||||
现在你知道了脚本的功能,可以在批处理模式下运行它:
|
||||
|
||||
```
|
||||
gimp -i -b '(chalk "Fourier.png" 2 4 3)' -b '(gimp-quit 0)'
|
||||
```
|
||||
|
||||
在运行 `chalk` 函数之后,它将使用 `-b` 选项调用第二个函数 `gimp-quit` 来告诉 GIMP 退出。
|
||||
|
||||
### 了解更多
|
||||
|
||||
本教程向你展示了如何开始使用 GIMP 的内置脚本功能,并介绍了 GIMP 的 Scheme 实现:Script-Fu。如果你想继续前进,建议你查看官方文档及其[入门教程][9]。如果你不熟悉 Scheme 或 Lisp,那么一开始的语法可能有点吓人,但我还是建议你尝试一下。这可能是一个不错的惊喜。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/gimp-scripting
|
||||
|
||||
作者:[Cristiano L. Fontana][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[amwps290](https://github.com/amwps290)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/cristianofontana
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/painting_computer_screen_art_design_creative.png?itok=LVAeQx3_ (Painting art on a computer screen)
|
||||
[2]: https://www.gimp.org/
|
||||
[3]: https://opensource.com/sites/default/files/uploads/fourier.png (Fourier transform equations)
|
||||
[4]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[5]: https://docs.gimp.org/en/gimp-filters-script-fu.html
|
||||
[6]: https://docs.gimp.org/en/gimp-concepts-script-fu.html
|
||||
[7]: https://en.wikipedia.org/wiki/Scheme_(programming_language)
|
||||
[8]: https://docs.gimp.org/en/gimp-filters-python-fu.html
|
||||
[9]: https://docs.gimp.org/en/gimp-using-script-fu-tutorial.html
|
||||
[10]: https://en.wikipedia.org/wiki/Lisp_%28programming_language%29
|
||||
[11]: https://en.wikipedia.org/wiki/Polish_notation
|
||||
[12]: https://xkcd.com/297/
|
||||
[13]: https://opensource.com/sites/default/files/uploads/procedure_browser.png (GIMP Procedure Browser)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/gui01_image.png (GUI with the displayed image)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/console01_variables.png (Script-Fu console)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/gui02_selected.png (Image with the selected color)
|
||||
[17]: https://opensource.com/sites/default/files/uploads/gui03_grow.png (Image with the selected color)
|
||||
[18]: https://opensource.com/sites/default/files/uploads/gui04_fill.png (Image with the selection filled with black)
|
||||
[19]: https://opensource.com/sites/default/files/uploads/gui05_no_selection.png (Image with no selection)
|
||||
[20]: https://opensource.com/sites/default/files/uploads/gui06_spread.png (Image with pixels moved around)
|
||||
[21]: https://opensource.com/sites/default/files/uploads/gui07_invert.png (Image with pixels moved around)
|
||||
[22]: https://opensource.com/sites/default/files/uploads/gui08_hurl.png (Image with pixels moved around)
|
||||
[23]: https://opensource.com/sites/default/files/uploads/modified_fourier.png (Equations of the Fourier transform and its inverse)
|
77
published/20210127 3 email mistakes and how to avoid them.md
Normal file
77
published/20210127 3 email mistakes and how to avoid them.md
Normal file
@ -0,0 +1,77 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13086-1.html)
|
||||
[#]: subject: (3 email mistakes and how to avoid them)
|
||||
[#]: via: (https://opensource.com/article/21/1/email-mistakes)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
3 个电子邮件错误以及如何避免它们
|
||||
======
|
||||
|
||||
> 自动化是美好的,但也不总是那样。确保你的电子邮件自动回复和抄送配置正确,这样你就不会浪费大家的时间。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/05/090335a888nqn7pcolblzn.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十七天。
|
||||
|
||||
好了,我们已经谈到了一些我们应该对电子邮件做的事情:[不要再把它当作即时通讯工具][2]、[优先处理事情][3]、[努力达到收件箱 0 新邮件][4],以及[有效过滤][5]。但哪些事情是我们不应该做的呢?
|
||||
|
||||
![Automated email reply][6]
|
||||
|
||||
*你真幸运 (Kevin Sonney, [CC BY-SA 4.0][7])*
|
||||
|
||||
### 1、请不要对所有事情自动回复
|
||||
|
||||
邮件列表中总有些人,他们去度假了,并设置了一个“我在度假”的自动回复信息。然而,他们没有正确地设置,所以它对列表上的每一封邮件都会回复“我在度假”,直到管理员将其屏蔽或取消订阅。
|
||||
|
||||
我们都感受到了这种痛苦,我承认过去至少有一次,我就是那个人。
|
||||
|
||||
从我的错误中吸取教训,并确保你的自动回复器或假期信息对它们将回复谁和多久回复一次有限制。
|
||||
|
||||
![An actual email with lots of CC'd recipients][8]
|
||||
|
||||
*这是一封真实的电子邮件 (Kevin Sonney, [CC BY-SA 4.0][7])*
|
||||
|
||||
### 2、请不要抄送给所有人
|
||||
|
||||
我们都至少做过一次。我们需要发送邮件的人员众多,因此我们只需抄送他们*所有人*。有时这是有必要的,但大多数时候,它并不是。当然,你邀请每个人在庭院吃生日蛋糕,或者你的表姐要结婚了,或者公司刚拿到一个大客户,这都是好事。如果你有邮件列表的话,请用邮件列表,如果没有的话,请给每个人密送。说真的,密送是你的朋友。
|
||||
|
||||
### 3、回复所有人不是你的朋友
|
||||
|
||||
![Reply options in Kmail][9]
|
||||
|
||||
这一条与上一条是相辅相成的。我不知道有多少次看到有人向一个名单(或者是一个大群的人)发送信息,而这个信息本来是要发给一个人的。我见过这样发送的相对好的邮件,以及随之而来的纪律处分邮件。
|
||||
|
||||
认真地说,除非必须,不要使用“回复全部”按钮。即使是这样,也要确保你*真的*需要这样做。
|
||||
|
||||
有些电子邮件应用比其他应用管理得更好。Kmail,[KDE Kontact][10] 的电子邮件组件,在**回复**工具栏按钮的子菜单中,有几个不同的回复选项。你可以选择只回复给**发件人**字段中的任何实体(通常是一个人,但有时是一个邮件列表),或者回复给作者(在抄送或密送中去除每一个人),或者只回复给一个邮件列表,或者回复*所有人*(不要这样做)。看到明确列出的选项,的确可以帮助你了解谁会收到你要发送的邮件副本,这有时比你想象的更发人深省。我曾经发现,当我意识到一个评论并不一定会对一个复杂的讨论的最终目标有所帮助时,我就会把邮件的收件人改为只是作者,而不是整个列表。
|
||||
|
||||
(另外,如果你写的邮件可能会给你的 HR 或公司带来麻烦,请在点击发送之前多考虑下。——
|
||||
|
||||
希望你已经*不再*在电子邮件中这么做了。如果你认识的人是这样的呢?欢迎与他们分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/email-mistakes
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_screen_windows_files.png?itok=kLTeQUbY (Computer screen with files or windows open)
|
||||
[2]: https://opensource.com/article/21/1/email-rules
|
||||
[3]: https://opensource.com/article/21/1/prioritize-tasks
|
||||
[4]: https://opensource.com/article/21/1/inbox-zero
|
||||
[5]: https://opensource.com/article/21/1/email-filter
|
||||
[6]: https://opensource.com/sites/default/files/day17-image1.png
|
||||
[7]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[8]: https://opensource.com/sites/default/files/day17-image2.png
|
||||
[9]: https://opensource.com/sites/default/files/kmail-replies.jpg (Reply options in Kmail)
|
||||
[10]: https://opensource.com/article/21/1/kde-kontact
|
@ -0,0 +1,176 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13100-1.html)
|
||||
[#]: subject: (Why I use the D programming language for scripting)
|
||||
[#]: via: (https://opensource.com/article/21/1/d-scripting)
|
||||
[#]: author: (Lawrence Aberba https://opensource.com/users/aberba)
|
||||
|
||||
我为什么要用 D 语言写脚本?
|
||||
======
|
||||
|
||||
> D 语言以系统编程语言而闻名,但它也是编写脚本的一个很好的选择。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/09/134351j4m3hrhll0h38plp.jpg)
|
||||
|
||||
D 语言由于其静态类型和元编程能力,经常被宣传为系统编程语言。然而,它也是一种非常高效的脚本语言。
|
||||
|
||||
由于 Python 在自动化任务和快速实现原型想法方面的灵活性,它通常被选为脚本语言。这使得 Python 对系统管理员、[管理者][2]和一般的开发人员非常有吸引力,因为它可以自动完成他们可能需要手动完成的重复性任务。
|
||||
|
||||
我们自然也可以期待任何其他的脚本编写语言具有 Python 的这些特性和能力。以下是我认为 D 是一个不错的选择的两个原因。
|
||||
|
||||
### 1、D 很容易读和写
|
||||
|
||||
作为一种类似于 C 的语言,D 应该是大多数程序员所熟悉的。任何使用 JavaScript、Java、PHP 或 Python 的人对 D 语言都很容易上手。
|
||||
|
||||
如果你还没有安装 D,请[安装 D 编译器][3],这样你就可以[运行本文中的 D 代码][4]。你也可以使用[在线 D 编辑器][5]。
|
||||
|
||||
下面是一个 D 代码的例子,它从一个名为 `words.txt` 的文件中读取单词,并在命令行中打印出来:
|
||||
|
||||
```
|
||||
open
|
||||
source
|
||||
is
|
||||
cool
|
||||
```
|
||||
|
||||
用 D 语言写脚本:
|
||||
|
||||
```
|
||||
#!/usr/bin/env rdmd
|
||||
// file print_words.d
|
||||
|
||||
// import the D standard library
|
||||
import std;
|
||||
|
||||
void main(){
|
||||
// open the file
|
||||
File("./words.txt")
|
||||
|
||||
//iterate by line
|
||||
.byLine
|
||||
|
||||
// print each number
|
||||
.each!writeln;
|
||||
}
|
||||
```
|
||||
|
||||
这段代码以 [释伴][6] 开头,它将使用 [rdmd][7] 来运行这段代码,`rdmd` 是 D 编译器自带的编译和运行代码的工具。假设你运行的是 Unix 或 Linux,在运行这个脚本之前,你必须使用` chmod` 命令使其可执行:
|
||||
|
||||
```
|
||||
chmod u+x print_words.d
|
||||
```
|
||||
|
||||
现在脚本是可执行的,你可以运行它:
|
||||
|
||||
```
|
||||
./print_words.d
|
||||
```
|
||||
|
||||
这将在你的命令行中打印以下内容:
|
||||
|
||||
```
|
||||
open
|
||||
source
|
||||
is
|
||||
cool
|
||||
```
|
||||
|
||||
恭喜你,你写了第一个 D 语言脚本。你可以看到 D 是如何让你按顺序链式调用函数,这让阅读代码的感觉很自然,类似于你在头脑中思考问题的方式。这个[功能让 D 成为我最喜欢的编程语言][8]。
|
||||
|
||||
试着再写一个脚本:一个非营利组织的管理员有一个捐款的文本文件,每笔金额都是单独的一行。管理员想把前 10 笔捐款相加,然后打印出金额:
|
||||
|
||||
```
|
||||
#!/usr/bin/env rdmd
|
||||
// file sum_donations.d
|
||||
|
||||
import std;
|
||||
|
||||
void main()
|
||||
{
|
||||
double total = 0;
|
||||
|
||||
// open the file
|
||||
File("monies.txt")
|
||||
|
||||
// iterate by line
|
||||
.byLine
|
||||
|
||||
// pick first 10 lines
|
||||
.take(10)
|
||||
|
||||
// remove new line characters (\n)
|
||||
.map!(strip)
|
||||
|
||||
// convert each to double
|
||||
.map!(to!double)
|
||||
|
||||
// add element to total
|
||||
.tee!((x) { total += x; })
|
||||
|
||||
// print each number
|
||||
.each!writeln;
|
||||
|
||||
// print total
|
||||
writeln("total: ", total);
|
||||
}
|
||||
```
|
||||
|
||||
与 `each` 一起使用的 `!` 操作符是[模板参数][9]的语法。
|
||||
|
||||
### 2、D 是快速原型设计的好帮手
|
||||
|
||||
D 是灵活的,它可以快速地将代码敲打在一起,并使其发挥作用。它的标准库中包含了丰富的实用函数,用于执行常见的任务,如操作数据(JSON、CSV、文本等)。它还带有一套丰富的通用算法,用于迭代、搜索、比较和 mutate 数据。这些巧妙的算法通过定义通用的 [基于范围的接口][10] 而按照序列进行处理。
|
||||
|
||||
上面的脚本显示了 D 中的链式调用函数如何提供顺序处理和操作数据的要领。D 的另一个吸引人的地方是它不断增长的用于执行普通任务的第三方包的生态系统。一个例子是,使用 [Vibe.d][11] web 框架构建一个简单的 web 服务器很容易。下面是一个例子:
|
||||
|
||||
```
|
||||
#!/usr/bin/env dub
|
||||
/+ dub.sdl:
|
||||
dependency "vibe-d" version="~>0.8.0"
|
||||
+/
|
||||
void main()
|
||||
{
|
||||
import vibe.d;
|
||||
listenHTTP(":8080", (req, res) {
|
||||
res.writeBody("Hello, World: " ~ req.path);
|
||||
});
|
||||
runApplication();
|
||||
}
|
||||
```
|
||||
|
||||
它使用官方的 D 软件包管理器 [Dub][12],从 [D 软件包仓库][13]中获取 vibe.d Web 框架。Dub 负责下载 Vibe.d 包,然后在本地主机 8080 端口上编译并启动一个 web 服务器。
|
||||
|
||||
### 尝试一下 D 语言
|
||||
|
||||
这些只是你可能想用 D 来写脚本的几个原因。
|
||||
|
||||
D 是一种非常适合开发的语言。你可以很容易从 D 下载页面安装,因此下载编译器,看看例子,并亲自体验 D 语言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/d-scripting
|
||||
|
||||
作者:[Lawrence Aberba][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://opensource.com/users/aberba
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-concentration-focus-windows-office.png?itok=-8E2ihcF (Woman using laptop concentrating)
|
||||
[2]: https://opensource.com/article/20/3/automating-community-management-python
|
||||
[3]: https://tour.dlang.org/tour/en/welcome/install-d-locally
|
||||
[4]: https://tour.dlang.org/tour/en/welcome/run-d-program-locally
|
||||
[5]: https://run.dlang.io/
|
||||
[6]: https://en.wikipedia.org/wiki/Shebang_(Unix)
|
||||
[7]: https://dlang.org/rdmd.html
|
||||
[8]: https://opensource.com/article/20/7/d-programming
|
||||
[9]: http://ddili.org/ders/d.en/templates.html
|
||||
[10]: http://ddili.org/ders/d.en/ranges.html
|
||||
[11]: https://vibed.org
|
||||
[12]: https://dub.pm/getting_started
|
||||
[13]: https://code.dlang.org
|
@ -0,0 +1,75 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13094-1.html)
|
||||
[#]: subject: (4 tips for preventing notification fatigue)
|
||||
[#]: via: (https://opensource.com/article/21/1/alert-fatigue)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
防止通知疲劳的 4 个技巧
|
||||
======
|
||||
|
||||
> 不要让提醒淹没自己:设置重要的提醒,让其它提醒消失。你会感觉更好,工作效率更高。
|
||||
|
||||
![W】(https://img.linux.net.cn/data/attachment/album/202102/06/234924mo3okotjlv7lo3yo.jpg)
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十八天。
|
||||
|
||||
当我和人们谈论生产力时,我注意到一件事,那就是几乎每个人都是为了保持更清晰的头脑。我们不是把所有的约会都记在脑子里,而是把它们放在一个数字日历上,在事件发生前提醒我们。我们有数字或实体笔记,这样我们就不必记住某件事的每一个小细节。我们有待办事项清单,提醒我们去做该做的事情。
|
||||
|
||||
![Text box offering to send notifications][2]
|
||||
|
||||
*NOPE(Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
如此多的应用、网站和服务想要提醒我们每一件小事,我们很容易就把它们全部调出来。而且,如果我们不这样做,我们将开始遭受**提醒疲劳**的困扰 —— 这时我们处于边缘的状态,只是等待下一个提醒,并生活在恐惧之中。
|
||||
|
||||
提醒疲劳在那些因工作而被随叫随到的人中非常常见。它也发生在那些 **FOMO** (错失恐惧症)的人身上,从而对每一个关键词、标签或在社交媒体上提到他们感兴趣的事情都会设置提醒。
|
||||
|
||||
此时,设置能引起我们的注意,但不会被忽略的提醒是件棘手的事情。不过,我确实有一些有用的提示,这样重要的提醒可能会在这个忙碌的世界中越过我们自己的心理过滤器。
|
||||
|
||||
![Alert for a task][4]
|
||||
|
||||
*我可以忽略这个,对吧?(Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
1. 弄清楚什么更适合你:视觉提醒或声音提醒。我使用视觉弹出和声音的组合,但这对我是有效的。有些人需要触觉提醒。比如手机或手表的震动。找到适合你的那一种。
|
||||
2. 为重要的提醒指定独特的音调或视觉效果。我有一个朋友,他的工作页面的铃声最响亮、最讨厌。这旨在吸引他的注意力,让他看到提醒。我的显示器上有一盏灯,当我在待命时收到工作提醒时,它就会闪烁红灯,以及发送通知到我手机上。
|
||||
3. 关掉那些实际上无关紧要的警报。社交网络、网站和应用都希望得到你的关注。它们不会在意你是否错过会议、约会迟到,或者熬夜到凌晨 4 点。关掉那些不重要的,让那些重要的可以被看到。
|
||||
4. 每隔一段时间就改变一下。上个月有效的东西,下个月可能就不行了。我们会适应、习惯一些东西,然后我们会忽略。如果有些东西不奏效,就换个东西试试吧!它不会伤害你,即使无法解决问题,也许你也会学到一些新知识。
|
||||
|
||||
![Blue alert indicators light][5]
|
||||
|
||||
*蓝色是没问题。红色是有问题。(Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
### 开源和选择
|
||||
|
||||
一个好的应用可以通知提供很多选择。我最喜欢的一个是 Android 的 Etar 日历应用。[Etar 可以从开源 F-droid 仓库中获得][6]。
|
||||
|
||||
Etar 和许多开源应用一样,为你提供了很多选项,尤其是通知设置。
|
||||
|
||||
![Etar][7]
|
||||
|
||||
通过 Etar,你可以激活或停用弹出式通知,设置打盹时间、打盹延迟、是否提醒你已拒绝的事件等。结合有计划的日程安排策略,你可以通过控制数字助手对你需要做的事情进行提示的频率来改变你一天的进程。
|
||||
|
||||
提醒和警报真的很有用,只要我们收到重要的提醒并予以注意即可。这可能需要做一些实验,但最终,少一些噪音是好事,而且更容易注意到真正需要我们注意的提醒。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/alert-fatigue
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/team_dev_email_chat_video_work_wfm_desk_520.png?itok=6YtME4Hj (Working on a team, busy worklife)
|
||||
[2]: https://opensource.com/sites/default/files/day18-image1.png
|
||||
[3]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[4]: https://opensource.com/sites/default/files/day18-image2.png
|
||||
[5]: https://opensource.com/sites/default/files/day18-image3.png
|
||||
[6]: https://f-droid.org/en/packages/ws.xsoh.etar/
|
||||
[7]: https://opensource.com/sites/default/files/etar.jpg (Etar)
|
@ -0,0 +1,168 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13106-1.html)
|
||||
[#]: subject: (How to Run a Shell Script in Linux [Essentials Explained for Beginners])
|
||||
[#]: via: (https://itsfoss.com/run-shell-script-linux/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
基础:如何在 Linux 中运行一个 Shell 脚本
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/10/235325tkv7h8dvlp4makkk.jpg)
|
||||
|
||||
在 Linux 中有两种运行 shell 脚本的方法。你可以使用:
|
||||
|
||||
```
|
||||
bash script.sh
|
||||
```
|
||||
|
||||
或者,你可以像这样执行 shell 脚本:
|
||||
|
||||
```
|
||||
./script.sh
|
||||
```
|
||||
|
||||
这可能很简单,但没太多解释。不要担心,我将使用示例来进行必要的解释,以便你能理解为什么在运行一个 shell 脚本时要使用给定的特定语法格式。
|
||||
|
||||
我将使用这一行 shell 脚本来使需要解释的事情变地尽可能简单:
|
||||
|
||||
```
|
||||
abhishek@itsfoss:~/Scripts$ cat hello.sh
|
||||
|
||||
echo "Hello World!"
|
||||
```
|
||||
|
||||
### 方法 1:通过将文件作为参数传递给 shell 以运行 shell 脚本
|
||||
|
||||
第一种方法涉及将脚本文件的名称作为参数传递给 shell 。
|
||||
|
||||
考虑到 bash 是默认 shell,你可以像这样运行一个脚本:
|
||||
|
||||
```
|
||||
bash hello.sh
|
||||
```
|
||||
|
||||
你知道这种方法的优点吗?**你的脚本不需要执行权限**。对于简单的任务非常方便快速。
|
||||
|
||||
![在 Linux 中运行一个 Shell 脚本][1]
|
||||
|
||||
如果你还不熟悉,我建议你 [阅读我的 Linux 文件权限详细指南][2] 。
|
||||
|
||||
记住,将其作为参数传递的需要是一个 shell 脚本。一个 shell 脚本是由命令组成的。如果你使用一个普通的文本文件,它将会抱怨错误的命令。
|
||||
|
||||
![运行一个文本文件为脚本][3]
|
||||
|
||||
在这种方法中,**你要明确地具体指定你想使用 bash 作为脚本的解释器** 。
|
||||
|
||||
shell 只是一个程序,并且 bash 只是 Shell 的一种实现。还有其它的 shell 程序,像 ksh 、[zsh][4] 等等。如果你安装有其它的 shell ,你也可以使用它们来代替 bash 。
|
||||
|
||||
例如,我已安装了 zsh ,并使用它来运行相同的脚本:
|
||||
|
||||
![使用 Zsh 来执行 Shell 脚本][5]
|
||||
|
||||
### 方法 2:通过具体指定 shell 脚本的路径来执行脚本
|
||||
|
||||
另外一种运行一个 shell 脚本的方法是通过提供它的路径。但是要这样做之前,你的文件必须是可执行的。否则,当你尝试执行脚本时,你将会得到 “权限被拒绝” 的错误。
|
||||
|
||||
因此,你首先需要确保你的脚本有可执行权限。你可以 [使用 chmod 命令][8] 来给予你自己脚本的这种权限,像这样:
|
||||
|
||||
```
|
||||
chmod u+x script.sh
|
||||
```
|
||||
|
||||
使你的脚本是可执行之后,你只需输入文件的名称及其绝对路径或相对路径。大多数情况下,你都在同一个目录中,因此你可以像这样使用它:
|
||||
|
||||
```
|
||||
./script.sh
|
||||
```
|
||||
|
||||
如果你与你的脚本不在同一个目录中,你可以具体指定脚本的绝对路径或相对路径:
|
||||
|
||||
![在其它的目录中运行 Shell 脚本][9]
|
||||
|
||||
在脚本前的这个 `./` 是非常重要的(当你与脚本在同一个目录中)。
|
||||
|
||||
![][10]
|
||||
|
||||
为什么当你在同一个目录下,却不能使用脚本名称?这是因为你的 Linux 系统会在 `PATH` 环境变量中指定的几个目录中查找可执行的文件来运行。
|
||||
|
||||
这里是我的系统的 `PATH` 环境变量的值:
|
||||
|
||||
```
|
||||
abhishek@itsfoss:~$ echo $PATH
|
||||
/home/abhishek/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
|
||||
```
|
||||
|
||||
这意味着在下面目录中具有可执行权限的任意文件都可以在系统的任何位置运行:
|
||||
|
||||
* `/home/abhishek/.local/bin`
|
||||
* `/usr/local/sbin`
|
||||
* `/usr/local/bin`
|
||||
* `/usr/sbin`
|
||||
* `/usr/bin`
|
||||
* `/sbin`
|
||||
* `/bin`
|
||||
* `/usr/games`
|
||||
* `/usr/local/games`
|
||||
* `/snap/bin`
|
||||
|
||||
Linux 命令(像 `ls`、`cat` 等)的二进制文件或可执行文件都位于这些目录中的其中一个。这就是为什么你可以在你系统的任何位置通过使用命令的名称来运作这些命令的原因。看看,`ls` 命令就是位于 `/usr/bin` 目录中。
|
||||
|
||||
![][11]
|
||||
|
||||
当你使用脚本而不具体指定其绝对路径或相对路径时,系统将不能在 `PATH` 环境变量中找到提及的脚本。
|
||||
|
||||
> 为什么大多数 shell 脚本在其头部包含 #! /bin/bash ?
|
||||
>
|
||||
> 记得我提过 shell 只是一个程序,并且有 shell 程序的不同实现。
|
||||
>
|
||||
> 当你使用 `#! /bin/bash` 时,你是具体指定 bash 作为解释器来运行脚本。如果你不这样做,并且以 `./script.sh` 的方式运行一个脚本,它通常会在你正在运行的 shell 中运行。
|
||||
>
|
||||
> 有问题吗?可能会有。看看,大多数的 shell 语法是大多数种类的 shell 中通用的,但是有一些语法可能会有所不同。
|
||||
>
|
||||
> 例如,在 bash 和 zsh 中数组的行为是不同的。在 zsh 中,数组索引是从 1 开始的,而不是从 0 开始。
|
||||
>
|
||||
>![Bash Vs Zsh][12]
|
||||
>
|
||||
> 使用 `#! /bin/bash` 来标识该脚本是 bash 脚本,并且应该使用 bash 作为脚本的解释器来运行,而不受在系统上正在使用的 shell 的影响。如果你使用 zsh 的特殊语法,你可以通过在脚本的第一行添加 `#! /bin/zsh` 的方式来标识其是 zsh 脚本。
|
||||
>
|
||||
> 在 `#!` 和 `/bin/bash` 之间的空格是没有影响的。你也可以使用 `#!/bin/bash` 。
|
||||
|
||||
### 它有帮助吗?
|
||||
|
||||
我希望这篇文章能够增加你的 Linux 知识。如果你还有问题或建议,请留下评论。
|
||||
|
||||
专家用户可能依然会挑出我遗漏的东西。但这种初级题材的问题是,要找到信息的平衡点,避免细节过多或过少,并不容易。
|
||||
|
||||
如果你对学习 bash 脚本感兴趣,在我们专注于系统管理的网站 [Linux Handbook][14] 上,我们有一个 [完整的 Bash 初学者系列][13] 。如果你想要,你也可以 [购买带有附加练习的电子书][15] ,以支持 Linux Handbook。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/run-shell-script-linux/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/run-a-shell-script-linux.png?resize=741%2C329&ssl=1
|
||||
[2]: https://linuxhandbook.com/linux-file-permissions/
|
||||
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/running-text-file-as-script.png?resize=741%2C329&ssl=1
|
||||
[4]: https://www.zsh.org
|
||||
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/execute-shell-script-with-zsh.png?resize=741%2C253&ssl=1
|
||||
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/run-multiple-commands-in-linux.png?fit=800%2C450&ssl=1
|
||||
[7]: https://itsfoss.com/run-multiple-commands-linux/
|
||||
[8]: https://linuxhandbook.com/chmod-command/
|
||||
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/running-shell-script-in-other-directory.png?resize=795%2C272&ssl=1
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/executing-shell-scripts-linux.png?resize=800%2C450&ssl=1
|
||||
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/locating-command-linux.png?resize=795%2C272&ssl=1
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/bash-vs-zsh.png?resize=795%2C386&ssl=1
|
||||
[13]: https://linuxhandbook.com/tag/bash-beginner/
|
||||
[14]: https://linuxhandbook.com
|
||||
[15]: https://www.buymeacoffee.com/linuxhandbook
|
174
published/20210129 Manage containers with Podman Compose.md
Normal file
174
published/20210129 Manage containers with Podman Compose.md
Normal file
@ -0,0 +1,174 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13125-1.html)
|
||||
[#]: subject: (Manage containers with Podman Compose)
|
||||
[#]: via: (https://fedoramagazine.org/manage-containers-with-podman-compose/)
|
||||
[#]: author: (Mehdi Haghgoo https://fedoramagazine.org/author/powergame/)
|
||||
|
||||
用 Podman Compose 管理容器
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
容器很棒,让你可以将你的应用连同其依赖项一起打包,并在任何地方运行。从 2013 年的 Docker 开始,容器已经让软件开发者的生活变得更加轻松。
|
||||
|
||||
Docker 的一个缺点是它有一个中央守护进程,它以 root 用户的身份运行,这对安全有影响。但这正是 Podman 的用武之地。Podman 是一个 [无守护进程容器引擎][2],用于开发、管理和在你的 Linux 系统上以 root 或无 root 模式运行 OCI 容器。
|
||||
|
||||
下面这些文章可以用来了解更多关于 Podman 的信息:
|
||||
|
||||
* [使用 Podman 以非 root 用户身份运行 Linux 容器][11]
|
||||
* [在 Fedora 上使用 Podman 的 Pod][3]
|
||||
* [在 Fedora 中结合权能使用 Podman][4]
|
||||
|
||||
如果你使用过 Docker,你很可能也知道 Docker Compose,它是一个用于编排多个可能相互依赖的容器的工具。要了解更多关于 Docker Compose 的信息,请看它的[文档][5]。
|
||||
|
||||
### 什么是 Podman Compose?
|
||||
|
||||
[Podman Compose][6] 项目的目标是作为 Docker Compose 的替代品,而不需要对 docker-compose.yaml 文件进行任何修改。由于 Podman Compose 使用<ruby>吊舱<rt>pod</rt></ruby> 工作,所以最好看下“吊舱”的最新定义。
|
||||
|
||||
> 一个“<ruby>吊舱<rt>pod</rt></ruby> ”(如一群鲸鱼或豌豆荚)是由一个或多个[容器][7]组成的组,具有共享的存储/网络资源,以及如何运行容器的规范。
|
||||
>
|
||||
> [Pods - Kubernetes 文档][8]
|
||||
|
||||
(LCTT 译注:容器技术领域大量使用了航海比喻,pod 一词,意为“豆荚”,在航海领域指“吊舱” —— 均指盛装多个物品的容器。常不翻译,考虑前后文,可译做“吊舱”。)
|
||||
|
||||
Podman Compose 的基本思想是,它选中 `docker-compose.yaml` 文件里面定义的服务,为每个服务创建一个容器。Docker Compose 和 Podman Compose 的一个主要区别是,Podman Compose 将整个项目的容器添加到一个单一的吊舱中,而且所有的容器共享同一个网络。如你在例子中看到的,在创建容器时使用 `--add-host` 标志,它甚至用和 Docker Compose 一样的方式命名容器。
|
||||
|
||||
### 安装
|
||||
|
||||
Podman Compose 的完整安装说明可以在[项目页面][6]上找到,它有几种方法。要安装最新的开发版本,使用以下命令:
|
||||
|
||||
```
|
||||
pip3 install https://github.com/containers/podman-compose/archive/devel.tar.gz
|
||||
```
|
||||
|
||||
确保你也安装了 [Podman][9],因为你也需要它。在 Fedora 上,使用下面的命令来安装Podman:
|
||||
|
||||
```
|
||||
sudo dnf install podman
|
||||
```
|
||||
|
||||
### 例子:用 Podman Compose 启动一个 WordPress 网站
|
||||
|
||||
想象一下,你的 `docker-compose.yaml` 文件在一个叫 `wpsite` 的文件夹里。一个典型的 WordPress 网站的 `docker-compose.yaml` (或 `docker-compose.yml`) 文件是这样的:
|
||||
|
||||
```
|
||||
version: "3.8"
|
||||
services:
|
||||
web:
|
||||
image: wordpress
|
||||
restart: always
|
||||
volumes:
|
||||
- wordpress:/var/www/html
|
||||
ports:
|
||||
- 8080:80
|
||||
environment:
|
||||
WORDPRESS_DB_HOST: db
|
||||
WORDPRESS_DB_USER: magazine
|
||||
WORDPRESS_DB_NAME: magazine
|
||||
WORDPRESS_DB_PASSWORD: 1maGazine!
|
||||
WORDPRESS_TABLE_PREFIX: cz
|
||||
WORDPRESS_DEBUG: 0
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
- wpnet
|
||||
db:
|
||||
image: mariadb:10.5
|
||||
restart: always
|
||||
ports:
|
||||
- 6603:3306
|
||||
|
||||
volumes:
|
||||
- wpdbvol:/var/lib/mysql
|
||||
|
||||
environment:
|
||||
MYSQL_DATABASE: magazine
|
||||
MYSQL_USER: magazine
|
||||
MYSQL_PASSWORD: 1maGazine!
|
||||
MYSQL_ROOT_PASSWORD: 1maGazine!
|
||||
networks:
|
||||
- wpnet
|
||||
volumes:
|
||||
wordpress: {}
|
||||
wpdbvol: {}
|
||||
|
||||
networks:
|
||||
wpnet: {}
|
||||
```
|
||||
|
||||
如果你用过 Docker,你就会知道你可运行 `docker-compose up` 来启动这些服务。Docker Compose 会创建两个名为 `wpsite_web_1` 和 `wpsite_db_1` 的容器,并将它们连接到一个名为 `wpsite_wpnet` 的网络。
|
||||
|
||||
现在,看看当你在项目目录下运行 `podman-compose up` 时会发生什么。首先,一个以执行命令的目录命名的吊舱被创建。接下来,它寻找 YAML 文件中定义的任何名称的卷,如果它们不存在,就创建卷。然后,在 YAML 文件的 `services` 部分列出的每个服务都会创建一个容器,并添加到吊舱中。
|
||||
|
||||
容器的命名与 Docker Compose 类似。例如,为你的 web 服务创建一个名为 `wpsite_web_1` 的容器。Podman Compose 还为每个命名的容器添加了 `localhost` 别名。之后,容器仍然可以通过名字互相解析,尽管它们并不像 Docker 那样在一个桥接网络上。要做到这一点,使用选项 `-add-host`。例如,`-add-host web:localhost`。
|
||||
|
||||
请注意,`docker-compose.yaml` 包含了一个从主机 8080 端口到容器 80 端口的 Web 服务的端口转发。现在你应该可以通过浏览器访问新 WordPress 实例,地址为 `http://localhost:8080`。
|
||||
|
||||
![WordPress Dashboard][10]
|
||||
|
||||
### 控制 pod 和容器
|
||||
|
||||
要查看正在运行的容器,使用 `podman ps`,它可以显示 web 和数据库容器以及吊舱中的基础设施容器。
|
||||
|
||||
```
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
a364a8d7cec7 docker.io/library/wordpress:latest apache2-foregroun... 2 hours ago Up 2 hours ago 0.0.0.0:8080-&gt;80/tcp, 0.0.0.0:6603-&gt;3306/tcp wpsite_web_1
|
||||
c447024aa104 docker.io/library/mariadb:10.5 mysqld 2 hours ago Up 2 hours ago 0.0.0.0:8080-&gt;80/tcp, 0.0.0.0:6603-&gt;3306/tcp wpsite_db_1
|
||||
12b1e3418e3e k8s.gcr.io/pause:3.2
|
||||
```
|
||||
|
||||
你也可以验证 Podman 已经为这个项目创建了一个吊舱,以你执行命令的文件夹命名。
|
||||
|
||||
```
|
||||
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
|
||||
8a08a3a7773e wpsite Degraded 2 hours ago 12b1e3418e3e 3
|
||||
```
|
||||
|
||||
要停止容器,在另一个命令窗口中输入以下命令:
|
||||
|
||||
```
|
||||
podman-compose down
|
||||
```
|
||||
|
||||
你也可以通过停止和删除吊舱来实现。这实质上是停止并移除所有的容器,然后再删除包含的吊舱。所以,同样的事情也可以通过这些命令来实现:
|
||||
|
||||
```
|
||||
podman pod stop podname
|
||||
podman pod rm podname
|
||||
```
|
||||
|
||||
请注意,这不会删除你在 `docker-compose.yaml` 中定义的卷。所以,你的 WordPress 网站的状态被保存下来了,你可以通过运行这个命令来恢复它。
|
||||
|
||||
```
|
||||
podman-compose up
|
||||
```
|
||||
|
||||
总之,如果你是一个 Podman 粉丝,并且用 Podman 做容器工作,你可以使用 Podman Compose 来管理你的开发和生产中的容器。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/manage-containers-with-podman-compose/
|
||||
|
||||
作者:[Mehdi Haghgoo][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/powergame/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2021/01/podman-compose-1-816x345.jpg
|
||||
[2]: https://podman.io
|
||||
[3]: https://fedoramagazine.org/podman-pods-fedora-containers/
|
||||
[4]: https://linux.cn/article-12859-1.html
|
||||
[5]: https://docs.docker.com/compose/
|
||||
[6]: https://github.com/containers/podman-compose
|
||||
[7]: https://kubernetes.io/docs/concepts/containers/
|
||||
[8]: https://kubernetes.io/docs/concepts/workloads/pods/
|
||||
[9]: https://podman.io/getting-started/installation
|
||||
[10]: https://fedoramagazine.org/wp-content/uploads/2021/01/Screenshot-from-2021-01-08-06-27-29-1024x767.png
|
||||
[11]: https://linux.cn/article-10156-1.html
|
@ -0,0 +1,64 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13113-1.html)
|
||||
[#]: subject: (3 wishes for open source productivity in 2021)
|
||||
[#]: via: (https://opensource.com/article/21/1/productivity-wishlist)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
2021 年开源生产力的 3 个愿望
|
||||
======
|
||||
|
||||
> 2021年,开源世界可以拓展的有很多。这是我特别感兴趣的三个领域。
|
||||
|
||||
![Looking at a map for career journey][1]
|
||||
|
||||
在前几年,这个年度系列涵盖了单个的应用。今年,我们除了关注 2021 年的策略外,还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的最后一天。
|
||||
|
||||
我们已经到了又一个系列的结尾处。因此,让我们谈谈我希望在 2021 年看到的更多事情。
|
||||
|
||||
### 断网
|
||||
|
||||
![Large Lego set built by the author][2]
|
||||
|
||||
*我在假期期间制作的(Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
对*许多、许多的*人来说,2020 年是非常困难的一年。疫情大流行、各种政治事件、24 小时的新闻轰炸等等,都对我们的精神健康造成了伤害。虽然我确实谈到了 [抽出时间进行自我护理][4],但我只是想断网:也就是关闭提醒、手机、平板等,暂时无视这个世界。我公司的一位经理实际上告诉我们,如果放假或休息一天,就把所有与工作有关的东西都关掉(除非我们在值班)。我最喜欢的“断网”活动之一就是听音乐和搭建大而复杂的乐高。
|
||||
|
||||
### 可访问性
|
||||
|
||||
尽管我谈论的许多技术都是任何人都可以做的,但是软件方面的可访问性都有一定难度。相对于自由软件运动之初,Linux 和开源世界在辅助技术方面已经有了长足发展。但是,仍然有太多的应用和系统不会考虑有些用户没有与设计者相同的能力。我一直在关注这一领域的发展,因为每个人都应该能够访问事物。
|
||||
|
||||
### 更多的一体化选择
|
||||
|
||||
![JPilot all in one organizer software interface][5]
|
||||
|
||||
*JPilot(Kevin Sonney, [CC BY-SA 4.0][3])*
|
||||
|
||||
在 FOSS 世界中,一体化的个人信息管理解决方案远没有商业软件世界中那么多。总体趋势是使用单独的应用,它们必须通过配置来相互通信或通过中介服务(如 CalDAV 服务器)。移动市场在很大程度上推动了这一趋势,但我仍然向往像 [JPilot][6] 这样无需额外插件或服务就能完成几乎所有我需要的事情的日子。
|
||||
|
||||
非常感谢大家阅读这个年度系列。如果你认为我错过了什么,或者明年需要注意什么,请在下方评论。
|
||||
|
||||
就像我在 [生产力炼金术][7] 上说的那样,尽最大努力保持生产力!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/productivity-wishlist
|
||||
|
||||
作者:[Kevin Sonney][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://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/career_journey_road_gps_path_map_520.png?itok=PpL6jJgY (Looking at a map for career journey)
|
||||
[2]: https://opensource.com/sites/default/files/day21-image1.png
|
||||
[3]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[4]: https://opensource.com/article/21/1/self-care
|
||||
[5]: https://opensource.com/sites/default/files/day21-image2.png
|
||||
[6]: http://www.jpilot.org/
|
||||
[7]: https://productivityalchemy.com
|
@ -0,0 +1,81 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13097-1.html)
|
||||
[#]: subject: (Generate QR codes with this open source tool)
|
||||
[#]: via: (https://opensource.com/article/21/2/zint-barcode-generator)
|
||||
[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
|
||||
|
||||
Zint:用这个开源工具生成二维码
|
||||
======
|
||||
|
||||
> Zint 可以轻松生成 50 多种类型的自定义条码。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/07/231854y8ffstg0m6l2fcmz.jpg)
|
||||
|
||||
二维码是一种很好的可以向人们提供信息的方式,且没有打印的麻烦和费用。大多数人的智能手机都支持二维码扫描,无论其操作系统是什么。
|
||||
|
||||
你可能想使用二维码的原因有很多。也许你是一名教师,希望通过补充材料来测试你的学生,以增强学习效果,或者是一家餐厅,需要在遵守社交距离准则的同时提供菜单。我经常行走于自然小径,那里贴有树木和其他植物的标签。用二维码来补充这些小标签是一种很好的方式,它可以提供关于公园展品的额外信息,而无需花费和维护标识牌。在这些和其他情况下,二维码是非常有用的。
|
||||
|
||||
在互联网上搜索一个简单的、开源的方法来创建二维码时,我发现了 [Zint][2]。Zint 是一个优秀的开源 (GPLv3.0) 生成条码的解决方案。根据该项目的 [GitHub 仓库][3]:“Zint 是一套可以方便地对任何一种公共领域条形码标准的数据进行编码的程序,并允许你将这种功能集成到你自己的程序中。”
|
||||
|
||||
Zint 支持 50 多种类型的条形码,包括二维码(ISO 18004),你可以轻松地创建这些条形码,然后复制和粘贴到 word 文档、博客、维基和其他数字媒体中。人们可以用智能手机扫描这些二维码,快速链接到信息。
|
||||
|
||||
### 安装 Zint
|
||||
|
||||
Zint 适用于 Linux、macOS 和 Windows。
|
||||
|
||||
你可以在基于 Ubuntu 的 Linux 发行版上使用 `apt` 安装 Zint 命令:
|
||||
|
||||
```
|
||||
$ sudo apt install zint
|
||||
```
|
||||
|
||||
我还想要一个图形用户界面(GUI),所以我安装了 Zint-QT:
|
||||
|
||||
```
|
||||
$ sudo apt install zint-qt
|
||||
```
|
||||
|
||||
请参考手册的[安装部分][4],了解 macOS 和 Windows 的说明。
|
||||
|
||||
### 用 Zint 生成二维码
|
||||
|
||||
安装好后,我启动了它,并创建了我的第一个二维码,这是一个指向 Opensource.com 的链接。
|
||||
|
||||
![Generating QR code with Zint][5]
|
||||
|
||||
Zint 的 50 多个其他条码选项包括许多国家的邮政编码、DotCode、EAN、EAN-14 和通用产品代码 (UPC)。[项目文档][2]中包含了它可以渲染的所有代码的完整列表。
|
||||
|
||||
你可以将任何条形码复制为 BMP 或 SVG,或者将输出保存为你应用中所需要的任何尺寸的图像文件。这是我的 77x77 像素的二维码。
|
||||
|
||||
![QR code][7]
|
||||
|
||||
该项目维护了一份出色的用户手册,其中包含了在[命令行][8]和 [GUI][9] 中使用 Zint 的说明。你甚至可以[在线][10]试用 Zint。对于功能请求或错误报告,请[访问网站][11]或[发送电子邮件][12]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/2/zint-barcode-generator
|
||||
|
||||
作者:[Don Watkins][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://opensource.com/users/don-watkins
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
|
||||
[2]: http://www.zint.org.uk/
|
||||
[3]: https://github.com/zint/zint
|
||||
[4]: http://www.zint.org.uk/Manual.aspx?type=p&page=2
|
||||
[5]: https://opensource.com/sites/default/files/uploads/zintqrcode_generation.png (Generating QR code with Zint)
|
||||
[6]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[7]: https://opensource.com/sites/default/files/uploads/zintqrcode_77px.png (QR code)
|
||||
[8]: http://zint.org.uk/Manual.aspx?type=p&page=4
|
||||
[9]: http://zint.org.uk/Manual.aspx?type=p&page=3
|
||||
[10]: http://www.barcode-generator.org/
|
||||
[11]: https://lists.sourceforge.net/lists/listinfo/zint-barcode
|
||||
[12]: mailto:zint-barcode@lists.sourceforge.net
|
@ -0,0 +1,86 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13119-1.html)
|
||||
[#]: subject: (Filmulator is a Simple, Open Source, Raw Image Editor for Linux Desktop)
|
||||
[#]: via: (https://itsfoss.com/filmulator/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
Filmulator:一个简单的、开源的 Raw 图像编辑器
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/15/100616o54wb5h4aqgmq4qe.jpg)
|
||||
|
||||
> Filmulator 是一个开源的具有库管理功能的 raw 照片编辑应用,侧重于简单、易用和简化的工作流程。
|
||||
|
||||
### Filmulator:适用于 Linux(和 Windows)的 raw 图像编辑器
|
||||
|
||||
[Linux 中有一堆 raw 照片编辑器][1],[Filmulator][2] 就是其中之一。Filmulator 的目标是仅提供基本要素,从而使 raw 图像编辑变得简单。它还增加了库处理的功能,如果你正在为你的相机图像寻找一个不错的应用,这是一个加分项。
|
||||
|
||||
对于那些不知道 raw 的人来说,[raw 图像文件][3]是一个最低限度处理、未压缩的文件。换句话说,它是未经压缩的数字文件,并且只经过了最低限度的处理。专业摄影师更喜欢用 raw 文件拍摄照片,并自行处理。普通人从智能手机拍摄照片,它通常被压缩为 JPEG 格式或被过滤。
|
||||
|
||||
让我们来看看在 Filmulator 编辑器中会有什么功能。
|
||||
|
||||
### Filmulator 的功能
|
||||
|
||||
![Filmulator interface][4]
|
||||
|
||||
Filmulator 宣称,它不是典型的“胶片效果滤镜” —— 这只是复制了胶片的外在特征。相反,Filmulator 从根本上解决了胶片的魅力所在:显影过程。
|
||||
|
||||
它模拟了胶片的显影过程:从胶片的“曝光”,到每个像素内“银晶”的生长,再到“显影剂”在相邻像素之间与储槽中大量显影剂的扩散。
|
||||
|
||||
Fimulator 开发者表示,这种模拟带来了以下好处:
|
||||
|
||||
* 大的明亮区域变得更暗,压缩了输出动态范围。
|
||||
* 小的明亮区域使周围环境变暗,增强局部对比度。
|
||||
* 在明亮区域,饱和度得到增强,有助于保留蓝天、明亮肤色和日落的色彩。
|
||||
* 在极度饱和的区域,亮度会被减弱,有助于保留细节,例如花朵。
|
||||
|
||||
以下是经 Filmulator 处理后的 raw 图像的对比,以自然的方式增强色彩,而不会引起色彩剪切。
|
||||
|
||||
![原图][5]
|
||||
|
||||
![处理后][10]
|
||||
|
||||
### 在 Ubuntu/Linux 上安装 Filmulator
|
||||
|
||||
Filmulator 有一个 AppImage 可用,这样你就可以在 Linux 上轻松使用它。使用 [AppImage 文件][6]真的很简单。下载后,使它可执行,然后双击运行。
|
||||
|
||||
- [下载 Filmulator for Linux][7]
|
||||
|
||||
对 Windows 用户也有一个 Windows 版本。除此之外,你还可以随时前往[它的 GitHub 仓库][8]查看它的源代码。
|
||||
|
||||
有一份[小文档][9]来帮助你开始使用 Fimulator。
|
||||
|
||||
### 总结
|
||||
|
||||
Fimulator 的设计理念是为任何工作提供最好的工具,而且只有这一个工具。这意味着牺牲了灵活性,但获得了一个大大简化和精简的用户界面。
|
||||
|
||||
我连业余摄影师都不是,更别说是专业摄影师了。我没有单反或其他高端摄影设备。因此,我无法测试和分享我对 Filmulator 的实用性的经验。
|
||||
|
||||
如果你有更多处理 raw 图像的经验,请尝试下 Filmulator,并分享你的意见。有一个 AppImage 可以让你快速测试它,看看它是否适合你的需求。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/filmulator/
|
||||
|
||||
作者:[Abhishek Prakash][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://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/raw-image-tools-linux/
|
||||
[2]: https://filmulator.org/
|
||||
[3]: https://www.findingtheuniverse.com/what-is-raw-in-photography/
|
||||
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/02/Filmulate.jpg?resize=799%2C463&ssl=1
|
||||
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/02/image-without-filmulator.jpeg?ssl=1
|
||||
[6]: https://itsfoss.com/use-appimage-linux/
|
||||
[7]: https://filmulator.org/download/
|
||||
[8]: https://github.com/CarVac/filmulator-gui
|
||||
[9]: https://github.com/CarVac/filmulator-gui/wiki
|
||||
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/02/image-with-filmulator.jpeg?ssl=1
|
@ -0,0 +1,153 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13122-1.html)
|
||||
[#]: subject: (Paru – A New AUR Helper and Pacman Wrapper Based on Yay)
|
||||
[#]: via: (https://itsfoss.com/paru-aur-helper/)
|
||||
[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
|
||||
|
||||
Paru:基于 Yay 的新 AUR 助手
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/16/101301ldekk9kkpqlplke6.jpg)
|
||||
|
||||
[用户选择 Arch Linux][1] 或 [基于 Arch 的 Linux 发行版][2]的主要原因之一就是 [Arch 用户仓库(AUR)][3]。
|
||||
|
||||
遗憾的是,[pacman][4],也就是 Arch 的包管理器,不能以类似官方仓库的方式访问 AUR。AUR 中的包是以 [PKGBUILD][5] 的形式存在的,需要手动过程来构建。
|
||||
|
||||
AUR 助手可以自动完成这个过程。毫无疑问,[yay][6] 是最受欢迎和备受青睐的 AUR 助手之一。
|
||||
|
||||
最近,`yay` 的两位开发者之一的 [Morganamilo][7][宣布][8]将退出 `yay` 的维护工作,以开始自己的 AUR 助手 [paru][9]。`paru` 是用 [Rust][10] 编写的,而 `yay` 是用 [Go][11] 编写的,它的设计是基于 yay 的。
|
||||
|
||||
请注意,`yay` 还没有结束支持,它仍然由 [Jguer][12] 积极维护。他还[评论][13]说,`paru` 可能适合那些寻找丰富功能的 AUR 助手的用户。因此我推荐大家尝试一下。
|
||||
|
||||
### 安装 Paru AUR 助手
|
||||
|
||||
要安装 `paru`,打开你的终端,逐一输入以下命令:
|
||||
|
||||
```
|
||||
sudo pacman -S --needed base-devel
|
||||
git clone https://aur.archlinux.org/paru.git
|
||||
cd paru
|
||||
makepkg -si
|
||||
```
|
||||
|
||||
现在已经安装好了,让我们来看看如何使用它。
|
||||
|
||||
### 使用 Paru AUR 助手的基本命令
|
||||
|
||||
在我看来,这些都是 `paru` 最基本的命令。你可以在 [GitHub][9] 的官方仓库中探索更多。
|
||||
|
||||
* `paru <用户输入>`:搜索并安装“用户输入”
|
||||
* `paru -`:`paru -Syu` 的别名
|
||||
* `paru -Sua`:仅升级 AUR 包。
|
||||
* `paru -Qua`:打印可用的 AUR 更新
|
||||
* `paru -Gc <用户输入>`:显示“用户输入”的 AUR 评论
|
||||
|
||||
### 充分使用 Paru AUR 助手
|
||||
|
||||
你可以在 GitHub 上访问 `paru` 的[更新日志][14]来查看完整的变更日志历史,或者你可以在[首次发布][15]中查看对 `yay` 的变化。
|
||||
|
||||
#### 在 Paru 中启用颜色
|
||||
|
||||
要在 `paru` 中启用颜色,你必须先在 `pacman` 中启用它。所有的[配置文件][16]都在 `/etc` 目录下。在此例中,我[使用 Nano 文本编辑器][17],但是,你可以选择使用任何[基于终端的文本编辑器][18]。
|
||||
|
||||
```
|
||||
sudo nano /etc/pacman.conf
|
||||
```
|
||||
|
||||
打开 `pacman` 配置文件后,取消 `Color` 的注释,即可启用此功能。
|
||||
|
||||
![][19]
|
||||
|
||||
#### 反转搜索顺序
|
||||
|
||||
根据你的搜索条件,最相关的包通常会显示在搜索结果的顶部。在 `paru` 中,你可以反转搜索顺序,使你的搜索更容易。
|
||||
|
||||
与前面的例子类似,打开 `paru` 配置文件:
|
||||
|
||||
```
|
||||
sudo nano /etc/paru.conf
|
||||
```
|
||||
|
||||
取消注释 `BottomUp` 项,然后保存文件。
|
||||
|
||||
![][20]
|
||||
|
||||
如你所见,顺序是反转的,第一个包出现在了底部。
|
||||
|
||||
![][21]
|
||||
|
||||
#### 编辑 PKGBUILD (对于高级用户)
|
||||
|
||||
如果你是一个有经验的 Linux 用户,你可以通过 `paru` 编辑 AUR 包。要做到这一点,你需要在 `paru` 配置文件中启用该功能,并设置你所选择的文件管理器。
|
||||
|
||||
在此例中,我将使用配置文件中的默认值,即 vifm 文件管理器。如果你还没有使用过它,你可能需要安装它。
|
||||
|
||||
```
|
||||
sudo pacman -S vifm
|
||||
sudo nano /etc/paru.conf
|
||||
```
|
||||
|
||||
打开配置文件,如下所示取消注释。
|
||||
|
||||
![][22]
|
||||
|
||||
让我们回到 [Google Calendar][23] 的 AUR 包,并尝试安装它。系统会提示你审查该软件包。输入 `Y` 并按下回车。
|
||||
|
||||
![][24]
|
||||
|
||||
从文件管理器中选择 PKGBUILD,然后按下回车查看软件包。
|
||||
|
||||
![][25]
|
||||
|
||||
你所做的任何改变都将是永久性的,下次升级软件包时,你的改变将与上游软件包合并。
|
||||
|
||||
![][26]
|
||||
|
||||
### 总结
|
||||
|
||||
`paru` 是 [AUR 助手家族][27]的又一个有趣的新成员,前途光明。此时,我不建议更换 `yay`,因为它还在维护,但一定要试试 `paru`。你可以把它们两个都安装到你的系统中,然后得出自己的结论。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/paru-aur-helper/
|
||||
|
||||
作者:[Dimitrios Savvopoulos][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://itsfoss.com/author/dimitrios/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/why-arch-linux/
|
||||
[2]: https://itsfoss.com/arch-based-linux-distros/
|
||||
[3]: https://itsfoss.com/aur-arch-linux/
|
||||
[4]: https://itsfoss.com/pacman-command/
|
||||
[5]: https://wiki.archlinux.org/index.php/PKGBUILD
|
||||
[6]: https://news.itsfoss.com/qt-6-released/
|
||||
[7]: https://github.com/Morganamilo
|
||||
[8]: https://www.reddit.com/r/archlinux/comments/jjn1c1/paru_v100_and_stepping_away_from_yay/
|
||||
[9]: https://github.com/Morganamilo/paru
|
||||
[10]: https://www.rust-lang.org/
|
||||
[11]: https://golang.org/
|
||||
[12]: https://github.com/Jguer
|
||||
[13]: https://aur.archlinux.org/packages/yay/#pinned-788241
|
||||
[14]: https://github.com/Morganamilo/paru/releases
|
||||
[15]: https://github.com/Morganamilo/paru/releases/tag/v1.0.0
|
||||
[16]: https://linuxhandbook.com/linux-directory-structure/#-etc-configuration-files
|
||||
[17]: https://itsfoss.com/nano-editor-guide/
|
||||
[18]: https://itsfoss.com/command-line-text-editors-linux/
|
||||
[19]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/pacman.conf-color.png?resize=800%2C480&ssl=1
|
||||
[20]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/paru.conf-bottomup.png?resize=800%2C480&ssl=1
|
||||
[21]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/paru.conf-bottomup-2.png?resize=800%2C480&ssl=1
|
||||
[22]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/paru.conf-vifm.png?resize=732%2C439&ssl=1
|
||||
[23]: https://aur.archlinux.org/packages/gcalcli/
|
||||
[24]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/paru-proceed-for-review.png?resize=800%2C480&ssl=1
|
||||
[25]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/paru-proceed-for-review-2.png?resize=800%2C480&ssl=1
|
||||
[26]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/paru-proceed-for-review-3.png?resize=800%2C480&ssl=1
|
||||
[27]: https://itsfoss.com/best-aur-helpers/
|
||||
[28]: https://news.itsfoss.com/
|
255
published/20210204 A hands-on tutorial of SQLite3.md
Normal file
255
published/20210204 A hands-on tutorial of SQLite3.md
Normal file
@ -0,0 +1,255 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "amwps290"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13117-1.html"
|
||||
[#]: subject: "A hands-on tutorial of SQLite3"
|
||||
[#]: via: "https://opensource.com/article/21/2/sqlite3-cheat-sheet"
|
||||
[#]: author: "Klaatu https://opensource.com/users/klaatu"
|
||||
|
||||
SQLite3 实践教程
|
||||
======
|
||||
|
||||
> 开始使用这个功能强大且通用的数据库吧。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/14/131146jsx2kvyobwxwswct.jpg)
|
||||
|
||||
应用程序经常需要保存数据。无论你的用户是创建简单的文本文档、复杂的图形布局、游戏进度还是错综复杂的客户和订单号列表,软件通常都意味着生成数据。有很多方法可以存储数据以供重复使用。你可以将文本转储为 INI、[YAML][2]、XML 或 JSON 等配置格式,可以输出原始的二进制数据,也可以将数据存储在结构化数据库中。SQLite 是一个自包含的、轻量级数据库,可轻松创建、解析、查询、修改和传输数据。
|
||||
|
||||
- 下载 [SQLite3 备忘录][3]
|
||||
|
||||
SQLite 专用于 [公共领域][4],[从技术上讲,这意味着它没有版权,因此不需要许可证][5]。如果你需要许可证,则可以 [购买所有权担保][6]。SQLite 非常常见,大约有 1 万亿个 SQLite 数据库正在使用中。在每个基于 Webkit 的 Web 浏览器,现代电视机,汽车多媒体系统以及无数其他软件应用程序中,Android 和 iOS 设备, macOS 和 Windows 10 计算机,大多数 Linux 系统上都包含多个这种数据库。
|
||||
|
||||
总而言之,它是用于存储和组织数据的一个可靠而简单的系统。
|
||||
|
||||
### 安装
|
||||
|
||||
你的系统上可能已经有 SQLite 库,但是你需要安装其命令行工具才能直接使用它。在 Linux上,你可能已经安装了这些工具。该工具提供的命令是 `sqlite3` (而不仅仅是 sqlite)。
|
||||
|
||||
如果没有在你的 Linux 或 BSD 上安装 SQLite,你则可以从软件仓库中或 ports 树中安装 SQLite,也可以从源代码或已编译的二进制文件进行[下载并安装][7]。
|
||||
|
||||
在 macOS 或 Windows 上,你可以从 [sqlite.org][7] 下载并安装 SQLite 工具。
|
||||
|
||||
### 使用 SQLite
|
||||
|
||||
通过编程语言与数据库进行交互是很常见的。因此,像 Java、Python、Lua、PHP、Ruby、C++ 以及其他编程语言都提供了 SQLite 的接口(或“绑定”)。但是,在使用这些库之前,了解数据库引擎的实际情况以及为什么你对数据库的选择很重要是有帮助的。本文向你介绍 SQLite 和 `sqlite3` 命令,以便你熟悉该数据库如何处理数据的基础知识。
|
||||
|
||||
### 与 SQLite 交互
|
||||
|
||||
你可以使用 `sqlite3` 命令与 SQLite 进行交互。 该命令提供了一个交互式的 shell 程序,以便你可以查看和更新数据库。
|
||||
|
||||
```
|
||||
$ sqlite3
|
||||
SQLite version 3.34.0 2020-12-01 16:14:00
|
||||
Enter ".help" for usage hints.
|
||||
Connected to a transient in-memory database.
|
||||
Use ".open FILENAME" to reopen on a persistent database.
|
||||
sqlite>
|
||||
```
|
||||
|
||||
该命令将使你处于 SQLite 的子 shell 中,因此现在的提示符是 SQLite 的提示符。你以前使用的 Bash 命令在这里将不再适用。你必须使用 SQLite 命令。要查看 SQLite 命令列表,请输入 `.help`:
|
||||
|
||||
```
|
||||
sqlite> .help
|
||||
.archive ... Manage SQL archives
|
||||
.auth ON|OFF SHOW authorizer callbacks
|
||||
.backup ?DB? FILE Backup DB (DEFAULT "main") TO FILE
|
||||
.bail ON|off Stop after hitting an error. DEFAULT OFF
|
||||
.binary ON|off Turn BINARY output ON OR off. DEFAULT OFF
|
||||
.cd DIRECTORY CHANGE the working directory TO DIRECTORY
|
||||
[...]
|
||||
```
|
||||
|
||||
这些命令中的其中一些是二进制的,而其他一些则需要唯一的参数(如文件名、路径等)。这些是 SQLite Shell 的管理命令,不是用于数据库查询。数据库以结构化查询语言(SQL)进行查询,许多 SQLite 查询与你从 [MySQL][8] 和 [MariaDB][9] 数据库中已经知道的查询相同。但是,数据类型和函数有所不同,因此,如果你熟悉另一个数据库,请特别注意细微的差异。
|
||||
|
||||
### 创建数据库
|
||||
|
||||
启动 SQLite 时,可以打开内存数据库,也可以选择要打开的数据库:
|
||||
|
||||
```
|
||||
$ sqlite3 mydatabase.db
|
||||
```
|
||||
|
||||
如果还没有数据库,则可以在 SQLite 提示符下创建一个数据库:
|
||||
|
||||
```
|
||||
sqlite> .open mydatabase.db
|
||||
```
|
||||
|
||||
现在,你的硬盘驱动器上有一个空文件,可以用作 SQLite 数据库。 文件扩展名 `.db` 是任意的。你也可以使用 `.sqlite` 或任何你想要的后缀。
|
||||
|
||||
### 创建一个表
|
||||
|
||||
数据库包含一些<ruby>表<rt>table</rt></ruby>,可以将其可视化为电子表格。有许多的行(在数据库中称为<ruby>记录<rt>record</rt></ruby>)和列。行和列的交集称为<ruby>字段<rt>field</rt></ruby>。
|
||||
|
||||
结构化查询语言(SQL)以其提供的内容而命名:一种以可预测且一致的语法查询数据库内容以接收有用的结果的方法。SQL 读起来很像普通的英语句子,即使有点机械化。当前,你的数据库是一个没有任何表的空数据库。
|
||||
|
||||
你可以使用 `CREATE` 来创建一个新表,你可以和 `IF NOT EXISTS` 结合使用。以便不会破坏现在已有的同名的表。
|
||||
|
||||
你无法在 SQLite 中创建一个没有任何字段的空表,因此在尝试 `CREATE` 语句之前,必须考虑预期表将存储的数据类型。在此示例中,我将使用以下列创建一个名为 `member` 的表:
|
||||
|
||||
* 唯一标识符
|
||||
* 人名
|
||||
* 记录创建的时间和日期
|
||||
|
||||
#### 唯一标识符
|
||||
|
||||
最好用唯一的编号来引用记录,幸运的是,SQLite 认识到这一点,创建一个名叫 `rowid` 的列来为你自动实现这一点。
|
||||
|
||||
无需 SQL 语句即可创建此字段。
|
||||
|
||||
#### 数据类型
|
||||
|
||||
对于我的示例表中,我正在创建一个 `name` 列来保存 `TEXT` 类型的数据。为了防止在没有指定字段数据的情况下创建记录,可以添加 `NOT NULL` 指令。
|
||||
|
||||
用 `name TEXT NOT NULL` 语句来创建。
|
||||
|
||||
SQLite 中有五种数据类型(实际上是 _储存类别_):
|
||||
|
||||
* `TEXT`:文本字符串
|
||||
* `INTEGER`:一个数字
|
||||
* `REAL`:一个浮点数(小数位数无限制)
|
||||
* `BLOB`:二进制数据(例如,.jpeg 或 .webp 图像)
|
||||
* `NULL`:空值
|
||||
|
||||
#### 日期和时间戳
|
||||
|
||||
SQLite 有一个方便的日期和时间戳功能。它本身不是数据类型,而是 SQLite 中的一个函数,它根据所需的格式生成字符串或整数。 在此示例中,我将其保留为默认值。
|
||||
|
||||
创建此字段的 SQL 语句是:`datestamp DATETIME DEFAULT CURRENT_TIMESTAMP`。
|
||||
|
||||
### 创建表的语句
|
||||
|
||||
在 SQLite 中创建此示例表的完整 SQL:
|
||||
|
||||
```
|
||||
sqlite> CREATE TABLE
|
||||
...> IF NOT EXISTS
|
||||
...> member (name TEXT NOT NULL,
|
||||
...> datestamp DATETIME DEFAULT CURRENT_TIMESTAMP);
|
||||
```
|
||||
|
||||
在此代码示例中,我在语句的分句后按了回车键。以使其更易于阅读。除非以分号(`;`)终止,否则 SQLite 不会运行你的 SQL 语句。
|
||||
|
||||
你可以使用 SQLite 命令 `.tables` 验证表是否已创建:
|
||||
|
||||
```
|
||||
sqlite> .tables
|
||||
member
|
||||
```
|
||||
|
||||
### 查看表中的所有列
|
||||
|
||||
你可以使用 `PRAGMA` 语句验证表包含哪些列和行:
|
||||
|
||||
```
|
||||
sqlite> PRAGMA table_info(member);
|
||||
0|name|TEXT|1||0
|
||||
1|datestamp|DATETIME|0|CURRENT_TIMESTAMP|0
|
||||
```
|
||||
|
||||
### 数据输入
|
||||
|
||||
你可以使用 `INSERT` 语句将一些示例数据填充到表中:
|
||||
|
||||
```
|
||||
> INSERT INTO member (name) VALUES ('Alice');
|
||||
> INSERT INTO member (name) VALUES ('Bob');
|
||||
> INSERT INTO member (name) VALUES ('Carol');
|
||||
> INSERT INTO member (name) VALUES ('David');
|
||||
```
|
||||
|
||||
查看表中的数据:
|
||||
|
||||
```
|
||||
> SELECT * FROM member;
|
||||
Alice|2020-12-15 22:39:00
|
||||
Bob|2020-12-15 22:39:02
|
||||
Carol|2020-12-15 22:39:05
|
||||
David|2020-12-15 22:39:07
|
||||
```
|
||||
|
||||
#### 添加多行数据
|
||||
|
||||
现在创建第二个表:
|
||||
|
||||
```
|
||||
> CREATE TABLE IF NOT EXISTS linux (
|
||||
...> distro TEXT NOT NULL);
|
||||
```
|
||||
|
||||
填充一些示例数据,这一次使用小的 `VALUES` 快捷方式,因此你可以在一个命令中添加多行。关键字 `VALUES` 期望以括号形式列出列表,而用多个逗号分隔多个列表:
|
||||
|
||||
```
|
||||
> INSERT INTO linux (distro)
|
||||
...> VALUES ('Slackware'), ('RHEL'),
|
||||
...> ('Fedora'),('Debian');
|
||||
```
|
||||
|
||||
### 修改表结构
|
||||
|
||||
你现在有两个表,但是到目前为止,两者之间没有任何关系。它们每个都包含独立的数据,但是可能你可能需要将第一个表的成员与第二个表中列出的特定项相关联。
|
||||
|
||||
为此,你可以为第一个表创建一个新列,该列对应于第二个表。由于两个表都设计有唯一标识符(这要归功于 SQLite 的自动创建),所以连接它们的最简单方法是将其中一个的 `rowid` 字段用作另一个的选择器。
|
||||
|
||||
在第一个表中创建一个新列,以存储第二个表中的值:
|
||||
|
||||
```
|
||||
> ALTER TABLE member ADD os INT;
|
||||
```
|
||||
|
||||
使用 `linux` 表中的唯一标识符作为 `member` 表中每一条记录中 `os` 字段的值。因为记录已经存在。因此你可以使用 `UPDATE` 语句而不是使用 `INSERT` 语句来更新数据。需要特别注意的是,你首先需要选中特定的一行来然后才能更新其中的某个字段。从句法上讲,这有点相反,更新首先发生,选择匹配最后发生:
|
||||
|
||||
```
|
||||
> UPDATE member SET os=1 WHERE name='Alice';
|
||||
```
|
||||
|
||||
对 `member` 表中的其他行重复相同的过程。更新 `os` 字段,为了数据多样性,在四行记录上分配三种不同的发行版(其中一种加倍)。
|
||||
|
||||
### 联接表
|
||||
|
||||
现在,这两个表相互关联,你可以使用 SQL 显示关联的数据。数据库中有多种 _联接方式_,但是一旦掌握了基础知识,就可以尝试所有的联接形式。这是一个基本联接,用于将 `member` 表的 `os` 字段中的值与 linux 表的 `rowid` 字段相关联:
|
||||
|
||||
```
|
||||
> SELECT * FROM member INNER JOIN linux ON member.os=linux.rowid;
|
||||
Alice|2020-12-15 22:39:00|1|Slackware
|
||||
Bob|2020-12-15 22:39:02|3|Fedora
|
||||
Carol|2020-12-15 22:39:05|3|Fedora
|
||||
David|2020-12-15 22:39:07|4|Debian
|
||||
```
|
||||
|
||||
`os` 和 `rowid` 字段形成了关联。
|
||||
|
||||
在一个图形应用程序中,你可以想象 `os` 字段是一个下拉选项菜单,其中的值是 `linux` 表中 `distro` 字段中的数据。将相关的数据集通过唯一的字段相关联,可以确保数据的一致性和有效性,并且借助 SQL,你可以在以后动态地关联它们。
|
||||
|
||||
### 了解更多
|
||||
|
||||
SQLite 是一个非常有用的自包含的、可移植的开源数据库。学习以交互方式使用它是迈向针对 Web 应用程序进行管理或通过编程语言库使用它的重要的第一步。
|
||||
|
||||
如果你喜欢 SQLite,也可以尝试由同一位作者 Richard Hipp 博士的 [Fossil][10]。
|
||||
|
||||
在学习和使用 SQLite 时,有一些常用命令可能会有所帮助,所以请立即下载我们的 [SQLite3 备忘单][3]!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/2/sqlite3-cheat-sheet
|
||||
|
||||
作者:[Klaatu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[amwps290](https://github.com/amwps290)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [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/coverimage_cheat_sheet.png?itok=lYkNKieP "Cheat Sheet cover image"
|
||||
[2]: https://www.redhat.com/sysadmin/yaml-beginners
|
||||
[3]: https://opensource.com/downloads/sqlite-cheat-sheet
|
||||
[4]: https://sqlite.org/copyright.html
|
||||
[5]: https://directory.fsf.org/wiki/License:PublicDomain
|
||||
[6]: https://www.sqlite.org/purchase/license?
|
||||
[7]: https://www.sqlite.org/download.html
|
||||
[8]: https://www.mysql.com/
|
||||
[9]: https://mariadb.org/
|
||||
[10]: https://opensource.com/article/20/11/fossil
|
@ -0,0 +1,58 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (scvoet)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13120-1.html)
|
||||
[#]: subject: (Why the success of open source depends on empathy)
|
||||
[#]: via: (https://opensource.com/article/21/2/open-source-empathy)
|
||||
[#]: author: (Bronagh Sorota https://opensource.com/users/bsorota)
|
||||
|
||||
为何开源的成功取决于同理心?
|
||||
======
|
||||
|
||||
> 随着对同理心认识的提高和传播同理心的激励,开源生产力将得到提升,协作者将会聚拢,可以充分激发开源软件开发的活力。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/15/110606rc48qf05904m9n7p.jpg)
|
||||
|
||||
开源开发的协调创新精神和社区精神改变了世界。Jim Whitehurst 在[《开放式组织》][2]中解释说,开源的成功源于“将人们视为社区的一份子,从交易思维转变为基于承诺基础的思维方式”。 但是,开源开发模型的核心仍然存在障碍:它经常性地缺乏人类的<ruby>同理心<rt>empathy</rt></ruby>。
|
||||
|
||||
同理心是理解或感受他人感受的能力。在开源社区中,面对面的人际互动和协作是很少的。任何经历过 GitHub <ruby>拉取请求<rt>Pull request</rt></ruby>或<ruby>议题<rt>Issue</rt></ruby>的开发者都曾收到过来自他们可能从未见过的人的评论,这些人往往身处地球的另一端,而他们的交流也可能同样遥远。现代开源开发就是建立在这种异步、事务性的沟通基础之上。因此,人们在社交媒体平台上所经历的同类型的网络欺凌和其他虐待行为,在开源社区中也不足为奇。
|
||||
|
||||
当然,并非所有开源交流都会事与愿违。许多人在工作中发展出了尊重并秉持着良好的行为标准。但是很多时候,人们的沟通也常常缺乏常识性的礼仪,他们将人们像机器而非人类一般对待。这种行为是激发开源创新模型全部潜力的障碍,因为它让许多潜在的贡献者望而却步,并扼杀了灵感。
|
||||
|
||||
### 恶意交流的历史
|
||||
|
||||
代码审查中存在的敌意言论对开源社区来说并不新鲜,它多年来一直被社区所容忍。开源教父<ruby>莱纳斯·托瓦尔兹<rt>Linus Torvalds</rt></ruby>经常在代码不符合他的标准时[抨击][3] Linux 社区,并将贡献者赶走。埃隆大学计算机科学教授 Megan Squire 借助[机器学习][4]分析了托瓦尔兹的侮辱行为,发现它们在四年内的数量高达数千次。2018 年,莱纳斯因自己的不良行为而自我放逐,责成自己学习同理心,道歉并为 Linux 社区制定了行为准则。
|
||||
|
||||
2015 年,[Sage Sharp][5] 虽然在技术上受人尊重,但因其缺乏对个人的尊重,被辞去了 FOSS 女性外展计划中的 Linux 内核协调员一职。
|
||||
|
||||
PR 审核中存在的贬低性评论对开发者会造成深远的影响。它导致开发者在提交 PR 时产生畏惧感,让他们对预期中的反馈感到恐惧。这吞噬了开发者对自己能力的信心。它逼迫工程师每次都只能追求完美,从而减缓了开发速度,这与许多社区采用的敏捷方法论背道而驰。
|
||||
|
||||
### 如何缩小开源中的同理心差距?
|
||||
|
||||
通常情况下,冒犯的评论常是无意间的,而通过一些指导,作者则可以学会如何在不带负面情绪的情况下表达意见。GitHub 不会监控议题和 PR 的评论是否有滥用内容,相反,它提供了一些工具,使得社区能够对其内容进行审查。仓库的所有者可以删除评论和锁定对话,所有贡献者可以报告滥用和阻止用户。
|
||||
|
||||
制定社区行为准则可为所有级别的贡献者提供一个安全且包容的环境,并且能让所有级别的贡献者参与并定义降低协作者之间冲突的过程。
|
||||
|
||||
我们能够克服开源中存在的同理心问题。面对面的辩论比文字更有利于产生共鸣,所以尽可能选择视频通话。以同理心的方式分享反馈,树立榜样。如果你目睹了一个尖锐的评论,请做一个指导者而非旁观者。如果你是受害者,请大声说出来。在面试候选人时,评估同理心能力,并将同理心能力与绩效评估和奖励挂钩。界定并执行社区行为准则,并管理好你的社区。
|
||||
|
||||
随着对同理心认识的提高和传播同理心的激励,开源生产力将得到提升,协作者将会聚拢,可以充分激发开源软件开发的活力。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/2/open-source-empathy
|
||||
|
||||
作者:[Bronagh Sorota][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[scvoet](https://github.com/scvoet)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/bsorota
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/practicing-empathy.jpg?itok=-A7fj6NF (Practicing empathy)
|
||||
[2]: https://www.redhat.com/en/explore/the-open-organization-book
|
||||
[3]: https://arstechnica.com/information-technology/2013/07/linus-torvalds-defends-his-right-to-shame-linux-kernel-developers/
|
||||
[4]: http://flossdata.syr.edu/data/insults/hicssInsultsv2.pdf
|
||||
[5]: https://en.wikipedia.org/wiki/Sage_Sharp
|
@ -0,0 +1,76 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13133-1.html)
|
||||
[#]: subject: (3 open source tools that make Linux the ideal workstation)
|
||||
[#]: via: (https://opensource.com/article/21/2/linux-workday)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
让 Linux 成为理想的工作站的 3 个开源工具
|
||||
======
|
||||
|
||||
> Linux 不但拥有你认为所需的一切,还有更多可以让你高效工作的工具。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202102/19/134935qhe252ifbvbpnzxk.jpg)
|
||||
|
||||
在 2021 年,有更多让人们喜欢 Linux 的理由。在这个系列中,我将分享 21 种使用 Linux 的不同理由。今天,我将与你分享为什么 Linux 是你工作的最佳选择。
|
||||
|
||||
每个人都希望在工作期间提高工作效率。如果你的工作通常涉及到文档、演示文稿和电子表格的工作,那么你可能已经习惯了特定的例行工作。问题在于,这个*惯常的例行工作*通常是由一两个特定的应用程序决定的,无论是某个办公套件还是桌面操作系统。当然,习惯并不意味着它是理想的,但是它往往会毫无疑义地持续存在,甚至影响到企业的运作架构。
|
||||
|
||||
### 更聪明地工作
|
||||
|
||||
如今,许多办公应用程序都在云端运行,因此如果你愿意的话,你可以在 Linux 上使用相同的方式。然而,由于许多典型的知名办公应用程序并不符合 Linux 上的文化预期,因此你可能会发现自己受到启发,想去探索其他的选择。正如任何渴望走出“舒适区”的人所知道的那样,这种微妙的打破可能会出奇的有用。很多时候,你不知道自己效率低下,因为你实际上并没有尝试过以不同的方式做事。强迫自己去探索其他方式,你永远不知道会发现什么。你甚至不必完全知道要寻找的内容。
|
||||
|
||||
### LibreOffice
|
||||
|
||||
Linux(或任何其他平台)上显而易见的开源办公主力之一是 [LibreOffice][2]。它具有多个组件,包括文字处理器、演示软件、电子表格、关系型数据库界面、矢量绘图等。它可以从其他流行的办公应用程序中导入许多文档格式,因此从其他工具过渡到 LibreOffice 通常很容易。
|
||||
|
||||
然而,LibreOffice 不仅仅是一个出色的办公套件。LibreOffice 支持宏,所以机智的用户可以自动完成重复性任务。它还具有终端命令的功能,因此你可以在不启动 LibreOffice 界面的情况下执行许多任务。
|
||||
|
||||
想象一下,比如要打开 21 个文档,导航到**文件**菜单,到**导出**或**打印**菜单项,并将文件导出为 PDF 或 EPUB。这至少需要 84 次以上的点击,可能要花费一个小时的时间。相比之下,打开一个文档文件夹,并转换所有文件为 PDF 或 EPUB,只需要执行一个迅速的命令或菜单操作。转换将在后台运行,而你可以处理其他事情。只需要四分之一的时间,可能更少。
|
||||
|
||||
```
|
||||
$ libreoffice --headless --convert-to epub *.docx
|
||||
```
|
||||
|
||||
这是一个小改进,是由 Linux 工具集和你可以自定义环境和工作流程的便利性所潜在带来的鼓励。
|
||||
|
||||
### Abiword 和 Gnumeric
|
||||
|
||||
有时,你并不需要一个大而全的办公套件。如果你喜欢简化你的办公室工作,那么使用一个轻量级和针对特定任务的应用程序可能更好。例如,我大部分时间都是用文本编辑器写文章,因为我知道在转换为 HTML 的过程中,所有的样式都会被丢弃。但有些时候,文字处理器是很有用的,无论是打开别人发给我的文档,还是因为我想用一种快速简单的方法来生成一些样式漂亮的文本。
|
||||
|
||||
[Abiword][3] 是一款简单的文字处理器,它基本支持流行的文档格式,并具备你所期望的文字处理器的所有基本功能。它并不意味着是一个完整的办公套件,这是它最大的特点。虽然没有太多的选择,但我们仍然处于信息过载的时代,这正是一个完整的办公套件或文字处理器有时会犯的错误。如果你想避免这种情况,那就用一些简单的东西来代替。
|
||||
|
||||
同样,[Gnumeric][4] 项目提供了一个简单的电子表格应用程序。Gnumeric 避免了任何严格意义上的电子表格所不需要的功能,所以你仍然可以获得强大的公式语法、大量的函数,以及样式和操作单元格的所有选项。我不怎么使用电子表格,所以我发现自己在极少数需要查看或处理分类账中的数据时,对 Gnumeric 相当满意。
|
||||
|
||||
### Pandoc
|
||||
|
||||
通过专门的命令和文件处理程序,可以最小化。`pandoc` 命令专门用于文件转换。它就像 `libreoffice --headless` 命令一样,只是要处理的文档格式数量是它的十倍。你甚至可以用它来生成演示文稿! 如果你的工作之一是从一个文档中提取源文本,并以多种格式交付它,那么 Pandoc 是必要的,所以你应该[下载我们的攻略][5]看看。
|
||||
|
||||
广义上讲,Pandoc 代表的是一种完全不同的工作方式。它让你脱离了办公应用的束缚。它将你从试图将你的想法写成文字,并同时决定这些文字应该使用什么字体的工作中分离出来。在纯文本中工作,然后转换为各种交付格式,让你可以使用任何你想要的应用程序,无论是移动设备上的记事本,还是你碰巧坐在电脑前的简单文本编辑器,或者是云端的文本编辑器。
|
||||
|
||||
### 寻找替代品
|
||||
|
||||
Linux 有很多意想不到的替代品。你可以从你正在做的事情中退后一步,分析你的工作流程,评估你所需的结果,并调查那些声称可以完全你的需求的新应用程序来找到它们。
|
||||
|
||||
改变你所使用的工具、工作流程和日常工作可能会让你迷失方向,特别是当你不知道你要找的到底是什么的时候。但 Linux 的优势在于,你有机会重新评估你在多年的计算机使用过程中潜意识里形成的假设。如果你足够努力地寻找答案,你最终会意识到问题所在。通常,你最终会欣赏你学到的东西。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/2/linux-workday
|
||||
|
||||
作者:[Seth Kenlon][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/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD (Person using a laptop)
|
||||
[2]: http://libreoffice.org
|
||||
[3]: https://www.abisource.com
|
||||
[4]: http://www.gnumeric.org
|
||||
[5]: https://opensource.com/article/20/5/pandoc-cheat-sheet
|
@ -1,296 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (bestony)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (lawyer The MIT License, Line by Line)
|
||||
[#]: via: (https://writing.kemitchell.com/2016/09/21/MIT-License-Line-by-Line.html)
|
||||
[#]: author: (Kyle E. Mitchell https://kemitchell.com/)
|
||||
|
||||
lawyer The MIT License, Line by Line
|
||||
======
|
||||
|
||||
### The MIT License, Line by Line
|
||||
|
||||
[The MIT License][1] is the most popular open-source software license. Here’s one read of it, line by line.
|
||||
|
||||
#### Read the License
|
||||
|
||||
If you’re involved in open-source software and haven’t taken the time to read the license from top to bottom—it’s only 171 words—you need to do so now. Especially if licenses aren’t your day-to-day. Make a mental note of anything that seems off or unclear, and keep trucking. I’ll repeat every word again, in chunks and in order, with context and commentary. But it’s important to have the whole in mind.
|
||||
|
||||
> The MIT License (MIT)
|
||||
>
|
||||
> Copyright (c) <year> <copyright holders>
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
>
|
||||
> The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
||||
|
||||
The license is arranged in five paragraphs, but breaks down logically like this:
|
||||
|
||||
* **Header**
|
||||
* **License Title** : “The MIT License”
|
||||
* **Copyright Notice** : “Copyright (c) …”
|
||||
* **License Grant** : “Permission is hereby granted …”
|
||||
* **Grant Scope** : “… to deal in the Software …”
|
||||
* **Conditions** : “… subject to …”
|
||||
* **Attribution and Notice** : “The above … shall be included …”
|
||||
* **Warranty Disclaimer** : “The software is provided ‘as is’ …”
|
||||
* **Limitation of Liability** : “In no event …”
|
||||
|
||||
|
||||
|
||||
Here we go:
|
||||
|
||||
#### Header
|
||||
|
||||
##### License Title
|
||||
|
||||
> The MIT License (MIT)
|
||||
|
||||
“The MIT License” is a not a single license, but a family of license forms derived from language prepared for releases from the Massachusetts Institute of Technology. It has seen a lot of changes over the years, both for the original projects that used it, and also as a model for other projects. The Fedora Project maintains a [kind of cabinet of MIT license curiosities][2], with insipid variations preserved in plain text like anatomical specimens in formaldehyde, tracing a wayward kind of evolution.
|
||||
|
||||
Fortunately, the [Open Source Initiative][3] and [Software Package Data eXchange][4] groups have standardized a generic MIT-style license form as “The MIT License”. OSI in turn has adopted SPDX’ standardized [string identifiers][5] for common open-source licenses, with `MIT` pointing unambiguously to the standardized form “MIT License”. If you want MIT-style terms for a new project, use [the standardized form][1].
|
||||
|
||||
Even if you include “The MIT License” or “SPDX:MIT” in a `LICENSE` file, any responsible reviewer will still run a comparison of the text against the standard form, just to be sure. While various license forms calling themselves “MIT License” vary only in minor details, the looseness of what counts as an “MIT License” has tempted some authors into adding bothersome “customizations”. The canonical horrible, no good, very bad example of this is [the JSON license][6], an MIT-family license plus “The Software shall be used for Good, not Evil.”. This kind of thing might be “very Crockford”. It is definitely a pain in the ass. Maybe the joke was supposed to be on the lawyers. But they laughed all the way to the bank.
|
||||
|
||||
Moral of the story: “MIT License” alone is ambiguous. Folks probably have a good idea what you mean by it, but you’re only going to save everyone—yourself included—time by copying the text of the standard MIT License form into your project. If you use metadata, like the `license` property in package manager metadata files, to designate the `MIT` license, make sure your `LICENSE` file and any header comments use the standard form text. All of this can be [automated][7].
|
||||
|
||||
##### Copyright Notice
|
||||
|
||||
> Copyright (c) <year> <copyright holders>
|
||||
|
||||
Until the 1976 Copyright Act, United States copyright law required specific actions, called “formalities”, to secure copyright in creative works. If you didn’t follow those formalities, your rights to sue others for unauthorized use of your work were limited, often completely lost. One of those formalities was “notice”: Putting marks on your work and otherwise making it known to the market that you were claiming copyright. The © is a standard symbol for marking copyrighted works, to give notice of copyright. The ASCII character set doesn’t have the © symbol, but `Copyright (c)` gets the same point across.
|
||||
|
||||
The 1976 Copyright Act, which “implemented” many requirements of the international Berne Convention, eliminated formalities for securing copyright. At least in the United States, copyright holders still need to register their copyrighted works before suing for infringement, with potentially higher damages if they register before infringement begins. In practice, however, many register copyright right before bringing suit against someone in particular. You don’t lose your copyright just by failing to put notices on it, registering, sending a copy to the Library of Congress, and so on.
|
||||
|
||||
Even if copyright notices aren’t as absolutely necessary as they used to be, they are still plenty useful. Stating the year a work was authored and who the copyright belonged to give some sense of when copyright in the work might expire, bringing the work into the public domain. The identity of the author or authors is also useful: United States law calculates copyright terms differently for individual and “corporate” authors. Especially in business use, it may also behoove a company to think twice about using software from a known competitor, even if the license terms give very generous permission. If you’re hoping others will see your work and want to license it from you, copyright notices serve nicely for attribution.
|
||||
|
||||
As for “copyright holder”: Not all standard form licenses have a space to write this out. More recent license forms, like [Apache 2.0][8] and [GPL 3.0][9], publish `LICENSE` texts that are meant to be copied verbatim, with header comments and separate files elsewhere to indicate who owns copyright and is giving the license. Those approaches neatly discourage changes to the “standard” texts, accidental or intentional. They also make automated license identification more reliable.
|
||||
|
||||
The MIT License descends from language written for releases of code by institutions. For institutional releases, there was just one clear “copyright holder”, the institution releasing the code. Other institutions cribbed these licenses, replacing “MIT” with their own names, leading eventually to the generic forms we have now. This process repeated for other short-form institutional licenses of the era, notably the [original four-clause BSD License][10] for the University of California, Berkeley, now used in [three-clause][11] and [two-clause][12] variants, as well as [The ISC License][13] for the Internet Systems Consortium, an MIT variant.
|
||||
|
||||
In each case, the institution listed itself as the copyright holder in reliance on rules of copyright ownership, called “[works made for hire][14]” rules, that give employers and clients ownership of copyright in some work their employees and contractors do on their behalf. These rules don’t usually apply to distributed collaborators submitting code voluntarily. This poses a problem for project-steward foundations, like the Apache Foundation and Eclipse Foundation, that accept contributions from a more diverse group of contributors. The usual foundation approach thus far has been to use a house license that states a single copyright holder—[Apache 2.0][8] and [EPL 1.0][15]—backed up by contributor license agreements—[Apache CLAs][16] and [Eclipse CLAs][17]—to collect rights from contributors. Collecting copyright ownership in one place is even more important under “copyleft” licenses like the GPL, which rely on copyright owners to enforce license conditions to promote software-freedom values.
|
||||
|
||||
These days, loads of projects without any kind of institutional or business steward use MIT-style license terms. SPDX and OSI have helped these use cases by standardizing forms of licenses like MIT and ISC that don’t refer to a specific entity or institutional copyright holder. Armed with those forms, the prevailing practice of project authors is to fill their own name in the copyright notice of the form very early on … and maybe bump the year here and there. At least under United States copyright law, the resulting copyright notice doesn’t give a full picture.
|
||||
|
||||
The original owner of a piece of software retains ownership of their work. But while MIT-style license terms give others rights to build on and change the software, creating what the law calls “derivative works”, they don’t give the original author ownership of copyright in others’ contributions. Rather, each contributor has copyright in any [even marginally creative][18] work they make using the existing code as a starting point.
|
||||
|
||||
Most of these projects also balk at the idea of taking contributor license agreements, to say nothing of signed copyright assignments. That’s both naive and understandable. Despite the assumption of some newer open-source developers that sending a pull request on GitHub “automatically” licenses the contribution for distribution on the terms of the project’s existing license, United States law doesn’t recognize any such rule. Strong copyright protection, not permissive licensing, is the default.
|
||||
|
||||
Update: GitHub later changed its site-wide terms of service to include an attempt to flip this default, at least on GitHub.com. I’ve written up some thoughts on that development, not all of them positive, in [another post][19].
|
||||
|
||||
To fill the gap between legally effective, well-documented grants of rights in contributions and no paper trail at all, some projects have adopted the [Developer Certificate of Origin][20], a standard statement contributors allude to using `Signed-Off-By` metadata tags in their Git commits. The Developer Certificate of Origin was developed for Linux kernel development in the wake of the infamous SCO lawsuits, which alleged that chunks of Linux’ code derived from SCO-owned Unix source. As a means of creating a paper trail showing that each line of Linux came from a contributor, the Developer Certificate of Origin functions nicely. While the Developer Certificate of Origin isn’t a license, it does provide lots of good evidence that those submitting code expected the project to distribute their code, and for others to use it under the kernel’s existing license terms. The kernel also maintains a machine-readable `CREDITS` file listing contributors with name, affiliation, contribution area, and other metadata. I’ve done [some][21] [experiments][22] adapting that approach for projects that don’t use the kernel’s development flow.
|
||||
|
||||
#### License Grant
|
||||
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”),
|
||||
|
||||
The meat of The MIT License is, you guessed it, a license. In general terms, a license is permission that one person or legal entity—the “licensor”—gives another—the “licensee”—to do something the law would otherwise let them sue for. The MIT License is a promise not to sue.
|
||||
|
||||
The law sometimes distinguishes licenses from promises to give licenses. If someone breaks a promise to give a license, you may be able to sue them for breaking their promise, but you may not end up with a license. “Hereby” is one of those hokey, archaic-sounding words lawyers just can’t get rid of. It’s used here to show that the license text itself gives the license, and not just a promise of a license. It’s a legal [IIFE][23].
|
||||
|
||||
While many licenses give permission to a specific, named licensee, The MIT License is a “public license”. Public licenses give everybody—the public at large—permission. This is one of the three great ideas in open-source licensing. The MIT License captures this idea by giving a license “to any person obtaining a copy of … the Software”. As we’ll see later, there is also a condition to receiving this license that ensures others will learn about their permission, too.
|
||||
|
||||
The parenthetical with a capitalized term in quotation marks (a “Definition”), is the standard way to give terms specific meanings in American-style legal documents. Courts will reliably look back to the terms of the definition when they see a defined, capitalized term used elsewhere in the document.
|
||||
|
||||
##### Grant Scope
|
||||
|
||||
> to deal in the Software without restriction,
|
||||
|
||||
From the licensee’s point of view, these are the seven most important words in The MIT License. The key legal concerns are getting sued for copyright infringement and getting sued for patent infringement. Neither copyright law nor patent law uses “to deal in” as a term of art; it has no specific meaning in court. As a result, any court deciding a dispute between a licensor and a licensee would ask what the parties meant and understood by this language. What the court will see is that the language is intentionally broad and open-ended. It gives licensees a strong argument against any claim by a licensor that they didn’t give permission for the licensee to do that specific thing with the software, even if the thought clearly didn’t occur to either side when the license was given.
|
||||
|
||||
> including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
|
||||
No piece of legal writing is perfect, “fully settled in meaning”, or unmistakably clear. Beware anyone who pretends otherwise. This is the least perfect part of The MIT License. There are three main issues:
|
||||
|
||||
First, “including without limitation” is a legal antipattern. It crops up in any number of flavors:
|
||||
|
||||
* “including, without limitation”
|
||||
* “including, without limiting the generality of the foregoing”
|
||||
* “including, but not limited to”
|
||||
* many, many pointless variations
|
||||
|
||||
|
||||
|
||||
All of these share a common purpose, and they all fail to achieve it reliably. Fundamentally, drafters who use them try to have their cake and eat it, too. In The MIT License, that means introducing specific examples of “dealing in the Software”—“use, copy, modify” and so on—without implying that licensee action has to be something like the examples given to count as “dealing in”. The trouble is that, if you end up needing a court to review and interpret the terms of a license, the court will see its job as finding out what those fighting meant by the language. If the court needs to decide what “deal in” means, it cannot “unsee” the examples, even if you tell it to. I’d argue that “deal in the Software without restriction” alone would be better for licensees. Also shorter.
|
||||
|
||||
Second, the verbs given as examples of “deal in” are a hodgepodge. Some have specific meanings under copyright or patent law, others almost do or just plain don’t:
|
||||
|
||||
* use appears in [United States Code title 35, section 271(a)][24], the patent law’s list of what patent owners can sue others for doing without permission.
|
||||
|
||||
* copy appears in [United States Code title 17, section 106][25], the copyright law’s list of what copyright owners can sue others for doing without permission.
|
||||
|
||||
* modify doesn’t appear in either copyright or patent statute. It is probably closest to “prepare derivative works” under the copyright statute, but may also implicate improving or otherwise derivative inventions.
|
||||
|
||||
* merge doesn’t appear in either copyright or patent statute. “Merger” has a specific meaning in copyright, but that’s clearly not what’s intended here. Rather, a court would probably read “merge” according to its meaning in industry, as in “to merge code”.
|
||||
|
||||
* publish doesn’t appear in either copyright or patent statute. Since “the Software” is what’s being published, it probably hews closest to “distribute” under the [copyright statute][25]. That statute also covers rights to perform and display works “publicly”, but those rights apply only to specific kinds of copyrighted work, like plays, sound recordings, and motion pictures.
|
||||
|
||||
* distribute appears in the [copyright statute][25].
|
||||
|
||||
* sublicense is a general term of intellectual property law. The right to sublicense means the right to give others licenses of their own, to do some or all of what you have permission to do. The MIT License’s right to sublicense is actually somewhat unusual in open-source licenses generally. The norm is what Heather Meeker calls a “direct licensing” approach, where everyone who gets a copy of the software and its license terms gets a license direct from the owner. Anyone who might get a sublicense under the MIT License will probably end up with a copy of the license telling them they have a direct license, too.
|
||||
|
||||
* sell copies of is a mongrel. It is close to “offer to sell” and “sell” in the [patent statute][24], but refers to “copies”, a copyright concept. On the copyright side, it seems close to “distribute”, but the [copyright statute][25] makes no mention of sales.
|
||||
|
||||
* permit persons to whom the Software is furnished to do so seems redundant of “sublicense”. It’s also unnecessary to the extent folks who get copies also get a direct license.
|
||||
|
||||
|
||||
|
||||
|
||||
Lastly, as a result of this mishmash of legal, industry, general-intellectual-property, and general-use terms, it isn’t clear whether The MIT License includes a patent license. The general language “deal in” and some of the example verbs, especially “use”, point toward a patent license, albeit a very unclear one. The fact that the license comes from the copyright holder, who may or may not have patent rights in inventions in the software, as well as most of the example verbs and the definition of “the Software” itself, all point strongly toward a copyright license. More recent permissive open-source licenses, like [Apache 2.0][8], address copyright, patent, and even trademark separately and specifically.
|
||||
|
||||
##### Three License Conditions
|
||||
|
||||
> subject to the following conditions:
|
||||
|
||||
There’s always a catch! MIT has three!
|
||||
|
||||
If you don’t follow The MIT License’s conditions, you don’t get the permission the license offers. So failing to do what the conditions say at least theoretically leaves you open to a lawsuit, probably a copyright lawsuit.
|
||||
|
||||
Using the value of the software to the licensee to motivate compliance with conditions, even though the licensee paid nothing for the license, is the second great idea of open-source licensing. The last, not found in The MIT License, builds off license conditions: “Copyleft” licenses like the [GNU General Public License][9] use license conditions to control how those making changes can license and distribute their changed versions.
|
||||
|
||||
##### Notice Condition
|
||||
|
||||
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
If you give someone a copy of the software, you need to include the license text and any copyright notice. This serves a few critical purposes:
|
||||
|
||||
1. Gives others notice that they have permission for the software under the public license. This is a key part of the direct-licensing model, where each user gets a license direct from the copyright holder.
|
||||
|
||||
2. Makes known who’s behind the software, so they can be showered in praises, glory, and cold, hard cash donations.
|
||||
|
||||
3. Ensures the warranty disclaimer and limitation of liability (coming up next) follow the software around. Everyone who gets a copy should get a copy of those licensor protections, too.
|
||||
|
||||
|
||||
|
||||
|
||||
There’s nothing to stop you charging for providing a copy, or even a copy in compiled form, without source code. But when you do, you can’t pretend that the MIT code is your own proprietary code, or provided under some other license. Those receiving get to know their rights under the “public license”.
|
||||
|
||||
Frankly, compliance with this condition is breaking down. Nearly every open-source license has such an “attribution” condition. Makers of system and installed software often understand they’ll need to compile a notices file or “license information” screen, with copies of license texts for libraries and components, for each release of their own. The project-steward foundations have been instrumental in teaching those practices. But web developers, as a whole, haven’t got the memo. It can’t be explained away by a lack of tooling—there is plenty—or the highly modular nature of packages from npm and other repositories—which uniformly standardize metadata formats for license information. All the good JavaScript minifiers have command-line flags for preserving license header comments. Other tools will concatenate `LICENSE` files from package trees. There’s really no excuse.
|
||||
|
||||
##### Warranty Disclaimer
|
||||
|
||||
> The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement.
|
||||
|
||||
Nearly every state in the United States has enacted a version of the Uniform Commercial Code, a model statute of laws governing commercial transactions. Article 2 of the UCC—“Division 2” in California—governs contracts for sales of goods, from used automobiles bought off the lot to large shipments of industrial chemicals to manufacturing plants.
|
||||
|
||||
Some of the UCC’s rules about sales contracts are mandatory. These rules always apply, whether those buying and selling like them or not. Others are just “defaults”. Unless buyers and sellers opt out in writing, the UCC implies that they want the baseline rule found in the UCC’s text for their deal. Among the default rules are implied “warranties”, or promises by sellers to buyers about the quality and usability of the goods being sold.
|
||||
|
||||
There is a big theoretical debate about whether public licenses like The MIT License are contracts—enforceable agreements between licensors and licensees—or just licenses, which go one way, but may come with strings attached, their conditions. There is less debate about whether software counts as “goods”, triggering the UCC’s rules. There is no debate among licensors on liability: They don’t want to get sued for lots of money if the software they give away for free breaks, causes problems, doesn’t work, or otherwise causes trouble. That’s exactly the opposite of what three default rules for “implied warranties” do:
|
||||
|
||||
1. The implied warranty of “merchantability” under [UCC section 2-314][26] is a promise that “the goods”—the Software—are of at least average quality, properly packaged and labeled, and fit for the ordinary purposes they are intended to serve. This warranty applies only if the one giving the software is a “merchant” with respect to the software, meaning they deal in software and hold themselves out as skilled in software.
|
||||
|
||||
2. The implied warranty of “fitness for a particular purpose” under [UCC section 2-315][27] kicks in when the seller knows the buyer is relying on them to provide goods for a particular purpose. The goods need to actually be “fit” for that purpose.
|
||||
|
||||
3. The implied warranty of “noninfringement” is not part of the UCC, but is a common feature of general contract law. This implied promise protects the buyer if it turns out the goods they received infringe somebody else’s intellectual property rights. That would be the case if the software under The MIT License didn’t actually belong to the one trying to license it, or if it fell under a patent owned by someone else.
|
||||
|
||||
|
||||
|
||||
|
||||
[Section 2-316(3)][28] of the UCC requires language opting out of, or “excluding”, implied warranties of merchantability and fitness for a particular purpose to be conspicuous. “Conspicuous” in turn means written or formatted to call attention to itself, the opposite of microscopic fine print meant to slip past unwary consumers. State law may impose a similar attention-grabbing requirement for disclaimers of noninfringement.
|
||||
|
||||
Lawyers have long suffered under the delusion that writing anything in `ALL-CAPS` meets the conspicuous requirement. That isn’t true. Courts have criticized the Bar for pretending as much, and most everyone agrees all-caps does more to discourage reading than compel it. All the same, most open-source-license forms set their warranty disclaimers in all-caps, in part because that’s the only obvious way to make it stand out in plain-text `LICENSE` files. I’d prefer to use asterisks or other ASCII art, but that ship sailed long, long ago.
|
||||
|
||||
##### Limitation of Liability
|
||||
|
||||
> In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
|
||||
|
||||
The MIT License gives permission for software “free of charge”, but the law does not assume that folks receiving licenses free of charge give up their rights to sue when things go wrong and the licensor is to blame. “Limitations of liability”, often paired with “damages exclusions”, work a lot like licenses, as promises not to sue. But these are protections for the licensor against lawsuits by licensees.
|
||||
|
||||
In general, courts read limitations of liability and damages exclusions warily, since they can shift an incredible amount of risk from one side to another. To protect the community’s vital interest in giving folks a way to redress wrongs done in court, they “strictly construe” language limiting liability, reading it against the one protected by it where possible. Limitations of liability have to be specific to stand up. Especially in “consumer” contracts and other situations where those giving up the right to sue lack sophistication or bargaining power, courts have sometimes refused to honor language that seemed buried out of sight. Partly for that reason, partly by sheer force of habit, lawyers tend to give limits of liability the all-caps treatment, too.
|
||||
|
||||
Drilling down a bit, the “limitation of liability” part is a cap on the amount of money a licensee can sue for. In open-source licenses, that limit is always no money at all, $0, “not liable”. By contrast, in commercial licenses, it’s often a multiple of license fees paid in the last 12-month period, though it’s often negotiated.
|
||||
|
||||
The “exclusion” part lists, specifically, kinds of legal claims—reasons to sue for damages—the licensor cannot use. Like many, many legal forms, The MIT License mentions actions “of contract”—for breaching a contract—and “of tort”. Tort rules are general rules against carelessly or maliciously harming others. If you run someone down on the road while texting, you have committed a tort. If your company sells faulty headphones that burn peoples’ ears off, your company has committed a tort. If a contract doesn’t specifically exclude tort claims, courts sometimes read exclusion language in a contract to prevent only contract claims. For good measure, The MIT License throws in “or otherwise”, just to catch the odd admiralty law or other, exotic kind of legal claim.
|
||||
|
||||
The phrase “arising from, out of or in connection with” is a recurring tick symptomatic of the legal draftsman’s inherent, anxious insecurity. The point is that any lawsuit having anything to do with the software is covered by the limitation and exclusions. On the off chance something can “arise from”, but not “out of”, or “in connection with”, it feels better to have all three in the form, so pack ‘em in. Never mind that any court forced to split hairs in this part of the form will have to come up with different meanings for each, on the assumption that a professional drafter wouldn’t use different words in a row to mean the same thing. Never mind that in practice, where courts don’t feel good about a limitation that’s disfavored to begin with, they’ll be more than ready to read the scope trigger narrowly. But I digress. The same language appears in literally millions of contracts.
|
||||
|
||||
#### Overall
|
||||
|
||||
All these quibbles are a bit like spitting out gum on the way into church. The MIT License is a legal classic. The MIT License works. It is by no means a panacea for all software IP ills, in particular the software patent scourge, which it predates by decades. But MIT-style licenses have served admirably, fulfilling a narrow purpose—reversing troublesome default rules of copyright, sales, and contract law—with a minimal combination of discreet legal tools. In the greater context of computing, its longevity is astounding. The MIT License has outlasted and will outlast the vast majority of software licensed under it. We can only guess how many decades of faithful legal service it will have given when it finally loses favor. It’s been especially generous to those who couldn’t have afforded their own lawyer.
|
||||
|
||||
We’ve seen how the The MIT License we know today is a specific, standardized set of terms, bringing order at long last to a chaos of institution-specific, haphazard variations.
|
||||
|
||||
We’ve seen how its approach to attribution and copyright notice informed intellectual property management practices for academic, standards, commercial, and foundation institutions.
|
||||
|
||||
We’ve seen how The MIT Licenses grants permission for software to all, for free, subject to conditions that protect licensors from warranties and liability.
|
||||
|
||||
We’ve seen that despite some crusty verbiage and lawyerly affectation, one hundred and seventy one little words can get a hell of a lot of legal work done, clearing a path for open-source software through a dense underbrush of intellectual property and contract.
|
||||
|
||||
I’m so grateful for all who’ve taken the time to read this rather long post, to let me know they found it useful, and to help improve it. As always, I welcome your comments via [e-mail][29], [Twitter][30], and [GitHub][31].
|
||||
|
||||
A number of folks have asked where they can read more, or find run-downs of other licenses, like the GNU General Public License or the Apache 2.0 license. No matter what your particular continuing interest may be, I heartily recommend the following books:
|
||||
|
||||
* Andrew M. St. Laurent’s [Understanding Open Source & Free Software Licensing][32], from O’Reilly.
|
||||
|
||||
I start with this one because, while it’s somewhat dated, its approach is also closest to the line-by-line approach used above. O’Reilly has made it [available online][33].
|
||||
|
||||
* Heather Meeker’s [Open (Source) for Business][34]
|
||||
|
||||
In my opinion, by far the best writing on the GNU General Public License and copyleft more generally. This book covers the history, the licenses, their development, as well as compatibility and compliance. It’s the book I lend to clients considering or dealing with the GPL.
|
||||
|
||||
* Larry Rosen’s [Open Source Licensing][35], from Prentice Hall.
|
||||
|
||||
A great first book, also available for free [online][36]. This is the best introduction to open-source licensing and related law for programmers starting from scratch. This one is also a bit dated in some specific details, but Larry’s taxonomy of licenses and succinct summary of open-source business models stand the test of time.
|
||||
|
||||
|
||||
|
||||
|
||||
All of these were crucial to my own education as an open-source licensing lawyer. Their authors are professional heroes of mine. Have a read! — K.E.M
|
||||
|
||||
I license this article under a [Creative Commons Attribution-ShareAlike 4.0 license][37].
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://writing.kemitchell.com/2016/09/21/MIT-License-Line-by-Line.html
|
||||
|
||||
作者:[Kyle E. Mitchell][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[bestony](https://github.com/bestony)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://kemitchell.com/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://spdx.org/licenses/MIT
|
||||
[2]: https://fedoraproject.org/wiki/Licensing:MIT?rd=Licensing/MIT
|
||||
[3]: https://opensource.org
|
||||
[4]: https://spdx.org
|
||||
[5]: http://spdx.org/licenses/
|
||||
[6]: https://spdx.org/licenses/JSON
|
||||
[7]: https://www.npmjs.com/package/licensor
|
||||
[8]: https://www.apache.org/licenses/LICENSE-2.0
|
||||
[9]: https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
[10]: http://spdx.org/licenses/BSD-4-Clause
|
||||
[11]: https://spdx.org/licenses/BSD-3-Clause
|
||||
[12]: https://spdx.org/licenses/BSD-2-Clause
|
||||
[13]: http://www.isc.org/downloads/software-support-policy/isc-license/
|
||||
[14]: http://worksmadeforhire.com/
|
||||
[15]: https://www.eclipse.org/legal/epl-v10.html
|
||||
[16]: https://www.apache.org/licenses/#clas
|
||||
[17]: https://wiki.eclipse.org/ECA
|
||||
[18]: https://en.wikipedia.org/wiki/Feist_Publications,_Inc.,_v._Rural_Telephone_Service_Co.
|
||||
[19]: https://writing.kemitchell.com/2017/02/16/Against-Legislating-the-Nonobvious.html
|
||||
[20]: http://developercertificate.org/
|
||||
[21]: https://github.com/berneout/berneout-pledge
|
||||
[22]: https://github.com/berneout/authors-certificate
|
||||
[23]: https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
|
||||
[24]: https://www.govinfo.gov/app/details/USCODE-2017-title35/USCODE-2017-title35-partIII-chap28-sec271
|
||||
[25]: https://www.govinfo.gov/app/details/USCODE-2017-title17/USCODE-2017-title17-chap1-sec106
|
||||
[26]: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=2314.&lawCode=COM
|
||||
[27]: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=2315.&lawCode=COM
|
||||
[28]: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=2316.&lawCode=COM
|
||||
[29]: mailto:kyle@kemitchell.com
|
||||
[30]: https://twitter.com/kemitchell
|
||||
[31]: https://github.com/kemitchell/writing/tree/master/_posts/2016-09-21-MIT-License-Line-by-Line.md
|
||||
[32]: https://lccn.loc.gov/2006281092
|
||||
[33]: http://www.oreilly.com/openbook/osfreesoft/book/
|
||||
[34]: https://www.amazon.com/dp/1511617772
|
||||
[35]: https://lccn.loc.gov/2004050558
|
||||
[36]: http://www.rosenlaw.com/oslbook.htm
|
||||
[37]: https://creativecommons.org/licenses/by-sa/4.0/legalcode
|
@ -92,7 +92,7 @@ via: https://twobithistory.org/2017/09/28/the-lineage-of-man.html
|
||||
|
||||
作者:[Two-Bit History][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[bestony](https://github.com/bestony)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,65 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (XYenChi )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (When the web grew up: A browser story)
|
||||
[#]: via: (https://opensource.com/article/19/3/when-web-grew)
|
||||
[#]: author: (Mike Bursell https://opensource.com/users/mikecamel)
|
||||
|
||||
web 的诞生:浏览器的故事grew up: A browser story
|
||||
======
|
||||
互联网诞生之处的个人故事。A personal story of when the internet came of age.
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_Internet_Sign.png?itok=5MFGKs14)
|
||||
|
||||
最近,我Recently, I [分享了shared how][1] 获得英文文学和神学学位离开大学,在一个大家都还不知道 web 服务器是什么的地方,设法找到一份运行 web 服务器的工作。upon leaving university in 1994 with a degree in English literature and theology, I somehow managed to land a job running a web server in a world where people didn't really know what a web server was yet. 那“地方”,我不仅仅指的是我工作的组织,而是泛指所有地方。And by "in a world," I don't just mean within the organisation in which I worked, but the world in general. Web 那时当真是全新的——人们还正尝试理出头绪。The web was new—really new—and people were still trying to get their heads around it.
|
||||
|
||||
That's not to suggest that the place where I was working—an academic publisher—particularly "got it" either. This was a world in which a large percentage of the people visiting their website were still running 28k8 modems. I remember my excitement in getting a 33k6 modem. At least we were past the days of asymmetric upload/download speeds,1 where 1200/300 seemed like an eminently sensible bandwidth description. This meant that the high-design, high-colour, high-resolution documents created by the print people (with whom I shared a floor) were completely impossible on the web. I wouldn't allow anything bigger than a 40k GIF on the front page of the website, and that was pushing it for many of our visitors. Anything larger than 60k or so would be explicitly linked as a standalone image from a thumbnail on the referring page.
|
||||
|
||||
To say that the marketing department didn't like this was an understatement. Even worse was the question of layout. "Browsers decide how to lay out documents," I explained, time after time, "you can use headers or paragraphs, but how documents appear on the page isn't defined by the document, but by the renderer!" They wanted control. They wanted different coloured backgrounds. After a while, they got that. I went to what I believe was the first W3C meeting at which the idea of Cascading Style Sheets (CSS) was discussed. And argued vehemently against them. The suggestion that document writers should control layout was anathema.2 It took some while for CSS to be adopted, and in the meantime, those who cared about such issues adopted the security trainwreck that was Portable Document Format (PDF).
|
||||
|
||||
How documents were rendered wasn't the only issue. Being a publisher of actual physical books, the whole point of having a web presence, as far as the marketing department was concerned, was to allow customers—or potential customers—to know not only what a book was about, but also how much it was going to cost them to buy. This, however, presented a problem. You see, the internet—in which I include the rapidly growing World Wide Web—was an open, free-for-all libertarian sort of place where nobody was interested in money; in fact, where talk of money was to be shunned and avoided.
|
||||
|
||||
I took the mainstream "Netizen" view that there was no place for pricing information online. My boss—and, indeed, pretty much everybody else in the organisation—took a contrary view. They felt that customers should be able to see how much books would cost them. They also felt that my bank manager would like to see how much money was coming into my bank account on a monthly basis, which might be significantly reduced if I didn't come round to their view.
|
||||
|
||||
Luckily, by the time I'd climbed down from my high horse and got over myself a bit—probably only a few weeks after I'd started digging my heels in—the web had changed, and there were other people putting pricing information up about their products. These newcomers were generally looked down upon by the old schoolers who'd been running web servers since the early days,3 but it was clear which way the wind was blowing. This didn't mean that the battle was won for our website, however. As an academic publisher, we shared an academic IP name ("ac.uk") with the University. The University was less than convinced that publishing pricing information was appropriate until some senior folks at the publisher pointed out that Princeton University Press was doing it, and wouldn't we look a bit silly if…?
|
||||
|
||||
The fun didn't stop there, either. A few months into my tenure as webmaster ("webmaster@…"), we started to see a worrying trend, as did lots of other websites. Certain visitors were single-handedly bringing our webserver to its knees. These visitors were running a new web browser: Netscape. Netscape was badly behaved. Netscape was multi-threaded.
|
||||
|
||||
Why was this an issue? Well, before Netscape, all web browsers had been single-threaded. They would open one connection at a time, so even if you had, say five GIFs on a page,4 they would request the HTML base file, parse that, then download the first GIF, complete that, then the second, complete that, and so on. In fact, they often did the GIFs in the wrong order, which made for very odd page loading, but still, that was the general idea. The rude people at Netscape decided that they could open multiple connections to the webserver at a time to request all the GIFs at the same time, for example! And why was this a problem? Well, the problem was that most webservers were single-threaded. They weren't designed to have multiple connections open at any one time. Certainly, the HTTP server that we ran (MacHTTP) was single-threaded. Even though we had paid for it (it was originally shareware), the version we had couldn't cope with multiple requests at a time.
|
||||
|
||||
The debate raged across the internet. Who did these Netscape people think they were, changing how the world worked? How it was supposed to work? The world settled into different camps, and as with all technical arguments, heated words were exchanged on both sides. The problem was that not only was Netscape multi-threaded, it was also just better than the alternatives. Lots of web server code maintainers, MacHTTP author Chuck Shotton among them, sat down and did some serious coding to produce multi-threaded beta versions of their existing code. Everyone moved almost immediately to the beta versions, they got stable, and in the end, single-threaded browsers either adapted and became multi-threaded themselves, or just went the way of all outmoded products and died a quiet death.6
|
||||
|
||||
This, for me, is when the web really grew up. It wasn't prices on webpages nor designers being able to define what you'd see on a page,8 but rather when browsers became easier to use and when the network effect of thousands of viewers moving to many millions tipped the balance in favour of the consumer, not the producer. There were more steps in my journey—which I'll save for another time—but from around this point, my employers started looking at our monthly, then weekly, then daily logs, and realising that this was actually going to be something big and that they'd better start paying some real attention.
|
||||
|
||||
1\. How did they come back, again?
|
||||
|
||||
2\. It may not surprise you to discover that I'm still happiest at the command line.
|
||||
|
||||
3\. About six months before.
|
||||
|
||||
4\. Reckless, true, but it was beginning to happen.5
|
||||
|
||||
5\. Oh, and no—it was GIFs or BMP. JPEG was still a bright idea that hadn't yet taken off.
|
||||
|
||||
6\. It's never actually quiet: there are always a few diehard enthusiasts who insist that their preferred solution is technically superior and bemoan the fact that the rest of the internet has gone to the devil.7
|
||||
|
||||
7\. I'm not one to talk: I still use Lynx from time to time.
|
||||
|
||||
8\. Creating major and ongoing problems for those with different accessibility needs, I would point out.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/when-web-grew
|
||||
|
||||
作者:[Mike Bursell][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/mikecamel
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/article/18/11/how-web-was-won
|
@ -1,78 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Where are all the IoT experts going to come from?)
|
||||
[#]: via: (https://www.networkworld.com/article/3404489/where-are-all-the-iot-experts-going-to-come-from.html)
|
||||
[#]: author: (Fredric Paul https://www.networkworld.com/author/Fredric-Paul/)
|
||||
|
||||
Where are all the IoT experts going to come from?
|
||||
======
|
||||
The fast growth of the internet of things (IoT) is creating a need to train cross-functional experts who can combine traditional networking and infrastructure expertise with database and reporting skills.
|
||||
![Kevin \(CC0\)][1]
|
||||
|
||||
If the internet of things (IoT) is going to fulfill its enormous promise, it’s going to need legions of smart, skilled, _trained_ workers to make everything happen. And right now, it’s not entirely clear where those people are going to come from.
|
||||
|
||||
That’s why I was interested in trading emails with Keith Flynn, senior director of product management, R&D at asset-optimization software company [AspenTech][2], who says that when dealing with the slew of new technologies that fall under the IoT umbrella, you need people who can understand how to configure the technology and interpret the data. Flynn sees a growing need for existing educational institutions to house IoT-specific programs, as well as an opportunity for new IoT-focused private colleges, offering a well -ounded curriculum
|
||||
|
||||
“In the future,” Flynn told me, “IoT projects will differ tremendously from the general data management and automation projects of today. … The future requires a more holistic set of skills and cross-trading capabilities so that we’re all speaking the same language.”
|
||||
|
||||
**[ Also read: [20 hot jobs ambitious IT pros should shoot for][3] ]**
|
||||
|
||||
With the IoT growing 30% a year, Flynn added, rather than a few specific skills, “everything from traditional deployment skills, like networking and infrastructure, to database and reporting skills and, frankly, even basic data science, need to be understood together and used together.”
|
||||
|
||||
### Calling all IoT consultants
|
||||
|
||||
“The first big opportunity for IoT-educated people is in the consulting field,” Flynn predicted. “As consulting companies adapt or die to the industry trends … having IoT-trained people on staff will help position them for IoT projects and make a claim in the new line of business: IoT consulting.”
|
||||
|
||||
The problem is especially acute for startups and smaller companies. “The bigger the organization, the more likely they have a means to hire different people across different lines of skillsets,” Flynn said. “But for smaller organizations and smaller IoT projects, you need someone who can do both.”
|
||||
|
||||
Both? Or _everything?_ The IoT “requires a combination of all knowledge and skillsets,” Flynn said, noting that “many of the skills aren’t new, they’ve just never been grouped together or taught together before.”
|
||||
|
||||
**[ [Looking to upgrade your career in tech? This comprehensive online course teaches you how.][4] ]**
|
||||
|
||||
### The IoT expert of the future
|
||||
|
||||
True IoT expertise starts with foundational instrumentation and electrical skills, Flynn said, which can help workers implement new wireless transmitters and boost technology for better battery life and power consumption.
|
||||
|
||||
“IT skills, like networking, IP addressing, subnet masks, cellular and satellite are also pivotal IoT needs,” Flynn said. He also sees a need for database management skills and cloud management and security expertise, “especially as things like [advanced process control] APC and sending sensor data directly to databases and data lakes become the norm.”
|
||||
|
||||
### Where will IoT experts come from?
|
||||
|
||||
Flynn said standardized formal education courses would be the best way to make sure that graduates or certificate holders have the right set of skills. He even laid out a sample curriculum: “Start in chronological order with the basics like [Electrical & Instrumentation] E&I and measurement. Then teach networking, and then database administration and cloud courses should follow that. This degree could even be looped into an existing engineering course, and it would probably take two years … to complete the IoT component.”
|
||||
|
||||
While corporate training could also play role, “that’s easier said than done,” Flynn warned. “Those trainings will need to be organization-specific efforts and pushes.”
|
||||
|
||||
Of course, there are already [plenty of online IoT training courses and certificate programs][5]. But, ultimately, the responsibility lies with the workers themselves.
|
||||
|
||||
“Upskilling is incredibly important in this world as tech continues to transform industries,” Flynn said. “If that upskilling push doesn’t come from your employer, then online courses and certifications would be an excellent way to do that for yourself. We just need those courses to be created. ... I could even see organizations partnering with higher-education institutions that offer these courses to give their employees better access to it. Of course, the challenge with an IoT program is that it will need to constantly evolve to keep up with new advancements in tech.”
|
||||
|
||||
**[ For more on IoT, see [tips for securing IoT on your network][6], our list of [the most powerful internet of things companies][7] and learn about the [industrial internet of things][8]. | Get regularly scheduled insights by [signing up for Network World newsletters][9]. ]**
|
||||
|
||||
Join the Network World communities on [Facebook][10] and [LinkedIn][11] to comment on topics that are top of mind.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3404489/where-are-all-the-iot-experts-going-to-come-from.html
|
||||
|
||||
作者:[Fredric Paul][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://www.networkworld.com/author/Fredric-Paul/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://images.idgesg.net/images/article/2018/07/programmer_certification-skills_code_devops_glasses_student_by-kevin-unsplash-100764315-large.jpg
|
||||
[2]: https://www.aspentech.com/
|
||||
[3]: https://www.networkworld.com/article/3276025/careers/20-hot-jobs-ambitious-it-pros-should-shoot-for.html
|
||||
[4]: https://pluralsight.pxf.io/c/321564/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fpaths%2Fupgrading-your-technology-career
|
||||
[5]: https://www.google.com/search?client=firefox-b-1-d&q=iot+training
|
||||
[6]: https://www.networkworld.com/article/3254185/internet-of-things/tips-for-securing-iot-on-your-network.html#nww-fsb
|
||||
[7]: https://www.networkworld.com/article/2287045/internet-of-things/wireless-153629-10-most-powerful-internet-of-things-companies.html#nww-fsb
|
||||
[8]: https://www.networkworld.com/article/3243928/internet-of-things/what-is-the-industrial-iot-and-why-the-stakes-are-so-high.html#nww-fsb
|
||||
[9]: https://www.networkworld.com/newsletters/signup.html#nww-fsb
|
||||
[10]: https://www.facebook.com/NetworkWorld/
|
||||
[11]: https://www.linkedin.com/company/network-world
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user