mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-03 23:40:14 +08:00
commit
ec3196ec16
220
published/20170918 Fun and Games in Emacs.md
Normal file
220
published/20170918 Fun and Games in Emacs.md
Normal file
@ -0,0 +1,220 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lujun9972)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11949-1.html)
|
||||
[#]: subject: (Fun and Games in Emacs)
|
||||
[#]: via: (https://www.masteringemacs.org/article/fun-games-in-emacs)
|
||||
[#]: author: (Mickey Petersen https://www.masteringemacs.org/about)
|
||||
|
||||
“Emacs 游戏机”完全指南
|
||||
======
|
||||
|
||||
又是周一,你正在为你的老板 Lumbergh (LCTT 译注:《上班一条虫》中的副总裁)努力倒腾那些 [无聊之极的文档][1]。为什么不玩玩 Emacs 中类似 zork 的文字冒险游戏来让你的大脑从单调的工作中解脱出来呢?
|
||||
|
||||
但说真的,Emacs 中既有游戏,也有古怪的玩物。有些你可能有所耳闻。这些玩意唯一的共同点就是,它们大多是很久以前就添加到 Emacs 中的:有些东西真的是相当古怪(如你将在下面看到的),而另一些则显然是由无聊的员工或学生们编写的。它们全有一个共同点,都带着一种奇思妙想和随意性,这在今天的 Emacs 中很少见。Emacs 现在变得十分严肃,在某种程度上,它已经与 20 世纪 80 年代那些游戏被编写出来的时候大不一样。
|
||||
|
||||
### 汉诺塔
|
||||
|
||||
[汉诺塔][2] 是一款古老的数学解密游戏,有些人可能对它很熟悉,因为它的递归和迭代解决方案经常被用于计算机科学教学辅助。
|
||||
|
||||
![Tower of Hanoi Screenshot](https://www.masteringemacs.org/static/uploads/hanoi.png)
|
||||
|
||||
Emacs 中有三个命令可以运行汉诺塔:`M-x hanoi` 默认为 3 个碟子; `M-x hanoi-unix` 和 `M-x hanoi-unix-64` 使用 unix 时间戳的位数(32 位或 64 位)作为默认盘子的个数,并且每秒钟自动移动一次,两者不同之处在于后者假装使用 64 位时钟(因此有 64 个碟子)。
|
||||
|
||||
Emacs 中汉诺塔的实现可以追溯到 20 世纪 80 年代中期——确实是久得可怕。它有一些自定义选项(`M-x customize-group RET hanoi RET`),如启用彩色碟子等。当你离开汉诺塔缓冲区或输入一个字符,你会收到一个讽刺的告别信息(见上图)。
|
||||
|
||||
### 5x5
|
||||
|
||||
![5x5 game grid](https://www.masteringemacs.org/static/uploads/5x5.png)
|
||||
|
||||
5x5 的游戏是一个逻辑解密游戏:你有一个 5x5 的网格,中间的十字被填满;你的目标是通过按正确的顺序切换它们的空满状态来填充所有的单元格,从而获得胜利。这并不像听起来那么容易!
|
||||
|
||||
输入 `M-x 5x5` 就可以开始玩了,使用可选的数字参数可以改变网格的大小。这款游戏的有趣之处在于它能向你建议下一步行动并尝试找到该游戏网格的解法。它用到了 Emacs 自己的一款非常酷的符号 RPN 计算器 `M-x calc`(在《[Emacs 快乐计算][3]》这篇文章中,我使用它来解决了一个简单的问题)。
|
||||
|
||||
所以我喜欢这个游戏的原因是它提供了一个非常复杂的解题器——真的,你应该通过 `M-x find-library RET 5x5` 来阅读其源代码——这是一个试图通过暴力破解游戏解法的“破解器”。
|
||||
|
||||
创建一个更大的游戏网格,例如输入 `M-10 M-x 5x5`,然后运行下面某个 `crack` 命令。破解器将尝试通过迭代获得最佳解决方案。它会实时运行该游戏,观看起来非常有趣:
|
||||
|
||||
- `M-x 5x5-crack-mutating-best`: 试图通过变异最佳解决方案来破解 5x5。
|
||||
- `M-x 5x5-crack-mutating-current`: 试图通过变异当前解决方案来破解 5x5。
|
||||
- `M-x 5x5-crack-random`: 尝试使用随机方案解破解 5x5。
|
||||
- `M-x 5x5-crack-xor-mutate`: 尝试通过将当前方案和最佳方案进行异或运算来破解 5x5。
|
||||
|
||||
### 文本动画
|
||||
|
||||
你可以通过运行 `M-x animation-birthday-present` 并给出你的名字来显示一个奇特的生日礼物动画。它看起来很酷!
|
||||
|
||||
![xkcd](https://imgs.xkcd.com/comics/real_programmers.png)
|
||||
|
||||
这里用的 `animate` 包也用在了 `M-x butterfly` 命令中,这是一个向上面的 [XKCD][4] 漫画致敬而添加到 Emacs 中的命令。当然,漫画中的 Emacs 命令在技术上是无效的,但它的幽默足以弥补这一点。
|
||||
|
||||
### 黑箱
|
||||
|
||||
我将逐字引用这款游戏的目标:
|
||||
|
||||
> 游戏的目标是通过向黑盒子发射光线来找到四个隐藏的球。有四种可能:
|
||||
> 1) 射线将通过盒子不受干扰;
|
||||
> 2) 它将击中一个球并被吸收;
|
||||
> 3) 它将偏转并退出盒子,或
|
||||
> 4) 立即偏转,甚至不能进入盒子。
|
||||
|
||||
所以,这有点像我们小时候玩的[战舰游戏][5],但是……是专为物理专业高学历的人准备的吧?
|
||||
|
||||
这是另一款添加于 20 世纪 80 年代的游戏。我建议你输入 `C-h f blackbox` 来阅读玩法说明(文档巨大)。
|
||||
|
||||
|
||||
### 泡泡
|
||||
|
||||
![Bubbles game](https://www.masteringemacs.org/static/uploads/bubbles.png)
|
||||
|
||||
`M-x bubble` 游戏相当简单:你必须用尽可能少移动清除尽可能多的“泡泡”。当你移除气泡时,其他气泡会掉落并粘在一起。这是一款有趣的游戏,此外如果你使用 Emacs 的图形用户界面,它还支持图像显示。而且它还支持鼠标。
|
||||
|
||||
你可以通过调用 `M-x bubbles-set-game-<difficulty>` 来设置难度,其中 `<difficulty>` 可以是这些之一:`easy`、`medium`、`difficult`、`hard` 或 `userdefined`。此外,你可以使用:`M-x custom-group bubbles` 来更改图形、网格大小和颜色。
|
||||
|
||||
由于它即简单又有趣,这是 Emacs 中我最喜欢的游戏之一。
|
||||
|
||||
### 幸运饼干
|
||||
|
||||
我喜欢 `fortune` 命令。每当我启动一个新 shell 时,这些与文学片段、谜语相结合的刻薄、无益、常常带有讽刺意味的“建议”就会点亮我的一天。
|
||||
|
||||
令人困惑的是,Emacs 中有两个包或多或少地做着类似的事情:`fortune` 和 `cookie`。前者主要用于在电子邮件签名中添加幸运饼干消息,而后者只是一个简单的 fortune 格式阅读器。
|
||||
|
||||
不管怎样,使用 Emacs 的 `cookie` 包前,你首先需要通过 `customize-option RET cookie RET` 来自定义变量 `cookie-file` 告诉它从哪找到 fortune 文件。
|
||||
|
||||
如果你的操作系统是 Ubuntu,那么你先安装 `fortune` 软件包,然后就能在 `/usr/share/games/fortune/` 目录中找到这些文件了。
|
||||
|
||||
之后你就可以调用 `M-x cookie` 随机显示 fortune 内容,或者,如果你想的话,也可以调用 `M-x cookie-apropos` 查找所有匹配的饼干。
|
||||
|
||||
### 破译器
|
||||
|
||||
这个包完美地抓住了 Emacs 的功利本质:这个包为你破解简单的替换密码(如“密码谜题”)提供了一个很有用的界面。你知道,二十多年前,有些人确实迫切需要破解很多基本的密码。正是像这个模块这样的小玩意让我非常高兴地用起 Emacs 来:一个只对少数人有用的模块,但是,如果你突然需要它了,那么它就在那里等着你。
|
||||
|
||||
那么如何使用它呢?让我们假设使用 “rot13” 密码:在 26 个字符的字母表中,将字符旋转 13 个位置。
|
||||
通过 `M-x ielm` (Emacs 用于 [运行 Elisp][6] 的 REPL 环境)可以很容易在 Emacs 中进行尝试:
|
||||
|
||||
```
|
||||
*** Welcome to IELM *** Type (describe-mode) for help.
|
||||
ELISP> (rot13 "Hello, World")
|
||||
"Uryyb, Jbeyq"
|
||||
ELISP> (rot13 "Uryyb, Jbeyq")
|
||||
"Hello, World"
|
||||
ELISP>
|
||||
```
|
||||
|
||||
简而言之,你将明文旋转了 13 个位置,就得到了密文。你又旋转了一次 13 个位置,就返回了最初的明文。 这就是这个包可以帮助你解决的问题。
|
||||
|
||||
那么,decipher 模块又是如何帮助我们的呢?让我们创建一个新的缓冲区 `test-cipher` 并输入你的密文(在我的例子中是 `Uryyb,Jbeyq`)。
|
||||
|
||||
![cipher](https://www.masteringemacs.org/static/uploads/cipher.png)
|
||||
|
||||
你现在面对的是一个相当复杂的界面。现在把光标放在紫色行的密文的任意字符上,并猜测这个字符可能是什么:Emacs 将根据你的选择更新其他明文的猜测结果,并告诉你目前为止字母表中的字符是如何分配的。
|
||||
|
||||
你现在可以用下面各种助手命令来关闭选项,以帮助推断密码字符可能对应的明文字符:
|
||||
|
||||
- `D`: 列出示意图(该加密算法中双字符对)及其频率
|
||||
- `F`: 表示每个密文字母的频率
|
||||
- `N`: 显示字符的邻近信息。我不确定这是干啥的。
|
||||
- `M` 和 `R`: 保存和恢复一个检查点,允许你对工作进行分支以探索破解密码的不同方法。
|
||||
|
||||
总而言之,对于这样一个深奥的任务,这个包是相当令人印象深刻的!如果你经常破解密码,也许这个程序包能帮上忙?
|
||||
|
||||
### 医生
|
||||
|
||||
![doctor](https://www.masteringemacs.org/static/uploads/doctor.png)
|
||||
|
||||
啊,Emacs 医生。其基于最初的 [ELIZA][7],“医生”试图对你说的话进行心理分析,并试图把问题复述给你。体验几分钟,相当有趣,它也是 Emacs 中最著名的古怪玩意之一。你可以使用 `M-x doctor` 来运行它。
|
||||
|
||||
### Dunnet
|
||||
|
||||
Emacs 自己特有的类 Zork 文字冒险游戏。输入 `M-x dunnet` 就能玩了。这是一款相当不错的游戏,简单的说,它是另一款非常著名的 Emacs 游戏,很少有人真正玩到通关。
|
||||
|
||||
如果你发现自己能在无聊的文档工作之间空出时间来,那么这是一个超级棒的游戏,内置“老板屏幕”,因为它是纯文本的。
|
||||
|
||||
哦,还有,不要想着吃掉那块 CPU 卡 :)
|
||||
|
||||
### 五子棋
|
||||
|
||||
![gomoku](https://www.masteringemacs.org/static/uploads/gomoku.png)
|
||||
|
||||
另一款写于 20 世纪 80 年代的游戏。你必须将 5 个方块连成一条线,井字棋风格。你可以运行 `M-x gomoku` 来与 Emacs 对抗。游戏还支持鼠标,非常方便。你也可以自定义 `gomoku` 组来调整网格的大小。
|
||||
|
||||
### 生命游戏
|
||||
|
||||
[康威的生命游戏][8] 是细胞自动机的一个著名例子。Emacs 版本提供了一些启动模式,你可以(通过 elisp 编程)调整 `life-patterns` 变量来更改这些模式。
|
||||
|
||||
你可以用 `M-x life` 触发生命游戏。事实上,所有的东西,包括显示代码、注释等等一切,总共不到 300 行,这也让人印象深刻。
|
||||
|
||||
### 乒乓,贪吃蛇和俄罗斯方块
|
||||
|
||||
![tetris](https://www.masteringemacs.org/static/uploads/tetris.png)
|
||||
|
||||
这些经典游戏都是使用 Emacs 包 `gamegrid` 实现的,这是一个用于构建网格游戏(如俄罗斯方块和贪吃蛇)的通用框架。gamegrid 包的伟大之处在于它同时兼容图形化和终端 Emacs:如果你在 GUI 中运行 Emacs,你会得到精美的图形;如果你没有,你看到简单的 ASCII 艺术。
|
||||
|
||||
你可以通过输入 `M-x pong`、`M-x snake`、`M-x tetris` 来运行这些游戏。
|
||||
|
||||
特别是俄罗斯方块游戏实现的非常到位,会逐渐增加速度并且能够滑块。而且既然你已经有了源代码,你完全可以移除那个讨厌的 Z 形块,没人喜欢它!
|
||||
|
||||
### Solitaire
|
||||
|
||||
![solitaire image](https://www.masteringemacs.org/static/uploads/solitaire.png)
|
||||
|
||||
可惜,这不是纸牌游戏,而是一个基于“钉子”的游戏,你可以选择一块石头(`o`)并“跳过”相邻的石头进入洞中(`.`),并在这个过程中去掉你跳过的石头,最终只能在棋盘上留下一块石头,重复该过程直到棋盘被请空(只保留一个石头)。
|
||||
|
||||
如果你卡住了,有一个内置的解题器名为 `M-x solitire-solve`。
|
||||
|
||||
### Zone
|
||||
|
||||
我的另一个最爱。这是一个屏幕保护程序——或者更确切地说,是一系列的屏幕保护程序。
|
||||
|
||||
输入 `M-x zone`,然后看看屏幕上发生了什么!
|
||||
|
||||
你可以通过运行 `M-x zone-when-idle`(或从 elisp 调用它)来配置屏幕保护程序的空闲时间,时间以秒为单位。你也可以通过 `M-x zone-leave-me-alone` 来关闭它。
|
||||
|
||||
如果在你的同事看着的时候启动它,你的同事肯定会抓狂的。
|
||||
|
||||
### 乘法解谜
|
||||
|
||||
![mpuz](https://www.masteringemacs.org/static/uploads/mpuz.png)
|
||||
|
||||
这是另一个脑筋急转弯的益智游戏。当你运行 `M-x mpuz` 时,将看到一个乘法解谜题,你必须将字母替换为对应的数字,并确保数字相加(相乘?)符合结果。
|
||||
|
||||
如果遇到难题,可以运行 `M-x mpuz-show-solution` 来解决。
|
||||
|
||||
### 杂项
|
||||
|
||||
还有更多好玩的东西,但它们就不如刚才那些那么好玩好用了:
|
||||
|
||||
- 你可以通过 `M-x morse-region` 和 `M-x unmorse-region` 将一个区域翻译成莫尔斯电码。
|
||||
- Dissociated Press 是一个非常简单的命令,它将一个类似随机穿行的马尔可夫链生成器应用到缓冲区中的文本中,并以此生成无意义的文本。试一下 `M-x dissociated-press`。
|
||||
- `gametree` 软件包是一个通过电子邮件记录和跟踪国际象棋游戏的复杂方法。
|
||||
- `M-x spook` 命令插入随机单词(通常是到电子邮件中),目的是混淆/超载 “NSA 拖网渔船” —— 记住,这个模块可以追溯到 20 世纪 80 年代和 90 年代,那时应该有间谍们在监听各种单词。当然,即使是在十年前,这样做也会显得非常偏执和古怪,不过现在看来已经不那么奇怪了……
|
||||
|
||||
### 总结
|
||||
|
||||
我喜欢 Emacs 附带的游戏和玩具。它们大多来自于,嗯,我们姑且称之为一个不同的时代:一个允许或甚至鼓励奇思妙想的时代。有些玩意非常经典(如俄罗斯方块和汉诺塔),有些对经典游戏进行了有趣的变种(如黑盒)——但我很高兴这么多年后它们依然存在于 Emacs 中。我想知道时至今日,类似这些的玩意是否还会再纳入 Emacs 的代码库中;嗯,它们很可能不会——它们将被归入包管理仓库中,而在这个干净而无菌的世界中,它们无疑属于包管理仓库。
|
||||
|
||||
Emacs 要求将对 Emacs 体验不重要的内容转移到包管理仓库 ELPA 中。我的意思是,作为一个开发者,这是有道理的,但是……对于每一个被移出并流放到 ELPA 的包,我们是不是在蚕食 Emacs 的精髓?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
via: https://www.masteringemacs.org/article/fun-games-in-emacs
|
||||
|
||||
作者:[Mickey Petersen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lujun9972](https://github.com/lujun9972)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.masteringemacs.org/about
|
||||
[b]:https://github.com/lujun9972
|
||||
[1]:https://en.wikipedia.org/wiki/Office_Space
|
||||
[2]:https://en.wikipedia.org/wiki/Tower_of_Hanoi
|
||||
[3]:https://www.masteringemacs.org/article/fun-emacs-calc
|
||||
[4]:http://www.xkcd.com
|
||||
[5]:https://en.wikipedia.org/wiki/Battleship_(game)
|
||||
[6]:https://www.masteringemacs.org/article/evaluating-elisp-emacs
|
||||
[7]:https://en.wikipedia.org/wiki/ELIZA
|
||||
[8]:https://en.wikipedia.org/wiki/Conway's_Game_of_Life
|
@ -1,26 +1,28 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11953-1.html)
|
||||
[#]: subject: (Troubleshooting hardware problems in Linux)
|
||||
[#]: via: (https://opensource.com/article/18/12/troubleshooting-hardware-problems-linux)
|
||||
[#]: author: (Daniel Oh https://opensource.com/users/daniel-oh)
|
||||
|
||||
Troubleshooting hardware problems in Linux
|
||||
Linux 硬件故障排除指南
|
||||
======
|
||||
Learn what's causing your Linux hardware to malfunction so you can get it back up and running quickly.
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_other11x_cc.png?itok=I_kCDYj0)
|
||||
|
||||
[Linux servers][1] run mission-critical business applications in many different types of infrastructures including physical machines, virtualization, private cloud, public cloud, and hybrid cloud. It's important for Linux sysadmins to understand how to manage Linux hardware infrastructure—including software-defined functionalities related to [networking][2], storage, Linux containers, and multiple tools on Linux servers.
|
||||
> 了解是什么原因导致你的 Linux 硬件发生故障,以便你可以将其恢复并快速运行。
|
||||
|
||||
It can take some time to troubleshoot and solve hardware-related issues on Linux. Even highly experienced sysadmins sometimes spend hours working to solve mysterious hardware and software discrepancies.
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/03/101312zcazy02wl2g8uhy1.jpg)
|
||||
|
||||
The following tips should make it quicker and easier to troubleshoot hardware in Linux. Many different things can cause problems with Linux hardware; before you start trying to diagnose them, it's smart to learn about the most common issues and where you're most likely to find them.
|
||||
[Linux 服务器][1]在物理机、虚拟化、私有云、公共云和混合云等许多不同种类的基础设施中运行着关键的业务应用程序。对于 Linux 系统管理员来说,了解如何管理 Linux 硬件基础设施(包括与 [网络][2]、存储、Linux 容器相关的软件定义功能)和 Linux 服务器上的多种工具非常重要。
|
||||
|
||||
### Quick-diagnosing devices, modules, and drivers
|
||||
在 Linux 上进行排除和解决与硬件相关的问题可能需要一些时间。即使是经验丰富的系统管理员,有时也会花费数小时来解决神秘的硬件和软件差异。
|
||||
|
||||
The first step in troubleshooting usually is to display a list of the hardware installed on your Linux server. You can obtain detailed information on the hardware using **ls** commands such as **[lspci][3]** , **[lsblk][4]** , **[lscpu][5]** , and **[lsscsi][6]**. For example, here is output of the **lsblk** command:
|
||||
以下提示可以使你更快、更轻松地对 Linux 中的硬件进行故障排除。许多不同的事情都可能导致 Linux 硬件出现问题。在开始诊断它们之前,明智的做法是了解最常见的问题以及最有可能找到问题的地方。
|
||||
|
||||
### 快速诊断设备、模块和驱动程序
|
||||
|
||||
故障排除的第一步通常是显示 Linux 服务器上安装的硬件的列表。你可以使用诸如 [lspci][3]、[lsblk][4]、[lscpu][5] 和 [lsscsi][6] 之类的列出命令获取有关硬件的详细信息。例如,这是 `lsblk` 命令的输出:
|
||||
|
||||
```
|
||||
# lsblk
|
||||
@ -32,7 +34,7 @@ xvdb 202:16 0 20G 0 disk
|
||||
└─xvdb1 202:17 0 20G 0 part
|
||||
```
|
||||
|
||||
If the **ls** commands don't reveal any errors, use init processes (e.g., **systemd** ) to see how the Linux server is working. **systemd** is the most popular init process for bootstrapping user spaces and controlling multiple system processes. For example, here is output of the **systemctl status** command:
|
||||
如果这些列出命令没有显示任何错误,请使用初始化系统(例如 systemd)查看 Linux 服务器的工作方式。 systemd 是最流行的初始化系统,用于启动用户空间并控制多个系统进程。例如,这是 `systemctl status` 命令的输出:
|
||||
|
||||
```
|
||||
# systemctl status
|
||||
@ -52,9 +54,9 @@ If the **ls** commands don't reveal any errors, use init processes (e.g., **syst
|
||||
....
|
||||
```
|
||||
|
||||
### Digging into multiple loggings
|
||||
### 深入到各个日志当中
|
||||
|
||||
**Dmesg** allows you to figure out errors and warnings in the kernel's latest messages. For example, here is output of the **dmesg | more** command:
|
||||
使用 `dmesg` 可以找出内核最新消息中的错误和警告。例如,这是 `dmesg | more` 命令的输出:
|
||||
|
||||
```
|
||||
# dmesg | more
|
||||
@ -73,7 +75,7 @@ If the **ls** commands don't reveal any errors, use init processes (e.g., **syst
|
||||
....
|
||||
```
|
||||
|
||||
You can also look at all Linux system logs in the **/var/log/messages** file, which is where you'll find errors related to specific issues. It's worthwhile to monitor the messages via the **tail** command in real time when you make modifications to your hardware, such as mounting an extra disk or adding an Ethernet network interface. For example, here is output of the **tail -f /var/log/messages** command:
|
||||
你还可以在 `/var/log/messages` 文件中查看所有 Linux 系统日志,在该文件中你可以找到与特定问题相关的错误。当你对硬件进行修改(例如安装额外的磁盘或添加以太网网卡)时,通过 `tail` 命令实时监视消息是值得的。例如,这是 `tail -f /var/log/messages` 命令的输出:
|
||||
|
||||
```
|
||||
# tail -f /var/log/messages
|
||||
@ -89,9 +91,9 @@ Dec 1 13:21:33 bastion dnsmasq[30201]: using nameserver 127.0.0.1#53 for domai
|
||||
Dec 1 13:21:33 bastion dnsmasq[30201]: using nameserver 127.0.0.1#53 for domain cluster.local
|
||||
```
|
||||
|
||||
### Analyzing networking functions
|
||||
### 分析网络功能
|
||||
|
||||
You may have hundreds of thousands of cloud-native applications to serve business services in a complex networking environment; these may include virtualization, multiple cloud, and hybrid cloud. This means you should analyze whether networking connectivity is working correctly as part of your troubleshooting. Useful commands to figure out networking functions in the Linux server include **ip addr** , **traceroute** , **nslookup** , **dig** , and **ping** , among others. For example, here is output of the **ip addr show** command:
|
||||
你可能有成千上万的云原生应用程序在一个复杂的网络环境中为业务提供服务,其中可能包括虚拟化、多云和混合云。这意味着,作为故障排除的一部分,你应该分析网络连接是否正常工作。弄清 Linux 服务器中网络功能的有用命令包括:`ip addr`、`traceroute`、`nslookup`、`dig` 和 `ping` 等。例如,这是 `ip addr show` 命令的输出:
|
||||
|
||||
```
|
||||
# ip addr show
|
||||
@ -116,9 +118,9 @@ You may have hundreds of thousands of cloud-native applications to serve busines
|
||||
....
|
||||
```
|
||||
|
||||
### In conclusion
|
||||
### 总结
|
||||
|
||||
Troubleshooting Linux hardware requires considerable knowledge, including how to use powerful command-line tools and figure out system loggings. You should also know how to diagnose the kernel space, which is where you can find the root cause of many hardware problems. Keep in mind that hardware issues in Linux may come from many different sources, including devices, modules, drivers, BIOS, networking, and even plain old hardware malfunctions.
|
||||
对 Linux 硬件进行故障排除需要大量的知识,包括如何使用功能强大的命令行工具以及找出系统日志记录。 你还应该知道如何诊断内核空间,在那里你可以找到许多硬件问题的根本原因。请记住,Linux 中的硬件问题可能来自许多不同的来源,包括设备、模块、驱动程序、BIOS、网络,甚至是普通的旧硬件故障。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -126,8 +128,8 @@ via: https://opensource.com/article/18/12/troubleshooting-hardware-problems-linu
|
||||
|
||||
作者:[Daniel Oh][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
235
published/20190113 Editing Subtitles in Linux.md
Normal file
235
published/20190113 Editing Subtitles in Linux.md
Normal file
@ -0,0 +1,235 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (chenmu-kk)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11946-1.html)
|
||||
[#]: subject: (Editing Subtitles in Linux)
|
||||
[#]: via: (https://itsfoss.com/editing-subtitles)
|
||||
[#]: author: (Shirish https://itsfoss.com/author/shirish/)
|
||||
|
||||
如何在 Linux 中编辑字幕
|
||||
======
|
||||
|
||||
我作为一位世界电影和地区电影爱好者已经几十年了。这期间字幕是一个必不可少的工具,它可以使我享受来自不同国家不同语言的优秀电影。
|
||||
|
||||
如果你喜欢观看带有字幕的电影,你可能会注意到有时字幕并不同步或者说并不正确。
|
||||
|
||||
你知道你可以自己编写字幕并使得它们更完美吗?让我们向你展示一些 Linux 中的基本字幕编辑吧。
|
||||
|
||||
![Editing subtitles in Linux][1]
|
||||
|
||||
### 从闭路字幕数据中提取字幕
|
||||
|
||||
大概在 2012、2013 年我开始了解到有一款叫做 [CCEextractor][2] 的工具。随着时间的推移,它已经成为我必不可少的工具之一,尤其是当我偶然发现一份内含有字幕的媒体文件。
|
||||
|
||||
CCExtractor 负责解析视频文件以及从<ruby>闭路字幕<rt>closed captions</rt></ruby>数据中产生独立的字幕文件。
|
||||
|
||||
CCExtractor 是一个跨平台的、自由开源工具。自它形成的那年起该工具已经成熟了不少而如今已成为 [GSOC][3] 和谷歌编码输入的一部分。
|
||||
|
||||
简单来说,这个工具基本上是一系列脚本,这些脚本以一种顺序方式一个接着一个地给你提供提取到的字幕。
|
||||
|
||||
你可以按照[本页][5]的 CCExtractor 安装指南进行操作。
|
||||
|
||||
若安装后你想从媒体文件中提取字幕,请按以下步骤操作:
|
||||
|
||||
```
|
||||
ccextractor <path_to_video_file>
|
||||
```
|
||||
|
||||
该命令将会输出以下内容:
|
||||
|
||||
```
|
||||
$ ccextractor $something.mkv
|
||||
CCExtractor 0.87, Carlos Fernandez Sanz, Volker Quetschke.
|
||||
Teletext portions taken from Petr Kutalek's telxcc
|
||||
--------------------------------------------------------------------------
|
||||
Input: $something.mkv
|
||||
[Extract: 1] [Stream mode: Autodetect]
|
||||
[Program : Auto ] [Hauppage mode: No] [Use MythTV code: Auto]
|
||||
[Timing mode: Auto] [Debug: No] [Buffer input: No]
|
||||
[Use pic_order_cnt_lsb for H.264: No] [Print CC decoder traces: No]
|
||||
[Target format: .srt] [Encoding: UTF-8] [Delay: 0] [Trim lines: No]
|
||||
[Add font color data: Yes] [Add font typesetting: Yes]
|
||||
[Convert case: No] [Video-edit join: No]
|
||||
[Extraction start time: not set (from start)]
|
||||
[Extraction end time: not set (to end)]
|
||||
[Live stream: No] [Clock frequency: 90000]
|
||||
[Teletext page: Autodetect]
|
||||
[Start credits text: None]
|
||||
[Quantisation-mode: CCExtractor's internal function]
|
||||
-----------------------------------------------------------------
|
||||
Opening file: $something.mkv
|
||||
File seems to be a Matroska/WebM container
|
||||
Analyzing data in Matroska mode
|
||||
|
||||
Document type: matroska
|
||||
Timecode scale: 1000000
|
||||
Muxing app: libebml v1.3.1 + libmatroska v1.4.2
|
||||
Writing app: mkvmerge v8.2.0 ('World of Adventure') 64bit
|
||||
Title: $something
|
||||
|
||||
Track entry:
|
||||
Track number: 1
|
||||
UID: 1
|
||||
Type: video
|
||||
Codec ID: V_MPEG4/ISO/AVC
|
||||
Language: mal
|
||||
Name: $something
|
||||
|
||||
Track entry:
|
||||
Track number: 2
|
||||
UID: 2
|
||||
Type: audio
|
||||
Codec ID: A_MPEG/L3
|
||||
Language: mal
|
||||
Name: $something
|
||||
|
||||
Track entry:
|
||||
Track number: 3
|
||||
UID: somenumber
|
||||
Type: subtitle
|
||||
Codec ID: S_TEXT/UTF8
|
||||
Name: $something
|
||||
99% | 144:34
|
||||
100% | 144:34
|
||||
Output file: $something_eng.srt
|
||||
Done, processing time = 6 seconds
|
||||
Issues? Open a ticket here
|
||||
https://github.com/CCExtractor/ccextractor/issues
|
||||
```
|
||||
它会大致浏览媒体文件。在这个例子中,它发现该媒体文件是马拉雅拉姆语言(mal)并且格式是 [.mkv][6]。之后它将字幕文件提取出来,命名为源文件名并添加“_eng”后缀。
|
||||
|
||||
CCExtractor 是一款用来增强字幕功能和字幕编辑的优秀工具,我将在下一部分对它进行介绍。
|
||||
|
||||
> 趣味阅读:在 [vicaps][7] 有一份有趣的字幕提要,它讲解和分享为何字幕对我们如此重要。对于那些对这类话题感兴趣的人来说,这里面也有许多电影制作的细节。
|
||||
|
||||
### 用 SubtitleEditor 工具编辑字幕
|
||||
|
||||
你大概意识到大多数的字幕都是 [.srt 格式][8] 的。这种格式的优点在于你可以将它加载到文本编辑器中并对它进行少量的修改。
|
||||
|
||||
当进入一个简单的文本编辑器时,一个 srt 文件看起来会是这个样子:
|
||||
|
||||
```
|
||||
1
|
||||
00:00:00,959 --> 00:00:13,744
|
||||
"THE CABINET
|
||||
OF DR. CALIGARI"
|
||||
|
||||
2
|
||||
00:00:40,084 --> 00:01:02,088
|
||||
A TALE of the modern re-appearance of an 11th Century Myth
|
||||
involting the strange and mysterious influence
|
||||
of a mountebank monk over a somnambulist.
|
||||
```
|
||||
|
||||
我分享的节选字幕来自于一部非常老的德国电影《[卡里加里博士的小屋][9]》(1920)。
|
||||
|
||||
Subtitleeditor 是一款非常棒的字幕编辑软件。字幕编辑器可以用来设置字幕持续时间、与多媒体文件同步的字幕帧率以及字幕间隔时间等等。接下来我将在这分享一些基本的字幕编辑。
|
||||
|
||||
![][10]
|
||||
|
||||
首先,以安装 ccextractor 工具同样的方式安装 subtitleeditor 工具,使用你自己喜爱的安装方式。在 Debian 中,你可以使用命令:
|
||||
|
||||
```
|
||||
sudo apt install subtitleeditor
|
||||
```
|
||||
|
||||
当你安装完成后,让我们来看一下在你编辑字幕时一些常见的场景。
|
||||
|
||||
#### 调整帧率使其媒体文件同步
|
||||
|
||||
如果你发现字幕与视频不同步,一个原因可能是视频文件的帧率与字幕文件的帧率并不一致。
|
||||
|
||||
你如何得知这些文件的帧率呢,然后呢?为了获取视频文件的帧率,你可以使用 `mediainfo` 工具。首先你可能需要发行版的包管理器来安装它。
|
||||
|
||||
使用 `mediainfo` 非常简单:
|
||||
|
||||
```
|
||||
$ mediainfo somefile.mkv | grep Frame
|
||||
Format settings : CABAC / 4 Ref Frames
|
||||
Format settings, ReFrames : 4 frames
|
||||
Frame rate mode : Constant
|
||||
Frame rate : 25.000 FPS
|
||||
Bits/(Pixel*Frame) : 0.082
|
||||
Frame rate : 46.875 FPS (1024 SPF)
|
||||
```
|
||||
|
||||
现在你可以看到视频文件的帧率是 25.000 FPS 。我们看到的另一个帧率则是音频文件的帧率。虽然我可以分享为何在视频解码和音频解码等地方会使用特定的 fps,但这将会是一个不同的主题,与它相关的历史信息有很多。
|
||||
|
||||
下一个问题是解决字幕文件的帧率,这个稍微有点复杂。
|
||||
|
||||
通常情况下,大多数字幕都是压缩格式的。将.zip 归档文件和字幕文件(以 XXX.srt 结尾)一起解压缩。除此之外,通常还会有一个同名的 .info 文件,该文件可能包含字幕的帧率。
|
||||
|
||||
如果不是,那么通常最好去某个站点并从具有该帧速率信息的站点下载字幕。对于这个特定的德文文件,我使用 [Opensubtitle.org][11] 来找到它。
|
||||
|
||||
正如你在链接中所看到的,字幕的帧率是 23.976 FPS 。很明显,它不能与帧率为 25.000 FPS 的视频文件一起很好地播放。
|
||||
|
||||
在这种情况下,你可以使用字幕编辑工具来改变字幕文件的帧率。
|
||||
|
||||
按下 `CTRL+A` 选择字幕文件中的全部内容。点击 “Timings -> Change Framerate” ,将 23.976 fps 改为 25.000 fps 或者你想要的其他帧率,保存已更改的文件。
|
||||
|
||||
![synchronize frame rates of subtitles in Linux][12]
|
||||
|
||||
#### 改变字幕文件的起点
|
||||
|
||||
有时以上的方法就足够解决问题了,但有时候以上方法并不足够解决问题。
|
||||
|
||||
在帧率相同时,你可能会发现字幕文件的开头与电影或媒体文件中起点并不相同。
|
||||
|
||||
在这种情况下,请按以下步骤进行操作:
|
||||
|
||||
按下 `CTRL+A` 键选中字幕文件的全部内容。点击 “Timings -> Select Move Subtitle” 。
|
||||
|
||||
![Move subtitles using Subtitle Editor on Linux][13]
|
||||
|
||||
设定字幕文件的新起点,保存已更改的文件。
|
||||
|
||||
![Move subtitles using Subtitle Editor in Linux][14]
|
||||
|
||||
如果你想要时间更精确一点,那么可以使用 [mpv][15] 来查看电影或者媒体文件并点击进度条(可以显示电影或者媒体文件的播放进度),它也会显示微秒。
|
||||
|
||||
通常我喜欢精准无误的操作,因此我会试着尽可能地仔细调节。相较于人类的反应时间来说,MPV 中的反应时间很精确。如果我想要极其精确的时间,那么我可以使用像 [Audacity][16] 之类的东西,但是那是另一种工具,你可以在上面做更多的事情。那也将会是我未来博客中将要探讨的东西。
|
||||
|
||||
#### 调整字幕间隔时间
|
||||
|
||||
有时,两种方法都采用了还不够,甚至你可能需要缩短或增加间隔时间以使其与媒体文件同步。这是较为繁琐的工作之一,因为你必须单独确定每个句子的间隔时间。尤其是在媒体文件中帧率可变的情况下(现已很少见,但你仍然会得到此类文件)
|
||||
|
||||
在这种设想下,你可能因为无法实现自动编辑而不得不手动的修改间隔时间。最好的方式是修改视频文件(会降低视频质量)或者换另一个更高质量的片源,用你喜欢的设置对它进行[转码][17] 。这又是一重大任务,以后我会在我的一些博客文章上阐明。
|
||||
|
||||
### 总结
|
||||
|
||||
以上我分享的内容或多或少是对现有字幕文件的改进。如果从头开始,你需要花费大量的时间。我完全没有分享这一点,因为一部电影或一个小时内的任何视频材料都可以轻易地花费 4-6 个小时,甚至更多的时间,这取决于字幕员的技巧、耐心、上下文、行话、口音、是否是以英语为母语的人、翻译等,所有的这些都会对字幕的质量产生影响。
|
||||
|
||||
我希望自此以后你会觉得这件事很有趣,并将你的字幕处理的更好一点。如果你有其他想要补充的问题,请在下方留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/editing-subtitles
|
||||
|
||||
作者:[Shirish][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[chenmu-kk](https://github.com/chenmu-kk)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/shirish/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/editing-subtitles-in-linux.jpeg?resize=800%2C450&ssl=1
|
||||
[2]: https://www.ccextractor.org/
|
||||
[3]: https://itsfoss.com/best-open-source-internships/
|
||||
[4]: https://www.ccextractor.org/public:codein:google_code-in_2018
|
||||
[5]: https://github.com/CCExtractor/ccextractor/wiki/Installation
|
||||
[6]: https://en.wikipedia.org/wiki/Matroska
|
||||
[7]: https://www.vicaps.com/blog/history-of-silent-movies-and-subtitles/
|
||||
[8]: https://en.wikipedia.org/wiki/SubRip#SubRip_text_file_format
|
||||
[9]: https://www.imdb.com/title/tt0010323/
|
||||
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/subtitleeditor.jpg?ssl=1
|
||||
[11]: https://www.opensubtitles.org/en/search/sublanguageid-eng/idmovie-4105
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/subtitleeditor-frame-rate-sync.jpg?resize=800%2C450&ssl=1
|
||||
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/Move-subtitles-Caligiri.jpg?resize=800%2C450&ssl=1
|
||||
[14]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/move-subtitles.jpg?ssl=1
|
||||
[15]: https://itsfoss.com/mpv-video-player/
|
||||
[16]: https://www.audacityteam.org/
|
||||
[17]: https://en.wikipedia.org/wiki/Transcoding
|
||||
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/editing-subtitles-in-linux.jpeg?fit=800%2C450&ssl=1
|
234
published/201911/20191107 Demystifying Kubernetes.md
Normal file
234
published/201911/20191107 Demystifying Kubernetes.md
Normal file
@ -0,0 +1,234 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Morisun029)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11628-1.html)
|
||||
[#]: subject: (Demystifying Kubernetes)
|
||||
[#]: via: (https://opensourceforu.com/2019/11/demystifying-kubernetes/)
|
||||
[#]: author: (Abhinav Nath Gupta https://opensourceforu.com/author/abhinav-gupta/)
|
||||
|
||||
揭开 Kubernetes 的神秘面纱
|
||||
======
|
||||
|
||||
![][2]
|
||||
|
||||
> Kubernetes 是一款生产级的开源系统,用于容器化应用程序的自动部署、扩展和管理。本文关于使用 Kubernetes 来管理容器。
|
||||
|
||||
“容器”已成为最新的流行语之一。但是,这个词到底意味着什么呢?说起“容器”,人们通常会把它和 Docker 联系起来,Docker 是一个被定义为软件的标准化单元容器。该容器将软件和运行软件所需的环境封装到一个易于交付的单元中。
|
||||
|
||||
容器是一个软件的标准单元,用它来打包代码及其所有依赖项,这样应用程序就可以从一个计算环境到另一个计算环境快速可靠地运行。容器通过创建类似于 ISO 镜像的方式来实现此目的。容器镜像是一个轻量级的、独立的、可执行的软件包,其中包含运行应用程序所需的所有信息,包括代码、运行时、系统工具、系统库和设置。
|
||||
|
||||
容器镜像在运行时变成容器,对于 Docker 容器,镜像在 Docker 引擎上运行时变成容器。容器将软件与环境隔离开来,确保不同环境下的实例,都可以正常运行。
|
||||
|
||||
###什么是容器管理?
|
||||
|
||||
容器管理是组织、添加或替换大量软件容器的过程。容器管理使用软件来自动化创建、部署和扩展容器。这一过程就需要容器编排,容器编排是一个自动对基于容器的应用程序进行部署、管理、扩展、联网和提供可用性的工具。
|
||||
|
||||
### Kubernetes
|
||||
|
||||
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,它有助于配置和自动化。它最初由 Google 开发,拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、技术支持和工具得到广泛应用。
|
||||
|
||||
Google 在 2014 年开源了 Kubernetes 项目。Kubernetes 建立在 Google 十五年大规模运行生产工作负载的经验基础上,并结合了社区中最好的想法和实践以及声明式句法的使用。
|
||||
|
||||
下面列出了与Kubernetes生态系统相关的一些常用术语。
|
||||
|
||||
**Pod**:Pod 是 Kubernetes 应用程序的基本执行单元,是你创建或部署的 Kubernetes 对象模型中的最小和最简单的单元。Pod 代表在 Kubernetes 集群上运行的进程。
|
||||
|
||||
Pod 将运行中的容器、存储、网络 IP(唯一)和控制容器应如何运行的命令封装起来。它代表 Kubernetes 生态系统内的单个部署单元,代表一个应用程序的单个实例,该程序可能包含一个或多个紧密耦合并共享资源的容器。
|
||||
|
||||
Kubernetes 集群中的 Pod 有两种主要的使用方式。第一种是运行单个容器。即“一个容器一个 Pod”,这种方式是最常见的。第二种是运行多个需要一起工作的容器。
|
||||
|
||||
Pod 可能封装一个由紧密关联且需要共享资源的多个同位容器组成的应用程序。
|
||||
|
||||
<ruby>副本集<rt>ReplicaSet</rt></ruby>:副本集的目的是维护在任何给定时间运行的一组稳定的副本容器集。 副本集包含有关一个特定 Pod 应该运行多少个副本的信息。为了创建多个 Pod 以匹配副本集条件,Kubernetes 使用 Pod 模板。副本集与其 Pod 的链接是通过后者的 `metas.ownerReferences` 字段实现,该字段指定哪个资源拥有当前对象。
|
||||
|
||||
<ruby>服务<rt>Services</rt></ruby>:服务是一种抽象,用来公开一组 Pod 功能。使用 Kubernetes,你无需修改应用程序即可使用陌生服务发现机制。Kubernetes 给 Pod 提供了其自己的 IP 地址和一组 Pod 的单个 DNS 名称,并且可以在它们之间负载平衡。
|
||||
|
||||
服务解决的一个主要问题是 Web 应用程序前端和后端的集成。由于 Kubernetes 将幕后的 IP 地址提供给 Pod,因此当 Pod 被杀死并复活时,IP 地址会更改。这给给定的后端 IP 地址连接到相应的前端 IP 地址带来一个大问题。服务通过在 Pod 上提供抽象来解决此问题,类似于负载均衡器。
|
||||
|
||||
<ruby>卷<rt>Volumes</rt></ruby>: Kubernetes 卷具有明确的生命周期,与围绕它的 Pod 相同。 因此,卷超过了 Pod 中运行的任何容器的寿命,并且在容器重新启动后保留了数据。当然,当 Pod 不存在时,该卷也将不再存在。也许比这更重要的是 Kubernetes 支持多种类型的卷,并且 Pod 可以同时使用任意数量的卷。
|
||||
|
||||
卷的核心只是一个目录,其中可能包含一些数据,Pod 中的容器可以访问该目录。该目录是如何产生的,它后端基于什么存储介质,其中的数据内容是什么,这些都由使用的特定卷类型来决定的。
|
||||
|
||||
### 为什么选择 Kubernetes?
|
||||
|
||||
容器是捆绑和运行应用程序的好方法。在生产环境中,你需要管理运行应用程序的容器,并确保没有停机时间。例如,如果一个容器发生故障,则需要启动另一个容器。如果由系统自动实现这一操作,岂不是更好? Kubernetes 就是来解决这个问题的!Kubernetes 提供了一个框架来弹性运行分布式系统。该框架负责扩展需求、故障转移、部署模式等。例如,Kubernetes 可以轻松管理系统的金丝雀部署。
|
||||
|
||||
Kubernetes 为用户提供了:
|
||||
|
||||
1. 服务发现和负载平衡
|
||||
2. 存储编排
|
||||
3. 自动退出和回退
|
||||
4. 自动打包
|
||||
5. 自我修复
|
||||
6. 秘密配置管理
|
||||
|
||||
### Kubernetes 可以做什么?
|
||||
|
||||
在本文中,我们将会看到一些从头构建 Web 应用程序时如何使用 Kubernetes 的代码示例。我们将在 Python 中使用 Flask 创建一个简单的后端服务器。
|
||||
|
||||
对于那些想从头开始构建 Web 应用程序的人,有一些前提条件,即:
|
||||
|
||||
1. 对 Docker、Docker 容器和 Docker 镜像的基本了解。可以访问[这里][8]快速了解。
|
||||
2. 系统中应该安装 Docker。
|
||||
3. 系统中应该安装 Kubernetes,有关如何在本地计算机上安装的说明,请访问[这里][9]。
|
||||
|
||||
现在,创建一个目录,如下代码片段所示:
|
||||
|
||||
```
|
||||
mkdir flask-kubernetes/app && cd flask-kubernetes/app
|
||||
```
|
||||
|
||||
接下来,在 `flask-kubernetes/app` 目录中,创建一个名为 `main.py` 的文件,如下面的代码片段所示:
|
||||
|
||||
```
|
||||
touch main.py
|
||||
```
|
||||
|
||||
在新创建的 `main.py` 文件中,粘贴下面代码:
|
||||
|
||||
```
|
||||
from flask import Flask
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/")
|
||||
def hello():
|
||||
return "Hello from Kubernetes!"
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host='0.0.0.0')
|
||||
```
|
||||
|
||||
使用下面命令在本地安装 Flask:
|
||||
|
||||
```
|
||||
pip install Flask==0.10.1
|
||||
```
|
||||
|
||||
Flask 安装后,执行下面的命令:
|
||||
|
||||
```
|
||||
python app.py
|
||||
```
|
||||
|
||||
应该在本地 5000 端口运行 Flask 服务器,这是 Flask 应用程序的默认端口,并且你可以在 http://localhost:5000 上看到输出 “Hello from Kubernetes!”。服务器在本地运行之后,我们创建一个供 Kubernetes 使用的 Docker 镜像。创建一个名为 `Dockerfile` 的文件,并将以下代码片段粘贴到其中:
|
||||
|
||||
```
|
||||
FROM python:3.7
|
||||
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
ADD . /app/
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
EXPOSE 5000
|
||||
CMD ["python", "/app/main.py"]
|
||||
```
|
||||
|
||||
`Dockerfile` 文件的说明如下:
|
||||
|
||||
1. Docker 将从 DockerHub 获取 Python 3.7 镜像。
|
||||
2. 将在镜像中创建一个应用程序目录。
|
||||
3. 它将一个 `/app` 目录设置为工作目录。
|
||||
4. 将内容从主机中的应用程序目录复制到镜像应用程序目录。
|
||||
5. 发布端口 5000。
|
||||
6. 最后,它运行命令,启动 Flask 服务器。
|
||||
|
||||
接下来,我们将使用以下命令创建 Docker 镜像:
|
||||
|
||||
```
|
||||
docker build -f Dockerfile -t flask-kubernetes:latest .
|
||||
```
|
||||
|
||||
创建 Docker 镜像后,我们可以使用以下命令在本地运行该镜像进行测试:
|
||||
|
||||
```
|
||||
docker run -p 5001:5000 flask-kubernetes
|
||||
```
|
||||
|
||||
通过运行容器在本地完成测试之后,我们需要在 Kubernetes 中部署它。我们将首先使用 `kubectl` 命令验证 Kubernetes 是否正在运行。如果没有报错,则说明它正在工作。如果有报错,请参考[该信息][9]。
|
||||
|
||||
接下来,我们创建一个部署文件。这是一个 Yaml 文件,其中包含有关 Kubernetes 的说明,该说明涉及如何以声明性的方式创建 Pod 和服务。因为我们有 Flask Web 应用程序,我们将创建一个 `deployment.yaml` 文件,并在其中包含 Pod 和服务声明。
|
||||
|
||||
创建一个名为 `deployment.yaml` 的文件并向其中添加以下内容,然后保存:
|
||||
|
||||
```
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: flask-kubernetes -service
|
||||
spec:
|
||||
selector:
|
||||
app: flask-kubernetes
|
||||
ports:
|
||||
- protocol: "TCP"
|
||||
port: 6000
|
||||
targetPort: 5000
|
||||
type: LoadBalancer
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: flask-kubernetes
|
||||
spec:
|
||||
replicas: 4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: flask-kubernetes
|
||||
spec:
|
||||
containers:
|
||||
- name: flask-kubernetes
|
||||
image: flask-kubernetes:latest
|
||||
imagePullPolicy: Never
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
```
|
||||
|
||||
使用以下命令将 yaml 文件发送到 Kubernetes:
|
||||
|
||||
```
|
||||
kubectl apply -f deployment.yaml
|
||||
```
|
||||
|
||||
如果执行以下命令,你会看到 Pod 正在运行:
|
||||
|
||||
```
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
现在,导航至 http://localhost:6000,你应该会看到 “Hello from Kubernetes!”消息。成功了! 该应用程序现在正在 Kubernetes 中运行!
|
||||
|
||||
### Kubernetes 做不了什么?
|
||||
|
||||
Kubernetes 不是一个传统的,包罗万象的 PaaS(平台即服务)系统。 由于 Kubernetes 运行在容器级别而非硬件级别,因此它提供了 PaaS 产品共有的一些普遍适用功能,如部署、扩展、负载平衡、日志记录和监控。Kubernetes 为开发人员平台提供了构建块,但在重要的地方保留了用户的选择和灵活性。
|
||||
|
||||
* Kubernetes 不限制所支持的应用程序的类型。如果应用程序可以在容器中运行,那么它应该可以在 Kubernetes 上更好地运行。
|
||||
* 它不部署和构建源代码。
|
||||
* 它不决定日志记录、监视或警报解决方案。
|
||||
* 它不提供或不要求配置语言/系统。它提供了一个声明式的 API 供所有人使用。
|
||||
* 它不提供或不采用任何全面的机器配置、维护、管理或自我修复系统。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensourceforu.com/2019/11/demystifying-kubernetes/
|
||||
|
||||
作者:[Abhinav Nath Gupta][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Morisun029](https://github.com/Morisun029)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensourceforu.com/author/abhinav-gupta/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i2.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Gear-kubernetes.jpg?resize=696%2C457&ssl=1 (Gear kubernetes)
|
||||
[2]: https://i2.wp.com/opensourceforu.com/wp-content/uploads/2019/11/Gear-kubernetes.jpg?fit=800%2C525&ssl=1
|
||||
[3]: https://secure.gravatar.com/avatar/f65917facf5f28936663731fedf545c4?s=100&r=g
|
||||
[4]: https://opensourceforu.com/author/abhinav-gupta/
|
||||
[5]: mailto:abhi.aec89@gmail.com
|
||||
[6]: http://opensourceforu.com/wp-content/uploads/2013/10/assoc.png
|
||||
[7]: https://feedburner.google.com/fb/a/mailverify?uri=LinuxForYou&loc=en_US
|
||||
[8]: https://www.docker.com/sites/default/files/Docker_CheatSheet_08.09.2016_0.pdf
|
||||
[9]: https://kubernetes.io/docs/setup/learning-environment/minikube/
|
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11627-1.html)
|
||||
[#]: subject: (How to Install VirtualBox 6.0 on CentOS 8 / RHEL 8)
|
||||
[#]: via: (https://www.linuxtechi.com/install-virtualbox-6-centos-8-rhel-8/)
|
||||
[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
|
||||
@ -10,27 +10,29 @@
|
||||
如何在 CentOS 8 / RHEL 8 上安装 VirtualBox 6.0
|
||||
======
|
||||
|
||||
**VirtualBox** 是一款免费的开源**虚拟化工具**,它允许技术人员同时运行多个不同风格的虚拟机。它通常用于运行桌面(Linux 和 Windows),当人们尝试探索新的 Linux 发行版的功能或希望在 VM 中安装 **OpenStack**、**Ansible** 和 **Puppet** 等软件时,它会非常方便,在这种情况下,我们可以使用 VirtualBox 启动 VM。
|
||||
![](https://img.linux.net.cn/data/attachment/album/201911/30/095031gbnm59ux0dw979wb.jpg)
|
||||
|
||||
VirtualBox 被分类为**2 类虚拟机管理程序**,这意味着它需要一个现有的操作系统,在上面安装 VirtualBox 软件。VirtualBox 提供功能来创建本机网络或 NAT 网络。在本文中,我们将演示如何在 CentOS 8 和 RHEL 8 系统上安装最新版本的 VirtualBox 6.0,并演示如何安装 VirtualBox 扩展。
|
||||
VirtualBox 是一款自由开源的虚拟化工具,它允许技术人员同时运行多个不同风格的虚拟机(VM)。它通常用于运行桌面(Linux 和 Windows),当人们尝试探索新的 Linux 发行版的功能或希望在 VM 中安装 OpenStack、Ansible 和 Puppet 等软件时,它会非常方便,在这种情况下,我们可以使用 VirtualBox 启动 VM。
|
||||
|
||||
VirtualBox 被分类为 2 类虚拟机管理程序,这意味着它需要一个现有的操作系统,在上面安装 VirtualBox 软件。VirtualBox 提供功能来创建本机网络或 NAT 网络。在本文中,我们将演示如何在 CentOS 8 和 RHEL 8 系统上安装最新版本的 VirtualBox 6.0,并演示如何安装 VirtualBox 扩展。
|
||||
|
||||
### 在 CentOS 8 / RHEL 8 上安装 VirtualBox 6.0 的安装步骤
|
||||
|
||||
#### 步骤 1: 启用 VirtualBox 和 EPEL 仓库
|
||||
|
||||
登录到你的 CentOS 8 或 RHEL 8 系统并打开终端,执行以下命令并启用 VirtualBox 和 EPEL 包仓库。
|
||||
登录到你的 CentOS 8 或 RHEL 8 系统并打开终端,执行以下命令并启用 VirtualBox 和 EPEL 包仓库:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# dnf config-manager --add-repo=https://download.virtualbox.org/virtualbox/rpm/el/virtualbox.repo
|
||||
```
|
||||
|
||||
使用以下 rpm 命令导入 Oracle VirtualBox 公钥
|
||||
使用以下 `rpm` 命令导入 Oracle VirtualBox 公钥:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# rpm --import https://www.virtualbox.org/download/oracle_vbox.asc
|
||||
```
|
||||
|
||||
使用以下 dnf 命令启用 EPEL 仓库,
|
||||
使用以下 `dnf` 命令启用 EPEL 仓库:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
|
||||
@ -38,17 +40,17 @@ VirtualBox 被分类为**2 类虚拟机管理程序**,这意味着它需要一
|
||||
|
||||
#### 步骤 2: 安装 VirtualBox 构建工具和依赖项
|
||||
|
||||
运行以下命令来安装所有 VirtualBox 构建工具和依赖项,
|
||||
运行以下命令来安装所有 VirtualBox 构建工具和依赖项:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# dnf install binutils kernel-devel kernel-headers libgomp make patch gcc glibc-headers glibc-devel dkms -y
|
||||
```
|
||||
|
||||
成功安装上面的依赖项和构建工具后,使用 dnf 命令继续安装 VirtualBox,
|
||||
成功安装上面的依赖项和构建工具后,使用 `dnf` 命令继续安装 VirtualBox。
|
||||
|
||||
#### 步骤 3: 在 CentOS 8 / RHEL 8 上安装 VirtualBox 6.0
|
||||
|
||||
如果希望在安装之前列出 VirtualBox 的可用版本,请执行以下 [dnf 命令][1],
|
||||
如果希望在安装之前列出 VirtualBox 的可用版本,请执行以下 dnf 命令:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# dnf search virtualbox
|
||||
@ -59,13 +61,13 @@ VirtualBox-6.0.x86_64 : Oracle VM VirtualBox
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
让我们使用以下 dnf 命令安装最新版本的 VirtualBox 6.0,
|
||||
让我们使用以下 `dnf` 命令安装最新版本的 VirtualBox 6.0:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# dnf install VirtualBox-6.0 -y
|
||||
```
|
||||
|
||||
如果有本地用户希望将 usb 设备连接到 VirtualBox VM,那么他/她应该是 “**vboxusers**” 组的一员,请使用下面的 usermod 命令将本地用户添加到 “vboxusers” 组。
|
||||
如果有本地用户希望将 usb 设备连接到 VirtualBox VM,那么他/她应该是 `vboxusers` 组的一员,请使用下面的 `usermod` 命令将本地用户添加到 `vboxusers` 组。
|
||||
|
||||
|
||||
```
|
||||
@ -74,7 +76,7 @@ VirtualBox-6.0.x86_64 : Oracle VM VirtualBox
|
||||
|
||||
#### 步骤 4: 访问 CentOS 8 / RHEL 8 上的 VirtualBox
|
||||
|
||||
有两种方法可以访问 VirtualBox,在命令行输入 “**virtualbox**” 然后回车:
|
||||
有两种方法可以访问 VirtualBox,在命令行输入 `virtualbox` 然后回车:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# virtualbox
|
||||
@ -82,11 +84,11 @@ VirtualBox-6.0.x86_64 : Oracle VM VirtualBox
|
||||
|
||||
在桌面环境中,在搜索框中搜索 “VirtualBox”。
|
||||
|
||||
[![Access-VirtualBox-CentOS8][2]][3]
|
||||
![Access-VirtualBox-CentOS8][3]
|
||||
|
||||
单击 VirtualBox 图标,
|
||||
单击 VirtualBox 图标:
|
||||
|
||||
[![VirtualBox-CentOS8][2]][4]
|
||||
![VirtualBox-CentOS8][4]
|
||||
|
||||
这确认 VirtualBox 6.0 已成功安装,让我们安装它的扩展包。
|
||||
|
||||
@ -100,37 +102,28 @@ VirtualBox-6.0.x86_64 : Oracle VM VirtualBox
|
||||
* Intel PXE 启动
|
||||
* 主机网络摄像头
|
||||
|
||||
|
||||
|
||||
使用下面的 wget 命令下载 Virtualbox 扩展包到下载文件夹中,
|
||||
使用下面的 `wget` 命令下载 Virtualbox 扩展包到下载文件夹中:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ cd Downloads/
|
||||
[root@linuxtechi Downloads]$ wget https://download.virtualbox.org/virtualbox/6.0.14/Oracle_VM_VirtualBox_Extension_Pack-6.0.14.vbox-extpack
|
||||
```
|
||||
|
||||
下载后,打开 VirtualBox 并依次点击 **File** –>**Preferences** –> **Extension**,然后点击 “+” 号图标添加下载的扩展包,
|
||||
下载后,打开 VirtualBox 并依次点击 “File -> Preferences -> Extension”,然后点击 “+” 号图标添加下载的扩展包:
|
||||
|
||||
[![Install-VirtualBox-Extension-Pack-CentOS8][2]][5]
|
||||
![Install-VirtualBox-Extension-Pack-CentOS8][5]
|
||||
|
||||
单击 “Install” 开始安装扩展包。
|
||||
单击 “Install” 开始安装扩展包:
|
||||
|
||||
[![Accept-VirtualBox-Extension-Pack-License-CentOS8][2]][6]
|
||||
![Accept-VirtualBox-Extension-Pack-License-CentOS8][6]
|
||||
|
||||
单击 "I Agree" 接受 VirtualBox 扩展包许可证。
|
||||
单击 “I Agree” 接受 VirtualBox 扩展包许可证。
|
||||
|
||||
成功安装 VirtualBox 扩展包后,我们将看到下面的页面,单击 OK 并开始使用 VirtualBox。
|
||||
|
||||
[![VirtualBox-Extension-Pack-Install-Message-CentOS8][2]][7]
|
||||
|
||||
本文就是这些了,我希望这些步骤可以帮助你在 CentOS 8 和 RHEL 8 系统上安装 VirtualBox 6.0。请分享你的宝贵反馈和意见。
|
||||
|
||||
* [Facebook][9]
|
||||
* [Twitter][10]
|
||||
* [LinkedIn][11]
|
||||
* [Reddit][12]
|
||||
成功安装 VirtualBox 扩展包后,我们将看到下面的页面,单击 “OK” 并开始使用 VirtualBox。
|
||||
|
||||
![VirtualBox-Extension-Pack-Install-Message-CentOS8][7]
|
||||
|
||||
本文就是这些了,我希望这些步骤可以帮助你在 CentOS 8 和 RHEL 8 系统上安装 VirtualBox 6.0。请分享你的宝贵的反馈和意见。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -139,7 +132,7 @@ via: https://www.linuxtechi.com/install-virtualbox-6-centos-8-rhel-8/
|
||||
作者:[Pradeep Kumar][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/) 荣誉推出
|
||||
|
@ -1,25 +1,25 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11624-1.html)
|
||||
[#]: subject: (How to document Python code with Sphinx)
|
||||
[#]: via: (https://opensource.com/article/19/11/document-python-sphinx)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
如何使用 Sphinx 给 Python 代码写文档
|
||||
======
|
||||
最好将文档作为开发过程的一部分。Sphinx 加上 Tox,让文档可以轻松书写,并且外观漂亮。
|
||||
|
||||
> 最好将文档作为开发过程的一部分。Sphinx 加上 Tox,让文档可以轻松书写,并且外观漂亮。
|
||||
|
||||
![Python in a coffee cup.][1]
|
||||
|
||||
Python 代码可以在源码中包含文档。这种方式默认依靠 **docstring**,它以三引号格式定义。虽然文档的价值是很大的,但是代码没有充足的文档还是很常见。让我们演练一个场景,了解出色的文档的强大功能。
|
||||
|
||||
经历了太多白板技术面试,要求你实现斐波那契数列,你已经受够了。你回家用 Python 写了一个可重用的斐波那契计算器,使用浮点技巧来实现 O(1) 复杂度。
|
||||
Python 代码可以在源码中包含文档。这种方式默认依靠 **docstring**,它以三引号格式定义。虽然文档的价值是很大的,但是没有充足的文档的代码还是很常见。让我们演练一个场景,了解出色的文档的强大功能。
|
||||
|
||||
经历了太多在白板技术面试上要求你实现斐波那契数列,你已经受够了。你回家用 Python 写了一个可重用的斐波那契计算器,使用浮点技巧来实现 `O(1)` 复杂度。
|
||||
|
||||
代码很简单:
|
||||
|
||||
|
||||
```
|
||||
# fib.py
|
||||
import math
|
||||
@ -33,8 +33,7 @@ def approx_fib(n):
|
||||
|
||||
(该斐波那契数列是四舍五入到最接近的整数的几何序列,这是我最喜欢的鲜为人知的数学事实之一。)
|
||||
|
||||
作为一个好人,你可以将代码开源,并将它放在 [PyPI][2] 上。setup.py 文件很简单:
|
||||
|
||||
作为一个好人,你可以将代码开源,并将它放在 [PyPI][2] 上。`setup.py` 文件很简单:
|
||||
|
||||
```
|
||||
import setuptools
|
||||
@ -47,7 +46,7 @@ setuptools.setup(
|
||||
)
|
||||
```
|
||||
|
||||
但是,没有文档的代码是没有用的。因此,你可以向函数添加 docstring。我最喜欢的 docstring 样式之一是 [“Google” 样式][3]。标记很轻量,这在它位于源代码中时很好。
|
||||
但是,没有文档的代码是没有用的。因此,你可以向函数添加 docstring。我最喜欢的 docstring 样式之一是 [“Google” 样式][3]。标记很轻量,当它放在源代码中时很好。
|
||||
|
||||
|
||||
```
|
||||
@ -64,10 +63,9 @@ def approx_fib(n):
|
||||
# ...
|
||||
```
|
||||
|
||||
但是函数的文档只是成功的一半。普通文档对于情境化代码用法很重要。在这种情况下,上下文是恼人的技术面试。
|
||||
|
||||
有一种添加更多文档的方式,Pythonic 模式通常是在 **docs/** 添加 **rst** 文件 ( [reStructuredText][4] 的缩写)。因此**docs/index.rst** 文件最终看起来像这样:
|
||||
但是函数的文档只是成功的一半。普通文档对于情境化代码用法很重要。在这种情况下,情景是恼人的技术面试。
|
||||
|
||||
有一种添加更多文档的方式,专业 Python 人的方式通常是在 `docs/` 添加 rst 文件( [reStructuredText][4] 的缩写)。因此 `docs/index.rst` 文件最终看起来像这样:
|
||||
|
||||
```
|
||||
Fibonacci
|
||||
@ -86,21 +84,17 @@ fib off.
|
||||
:members:
|
||||
```
|
||||
|
||||
我们完成了,对吧?我们已经将文本放在了文件中。人们应该看看。
|
||||
我们完成了,对吧?我们已经将文本放在了文件中。人们应该会看的。
|
||||
|
||||
### 使 Python 文档更漂亮
|
||||
|
||||
为了使你的文档看起来更漂亮,你可以利用 [Sphinx][5],它旨在制作漂亮的 Python 文档。这三个 Sphinx 扩展特别有用:
|
||||
|
||||
* **sphinx.ext.autodoc**:从模块内部获取文档
|
||||
* **sphinx.ext.napoleon**:支持 Google 样式的 docstring
|
||||
* **sphinx.ext.viewcode**:将 ReStructured Text 源码与生成的文档打包在一起
|
||||
|
||||
|
||||
|
||||
|
||||
为了告诉 Sphinx 该生成什么以及如何生成,我们在 **docs/conf.py** 中配置一个辅助文件:
|
||||
* `sphinx.ext.autodoc`:从模块内部获取文档
|
||||
* `sphinx.ext.napoleon`:支持 Google 样式的 docstring
|
||||
* `sphinx.ext.viewcode`:将 ReStructured Text 源码与生成的文档打包在一起
|
||||
|
||||
为了告诉 Sphinx 该生成什么以及如何生成,我们在 `docs/conf.py` 中配置一个辅助文件:
|
||||
|
||||
```
|
||||
extensions = [
|
||||
@ -108,12 +102,12 @@ extensions = [
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx.ext.viewcode',
|
||||
]
|
||||
# The name of the entry point, without the ".rst" extension.
|
||||
# By convention this will be "index"
|
||||
# 该入口点的名称,没有 .rst 扩展名。
|
||||
# 惯例该名称是 index
|
||||
master_doc = "index"
|
||||
# This values are all used in the generated documentation.
|
||||
# Usually, the release and version are the same,
|
||||
# but sometimes we want to have the release have an "rc" tag.
|
||||
# 这些值全部用在生成的文档当中。
|
||||
# 通常,发布(release)与版本(version)是一样的,
|
||||
# 但是有时候我们会有带有 rc 标签的发布。
|
||||
project = "Fib"
|
||||
copyright = "2019, Moshe Zadka"
|
||||
author = "Moshe Zadka"
|
||||
@ -122,43 +116,43 @@ version = release = "2019.1.0"
|
||||
|
||||
此文件使我们可以使用所需的所有元数据来发布代码,并注意扩展名(上面的注释说明了方式)。最后,要确保生成我们想要的文档,请使用 [Tox][6] 管理虚拟环境以确保我们顺利生成文档:
|
||||
|
||||
|
||||
```
|
||||
[tox]
|
||||
# By default, .tox is the directory.
|
||||
# Putting it in a non-dot file allows opening the generated
|
||||
# documentation from file managers or browser open dialogs
|
||||
# that will sometimes hide dot files.
|
||||
# 默认情况下,`.tox` 是该目录。
|
||||
# 将其放在非点文件中可以从
|
||||
# 文件管理器或浏览器的
|
||||
# 打开对话框中打开生成的文档,
|
||||
# 这些对话框有时会隐藏点文件。
|
||||
toxworkdir = {toxinidir}/build/tox
|
||||
|
||||
[testenv:docs]
|
||||
# Running sphinx from inside the "docs" directory
|
||||
# ensures it will not pick up any stray files that might
|
||||
# get into a virtual environment under the top-level directory
|
||||
# or other artifacts under build/
|
||||
# 从 `docs` 目录内运行 `sphinx`,
|
||||
# 以确保它不会拾取任何可能进入顶层目录下的
|
||||
# 虚拟环境或 `build/` 目录下的其他工件的杂散文件。
|
||||
changedir = docs
|
||||
# The only dependency is sphinx
|
||||
# If we were using extensions packaged separately,
|
||||
# we would specify them here.
|
||||
# A better practice is to specify a specific version of sphinx.
|
||||
# 唯一的依赖关系是 `sphinx`。
|
||||
# 如果我们使用的是单独打包的扩展程序,
|
||||
# 我们将在此处指定它们。
|
||||
# 更好的做法是指定特定版本的 sphinx。
|
||||
deps =
|
||||
sphinx
|
||||
# This is the sphinx command to generate HTML.
|
||||
# In other circumstances, we might want to generate a PDF or an ebook
|
||||
# 这是用于生成 HTML 的 `sphinx` 命令。
|
||||
# 在其他情况下,我们可能想生成 PDF 或电子书。
|
||||
commands =
|
||||
sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
|
||||
# We use Python 3.7. Tox sometimes tries to autodetect it based on the name of
|
||||
# the testenv, but "docs" does not give useful clues so we have to be explicit.
|
||||
# 我们使用 Python 3.7。
|
||||
# Tox 有时会根据 testenv 的名称尝试自动检测它,
|
||||
# 但是 `docs` 没有给出有用的线索,因此我们必须明确它。
|
||||
basepython = python3.7
|
||||
```
|
||||
|
||||
现在,无论何时运行T ox,它都会为你的 Python 代码生成漂亮的文档。
|
||||
现在,无论何时运行 Tox,它都会为你的 Python 代码生成漂亮的文档。
|
||||
|
||||
### 在 Python 中写文档很好
|
||||
|
||||
作为 Python 开发人员,我们可以使用的工具链很棒。 我们可以从 **docstring** 开始,添加 **.rst** 文件,然后添加 Sphinx 和 Tox 来为用户美化结果。
|
||||
作为 Python 开发人员,我们可以使用的工具链很棒。我们可以从 **docstring** 开始,添加 .rst 文件,然后添加 Sphinx 和 Tox 来为用户美化结果。
|
||||
|
||||
你对好的文档有何评价? 你还有其他喜欢的方式么? 请在评论中分享它们!
|
||||
你对好的文档有何评价?你还有其他喜欢的方式么?请在评论中分享它们!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -167,7 +161,7 @@ via: https://opensource.com/article/19/11/document-python-sphinx
|
||||
作者:[Moshe Zadka][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/) 荣誉推出
|
||||
|
168
published/201911/20191127 Displaying dates and times your way.md
Normal file
168
published/201911/20191127 Displaying dates and times your way.md
Normal file
@ -0,0 +1,168 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11623-1.html)
|
||||
[#]: subject: (Displaying dates and times your way)
|
||||
[#]: via: (https://www.networkworld.com/article/3481602/displaying-dates-and-times-your-way-with-linux.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
在终端里按你的方式显示日期和时间
|
||||
======
|
||||
|
||||
> Linux 的 date 命令提供了很多显示日期和时间的选项,要比你想的还要多。这是一些有用的选择。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201911/29/144555a8mq82mcc9cfttt9.jpg)
|
||||
|
||||
在 Linux 系统上,`date` 命令非常简单。你键入 `date`,日期和时间将以一种有用的方式显示。它包括星期几、日期、时间和时区:
|
||||
|
||||
```
|
||||
$ date
|
||||
Tue 26 Nov 2019 11:45:11 AM EST
|
||||
```
|
||||
|
||||
只要你的系统配置正确,你就会看到日期和当前时间以及时区。
|
||||
|
||||
但是,该命令还提供了许多选项来以不同方式显示日期和时间信息。例如,如果要显示日期以便进行排序,则可能需要使用如下命令:
|
||||
|
||||
```
|
||||
$ date "+%Y-%m-%d"
|
||||
2019-11-26
|
||||
```
|
||||
|
||||
在这种情况下,年、月和日按该顺序排列。请注意,我们使用大写字母 `Y` 来获得四位数的年份。如果我们使用小写的 `y`,则只会看到两位数字的年份(例如 19)。不要让这种做法使你错误地联想到如果 `%m` 给你一个数字月份,`%M` 可能会给你月份的名称。不,`%M` 将给你分钟数。要以缩写名称格式获得月份,你要使用 `%b`,而对于完全拼写的月份,则要使用 `%B`。
|
||||
|
||||
```
|
||||
$ date "+%b %B"
|
||||
Nov November
|
||||
```
|
||||
|
||||
或者,你可能希望以这种常用格式显示日期:
|
||||
|
||||
```
|
||||
$ date "+%D"
|
||||
11/26/19
|
||||
```
|
||||
|
||||
如果你需要四位数的年份,则可以执行以下操作:
|
||||
|
||||
```
|
||||
$ date "+%x"
|
||||
11/26/2019
|
||||
```
|
||||
|
||||
下面是一个可能有用的示例。假设你需要创建一个每日报告并在文件名中包含日期,则可以使用以下命令来创建文件(可能用在脚本中):
|
||||
|
||||
```
|
||||
$ touch Report-`date "+%Y-%m-%d"`
|
||||
```
|
||||
|
||||
当你列出你的报告时,它们将按日期顺序或反向日期顺序(如果你添加 `-r`)列出。
|
||||
|
||||
```
|
||||
$ ls -r Report*
|
||||
Report-2019-11-26
|
||||
Report-2019-11-25
|
||||
Report-2019-11-22
|
||||
Report-2019-11-21
|
||||
Report-2019-11-20
|
||||
```
|
||||
|
||||
你还可以在日期字符串中添加其他详细信息。可用的各种选项多得令人惊讶。你可以使用 `date "+%q"` 来显示你所在的一年中的哪个季度,或使用类似以下命令来显示两个月前的日期:
|
||||
|
||||
```
|
||||
$ date --date="2 months ago"
|
||||
Thu 26 Sep 2019 09:02:43 AM EDT
|
||||
```
|
||||
|
||||
是否想知道下周四的日期?你可以使用类似 `date --date="next thu"` 的命令,但是要理解,对于Linux,下个周四意味着今天之后的周四。如果今天是星期三,那就是明天,而不是下周的星期四。但是,你可以像下面的第二个命令一样指定下周的星期四。
|
||||
|
||||
```
|
||||
$ date --date="next thu"
|
||||
Thu 28 Nov 2019 12:00:00 AM EST
|
||||
$ date --date="next week thu"
|
||||
Thu 05 Dec 2019 12:00:00 AM EST
|
||||
```
|
||||
|
||||
`date` 命令的手册页列出了其所有选项。该列表多得令人难以置信,但是你可能会发现一些日期/时间显示选项非常适合你。以下是一些你可能会发现有趣的东西。
|
||||
|
||||
世界标准时间(UTC):
|
||||
|
||||
```
|
||||
$ date -u
|
||||
Tue 26 Nov 2019 01:13:59 PM UTC
|
||||
```
|
||||
|
||||
自 1970 年 1 月 1 日以来的秒数(与 Linux 系统上日期的存储方式有关):
|
||||
|
||||
```
|
||||
$ date +%s
|
||||
1574774137
|
||||
```
|
||||
|
||||
以下是 `date` 命令选项的完整列表。正如我所说,它比我们大多数人想象的要广泛得多。
|
||||
|
||||
- `%%` 显示字母 %
|
||||
- `%a` 本地语言环境的缩写星期名称(例如,日 / Sun)
|
||||
- `%A` 本地语言环境的完整星期名称(例如,星期日 / Sunday)
|
||||
- `%b` 本地语言环境的缩写月份名称(例如 一 / Jan)
|
||||
- `%B` 本地语言环境的完整月份名称(例如,一月 / January)
|
||||
- `%c` 本地语言环境的日期和时间(例如 2005年3月3日 星期四 23:05:25 / Thu Mar 3 23:05:25 2005)
|
||||
- `%C` 世纪;类似于 `%Y`,但省略了后两位数字(例如,20)
|
||||
- `%d` 月份的天(例如,01)
|
||||
- `%D` 日期;与 `%m/%d/%y` 相同
|
||||
- `%e` 月份的天,填充前缀空格;与 `%_d` 相同
|
||||
- `%F` 完整日期;与 `%Y-%m-%d` 相同
|
||||
- `%g` ISO 周号的年份的后两位数字(请参见 `%G`)
|
||||
- `%G` ISO 周号的年份(请参阅 `%V`);通常仅配合 `%V` 使用
|
||||
- `%h` 与 `%b` 相同
|
||||
- `%H` 24 小时制的小时(00..23)
|
||||
- `%I` 12 小时制的小时(01..12)
|
||||
- `%j` 一年的天(001..366)
|
||||
- `%k` 24 小时制的小时,填充前缀空格( 0..23);与 `%_H` 相同
|
||||
- `%l` 12 小时制的小时,填充前缀空格( 1..12);与 `%_I` 相同
|
||||
- `%m` 月份(01..12)
|
||||
- `%M` 分钟(00..59)
|
||||
- `%n` 换行符
|
||||
- `%N` 纳秒(000000000..999999999)
|
||||
- `%p` 本地语言环境中等同于 AM 或 PM 的字符串;如果未知,则为空白
|
||||
- `%P` 像 `%p`,但使用小写
|
||||
- `%q` 季度(1..4)
|
||||
- `%r` 本地语言环境的 12 小时制时间(例如,晚上 11:11:04 / 11:11:04 PM)
|
||||
- `%R` 24 小时制的小时和分钟;与 `%H:%M` 相同
|
||||
- `%s` 自 1970-01-01 00:00:00 UTC 以来的秒数
|
||||
- `%S` 秒(00..60)
|
||||
- `%t` 制表符
|
||||
- `%T` 时间;与 `%H:%M:%S` 相同
|
||||
- `%u` 星期(1..7);1 是星期一
|
||||
- `%U` 年的周号,以星期日为一周的第一天,从 00 开始(00..53)
|
||||
- `%V` ISO 周号,以星期一为一周的第一天,从 01 开始(01..53)
|
||||
- `%w` 星期(0..6);0 是星期日
|
||||
- `%W` 年的周号,星期一为一周的第一天,从 00 开始(00..53)
|
||||
- `%x` 本地语言环境的日期表示形式(例如,1999年12月31日 / 12/31/99)
|
||||
- `%X` 本地语言环境的时间表示形式(例如,23:13:48)
|
||||
- `%y` 年的最后两位数字(00..99)
|
||||
- `%Y` 年份
|
||||
- `%z` +hhmm 格式的数字时区(例如,-0400)
|
||||
- `%:z` +hh:mm 格式的数字时区(例如,-04:00)
|
||||
- `%::z` +hh:mm:ss 格式的数字时区(例如,-04:00:00)
|
||||
- `%:::z` 数字时区,`:` 指明精度(例如,-04, +05:30)
|
||||
- `%Z` 字母时区缩写(例如,EDT)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3481602/displaying-dates-and-times-your-way-with-linux.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][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://www.networkworld.com/author/Sandra-Henry_Stocker/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.networkworld.com/newsletters/signup.html
|
||||
[2]: 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)
|
||||
[3]: https://www.facebook.com/NetworkWorld/
|
||||
[4]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,240 @@
|
||||
自动共享和上传文件到兼容的托管站点
|
||||
======
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2017/10/Upload-720x340.png)
|
||||
|
||||
前阵子我们写了一个关于 [Transfer.sh][1]的指南,它允许你使用命令行通过互联网来分享文件。今天,我们来看看另一种文件分享实用工具 Anypaste。这是一个基于文件类型自动共享和上传文件到兼容托管站点的简单脚本。你不需要去手动登录到托管站点来上传或分享你的文件。Anypaste 将会根据你想上传的文件的类型来**自动挑选合适的托管站点**。简单地说,照片将被上传到图像托管站点,视频被传到视频站点,代码被传到 pastebin。难道不是很酷的吗?Anypaste 是一个完全开源、免费、轻量的脚本,你可以通过命令行完成所有操作。因此,你不需要依靠那些臃肿的、需要消耗大量内存的 GUI 应用来上传和共享文件。
|
||||
|
||||
### 安装
|
||||
|
||||
正如我所说,这仅仅是一个脚本。所以不存在任何复杂的安装步骤。只需要将脚本下载后放置在你想要运行的位置(例如 `/usr/bin/`),并将其设置为可执行文件后就可以直接使用了。此外,你也可以通过下面的这两条命令来快速安装 Anypaste。
|
||||
|
||||
```
|
||||
sudo curl -o /usr/bin/anypaste https://anypaste.xyz/sh
|
||||
sudo chmod +x /usr/bin/anypaste
|
||||
```
|
||||
|
||||
就是这样简单。如果需要更新老的 Anypaste 版本,只需要用新的可执行文件覆写旧的即可。
|
||||
|
||||
现在,让我们看看一些实例。
|
||||
|
||||
### 配置
|
||||
|
||||
Anypaste 开箱即用,并不需要特别的配置。默认的配置文件是 `~/.config/anypaste.conf`,这个文件在你第一次运行 Anypaste 时会自动创建。
|
||||
|
||||
需要配置的选项只有 `ap_plugins`。Anypaste 使用插件系统上传文件。每个站点(的上传)都由一个特定的插件表示。你可以在 `anypaste.conf` 文件中的 `ap-plugins directive` 位置浏览可用的插件列表。
|
||||
|
||||
```
|
||||
# List of plugins
|
||||
# If there are multiple compatible plugins, precedence is determined
|
||||
# by which one is listed first in this array
|
||||
ap_plugins=(
|
||||
# Videos/Gifs
|
||||
'sendvid' 'streamable' 'gfycat'
|
||||
# Images
|
||||
'tinyimg' 'vgyme'
|
||||
# Audio
|
||||
'instaudio'
|
||||
# Text
|
||||
'hastebin' 'ixio' 'sprunge'
|
||||
# Documents
|
||||
'docdroid'
|
||||
# Any file
|
||||
'jirafeau' 'fileio'
|
||||
)
|
||||
[...]
|
||||
```
|
||||
|
||||
如果你要安装一个新的插件,将它添加进这个列表中就可以了。如果你想禁用一个默认插件,只需要将它从列表中移除即可。如果有多个兼容的插件,排列中的第一个会被选择,因此**顺序很重要**。
|
||||
|
||||
### 用法
|
||||
|
||||
上传一个简单的文件,例如 `test.png`,可以运行以下命令:
|
||||
|
||||
```
|
||||
anypaste test.png
|
||||
```
|
||||
|
||||
输出示例:
|
||||
|
||||
```
|
||||
Current file: test.png
|
||||
Attempting to upload with plugin 'tinyimg'
|
||||
######################################################################## 100.0%
|
||||
|
||||
Direct Link: https://tinyimg.io/i/Sa1zsjj.png
|
||||
|
||||
Upload complete.
|
||||
All files processed. Have a nice day!
|
||||
```
|
||||
|
||||
正如输出结果中所看到的,Anypaste 通过自动匹配图像文件 `test.png` 发现了兼容的托管站点(https://tinyimg.io),并将文件上传到了该站点。此外,Anypaste 也为我们提供了用于直接浏览/下载该文件的链接。
|
||||
|
||||
不仅是 png 格式文件,你还可以上传任何其他图片格式的文件。例如,下面的命令将会上传 gif 格式文件:
|
||||
|
||||
```
|
||||
$ anypaste file.gif
|
||||
Current file: file.gif
|
||||
Plugin 'streamable' is compatible, but missing config parameters: 'streamable_email' 'streamable_password'
|
||||
You can set them in /home/sk/.config/anypaste.conf
|
||||
Attempting to upload with plugin 'gfycat'
|
||||
######################################################################## 100.0%
|
||||
Reminder: Gfycat needs time to encode. Your video will not appear right away.
|
||||
|
||||
Link: https://gfycat.com/MisguidedQuaintBergerpicard
|
||||
Direct(ish) Link: https://thumbs.gfycat.com/MisguidedQuaintBergerpicard-size_restricted.gif
|
||||
|
||||
Upload complete.
|
||||
All files processed. Have a nice day!
|
||||
```
|
||||
|
||||
你可以将链接分享给你的家庭、朋友和同事们。下图是我刚刚将图片上传到 gfycat 网站的截图。
|
||||
|
||||
![][3]
|
||||
|
||||
也可以一次同时上传多个(相同格式或不同格式)文件。
|
||||
|
||||
下面的例子提供参考,这里我会上传两个不同的文件,包含一个图片文件和一个视频文件:
|
||||
|
||||
```
|
||||
anypaste image.png video.mp4
|
||||
```
|
||||
|
||||
输出示例:
|
||||
|
||||
```
|
||||
Current file: image.png
|
||||
Attempting to upload with plugin 'tinyimg'
|
||||
######################################################################## 100.0%
|
||||
|
||||
Direct Link: https://tinyimg.io/i/au1PHpg.png
|
||||
|
||||
Upload complete.
|
||||
Current file: video.mp4
|
||||
Plugin 'streamable' is compatible, but missing config parameters: 'streamable_email' 'streamable_password'
|
||||
You can set them in /home/sk/.config/anypaste.conf
|
||||
Attempting to upload with plugin 'sendvid'
|
||||
######################################################################## 100.0%
|
||||
|
||||
Link: http://sendvid.com/wwy7w96h
|
||||
Delete/Edit: http://sendvid.com/wwy7w96h?secret=39c0af2d-d8bf-4d3d-bad3-ad37432a40a5
|
||||
|
||||
Upload complete.
|
||||
All files processed. Have a nice day!
|
||||
```
|
||||
|
||||
Anypaste 针对两个文件自动发现了与之相兼容的托管站点并成功上传。
|
||||
|
||||
正如你在上述用法介绍部分的例子中注意到的,Anypaste 会自动挑选最佳的插件。此外,你可以指定插件进行文件上传,这里提供一个上传到 gfycat 的案例,运行以下命令:
|
||||
|
||||
```
|
||||
anypaste -p gfycat file.gif
|
||||
```
|
||||
|
||||
输出示例:
|
||||
|
||||
```
|
||||
Current file: file.gif
|
||||
Plugin 'streamable' is compatible, but missing config parameters: 'streamable_email' 'streamable_password'
|
||||
You can set them in /home/sk/.config/anypaste.conf
|
||||
Attempting to upload with plugin 'gfycat'
|
||||
######################################################################## 100.0%
|
||||
Reminder: Gfycat needs time to encode. Your video will not appear right away.
|
||||
|
||||
Link: https://gfycat.com/GrayDifferentCollie
|
||||
Direct(ish) Link: https://thumbs.gfycat.com/GrayDifferentCollie-size_restricted.gif
|
||||
|
||||
Upload complete.
|
||||
All files processed. Have a nice day!
|
||||
```
|
||||
|
||||
如果要使用特定插件进行文件上传,可以通过以下命令绕过兼容性检查:
|
||||
|
||||
```
|
||||
anypaste -fp gfycat file.gif
|
||||
```
|
||||
|
||||
如果你发现在配置文件中忽略了特定的插件,你仍然可以强制 Anypaste 去使用特定的插件,只不过需要加上 `-xp` 参数。
|
||||
|
||||
```
|
||||
anypaste -xp gfycat file.gif
|
||||
```
|
||||
|
||||
如果想要以交互模式上传文件,可以在命令后加上 `-i` 标签:
|
||||
|
||||
```
|
||||
$ anypaste -i file.gif
|
||||
Current file: file.gif
|
||||
Determine compatible plugins automatically? [Y/n] **n**
|
||||
The following plugins were found: 'sendvid' 'streamable' 'gfycat' 'tinyimg' 'vgyme' 'instaudio' 'hastebin' 'ixio' 'sprunge' 'docdroid' 'jirafeau' 'fileio'
|
||||
|
||||
Enter the (partial) name of a plugin, or nothing for automatic selection
|
||||
**gfycat**
|
||||
Attempt to upload with plugin 'gfycat'? [Y/n] **y**
|
||||
Attempting to upload with plugin 'gfycat'
|
||||
######################################################################## 100.0%
|
||||
Reminder: Gfycat needs time to encode. Your video will not appear right away.
|
||||
|
||||
Link: https://gfycat.com/WaryAshamedBlackbear
|
||||
Direct(ish) Link: https://thumbs.gfycat.com/WaryAshamedBlackbear-size_restricted.gif
|
||||
|
||||
Upload complete.
|
||||
All files processed. Have a nice day!
|
||||
```
|
||||
|
||||
正如你所见,Anypaste 首先询问了我是否需要自动确定插件。因为我不想自动寻找插件,所以我回复了 “No”。之后,Anypaste 列出了所有可选择的插件,并要求我从列表中选择一个。同样的,你可以上传和共享不同类型的文件,相关文件会被上传到相兼容的站点。
|
||||
|
||||
无论你何时上传一个视频文件,Anypaste 都会将其上传到以下站点中的一个:
|
||||
|
||||
1. sendvid
|
||||
2. streamable
|
||||
3. gfycat
|
||||
|
||||
这里注意列表顺序,Anypaste 将首先将文件上传到 sendvid 站点,如果没有 sendvid 的插件可供使用,Anypaste 将会尝试顺序中的另外两个站点。当然你也可以通过更改配置文件来修改顺序。
|
||||
|
||||
图像文件上传站点:
|
||||
|
||||
1. tinyimg.io
|
||||
2. vgy.me
|
||||
|
||||
音频文件上传站点:
|
||||
|
||||
1. instaud
|
||||
|
||||
文本文件上传站点:
|
||||
|
||||
1. hastebin
|
||||
2. ix.io
|
||||
3. sprunge.us
|
||||
|
||||
文档上传站点:
|
||||
|
||||
1. docdroid
|
||||
|
||||
其他任意类型的文件上传站点:
|
||||
|
||||
1. jirafeau
|
||||
2. file.io
|
||||
|
||||
上面列出来的部分站点一段特定的时间后会删除上传的内容,所以在上传和分享内容时应先明确这些站点的条款和条件。
|
||||
|
||||
### 结论
|
||||
|
||||
在我看来,识别文件并决定将其上传到何处的想法非常棒,而且开发者也以恰当的方式完美地实现了它。毫无疑问,Anypaste 对那些在互联网上需要频繁分享文件的人们非常有用,我希望你也能这么觉得。
|
||||
|
||||
这就是今天的全部内容,后面会有越来越多的好东西分享给大家。再见啦!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/anypaste-share-upload-files-compatible-hosting-sites-automatically/
|
||||
|
||||
作者:[SK][a]
|
||||
译者:[lixin555](https://github.com/lixin555)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.ostechnix.com/author/sk/
|
||||
[1]:https://www.ostechnix.com/easy-fast-way-share-files-internet-command-line/
|
||||
[2]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[3]:http://www.ostechnix.com/wp-content/uploads/2017/10/gfycat.png
|
@ -0,0 +1,289 @@
|
||||
23 款开源的声音、视觉生产工具
|
||||
======
|
||||
|
||||
> 无论你是要进行音频、图形、视频、动画还是它们的任意组合,都有一个开源工具可以帮助你产生专业水平的结果。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/04/093037w8ab8v0voz0b5u88.jpg)
|
||||
|
||||
“开源”在云基础设施、网站托管、嵌入式设备和其他领域已经建立的相当完善。很少数人知道开源在生产专业级的声音视觉素材上也是一个不错的选择。
|
||||
|
||||
作为一名产品经理(有时候也是市场支持),我为终端用户提供很多内容:文档、文章、视频教学,甚至是展台物料、白皮书、采访等等。我找到了很多可以帮我制作音频、视频、排版、截屏的开源软件。人们选择开源软件而不是专有软件的[原因][1]有很多,而我也为以下人群编制了一份开源音视频工具清单:
|
||||
|
||||
* 想要入坑 GNU/Linux,但需要在原来的操作系统上慢慢从使用跨平台软件开始
|
||||
* 热爱开源,但对音视频开源软件所知甚少,不知道该如何选择
|
||||
* 想要为创造力充电而探索新的工具,并且不想使用其他人使用过的方法工具
|
||||
* 存在某些其他的原因使用开源音视频解决方案(如果是你,不妨在评论里分享一下)
|
||||
|
||||
幸运的是,存在着很多开源的音视频创作软件,也存在着很多硬件来支持这些应用。本文清单里的所有软件都符合以下标准:
|
||||
|
||||
* 跨平台
|
||||
* 开源(软件和驱动)
|
||||
* 稳定
|
||||
* 积极维护
|
||||
* 良好的文档与技术支持
|
||||
|
||||
我将清单中的解决方案划分为图形、音频、视频和动画。注意,本文中提到的应用程序并不完全等同于一些有名的私有软件,它们需要花时间来学习,并且可能需要改变你的工作流程,但是学习新的工具能够让体验全新的创造方式。
|
||||
|
||||
### 图形
|
||||
|
||||
我制作过很多出版和网站使用的图形,包括徽标、横幅、视频节目、草图。这里是一些我用过的开源应用,也包括一同使用的硬件。
|
||||
|
||||
#### 软件
|
||||
|
||||
**1、[Inkscape][2]**(矢量图)
|
||||
|
||||
Inkscape 是一款不错的矢量图编辑器,用来制作 RGB 颜色空间下的 SVG 和 PDF 文件。(它可以制作 CMYK 图像,但不是主要用途)它是为 web 应用制作 SVG 格式的地图和图表的人的救命稻草。你不仅可以使用集成的 XML 编辑器打开文件,也可以用它查看对象的所有参数。但有一个缺点:它在 Mac 上的优化不是很好。有很多样例,可以看[Inkscape 画廊][3]。
|
||||
|
||||
**2、[GIMP][4]**(图片编辑器)
|
||||
|
||||
GIMP 是我最喜欢的图片编辑程序,它包括了色彩调整、裁剪和拉伸,并且(尤其是)对于网页使用的文件大小进行了优化(很多使用 Photoshop 的同事让我帮他们做这最后一步)。你也可以从头制作并绘制一张图片,但 GIMP 并不是我最喜欢用来做这件事的工具。在 [GIMP Artists on DevianArt][5] 上查看众多的样例。
|
||||
|
||||
**3、[Krita][6]**(数字绘画)
|
||||
|
||||
当你桌子上摆着一个漂亮的 Wacom 数位板,你肯定想试试真正的数字绘画应用。Krita 就是你创作漂亮插画所需要的工具。在 [Krita 画廊][7] 里看看我说的东西吧。
|
||||
|
||||
**4、[Scribus][8]**(桌面印刷系统)
|
||||
|
||||
你可以使用 Scribus 来创建一个完整的文档,或者只是把用 Inkscape 或 Libre Office 制作的 PDF 从 RGB 转换到 CMYK。有一个功能我非常喜欢:你可以试着模拟视觉障碍人士使用 Scribus 时的体验。当我发送 PDF 文件给商业印刷公司时全指望 Scribus。尽管出版社可能使用像 InDesign 这样的私有软件创建文档,但如果你用 Scribus 正确的完成一份文档,那么打印时就不会出现任何问题。免费建议:第一次发送文件给印刷公司时,不要告诉印刷公司创建该文档所使用的软件。你可以在 [Scribus 教程][9]中寻找创建文档的例子。
|
||||
|
||||
**5、[RawTherapee][10]**(RAW 图像开发工具)
|
||||
|
||||
RawTherapee 是我所知道唯一跨平台可替代 Lightroom 的软件。你可以将相机调整到 RAW 模式,然后使用 RawTherapee 来修图。它提供了非常强大的引擎和对图片没有破坏的编辑器。例如,可以见 [Raw Therapee 截图][11]。
|
||||
|
||||
**6、[LibreOffice Draw][12]**(桌面印刷系统)
|
||||
|
||||
尽管你可能认为 LibraOffice Draw 不是一款专业的桌面印刷解决方案,但它仍然能够在很多情况下帮助你。例如,制作其他人(尽管是那些不懂图形软件的人)以后可以修改的白皮书、图表或海报。它不仅方便使用,而且当创建有趣的文档时也是 Impress 或 PowerPoint 的绝佳替代软件。
|
||||
|
||||
#### 图形硬件
|
||||
|
||||
**绘图板**
|
||||
|
||||
[Wacom][13] 数位板(和兼容设备)通常支持所有的操作系统。
|
||||
|
||||
**颜色校正**
|
||||
|
||||
颜色校正产品通常可用于所有操作系统,也包括了 GNU/Linux。Datacolor 生产的 [Spyder][14] 在所有平台上都有应用程序的支持。
|
||||
|
||||
**扫描仪和打印机**
|
||||
|
||||
图形艺术家需要输出(无论是打印还是电子版)的颜色是精确的。但是真正跨平台的设备,以及所有平台都易于安装的驱动,并不像你想的那样普遍。你的最佳选择是兼容 TWAIN 的扫描仪和兼容 Postscript 的打印机。以我的经验,Epson 和 Xerox 的专业级扫描仪和打印机更不容易出现驱动问题,并且它们通常也是开箱即用,拥有漂亮精确的颜色。
|
||||
|
||||
### 音频
|
||||
|
||||
有许多可供音乐家、视频制作者、游戏制作者、音乐出版商等等人群选择的开源音频软件。这里有一些我曾经用来进行内容创作与声音录制时所使用的软件。
|
||||
|
||||
#### 软件
|
||||
|
||||
**7、[Ardour][15]**(数字音频录制)
|
||||
|
||||
对录音与编辑来说,最专业级的工具选择当然是唾手可得的 Ardour。听起来很棒,它的混音部分非常的完整灵活,能够提供给你喜欢的插件,并且易于回放、编辑、对比修改。我经常用它进行声音录制和视频混音。要找出一些使用 Ardour 录制好的音乐并不容易,因为音乐家们很少表明他们使用的软件。然而,你可以查看它的[截图][16]和一些特性来了解它的功能。
|
||||
|
||||
(如果你在寻求一种声音制作方面的“模拟体验”,你可以试试 [Harrison Mixbus][17],它并不是一个开源项目,但是高度基于 Ardour,拥有模拟显示的终端。我非常喜欢用它进行工作,我的客户也喜欢用它制作的声音。Mixbus 也是跨平台的)
|
||||
|
||||
**8、[Audacity][18]** (声音编辑)
|
||||
|
||||
Audacity 属于“瑞士军刀”级的声音制作软件。它并不完美,但你几乎可以用它做所有的事情。加上非常易于使用,任何人都能在几分钟之内上手。像 Ardour 一样,很难找到一份归功于 Audacity 的作品,但你可以从这些[截图][19]中了解如何使用它。
|
||||
|
||||
**9、[LMMS][20]** (音乐制作)
|
||||
|
||||
LMMS,设计作为 FL Studio 的替代品,也许使用并不那么广泛,但它非常完整并易于使用。你可以使用自己最喜欢的插件,使用“钢琴键”编辑乐器,使用<ruby>步定序器<rt>step sequencer</rt></ruby>播放鼓点,混合音轨...几乎能做任何事情。在我没有时间为音乐家录音的时候我就使用它为视频创建声音片段。查看[最好的 LMMS][21] 榜单来看看一些例子。
|
||||
|
||||
**10、[Mixxx][22]** (DJ,音乐混音)
|
||||
|
||||
如果你需要强大的混音和播放 DJ 软件,Mixxx 就可以满足你的需求。它与大多数 MIDI 控制器、唱片、专用声卡所兼容。你可以用它管理音乐库、添加音效,做一些有趣的事情。查看它的[功能][23]来了解它是如何工作的。
|
||||
|
||||
#### 音频接口硬件
|
||||
|
||||
尽管你可以使用任何一个计算机的声卡录制音频,但要录制的很好,就需要一个音频接口——一个录制高质量音频输入的专用的外部声卡。对于跨平台兼容性来说,大多数“兼容 USB”和“兼容 iOS”的音频接口设备应该都能录制 MIDI 或其他音频。下面是一些我用过的一些有名气的跨平台设备。
|
||||
|
||||
**[Behringer U-PHORIA UMC22][24]**
|
||||
|
||||
UMC22 是你可以考虑的最便宜的选择。但它的前置放大器噪音太大,<ruby>音腔<rt>box</rt></ruby>质量也比较低。
|
||||
|
||||
**[Presonus AudioBox USB][25]**
|
||||
|
||||
AudioBox USB 是第一个兼容 USB(因此也跨平台)的录音系统。它非常的耐用,经常在二手市场也能见到。
|
||||
|
||||
**[Focusrite Scarlett][26]**
|
||||
|
||||
Scarlett 在我看来是目前最高质量的跨平台声卡。不同种类的设备可以涵盖 2-18 个输入/输出端口。你可以在二手市场找到它的最初版本,而最新的第二代具有更好的前置放大器与规格。[2i2][27] 型号是我经常使用的那一款。
|
||||
|
||||
**[Arturia AudioFuse][28]**
|
||||
|
||||
AudioFuse 几乎可以让你接入任何设备,从麦克风到黑胶唱片机再到各种数字输入设备。它具有优质的声音与良好的设计,也是我目前用的最多的一款设备。它是跨平台的,但目前配置软件还不能在 GUN/Linux 上使用。即使我把它从 Windows 电脑上断开,它仍然保留着我的配置。但是讲真,Arturia,劳烦认真考虑做一个 Linux 的软件。
|
||||
|
||||
#### MIDI 控制器
|
||||
|
||||
MIDI 控制器是一种乐器——例如电子琴、鼓垫等等。可以让你控制音乐软件或者硬件。现有的大多数 USB MIDI 控制器都跨平台并兼容主流的录音编辑软件。基于网页的教程可以帮你对不同的软件进行配置。尽管找到有关在 GNU/Linux 上配置的信息可能比较困难,但它们仍然是可以使用的。我用过许多 Akai 和 M-Audio 设备,没有任何问题。在买乐器之前最好先试一下,至少去听一下它们的音质或体验一下按键触感。
|
||||
|
||||
#### 音频编解码器
|
||||
|
||||
音频编解码器压缩或解压数字音频,用尽可能小的文件大小获得最佳质量的声音。幸运的是,用于收听或流媒体播放的编解码器恰好是开源的:[FLAC][29]。[Ogg Vorbis][30] 是另一个值得了解的开源音频编解码器;在相同的比特率下比 MP3 好的多。如果你需要输出不同的音频格式,我建议通常存档最好质量的音频,然后再压缩成特定的版本。
|
||||
|
||||
### 视频
|
||||
|
||||
视频对于品牌的传播是影响巨大的。即使你不是一个视频专家,学习一些基础的东西也是非常明智的。
|
||||
|
||||
#### 软件
|
||||
|
||||
**11、[VLC][31]** (视频播放器与转换器)
|
||||
|
||||
最初是为流媒体而开发的,VLC 现在因能够在所有设备上读取所有的视频格式被人们熟知。它非常的实用,例如,你可以使用它将视频转换成其他编解码格式或容器,也可以用来恢复破损的视频。
|
||||
|
||||
**12、[OpenShot][32]** (视频编辑)
|
||||
|
||||
OpenShot 是一个简单的软件,但它却可以制作出很好的效果,尤其是在短视频上。(在编辑或改善音质方面有一定的限制,但它也能够完成)我非常喜欢它的移动、拉伸、裁剪工具;用它创建视频的开头或结尾,导出之后使用更复杂的编辑器进行编辑,非常的完美。你可以在 OpenShot 的网站上看这些[例子][33](并获取更多信息)。
|
||||
|
||||
**13、[Shotcut][34]** (视频编辑)
|
||||
|
||||
我认为 Shotcut 是比 OpenShot 更完整一些的工具——它在你的操作系统上比起其他较为基础的编辑器更具有竞争力,并且它支持 4K 分辨率,具有专业的解码器。尝试一下,我相信你会爱上它的。你可以在这些[视频教程][35]里看一些范例。
|
||||
|
||||
**14、[Blender Velvets][36]** (视频编辑、合成、特效)
|
||||
|
||||
尽管这一章节不是本文的学习重点,但 Blender Velvets 是你能找到的最强大的解决方案之一。它是由一些视频创作者所制作的一系列扩展工具和脚本的合集,是通过 Blender 3D 制作软件转换成的 2D 视频编辑器。尽管它的复杂度意味着不是我的首选视频编辑器,但你仍可以在 YouTube 和其他网站上找到它的教程,并且一旦你学习了它,你就能通过它做任何事情。观看这个[视频教程][37]来了解它的功能与运作方式。
|
||||
|
||||
**15、[Natron][38]**(合成)
|
||||
|
||||
我不使用 Natron,但我听说它广受好评。它是 Adobe After Effects 的替代品,但运作方式并不同。想了解更多可以观看一些视频教程,比如这些 Natron 的 [YouTube 频道][39]。
|
||||
|
||||
**16、[OBS][40]** (实时编辑、录制、流媒体)
|
||||
|
||||
Open Broadcaster Software(OBS)是一个领先的在 YouTube 或 Twitch 上进行现场录制或现场直播电子竞技、电视游戏的解决方案。我经常使用它记录用户的屏幕、会议和聚会。要获取更多信息,查看我曾经在 Opensource.com 上写的关于录制现场汇报的教程,[第一部分:选择你的设备][42]和[第二部分:软件安装][43]。
|
||||
|
||||
#### 视频硬件
|
||||
|
||||
结论先行:你需要一个强大的工作站以及快速的硬盘和更新的软件和驱动。
|
||||
|
||||
**图形处理单元(GPU)**
|
||||
|
||||
一部分包含在清单里的软件比如 Blender 和 Shotcut 使用 OpenGL 和硬件加速,这些都高度依赖 GPU。我建议你使用可以负担起的最强大的 GPU。我所使用过的 AMD 和 Nvidia 都有着良好的体验,这取决于使用的平台。不要忘记安装最新的驱动。
|
||||
|
||||
**硬盘**
|
||||
|
||||
大体上来说,越快越大的硬盘,对视频越好。不要忘记在软件里配置好正确的路径。
|
||||
|
||||
**视频录制硬件**
|
||||
|
||||
* [Blackmagic Design][44]: Blackmagic 提供了非常好的、专业级的视频录制和回放硬件。驱动支持 Mac、Windows 和 GNU/Linux(但不是所有的发行版)
|
||||
* [Epiphan][45]: 在 Epiphan 的专业级 USB 视频录制设备中有一款新型产品,它适用于 HDMI 和高分辨率的屏幕。然而,你也可以在二手市场找到旧的 VGA 设备,因为他们还在继续为 GNU/Linux 和 Windows 上提供专用的驱动程序。
|
||||
|
||||
#### 视频编解码
|
||||
|
||||
不幸的是,使用开源的编解码器仍然很困难。例如,许多相机使用专有的编解码器录制 H.264 的视频和 AC3 的音频,组成称为 AVCHD 的格式。因此,我们必须务实,尽可能利用现有资源。
|
||||
|
||||
好消息是内容产业正在步向开源的编解码器来避免一些费用,并使用开源标准。对于出版和流媒体,[谷歌][46]的 [WebM][46] 便是一款优秀的开源编解码器,并且大多数视频编辑器可以导入这种格式。同样地, [GoPro][47]的超高分辨率和 360° 视频编解码器 [Cineform][47] 现在也进行了开源。希望更多的设备和供应商将会在不久之后使用它。
|
||||
|
||||
### 2D 和 3D 动画
|
||||
|
||||
动画不是我的专业领域,因此我问了从事于动画内容生产的朋友一些建议并加入到清单中,他的工作包含儿童电影和连续剧。
|
||||
|
||||
#### 软件
|
||||
|
||||
**17、[Blender][48]** (3D 模型和渲染)
|
||||
|
||||
Blender 是顶级的开源跨平台 3D 建模和渲染软件。你可以直接在 Blender 中完成整个项目的工作,或者使用它为电影或视频创建 3D 效果。你能够在网上找到许多视频教程,因此即使它不是一个简单的软件,但也非常容易上手。Blender 是一个非常活跃的项目,经常还会制作一些微电影来展示他们的技术。你可以在 [Blender Open Movies][49] 上观看。
|
||||
|
||||
**18、[Synfig Studio][50]** (2D 动画)
|
||||
|
||||
第一次用 Synfig 时,它让我想起了那个不错的 Macromedia 老式 Flash 编辑器。在那之后,它已经发展成一个全功能的 2D 动画工作室。你可以使用它制作宣传故事、商业广告、演示、开场或结尾动画以及视频中的转场,或者甚至用它制作全动画的电影。见 [Synfig 作品集][51]。
|
||||
|
||||
**19、[TupiTube][52]** (定格 2D 动画)
|
||||
|
||||
使用 TupiTube 是一个学习基本 2D 动画的极好方法。你可以将一系列绘画或其他图片转换成一个视频或者创建一个 GIF 循环动画。它是一个相当简单的软件,但非常完整。查看 [TupiTude 的 YouTube][53] 频道获取一些教程和范例。
|
||||
|
||||
#### 硬件
|
||||
|
||||
动画制作使用与图形设计相同的硬件,因此查看第一小结中的硬件清单获取一些建议。
|
||||
|
||||
有一点需要注意:你要用一个强大的 GPU 来进行 3D 建模和渲染。选择可能有些限制,因为这取决于你使用的平台或电脑制造商,但是不要忘记安装最新的驱动。谨慎选择你的显卡:它们非常昂贵,并且在大型的 3D 项目中至关重要,尤其是在渲染步骤中。
|
||||
|
||||
### Linux 上的选择
|
||||
|
||||
如果你是 GUN/Linux 用户,那么我为你提供了更多不错的选择。它们并不是完全跨平台的,但部分拥有 Windows 版本,还有一些可以在 Mac 上使用 Macports 安装。
|
||||
|
||||
**20、[Kdenlive][54]** (视频编辑)
|
||||
|
||||
伴随着最新版本的发布(几个月之前),Kdenlive 成为了我最喜欢的视频编辑器,尤其是当我在 Linux 机器上处理一些长视频的时候。如果你经常使用流行的非线性视频编辑器,Kdenlive(全称是 <ruby>KDE 非线性视频编辑器<rt>KDE Non-Linear Video Editor</rt></ruby>)对你来说将非常简单。它拥有很棒的视频和音频特效,强大的细节处理能力。并且在 BSD 和 MacOS(尽管它对准的是 GNU/Linux)都能使用,还有望移植到 Windows 上。
|
||||
|
||||
**21、[Darktable][55]** (RAW 图像开发)
|
||||
|
||||
Darktable 是一款由摄影师制作的非常完整的 DxO PhotoLab 替代品。一些研究型项目使用它当做开发平台并测试一些图像处理算法。它是一个非常活跃的项目,我已经等不及的见到它的跨平台版本了。
|
||||
|
||||
**22、[MyPaint][56]** (digital painting数字绘画)
|
||||
|
||||
MyPaint 就像数字绘画领域的 light table(LCTT 译注:集成开发环境)。它在 Wacom 设备上表现良好,并且它的笔刷引擎尤其值得赞赏,因此 GIMP 开发人员正在密切的关注它。
|
||||
|
||||
**23、[Shutter][57]** (桌面截图)
|
||||
|
||||
当我写这篇教程的时候,我使用了许多截图来进行展示。我最喜欢的 GNU/Linux 截图工具就是 Shutter。事实上,我都找不到在 Windows 或 Mac 上能与之抗衡的一些功能。有一点小遗憾:我很期待 Shutter 在将来能够增加新的功能来创建几秒动态的 GIF 截图。
|
||||
|
||||
我希望这些足以说服你开源软件是一种非常卓越且可行的音视频内容生产解决方案。如果你正在使用其他开源软件,或者对于使用跨平台软件和硬件进行音视频项目有好的建议,请在评论中分享你的观点。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/2/open-source-audio-visual-production-tools
|
||||
|
||||
作者:[Antoine Thomas][a]
|
||||
译者:[LuuMing](https://github.com/LuuMing)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/ttoine
|
||||
[1]:https://opensource.com/resources/what-open-source
|
||||
[2]:https://inkscape.org/
|
||||
[3]:https://inkscape.org/en/gallery/
|
||||
[4]:https://www.gimp.org/
|
||||
[5]:https://gimp-artists.deviantart.com/gallery/
|
||||
[6]:https://krita.org/
|
||||
[7]:https://krita.org/en/features/gallery/
|
||||
[8]:https://www.scribus.net/
|
||||
[9]:https://www.scribus.net/category/made-with-scribus/
|
||||
[10]:http://rawtherapee.com/
|
||||
[11]:http://rawtherapee.com/blog/screenshots
|
||||
[12]:https://www.libreoffice.org/discover/draw/
|
||||
[13]:http://www.wacom.com/en-us
|
||||
[14]:http://www.datacolor.com/photography-design/product-overview/#workflow_2
|
||||
[15]:https://www.ardour.org/
|
||||
[16]:http://ardour.org/features.html
|
||||
[17]:http://harrisonconsoles.com/site/mixbus.html
|
||||
[18]:http://www.audacityteam.org/
|
||||
[19]:http://www.audacityteam.org/about/screenshots/
|
||||
[20]:https://lmms.io/
|
||||
[21]:https://lmms.io/showcase/
|
||||
[22]:https://www.mixxx.org/
|
||||
[23]:https://www.mixxx.org/features/
|
||||
[24]:http://www.musictri.be/Categories/Behringer/Computer-Audio/Interfaces/UMC22/p/P0AUX
|
||||
[25]:https://www.presonus.com/products/audiobox-usb
|
||||
[26]:https://us.focusrite.com/scarlett-range
|
||||
[27]:https://us.focusrite.com/usb-audio-interfaces/scarlett-2i2
|
||||
[28]:https://www.arturia.com/products/audio/audiofuse/overview
|
||||
[29]:https://en.wikipedia.org/wiki/FLAC
|
||||
[30]:https://xiph.org/vorbis/
|
||||
[31]:https://www.videolan.org/
|
||||
[32]:https://www.openshot.org/
|
||||
[33]:https://www.openshot.org/videos/
|
||||
[34]:https://shotcut.com/
|
||||
[35]:https://shotcut.org/tutorials/
|
||||
[36]:http://blendervelvets.org/
|
||||
[37]:http://blendervelvets.org/video-tutorial-new-functions-for-the-blender-velvets/
|
||||
[38]:https://natron.fr/
|
||||
[39]:https://www.youtube.com/playlist?list=PL2n8LbT_b5IeMwi3AIzqG4Rbg8y7d6Amk
|
||||
[40]:https://obsproject.com/
|
||||
[41]:https://opensource.com/article/17/7/obs-studio-pro-level-streaming
|
||||
[42]:https://opensource.com/article/17/9/equipment-recording-presentations
|
||||
[43]:https://opensource.com/article/17/9/equipment-setup-live-presentations
|
||||
[44]:https://www.blackmagicdesign.com/
|
||||
[45]:https://www.epiphan.com/
|
||||
[46]:https://www.webmproject.org/
|
||||
[47]:https://fr.gopro.com/news/gopro-open-sources-the-cineform-codec
|
||||
[48]:https://www.blender.org/
|
||||
[49]:https://www.blender.org/about/projects/
|
||||
[50]:https://www.synfig.org/
|
||||
[51]:https://www.synfig.org/#portfolio
|
||||
[52]:https://maefloresta.com/
|
||||
[53]:https://www.youtube.com/channel/UCBavSfmoZDnqZalr52QZRDw
|
||||
[54]:https://kdenlive.org/
|
||||
[55]:https://www.darktable.org/
|
||||
[56]:http://mypaint.org/
|
||||
[57]:http://shutter-project.org/
|
@ -0,0 +1,95 @@
|
||||
全球化思考:怎样克服交流中的文化差异
|
||||
======
|
||||
|
||||
> 这有一些建议帮助你的全球化开发团队能够更好地理解你们的讨论并能参与其中。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/people_remote_teams_world.png?itok=_9DCHEel)
|
||||
|
||||
几周前,我见证了两位同事之间一次有趣的互动,他们分别是 Jason,我们的一位美国员工,和 Raj,一位来自印度的访问工作人员。
|
||||
|
||||
Raj 在印度时,他一般会通过电话参加美国中部时间上午 9 点的每日立会,现在他到美国工作了,就可以和组员们坐在同一间会议室里开会了。Jason 拦下了 Raj,说:“Raj 你要去哪?你不是一直和我们开电话会议吗?你突然出现在会议室里我还不太适应。” Raj 听了说,“是这样吗?没问题。”就回到自己工位前准备和以前一样参加电话会议了。
|
||||
|
||||
我去找 Raj,问他为什么不去参加每日立会,Raj 说 Jason 让自己给组员们打电话参会,而与此同时,Jason 也在会议室等着 Raj 来参加立会。
|
||||
|
||||
到底是哪里出的问题?Jason 明显只是调侃 Raj 终于能来一起开会了,为什么 Raj 没能听懂呢?
|
||||
|
||||
Jason 明显是在开玩笑,但 Raj 把它当真了。这就是在两人互相不了解对方文化语境时发生的一个典型误会。
|
||||
|
||||
我经常会遇到有人在电子邮件的末尾写“请复原”,最开始我很迷惑,“这有什么需要我复原的内容?”后来我才搞懂,“请复原”其实是“请回复”的意思。
|
||||
|
||||
在 Ricardo Fernandez 的TED 演讲“[如何管理跨文化团队][1]” 中,他提到了自己与一位南非同事发生的小故事。那位同事用一句“我一会给你打电话。”结束了两人的 IM 会话,Ricardo 回到办公室后就开始等这位同事的电话,十五分钟后他忍不住主动给这位同事打了电话,问他:“你不是说要给我打电话吗?”,这位同事答到:“是啊,我是说以后有机会给你打电话。”这时 Ricardo 才理解那位同事说的“一会”是“以后”的意思。
|
||||
|
||||
现在是全球化时代,我们的同事很可能不跟我们面对面接触,甚至不在同一座城市,来自不同的国家。越来越多的技术公司拥有全球化的工作场所,和来自世界各地的员工,他们有着不同的背景和经历。这种多样性使得技术公司能够在这个快速发展的科技大环境下拥有更强的竞争力。
|
||||
|
||||
但是这种地域的多样性也会给团队带来挑战。管理和维持高性能的团队发展对于同地协作的团队来说就有着很大难度,对于有着多样背景成员的全球化团队来说,无疑更加困难。成员之间的交流会发生延迟,误解时有发生,成员之间甚至会互相怀疑,这些都会影响着公司的成功。
|
||||
|
||||
到底是什么因素让全球化交流间发生误解呢?我们可以参照 Erin Meyer 的书《[文化地图][2]》,她在书中将全球文化分为八个类型,其中美国文化被分为低语境文化,与之相对的,日本为高语境文化。
|
||||
|
||||
看到这里你可能会问,高、低语境文化到底是什么意思?美国人从小就教育孩子们简洁表达,“直言不讳”是他们的表达准则;另一边,日本人从小学习在高效处理社交线索的同时进行交流,“察言观色”是他们的交流习惯。
|
||||
|
||||
大部分亚洲国家的文化都属于高语境文化。作为一个年轻的移民国家,美国毫不意外地拥有着低语境文化。移民来自于世界各地,拥有着不同的文化背景,他们不得不选择简洁而直接的交流方式,这或许就是其拥有低语境文化的原因。
|
||||
|
||||
### 从文化语境的角度与异国同事交流的三个步骤:
|
||||
|
||||
怎样面临跨文化交流中遇到的挑战?比如说一位美国人与他的日本同事交流,他更应该注重日本同事的非语言线索,同样的日本同事应当更关注美国人直接表达出的信息。如果你也面临类似的挑战,按照下面这三个步骤做,可以帮助你更有效地和异国同事交流,增进与他们的感情。
|
||||
|
||||
#### 认识到文化语境的差异
|
||||
|
||||
跨文化交流的第一步是认识到文化差异,跨文化交流从认识其他文化开始。
|
||||
|
||||
#### 尊重文化语境的差异
|
||||
|
||||
一旦你意识到了文化语境的差异会影响跨文化交流,你要做的就是尊重这些差异。在你遇到一种不同的交流方式时,学会接受差异,学会积极听取他人意见。
|
||||
|
||||
#### 调和文化语境的差异
|
||||
|
||||
只是认识和尊重差异还远远不够,你还需要学会如何调和这些差异。互相理解和换位思考可以增进差异的调和,你还要学着用它们去提高同事间的交流效率,推动生产力。
|
||||
|
||||
### 五种促进不同文化语境间交流的方法
|
||||
|
||||
为了加强组员们之间关系,这么多年来我一直在收集各种各样的方法和建议。这些方法帮助我解决了与外国组员间产生的很多交流问题,下面有其中一些例子:
|
||||
|
||||
#### 与外国组员交流时尽量使用视频会议的形式
|
||||
|
||||
研究表明,交流中约 55% 的内容不是靠语言传递的。肢体语言传达着一种十分微妙的信息,你可以根据它们理解对方的意思,而视频会议中处于异地的组员们能够看到对方的肢体语言。因此,组织远程会议时我一般都会采用视频会议的形式。
|
||||
|
||||
#### 确保每位成员都有机会分享他们的想法
|
||||
|
||||
我虽然喜欢开视频会议,但不是每次都能开的成。如果视频会议对你的团队来说并不常用,大家可能要一些时间去适应,你需要积极鼓励大家参与到其中,先从进行语音会议开始。
|
||||
|
||||
我们有一个外地的组员,每次都和我们进行语音会议,和我们提到她经常会有些想法想要分享,或者想做些贡献,但是我们互相看不到,她不知道该怎样开口。如果你一直在进行语音会议,注意要给组员们足够的时间和机会分享他们的想法。
|
||||
|
||||
#### 互相学习
|
||||
|
||||
通过你身边一两名外国朋友来学习他们的文化,你可以把从一位同事身上学到的应用于所有来自这个国家的同事。我有几位南亚和南美的同事,他们帮助我理解他们的文化,而这些也使得我更加专业。
|
||||
|
||||
对编程人员来说,我建议请你全世界的同行们检查你的代码,这个过程能让你观察到其他文化中人们怎样进行反馈、劝说他人,和最终进行技术决策。
|
||||
|
||||
#### 学会感同身受
|
||||
|
||||
同理心是一段牢固关系的核心。你越能换位思考,就越容易获得信任,来建立长久的关系。你可以在每次会议开始之前和大家闲聊几句,这样大家更容易处于一个放松的状态,如果团队中有很多外国人,要确保大家都能参与进来。
|
||||
|
||||
#### 和你的外国同事们单独见面
|
||||
|
||||
保持长久关系最好的方法是和你的组员们单独见面。如果你的公司可以报销这些费用,那么努力去和组员们见面吧。和一起工作了很长时间的组员们见面能够使你们的关系更加坚固。我所在的公司就有着周期性交换员工的传统,每隔一段时间,世界各地的员工就会来到美国工作,美国员工再到其他分部工作。
|
||||
|
||||
另一种聚齐组员们的机会是研讨会。研讨会创造的不仅是学习和培训的机会,你还可以挤出一些时间和组员们培养感情。
|
||||
|
||||
在如今,全球化经济不断发展,拥有来自不同国家和地区的员工对维持一个公司的竞争力来说越来越重要。即使组员们来自世界各地,团队中会出现一些交流问题,但拥有一支国际化的高绩效团队不是问题。如果你在工作中有什么促进团队交流的小窍门,请在评论中告诉我们吧。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/10/think-global-communication-challenges
|
||||
|
||||
作者:[Avindra Fernando][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Valoniakim](https://github.com/Valoniakim)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/avindrafernando
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.youtube.com/watch?v=QIoAkFpN8wQ
|
||||
[2]: https://www.amazon.com/The-Culture-Map-Invisible-Boundaries/dp/1610392507
|
@ -0,0 +1,247 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11691-1.html)
|
||||
[#]: subject: (Easily Upload Text Snippets To Pastebin-like Services From Commandline)
|
||||
[#]: via: (https://www.ostechnix.com/how-to-easily-upload-text-snippets-to-pastebin-like-services-from-commandline/)
|
||||
[#]: author: (SK https://www.ostechnix.com/author/sk/)
|
||||
|
||||
从命令行轻松将文本片段上传到类似 Pastebin 的服务中
|
||||
======
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2018/12/wgetpaste-720x340.png)
|
||||
|
||||
每当需要在线共享代码片段时,我们想到的第一个便是 Pastebin.com,这是 Paul Dixon 于 2002 年推出的在线文本共享网站。现在,有几种可供选择的文本共享服务可以上传和共享文本片段、错误日志、配置文件、命令输出或任何类型的文本文件。如果你碰巧经常使用各种类似于 Pastebin 的服务来共享代码,那么这对你来说确实是个好消息。向 Wgetpaste 打个招呼吧,它是一个命令行 BASH 实用程序,可轻松地将文本摘要上传到类似 Pastebin 的服务中。使用 Wgetpaste 脚本,任何人都可以与自己的朋友、同事或想在类似 Unix 的系统中的命令行中查看/使用/审查代码的人快速共享文本片段。
|
||||
|
||||
### 安装 Wgetpaste
|
||||
|
||||
Wgetpaste 在 Arch Linux [Community] 存储库中可用。要将其安装在 Arch Linux 及其变体(如 Antergos 和 Manjaro Linux)上,只需运行以下命令:
|
||||
|
||||
```
|
||||
$ sudo pacman -S wgetpaste
|
||||
```
|
||||
|
||||
对于其他发行版,请从 [Wgetpaste 网站][1] 获取源代码,并按如下所述手动安装。
|
||||
|
||||
首先下载最新的 Wgetpaste tar 文件:
|
||||
|
||||
```
|
||||
$ wget http://wgetpaste.zlin.dk/wgetpaste-2.28.tar.bz2
|
||||
```
|
||||
|
||||
提取它:
|
||||
|
||||
```
|
||||
$ tar -xvjf wgetpaste-2.28.tar.bz2
|
||||
```
|
||||
|
||||
它将 tar 文件的内容提取到名为 `wgetpaste-2.28` 的文件夹中。
|
||||
|
||||
转到该目录:
|
||||
|
||||
```
|
||||
$ cd wgetpaste-2.28/
|
||||
```
|
||||
|
||||
将 `wgetpaste` 二进制文件复制到 `$PATH` 中,例如 `/usr/local/bin/`。
|
||||
|
||||
```
|
||||
$ sudo cp wgetpaste /usr/local/bin/
|
||||
```
|
||||
|
||||
最后,使用命令使其可执行:
|
||||
|
||||
```
|
||||
$ sudo chmod +x /usr/local/bin/wgetpaste
|
||||
```
|
||||
|
||||
### 将文本片段上传到类似 Pastebin 的服务中
|
||||
|
||||
使用 Wgetpaste 上传文本片段很简单。让我向你展示一些示例。
|
||||
|
||||
#### 1、上传文本文件
|
||||
|
||||
要使用 Wgetpaste 上传任何文本文件,只需运行:
|
||||
|
||||
```
|
||||
$ wgetpaste mytext.txt
|
||||
```
|
||||
|
||||
此命令将上传 `mytext.txt` 文件的内容。
|
||||
|
||||
示例输出:
|
||||
|
||||
```
|
||||
Your paste can be seen here: https://paste.pound-python.org/show/eO0aQjTgExP0wT5uWyX7/
|
||||
```
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2018/12/wgetpaste-1.png)
|
||||
|
||||
你可以通过邮件、短信、whatsapp 或 IRC 等任何媒体共享 pastebin 的 URL。拥有此 URL 的人都可以访问它,并在他们选择的 Web 浏览器中查看文本文件的内容。
|
||||
|
||||
这是 Web 浏览器中 `mytext.txt` 文件的内容:
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2018/12/wgetpaste-2.png)
|
||||
|
||||
你也可以使用 `tee` 命令显示粘贴的内容,而不是盲目地上传它们。
|
||||
|
||||
为此,请使用如下的 `-t` 选项。
|
||||
|
||||
```
|
||||
$ wgetpaste -t mytext.txt
|
||||
```
|
||||
|
||||
![][3]
|
||||
|
||||
#### 2、将文字片段上传到其他服务
|
||||
|
||||
默认情况下,Wgetpaste 会将文本片段上传到 poundpython(<https://paste.pound-python.org/>)服务。
|
||||
|
||||
要查看支持的服务列表,请运行:
|
||||
|
||||
```
|
||||
$ wgetpaste -S
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
```
|
||||
Services supported: (case sensitive):
|
||||
Name: | Url:
|
||||
=============|=================
|
||||
bpaste | https://bpaste.net/
|
||||
codepad | http://codepad.org/
|
||||
dpaste | http://dpaste.com/
|
||||
gists | https://api.github.com/gists
|
||||
*poundpython | https://paste.pound-python.org/
|
||||
```
|
||||
|
||||
在这里,`*` 表示默认服务。
|
||||
|
||||
如你所见,Wgetpaste 当前支持五种文本共享服务。我并没有全部尝试,但是我相信所有服务都可以使用。
|
||||
|
||||
要将内容上传到其他服务,例如 bpaste.net,请使用如下所示的 `-s` 选项。
|
||||
|
||||
```
|
||||
$ wgetpaste -s bpaste mytext.txt
|
||||
Your paste can be seen here: https://bpaste.net/show/5199e127e733
|
||||
```
|
||||
|
||||
#### 3、从标准输入读取输入
|
||||
|
||||
Wgetpaste 也可以从标准输入读取。
|
||||
|
||||
```
|
||||
$ uname -a | wgetpaste
|
||||
```
|
||||
|
||||
此命令将上传 `uname -a` 命令的输出。
|
||||
|
||||
#### 4、上传命令及命令的输出
|
||||
|
||||
有时,你可能需要粘贴命令及其输出。为此,请在如下所示的引号内指定命令的内容。
|
||||
|
||||
```
|
||||
$ wgetpaste -c 'ls -l'
|
||||
```
|
||||
|
||||
这会将命令 `ls -l` 及其输出上传到 pastebin 服务。
|
||||
|
||||
当你想让其他人清楚地知道你刚运行的确切命令及其输出时,此功能很有用。
|
||||
|
||||
![][4]
|
||||
|
||||
如你在输出中看到的,我运行了 `ls -l` 命令。
|
||||
|
||||
#### 5、上载系统日志文件、配置文件
|
||||
|
||||
就像我已经说过的,我们可以上载你的系统中任何类型的文本文件,而不仅仅是普通的文本文件,例如日志文件、特定命令的输出等。例如,你刚刚更新了 Arch Linux 机器,最后系统损坏了。你问你的同事该如何解决此问题,他(她)想阅读 `pacman.log` 文件。 这是上传 `pacman.log` 文件内容的命令:
|
||||
|
||||
```
|
||||
$ wgetpaste /var/log/pacman.log
|
||||
```
|
||||
|
||||
与你的同事共享 pastebin URL,以便他/她可以查看 `pacman.log`,并通过查看日志文件来帮助你解决问题。
|
||||
|
||||
通常,日志文件的内容可能太长,你不希望全部共享它们。在这种情况下,只需使用 `cat` 命令读取输出,然后使用 `tail -n` 命令定义要共享的行数,最后将输出通过管道传递到 Wgetpaste,如下所示。
|
||||
|
||||
```
|
||||
$ cat /var/log/pacman.log | tail -n 50 | wgetpaste
|
||||
```
|
||||
|
||||
上面的命令将仅上传 `pacman.log` 文件的“最后 50 行”。
|
||||
|
||||
#### 6、将输入网址转换为短链接
|
||||
|
||||
默认情况下,Wgetpaste 将在输出中显示完整的 pastebin URL。如果要将输入 URL 转换为短链接,只需使用 `-u` 选项。
|
||||
|
||||
```
|
||||
$ wgetpaste -u mytext.txt
|
||||
Your paste can be seen here: http://tinyurl.com/y85d8gtz
|
||||
```
|
||||
|
||||
#### 7、设定语言
|
||||
|
||||
默认情况下,Wgetpaste 将上传“纯文本”中的文本片段。
|
||||
|
||||
要列出指定服务支持的语言,请使用 `-L` 选项。
|
||||
|
||||
```
|
||||
$ wgetpaste -L
|
||||
```
|
||||
|
||||
该命令将列出默认服务(poundpython <https://paste.pound-python.org/>)支持的所有语言。
|
||||
|
||||
我们可以使用 `-l` 选项来改变它。
|
||||
|
||||
```
|
||||
$ wgetpaste -l Bash mytext.txt
|
||||
```
|
||||
|
||||
#### 8、在输出中禁用语法突出显示或 html
|
||||
|
||||
如上所述,文本片段将以特定的语言格式(纯文本、Bash 等)显示。
|
||||
|
||||
但是,你可以更改此行为,以使用 `-r` 选项显示原始文本摘要。
|
||||
|
||||
```
|
||||
$ wgetpaste -r mytext.txt
|
||||
Your raw paste can be seen here: https://paste.pound-python.org/raw/CUJhQ3jEmr2UvfmD2xCL/
|
||||
```
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2018/12/wgetpaste-5.png)
|
||||
|
||||
如你在上面的输出中看到的,没有语法突出显示,没有 html 格式。只是原始输出。
|
||||
|
||||
#### 9、更改 Wgetpaste 默认值
|
||||
|
||||
所有默认值(`DEFAULT_{NICK,LANGUAGE,EXPIRATION}[_${SERVICE}]` 和 `DEFAULT_SERVICE`)都可以在 `/etc/wgetpaste.conf` 中全局更改,也可以在 `~/.wgetpaste.conf` 文件中针对每个用户更改。但是,这些文件在我的系统中默认情况下并不存在。我想我们需要手动创建它们。开发人员已经在[这里][5]和[这里][6]为这两个文件提供了示例内容。只需使用给定的样本内容手动创建这些文件,并相应地修改参数即可更改 Wgetpaste 的默认设置。
|
||||
|
||||
#### 10、获得帮助
|
||||
|
||||
要显示帮助部分,请运行:
|
||||
|
||||
```
|
||||
$ wgetpaste -h
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-easily-upload-text-snippets-to-pastebin-like-services-from-commandline/
|
||||
|
||||
作者:[SK][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://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://wgetpaste.zlin.dk/
|
||||
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[3]: http://www.ostechnix.com/wp-content/uploads/2018/12/wgetpaste-3.png
|
||||
[4]: http://www.ostechnix.com/wp-content/uploads/2018/12/wgetpaste-4.png
|
||||
[5]: http://wgetpaste.zlin.dk/zlin.conf
|
||||
[6]: http://wgetpaste.zlin.dk/wgetpaste.example
|
@ -0,0 +1,207 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11711-1.html)
|
||||
[#]: subject: (Install Android 8.1 Oreo on Linux To Run Apps & Games)
|
||||
[#]: via: (https://fosspost.org/tutorials/install-android-8-1-oreo-on-linux)
|
||||
[#]: author: (Python Programmer;Open Source Software Enthusiast. Worked On Developing A Lot Of Free Software. The Founder Of Foss Post;Foss Project. Computer Science Major. )
|
||||
|
||||
在 Linux 上安装安卓 8.1 Oreo 来运行应用程序和游戏
|
||||
======
|
||||
|
||||
![](https://i2.wp.com/fosspost.org/wp-content/uploads/2019/02/android-8.1-oreo-x86-on-linux.png?resize=1237%2C527&ssl=1)
|
||||
|
||||
[android x86][1] 是一个自由而开源的项目,将谷歌制作的安卓系统从 ARM 架构移植到了 x86 架构,可以让用户在他们的桌面电脑上运行安卓系统来享受所有的安卓功能和应用程序及游戏。
|
||||
|
||||
在前一段时间,android x86 项目完成了安卓 8.1 Oreo 系统的 x86 架构移植。在这篇文章中,我们将解释如何在你的 Linux 系统上安装它,以便你能够随时使用你的安卓 用程序和游戏。
|
||||
|
||||
### 在 Linux 上安装安卓 x86 8.1 Oreo
|
||||
|
||||
#### 准备环境
|
||||
|
||||
首先,让我们下载 android x86 8.1 Oreo 系统镜像。你可以从[这个页面][2]下载它,只需单击 “android-x86_64-8.1-r1.iso” 文件下的 “View” 按钮。
|
||||
|
||||
我们将在我们的 Linux 系统上使用 QEMU 来运行 android x86。QEMU 是一个非常好的模拟器软件,它也是自由而开源的,并且在所有主要的 Linux 发行版存储库中都是可用的。
|
||||
|
||||
在 Ubuntu/Linux Mint/Debian 上安装 QEMU:
|
||||
|
||||
```
|
||||
sudo apt-get install qemu qemu-kvm libvirt-bin
|
||||
```
|
||||
|
||||
在 Fedora 上安装 QEMU:
|
||||
|
||||
```
|
||||
sudo dnf install qemu qemu-kvm
|
||||
```
|
||||
|
||||
对于其它发行版,只需要搜索 “qemu” 和 “qemu-kvm” 软件包,并安装它们。
|
||||
|
||||
在你安装 QEMU 后,我们将需要运行下面的命令来创建 `android.img` 文件,它就像某种分配给安卓系统的磁盘空间。所有安卓文件和系统都将位于该镜像文件中:
|
||||
|
||||
```
|
||||
qemu-img create -f qcow2 android.img 15G
|
||||
```
|
||||
|
||||
我们在这里的意思是,我们想为该安卓系统分配一个最大 15GB 的磁盘空间,但是,你可以更改它到你想要的任意大小(确保它至少大于 5GB)。
|
||||
|
||||
现在,首次启动运行该安卓系统,运行:
|
||||
|
||||
```
|
||||
sudo qemu-system-x86_64 -m 2048 -boot d -enable-kvm -smp 3 -net nic -net user -hda android.img -cdrom /home/mhsabbagh/android-x86_64-8.1-r1.iso
|
||||
```
|
||||
|
||||
将 `/home/mhsabbagh/android-x86_64-8.1-r1.iso` 替换为你从 android x86 网站下载的文件的路径。关于我们在这里正在使用的其它选项的解释,你可以参考[这篇文章][3]。
|
||||
|
||||
在你运行上面的命令后,该安卓系统将启动:
|
||||
|
||||
![][4]
|
||||
|
||||
#### 安装系统
|
||||
|
||||
从这个窗口中,选择 “Advanced options”, 它将引导到下面的菜单,你应如下在其中选择 “Auto_installation” :
|
||||
|
||||
![][5]
|
||||
|
||||
在这以后,安装器将告知你是否想要继续,选择 “Yes”:
|
||||
|
||||
![][6]
|
||||
|
||||
接下来,安装器将无需你的指示而继续进行:
|
||||
|
||||
![][7]
|
||||
|
||||
最后,你将收到这个信息,它表示你已经成功安装安卓 8.1 :
|
||||
|
||||
![][8]
|
||||
|
||||
现在,关闭 QEMU 窗口即可。
|
||||
|
||||
#### 启动和使用 安卓 8.1 Oreo
|
||||
|
||||
现在,安卓系统已经完全安装在你的 `android.img` 文件中,你应该使用下面的 QEMU 命令来启动它,而不是前面的命令:
|
||||
|
||||
```
|
||||
sudo qemu-system-x86_64 -m 2048 -boot d -enable-kvm -smp 3 -net nic -net user -hda android.img
|
||||
```
|
||||
|
||||
注意,我们所做的只是移除 `-cdrom` 选项及其参数。这是告诉 QEMU,我们不再想从我们下载的 ISO 文件启动,相反,从这个安装的安卓系统启动。
|
||||
|
||||
你现在能够看到安卓的启动菜单:
|
||||
|
||||
![][9]
|
||||
|
||||
然后,你将进入第一个准备向导,选择你的语言并继续:
|
||||
|
||||
![][10]
|
||||
|
||||
从这里,选择 “Set up as new” 选项:
|
||||
|
||||
![][11]
|
||||
|
||||
然后,安卓将询问你是否想登录到你当前的谷歌账号。这步骤是可选的,但是这很重要,以便你随后可以使用谷歌 Play 商店:
|
||||
|
||||
![][12]
|
||||
|
||||
然后,你将需要接受条款:
|
||||
|
||||
![][13]
|
||||
|
||||
现在,你可以选择你当前的时区:
|
||||
|
||||
![][14]
|
||||
|
||||
系统将询问你是否想启动一些数据收集功能。如果我是你的话,我将简单地全部关闭它们,像这样:
|
||||
|
||||
![][15]
|
||||
|
||||
最后,你将有两种启动类型可供选择,我建议你选择 Launcher3 选项,并使其成为默认项:
|
||||
|
||||
![][16]
|
||||
|
||||
然后,你将看到完整工作的安卓系统主屏幕:
|
||||
|
||||
![][17]
|
||||
|
||||
从现在起,你可以做你想做的任何事情;你可以使用内置的安卓应用程序,或者你可以浏览你的系统设置来根据你的喜好进行调整。你可以更改你的系统的外观和体验,或者你可以像示例一样运行 Chrome :
|
||||
|
||||
![][18]
|
||||
|
||||
你可以开始从谷歌 Play 商店安装一些应用程序程序,像 WhatsApp 和其它的应用程序,以供你自己使用:
|
||||
|
||||
![][19]
|
||||
|
||||
你现在可以用你的系统做任何你想做的事。恭喜!
|
||||
|
||||
### 以后如何轻松地运行安卓 8.1 Oreo
|
||||
|
||||
我们不想总是不得不打开终端窗口,并写那些长长的 QEMU 命令来运行安卓系统,相反,我们想在我们需要时一次单击就运行它。
|
||||
|
||||
为此,我们将使用下面的命令在 `/usr/share/applications` 下创建一个名为 `android.desktop` 的新文件:
|
||||
|
||||
```
|
||||
sudo nano /usr/share/applications/android.desktop
|
||||
```
|
||||
|
||||
并在其中粘贴下面的内容(右键单击然后粘贴):
|
||||
|
||||
```
|
||||
[Desktop Entry]
|
||||
Name=Android 8.1
|
||||
Comment=Run Android 8.1 Oreo on Linux using QEMU
|
||||
Icon=phone
|
||||
Exec=bash -c 'pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY qemu-system-x86_64 -m 2048 -boot d -enable-kvm -smp 3 -net nic -net user -hda /home/mhsabbagh/android.img'
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GTK;
|
||||
```
|
||||
|
||||
再强调一次,你必需使用你系统上的本地镜像路径来替换 `/home/mhsabbagh/android.img` 。然后保存文件(`Ctrl+X`,然后按 `Y`,然后按回车)。
|
||||
|
||||
注意,我们需要使用 `pkexec` 来使用 root 权限运行 QEMU ,因为从较新的版本开始,普通用户不允许通过 libvirt 访问 KVM 技术;这就是为什么它将每次要求你输入 root 密码的原因。
|
||||
|
||||
现在,你将在应用程序菜单中看到安卓图标,你可以在你想使用安卓的任何时间来简单地单击该图标,QEMU 程序将启动:
|
||||
|
||||
![][20]
|
||||
|
||||
### 总结
|
||||
|
||||
我们向你展示如何在你的 Linux 系统上安装和运行安卓 8.1 Oreo 。从现在起,在没有其它一些软件的(像 Blutsticks 和类似的方法)的情况下,你可以更容易地完成基于安卓的任务。在这里,你有一个完整工作和功能的安卓系统,你可以随心所欲地操作它,如果一些东西出错,你可以简单地干掉该镜像文件,然后随时再一次重新运行安装程序。
|
||||
|
||||
你之前尝试过 android x86 吗?你的体验如何?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fosspost.org/tutorials/install-android-8-1-oreo-on-linux
|
||||
|
||||
作者:[M.Hanny Sabbagh][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://fosspost.org/author/mhsabbagh
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://www.android-x86.org/
|
||||
[2]: http://www.android-x86.org/download
|
||||
[3]: https://fosspost.org/tutorials/use-qemu-test-operating-systems-distributions
|
||||
[4]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-16.png?resize=694%2C548&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 40 android 8.1 oreo on linux)
|
||||
[5]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-15.png?resize=673%2C537&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 42 android 8.1 oreo on linux)
|
||||
[6]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-14.png?resize=769%2C469&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 44 android 8.1 oreo on linux)
|
||||
[7]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-13.png?resize=767%2C466&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 46 android 8.1 oreo on linux)
|
||||
[8]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-12.png?resize=750%2C460&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 48 android 8.1 oreo on linux)
|
||||
[9]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-11.png?resize=754%2C456&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 50 android 8.1 oreo on linux)
|
||||
[10]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-10.png?resize=850%2C559&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 52 android 8.1 oreo on linux)
|
||||
[11]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-09.png?resize=850%2C569&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 54 android 8.1 oreo on linux)
|
||||
[12]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-08.png?resize=850%2C562&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 56 android 8.1 oreo on linux)
|
||||
[13]: https://i2.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-07-1.png?resize=850%2C561&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 58 android 8.1 oreo on linux)
|
||||
[14]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-06.png?resize=850%2C569&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 60 android 8.1 oreo on linux)
|
||||
[15]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-05.png?resize=850%2C559&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 62 android 8.1 oreo on linux)
|
||||
[16]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-04.png?resize=850%2C553&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 64 android 8.1 oreo on linux)
|
||||
[17]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-03.png?resize=850%2C571&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 66 android 8.1 oreo on linux)
|
||||
[18]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-02.png?resize=850%2C555&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 68 android 8.1 oreo on linux)
|
||||
[19]: https://i2.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-01.png?resize=850%2C557&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 70 android 8.1 oreo on linux)
|
||||
[20]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Screenshot-at-2019-02-17-1539.png?resize=850%2C557&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 72 android 8.1 oreo on linux)
|
183
published/201912/20190225 Netboot a Fedora Live CD.md
Normal file
183
published/201912/20190225 Netboot a Fedora Live CD.md
Normal file
@ -0,0 +1,183 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11708-1.html)
|
||||
[#]: subject: (Netboot a Fedora Live CD)
|
||||
[#]: via: (https://fedoramagazine.org/netboot-a-fedora-live-cd/)
|
||||
[#]: author: (Gregory Bartholomew https://fedoramagazine.org/author/glb/)
|
||||
|
||||
网络启动一个 Fedora Live CD
|
||||
======
|
||||
|
||||
![](https://fedoramagazine.org/wp-content/uploads/2019/02/netboot-livecd-816x345.jpg)
|
||||
|
||||
[Live CD][1] 对于很多任务是很有用的,例如:
|
||||
|
||||
* 将操作系统安装到一个硬盘驱动器
|
||||
* 修复一个启动加载程序或执行其它救援模式操作
|
||||
* 为 Web 浏览提供一个相适应的最小环境
|
||||
* …以及[更多的东西][2]。
|
||||
|
||||
作为使用 DVD 和 USB 驱动器来存储你的 Live CD 镜像是一个替代方案,你可以上传它们到一个不太可能丢失或损坏的 [iSCSI][3] 服务器中。这个指南向你展示如何加载你的 Live CD 镜像到一个 ISCSI 服务器上,并使用 [iPXE][4] 启动加载程序来访问它们。
|
||||
|
||||
### 下载一个 Live CD 镜像
|
||||
|
||||
```
|
||||
$ MY_RLSE=27
|
||||
$ MY_LIVE=$(wget -q -O - https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/$MY_RLSE/Workstation/x86_64/iso | perl -ne '/(Fedora[^ ]*?-Live-[^ ]*?\.iso)(?{print $^N})/;')
|
||||
$ MY_NAME=fc$MY_RLSE
|
||||
$ wget -O $MY_NAME.iso https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/$MY_RLSE/Workstation/x86_64/iso/$MY_LIVE
|
||||
```
|
||||
|
||||
上面的命令下载 `Fedora-Workstation-Live-x86_64-27-1.6.iso` Fedora Live 镜像,并保存为 `fc27.iso`。更改 `MY_RLSE` 的值来下载其它档案版本。或者,你可以浏览 <https://getfedora.org/> 来下载最新的 Fedora live 镜像。在 21 之前的版本使用不同的命名约定,必需[在这里手动下载][5]。如果你手动下载一个 Live CD 镜像,设置 `MY_NAME` 变量为不带有扩展名的文件的基本名称。用此方法,下面部分中命令将引用正确的文件。
|
||||
|
||||
### 转换 Live CD 镜像
|
||||
|
||||
使用 `livecd-iso-to-disk` 工具来转换 ISO 文件为一个磁盘镜像,并添加 `netroot` 参数到嵌入的内核命令行:
|
||||
|
||||
```
|
||||
$ sudo dnf install -y livecd-tools
|
||||
$ MY_SIZE=$(du -ms $MY_NAME.iso | cut -f 1)
|
||||
$ dd if=/dev/zero of=$MY_NAME.img bs=1MiB count=0 seek=$(($MY_SIZE+512))
|
||||
$ MY_SRVR=server-01.example.edu
|
||||
$ MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
$ MY_LOOP=$(sudo losetup --show --nooverlap --find $MY_NAME.img)
|
||||
$ sudo livecd-iso-to-disk --format --extra-kernel-args netroot=iscsi:$MY_SRVR:::1:iqn.$MY_RVRS:$MY_NAME $MY_NAME.iso $MY_LOOP
|
||||
$ sudo losetup -d $MY_LOOP
|
||||
```
|
||||
|
||||
### 上传 Live 镜像到你的服务器
|
||||
|
||||
在你的 ISCSI 服务器上创建一个目录来存储你的 live 镜像,随后上传你修改的镜像到其中。
|
||||
|
||||
对于 21 及更高发布版本:
|
||||
|
||||
```
|
||||
$ MY_FLDR=/images
|
||||
$ scp $MY_NAME.img $MY_SRVR:$MY_FLDR/
|
||||
```
|
||||
|
||||
对于 21 以前发布版本:
|
||||
|
||||
```
|
||||
$ MY_FLDR=/images
|
||||
$ MY_LOOP=$(sudo losetup --show --nooverlap --find --partscan $MY_NAME.img)
|
||||
$ sudo tune2fs -O ^has_journal ${MY_LOOP}p1
|
||||
$ sudo e2fsck ${MY_LOOP}p1
|
||||
$ sudo dd status=none if=${MY_LOOP}p1 | ssh $MY_SRVR "dd of=$MY_FLDR/$MY_NAME.img"
|
||||
$ sudo losetup -d $MY_LOOP
|
||||
```
|
||||
|
||||
### 定义 iSCSI 目标
|
||||
|
||||
在你的 iSCSI 服务器上运行下面的命令:
|
||||
|
||||
```
|
||||
$ sudo -i
|
||||
# MY_NAME=fc27
|
||||
# MY_FLDR=/images
|
||||
# MY_SRVR=`hostname`
|
||||
# MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
# cat << END > /etc/tgt/conf.d/$MY_NAME.conf
|
||||
<target iqn.$MY_RVRS:$MY_NAME>
|
||||
backing-store $MY_FLDR/$MY_NAME.img
|
||||
readonly 1
|
||||
allow-in-use yes
|
||||
</target>
|
||||
END
|
||||
# tgt-admin --update ALL
|
||||
```
|
||||
|
||||
### 创建一个可启动 USB 驱动器
|
||||
|
||||
[iPXE][4] 启动加载程序有一个 [sanboot][6] 命令,你可以使用它来连接并启动托管于你 ISCSI 服务器上运行的 live 镜像。它可以以很多不同的[格式][7]编译。最好的工作格式依赖于你正在运行的硬件。例如,下面的说明向你展示如何在一个 USB 驱动器上从 [syslinux][9] 中 [链式加载][8] iPXE。
|
||||
|
||||
首先,下载 iPXE,并以它的 lkrn 格式构建。这应该作为一个工作站上的普通用户完成:
|
||||
|
||||
```
|
||||
$ sudo dnf install -y git
|
||||
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
|
||||
$ sudo dnf groupinstall -y "C Development Tools and Libraries"
|
||||
$ cd $HOME/ipxe/src
|
||||
$ make clean
|
||||
$ make bin/ipxe.lkrn
|
||||
$ cp bin/ipxe.lkrn /tmp
|
||||
```
|
||||
|
||||
接下来,准备一个带有一个 MSDOS 分区表和一个 FAT32 文件系统的 USB 驱动器。下面的命令假设你已经连接将要格式化的 USB 驱动器。**注意:你要格式正确的驱动器!**
|
||||
|
||||
```
|
||||
$ sudo -i
|
||||
# dnf install -y parted util-linux dosfstools
|
||||
# echo; find /dev/disk/by-id ! -regex '.*-part.*' -name 'usb-*' -exec readlink -f {} \; | xargs -i bash -c "parted -s {} unit MiB print | perl -0 -ne '/^Model: ([^(]*).*\n.*?([0-9]*MiB)/i && print \"Found: {} = \$2 \$1\n\"'"; echo; read -e -i "$(find /dev/disk/by-id ! -regex '.*-part.*' -name 'usb-*' -exec readlink -f {} \; -quit)" -p "Drive to format: " MY_USB
|
||||
# umount $MY_USB?
|
||||
# wipefs -a $MY_USB
|
||||
# parted -s $MY_USB mklabel msdos mkpart primary fat32 1MiB 100% set 1 boot on
|
||||
# mkfs -t vfat -F 32 ${MY_USB}1
|
||||
```
|
||||
|
||||
最后,在 USB 驱动器上安装并配置 syslinux ,来链式加载 iPXE:
|
||||
|
||||
```
|
||||
# dnf install -y syslinux-nonlinux
|
||||
# syslinux -i ${MY_USB}1
|
||||
# dd if=/usr/share/syslinux/mbr.bin of=${MY_USB}
|
||||
# MY_MNT=$(mktemp -d)
|
||||
# mount ${MY_USB}1 $MY_MNT
|
||||
# MY_NAME=fc27
|
||||
# MY_SRVR=server-01.example.edu
|
||||
# MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
# cat << END > $MY_MNT/syslinux.cfg
|
||||
ui menu.c32
|
||||
default $MY_NAME
|
||||
timeout 100
|
||||
menu title SYSLINUX
|
||||
label $MY_NAME
|
||||
menu label ${MY_NAME^^}
|
||||
kernel ipxe.lkrn
|
||||
append dhcp && sanboot iscsi:$MY_SRVR:::1:iqn.$MY_RVRS:$MY_NAME
|
||||
END
|
||||
# cp /usr/share/syslinux/menu.c32 $MY_MNT
|
||||
# cp /usr/share/syslinux/libutil.c32 $MY_MNT
|
||||
# cp /tmp/ipxe.lkrn $MY_MNT
|
||||
# umount ${MY_USB}1
|
||||
```
|
||||
|
||||
通过简单地编辑 `syslinux.cfg` 文件,并添加附加的菜单项,你应该能够使用这同一个 USB 驱动器来网络启动附加的 ISCSI 目标。
|
||||
|
||||
这仅是加载 IPXE 的一种方法。你可以直接在你的工作站上安装 syslinux 。再一种选项是编译 iPXE 为一个 EFI 可执行文件,并直接放置它到你的 [ESP][10] 中。又一种选项是编译 iPXE 为一个 PXE 加载器,并放置它到你的能够被 DHCP 引用的 TFTP 服务器。最佳的选项依赖于的环境
|
||||
|
||||
### 最后说明
|
||||
|
||||
* 如果你以 IPXE 的 EFI 格式编译 IPXE ,你可能想添加 `–filename \EFI\BOOT\grubx64.efi` 参数到 `sanboot` 命令。
|
||||
* 能够创建自定义 live 镜像。更多信息参考[创建和使用 live CD][11]。
|
||||
* 可以添加 `–overlay-size-mb` 和 `–home-size-mb` 参数到 `livecd-iso-to-disk` 命令来创建永久存储的 live 镜像。然而,如果你有多个并发用户,你将需要设置你的 ISCSI 服务器来管理独立的每个用户的可写覆盖。这与 “[如何构建一个网络启动服务器,部分 4][12]” 一文所示类似。
|
||||
* Live 镜像在它们的内核命令行中支持一个 `persistenthome` 选项(例如, `persistenthome=LABEL=HOME`)。与经过 CHAP 身份验证的 iSCSI 目标一起使用,对于中心控制主目录,`persistenthome` 选项为 NFS 提供一个有趣的替代方案。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/netboot-a-fedora-live-cd/
|
||||
|
||||
作者:[Gregory Bartholomew][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://fedoramagazine.org/author/glb/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Live_CD
|
||||
[2]: https://en.wikipedia.org/wiki/Live_CD#Uses
|
||||
[3]: https://en.wikipedia.org/wiki/ISCSI
|
||||
[4]: https://ipxe.org/
|
||||
[5]: https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/
|
||||
[6]: http://ipxe.org/cmd/sanboot/
|
||||
[7]: https://ipxe.org/appnote/buildtargets#boot_type
|
||||
[8]: https://en.wikipedia.org/wiki/Chain_loading
|
||||
[9]: https://www.syslinux.org/wiki/index.php?title=SYSLINUX
|
||||
[10]: https://en.wikipedia.org/wiki/EFI_system_partition
|
||||
[11]: https://docs.fedoraproject.org/en-US/quick-docs/creating-and-using-a-live-installation-image/#proc_creating-and-using-live-cd
|
||||
[12]: https://fedoramagazine.org/how-to-build-a-netboot-server-part-4/
|
||||
|
79
published/201912/20190322 Easy means easy to debug.md
Normal file
79
published/201912/20190322 Easy means easy to debug.md
Normal file
@ -0,0 +1,79 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (LuuMing)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11693-1.html)
|
||||
[#]: subject: (Easy means easy to debug)
|
||||
[#]: via: (https://arp242.net/weblog/easy.html)
|
||||
[#]: author: (Martin Tournoij https://arp242.net/)
|
||||
|
||||
简单就是易于调试
|
||||
======
|
||||
|
||||
对于框架、库或者工具来说,怎样做才算是“简单”?也许有很多的定义,但我的理解通常是**易于调试**。我经常见到人们宣传某个特定的程序、框架、库、文件格式或者其它什么东西是简单的,因为他们会说“看,我只需要这么一点工作量就能够完成某项工作,这太简单了”。非常好,但并不完善。
|
||||
|
||||
你可能只编写一次软件,但几乎总要经历好几个调试周期。注意我说的调试周期并不意味着“代码里面有 bug 你需要修复”,而是说“我需要再看一下这份代码来修复 bug”。为了调试代码,你需要理解它,因此“易于调试”延伸来讲就是“易于理解”。
|
||||
|
||||
抽象使得程序易于编写,但往往是以难以理解为代价。有时候这是一个很好的折中,但通常不是。大体上,如果能使程序在日后易于理解和调试,我很乐意花更多的时间来写一些东西,因为这样实际上更省时间。
|
||||
|
||||
简洁并不是让程序易于调试的**唯一**方法,但它也许是最重要的。良好的文档也是,但不幸的是好的文档太少了。(注意,质量并**不**取决于字数!)
|
||||
|
||||
这种影响是真是存在的。难以调试的程序会有更多的 bug,即使最初的 bug 数量与易于调试的程序完全相同,而是因为修复 bug 更加困难、更花时间。
|
||||
|
||||
在公司的环境中,把时间花在难以修复的 bug 上通常被认为是不划算的投资。而在开源的环境下,人们花的时间会更少。(大多数项目都有一个或多个定期的维护者,但成百上千的贡献者提交的仅只是几个补丁)
|
||||
|
||||
---
|
||||
|
||||
这并不全是 1974 年由 Brian W. Kernighan 和 P. J. Plauger 合著的《<ruby>编程风格的元素<rt>The Elements of Programming Style</rt></ruby>》中的观点:
|
||||
|
||||
> 每个人都知道调试比起编写程序困难两倍。当你写程序的时候耍小聪明,那么将来应该怎么去调试?
|
||||
|
||||
我见过许多看起来写起来“极尽精妙”,但却导致难以调试的代码。我会在下面列出几种样例。争论这些东西本身有多坏并不是我的本意,我仅想强调对于“易于使用”和“易于调试”之间的折中。
|
||||
|
||||
* <ruby>ORM<rt>对象关系映射</rt></ruby> 库可以让数据库查询变得简单,代价是一旦你想解决某个问题,事情就变得难以理解。
|
||||
* 许多测试框架让调试变得困难。Ruby 的 rspec 就是一个很好的例子。有一次我不小心使用错了,结果花了很长时间搞清楚**究竟**哪里出了问题(因为它给出错误提示非常含糊)。
|
||||
|
||||
我在《[测试并非万能][1]》这篇文章中写了更多关于以上的例子。
|
||||
* 我用过的许多 JavaScript 框架都很难完全理解。Clever(LCTT 译注:一种 JS 框架)的语句一向很有逻辑,直到某条语句不能如你预期的工作,这时你就只能指望 Stack Overflow 上的某篇文章或 GitHub 上的某个回帖来帮助你了。
|
||||
|
||||
这些函数库**确实**让任务变得非常简单,使用它们也没有什么错。但通常人们都过于关注“易于使用”而忽视了“易于调试”这一点。
|
||||
* Docker 非常棒,并且让许多事情变得非常简单,直到你看到了这条提示:
|
||||
|
||||
```
|
||||
ERROR: for elasticsearch Cannot start service elasticsearch:
|
||||
oci runtime error: container_linux.go:247: starting container process caused "process_linux.go:258:
|
||||
applying cgroup configuration for process caused \"failed to write 898 to cgroup.procs: write
|
||||
/sys/fs/cgroup/cpu,cpuacct/docker/b13312efc203e518e3864fc3f9d00b4561168ebd4d9aad590cc56da610b8dd0e/cgroup.procs:
|
||||
invalid argument\""
|
||||
```
|
||||
|
||||
或者这条:
|
||||
|
||||
```
|
||||
ERROR: for elasticsearch Cannot start service elasticsearch: EOF
|
||||
```
|
||||
|
||||
那么...你怎么看?
|
||||
* `Systemd` 比起 `SysV`、`init.d` 脚本更加简单,因为编写 `systemd` 单元文件比起编写 `shell` 脚本更加方便。这也是 Lennart Poetterin 在他的 [systemd 神话][2] 中解释 `systemd` 为何简单时使用的论点。
|
||||
|
||||
我非常赞同 Poettering 的观点——也可以看 [shell 脚本陷阱][3] 这篇文章。但是这种角度并不全面。单元文件简单的背后意味着 `systemd` 作为一个整体要复杂的多,并且用户确实会受到它的影响。看看我遇到的这个[问题][4]和为它所做的[修复][5]。看起来很简单吗?
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://arp242.net/weblog/easy.html
|
||||
|
||||
作者:[Martin Tournoij][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[LuuMing](https://github.com/LuuMing)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://arp242.net/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.arp242.net/testing.html
|
||||
[2]: http://0pointer.de/blog/projects/the-biggest-myths.html
|
||||
[3]:https://www.arp242.net/shell-scripting-trap.html
|
||||
[4]:https://unix.stackexchange.com/q/185495/33645
|
||||
[5]:https://cgit.freedesktop.org/systemd/systemd/commit/?id=6e392c9c45643d106673c6643ac8bf4e65da13c1
|
@ -0,0 +1,186 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11709-1.html)
|
||||
[#]: subject: (How To Set Password Complexity On Linux?)
|
||||
[#]: via: (https://www.2daygeek.com/how-to-set-password-complexity-policy-on-linux/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
Linux 如何设置密码复杂度?
|
||||
======
|
||||
|
||||
对于 Linux 系统管理员来说,用户管理是最重要的事之一。这涉及到很多因素,实现强密码策略是用户管理的其中一个方面。移步后面的 URL 查看如何 [在 Linux 上生成一个强密码][1]。它会限制系统未授权的用户的访问。
|
||||
|
||||
所有人都知道 Linux 的默认策略很安全,然而我们还是要做一些微调,这样才更安全。弱密码有安全隐患,因此,请特别注意。移步后面的 URL 查看生成的强密码的[密码长度和分值][2]。本文将教你在 Linux 中如何实现最安全的策略。
|
||||
|
||||
在大多数 Linux 系统中,我们可以用 PAM(<ruby>可插拔认证模块<rt>pluggable authentication module</rt></ruby>)来加强密码策略。在下面的路径可以找到这个文件。
|
||||
|
||||
- 在红帽系列的系统中,路径:`/etc/pam.d/system-auth`。
|
||||
- Debian 系列的系统中,路径:`/etc/pam.d/common-password`。
|
||||
|
||||
关于默认的密码过期时间,可以在 `/etc/login.defs` 文件中查看详细信息。
|
||||
|
||||
为了更好理解,我摘取了文件的部分内容:
|
||||
|
||||
```
|
||||
# vi /etc/login.defs
|
||||
|
||||
PASS_MAX_DAYS 99999
|
||||
PASS_MIN_DAYS 0
|
||||
PASS_MIN_LEN 5
|
||||
PASS_WARN_AGE 7
|
||||
```
|
||||
|
||||
详细解释:
|
||||
|
||||
* `PASS_MAX_DAYS`:一个密码可使用的最大天数。
|
||||
* `PASS_MIN_DAYS`:两次密码修改之间最小的间隔天数。
|
||||
* `PASS_MIN_LEN`:密码最小长度。
|
||||
* `PASS_WARN_AGE`:密码过期前给出警告的天数。
|
||||
|
||||
我们将会展示在 Linux 中如何实现下面的 11 个密码策略。
|
||||
|
||||
* 一个密码可使用的最大天数
|
||||
* 两次密码修改之间最小的间隔天数
|
||||
* 密码过期前给出警告的天数
|
||||
* 密码历史记录/拒绝重复使用密码
|
||||
* 密码最小长度
|
||||
* 最少的大写字母个数
|
||||
* 最少的小写字母个数
|
||||
* 最少的数字个数
|
||||
* 最少的其他字符(符号)个数
|
||||
* 账号锁定 — 重试
|
||||
* 账号解锁时间
|
||||
|
||||
### 密码可使用的最大天数是什么?
|
||||
|
||||
这一参数限制一个密码可使用的最大天数。它强制用户在过期前修改他/她的密码。如果他们忘记修改,那么他们会登录不了系统。他们需要联系管理员才能正常登录。这个参数可以在 `/etc/login.defs` 文件中设置。我把这个参数设置为 90 天。
|
||||
|
||||
```
|
||||
# vi /etc/login.defs
|
||||
|
||||
PASS_MAX_DAYS 90
|
||||
```
|
||||
|
||||
### 密码最小天数是什么?
|
||||
|
||||
这个参数限制两次修改之间的最少天数。举例来说,如果这个参数被设置为 15 天,用户今天修改了密码,那么在 15 天之内他都不能修改密码。这个参数可以在 `/etc/login.defs` 文件中设置。我设置为 15 天。
|
||||
|
||||
```
|
||||
# vi /etc/login.defs
|
||||
|
||||
PASS_MIN_DAYS 15
|
||||
```
|
||||
|
||||
### 密码警告天数是什么?
|
||||
|
||||
这个参数控制密码警告的前置天数,在密码即将过期时会给用户警告提示。在警告天数结束前,用户会收到日常警告提示。这可以提醒用户在密码过期前修改他们的密码,否则我们就需要联系管理员来解锁密码。这个参数可以在 `/etc/login.defs` 文件中设置。我设置为 10 天。
|
||||
|
||||
```
|
||||
# vi /etc/login.defs
|
||||
|
||||
PASS_WARN_AGE 10
|
||||
```
|
||||
|
||||
**注意:** 上面的所有参数仅对新账号有效,对已存在的账号无效。
|
||||
|
||||
### 密码历史或拒绝重复使用密码是什么?
|
||||
|
||||
这个参数控制密码历史。它记录曾经使用过的密码(禁止使用的曾用密码的个数)。当用户设置新的密码时,它会检查密码历史,如果他们要设置的密码是一个曾经使用过的旧密码,将会发出警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置密码历史为 5。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok remember=5
|
||||
```
|
||||
|
||||
### 密码最小长度是什么?
|
||||
|
||||
这个参数表示密码的最小长度。当用户设置新密码时,系统会检查这个参数,如果新设的密码长度小于这个参数设置的值,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置最小密码长度为 12。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 minlen=12
|
||||
```
|
||||
|
||||
`try_first_pass retry=3`:在密码设置交互界面,用户有 3 次机会重设密码。
|
||||
|
||||
### 设置最少的大写字母个数?
|
||||
|
||||
这个参数表示密码中至少需要的大写字母的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有大写字母,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置密码(中的大写字母)的最小长度为 1 个字母。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 ucredit=-1
|
||||
```
|
||||
|
||||
### 设置最少的小写字母个数?
|
||||
|
||||
这个参数表示密码中至少需要的小写字母的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有小写字母,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 1 个字母。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 lcredit=-1
|
||||
```
|
||||
|
||||
### 设置密码中最少的数字个数?
|
||||
|
||||
这个参数表示密码中至少需要的数字的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有数字,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 1 个数字。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 dcredit=-1
|
||||
```
|
||||
|
||||
### 设置密码中最少的其他字符(符号)个数?
|
||||
|
||||
这个参数表示密码中至少需要的特殊符号的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有特殊符号,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 1 个字符。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 ocredit=-1
|
||||
```
|
||||
|
||||
### 设置账号锁定?
|
||||
|
||||
这个参数控制用户连续登录失败的最大次数。当达到设定的连续失败登录次数阈值时,锁定账号。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
auth required pam_tally2.so onerr=fail audit silent deny=5
|
||||
account required pam_tally2.so
|
||||
```
|
||||
|
||||
### 设定账号解锁时间?
|
||||
|
||||
这个参数表示用户解锁时间。如果一个用户账号在连续认证失败后被锁定了,当过了设定的解锁时间后,才会解锁。设置被锁定中的账号的解锁时间(900 秒 = 15分钟)。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
|
||||
auth required pam_tally2.so onerr=fail audit silent deny=5 unlock_time=900
|
||||
account required pam_tally2.so
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-set-password-complexity-policy-on-linux/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [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/5-ways-to-generate-a-random-strong-password-in-linux-terminal/
|
||||
[2]: https://www.2daygeek.com/how-to-check-password-complexity-strength-and-score-in-linux/
|
@ -0,0 +1,196 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11631-1.html)
|
||||
[#]: subject: (How to Install LEMP (Linux, Nginx, MariaDB, PHP) on Fedora 30 Server)
|
||||
[#]: via: (https://www.linuxtechi.com/install-lemp-stack-fedora-30-server/)
|
||||
[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
|
||||
|
||||
如何在 Fedora 30 Server 上安装 LEMP(Linux、Nginx、MariaDB、PHP)
|
||||
======
|
||||
|
||||
在这篇文章中,我们将看看如何在 Fedora 30 Server 上安装 **LEMP** 。LEMP 代表:
|
||||
|
||||
* L -> Linux
|
||||
* E -> Nginx
|
||||
* M -> Maria DB
|
||||
* P -> PHP
|
||||
|
||||
我假设 [Fedora 30][1] 已经安装在你的电脑系统上。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/01/103537wil7hd36dhcxdh03.jpg)
|
||||
|
||||
LEMP 是一组强大的软件设置集合,它安装在一个 Linux 服务器上以帮助使用流行的开发平台来构建网站,LEMP 是 LAMP 的一个变种,在其中不是 Apache ,而是使用 EngineX(Nginx),此外,使用 MariaDB 代替 MySQL。这篇入门指南是一个安装 Nginx、Maria DB 和 PHP 的独立指南的作品集合。
|
||||
|
||||
### 在 Fedora 30 Server 上安装 Nginx、PHP 7.3 和 PHP-FPM
|
||||
|
||||
让我们看看如何在 Fedora 30 Server 上安装 Nginx 和 PHP 以及 PHP FPM。
|
||||
|
||||
#### 步骤 1) 切换到 root 用户
|
||||
|
||||
在系统上安装 Nginx 的第一步是切换到 root 用户。使用下面的命令:
|
||||
|
||||
```
|
||||
root@linuxtechi ~]$ sudo -i
|
||||
[sudo] password for pkumar:
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
#### 步骤 2) 使用 dnf 命令安装 Nginx、PHP 7.3 和 PHP FPM
|
||||
|
||||
使用下面的 `dnf` 命令安装 Nginx:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# dnf install nginx php php-fpm php-common -y
|
||||
```
|
||||
|
||||
#### 步骤 3) 安装额外的 PHP 模块
|
||||
|
||||
PHP 的默认安装仅自带基本模块和最需要的模块,如果你需要额外的模块,像 PHP 支持的 GD、XML、命令行接口、Zend OPCache 功能等等,你总是能够选择你的软件包,并一次性安装所有的东西。查看下面的示例命令:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# sudo dnf install php-opcache php-pecl-apcu php-cli php-pear php-pdo php-pecl-mongodb php-pecl-redis php-pecl-memcache php-pecl-memcached php-gd php-mbstring php-mcrypt php-xml -y
|
||||
```
|
||||
|
||||
#### 步骤 4) 开始 & 启用 Nginx 和 PHP-fpm 服务
|
||||
|
||||
使用下面的命令来开始并启用 Nginx 服务:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# systemctl start nginx && systemctl enable nginx
|
||||
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
使用下面的命令来开始并启用 PHP-FPM 服务:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# systemctl start php-fpm && systemctl enable php-fpm
|
||||
Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm.service → /usr/lib/systemd/system/php-fpm.service.
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
#### 步骤 5) 核实 Nginx (Web 服务) 和 PHP 安装
|
||||
|
||||
注意:假使操作系统防火墙是启用的,并运行在你的 Fedora 30 系统上,那么使用下面的命令来准许 80 和 443 端口:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# firewall-cmd --permanent --add-service=http
|
||||
success
|
||||
[root@linuxtechi ~]#
|
||||
[root@linuxtechi ~]# firewall-cmd --permanent --add-service=https
|
||||
success
|
||||
[root@linuxtechi ~]# firewall-cmd --reload
|
||||
success
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
打开网页浏览器,输入下面的 URL: http://<Your-Server-IP> 。
|
||||
|
||||
![Test-Page-HTTP-Server-Fedora-30][4]
|
||||
|
||||
上面的屏幕证实 Nginx 已经成功地安装。
|
||||
|
||||
现在,让我们核实 PHP 安装,使用下面的命令创建一个测试 php 页(`info.php`):
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# echo "<?php phpinfo(); ?>" > /usr/share/nginx/html/info.php
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
在网页浏览器中输入下面的 URL, http://<Your-Server-IP>/info.php
|
||||
|
||||
![Php-info-page-fedora30][6]
|
||||
|
||||
上面的页面验证 PHP 7.3.5 已经被成功地安装。现在,让我们安装 MariaDB 数据库服务器。
|
||||
|
||||
### 在 Fedora 30 上安装 MariaDB
|
||||
|
||||
MariaDB 是 MySQL 数据库的一个极好的替代品,因为它的工作方式与 MySQL 非常类似,并且兼容性也与 MySQL 一致。让我们看看在 Fedora 30 Server 上安装 MariaDB 的步骤。
|
||||
|
||||
#### 步骤 1) 切换到 root 用户
|
||||
|
||||
在系统上安装 MariaDB 的第一步是切换到 root 用户,或者你可以使用有 root 权限的本地用户。使用下面的命令:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# sudo -i
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
#### 步骤 2) 使用 dnf 命令安装 MariaDB(10.3)的最新版本
|
||||
|
||||
在 Fedora 30 Server 上使用下面的命令来安装 MariaDB:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# dnf install mariadb-server -y
|
||||
```
|
||||
|
||||
#### 步骤 3) 开启并启用 MariaDB 服务
|
||||
|
||||
在步骤 2 中成功地安装 MariaDB 后,接下来的步骤是开启 MariaDB 服务。使用下面的命令:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# systemctl start mariadb.service ; systemctl enable mariadb.service
|
||||
```
|
||||
|
||||
#### 步骤 4) 保护安装好的 MariaDB
|
||||
|
||||
当我们安装 MariaDB 服务器时,因为默认情况下没有 root 密码,在数据库中也会创建匿名用户。因此,要保护安装好的 MariaDB,运行下面的 `mysql_secure_installation` 命令:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# mysql_secure_installation
|
||||
```
|
||||
|
||||
接下来你将被提示一些问题,仅回答下面展示的问题:
|
||||
|
||||
![Secure-MariaDB-Installation-Part1][7]
|
||||
|
||||
![Secure-MariaDB-Installation-Part2][8]
|
||||
|
||||
#### 步骤 5) 测试 MariaDB 安装
|
||||
|
||||
在你安装后,你总是能够测试是否 MariaDB 被成功地安装在 Fedora 30 Server 上。使用下面的命令:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# mysql -u root -p
|
||||
Enter password:
|
||||
```
|
||||
|
||||
接下来,你将被提示一个密码。输入在保护安装好的 MariaDB 期间你设置的密码,接下来你可以看到 MariaDB 欢迎屏幕。
|
||||
|
||||
```
|
||||
Welcome to the MariaDB monitor. Commands end with ; or \g.
|
||||
Your MariaDB connection id is 17
|
||||
Server version: 10.3.12-MariaDB MariaDB Server
|
||||
|
||||
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
|
||||
|
||||
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
|
||||
|
||||
MariaDB [(none)]>
|
||||
```
|
||||
|
||||
最后,我们已经在你的 Fedora 30 Server 上成功地完成安装 LEMP(Linux、Nginx、MariaDB 和 PHP)的所有工作。请在下面的反馈部分发布你的评论和建议,我们将尽快在后面回应。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxtechi.com/install-lemp-stack-fedora-30-server/
|
||||
|
||||
作者:[Pradeep Kumar][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://www.linuxtechi.com/author/pradeep/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.linuxtechi.com/fedora-30-workstation-installation-guide/
|
||||
[2]: https://www.linuxtechi.com/wp-content/uploads/2019/06/LEMP-Stack-Fedora30.jpg
|
||||
[3]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Test-Page-HTTP-Server-Fedora-30-1024x732.jpg
|
||||
[4]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Test-Page-HTTP-Server-Fedora-30.jpg
|
||||
[5]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Php-info-page-fedora30-1024x732.jpg
|
||||
[6]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Php-info-page-fedora30.jpg
|
||||
[7]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Secure-MariaDB-Installation-Part1.jpg
|
||||
[8]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Secure-MariaDB-Installation-Part2.jpg
|
73
published/201912/20190711 DevOps for introverted people.md
Normal file
73
published/201912/20190711 DevOps for introverted people.md
Normal file
@ -0,0 +1,73 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (XLCYun)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11725-1.html)
|
||||
[#]: subject: (DevOps for introverted people)
|
||||
[#]: via: (https://opensource.com/article/19/7/devops-introverted-people)
|
||||
[#]: author: (Matthew Broberg https://opensource.com/users/mbbroberg)
|
||||
|
||||
内向者的 DevOps
|
||||
======
|
||||
|
||||
> 我们邀请 Opensource.com 的 DevOps 团队,希望他们能够谈一谈作为 DevOps 内向者的休验,同时给 DevOps 外向者一些建议。下面是他们的回答。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/29/103642jmzt6t6mggjjx5yt.jpg)
|
||||
|
||||
我们邀请我们的 [DevOps 团队][2] 谈一谈他们作为一个内向者的体验,并给外向者们一些建议。但是在我们开始了解他们的回答之前,让我们先来定义一下这些词汇。
|
||||
|
||||
### “内向者”是什么意思?
|
||||
|
||||
内向者通常指的是一部分人群,当他们和别人相处的时候,会使他们的能量耗尽,而不是激发他们更多的能量。当我们思考我们是如何恢复能量时,这是一个非常有用的词汇:内向者通常需要更多的独处时间来恢复能量,特别是和一群人在一起很长时间后。关于内向者的一个非常大的误解就是他们一定是“害羞的”,但是科学表明,那不过是另一种不同的性格特征。
|
||||
|
||||
内向性与外向性是通过 [Myers Briggs 类型指标][4] 而为人所知的,现在也常常被称作一个 [光谱][5] 的两端。虽然这个世界看起来好像外向者比内向者要多,但是心理学者则倾向于认为大部分人在光谱上的位置是落在 [中间性格或偏内向性格的][6]。
|
||||
|
||||
现在,我们来看看问答。
|
||||
|
||||
### DevOps 技术主管可以通过哪些方式来让内向者感觉他们是团队的一部分并且愿意分享他们的想法?
|
||||
|
||||
“每个人都会不大一样,所以观察敏锐就很重要了。从 GitLab 过来的一个人告诉我,他们的哲学就是如果他们没有提供任何意见,那么他们就是被排除在外的。如果有人在一个会议上没有提供任何的意见,那就想办法让他们加入进来。**当我知道一个内向者对我们将要讨论的会议论题感兴趣的时候,我会提前请他写一些书面文本。有非常多的会议其实是可以避免的,只要通过把讨论放到 Slack 或者 GitLab 上就行了,内向者会更愿意参与进来**。在站立会议中,每个人都会交代最新的进展,在这个环境下,内向者表现得很好。有时候我们在其实会议上会重复做一些事情,仅仅是为了保证每个人都有时间发言。我同时也会鼓励内向者在工作小组或者社区小组面前发言,以此来锻炼他们的这些技能。”—— 丹·巴克
|
||||
|
||||
“**我觉得别人对我做的最好的事情,就是他们保证了当重大问题来临的时候,我拥有必要的技能去回答它**。彼时,我作为一名非常年轻的入伍空军的一员,我需要给我们部队的高级领导做状态简报的汇报。我必须在任何时候都有一些可用的数据点,以及在实现我们确立的目标的过程中,产生延误以及偏差的背后的原因。那样的经历推动着我从一个‘幕后人员’逐渐变得更加愿意和别人分享自己的观点和想法。”—— 克里斯·肖特
|
||||
|
||||
“**通过文化去领导。为你的同僚一起设计和尝试仪式。**你可以为给你的小组或团队设计一个小的每周仪式,甚至给你的部门或组织设计一个年度的大仪式。它的意义在于去尝试一些事物,并观察你在其中的领导角色。去找到你们文化当中的代沟以及对立。回顾团队的信仰和行为。你能从哪里观察到对立?你们的文化中缺失了什么?从一个小陈述开始‘我从 X 和 Y 之间看到了对立’,或者‘我的团队缺少了 Z’。接着,将代沟与对立转换为问题:写下三个‘我们如何能……(How might we's, HMWs)’。”—— 凯瑟琳·路易斯
|
||||
|
||||
“内向者不是一个不同的群体,他们要么是在分享他们的想法之前想得太多或等得太久的一些人,要么就是一些根本不知道发生了什么的人。我就是第一种,我想太多了,有时候还担心我的意见会被其他人嘲笑,或者没有什么意思,或者想偏了。形成那样的思维方式很难,但它同时也在吞噬着我学习更好事物的机会。有一次,我们团队在讨论一个实现问题。我当时的老大一次又一次地问我,为什么我没有作为团队中更具经验的人参与进来,然后我就(集齐了全宇宙的力量之后)开口说我想说的大家都已经说过了。他说,有时候我可以重复说一次,事情纷繁,如果你能够重复一遍你的想法,即使它已经被讨论过了,也会大有裨益。好吧,虽然它不是一种特别信服的方式,但是我知道了至少有人想听听我怎么说,它给了我一点信心。
|
||||
|
||||
“现在,我所使用的让团队中的人发言的方法是**我经常向内向的人求助,即使我知道解决方法,并且在团队会议和讨论中感谢他们来建立他们的自信心,通过给他们时间让他们一点一点的从他们寡言的本性中走出来,从而跟团队分享很多的知识**。他们在外面的世界中可能仍然会有一点点孤立,但是在团队里面,有些会成为我们可以信赖的人。”—— 阿布希什克·塔姆拉卡尔
|
||||
|
||||
“我给参加会议的内向者的建议是,找一个同样要参加会议的朋友或者同事,这样到时你就会有人可以跟你一起舒服地交谈,在会议开始之前,提前跟其他的与会者(朋友、行业联系人、前同事等等)约着见个面或者吃顿饭,**要注意你的疲劳程度,并且照顾好自己**:如果你需要重新恢复能量,就跳过那些社交或者夜晚的活动,在事后回顾中记录一下自己的感受。”—— 伊丽莎白·约瑟夫
|
||||
|
||||
### 和一个内向者倾向的同事一起工作时,有什么提高生产效率的小建议?
|
||||
|
||||
“在保证质量时,生产效率会越来越具备挑战性。在大多数时候,工作中的一个小憩或者轻松随意的交谈,可能正是我们的创造性活动中需要的一个火花。再说一次,我发现当你的团队中有内向者时, Slack 和 Github 会是一个非常有用的用于交换想法以及和其他人互动的媒介。**我同时也发现,结对编程对于大部分的内向者也非常有用,虽然一对一的交流对于他们来说,并不像交税那么频繁,但是生产质量和效率的提升却是重大的**。但是,当一个内向者在独自工作的时间,团队中的所有人都不应该去打断他们。最好是发个邮件,或者使用没有那么强的侵入性的媒介。”—— 丹·巴克
|
||||
|
||||
“给他们趁手的工具,让他们工作并归档他们的工作。**让他们能够在他们的工作上做到最好**。要足够经常地去检查一下,保证他们没有走偏路,但是要记住,相比外向者而言,这样做是更大的一种让人分心的困扰。”—— 克里斯·肖特
|
||||
|
||||
“**当我低着头的时候,不要打断我。真的,别打断我!**当我沉浸在某件事物中时,这样做会造成我至少需要花费两个小时,才能让我的大脑重新回到之前的状态。感觉很痛苦。真的。你可以发个邮件让我去有白板的地方。然后从客户的角度而不是你的角度——通过画图的方式——分享下有什么问题。要知道,可能同时会有十几个客户问题缠绕在我的脑海中,如果你的问题听起来就是‘这样子做会让我在我的领导面前显得很好’的那一类问题,那么相比我脑袋中已经有的真正的客户问题而言,它不会得到更多的关注的。画个图,给我点时间思考。当我准备分享我的看法的时候,保证有多支马克笔可以使用。准备好接受你对问题的假设有可能完全是错误的。”—— 凯瑟琳·路易斯
|
||||
|
||||
“感谢和鼓励就是解决的方法,感谢可能不是一份工作评估,但是感谢能让人舒服地感受到自己并不仅仅是一个活着的独立实体,**因而每个人都能够感觉到自己是被倾听的,而不是被嘲笑或者低估的**。”—— 阿布希什克·塔姆拉卡尔
|
||||
|
||||
### 结语
|
||||
|
||||
在与内向的 DevOps 爱好者的这次交谈中,我们最大的启迪就是平等:其他人需要被怎样对待,就怎样对待他们,同时你想被怎样对待,就去要求别人怎样对待你。无论你是内向还是外向,我们都需要承认我们并非全以相同的一种方式体验这个世界。我们的同事应当被给予足够的空间以完成他们的工作,通过讨论他们的需求作为了解如何支持他们的开始。我们的差异正是我们的社区如此特别的原因,它让我们的工作对更多的人更加的有用。与别人沟通最有效的方式,就是对于你们两者而言都可行的方式。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/7/devops-introverted-people
|
||||
|
||||
作者:[Matthew Broberg][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[XLCYun](https://github.com/XLCYun)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mbbroberg
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_QandAorange_520x292_0311LL.png?itok=qa3hHSou (Q and A letters)
|
||||
[2]: https://opensource.com/devops-team
|
||||
[3]: https://www.inc.com/melanie-curtin/are-you-shy-or-introverted-science-says-this-is-1-primary-difference.html
|
||||
[4]: https://www.myersbriggs.org/my-mbti-personality-type/mbti-basics/extraversion-or-introversion.htm?bhcp=1
|
||||
[5]: https://lifehacker.com/lets-quit-it-with-the-introvert-extrovert-nonsense-1713772952
|
||||
[6]: https://www.psychologytoday.com/us/blog/the-gen-y-guide/201710/the-majority-people-are-not-introverts-or-extroverts
|
@ -0,0 +1,235 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11673-1.html)
|
||||
[#]: subject: (24 sysadmin job interview questions you should know)
|
||||
[#]: via: (https://opensource.com/article/19/7/sysadmin-job-interview-questions)
|
||||
[#]: author: (DirectedSoul https://opensource.com/users/directedsoul)
|
||||
|
||||
24 个必知必会的系统管理员面试问题
|
||||
======
|
||||
|
||||
> 即将进行系统管理员工作面试吗?阅读本文,了解你可能会遇到的一些问题以及可能的答案。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/14/124906g3vrkr3vrvqdkw7f.jpg)
|
||||
|
||||
作为一个经常与计算机打交道的极客,在硕士毕业后在 IT 行业选择我的职业是很自然的选择。因此,我认为走上系统管理员之路是正确的路径。在我的职业生涯中,我对求职面试过程非常熟悉。现在来看一下对该职位的预期、职业发展道路,以及一系列常见面试问题及我的回答。
|
||||
|
||||
### 系统管理员的典型任务和职责
|
||||
|
||||
组织需要了解系统工作原理的人员,以确保数据安全并保持服务平稳运行。你可能会问:“等等,是不是系统管理员还能做更多的事情?”
|
||||
|
||||
你是对的。现在,一般来说,让我们看一下典型的系统管理员的日常任务。根据公司的需求和人员的技能水平,系统管理员的任务从管理台式机、笔记本电脑、网络和服务器到设计组织的 IT 策略不等。有时,系统管理员甚至负责购买和订购新的 IT 设备。
|
||||
|
||||
那些寻求系统管理工作以作为其职业发展道路的人可能会发现,由于 IT 领域的快速变化是不可避免的,因此难以保持其技能和知识的最新状态。所有人都会想到的下一个自然而然的问题是 IT 专业人员如何掌握最新的更新和技能。
|
||||
|
||||
### 简单的问题
|
||||
|
||||
这是你将遇到的一些最基本的问题,以及我的答案:
|
||||
|
||||
**1、你在 \*nix 服务器上登录后键入的前五个命令是什么?**
|
||||
|
||||
> * `lsblk` 以查看所有的块设备信息
|
||||
> * `who` 查看谁登录到服务器
|
||||
> * `top`,以了解服务器上正在运行的进程
|
||||
> * `df -khT` 以查看服务器上可用的磁盘容量
|
||||
> * `netstat` 以查看哪些 TCP 网络连接处于活动状态
|
||||
|
||||
**2、如何使进程在后台运行,这样做的好处是什么?**
|
||||
|
||||
> 你可以通过在命令末尾添加特殊字符 `&` 来使进程在后台运行。通常,执行时间太长并且不需要用户交互的应用程序可以放到后台,以便我们可以在终端中继续工作。([引文][2])
|
||||
|
||||
**3、以 root 用户身份运行这些命令是好事还是坏事?**
|
||||
|
||||
> 由于两个主要问题,以 root 身份运行(任何命令)是不好的。第一个是*风险*。当你以 **root** 身份登录时,无法避免你由于粗心大意而犯错。如果你尝试以带有潜在危害的方式更改系统,则需要使用 `sudo`,它会引入一个暂停(在你输入密码时),以确保你不会犯错。
|
||||
>
|
||||
> 第二个原因是*安全*。如果你不知道管理员用户的登录信息,则系统更难被攻击。拥有 root 的访问权限意味着你已经能够进行管理员身份下的一半工作任务。
|
||||
|
||||
**4、`rm` 和 `rm -rf` 有什么区别?**
|
||||
|
||||
> `rm` 命令本身仅删除指明的文件(而不删除目录)。使用 `-rf` 标志,你添加了两个附加功能:`-r`(或等价的 `-R`、`--recursive`)标志可以递归删除目录的内容,包括隐藏的文件和子目录;而 `-f`(或 `--force`)标志使 `rm` 忽略不存在的文件,并且从不提示你进行确认。
|
||||
|
||||
**5、有一个大小约为 15GB 的 `Compress.tgz` 文件。你如何列出其内容,以及如何仅提取出特定文件?**
|
||||
|
||||
> 要列出文件的内容:
|
||||
>
|
||||
> `tar tf archive.tgz`
|
||||
>
|
||||
> 要提取特定文件:
|
||||
>
|
||||
> `tar xf archive.tgz filename`
|
||||
|
||||
### 有点难度的问题
|
||||
|
||||
这是你可能会遇到的一些较难的问题,以及我的答案:
|
||||
|
||||
**6、什么是 RAID?什么是 RAID 0、RAID 1、RAID 5、RAID 6 和 RAID 10?**
|
||||
|
||||
> RAID(<ruby>廉价磁盘冗余阵列<rt>Redundant Array of Inexpensive Disks</rt></ruby>)是一种用于提高数据存储性能和/或可靠性的技术。RAID 级别为:
|
||||
>
|
||||
> * RAID 0:也称为磁盘条带化,这是一种分解文件并将数据分布在 RAID 组中所有磁盘驱动器上的技术。它没有防止磁盘失败的保障。([引文][3])
|
||||
> * RAID 1:一种流行的磁盘子系统,通过在两个驱动器上写入相同的数据来提高安全性。RAID 1 被称为*镜像*,它不会提高写入性能,但读取性能可能会提高到每个磁盘性能的总和。另外,如果一个驱动器发生故障,则会使用第二个驱动器,发生故障的驱动器需要手动更换。更换后,RAID 控制器会将可工作的驱动器的内容复制到新驱动器上。
|
||||
> * RAID 5:一种磁盘子系统,可通过计算奇偶校验数据来提高安全性和提高速度。RAID 5 通过跨三个或更多驱动器交错数据(条带化)来实现此目的。在单个驱动器发生故障时,后续读取可以从分布式奇偶校验计算出,从而不会丢失任何数据。
|
||||
> * RAID 6:通过添加另一个奇偶校验块来扩展 RAID 5。此级别至少需要四个磁盘,并且可以在任何两个并发磁盘故障的情况下继续执行读/写操作。RAID 6 不会对读取操作造成性能损失,但由于与奇偶校验计算相关的开销,因此确实会对写入操作造成性能损失。
|
||||
> * RAID 10:RAID 10 也称为 RAID 1 + 0,它结合了磁盘镜像和磁盘条带化功能来保护数据。它至少需要四个磁盘,并且跨镜像对对数据进行条带化。只要每个镜像对中的一个磁盘起作用,就可以检索数据。如果同一镜像对中的两个磁盘发生故障,则所有数据将丢失,因为带区集中没有奇偶校验。([引文][4])
|
||||
|
||||
**7、`ping` 命令使用哪个端口?**
|
||||
|
||||
> `ping` 命令使用 ICMP。具体来说,它使用 ICMP 回显请求和应答包。
|
||||
>
|
||||
> ICMP 不使用 UDP 或 TCP 通信服务:相反,它使用原始的 IP 通信服务。这意味着,ICMP 消息直接承载在 IP 数据报数据字段中。
|
||||
|
||||
**8、路由器和网关之间有什么区别?什么是默认网关?**
|
||||
|
||||
> *路由器*描述的是一种通用技术功能(第 3 层转发)或用于该目的的硬件设备,而*网关*描述的是本地网段的功能(提供到其他地方的连接性)。你还可以说“将路由器设置为网关”。另一个术语是“跳”,它描述了子网之间的转发。
|
||||
>
|
||||
> 术语*默认网关*表示局域网上的路由器,它的责任是作为对局域网外部的计算机通信的第一个联系点。
|
||||
|
||||
**9、解释一下 Linux 的引导过程。**
|
||||
|
||||
> BIOS -> 主引导记录(MBR) -> GRUB -> 内核 -> 初始化 -> 运行级
|
||||
|
||||
**10、服务器启动时如何检查错误消息?**
|
||||
|
||||
> 内核消息始终存储在 kmsg 缓冲区中,可通过 `dmesg` 命令查看。
|
||||
>
|
||||
> 引导出现的问题和错误要求系统管理员结合某些特定命令来查看某些重要文件,这些文件不同版本的 Linux 处理方式不同:
|
||||
>
|
||||
> * `/var/log/boot.log` 是系统引导日志,其中包含系统引导过程中展开的所有内容。
|
||||
> * `/var/log/messages` 存储全局系统消息,包括系统引导期间记录的消息。
|
||||
> * `/var/log/dmesg` 包含内核环形缓冲区信息。
|
||||
|
||||
**11、符号链接和硬链接有什么区别?**
|
||||
|
||||
> *符号链接*(*软链接*)实际是到原始文件的链接,而*硬链接*是原始文件的镜像副本。如果删除原始文件,则该软链接就没有用了,因为它指向的文件不存在了。如果是硬链接,则完全相反。如果删除原始文件,则硬链接仍然包含原始文件中的数据。([引文][5])
|
||||
|
||||
**12、如何更改内核参数?你可能需要调整哪些内核选项?**
|
||||
|
||||
> 要在类 Unix 系统中设置内核参数,请首先编辑文件 `/etc/sysctl.conf`。进行更改后,保存文件并运行 `sysctl -p` 命令。此命令使更改永久生效,而无需重新启动计算机
|
||||
|
||||
**13、解释一下 `/proc` 文件系统。**
|
||||
|
||||
> `/proc` 文件系统是虚拟的,并提供有关内核、硬件和正在运行的进程的详细信息。由于 `/proc` 包含虚拟文件,因此称为“虚拟文件系统”。这些虚拟文件具有独特性。其中大多数显示为零字节。
|
||||
>
|
||||
> 虚拟文件,例如 `/proc/interrupts`、`/proc/meminfo`、`/proc/mounts` 和 `/proc/partitions`,提供了系统硬件的最新信息。其他诸如 `/proc/filesystems` 和 `/proc/sys` 目录提供系统配置信息和接口。
|
||||
|
||||
**14、如何在没有密码的情况下以其他用户身份运行脚本?**
|
||||
|
||||
> 例如,如果你可以编辑 sudoers 文件(例如 `/private/etc/sudoers`),则可以使用 `visudo` 添加以下[内容][2]:
|
||||
>
|
||||
> `user1 ALL =(user2)NOPASSWD:/opt/scripts/bin/generate.sh`
|
||||
|
||||
**15、什么是 UID 0 toor 帐户?是被入侵了么?**
|
||||
|
||||
> `toor` 用户是备用的超级用户帐户,其中 `toor` 是 `root` 反向拼写。它预期与非标准 shell 一起使用,因此 `root` 的默认 shell 不需要更改。
|
||||
>
|
||||
> 此用途很重要。这些 shell 不是基本发行版的一部分,而是从 ports 或软件包安装的,它们安装在 `/usr/local/bin` 中,默认情况下,位于其他文件系统上。如果 root 的 shell 位于 `/usr/local/bin` 中,并且未挂载包含 `/usr/local/bin` 的文件系统,则 root 无法登录以解决问题,并且系统管理员必须重新启动进入单用户模式来输入 shell 程序的路径。
|
||||
|
||||
### 更难的问题
|
||||
|
||||
这是你可能会遇到的甚至更困难的问题:
|
||||
|
||||
**16、`tracert` 如何工作,使用什么协议?**
|
||||
|
||||
> 命令 `tracert`(或 `traceroute`,具体取决于操作系统)使你可以准确地看到在连接到最终目的地的连接链条中所触及的路由器。如果你遇到无法连接或无法 `ping` 通最终目的地的问题,则可以使用 `tracert` 来帮助你确定连接链在何处停止。([引文][6])
|
||||
>
|
||||
> 通过此信息,你可以联系正确的人;无论是你自己的防火墙、ISP、目的地的 ISP 还是中间的某个位置。 `tracert` 命令像 `ping` 一样使用 ICMP 协议,但也可以使用 TCP 三步握手的第一步来发送 SYN 请求以进行响应。
|
||||
|
||||
**17、使用 `chroot` 的主要优点是什么?我们何时以及为什么使用它?在 chroot 环境中,`mount /dev`、`mount /proc` 和 `mount /sys` 命令的作用是什么?**
|
||||
|
||||
> chroot 环境的优点是文件系统与物理主机是隔离的,因为 chroot 在文件系统内部有一个单独的文件系统。区别在于 `chroot` 使用新创建的根目录(`/`)作为其根目录。
|
||||
>
|
||||
> chroot 监狱可让你将进程及其子进程与系统其余部分隔离。它仅应用于不以 root 身份运行的进程,因为 root 用户可以轻松地脱离监狱。
|
||||
>
|
||||
> 该思路是创建一个目录树,在其中复制或链接运行该进程所需的所有系统文件。然后,你可以使用 `chroot()` 系统调用来告诉它根目录现在位于此新树的基点上,然后启动在该 chroot 环境中运行的进程。由于该命令因此而无法引用修改后的根目录之外的路径,因此它无法在这些位置上执行恶意操作(读取、写入等)。([引文][7])
|
||||
|
||||
**18、如何保护你的系统免遭黑客攻击?**
|
||||
|
||||
> 遵循最低特权原则和这些做法:
|
||||
>
|
||||
> * 使用公钥加密,它可提供出色的安全性。
|
||||
> * 增强密码复杂性。
|
||||
> * 了解为什么要对上述规则设置例外。
|
||||
> * 定期检查你的例外情况。
|
||||
> * 让具体的人对失败负责。(它使你保持警惕。)([引文][8])
|
||||
|
||||
**19、什么是 LVM,使用 LVM 有什么好处?**
|
||||
|
||||
> LVM(逻辑卷管理)是一种存储设备管理技术,该技术使用户能够合并和抽象化组件存储设备的物理布局,从而可以更轻松、灵活地进行管理。使用设备映射器的 Linux 内核框架,当前迭代(LVM2)可用于将现有存储设备收集到组中,并根据需要从组合的空间分配逻辑单元。
|
||||
|
||||
**20、什么是粘性端口?**
|
||||
|
||||
> 粘性端口是网络管理员最好的朋友,也是最头痛的事情之一。它们允许你设置网络,以便通过将交换机上的每个端口锁定到特定的 MAC 地址,仅允许一台(或你指定的数字)计算机在该端口上进行连接。
|
||||
|
||||
**21、解释一下端口转发?**
|
||||
|
||||
> 尝试与安全的网络内部的系统进行通信时,从外部进行通信可能非常困难,这是很显然的。因此,在路由器本身或其他连接管理设备中使用端口转发表可以使特定流量自动转发到特定目的地。例如,如果你的网络上运行着一台 Web 服务器,并且想从外部授予对该服务器的访问权限,则可以将端口转发设置为该服务器上的端口 80。这意味着在 Web 浏览器中输入你的(外网)IP 地址的任何人都将立即连接到该服务器的网站。
|
||||
>
|
||||
> 请注意,通常不建议允许从你的网络外部直接访问服务器。
|
||||
|
||||
**22、对于 IDS,误报和漏报是什么?**
|
||||
|
||||
> 当入侵检测系统(IDS)设备为实际上没有发生的入侵生成警报时,这是<ruby>误报(假阳性)<rt>false positive</rt></ruby>。如果设备未生成任何警报,而入侵实际上已发生,则为<ruby>漏报(假阴性)</rt></ruby>。
|
||||
|
||||
**23、解释一下 `:(){ :|:& };:`,如果已经登录系统,如何停止此代码?**
|
||||
|
||||
> 这是一枚复刻炸弹。它分解如下:
|
||||
>
|
||||
> * `:()` 定义了函数,以 `:` 作为函数名,并且空括号表示它不接受任何参数。
|
||||
> * `{}` 是函数定义的开始和结束。
|
||||
> * `:|:` 将函数 `:` 的副本加载到内存中,并将其输出通过管道传递给函数 `:` 的另一个副本,该副本也必须加载到内存中。
|
||||
> * `&` 使前一个命令行成为后台进程,因此即使父进程被自动杀死,子进程也不会被杀死。
|
||||
> * `:` 执行该函数,因此连锁反应开始。
|
||||
>
|
||||
> 保护多用户系统的最佳方法是使用特权访问管理(PAM)来限制用户可以使用的进程数。
|
||||
>
|
||||
> 复刻炸弹的最大问题是它发起了太多进程。因此,如果你已经登录系统,我们有两种尝试解决此问题的方法。一种选择是执行一个 `SIGSTOP` 命令来停止进程,例如:
|
||||
>
|
||||
> `killall -STOP -u user1`
|
||||
>
|
||||
> 如果由于占用了所有进程而无法使用命令行,则必须使用 `exec` 强制其运行:
|
||||
>
|
||||
> `exec killall -STOP -u user1`
|
||||
>
|
||||
> 对于复刻炸弹,最好的选择是防患于未然。
|
||||
|
||||
**24、什么是 OOM 杀手,它如何决定首先杀死哪个进程?**
|
||||
|
||||
> 如果内存被进程彻底耗尽,可能会威胁到系统的稳定性,那么<ruby>内存不足<rt>out of memory</rt></ruby>(OOM)杀手就登场了。
|
||||
>
|
||||
> OOM 杀手首先必须选择要杀死的最佳进程。*最佳*在这里指的是在被杀死时将释放最大内存的进程,并且对系统来说最不重要。主要目标是杀死最少数量的进程,以最大程度地减少造成的损害,同时最大化释放的内存量。
|
||||
>
|
||||
> 为了实现此目标,内核为每个进程维护一个 `oom_score`。你可以在 `/proc` 文件系统中的 `pid` 目录下的看到每个进程的 `oom_score`:
|
||||
>
|
||||
> `$ cat /proc/10292/oom_score`
|
||||
>
|
||||
> 任何进程的 `oom_score` 值越高,在内存不足的情况下被 OOM 杀手杀死的可能性就越高。([引文][9])
|
||||
|
||||
### 总结
|
||||
|
||||
系统管理人员的薪水[差别很大][10],有些网站上说年薪在 70,000 到 100,000 美元之间,具体取决于地点、组织的规模以及你的教育水平以及多年的工作经验。系统管理的职业道路最终归结为你对使用服务器和解决那些酷问题的兴趣。现在,我要说,继续前进,实现你的梦想之路吧!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/7/sysadmin-job-interview-questions
|
||||
|
||||
作者:[DirectedSoul][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/directedsoul
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_HowToFish_520x292.png?itok=DHbdxv6H (Question and answer.)
|
||||
[2]: https://github.com/trimstray/test-your-sysadmin-skills
|
||||
[3]: https://www.waytoeasylearn.com/2016/05/netapp-filer-tutorial.html
|
||||
[4]: https://searchstorage.techtarget.com/definition/RAID-10-redundant-array-of-independent-disks
|
||||
[5]: https://www.answers.com/Q/What_is_hard_link_and_soft_link_in_Linux
|
||||
[6]: https://www.wisdomjobs.com/e-university/network-administrator-interview-questions.html
|
||||
[7]: https://unix.stackexchange.com/questions/105/chroot-jail-what-is-it-and-how-do-i-use-it
|
||||
[8]: https://serverfault.com/questions/391370/how-to-prevent-zero-day-attacks
|
||||
[9]: https://unix.stackexchange.com/a/153586/8369
|
||||
[10]: https://blog.netwrix.com/2018/07/23/systems-administrator-salary-in-2018-how-much-can-you-earn/
|
82
published/201912/20190827 curl exercises.md
Normal file
82
published/201912/20190827 curl exercises.md
Normal file
@ -0,0 +1,82 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (hanwckf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11648-1.html)
|
||||
[#]: subject: (curl exercises)
|
||||
[#]: via: (https://jvns.ca/blog/2019/08/27/curl-exercises/)
|
||||
[#]: author: (Julia Evans https://jvns.ca/)
|
||||
|
||||
21 个 curl 命令练习
|
||||
======
|
||||
|
||||
最近,我对人们如何学习新事物感兴趣。我正在读 Kathy Sierra 的好书《[Badass: Making Users Awesome][1]》,它探讨了有关“刻意练习”的想法。这个想法是,你找到一个可以用三节 45 分钟课程内能够学会的小技能,并专注于学习这项小技能。因此,作为一项练习,我尝试考虑一项能够在三节 45 分钟课程内学会的计算机技能。
|
||||
|
||||
我认为使用 `curl` 构造 HTTP 请求也许就是这样的一项技能,所以这里有一些 `curl` 练习作为实验!
|
||||
|
||||
### 什么是 curl ?
|
||||
|
||||
`curl` 是用于构造 HTTP 请求的命令行工具。我喜欢使用 `curl`,因为它能够很轻松地测试服务器或 API 的行为是否符合预期,但是刚开始接触它的时候会让你感到一些困惑!
|
||||
|
||||
下面是一幅解释 `curl` 常用命令行参数的漫画 (在我的 [Bite Size Networking][2] 杂志的第 6 页)。
|
||||
|
||||
![](https://jvns.ca/images/curl.jpeg)
|
||||
|
||||
### 熟能生巧
|
||||
|
||||
对于任何命令行工具,我认为熟练使用是很有帮助的,能够做到只输入必要的命令真是太好了。例如,最近我在测试 Gumroad API,我只需要输入:
|
||||
|
||||
```
|
||||
curl https://api.gumroad.com/v2/sales \
|
||||
-d "access_token=<SECRET>" \
|
||||
-X GET -d "before=2016-09-03"
|
||||
```
|
||||
|
||||
就能从命令行中得到想要的结果。
|
||||
|
||||
### 21 个 curl 练习
|
||||
|
||||
这些练习是用来理解如何使用 `curl` 构造不同种类的 HTTP 请求的,它们是故意有点重复的,基本上包含了我需要 `curl` 做的任何事情。
|
||||
|
||||
为了简单起见,我们将对 https://httpbin.org 发起一系列 HTTP 请求,httpbin 接受 HTTP 请求,然后在响应中回显你所发起的 HTTP 请求。
|
||||
|
||||
1. 请求 <https://httpbin.org>
|
||||
2. 请求 <https://httpbin.org/anything>,它将会解析你发起的请求,并且在响应中回显。`curl` 默认发起的是 GET 请求
|
||||
3. 向 <https://httpbin.org/anything> 发起 GET 请求
|
||||
4. 向 <https://httpbin.org/anything> 发起 GET 请求,但是这次需要添加一些查询参数(设置 `value=panda`)
|
||||
5. 请求 Google 的 `robots.txt` 文件 ([www.google.com/robots.txt][3])
|
||||
6. 向 <https://httpbin.org/anything> 发起 GET 请求,并且设置请求头为 `User-Agent: elephant`
|
||||
7. 向 <https://httpbin.org/anything> 发起 DELETE 请求
|
||||
8. 请求 <https://httpbin.org/anything> 并获取响应头信息
|
||||
9. 向 <https://httpbin.com/anything> 发起请求体为 JSON `{"value": "panda"}` 的 POST 请求
|
||||
10. 发起与上一次相同的 POST 请求,但是这次要把请求头中的 `Content-Type` 字段设置成 `application/json`(因为 POST 请求需要一个与请求体相匹配的 `Content-Type` 请求头字段)。查看响应体中的 `json` 字段,对比上一次得到的响应体
|
||||
11. 向 <https://httpbin.org/anything> 发起 GET 请求,并且在请求头中设置 `Accept-Encoding: gzip`(将会发生什么?为什么会这样?)
|
||||
12. 将一些 JSON 放在文件中,然后向 <https://httpbin.org/anything> 发起请求体为该文件的 POST 请求
|
||||
13. 设置请求头为 `Accept: image/png` 并且向 <https://httpbin.org/image> 发起请求,将输出保存为 PNG 文件,然后使用图片浏览器打开。尝试使用不同的 `Accept:` 字段去请求此 URL
|
||||
14. 向 <https://httpbin.org/anything> 发起 PUT 请求
|
||||
15. 请求 <https://httpbin.org/image/jpeg> 并保存为文件,然后使用你的图片编辑器打开这个文件
|
||||
16. 请求 <https://www.twitter.com>,你将会得到空的响应。让 `curl` 显示出响应头信息,并尝试找出响应内容为空的原因
|
||||
17. 向 <https://httpbin.org/anything> 发起任意的请求,同时设置一些无意义的请求头(例如:`panda: elephant`)
|
||||
18. 请求 <https://httpbin.org/status/404> 和 <https://httpbin.org/status/200>,然后再次请求它们并且让 curl 显示响应头信息
|
||||
19. 请求 <https://httpbin.org/anything> 并且设置用户名和密码(使用 `-u username:password`)
|
||||
20. 设置 `Accept-Language: es-ES` 的请求头用以下载 Twitter 的西班牙语主页 (<https://twitter.com>)
|
||||
21. 使用 `curl` 向 Stripe API 发起请求(请查看 <https://stripe.com/docs/development> 了解如何使用,他们会给你一个测试用的 API key)。尝试向 <https://httpbin.org/anything> 发起相同的请求
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2019/08/27/curl-exercises/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[hanwckf](https://github.com/hanwckf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.amazon.com/Badass-Making-Awesome-Kathy-Sierra/dp/1491919019
|
||||
[2]: https://wizardzines.com/zines/bite-size-networking
|
||||
[3]: http://www.google.com/robots.txt
|
220
published/201912/20190927 5 tips for GNU Debugger.md
Normal file
220
published/201912/20190927 5 tips for GNU Debugger.md
Normal file
@ -0,0 +1,220 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11647-1.html)
|
||||
[#]: subject: (5 tips for GNU Debugger)
|
||||
[#]: via: (https://opensource.com/article/19/9/tips-gnu-debugger)
|
||||
[#]: author: (Tim Waugh https://opensource.com/users/twaugh)
|
||||
|
||||
5 个鲜为人知 GNU 调试器(GDB)技巧
|
||||
======
|
||||
|
||||
> 了解如何使用 gdb 的一些鲜为人知的功能来检查和修复代码。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/05/203701ss8onfvpsnvnsnn5.jpg)
|
||||
|
||||
[GNU 调试器][2](`gdb`)是一种宝贵的工具,可用于在开发程序时检查正在运行的进程并解决问题。
|
||||
|
||||
你可以在特定位置(按函数名称、行号等)设置断点、启用和禁用这些断点、显示和更改变量值,并执行所有调试器希望执行的所有标准操作。但是它还有许多其它你可能没有尝试过的功能。这里有五个你可以尝试一下。
|
||||
|
||||
### 条件断点
|
||||
|
||||
设置断点是学习使用 GNU 调试器的第一步。程序在达到断点时停止,你可以运行 `gdb` 的命令对其进行检查或更改变量,然后再允许该程序继续运行。
|
||||
|
||||
例如,你可能知道一个经常调用的函数有时会崩溃,但仅当它获得某个参数值时才会崩溃。你可以在该函数的开始处设置一个断点并运行程序。每次碰到该断点时都会显示函数参数,并且如果未提供触发崩溃的参数值,则可以继续操作,直到再次调用该函数为止。当这个惹了麻烦的参数触发崩溃时,你可以单步执行代码以查看问题所在。
|
||||
|
||||
|
||||
```
|
||||
(gdb) break sometimes_crashes
|
||||
Breakpoint 1 at 0x40110e: file prog.c, line 5.
|
||||
(gdb) run
|
||||
[...]
|
||||
Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
|
||||
5 fprintf(stderr,
|
||||
(gdb) continue
|
||||
Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
|
||||
5 fprintf(stderr,
|
||||
(gdb) continue
|
||||
```
|
||||
|
||||
为了使此方法更具可重复性,你可以在你感兴趣的特定调用之前计算该函数被调用的次数,并在该断点处设置一个计数器(例如,`continue 30` 以使其在接下来的 29 次到达该断点时忽略它)。
|
||||
|
||||
但是断点真正强大的地方在于它们在运行时评估表达式的能力,这使你可以自动化这种测试。
|
||||
|
||||
```
|
||||
break [LOCATION] if CONDITION
|
||||
|
||||
(gdb) break sometimes_crashes if !f
|
||||
Breakpoint 1 at 0x401132: file prog.c, line 5.
|
||||
(gdb) run
|
||||
[...]
|
||||
Breakpoint 1, sometimes_crashes (f=0x0) at prog.c:5
|
||||
5 fprintf(stderr,
|
||||
(gdb)
|
||||
```
|
||||
|
||||
条件断点使你不必让 `gdb` 每次调用该函数时都去问你要做什么,而是让条件断点仅在特定表达式的值为 `true` 时才使 `gdb` 停止在该位置。如果执行到达条件断点的位置,但表达式的计算结果为 `false`,调试器会自动使程序继续运行,而无需询问用户该怎么做。
|
||||
|
||||
### 断点命令
|
||||
|
||||
GNU 调试器中断点的一个甚至更复杂的功能是能够编写对到达断点的响应的脚本。断点命令使你可以编写一系列 GNU 调试器命令,以在到达该断点时运行。
|
||||
|
||||
我们可以使用它来规避在 `sometimes_crashes` 函数中我们已知的错误,并在它提供空指针时使其无害地从该函数返回。
|
||||
|
||||
我们可以使用 `silent` 作为第一行,以更好地控制输出。否则,每次命中断点时,即使在运行断点命令之前,也会显示堆栈帧。
|
||||
|
||||
```
|
||||
(gdb) break sometimes_crashes
|
||||
Breakpoint 1 at 0x401132: file prog.c, line 5.
|
||||
(gdb) commands 1
|
||||
Type commands for breakpoint(s) 1, one per line.
|
||||
End with a line saying just "end".
|
||||
>silent
|
||||
>if !f
|
||||
>frame
|
||||
>printf "Skipping call\n"
|
||||
>return 0
|
||||
>continue
|
||||
>end
|
||||
>printf "Continuing\n"
|
||||
>continue
|
||||
>end
|
||||
(gdb) run
|
||||
Starting program: /home/twaugh/Documents/GDB/prog
|
||||
warning: Loadable section ".note.gnu.property" outside of ELF segments
|
||||
Continuing
|
||||
Continuing
|
||||
Continuing
|
||||
#0 sometimes_crashes (f=0x0) at prog.c:5
|
||||
5 fprintf(stderr,
|
||||
Skipping call
|
||||
[Inferior 1 (process 9373) exited normally]
|
||||
(gdb)
|
||||
```
|
||||
|
||||
### 转储二进制内存
|
||||
|
||||
GNU 调试器内置支持使用 `x` 命令以各种格式检查内存,包括八进制、十六进制等。但是我喜欢并排看到两种格式:左侧为十六进制字节,右侧为相同字节表示的 ASCII 字符。
|
||||
|
||||
当我想逐字节查看文件的内容时,经常使用 `hexdump -C`(`hexdump` 来自 [util-linux][3] 软件包)。这是 `gdb` 的 `x` 命令显示的十六进制字节:
|
||||
|
||||
```
|
||||
(gdb) x/33xb mydata
|
||||
0x404040 <mydata> : 0x02 0x01 0x00 0x02 0x00 0x00 0x00 0x01
|
||||
0x404048 <mydata+8> : 0x01 0x47 0x00 0x12 0x61 0x74 0x74 0x72
|
||||
0x404050 <mydata+16>: 0x69 0x62 0x75 0x74 0x65 0x73 0x2d 0x63
|
||||
0x404058 <mydata+24>: 0x68 0x61 0x72 0x73 0x65 0x75 0x00 0x05
|
||||
0x404060 <mydata+32>: 0x00
|
||||
```
|
||||
|
||||
如果你想让 `gdb` 像 `hexdump` 一样显示内存怎么办?这是可以的,实际上,你可以将这种方法用于你喜欢的任何格式。
|
||||
|
||||
通过使用 `dump` 命令以将字节存储在文件中,结合 `shell` 命令以在文件上运行 `hexdump` 以及`define` 命令,我们可以创建自己的新的 `hexdump` 命令来使用 `hexdump` 显示内存内容。
|
||||
|
||||
```
|
||||
(gdb) define hexdump
|
||||
Type commands for definition of "hexdump".
|
||||
End with a line saying just "end".
|
||||
>dump binary memory /tmp/dump.bin $arg0 $arg0+$arg1
|
||||
>shell hexdump -C /tmp/dump.bin
|
||||
>end
|
||||
```
|
||||
|
||||
这些命令甚至可以放在 `~/.gdbinit` 文件中,以永久定义 `hexdump` 命令。以下是它运行的例子:
|
||||
|
||||
```
|
||||
(gdb) hexdump mydata sizeof(mydata)
|
||||
00000000 02 01 00 02 00 00 00 01 01 47 00 12 61 74 74 72 |.........G..attr|
|
||||
00000010 69 62 75 74 65 73 2d 63 68 61 72 73 65 75 00 05 |ibutes-charseu..|
|
||||
00000020 00 |.|
|
||||
00000021
|
||||
```
|
||||
|
||||
### 行内反汇编
|
||||
|
||||
有时你想更多地了解导致崩溃的原因,而源代码还不够。你想查看在 CPU 指令级别发生了什么。
|
||||
|
||||
`disassemble` 命令可让你查看实现函数的 CPU 指令。但是有时输出可能很难跟踪。通常,我想查看与该函数源代码的特定部分相对应的指令。为此,请使用 `/s` 修饰符在反汇编中包括源代码行。
|
||||
|
||||
```
|
||||
(gdb) disassemble/s main
|
||||
Dump of assembler code for function main:
|
||||
prog.c:
|
||||
11 {
|
||||
0x0000000000401158 <+0>: push %rbp
|
||||
0x0000000000401159 <+1>: mov %rsp,%rbp
|
||||
0x000000000040115c <+4>: sub $0x10,%rsp
|
||||
|
||||
12 int n = 0;
|
||||
0x0000000000401160 <+8>: movl $0x0,-0x4(%rbp)
|
||||
|
||||
13 sometimes_crashes(&n);
|
||||
0x0000000000401167 <+15>: lea -0x4(%rbp),%rax
|
||||
0x000000000040116b <+19>: mov %rax,%rdi
|
||||
0x000000000040116e <+22>: callq 0x401126 <sometimes_crashes>
|
||||
[...snipped...]
|
||||
```
|
||||
|
||||
这里,用 `info` 寄存器查看所有 CPU 寄存器的当前值,以及用如 `stepi` 这样命令一次执行一条指令,可以使你对程序有了更详细的了解。
|
||||
|
||||
### 反向调试
|
||||
|
||||
有时,你希望自己可以逆转时间。想象一下,你已经达到了变量的监视点。监视点像是一个断点,但不是在程序中的某个位置设置,而是在表达式上设置(使用 `watch` 命令)。每当表达式的值更改时,执行就会停止,并且调试器将获得控制权。
|
||||
|
||||
想象一下你已经达到了这个监视点,并且由该变量使用的内存已更改了值。事实证明,这可能是由更早发生的事情引起的。例如,内存已释放,现在正在重新使用。但是它是何时何地被释放的呢?
|
||||
|
||||
GNU 调试器甚至可以解决此问题,因为你可以反向运行程序!
|
||||
|
||||
它通过在每个步骤中仔细记录程序的状态来实现此目的,以便可以恢复以前记录的状态,从而产生时间倒流的错觉。
|
||||
|
||||
要启用此状态记录,请使用 `target record-full` 命令。然后,你可以使用一些听起来不太可行的命令,例如:
|
||||
|
||||
* `reverse-step`,倒退到上一个源代码行
|
||||
* `*reverse-next`,它倒退到上一个源代码行,向后跳过函数调用
|
||||
* `reverse-finish`,倒退到当前函数即将被调用的时刻
|
||||
* `reverse-continue`,它返回到程序中的先前状态,该状态将(现在)触发断点(或其他导致断点停止的状态)
|
||||
|
||||
这是运行中的反向调试的示例:
|
||||
|
||||
```
|
||||
(gdb) b main
|
||||
Breakpoint 1 at 0x401160: file prog.c, line 12.
|
||||
(gdb) r
|
||||
Starting program: /home/twaugh/Documents/GDB/prog
|
||||
[...]
|
||||
|
||||
Breakpoint 1, main () at prog.c:12
|
||||
12 int n = 0;
|
||||
(gdb) target record-full
|
||||
(gdb) c
|
||||
Continuing.
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0x0000000000401154 in sometimes_crashes (f=0x0) at prog.c:7
|
||||
7 return *f;
|
||||
(gdb) reverse-finish
|
||||
Run back to call of #0 0x0000000000401154 in sometimes_crashes (f=0x0)
|
||||
at prog.c:7
|
||||
0x0000000000401190 in main () at prog.c:16
|
||||
16 sometimes_crashes(0);
|
||||
```
|
||||
|
||||
这些只是 GNU 调试器可以做的一些有用的事情。还有更多有待发现。你最喜欢 `gdb` 的哪个隐藏的、鲜为人知或令人吃惊的功能?请在评论中分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/tips-gnu-debugger
|
||||
|
||||
作者:[Tim Waugh][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/twaugh
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bug_software_issue_tracking_computer_screen.jpg?itok=6qfIHR5y (Bug tracking magnifying glass on computer screen)
|
||||
[2]: https://www.gnu.org/software/gdb/
|
||||
[3]: https://en.wikipedia.org/wiki/Util-linux
|
200
published/201912/20191004 What-s in an open source name.md
Normal file
200
published/201912/20191004 What-s in an open source name.md
Normal file
@ -0,0 +1,200 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (laingke)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11688-1.html)
|
||||
[#]: subject: (What's in an open source name?)
|
||||
[#]: via: (https://opensource.com/article/19/10/open-source-name-origins)
|
||||
[#]: author: (Joshua Allen Holm https://opensource.com/users/holmja)
|
||||
|
||||
开源软件名称中的故事
|
||||
======
|
||||
|
||||
> 有没有想过你喜欢的开源项目或编程语言的名称来自何处?让我们按字母顺序了解一下流行的技术术语背后的起源故事。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/17/225902ogkk85zm4gqlim9h.jpg)
|
||||
|
||||
GNOME、Java、Jupyter、Python……如果你的朋友或家人曾留意过你的工作对话,他们可能会认为你从事文艺复兴时期的民间文学艺术、咖啡烘焙、天文学或动物学工作。这些开源技术的名称从何而来?我们请我们的作者社区提供意见,并汇总了一些我们最喜欢的技术名称的起源故事。
|
||||
|
||||
### Ansible
|
||||
|
||||
“Ansible”这个名称直接来自科幻小说。Ursula Le Guin 的《Rocannon's World》一书中能进行即时(比光速更快)通信的设备被称为 ansibles(显然来自 “answerable” 一词)。Ansibles 开始流行于科幻小说之中,Orson Scott Card 的《Ender's Game》(后来成为受欢迎的电影)中,该设备控制了许多远程太空飞船。对于控制分布式机器的软件来说,这似乎是一个很好的模型,因此 Michael DeHaan(Ansible 的创建者和创始人)借用了这个名称。
|
||||
|
||||
### Apache
|
||||
|
||||
[Apache][2] 是最初于 1995 年发布的开源 Web 服务器。它的名称与著名的美国原住民部落无关;相反,它是指对原始软件代码的重复补丁。因此称之为,“<ruby>一个修补的<rt>A-patchy</rt></ruby>服务器”。
|
||||
|
||||
### awk
|
||||
|
||||
“awk(1) 代表着 Aho、Weinberger、Kernighan(作者)”—— Michael Greenberg
|
||||
|
||||
### Bash
|
||||
|
||||
“最初的 Unix shell,即 Bourne shell,是以其创造者的名字命名的。在开发出来 Bash 时,csh(发音为 ‘seashell’)实际上更受交互登录用户的欢迎。Bash 项目旨在赋予 Bourne shell 新的生命,使其更适合于交互式使用,因此它被命名为 ‘Bourne again shell’,是‘<ruby>重生<rt>born again</rt></ruby>’的双关语。”——Ken Gaillot
|
||||
|
||||
### C
|
||||
|
||||
在早期,AT&T 的 Ken Thompson 和 Dennis Ritchie 发现可以使用更高级的编程语言(而不是低级的、可移植性更低的汇编编程)来编写操作系统和工具。早期有一个叫做 BCPL(<ruby>基本组合编程语言<rt>Basic Combined programming Language</rt></ruby>)的编程系统,Thompson 创建了一个名为 B 的简化版 BCPL,但 B 的灵活性和速度都不高。然后,Ritchie 把 B 的思想扩展成一种叫做 C 的编译语言。”——Jim Hall
|
||||
|
||||
### dd
|
||||
|
||||
“我想你发表这样一篇文章不能不提到 dd。我的外号叫 Didi。发音正确的话听起来像 ‘dd’。我开始学的是 Unix,然后是 Linux,那是在 1993 年,当时我还是个学生。然后我去了军队,来到了我的部队中少数几个使用 Unix(Ultrix)的部门之一(其它部门主要是 VMS),那里的一个人说:‘这么说,你是一个黑客,对吗?你以为你了解 Unix 吗?好的,那么 dd 这个名字的是怎么来的呢?’我不知道,试着猜道:‘<ruby>数据复印机<rt>Data duplicator</rt></ruby>?’所以他说,‘我要告诉你 dd 的故事。dd 是<ruby>转换<rt>convert</rt></ruby>和<ruby>复制<rt>copy</rt></ruby>的缩写(如今人们仍然可以在手册页中看到),但由于 cc 这个缩写已经被 C 编译器占用,所以它被命名为 dd。’就在几年后,我听闻了关于 JCL 的数据定义和 Unix dd 命令不统一的、半开玩笑的语法的真实故事,某种程度是基于此的。”——Yedidyah Bar David
|
||||
|
||||
### Emacs
|
||||
|
||||
经典的<ruby>反 vi<rt>anti-vi</rt></ruby>编辑器,其名称的真正词源并不明显,因为它源自“<ruby>编辑宏<rt>Editing MACroS</rt></ruby>”。但是,它作为一个伟大的宗教亵渎和崇拜的对象,吸引了许多恶作剧般的缩写,例如“Escape Meta Alt Control Shift”(以调侃其对键盘的大量依赖),“<ruby>8MB 并经常发生内存交换<rt>Eight Megabytes And Constantly Swapping</rt></ruby>”(从那时起就很吃内存了),“<ruby>最终分配了所有的计算机存储空间<rt>Eventually malloc()s All Computer Storage</rt></ruby>”和 “<ruby>EMACS 使一台计算机慢<rt>EMACS Makes A Computer Slow</rt></ruby>”——改编自 Jargon File/Hacker's Dictionary
|
||||
|
||||
### Enarx
|
||||
|
||||
[Enarx][3] 是机密计算领域的一个新项目。该项目的设计原则之一是它应该是“可替代的”。因此最初的名字是“psilocybin”(著名的魔术蘑菇)。一般情况下,经理级别的人可能会对这个名称有所抵触,因此考虑使用新名称。该项目的两位创始人 Mike Bursell 和 Nathaniel McCallum 都是古老语言极客,因此他们考虑了许多不同的想法,包括 тайна(Tayna——俄语中代表秘密或神秘——虽然俄语并不是一门古老的语言,但你就不要在乎这些细节了),crypticon(希腊语的意思是完全私生的),cryptidion(希腊中表示小密室),arconus(拉丁语中表示秘密的褒义形容词),arcanum(拉丁语中表示秘密的中性形容词)和 ærn(盎格鲁撒克逊人表示地方、秘密的地方、壁橱、住所、房子,或小屋的词汇)。最后,由于各种原因,包括域名和 GitHub 项目名称的可用性,他们选择了 enarx,这是两个拉丁词根的组合:en-(表示内部)和 -arx(表示城堡、要塞或堡垒)。
|
||||
|
||||
### GIMP
|
||||
|
||||
没有 [GIMP][4] 我们会怎么样?<ruby>GNU 图像处理项目<rt>GNU Image Manipulation Project</rt></ruby>多年来一直是开源的重要基础。[维基百科][5]指出,“1995 年,[Spencer Kimball][6] 和 [Peter Mattis][7] 在加州大学伯克利分校开始为<ruby>实验计算设施<rt>eXperimental Computing Facility</rt></ruby>开发 GIMP,这是一个为期一个学期的项目。”
|
||||
|
||||
### GNOME
|
||||
|
||||
你有没有想过为什么 GNOME 被称为 GNOME?根据[维基百科][8],GNOME 最初是一个表示“<ruby>GNU 网络对象模型环境<rt>GNU Network Object Model Environment</rt></ruby>”的缩写词。现在,该名称不再表示该项目,并且该项目已被放弃,但这个名称仍然保留了下来。[GNOME 3][9] 是 Fedora、红帽企业版、Ubuntu、Debian、SUSE Linux 企业版等发行版的默认桌面环境。
|
||||
|
||||
### Java
|
||||
|
||||
你能想象这种编程语言还有其它名称吗?Java 最初被称为 Oak,但是遗憾的是,Sun Microsystems 的法律团队由于已有该商标而否决了它。所以开发团队又重新给它命名。[据说][10]该语言的工作组在 1995 年 1 月举行了一次大规模的头脑风暴。许多其它名称也被扔掉了,包括 Silk、DNA、WebDancer 等。该团队不希望新名称与过度使用的术语“web”或“net”有任何关系。取而代之的是,他们在寻找更有活力、更有趣、更容易记住的东西。Java 满足了这些要求,并且奇迹般地,团队同意通过了!
|
||||
|
||||
### Jupyter
|
||||
|
||||
现在许多数据科学家和学生在工作中使用 [Jupyter][11] 笔记本。“Jupyter”这个名字是三种开源计算机语言的融合,这三种语言在这个笔记本中都有使用,在数据科学中也很突出:[Julia][12]、[Python][13] 和 [R][14]。
|
||||
|
||||
### Kubernetes
|
||||
|
||||
Kubernetes 源自希腊语中的舵手。Kubernetes 项目创始人 Craig McLuckie 在 [2015 Hacker News][15] 回应中证实了这种词源。他坚持航海主题,解释说,这项技术可以驱动集装箱,就像舵手或驾驶员驾驶集装箱船一样,因此,他选择了 Kubernetes 这个名字。我们中的许多人仍然在尝试正确的发音(koo-bur-NET-eez),因此 替代使用 K8s 也是可以接受的。有趣的是,它与英语单词“<ruby>行政长官<rt>governor</rt></ruby>”具有相同的词源,也与蒸汽机上的机械负反馈装置相同。
|
||||
|
||||
### KDE
|
||||
|
||||
那 K 桌面呢?KDE 最初代表“<ruby>酷桌面环境<rt>Kool Desktop Environment</rt></ruby>”。 它由 [Matthias Ettrich][16] 于 1996 年创立。根据[维基百科][17]上的说法,该名称是对 Unix 上 <ruby>[通用桌面环境][18]<rt>Common Desktop Environment</rt></ruby>(CDE)一词的调侃。
|
||||
|
||||
### Linux
|
||||
|
||||
[Linux][19] 因其发明者 Linus Torvalds 的名字命名的。Linus 最初想将他的作品命名为“Freax”,因为他认为以他自己的名字命名太自负了。根据[维基百科][19]的说法,“赫尔辛基科技大学 Torvalds 的同事 Ari Lemmke 当时是 FTP 服务器的志愿管理员之一,他并不认为‘Freax’是个好名字。因此,他没有征询 Torvalds 就将服务器上的这个项目命名为‘Linux’。”
|
||||
|
||||
以下是一些最受欢迎的 Linux 发行版。
|
||||
|
||||
#### CentOS
|
||||
|
||||
[CentOS][20] 是<ruby>社区企业操作系统<rt>Community Enterprise Operating System</rt></ruby>的缩写。它包含来自 Red Hat Enterprise Linux 的上游软件包。
|
||||
|
||||
#### Debian
|
||||
|
||||
[Debian][21] Linux 创建于 1993 年 9 月,是其创始人 Ian Murdock 和他当时的女友 Debra Lynn 的名字的混成词。
|
||||
|
||||
#### RHEL
|
||||
|
||||
[Red Hat Linux][22] 得名于它的创始人 Marc Ewing,他戴着一顶祖父送给他的康奈尔大学红色<ruby>软呢帽<rt>fedora</rt></ruby>。红帽公司成立于 1993 年 3 月 26 日。[Fedora Linux][23] 最初是一个志愿者项目,旨在为红帽发行版提供额外的软件,它的名字来自红帽的“Shadowman”徽标。
|
||||
|
||||
#### Ubuntu
|
||||
|
||||
[Ubuntu][24] 旨在广泛分享开源软件,它以非洲哲学“<ruby>人的本质<rt>ubuntu</rt></ruby>”命名,可以翻译为“对他人的人道主义”或“我之所以是我,是因为我们都是这样的人”。
|
||||
|
||||
### Moodle
|
||||
|
||||
开源学习平台 [Moodle][25] 是“<ruby>模块化面向对象动态学习环境<rt>modular object-oriented dynamic learning environment</rt></ruby>”的首字母缩写。Moodle 仍然是领先的线上学习平台。全球有近 10.4 万个注册的 Moodle 网站。
|
||||
|
||||
另外两个流行的开源内容管理系统是 Drupal 和 Joomla。Drupal 的名字来自荷兰语 “druppel”,意思是“掉落”。根据维基百科,Joomla 是斯瓦希里语单词“jumla”的[英式拼写][26],在阿拉伯语、乌尔都语和其他语言中是“在一起”的意思。
|
||||
|
||||
### Mozilla
|
||||
|
||||
[Mozilla][27] 是一个成立于 1998 年的开源软件社区。根据其网站,“Mozilla 项目创建于 1998 年,发布了 Netscape 浏览器套件源代码。其旨在利用互联网上成千上万的程序员的创造力,并推动浏览器市场上前所未有的创新水平。” 这个名字是 [Mosaic] [28] 和 Godzilla 的混成词。
|
||||
|
||||
### Nginx
|
||||
|
||||
“许多技术人员都试图装酷,并将它念成‘n’‘g’‘n’‘x’。实际上,很少的一些人做点基本的调查工作,就可以很快发现该名称实际上应该被念成是“EngineX”,指的是功能强大的 web 服务器,像个引擎。”——Jean Sebastien Tougne
|
||||
|
||||
### Perl
|
||||
|
||||
Perl 的创始人 Larry Wall 最初将他的项目命名为“Pearl”。根据维基百科,Wall 想给这种语言起一个有积极含义的简短名字。在 Perl 正式发布之前,Wall 发现了已有 [PEARL][29] 编程语言,于是更改了名称的拼写。
|
||||
|
||||
### Piet 和 Mondrian
|
||||
|
||||
“有两种编程语言以艺术家 Piet Mondrian 命名。一种叫做‘Piet’,另一种叫做‘Mondrian’。(David Morgan-Mar [写道][30]):‘Piet 是一种编程语言,其中的程序看起来像抽象绘画。该语言以几何抽象艺术的开创者 Piet Mondrian 的名字命名。我曾想将这种语言命名为 Mondrian,但是有人告诉我这会让它看起来像一种很普通的脚本语言。哦,好吧,我想我们不能都是深奥的语言作家。’”——Yuval Lifshitz
|
||||
|
||||
### Python
|
||||
|
||||
Python 编程语言的独特名称来自其创建者 Guido Van Rossum,他是英国六人喜剧团体 Monty Python 的粉丝。
|
||||
|
||||
### Raspberry Pi
|
||||
|
||||
Raspberry Pi 以其微小但强大的功能和对低廉的价格而闻名,在开源社区中是最受欢迎的。但是它可爱(和好吃)的名字是从哪里来的呢?在 70 年代和 80 年代,以水果命名的计算机是一种流行的趋势。苹果、橘子、杏……有人饿了吗?根据创始人 Eben Upton 的 [2012 采访] [31],“<ruby>树莓派<rt>Raspberry Pi</rt></ruby>”这个名称是对这种趋势的致敬。树莓也很小,但却很有味道。名称中的“Pi”暗示着这样的事实:最初,该计算机只能运行 Python。
|
||||
|
||||
### Samba
|
||||
|
||||
[Server Message Block][32] 用于在 Linux 上共享 Windows 文件。
|
||||
|
||||
### ScummVM
|
||||
|
||||
[ScummVM][33](《疯狂大楼》虚拟机的脚本创建实用程序)是一个程序,可以在现代计算机上运行一些经典的计算机冒险游戏。最初,它旨在玩用 SCUMM 构建的 LucasArts 的冒险游戏,该游戏最初用于开发《疯狂大楼》,后来又被用来开发 LucasArts 的其它大多数冒险游戏。目前,ScummVM 支持大量游戏引擎,包括 Sierra Online 的 AGI 和 SCI,但仍保留着名称 ScummVM。
|
||||
|
||||
有一个相关的项目 [ResidualVM][34] 之所以得名,是因为它涵盖了 ScummVM 未涵盖的“<ruby>剩余的<rt>residual</rt></ruby>” LucasArts 冒险游戏。 ResidualVM 涵盖的 LucasArts 游戏是使用 GrimE(Grim Engine)开发的,该引擎最初用于开发 Grim Fandango,因此 ResidualVM 的名称是双关语。
|
||||
|
||||
### SQL
|
||||
|
||||
“你可能知道 SQL 代表<ruby>结构化查询语言<rt>Structured Query Language</rt></ruby>,但你知道为什么它经常被读作‘sequel’吗?它是作为原本的‘QUEL’(<ruby>查询语言<rt>QUEry Language</rt></ruby>)的后续(如<ruby>结局<rt>sequel</rt></ruby>)而创建的。”——Ken Gaillot
|
||||
|
||||
### XFCE
|
||||
|
||||
[XFCE][35] 是由 [Olivier Fourdan][36] 创建的一个流行的桌面。它在 1996 年作为 CDE 的替代品出现,最初是 <ruby>XForms 公共环境<rt>XForms Common Environment</rt></ruby>的缩写。
|
||||
|
||||
### Zsh
|
||||
|
||||
Zsh 是一个交互式登录 shell。1990 年,普林斯顿大学的学生 Paul Falstad 写了该 shell 的第一个版本。他在看到当时在普林斯顿大学担任助教的 Zhong Sha 的登录 ID(zsh)后,觉得这个名字听起来像 [shell 的好名字][37],给它起了这个名字。
|
||||
|
||||
还有更多的项目和名称还没有包括在这个列表中。请一定要在评论中分享你的收藏。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/open-source-name-origins
|
||||
|
||||
作者:[Joshua Allen Holm][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[laingke](https://github.com/laingke)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/holmja
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003784_02_os.comcareers_resume_rh1x.png?itok=S3HGxi6E (A person writing.)
|
||||
[2]: https://httpd.apache.org/
|
||||
[3]: https://enarx.io
|
||||
[4]: https://www.gimp.org/
|
||||
[5]: https://en.wikipedia.org/wiki/GIMP
|
||||
[6]: https://en.wikipedia.org/wiki/Spencer_Kimball_(computer_programmer)
|
||||
[7]: https://en.wikipedia.org/wiki/Peter_Mattis
|
||||
[8]: https://en.wikipedia.org/wiki/GNOME
|
||||
[9]: https://www.gnome.org/gnome-3/
|
||||
[10]: https://www.javaworld.com/article/2077265/so-why-did-they-decide-to-call-it-java-.html
|
||||
[11]: https://jupyter.org/
|
||||
[12]: https://julialang.org/
|
||||
[13]: https://www.python.org/
|
||||
[14]: https://www.r-project.org/
|
||||
[15]: https://news.ycombinator.com/item?id=9653797
|
||||
[16]: https://en.wikipedia.org/wiki/Matthias_Ettrich
|
||||
[17]: https://en.wikipedia.org/wiki/KDE
|
||||
[18]: https://sourceforge.net/projects/cdesktopenv/
|
||||
[19]: https://en.wikipedia.org/wiki/Linux
|
||||
[20]: https://www.centos.org/
|
||||
[21]: https://www.debian.org/
|
||||
[22]: https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux
|
||||
[23]: https://getfedora.org/
|
||||
[24]: https://ubuntu.com/about
|
||||
[25]: https://moodle.org/
|
||||
[26]: https://en.wikipedia.org/wiki/Joomla#Historical_background
|
||||
[27]: https://www.mozilla.org/en-US/
|
||||
[28]: https://en.wikipedia.org/wiki/Mosaic_(web_browser)
|
||||
[29]: https://en.wikipedia.org/wiki/PEARL_(programming_language)
|
||||
[30]: http://www.dangermouse.net/esoteric/piet.html
|
||||
[31]: https://www.techspot.com/article/531-eben-upton-interview/
|
||||
[32]: https://www.samba.org/
|
||||
[33]: https://www.scummvm.org/
|
||||
[34]: https://www.residualvm.org/
|
||||
[35]: https://www.xfce.org/
|
||||
[36]: https://en.wikipedia.org/wiki/Olivier_Fourdan
|
||||
[37]: http://www.zsh.org/mla/users/2005/msg00951.html
|
265
published/201912/20191007 Using the Java Persistence API.md
Normal file
265
published/201912/20191007 Using the Java Persistence API.md
Normal file
@ -0,0 +1,265 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (runningwater)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11717-1.html)
|
||||
[#]: subject: (Using the Java Persistence API)
|
||||
[#]: via: (https://opensource.com/article/19/10/using-java-persistence-api)
|
||||
[#]: author: (Stephon Brown https://opensource.com/users/stephb)
|
||||
|
||||
使用 Java 持久化 API
|
||||
======
|
||||
|
||||
> 我们通过为自行车商店构建示例应用程序来学习如何使用 JPA。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/27/000705dymv92hnba2a2322.jpg)
|
||||
|
||||
对应用开发者来说,<ruby>Java 持久化 API<rt>Java Persistence API</rt></ruby>(JPA)是一项重要的 java 功能,需要透彻理解。它为 Java 开发人员定义了如何将对象的方法调用转换为访问、持久化及管理存储在 NoSQL 和关系型数据库中的数据的方案。
|
||||
|
||||
本文通过构建自行车借贷服务的教程示例来详细研究 JPA。此示例会使用 Spring Boot 框架、MongoDB 数据库([已经不开源][2])和 Maven 包管理来构建一个大型应用程序,并且构建一个创建、读取、更新和删除(CRUD)层。这儿我选择 NetBeans 11 作为我的 IDE。
|
||||
|
||||
此教程仅从开源的角度来介绍 Java 持久化 API 的工作原理,不涉及其作为工具的使用说明。这全是关于编写应用程序模式的学习,但对于理解具体的软件实现也很益处。可以从我的 [GitHub 仓库][3]来获取相关代码。
|
||||
|
||||
### Java: 不仅仅是“豆子”
|
||||
|
||||
Java 是一门面向对象的编程语言,自 1996 年发布第一版 Java 开发工具(JDK)起,已经变化了很多很多。要了解其各种发展及其虚拟机本身就是一堂历史课。简而言之,和 Linux 内核很相似,自发布以来,该语言已经向多个方向分支发展。有对社区免费的标准版本、有针对企业的企业版本及由多家供应商提供的开源替代品。主要版本每六个月发布一次,其功能往往差异很大,所以确认选用版本前得先做些研究。
|
||||
|
||||
总而言之,Java 的历史很悠久。本教程重点介绍 Java 11 的开源实现 [JDK 11][4]。因其是仍然有效的长期支持版本之一。
|
||||
|
||||
* **Spring Boot** 是由 Pivotal 公司开发的大型 Spring 框架的一个模块。Spring 是 Java 开发中一个非常流行的框架。它支持各种框架和配置,也为 WEB 应用程序及安全提供了保障。Spring Boot 为快速构建各种类型的 Java 项目提供了基本的配置。本教程使用 Spring Boot 来快速编写控制台应用程序并针对数据库编写测试用例。
|
||||
* **Maven** 是由 Apache 开发的项目/包管理工具。Maven 通过 `POM.xml` 文件来管理包及其依赖项。如果你使用过 NPM 的话,可能会非常熟悉包管理器的功能。此外 Maven 也用来进行项目构建及生成功能报告。
|
||||
* **Lombok** 是一个库,它通过在对象文件里面添加注解来自动创建 getters/setters 方法。像 C# 这些语言已经实现了此功能,Lombok 只是把此功能引入 Java 语言而已。
|
||||
* **NetBeans** 是一款很流行的开源 IDE,专门用于 Java 开发。它的许多工具都随着 Java SE 和 EE 的版本更新而更新。
|
||||
|
||||
我们会用这组工具为一个虚构自行车商店创建一个简单的应用程序。会实现对 `Customer` 和 `Bike` 对象集合的的插入操作。
|
||||
|
||||
### 酿造完美
|
||||
|
||||
导航到 [Spring Initializr][5] 页面。该网站可以生成基于 Spring Boot 和其依赖项的基本项目。选择以下选项:
|
||||
|
||||
1. **项目:** Maven 工程
|
||||
2. **语言:** Java
|
||||
3. **Spring Boot:** 2.1.8(或最稳定版本)
|
||||
4. **项目元数据:** 无论你使用什么名字,其命名约定都是像 `com.stephb` 这样的。
|
||||
* 你可以保留 Artifact 名字为 “Demo”。
|
||||
5. **依赖项:** 添加:
|
||||
* Spring Data MongoDB
|
||||
* Lombok
|
||||
|
||||
点击 **下载**,然后用你的 IDE(例如 NetBeans) 打开此新项目。
|
||||
|
||||
#### 模型层概要
|
||||
|
||||
在项目里面,<ruby>模型<rt>model</rt></ruby>代表从数据库里取出的信息的具体对象。我们关注两个对象:`Customer` 和 `Bike`。首先,在 `src` 目录创建 `dto` 目录;然后,创建两个名为 `Customer.java` 和 `Bike.java` 的 Java 类对象文件。其结构如下示:
|
||||
|
||||
```Java
|
||||
package com.stephb.JavaMongo.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class Customer {
|
||||
|
||||
private @Id String id;
|
||||
private String emailAddress;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String address;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
*Customer.Java*
|
||||
|
||||
```Java
|
||||
package com.stephb.JavaMongo.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class Bike {
|
||||
private @Id String id;
|
||||
private String modelNumber;
|
||||
private String color;
|
||||
private String description;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "This bike model is " + this.modelNumber + " is the color " + this.color + " and is " + description;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Bike.java*
|
||||
|
||||
如你所见,对象中使用 Lombok 注解来为定义的<ruby>属性<rt>properties</rt></ruby>/<ruby>特性<rt>attributes</rt></ruby>生成 getters/setters 方法。如果你不想对该类的所有特性都生成 getters/setters 方法,可以在属性上专门定义这些注解。这两个类会变成容器,里面携带有数据,无论在何处想显示信息都可以使用。
|
||||
|
||||
#### 配置数据库
|
||||
|
||||
我使用 [Mongo Docker][7] 容器来进行此次测试。如果你的系统上已经安装了 MongoDB,则不必运行 Docker 实例。你也可以登录其官网,选择系统信息,然后按照安装说明来安装 MongoDB。
|
||||
|
||||
安装后,就可以使用命令行、GUI(例如 MongoDB Compass)或用于连接数据源的 IDE 驱动程序来与新的 MongoDB 服务器进行交互。到目前为止,可以开始定义数据层了,用来拉取、转换和持久化数据。需要设置数据库访问属性,请导航到程序中的 `applications.properties` 文件,然后添加如下内容:
|
||||
|
||||
```
|
||||
spring.data.mongodb.host=localhost
|
||||
spring.data.mongodb.port=27017
|
||||
spring.data.mongodb.database=BikeStore
|
||||
```
|
||||
|
||||
#### 定义数据访问对象/数据访问层
|
||||
|
||||
<ruby>数据访问层<rt>data access layer</rt></ruby>(DAL)中的<ruby>数据访问对象<rt>data access objects</rt></ruby>(DAO)定义了与数据库中的数据的交互过程。令人惊叹的就是在使用 `spring-boot-starter` 后,查询数据库的大部分工作已经完成。
|
||||
|
||||
让我们从 `Customer` DAO 开始。在 `src` 下的新目录 `dao` 中创建一个接口文件,然后再创建一个名为 `CustomerRepository.java` 的 Java 类文件,其内容如下示:
|
||||
|
||||
```
|
||||
package com.stephb.JavaMongo.dao;
|
||||
|
||||
import com.stephb.JavaMongo.dto.Customer;
|
||||
import java.util.List;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
public interface CustomerRepository extends MongoRepository<Customer, String>{
|
||||
@Override
|
||||
public List<Customer> findAll();
|
||||
public List<Customer> findByFirstName(String firstName);
|
||||
public List<Customer> findByLastName(String lastName);
|
||||
}
|
||||
```
|
||||
|
||||
这个类是一个接口,扩展或继承于 `MongoRepository` 类,而 `MongoRepository` 类依赖于 DTO (`Customer.java`)和一个字符串,它们用来实现自定义函数查询功能。因为你已继承自此类,所以你可以访问许多方法函数,这些函数允许持久化和查询对象,而无需实现或引用自己定义的方法函数。例如,在实例化 `CustomerRepository` 对象后,你就可以直接使用 `Save` 函数。如果你需要扩展更多的功能,也可以重写这些函数。我创建了一些自定义查询来搜索我的集合,这些集合对象是我自定义的元素。
|
||||
|
||||
`Bike` 对象也有一个存储源负责与数据库交互。与 `CustomerRepository` 的实现非常类似。其实现如下所示:
|
||||
|
||||
```
|
||||
package com.stephb.JavaMongo.dao;
|
||||
|
||||
import com.stephb.JavaMongo.dto.Bike;
|
||||
import java.util.List;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
public interface BikeRepository extends MongoRepository<Bike,String>{
|
||||
public Bike findByModelNumber(String modelNumber);
|
||||
@Override
|
||||
public List<Bike> findAll();
|
||||
public List<Bike> findByColor(String color);
|
||||
}
|
||||
```
|
||||
|
||||
#### 运行程序
|
||||
|
||||
现在,你已经有了一种结构化数据的方式,可以对数据进行提取、转换和持久化,然后运行这个程序。
|
||||
|
||||
找到 `Application.java` 文件(有可能不是此名称,具体取决于你的应用程序名称,但都会包含有 “application” )。在定义此类的地方,在后面加上 `implements CommandLineRunner`。这将允许你实现 `run` 方法来创建命令行应用程序。重写 `CommandLineRunner` 接口提供的 `run` 方法,并包含如下内容用来测试 `BikeRepository` :
|
||||
|
||||
```
|
||||
package com.stephb.JavaMongo;
|
||||
|
||||
import com.stephb.JavaMongo.dao.BikeRepository;
|
||||
import com.stephb.JavaMongo.dao.CustomerRepository;
|
||||
import com.stephb.JavaMongo.dto.Bike;
|
||||
import java.util.Scanner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class JavaMongoApplication implements CommandLineRunner {
|
||||
@Autowired
|
||||
private BikeRepository bikeRepo;
|
||||
private CustomerRepository custRepo;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(JavaMongoApplication.class, args);
|
||||
}
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
Scanner scan = new Scanner(System.in);
|
||||
String response = "";
|
||||
boolean running = true;
|
||||
while(running){
|
||||
System.out.println("What would you like to create? \n C: The Customer \n B: Bike? \n X:Close");
|
||||
response = scan.nextLine();
|
||||
if ("B".equals(response.toUpperCase())) {
|
||||
String[] bikeInformation = new String[3];
|
||||
System.out.println("Enter the information for the Bike");
|
||||
System.out.println("Model Number");
|
||||
bikeInformation[0] = scan.nextLine();
|
||||
System.out.println("Color");
|
||||
bikeInformation[1] = scan.nextLine();
|
||||
System.out.println("Description");
|
||||
bikeInformation[2] = scan.nextLine();
|
||||
|
||||
Bike bike = new Bike();
|
||||
bike.setModelNumber(bikeInformation[0]);
|
||||
bike.setColor(bikeInformation[1]);
|
||||
bike.setDescription(bikeInformation[2]);
|
||||
|
||||
bike = bikeRepo.save(bike);
|
||||
System.out.println(bike.toString());
|
||||
|
||||
|
||||
} else if ("X".equals(response.toUpperCase())) {
|
||||
System.out.println("Bye");
|
||||
running = false;
|
||||
} else {
|
||||
System.out.println("Sorry nothing else works right now!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
其中的 `@Autowired` 注解会自动依赖注入 `BikeRepository` 和 `CustomerRepository` Bean。我们将使用这些类来从数据库持久化和采集数据。
|
||||
|
||||
已经好了。你已经创建了一个命令行应用程序。该应用程序连接到数据库,并且能够以最少的代码执行 CRUD 操作
|
||||
|
||||
### 结论
|
||||
|
||||
从诸如对象和类之类的编程语言概念转换为用于在数据库中存储、检索或更改数据的调用对于构建应用程序至关重要。Java 持久化 API(JPA)正是为 Java 开发人员解决这一难题的重要工具。你正在使用 Java 操纵哪些数据库呢?请在评论中分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/using-java-persistence-api
|
||||
|
||||
作者:[Stephon Brown][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[runningwater](https://github.com/runningwater)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/stephb
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/java-coffee-beans.jpg?itok=3hkjX5We (Coffee beans)
|
||||
[2]: https://www.techrepublic.com/article/mongodb-ceo-tells-hard-truths-about-commercial-open-source/
|
||||
[3]: https://github.com/StephonBrown/SpringMongoJava
|
||||
[4]: https://openjdk.java.net/projects/jdk/11/
|
||||
[5]: https://start.spring.io/
|
||||
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[7]: https://hub.docker.com/_/mongo
|
||||
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+exception
|
||||
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
|
140
published/201912/20191017 How to type emoji on Linux.md
Normal file
140
published/201912/20191017 How to type emoji on Linux.md
Normal file
@ -0,0 +1,140 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11702-1.html)
|
||||
[#]: subject: (How to type emoji on Linux)
|
||||
[#]: via: (https://opensource.com/article/19/10/how-type-emoji-linux)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
如何在 Linux 系统中输入 emoji
|
||||
======
|
||||
|
||||
> 使用 GNOME 桌面可以让你在文字中轻松加入 emoji。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/22/003829tsuogoonoxunn33o.jpg)
|
||||
|
||||
emoji 是潜藏在 Unicode 字符空间里的有趣表情图,它们已经风靡于整个互联网。emoji 可以用来在社交媒体上表示自己的心情状态,也可以作为重要文件名的视觉标签,总之它们的各种用法层出不穷。在 Linux 系统中有很多种方式可以输入 Unicode 字符,但 GNOME 桌面能让你更轻松地查找和输入 emoji。
|
||||
|
||||
![Emoji in Emacs][2]
|
||||
|
||||
### 准备工作
|
||||
|
||||
首先,你需要一个运行 [GNOME][3] 桌面的 Linux 系统。
|
||||
|
||||
同时还需要安装一款支持 emoji 的字体。符合这个要求的字体有很多,使用你喜欢的软件包管理器直接搜索 `emoji` 并选择一款安装就可以了。
|
||||
|
||||
例如在 Fedora 上:
|
||||
|
||||
```
|
||||
$ sudo dnf search emoji
|
||||
emoji-picker.noarch : An emoji selection tool
|
||||
unicode-emoji.noarch : Unicode Emoji Data Files
|
||||
eosrei-emojione-fonts.noarch : A color emoji font
|
||||
twitter-twemoji-fonts.noarch : Twitter Emoji for everyone
|
||||
google-android-emoji-fonts.noarch : Android Emoji font released by Google
|
||||
google-noto-emoji-fonts.noarch : Google “Noto Emoji” Black-and-White emoji font
|
||||
google-noto-emoji-color-fonts.noarch : Google “Noto Color Emoji” colored emoji font
|
||||
[...]
|
||||
```
|
||||
|
||||
对于 Ubuntu 或者 Debian,需要使用 `apt search`。
|
||||
|
||||
在这篇文章中,我会使用 [Google Noto Color Emoji][4] 这款字体为例。
|
||||
|
||||
### 设置
|
||||
|
||||
要开始设置,首先打开 GNOME 的设置面板。
|
||||
|
||||
1、在左边侧栏中,选择“<ruby>地区与语言<rt>Region & Language</rt></ruby>”类别。
|
||||
|
||||
2、点击“<ruby>输入源<rt>Input Sources</rt></ruby>”选项下方的加号(+)打开“<ruby>添加输入源<rt>Add an Input Source</rt></ruby>”面板。
|
||||
|
||||
![Add a new input source][5]
|
||||
|
||||
3、在“<ruby>添加输入源<rt>Add an Input Source</rt></ruby>”面板中,点击底部的菜单按钮。
|
||||
|
||||
![Add an Input Source panel][6]
|
||||
|
||||
4、滑动到列表底部并选择“<ruby>其它<rt>Other</rt></ruby>”。
|
||||
|
||||
5、在“<ruby>其它<rt>Other</rt></ruby>”列表中,找到“<ruby>其它<rt>Other</rt></ruby>(<ruby>快速输入<rt>Typing Booster</rt></ruby>)”。
|
||||
|
||||
![Find Other \(Typing Booster\) in inputs][7]
|
||||
|
||||
6、点击右上角的“<ruby>添加<rt>Add</rt></ruby>”按钮,将输入源添加到 GNOME 桌面。
|
||||
|
||||
以上操作完成之后,就可以关闭设置面板了。
|
||||
|
||||
#### 切换到快速输入
|
||||
|
||||
现在 GNOME 桌面的右上角会出现一个新的图标,一般情况下是当前语言的双字母缩写(例如英语是 en,世界语是 eo,西班牙语是 es,等等)。如果你按下了<ruby>超级键<rt>Super key</rt></ruby>(也就是键盘上带有 Linux 企鹅/Windows 徽标/Mac Command 标志的键)+ 空格键的组合键,就会切换到输入列表中的下一个输入源。在这里,我们只有两个输入源,也就是默认语言和快速输入。
|
||||
|
||||
你可以尝试使用一下这个组合键,观察图标的变化。
|
||||
|
||||
#### 配置快速输入
|
||||
|
||||
在快速输入模式下,点击右上角的输入源图标,选择“<ruby>Unicode 符号和 emoji 联想<rt>Unicode symbols and emoji predictions</rt></ruby>”选项,设置为“<ruby>开<rt>On</rt></ruby>”。
|
||||
|
||||
![Set Unicode symbols and emoji predictions to On][8]
|
||||
|
||||
现在快速输入模式已经可以输入 emoji 了。这正是我们现在所需要的,当然快速输入模式的功能也并不止于此。
|
||||
|
||||
### 输入 emoji
|
||||
|
||||
在快速输入模式下,打开一个文本编辑器,或者网页浏览器,又或者是任意一种支持输入 Unicode 字符的软件,输入“thumbs up”,快速输入模式就会帮你迅速匹配的 emoji 了。
|
||||
|
||||
![Typing Booster searching for emojis][9]
|
||||
|
||||
要退出 emoji 模式,只需要再次使用超级键+空格键的组合键,输入源就会切换回你的默认输入语言。
|
||||
|
||||
### 使用其它切换方式
|
||||
|
||||
如果你觉得“超级键+空格键”这个组合用起来不顺手,你也可以换成其它键的组合。在 GNOME 设置面板中选择“<ruby>设备<rt>Device</rt></ruby>”→“<ruby>键盘<rt>Keyboard</rt></ruby>”。
|
||||
|
||||
在“<ruby>键盘<rt>Keyboard</rt></ruby>”页面中,将“<ruby>切换到下一个输入源<rt>Switch to next input source</rt></ruby>”更改为你喜欢的组合键。
|
||||
|
||||
![Changing keystroke combination in GNOME settings][10]
|
||||
|
||||
### 输入 Unicode
|
||||
|
||||
实际上,现代键盘的设计只是为了输入 26 个字母以及尽可能多的数字和符号。但 ASCII 字符的数量已经比键盘上能看到的字符多得多了,遑论上百万个 Unicode 字符。因此,如果你想要在 Linux 应用程序中输入 Unicode,但又不想使用快速输入,你可以尝试一下 Unicode 输入。
|
||||
|
||||
1. 打开任意一种支持输入 Unicode 字符的软件,但仍然使用你的默认输入语言
|
||||
2. 使用 `Ctrl+Shift+U` 组合键进入 Unicode 输入模式
|
||||
3. 在 Unicode 输入模式下,只需要输入某个 Unicode 字符的对应序号,就实现了对这个 Unicode 字符的输入。例如 `1F44D` 对应的是 👍,而 `2620` 则对应了 ☠。想要查看所有 Unicode 字符的对应序号,可以参考 [Unicode 规范][11]。
|
||||
|
||||
### emoji 的实用性
|
||||
|
||||
emoji 可以让你的文本变得与众不同,这就是它们有趣和富有表现力的体现。同时 emoji 也有很强的实用性,因为它们本质上是 Unicode 字符,在很多支持自定义字体的地方都可以用到它们,而且跟使用其它常规字符没有什么太大的差别。因此,你可以使用 emoji 来对不同的文件做标记,在搜索的时候就可以使用 emoji 把这些文件快速筛选出来。
|
||||
|
||||
![Labeling a file with emoji][12]
|
||||
|
||||
你可以在 Linux 中尽情地使用 emoji,因为 Linux 是一个对 Unicode 友好的环境,未来也会对 Unicode 有着越来越好的支持。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/how-type-emoji-linux
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[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/osdc-lead_cat-keyboard.png?itok=fuNmiGV- "A cat under a keyboard."
|
||||
[2]: https://opensource.com/sites/default/files/uploads/emacs-emoji.jpg "Emoji in Emacs"
|
||||
[3]: https://www.gnome.org/
|
||||
[4]: https://www.google.com/get/noto/help/emoji/
|
||||
[5]: https://opensource.com/sites/default/files/uploads/gnome-setting-region-add.png "Add a new input source"
|
||||
[6]: https://opensource.com/sites/default/files/uploads/gnome-setting-input-list.png "Add an Input Source panel"
|
||||
[7]: https://opensource.com/sites/default/files/uploads/gnome-setting-input-other-typing-booster.png "Find Other (Typing Booster) in inputs"
|
||||
[8]: https://opensource.com/sites/default/files/uploads/emoji-input-on.jpg "Set Unicode symbols and emoji predictions to On"
|
||||
[9]: https://opensource.com/sites/default/files/uploads/emoji-input.jpg "Typing Booster searching for emojis"
|
||||
[10]: https://opensource.com/sites/default/files/uploads/gnome-setting-keyboard-switch-input.jpg "Changing keystroke combination in GNOME settings"
|
||||
[11]: http://unicode.org/emoji/charts/full-emoji-list.html
|
||||
[12]: https://opensource.com/sites/default/files/uploads/file-label.png "Labeling a file with emoji"
|
||||
|
118
published/201912/20191017 Using multitail on Linux.md
Normal file
118
published/201912/20191017 Using multitail on Linux.md
Normal file
@ -0,0 +1,118 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11643-1.html)
|
||||
[#]: subject: (Using multitail on Linux)
|
||||
[#]: via: (https://www.networkworld.com/article/3445228/using-multitail-on-linux.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
在 Linux 上使用 Multitail
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/05/053423mpnrn95hqqknzheq.jpg)
|
||||
|
||||
当你想同时查看多个文件(尤其是日志文件)的活动时,`multitail` 命令会非常有用。它的工作方式类似于多窗口形式的 `tail -f` 命令。也就是说,它显示这些文件的底部和添加的新行。虽然通常使用简单,但是 `multitail` 提供了一些命令行和交互式选项,在开始使用它之前,你应该了解它们。
|
||||
|
||||
### 基本 multitail 使用
|
||||
|
||||
`multitail` 的最简单用法是在命令行中列出你要查看的文件名称。此命令水平分割屏幕(即顶部和底部),并显示每个文件的底部以及更新。
|
||||
|
||||
```
|
||||
$ multitail /var/log/syslog /var/log/dmesg
|
||||
```
|
||||
|
||||
显示内容将像这样拆分:
|
||||
|
||||
```
|
||||
+-----------------------+
|
||||
| |
|
||||
| |
|
||||
+-----------------------|
|
||||
| |
|
||||
| |
|
||||
+-----------------------+
|
||||
```
|
||||
|
||||
每个文件都有一行显示该文件的文件编号(从 00 开始)、文件名、文件大小、最新内容的添加日期和时间。每个文件将被分配一半空间,而不论它的大小和活动情况。比如:
|
||||
|
||||
```
|
||||
content lines from my1.log
|
||||
more content
|
||||
more lines
|
||||
|
||||
00] my1.log 59KB - 2019/10/14 12:12:09
|
||||
content lines from my2.log
|
||||
more content
|
||||
more lines
|
||||
|
||||
01] my2.log 120KB - 2019/10/14 14:22:29
|
||||
```
|
||||
|
||||
请注意,如果你要求 `multitail` 显示非文本文件或者你无权查看的文件,它不会报错。你只是看不到内容。
|
||||
|
||||
你还可以使用通配符指定要查看的文件:
|
||||
|
||||
```
|
||||
$ multitail my*.log
|
||||
```
|
||||
|
||||
要记住的一件事是,`multitail` 将平均分割屏幕。如果指定的文件太多,那么除非你采取额外的步骤查看之后的文件(参考下面的滚动选项),否则你将只会看到前面 7 个文件的前面几行。确切的结果取决于终端窗口中有多少行可用。
|
||||
|
||||
按 `q` 退出 `multitail` 并返回到正常的屏幕视图。
|
||||
|
||||
### 分割屏幕
|
||||
|
||||
如果你愿意,`multitail` 也可以垂直分割你的终端窗口(即,左和右)。为此,请使用 `-s` 选项。如果指定了三个文件,那么屏幕右侧的窗口将会水平分隔。四个文件的话,你将拥有四个大小相等的窗口。
|
||||
|
||||
```
|
||||
+-----------+-----------+ +-----------+-----------+ +-----------+-----------+
|
||||
| | | | | | | | |
|
||||
| | | | | | | | |
|
||||
| | | | +-----------+ +-----------+-----------+
|
||||
| | | | | | | | |
|
||||
| | | | | | | | |
|
||||
+-----------+-----------+ +-----------+-----------+ +-----------+-----------+
|
||||
2 个文件 3 个文件 4 个文件
|
||||
```
|
||||
|
||||
如果要将屏幕分为三列,请使用 `multitail -s 3 file1 file2 file3`。
|
||||
|
||||
```
|
||||
+-------+-------+-------+
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
+-------+-------+-------+
|
||||
3 个文件带上 -s 3 选项
|
||||
```
|
||||
|
||||
### 滚动
|
||||
|
||||
你可以上下滚动文件,但是需要按下 `b` 弹出选择菜单,然后使用向上和向下箭头按钮选择要滚动浏览的文件。然后按下回车键。然后,你可以再次使用向上和向下箭头在放大的区域中滚动浏览各行。完成后按下 `q` 返回正常视图。
|
||||
|
||||
### 获得帮助
|
||||
|
||||
在 `multitail` 中按下 `h` 将打开一个帮助菜单,其中描述了一些基本操作,但是手册页提供了更多信息,如果莫想了解更多有关使用此工具的信息,请仔细阅读。
|
||||
|
||||
默认情况下,你的系统上不会安装 `multitail`,但是使用 `apt-get` 或 `yum` 可以使你轻松安装。该工具提供了许多功能,不过它是基于字符显示的,窗口边框只是 `q` 和 `x` 的字符串组成的。当你需要关注文件更新时,它非常方便。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3445228/using-multitail-on-linux.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][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://www.networkworld.com/author/Sandra-Henry_Stocker/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.flickr.com/photos/glenbowman/7992498919/in/photolist-dbgDtv-gHfRRz-5uRM4v-gHgFnz-6sPqTZ-5uaP7H-USFPqD-pbtRUe-fiKiYn-nmgWL2-pQNepR-q68p8d-dDsUxw-dbgFKG-nmgE6m-DHyqM-nCKA4L-2d7uFqH-Kbqzk-8EwKg-8Vy72g-2X3NSN-78Bv84-buKWXF-aeM4ok-yhweWf-4vwpyX-9hu8nq-9zCoti-v5nzP5-23fL48r-24y6pGS-JhWDof-6zF75k-24y6nHS-9hr19c-Gueh6G-Guei7u-GuegFy-24y6oX5-26qu5iX-wKrnMW-Gueikf-24y6oYh-27y4wwA-x4z19F-x57yP4-24BY6gc-24y6nPo-QGwbkf
|
||||
[2]: https://creativecommons.org/licenses/by-sa/2.0/legalcode
|
||||
[5]: https://www.facebook.com/NetworkWorld/
|
||||
[6]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,245 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11669-1.html)
|
||||
[#]: subject: (14 SCP Command Examples to Securely Transfer Files in Linux)
|
||||
[#]: via: (https://www.linuxtechi.com/scp-command-examples-in-linux/)
|
||||
[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
|
||||
|
||||
在 Linux 上安全传输文件的 14 SCP 命令示例
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/13/100239f31is1ios31vvoo3.jpg)
|
||||
|
||||
SCP(<ruby>安全复制<rt>Secure Copy</rt></ruby>)是 Linux 和 Unix 之类的系统中的命令行工具,用于通过网络安全地跨系统传输文件和目录。当我们使用 `scp` 命令将文件和目录从本地系统复制到远程系统时,则在后端与远程系统建立了 ssh 连接。换句话说,我们可以说 `scp` 在后端使用了相同的 SSH 安全机制,它需要密码或密钥进行身份验证。
|
||||
|
||||
![scp-command-examples-linux][2]
|
||||
|
||||
在本教程中,我们将讨论 14 个有用的 Linux `scp` 命令示例。
|
||||
|
||||
`scp` 命令语法:
|
||||
|
||||
```
|
||||
# scp <选项> <文件或目录> 用户名@目标主机:/<文件夹>
|
||||
|
||||
# scp <选项> 用户名@目标主机:/文件 <本地文件夹>
|
||||
```
|
||||
|
||||
`scp` 命令的第一个语法演示了如何将文件或目录从本地系统复制到特定文件夹下的目标主机。
|
||||
|
||||
`scp` 命令的第二种语法演示了如何将目标主机中的文件复制到本地系统中。
|
||||
|
||||
下面列出了 `scp` 命令中使用最广泛的一些选项,
|
||||
|
||||
* `-C` 启用压缩
|
||||
* `-i` 指定识别文件或私钥
|
||||
* `-l` 复制时限制带宽
|
||||
* `-P` 指定目标主机的 ssh 端口号
|
||||
* `-p` 复制时保留文件的权限、模式和访问时间
|
||||
* `-q` 禁止 SSH 警告消息
|
||||
* `-r` 递归复制文件和目录
|
||||
* `-v` 详细输出
|
||||
|
||||
现在让我们跳入示例!
|
||||
|
||||
### 示例:1)使用 scp 将文件从本地系统复制到远程系统
|
||||
|
||||
假设我们要使用 `scp` 命令将 jdk 的 rpm 软件包从本地 Linux 系统复制到远程系统(172.20.10.8),请使用以下命令,
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp jdk-linux-x64_bin.rpm root@linuxtechi:/opt
|
||||
root@linuxtechi's password:
|
||||
jdk-linux-x64_bin.rpm 100% 10MB 27.1MB/s 00:00
|
||||
[root@linuxtechi ~]$
|
||||
```
|
||||
|
||||
上面的命令会将 jdk 的 rpm 软件包文件复制到 `/opt` 文件夹下的远程系统。
|
||||
|
||||
### 示例:2)使用 scp 将文件从远程系统复制到本地系统
|
||||
|
||||
假设我们想将文件从远程系统复制到本地系统下的 `/tmp` 文件夹,执行以下 `scp` 命令,
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp root@linuxtechi:/root/Technical-Doc-RHS.odt /tmp
|
||||
root@linuxtechi's password:
|
||||
Technical-Doc-RHS.odt 100% 1109KB 31.8MB/s 00:00
|
||||
[root@linuxtechi ~]$ ls -l /tmp/Technical-Doc-RHS.odt
|
||||
-rwx------. 1 pkumar pkumar 1135521 Oct 19 11:12 /tmp/Technical-Doc-RHS.odt
|
||||
[root@linuxtechi ~]$
|
||||
```
|
||||
|
||||
### 示例:3)使用 scp 传输文件时的详细输出(-v)
|
||||
|
||||
在 `scp` 命令中,我们可以使用 `-v` 选项启用详细输出。使用详细输出,我们可以轻松地发现后台确切发生了什么。这对于调试连接、认证和配置等问题非常有用。
|
||||
|
||||
```
|
||||
root@linuxtechi ~]$ scp -v jdk-linux-x64_bin.rpm root@linuxtechi:/opt
|
||||
Executing: program /usr/bin/ssh host 172.20.10.8, user root, command scp -v -t /opt
|
||||
OpenSSH_7.8p1, OpenSSL 1.1.1 FIPS 11 Sep 2018
|
||||
debug1: Reading configuration data /etc/ssh/ssh_config
|
||||
debug1: Reading configuration data /etc/ssh/ssh_config.d/05-redhat.conf
|
||||
debug1: Reading configuration data /etc/crypto-policies/back-ends/openssh.config
|
||||
debug1: /etc/ssh/ssh_config.d/05-redhat.conf line 8: Applying options for *
|
||||
debug1: Connecting to 172.20.10.8 [172.20.10.8] port 22.
|
||||
debug1: Connection established.
|
||||
…………
|
||||
debug1: Next authentication method: password
|
||||
root@linuxtechi's password:
|
||||
```
|
||||
|
||||
### 示例:4)将多个文件传输到远程系统
|
||||
|
||||
可以使用 `scp` 命令一次性将多个文件复制/传输到远程系统,在 `scp` 命令中指定多个文件,并用空格隔开,示例如下所示
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp install.txt index.html jdk-linux-x64_bin.rpm root@linuxtechi:/mnt
|
||||
root@linuxtechi's password:
|
||||
install.txt 100% 0 0.0KB/s 00:00
|
||||
index.html 100% 85KB 7.2MB/s 00:00
|
||||
jdk-linux-x64_bin.rpm 100% 10MB 25.3MB/s 00:00
|
||||
[root@linuxtechi ~]$
|
||||
```
|
||||
|
||||
### 示例:5)在两个远程主机之间传输文件
|
||||
|
||||
使用 `scp` 命令,我们可以在两个远程主机之间复制文件和目录,假设我们有一个可以连接到两个远程 Linux 系统的本地 Linux 系统,因此从我的本地 Linux 系统中,我可以使用 `scp` 命令在这两个系统之间复制文件,
|
||||
|
||||
命令语法:
|
||||
|
||||
```
|
||||
# scp 用户名@远程主机1:/<要传输的文件> 用户名@远程主机2:/<文件夹>
|
||||
```
|
||||
|
||||
示例如下:
|
||||
|
||||
```
|
||||
# scp root@linuxtechi:~/backup-Oct.zip root@linuxtechi:/tmp
|
||||
# ssh root@linuxtechi "ls -l /tmp/backup-Oct.zip"
|
||||
-rwx------. 1 root root 747438080 Oct 19 12:02 /tmp/backup-Oct.zip
|
||||
```
|
||||
|
||||
### 示例:6)递归复制文件和目录(-r)
|
||||
|
||||
在 `scp` 命令中使用 `-r` 选项将整个目录从一个系统递归地复制到另一个系统,示例如下所示:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp -r Downloads root@linuxtechi:/opt
|
||||
```
|
||||
|
||||
使用以下命令验证 `Downloads` 文件夹是否已复制到远程系统,
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ ssh root@linuxtechi "ls -ld /opt/Downloads"
|
||||
drwxr-xr-x. 2 root root 75 Oct 19 12:10 /opt/Downloads
|
||||
[root@linuxtechi ~]$
|
||||
```
|
||||
|
||||
### 示例:7)通过启用压缩来提高传输速度(-C)
|
||||
|
||||
在 `scp` 命令中,我们可以通过使用 `-C` 选项启用压缩来提高传输速度,它将自动在源主机上启用压缩并在目标主机上解压缩。
|
||||
|
||||
```
|
||||
root@linuxtechi ~]$ scp -r -C Downloads root@linuxtechi:/mnt
|
||||
```
|
||||
|
||||
在以上示例中,我们正在启用压缩的情况下传输下载目录。
|
||||
|
||||
### 示例:8)复制时限制带宽(-l)
|
||||
|
||||
在 `scp` 命令中使用 `-l` 选项设置复制时对带宽使用的限制。带宽以 Kbit/s 为单位指定,示例如下所示:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp -l 500 jdk-linux-x64_bin.rpm root@linuxtechi:/var
|
||||
```
|
||||
|
||||
### 示例:9)在 scp 时指定其他 ssh 端口(-P)
|
||||
|
||||
在某些情况下,目标主机上的 ssh 端口会更改,因此在使用 `scp` 命令时,我们可以使用 `-P` 选项指定 ssh 端口号。
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp -P 2022 jdk-linux-x64_bin.rpm root@linuxtechi:/var
|
||||
```
|
||||
|
||||
在上面的示例中,远程主机的 ssh 端口为 “2022”。
|
||||
|
||||
### 示例:10)复制时保留文件的权限、模式和访问时间(-p)
|
||||
|
||||
从源复制到目标时,在 `scp` 命令中使用 `-p` 选项保留权限、访问时间和模式。
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp -p jdk-linux-x64_bin.rpm root@linuxtechi:/var/tmp
|
||||
jdk-linux-x64_bin.rpm 100% 10MB 13.5MB/s 00:00
|
||||
[root@linuxtechi ~]$
|
||||
```
|
||||
|
||||
### 示例:11)在 scp 中以安静模式传输文件(-q)
|
||||
|
||||
在 `scp` 命令中使用 `-q` 选项可禁止显示 ssh 的传输进度、警告和诊断消息。示例如下所示:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp -q -r Downloads root@linuxtechi:/var/tmp
|
||||
[root@linuxtechi ~]$
|
||||
```
|
||||
|
||||
### 示例:12)在传输时使用 scp 中的识别文件(-i)
|
||||
|
||||
在大多数 Linux 环境中,首选基于密钥的身份验证。在 `scp` 命令中,我们使用 `-i` 选项指定识别文件(私钥文件),示例如下所示:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp -i my_key.pem -r Downloads root@linuxtechi:/root
|
||||
```
|
||||
|
||||
在上面的示例中,`my_key.pem` 是识别文件或私钥文件。
|
||||
|
||||
### 示例:13)在 scp 中使用其他 ssh_config 文件(-F)
|
||||
|
||||
在某些情况下,你使用不同的网络连接到 Linux 系统,可能某些网络位于代理服务器后面,因此在这种情况下,我们必须具有不同的 `ssh_config` 文件。
|
||||
|
||||
通过 `-F` 选项在 `scp` 命令中指定了不同的 `ssh_config` 文件,示例如下所示:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]$ scp -F /home/pkumar/new_ssh_config -r Downloads root@linuxtechi:/root
|
||||
root@linuxtechi's password:
|
||||
jdk-linux-x64_bin.rpm 100% 10MB 16.6MB/s 00:00
|
||||
backup-Oct.zip 100% 713MB 41.9MB/s 00:17
|
||||
index.html 100% 85KB 6.6MB/s 00:00
|
||||
[root@linuxtechi ~]$
|
||||
```
|
||||
|
||||
### 示例:14)在 scp 命令中使用其他加密方式(-c)
|
||||
|
||||
默认情况下,`scp` 使用 AES-128 加密方式来加密文件。如果你想在 `scp` 命令中使用其他加密方式,请使用 `-c` 选项,后接加密方式名称。
|
||||
|
||||
假设我们要在用 `scp` 命令传输文件时使用 3des-cbc 加密方式,请运行以下 `scp` 命令:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# scp -c 3des-cbc -r Downloads root@linuxtechi:/root
|
||||
```
|
||||
|
||||
使用以下命令列出 `ssh` 和 `scp` 支持的加密方式:
|
||||
|
||||
```
|
||||
[root@linuxtechi ~]# ssh -Q cipher localhost | paste -d , -s -
|
||||
3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc,root@linuxtechi,aes128-ctr,aes192-ctr,aes256-ctr,root@linuxtechi,root@linuxtechi,root@linuxtechi
|
||||
[root@linuxtechi ~]#
|
||||
```
|
||||
|
||||
以上就是本教程的全部内容,要获取有关 `scp` 命令的更多详细信息,请参考其手册页。请在下面的评论部分中分享你的反馈和评论。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxtechi.com/scp-command-examples-in-linux/
|
||||
|
||||
作者:[Pradeep Kumar][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://www.linuxtechi.com/author/pradeep/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[2]: https://www.linuxtechi.com/wp-content/uploads/2019/10/scp-command-examples-linux.jpg
|
||||
[3]: https://www.linuxtechi.com/cdn-cgi/l/email-protection
|
@ -0,0 +1,467 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11687-1.html)
|
||||
[#]: subject: (How to program with Bash: Logical operators and shell expansions)
|
||||
[#]: via: (https://opensource.com/article/19/10/programming-bash-logical-operators-shell-expansions)
|
||||
[#]: author: (David Both https://opensource.com/users/dboth)
|
||||
|
||||
怎样用 Bash 编程:逻辑操作符和 shell 扩展
|
||||
======
|
||||
|
||||
> 学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/17/173459pxhz0aiicimzd1m2.jpg)
|
||||
|
||||
Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本。本系列(三篇文章,基于我的 [三集 Linux 自学课程][2])讲解如何在 CLI 使用 Bash 编程。
|
||||
|
||||
[第一篇文章][3] 讲解了 Bash 的一些简单命令行操作,包括如何使用变量和控制操作符。第二篇文章探讨文件、字符串、数字等类型和各种各样在执行流中提供控制逻辑的的逻辑运算符,还有 Bash 中的各类 shell 扩展。本系列第三篇也是最后一篇文章,将会探索能重复执行操作的 `for` 、`while` 和 `until` 循环。
|
||||
|
||||
逻辑操作符是程序中进行判断的根本要素,也是执行不同的语句组合的依据。有时这也被称为流控制。
|
||||
|
||||
### 逻辑操作符
|
||||
|
||||
Bash 中有大量的用于不同条件表达式的逻辑操作符。最基本的是 `if` 控制结构,它判断一个条件,如果条件为真,就执行一些程序语句。操作符共有三类:文件、数字和非数字操作符。如果条件为真,所有的操作符返回真值(`0`),如果条件为假,返回假值(`1`)。
|
||||
|
||||
这些比较操作符的函数语法是,一个操作符加一个或两个参数放在中括号内,后面跟一系列程序语句,如果条件为真,程序语句执行,可能会有另一个程序语句列表,该列表在条件为假时执行:
|
||||
|
||||
|
||||
```
|
||||
if [ arg1 operator arg2 ] ; then list
|
||||
或
|
||||
if [ arg1 operator arg2 ] ; then list ; else list ; fi
|
||||
```
|
||||
|
||||
像例子中那样,在比较表达式中,空格不能省略。中括号的每部分,`[` 和 `]`,是跟 `test` 命令一样的传统的 Bash 符号:
|
||||
|
||||
```
|
||||
if test arg1 operator arg2 ; then list
|
||||
```
|
||||
|
||||
还有一个更新的语法能提供一点点便利,一些系统管理员比较喜欢用。这种格式对于不同版本的 Bash 和一些 shell 如 ksh(Korn shell)兼容性稍差。格式如下:
|
||||
|
||||
```
|
||||
if [[ arg1 operator arg2 ]] ; then list
|
||||
```
|
||||
|
||||
#### 文件操作符
|
||||
|
||||
文件操作符是 Bash 中一系列强大的逻辑操作符。图表 1 列出了 20 多种不同的 Bash 处理文件的操作符。在我的脚本中使用频率很高。
|
||||
|
||||
操作符 | 描述
|
||||
---|---
|
||||
`-a filename` | 如果文件存在,返回真值;文件可以为空也可以有内容,但是只要它存在,就返回真值
|
||||
`-b filename` | 如果文件存在且是一个块设备,如 `/dev/sda` 或 `/dev/sda1`,则返回真值
|
||||
`-c filename` | 如果文件存在且是一个字符设备,如 `/dev/TTY1`,则返回真值
|
||||
`-d filename` | 如果文件存在且是一个目录,返回真值
|
||||
`-e filename` | 如果文件存在,返回真值;与上面的 `-a` 相同
|
||||
`-f filename` | 如果文件存在且是一个一般文件,不是目录、设备文件或链接等的其他的文件,则返回 真值
|
||||
`-g filename` | 如果文件存在且 `SETGID` 标记被设置在其上,返回真值
|
||||
`-h filename` | 如果文件存在且是一个符号链接,则返回真值
|
||||
`-k filename` | 如果文件存在且粘滞位已设置,则返回真值
|
||||
`-p filename` | 如果文件存在且是一个命名的管道(FIFO),返回真值
|
||||
`-r filename` | 如果文件存在且有可读权限(它的可读位被设置),返回真值
|
||||
`-s filename` | 如果文件存在且大小大于 0,返回真值;如果一个文件存在但大小为 0,则返回假值
|
||||
`-t fd` | 如果文件描述符 `fd` 被打开且被关联到一个终端设备上,返回真值
|
||||
`-u filename` | 如果文件存在且它的 `SETUID` 位被设置,返回真值
|
||||
`-w filename` | 如果文件存在且有可写权限,返回真值
|
||||
`-x filename` | 如果文件存在且有可执行权限,返回真值
|
||||
`-G filename` | 如果文件存在且文件的组 ID 与当前用户相同,返回真值
|
||||
`-L filename` | 如果文件存在且是一个符号链接,返回真值(同 `-h`)
|
||||
`-N filename` | 如果文件存在且从文件上一次被读取后文件被修改过,返回真值
|
||||
`-O filename` | 如果文件存在且你是文件的拥有者,返回真值
|
||||
`-S filename` | 如果文件存在且文件是套接字,返回真值
|
||||
`file1 -ef file2` | 如果文件 `file1` 和文件 `file2` 指向同一设备的同一 INODE 号,返回真值(即硬链接)
|
||||
`file1 -nt file2` | 如果文件 `file1` 比 `file2` 新(根据修改日期),或 `file1` 存在而 `file2` 不存在,返回真值
|
||||
`file1 -ot file2` | 如果文件 `file1` 比 `file2` 旧(根据修改日期),或 `file1` 不存在而 `file2` 存在
|
||||
|
||||
*图表 1:Bash 文件操作符*
|
||||
|
||||
以测试一个文件存在与否来举例:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; if [ -e $File ] ; then echo "The file $File exists." ; else echo "The file $File does not exist." ; fi
|
||||
The file TestFile1 does not exist.
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
创建一个用来测试的文件,命名为 `TestFile1`。目前它不需要包含任何数据:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ touch TestFile1
|
||||
```
|
||||
|
||||
在这个简短的 CLI 程序中,修改 `$File` 变量的值相比于在多个地方修改表示文件名的字符串的值要容易:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; if [ -e $File ] ; then echo "The file $File exists." ; else echo "The file $File does not exist." ; fi
|
||||
The file TestFile1 exists.
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
现在,运行一个测试来判断一个文件是否存在且长度不为 0(表示它包含数据)。假设你想判断三种情况:
|
||||
|
||||
1. 文件不存在;
|
||||
2. 文件存在且为空;
|
||||
3. 文件存在且包含数据。
|
||||
|
||||
因此,你需要一组更复杂的测试代码 — 为了测试所有的情况,使用 `if-elif-else` 结构中的 `elif` 语句:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; if [ -s $File ] ; then echo "$File exists and contains data." ; fi
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
在这个情况中,文件存在但不包含任何数据。向文件添加一些数据再运行一次:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; echo "This is file $File" > $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; fi
|
||||
TestFile1 exists and contains data.
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
这组语句能返回正常的结果,但是仅仅是在我们已知三种可能的情况下测试某种确切的条件。添加一段 `else` 语句,这样你就可以更精确地测试。把文件删掉,你就可以完整地测试这段新代码:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; rm $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; else echo "$File does not exist or is empty." ; fi
|
||||
TestFile1 does not exist or is empty.
|
||||
```
|
||||
|
||||
现在创建一个空文件用来测试:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; touch $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; else echo "$File does not exist or is empty." ; fi
|
||||
TestFile1 does not exist or is empty.
|
||||
```
|
||||
|
||||
向文件添加一些内容,然后再测试一次:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; echo "This is file $File" > $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; else echo "$File does not exist or is empty." ; fi
|
||||
TestFile1 exists and contains data.
|
||||
```
|
||||
|
||||
现在加入 `elif` 语句来辨别是文件不存在还是文件为空:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; touch $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; elif [ -e $File ] ; then echo "$File exists and is empty." ; else echo "$File does not exist." ; fi
|
||||
TestFile1 exists and is empty.
|
||||
[student@studentvm1 testdir]$ File="TestFile1" ; echo "This is $File" > $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; elif [ -e $File ] ; then echo "$File exists and is empty." ; else echo "$File does not exist." ; fi
|
||||
TestFile1 exists and contains data.
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
现在你有一个可以测试这三种情况的 Bash CLI 程序,但是可能的情况是无限的。
|
||||
|
||||
如果你能像保存在文件中的脚本那样组织程序语句,那么即使对于更复杂的命令组合也会很容易看出它们的逻辑结构。图表 2 就是一个示例。 `if-elif-else` 结构中每一部分的程序语句的缩进让逻辑更变得清晰。
|
||||
|
||||
|
||||
```
|
||||
File="TestFile1"
|
||||
echo "This is $File" > $File
|
||||
if [ -s $File ]
|
||||
then
|
||||
echo "$File exists and contains data."
|
||||
elif [ -e $File ]
|
||||
then
|
||||
echo "$File exists and is empty."
|
||||
else
|
||||
echo "$File does not exist."
|
||||
fi
|
||||
```
|
||||
|
||||
*图表 2: 像在脚本里一样重写书写命令行程序*
|
||||
|
||||
对于大多数 CLI 程序来说,让这些复杂的命令变得有逻辑需要写很长的代码。虽然 CLI 可能是用 Linux 或 Bash 内置的命令,但是当 CLI 程序很长或很复杂时,创建一个保存在文件中的脚本将更有效,保存到文件中后,可以随时运行。
|
||||
|
||||
#### 字符串比较操作符
|
||||
|
||||
字符串比较操作符使我们可以对字符串中的字符按字母顺序进行比较。图表 3 列出了仅有的几个字符串比较操作符。
|
||||
|
||||
操作符 | 描述
|
||||
---|---
|
||||
`-z string` | 如果字符串的长度为 0 ,返回真值
|
||||
`-n string` |如果字符串的长度不为 0 ,返回真值
|
||||
`string1 == string2` 或 `string1 = string2` | 如果两个字符串相等,返回真值。处于遵从 POSIX 一致性,在测试命令中应使用一个等号 `=`。与命令 `[[` 一起使用时,会进行如上描述的模式匹配(混合命令)。
|
||||
`string1 != string2` | 两个字符串不相等,返回真值
|
||||
`string1 < string2` | 如果对 `string1` 和 `string2` 按字母顺序进行排序,`string1` 排在 `string2` 前面(即基于地区设定的对所有字母和特殊字符的排列顺序)
|
||||
`string1 > string2` | 如果对 `string1` 和 `string2` 按字母顺序进行排序,`string1` 排在 `string2` 后面
|
||||
|
||||
*图表 3: Bash 字符串逻辑操作符*
|
||||
|
||||
首先,检查字符串长度。比较表达式中 `$MyVar` 两边的双引号不能省略(你仍应该在目录 `~/testdir` 下 )。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ MyVar="" ; if [ -z "" ] ; then echo "MyVar is zero length." ; else echo "MyVar contains data" ; fi
|
||||
MyVar is zero length.
|
||||
[student@studentvm1 testdir]$ MyVar="Random text" ; if [ -z "" ] ; then echo "MyVar is zero length." ; else echo "MyVar contains data" ; fi
|
||||
MyVar is zero length.
|
||||
```
|
||||
|
||||
你也可以这样做:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ MyVar="Random text" ; if [ -n "$MyVar" ] ; then echo "MyVar contains data." ; else echo "MyVar is zero length" ; fi
|
||||
MyVar contains data.
|
||||
[student@studentvm1 testdir]$ MyVar="" ; if [ -n "$MyVar" ] ; then echo "MyVar contains data." ; else echo "MyVar is zero length" ; fi
|
||||
MyVar is zero length
|
||||
```
|
||||
|
||||
有时候你需要知道一个字符串确切的长度。这虽然不是比较,但是也与比较相关。不幸的是,计算字符串的长度没有简单的方法。有很多种方法可以计算,但是我认为使用 `expr`(求值表达式)命令是相对最简单的一种。阅读 `expr` 的手册页可以了解更多相关知识。注意表达式中你检测的字符串或变量两边的引号不要省略。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ MyVar="" ; expr length "$MyVar"
|
||||
0
|
||||
[student@studentvm1 testdir]$ MyVar="How long is this?" ; expr length "$MyVar"
|
||||
17
|
||||
[student@studentvm1 testdir]$ expr length "We can also find the length of a literal string as well as a variable."
|
||||
70
|
||||
```
|
||||
|
||||
关于比较操作符,在我们的脚本中使用了大量的检测两个字符串是否相等(例如,两个字符串是否实际上是同一个字符串)的操作。我使用的是非 POSIX 版本的比较表达式:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ Var1="Hello World" ; Var2="Hello World" ; if [ "$Var1" == "$Var2" ] ; then echo "Var1 matches Var2" ; else echo "Var1 and Var2 do not match." ; fi
|
||||
Var1 matches Var2
|
||||
[student@studentvm1 testdir]$ Var1="Hello World" ; Var2="Hello world" ; if [ "$Var1" == "$Var2" ] ; then echo "Var1 matches Var2" ; else echo "Var1 and Var2 do not match." ; fi
|
||||
Var1 and Var2 do not match.
|
||||
```
|
||||
|
||||
在你自己的脚本中去试一下这些操作符。
|
||||
|
||||
#### 数字比较操作符
|
||||
|
||||
数字操作符用于两个数字参数之间的比较。像其他类操作符一样,大部分都很容易理解。
|
||||
|
||||
操作符 | 描述
|
||||
---|---
|
||||
`arg1 -eq arg2` | 如果 `arg1` 等于 `arg2`,返回真值
|
||||
`arg1 -ne arg2` | 如果 `arg1` 不等于 `arg2`,返回真值
|
||||
`arg1 -lt arg2` | 如果 `arg1` 小于 `arg2`,返回真值
|
||||
`arg1 -le arg2` | 如果 `arg1` 小于或等于 `arg2`,返回真值
|
||||
`arg1 -gt arg2` | 如果 `arg1` 大于 `arg2`,返回真值
|
||||
`arg1 -ge arg2` | 如果 `arg1` 大于或等于 `arg2`,返回真值
|
||||
|
||||
*图表 4: Bash 数字比较逻辑操作符*
|
||||
|
||||
来看几个简单的例子。第一个示例设置变量 `$X` 的值为 1,然后检测 `$X` 是否等于 1。第二个示例中,`$X` 被设置为 0,所以比较表达式返回结果不为真值。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ X=1 ; if [ $X -eq 1 ] ; then echo "X equals 1" ; else echo "X does not equal 1" ; fi
|
||||
X equals 1
|
||||
[student@studentvm1 testdir]$ X=0 ; if [ $X -eq 1 ] ; then echo "X equals 1" ; else echo "X does not equal 1" ; fi
|
||||
X does not equal 1
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
自己来多尝试一下其他的。
|
||||
|
||||
#### 杂项操作符
|
||||
|
||||
这些杂项操作符展示一个 shell 选项是否被设置,或一个 shell 变量是否有值,但是它不显示变量的值,只显示它是否有值。
|
||||
|
||||
操作符 | 描述
|
||||
---|---
|
||||
`-o optname` | 如果一个 shell 选项 `optname` 是启用的(查看内建在 Bash 手册页中的 set `-o` 选项描述下面的选项列表),则返回真值
|
||||
`-v varname` | 如果 shell 变量 `varname` 被设置了值(被赋予了值),则返回真值
|
||||
`-R varname` | 如果一个 shell 变量 `varname` 被设置了值且是一个名字引用,则返回真值
|
||||
|
||||
*图表 5: 杂项 Bash 逻辑操作符*
|
||||
|
||||
自己来使用这些操作符实践下。
|
||||
|
||||
### 扩展
|
||||
|
||||
Bash 支持非常有用的几种类型的扩展和命令替换。根据 Bash 手册页,Bash 有七种扩展格式。本文只介绍其中五种:`~` 扩展、算术扩展、路径名称扩展、大括号扩展和命令替换。
|
||||
|
||||
#### 大括号扩展
|
||||
|
||||
大括号扩展是生成任意字符串的一种方法。(下面的例子是用特定模式的字符创建大量的文件。)大括号扩展可以用于产生任意字符串的列表,并把它们插入一个用静态字符串包围的特定位置或静态字符串的两端。这可能不太好想象,所以还是来实践一下。
|
||||
|
||||
首先,看一下大括号扩展的作用:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ echo {string1,string2,string3}
|
||||
string1 string2 string3
|
||||
```
|
||||
|
||||
看起来不是很有用,对吧?但是用其他方式使用它,再来看看:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ echo "Hello "{David,Jen,Rikki,Jason}.
|
||||
Hello David. Hello Jen. Hello Rikki. Hello Jason.
|
||||
```
|
||||
|
||||
这看起来貌似有点用了 — 我们可以少打很多字。现在试一下这个:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ echo b{ed,olt,ar}s
|
||||
beds bolts bars
|
||||
```
|
||||
|
||||
我可以继续举例,但是你应该已经理解了它的用处。
|
||||
|
||||
#### ~ 扩展
|
||||
|
||||
资料显示,使用最多的扩展是波浪字符(`~`)扩展。当你在命令中使用它(如 `cd ~/Documents`)时,Bash shell 把这个快捷方式展开成用户的完整的家目录。
|
||||
|
||||
使用这个 Bash 程序观察 `~` 扩展的作用:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ echo ~
|
||||
/home/student
|
||||
[student@studentvm1 testdir]$ echo ~/Documents
|
||||
/home/student/Documents
|
||||
[student@studentvm1 testdir]$ Var1=~/Documents ; echo $Var1 ; cd $Var1
|
||||
/home/student/Documents
|
||||
[student@studentvm1 Documents]$
|
||||
```
|
||||
|
||||
#### 路径名称扩展
|
||||
|
||||
路径名称扩展是展开文件通配模式为匹配该模式的完整路径名称的另一种说法,匹配字符使用 `?` 和 `*`。文件通配指的是在大量操作中匹配文件名、路径和其他字符串时用特定的模式字符产生极大的灵活性。这些特定的模式字符允许匹配字符串中的一个、多个或特定字符。
|
||||
|
||||
* `?` — 匹配字符串中特定位置的一个任意字符
|
||||
* `*` — 匹配字符串中特定位置的 0 个或多个任意字符
|
||||
|
||||
这个扩展用于匹配路径名称。为了弄清它的用法,请确保 `testdir` 是当前工作目录(`PWD`),先执行基本的列出清单命令 `ls`(我家目录下的内容跟你的不一样)。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ ls
|
||||
chapter6 cpuHog.dos dmesg1.txt Documents Music softlink1 testdir6 Videos
|
||||
chapter7 cpuHog.Linux dmesg2.txt Downloads Pictures Templates testdir
|
||||
testdir cpuHog.mac dmesg3.txt file005 Public testdir tmp
|
||||
cpuHog Desktop dmesg.txt link3 random.txt testdir1 umask.test
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
现在列出以 `Do`、`testdir/Documents` 和 `testdir/Downloads` 开头的目录:
|
||||
|
||||
```
|
||||
Documents:
|
||||
Directory01 file07 file15 test02 test10 test20 testfile13 TextFiles
|
||||
Directory02 file08 file16 test03 test11 testfile01 testfile14
|
||||
file01 file09 file17 test04 test12 testfile04 testfile15
|
||||
file02 file10 file18 test05 test13 testfile05 testfile16
|
||||
file03 file11 file19 test06 test14 testfile09 testfile17
|
||||
file04 file12 file20 test07 test15 testfile10 testfile18
|
||||
file05 file13 Student1.txt test08 test16 testfile11 testfile19
|
||||
file06 file14 test01 test09 test18 testfile12 testfile20
|
||||
|
||||
Downloads:
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
然而,并没有得到你期望的结果。它列出了以 `Do` 开头的目录下的内容。使用 `-d` 选项,仅列出目录而不列出它们的内容。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ ls -d Do*
|
||||
Documents Downloads
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
在两个例子中,Bash shell 都把 `Do*` 模式展开成了匹配该模式的目录名称。但是如果有文件也匹配这个模式,会发生什么?
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ touch Downtown ; ls -d Do*
|
||||
Documents Downloads Downtown
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
因此所有匹配这个模式的文件也被展开成了完整名字。
|
||||
|
||||
#### 命令替换
|
||||
|
||||
命令替换是让一个命令的标准输出数据流被当做参数传给另一个命令的扩展形式,例如,在一个循环中作为一系列被处理的项目。Bash 手册页显示:“命令替换可以让你用一个命令的输出替换为命令的名字。”这可能不太好理解。
|
||||
|
||||
命令替换有两种格式:\`command\` 和 `$(command)`。在更早的格式中使用反引号(\`),在命令中使用反斜杠(`\`)来保持它转义之前的文本含义。然而,当用在新版本的括号格式中时,反斜杠被当做一个特殊字符处理。也请注意带括号的格式打开个关闭命令语句都是用一个括号。
|
||||
|
||||
我经常在命令行程序和脚本中使用这种能力,一个命令的结果能被用作另一个命令的参数。
|
||||
|
||||
来看一个非常简单的示例,这个示例使用了这个扩展的两种格式(再一次提醒,确保 `testdir` 是当前工作目录):
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ echo "Todays date is `date`"
|
||||
Todays date is Sun Apr 7 14:42:46 EDT 2019
|
||||
[student@studentvm1 testdir]$ echo "Todays date is $(date)"
|
||||
Todays date is Sun Apr 7 14:42:59 EDT 2019
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
`-seq` 工具用于一个数字序列:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ seq 5
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
[student@studentvm1 testdir]$ echo `seq 5`
|
||||
1 2 3 4 5
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
现在你可以做一些更有用处的操作,比如创建大量用于测试的空文件。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for I in $(seq -w 5000) ; do touch file-$I ; done
|
||||
```
|
||||
|
||||
`seq` 工具加上 `-w` 选项后,在生成的数字前面会用 0 补全,这样所有的结果都等宽,例如,忽略数字的值,它们的位数一样。这样在对它们按数字顺序进行排列时很容易。
|
||||
|
||||
`seq -w 5000` 语句生成了 1 到 5000 的数字序列。通过把命令替换用于 `for` 语句,`for` 语句就可以使用该数字序列来生成文件名的数字部分。
|
||||
|
||||
#### 算术扩展
|
||||
|
||||
Bash 可以进行整型的数学计算,但是比较繁琐(你一会儿将看到)。数字扩展的语法是 `$((arithmetic-expression))` ,分别用两个括号来打开和关闭表达式。算术扩展在 shell 程序或脚本中类似命令替换;表达式结算后的结果替换了表达式,用于 shell 后续的计算。
|
||||
|
||||
我们再用一个简单的用法来开始:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ echo $((1+1))
|
||||
2
|
||||
[student@studentvm1 testdir]$ Var1=5 ; Var2=7 ; Var3=$((Var1*Var2)) ; echo "Var 3 = $Var3"
|
||||
Var 3 = 35
|
||||
```
|
||||
|
||||
下面的除法结果是 0,因为表达式的结果是一个小于 1 的整型数字:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ Var1=5 ; Var2=7 ; Var3=$((Var1/Var2)) ; echo "Var 3 = $Var3"
|
||||
Var 3 = 0
|
||||
```
|
||||
|
||||
这是一个我经常在脚本或 CLI 程序中使用的一个简单的计算,用来查看在 Linux 主机中使用了多少虚拟内存。 `free` 不提供我需要的数据:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ RAM=`free | grep ^Mem | awk '{print $2}'` ; Swap=`free | grep ^Swap | awk '{print $2}'` ; echo "RAM = $RAM and Swap = $Swap" ; echo "Total Virtual memory is $((RAM+Swap))" ;
|
||||
RAM = 4037080 and Swap = 6291452
|
||||
Total Virtual memory is 10328532
|
||||
```
|
||||
|
||||
我使用 \` 字符来划定用作命令替换的界限。
|
||||
|
||||
我用 Bash 算术扩展的场景主要是用脚本检查系统资源用量后基于返回的结果选择一个程序运行的路径。
|
||||
|
||||
### 总结
|
||||
|
||||
本文是 Bash 编程语言系列的第二篇,探讨了 Bash 中文件、字符串、数字和各种提供流程控制逻辑的逻辑操作符还有不同种类的 shell 扩展。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/programming-bash-logical-operators-shell-expansions
|
||||
|
||||
作者:[David Both][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[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/OSDC_women_computing_5.png?itok=YHpNs_ss (Women in computing and open source v5)
|
||||
[2]: http://www.both.org/?page_id=1183
|
||||
[3]: https://linux.cn/article-11552-1.html
|
336
published/201912/20191023 How to program with Bash- Loops.md
Normal file
336
published/201912/20191023 How to program with Bash- Loops.md
Normal file
@ -0,0 +1,336 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11714-1.html)
|
||||
[#]: subject: (How to program with Bash: Loops)
|
||||
[#]: via: (https://opensource.com/article/19/10/programming-bash-loops)
|
||||
[#]: author: (David Both https://opensource.com/users/dboth)
|
||||
|
||||
怎样用 Bash 编程:循环
|
||||
======
|
||||
|
||||
> 本文是 Bash 编程系列三篇中的最后一篇,来学习使用循环执行迭代的操作。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/26/111437f9pa3zqqwcc9wwg1.jpg)
|
||||
|
||||
Bash 是一种强大的用于命令行和 shell 脚本的编程语言。本系列的三部分都是基于我的三集 [Linux 自学课程][2] 写的,探索怎么用 CLI 进行 bash 编程。
|
||||
|
||||
本系列的 [第一篇文章][3] 讨论了 bash 编程的一些简单命令行操作,如使用变量和控制操作符。[第二篇文章][4] 探讨了文件、字符串、数字等类型和各种各样在执行流中提供控制逻辑的的逻辑运算符,还有 bash 中不同种类的扩展。本文是第三篇(也是最后一篇),意在考察在各种迭代的操作中使用循环以及怎么合理控制循环。
|
||||
|
||||
### 循环
|
||||
|
||||
我使用过的所有编程语言都至少有两种循环结构来用来执行重复的操作。我经常使用 `for` 循环,然而我发现 `while` 和 `until` 循环也很有用处。
|
||||
|
||||
#### for 循环
|
||||
|
||||
我的理解是,在 bash 中实现的 `for` 命令比大部分语言灵活,因为它可以处理非数字的值;与之形成对比的是,诸如标准 C 语言的 `for` 循环只能处理数字类型的值。
|
||||
|
||||
Bash 版的 `for` 命令基本的结构很简单:
|
||||
|
||||
```
|
||||
for Var in list1 ; do list2 ; done
|
||||
```
|
||||
|
||||
解释一下:“对于 `list1` 中的每一个值,把 `$Var` 设置为那个值,使用该值执行 `list2` 中的程序语句;`list1` 中的值都执行完后,整个循环结束,退出循环。” `list1` 中的值可以是一个简单的显式字符串值,也可以是一个命令执行后的结果(`` 包含其内的命令执行的结果,本系列第二篇文章中有描述)。我经常使用这种结构。
|
||||
|
||||
要测试它,确认 `~/testdir` 仍然是当前的工作目录(PWD)。删除目录下所有东西,来看下这个显式写出值列表的 `for` 循环的简单的示例。这个列表混合了字母和数字 — 但是不要忘了,在 bash 中所有的变量都是字符串或者可以被当成字符串来处理。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rm *
|
||||
[student@studentvm1 testdir]$ for I in a b c d 1 2 3 4 ; do echo $I ; done
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
```
|
||||
|
||||
给变量赋予更有意义的名字,变成前面版本的进阶版:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Department $Dept" ; done
|
||||
Department Human Resources
|
||||
Department Sales
|
||||
Department Finance
|
||||
Department Information Technology
|
||||
Department Engineering
|
||||
Department Administration
|
||||
Department Research
|
||||
```
|
||||
|
||||
创建几个目录(创建时显示一些处理信息):
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; done
|
||||
Working on Department Human Resources
|
||||
Working on Department Sales
|
||||
Working on Department Finance
|
||||
Working on Department Information Technology
|
||||
Working on Department Engineering
|
||||
Working on Department Administration
|
||||
Working on Department Research
|
||||
[student@studentvm1 testdir]$ ll
|
||||
total 28
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Administration
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Engineering
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Finance
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 'Human Resources'
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 'Information Technology'
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Research
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Sales
|
||||
```
|
||||
|
||||
在 `mkdir` 语句中 `$Dept` 变量必须用引号包裹起来;否则名字中间有空格(如 `Information Technology`)会被当做两个独立的目录处理。我一直信奉的一条实践规则:所有的文件和目录都应该为一个单词(中间没有空格)。虽然大部分现代的操作系统可以处理名字中间有空格的情况,但是系统管理员需要花费额外的精力去确保脚本和 CLI 程序能正确处理这些特例。(即使它们很烦人,也务必考虑它们,因为你永远不知道将拥有哪些文件。)
|
||||
|
||||
再次删除 `~/testdir` 下的所有东西 — 再运行一次下面的命令:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rm -rf * ; ll
|
||||
total 0
|
||||
[student@studentvm1 testdir]$ for Dept in Human-Resources Sales Finance Information-Technology Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; done
|
||||
Working on Department Human-Resources
|
||||
Working on Department Sales
|
||||
Working on Department Finance
|
||||
Working on Department Information-Technology
|
||||
Working on Department Engineering
|
||||
Working on Department Administration
|
||||
Working on Department Research
|
||||
[student@studentvm1 testdir]$ ll
|
||||
total 28
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Administration
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Engineering
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Finance
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Human-Resources
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Information-Technology
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Research
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Sales
|
||||
```
|
||||
|
||||
假设现在有个需求,需要列出一台 Linux 机器上所有的 RPM 包并对每个包附上简短的描述。我为北卡罗来纳州工作的时候,曾经遇到过这种需求。由于当时开源尚未得到州政府的“批准”,而且我只在台式机上使用 Linux,对技术一窍不通的老板(PHB)需要我列出我计算机上安装的所有软件,以便他们可以“批准”一个特例。
|
||||
|
||||
你怎么实现它?有一种方法是,已知 `rpm –qa` 命令提供了 RPM 包的完整描述,包括了白痴老板想要的东西:软件名称和概要描述。
|
||||
|
||||
让我们一步步执行出最后的结果。首先,列出所有的 RPM 包:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rpm -qa
|
||||
perl-HTTP-Message-6.18-3.fc29.noarch
|
||||
perl-IO-1.39-427.fc29.x86_64
|
||||
perl-Math-Complex-1.59-429.fc29.noarch
|
||||
lua-5.3.5-2.fc29.x86_64
|
||||
java-11-openjdk-headless-11.0.ea.28-2.fc29.x86_64
|
||||
util-linux-2.32.1-1.fc29.x86_64
|
||||
libreport-fedora-2.9.7-1.fc29.x86_64
|
||||
rpcbind-1.2.5-0.fc29.x86_64
|
||||
libsss_sudo-2.0.0-5.fc29.x86_64
|
||||
libfontenc-1.1.3-9.fc29.x86_64
|
||||
<snip>
|
||||
```
|
||||
|
||||
用 `sort` 和 `uniq` 命令对列表进行排序和打印去重后的结果(有些已安装的 RPM 包具有相同的名字):
|
||||
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rpm -qa | sort | uniq
|
||||
a2ps-4.14-39.fc29.x86_64
|
||||
aajohan-comfortaa-fonts-3.001-3.fc29.noarch
|
||||
abattis-cantarell-fonts-0.111-1.fc29.noarch
|
||||
abiword-3.0.2-13.fc29.x86_64
|
||||
abrt-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-ccpp-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-coredump-helper-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-kerneloops-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-pstoreoops-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-vmcore-2.11.0-1.fc29.x86_64
|
||||
<snip>
|
||||
```
|
||||
|
||||
以上命令得到了想要的 RPM 列表,因此你可以把这个列表作为一个循环的输入信息,循环最终会打印每个 RPM 包的详细信息:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done
|
||||
```
|
||||
|
||||
这段代码产出了多余的信息。当循环结束后,下一步就是提取出白痴老板需要的信息。因此,添加一个 `egrep` 命令用来搜索匹配 `^Name` 或 `^Summary` 的行。脱字符(`^`)表示行首,整个命令表示显示所有以 Name 或 Summary 开头的行。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary"
|
||||
Name : a2ps
|
||||
Summary : Converts text and other types of files to PostScript
|
||||
Name : aajohan-comfortaa-fonts
|
||||
Summary : Modern style true type font
|
||||
Name : abattis-cantarell-fonts
|
||||
Summary : Humanist sans serif font
|
||||
Name : abiword
|
||||
Summary : Word processing program
|
||||
Name : abrt
|
||||
Summary : Automatic bug detection and reporting tool
|
||||
<snip>
|
||||
```
|
||||
|
||||
在上面的命令中你可以试试用 `grep` 代替 `egrep` ,你会发现用 `grep` 不能得到正确的结果。你也可以通过管道把命令结果用 `less` 过滤器来查看。最终命令像这样:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary" > RPM-summary.txt
|
||||
```
|
||||
|
||||
这个命令行程序用到了管道、重定向和 `for` 循环,这些全都在一行中。它把你的 CLI 程序的结果重定向到了一个文件,这个文件可以在邮件中使用或在其他地方作为输入使用。
|
||||
|
||||
这个一次一步构建程序的过程让你能看到每步的结果,以此来确保整个程序以你期望的流程进行且输出你想要的结果。
|
||||
|
||||
白痴老板最终收到了超过 1900 个不同的 RPM 包的清单,我严重怀疑根本就没人读过这个列表。我给了他们想要的东西,没有从他们嘴里听到过任何关于 RPM 包的信息。
|
||||
|
||||
### 其他循环
|
||||
|
||||
Bash 中还有两种其他类型的循环结构:`while` 和 `until` 结构,两者在语法和功能上都类似。这些循环结构的基础语法很简单:
|
||||
|
||||
```
|
||||
while [ expression ] ; do list ; done
|
||||
```
|
||||
|
||||
逻辑解释:表达式(`expression`)结果为 true 时,执行程序语句 `list`。表达式结果为 false 时,退出循环。
|
||||
|
||||
```
|
||||
until [ expression ] ; do list ; done
|
||||
```
|
||||
|
||||
逻辑解释:执行程序语句 `list`,直到表达式的结果为 true。当表达式结果为 true 时,退出循环。
|
||||
|
||||
#### While 循环
|
||||
|
||||
`while` 循环用于当逻辑表达式结果为 true 时执行一系列程序语句。假设你的 PWD 仍是 `~/testdir`。
|
||||
|
||||
最简单的 `while` 循环形式是这个会一直运行下去的循环。下面格式的条件语句永远以 `true` 作为返回。你也可以用简单的 `1` 代替 `true`,结果一样,但是这解释了 true 表达式的用法。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ X=0 ; while [ true ] ; do echo $X ; X=$((X+1)) ; done | head
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
既然你已经学了 CLI 的各部分知识,那就让它变得更有用处。首先,为了防止变量 `$X` 在前面的程序或 CLI 命令执行后有遗留的值,设置 `$X` 的值为 0。然后,因为逻辑表达式 `[ true ]` 的结果永远是 1,即 true,在 `do` 和 `done` 中间的程序指令列表会一直执行 — 或者直到你按下 `Ctrl+C` 抑或发送一个 2 号信号给程序。那些程序指令是算数扩展,用来打印变量 `$X` 当前的值并加 1.
|
||||
|
||||
《[系统管理员的 Linux 哲学][5]》的信条之一是追求优雅,实现优雅的一种方式就是简化。你可以用操作符 `++` 来简化这个程序。在第一个例子中,变量当前的值被打印出来,然后变量的值增加了。可以在变量后加一个 `++` 来表示这个逻辑:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((X++)) ; done | head
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
```
|
||||
|
||||
现在删掉程序最后的 `| head` 再运行一次。
|
||||
|
||||
在下面这个版本中,变量在值被打印之前就自增了。这是通过在变量之前添加 `++` 操作符实现的。你能看出区别吗?
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((++X)) ; done | head
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
```
|
||||
|
||||
你已经把打印变量的值和自增简化到了一条语句。类似 `++` 操作符,也有 `--` 操作符。
|
||||
|
||||
你需要一个在循环到某个特定数字时终止循环的方法。把 true 表达式换成一个数字比较表达式来实现它。这里有一个循环到 5 终止的程序。在下面的示例代码中,你可以看到 `-le` 是 “小于或等于” 的数字逻辑操作符。整个语句的意思:只要 `$X` 的值小于或等于 5,循环就一直运行。当 `$X` 增加到 6 时,循环终止。
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; while [ $X -le 5 ] ; do echo $((X++)) ; done
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
#### Until 循环
|
||||
|
||||
`until` 命令非常像 `while` 命令。不同之处是,它直到逻辑表达式的值是 `true` 之前,会一直循环。看一下这种结构最简单的格式:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; until false ; do echo $((X++)) ; done | head
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
它用一个逻辑比较表达式来计数到一个特定的值:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((X++)) ; done
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((++X)) ; done
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
本系列探讨了构建 Bash 命令行程序和 shell 脚本的很多强大的工具。但是这仅仅是你能用 Bash 做的很多有意思的事中的冰山一角,接下来就看你的了。
|
||||
|
||||
我发现学习 Bash 编程最好的方法就是实践。找一个需要多个 Bash 命令的简单项目然后写一个 CLI 程序。系统管理员们要做很多适合 CLI 编程的工作,因此我确信你很容易能找到自动化的任务。
|
||||
|
||||
很多年前,尽管我对其他的 Shell 语言和 Perl 很熟悉,但还是决定用 Bash 做所有系统管理员的自动化任务。我发现,有时稍微搜索一下,我可以用 Bash 实现我需要的所有事情。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/programming-bash-loops
|
||||
|
||||
作者:[David Both][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[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/fail_progress_cycle_momentum_arrow.png?itok=q-ZFa_Eh (arrows cycle symbol for failing faster)
|
||||
[2]: http://www.both.org/?page_id=1183
|
||||
[3]: https://linux.cn/article-11552-1.html
|
||||
[4]: https://linux.cn/article-11687-1.html
|
||||
[5]: https://www.apress.com/us/book/9781484237298
|
@ -0,0 +1,240 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11657-1.html)
|
||||
[#]: subject: (Get sorted with sort at the command line)
|
||||
[#]: via: (https://opensource.com/article/19/10/get-sorted-sort)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
在命令行用 sort 进行排序
|
||||
======
|
||||
|
||||
> 在 Linux、BSD 或 Mac 的终端中使用 sort 命令,按自己的需求重新整理数据。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/09/065444f42xl2lddxillz09.jpg)
|
||||
|
||||
如果你曾经用过数据表应用程序,你就会知道可以按列的内容对行进行排序。例如,如果你有一个费用列表,你可能希望对它们进行按日期或价格升序抑或按类别进行排序。如果你熟悉终端的使用,你不会仅为了排序文本数据就去使用庞大的办公软件。这正是 [sort][2] 命令的用处。
|
||||
|
||||
### 安装
|
||||
|
||||
你不必安装 `sort` ,因为它向来都包含在 [POSIX][3] 系统里。在大多数 Linux 系统中,`sort` 命令来自 GNU 组织打包的实用工具集合中。在其他的 POSIX 系统中,像 BSD 和 Mac,默认的 `sort` 命令不是 GNU 提供的,所以有一些选项可能不一样。本文中我尽量对 GNU 和 BSD 两者的实现都进行说明。
|
||||
|
||||
### 按字母顺序排列行
|
||||
|
||||
`sort` 命令默认会读取文件每行的第一个字符并对每行按字母升序排序后输出。两行中的第一个字符相同的情况下,对下一个字符进行对比。例如:
|
||||
|
||||
```
|
||||
$ cat distro.list
|
||||
Slackware
|
||||
Fedora
|
||||
Red Hat Enterprise Linux
|
||||
Ubuntu
|
||||
Arch
|
||||
1337
|
||||
Mint
|
||||
Mageia
|
||||
Debian
|
||||
$ sort distro.list
|
||||
1337
|
||||
Arch
|
||||
Debian
|
||||
Fedora
|
||||
Mageia
|
||||
Mint
|
||||
Red Hat Enterprise Linux
|
||||
Slackware
|
||||
Ubuntu
|
||||
```
|
||||
|
||||
使用 `sort` 不会改变原文件。`sort` 仅起到过滤的作用,所以如果你希望按排序后的格式保存数据,你需要用 `>` 或 `tee` 进行重定向。
|
||||
|
||||
|
||||
```
|
||||
$ sort distro.list | tee distro.sorted
|
||||
1337
|
||||
Arch
|
||||
Debian
|
||||
[...]
|
||||
$ cat distro.sorted
|
||||
1337
|
||||
Arch
|
||||
Debian
|
||||
[...]
|
||||
```
|
||||
|
||||
### 按列排序
|
||||
|
||||
复杂数据集有时候不止需要对每行的第一个字符进行排序。例如,假设有一个动物列表,每个都有其种和属,用可预见的分隔符分隔每一个“字段”(即数据表中的“单元格”)。这类由数据表导出的格式很常见,CSV(<ryby>以逗号分隔的数据<rt>comma-separated values</rt></ruby>)后缀可以标识这些文件(虽然 CSV 文件不一定用逗号分隔,有分隔符的文件也不一定用 CSV 后缀)。以下数据作为示例:
|
||||
|
||||
```
|
||||
Aptenodytes;forsteri;Miller,JF;1778;Emperor
|
||||
Pygoscelis;papua;Wagler;1832;Gentoo
|
||||
Eudyptula;minor;Bonaparte;1867;Little Blue
|
||||
Spheniscus;demersus;Brisson;1760;African
|
||||
Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
|
||||
Eudyptes;chrysocome;Viellot;1816;Southern Rockhopper
|
||||
Torvaldis;linux;Ewing,L;1996;Tux
|
||||
```
|
||||
|
||||
对于这组示例数据,你可以用 `--field-separator` (在 BSD 和 Mac 用 `-t`,在 GNU 上也可以用简写 `-t` )设置分隔符为分号(因为该示例数据中是用分号而不是逗号,理论上分隔符可以是任意字符),用 `--key`(在 BSD 和 Mac 上用 `-k`,在 GNU 上也可以用简写 `-k`)选项指定哪个字段被排序。例如,对每行第二个字段进行排序(计数以 1 开头而不是 0):
|
||||
|
||||
```
|
||||
sort --field-separator=";" --key=2
|
||||
Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
|
||||
Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
|
||||
Spheniscus;demersus;Brisson;1760;African
|
||||
Aptenodytes;forsteri;Miller,JF;1778;Emperor
|
||||
Torvaldis;linux;Ewing,L;1996;Tux
|
||||
Eudyptula;minor;Bonaparte;1867;Little Blue
|
||||
Pygoscelis;papua;Wagler;1832;Gentoo
|
||||
```
|
||||
|
||||
结果有点不容易读,但是 Unix 以构造命令的管道方式而闻名,所以你可以使用 `column` 命令美化输出结果。使用 GNU `column`:
|
||||
|
||||
```
|
||||
$ sort --field-separator=";" \
|
||||
\--key=2 penguins.list | column --table --separator ";"
|
||||
Megadyptes antipodes Milne-Edwards 1880 Yellow-eyed
|
||||
Eudyptes chrysocome Viellot 1816 Southern Rockhopper
|
||||
Spheniscus demersus Brisson 1760 African
|
||||
Aptenodytes forsteri Miller,JF 1778 Emperor
|
||||
Torvaldis linux Ewing,L 1996 Tux
|
||||
Eudyptula minor Bonaparte 1867 Little Blue
|
||||
Pygoscelis papua Wagler 1832 Gentoo
|
||||
```
|
||||
|
||||
对于初学者可能有点不好理解(但是写起来简单),BSD 和 Mac 上的命令选项:
|
||||
|
||||
```
|
||||
$ sort -t ";" \
|
||||
-k2 penguins.list | column -t -s ";"
|
||||
Megadyptes antipodes Milne-Edwards 1880 Yellow-eyed
|
||||
Eudyptes chrysocome Viellot 1816 Southern Rockhopper
|
||||
Spheniscus demersus Brisson 1760 African
|
||||
Aptenodytes forsteri Miller,JF 1778 Emperor
|
||||
Torvaldis linux Ewing,L 1996 Tux
|
||||
Eudyptula minor Bonaparte 1867 Little Blue
|
||||
Pygoscelis papua Wagler 1832 Gentoo
|
||||
```
|
||||
|
||||
当然 `-k` 不一定非要设为 `2`。任意存在的字段都可以被设为排序的键。
|
||||
|
||||
### 逆序排列
|
||||
|
||||
你可以用 `--reverse`(BSD/Mac 上用 `-r`,GNU 上也可以用简写 `-r`)选项来颠倒已经排好序的列表。
|
||||
|
||||
```
|
||||
$ sort --reverse alphabet.list
|
||||
z
|
||||
y
|
||||
x
|
||||
w
|
||||
[...]
|
||||
```
|
||||
|
||||
你也可以把输出结果通过管道传给命令 [tac][4] 来实现相同的效果。
|
||||
|
||||
### 按月排序(仅 GNU 支持)
|
||||
|
||||
理想情况下,所有人都按照 ISO 8601 标准来写日期:年、月、日。这是一种合乎逻辑的指定精确日期的方法,也可以很容易地被计算机理解。也有很多情况下,人类用其他的方式标注日期,包括用很名字随意的月份。
|
||||
|
||||
幸运的是,GNU `sort` 命令能识别这种写法,并可以按月份的名称正确排序。使用 `--month-sort`(`-M`)选项:
|
||||
|
||||
```
|
||||
$ cat month.list
|
||||
November
|
||||
October
|
||||
September
|
||||
April
|
||||
[...]
|
||||
$ sort --month-sort month.list
|
||||
January
|
||||
February
|
||||
March
|
||||
April
|
||||
May
|
||||
[...]
|
||||
November
|
||||
December
|
||||
```
|
||||
|
||||
月份的全称和简写都可以被识别。
|
||||
|
||||
### 人类可读的数字排序(仅 GNU 支持)
|
||||
|
||||
另一个人类和计算机的常见混淆点是数字的组合。例如,人类通常把 “1024 kilobytes” 写成 “1KB”,因为人类解析 “1 KB” 比 “1024” 要容易且更快(数字越大,这种差异越明显)。对于计算机来说,一个 9 KB 的字符串要比诸如 1 MB 的字符串大(尽管 9 KB 是 1 MB 很小一部分)。GNU `sort` 命令提供了`--human-numeric-sort`(`-h`)选项来帮助正确解析这些值。
|
||||
|
||||
```
|
||||
$ cat sizes.list
|
||||
2M
|
||||
12MB
|
||||
1k
|
||||
9k
|
||||
900
|
||||
7000
|
||||
$ sort --human-numeric-sort
|
||||
900
|
||||
7000
|
||||
1k
|
||||
9k
|
||||
2M
|
||||
12MB
|
||||
```
|
||||
|
||||
有一些情况例外。例如,“16000 bytes” 比 “1 KB” 大,但是 `sort` 识别不了。
|
||||
|
||||
```
|
||||
$ cat sizes0.list
|
||||
2M
|
||||
12MB
|
||||
16000
|
||||
1k
|
||||
$ sort -h sizes0.list
|
||||
16000
|
||||
1k
|
||||
2M
|
||||
12MB
|
||||
```
|
||||
|
||||
逻辑上来说,这个示例中 16000 应该写成 16 KB,所以也不应该全部归咎于GNU `sort`。只要你确保数字的一致性,`--human-numeric-sort` 可以用一种计算机友好的方式解析成人类可读的数字。
|
||||
|
||||
### 随机排序(仅 GNU 支持)
|
||||
|
||||
有时候工具也提供了一些与设计初衷相悖的选项。某种程度上说,`sort` 命令提供对一个文件进行随机排序的能力没有任何意义。这个命令的工作流让这个特性变得很方便。你*可以*用其他的命令,像 [shuf][5] ,或者你可以用现在的命令添加一个选项。不管你认为它是一个臃肿的还是极具创造力的用户体验设计,GNU `sort` 命令提供了对文件进行随机排序的功能。
|
||||
|
||||
最纯粹的随机排序格式选项是 `--random-sort` 或 `-R`(不要跟 `-r` 混淆,`-r` 是 `--reverse` 的简写)。
|
||||
|
||||
```
|
||||
$ sort --random-sort alphabet.list
|
||||
d
|
||||
m
|
||||
p
|
||||
a
|
||||
[...]
|
||||
```
|
||||
|
||||
每次对文件运行随机排序都会有不同的结果。
|
||||
|
||||
### 结语
|
||||
|
||||
GNU 和 BSD 的 `sort` 命令还有很多功能,所以花点时间去了解这些选项。你会惊异于 `sort` 的灵活性,尤其是当它和其他的 Unix 工具一起使用时。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/get-sorted-sort
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[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/code_computer_laptop_hack_work.png?itok=aSpcWkcl "Coding on a computer"
|
||||
[2]: https://en.wikipedia.org/wiki/Sort_(Unix)
|
||||
[3]: https://en.wikipedia.org/wiki/POSIX
|
||||
[4]: https://opensource.com/article/19/9/tac-command
|
||||
[5]: https://www.gnu.org/software/coreutils/manual/html_node/shuf-invocation.html
|
153
published/201912/20191028 6 signs you might be a Linux user.md
Normal file
153
published/201912/20191028 6 signs you might be a Linux user.md
Normal file
@ -0,0 +1,153 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11635-1.html)
|
||||
[#]: subject: (6 signs you might be a Linux user)
|
||||
[#]: via: (https://opensource.com/article/19/10/signs-linux-user)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Linux 资深用户的 6 大特征
|
||||
======
|
||||
|
||||
> 如果你是 Linux 资深用户,则可能会有这些共同倾向。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/02/093348ek4jcyvj4wahytwq.jpg)
|
||||
|
||||
Linux 用户千差万别,但是我们许多人都有一些相同的习惯。你可能没有本文列出的任何特征,而且如果你是个 Linux 新用户,你可能还不能理解这些特征……
|
||||
|
||||
下面是你可能是 Linux 用户的六个特征。
|
||||
|
||||
### 1、理所当然,纪元始于 1970 年 1 月 1 日
|
||||
|
||||
关于 Unix 计算机时钟为何在重置时总是将其设置回 1970-01-01 的传闻有很多。但有点令人感到乏味的事实是,Unix “纪元”是用于同步的通用且简单的参考点。例如,万圣节在儒略历中是今年的 304 日,但我们通常将该节日称为 “31 号”。我们知道指的是哪个月的 31 号,因为我们有个共同的参考点:我们知道万圣节在 10 月庆祝,而 10 月是一年中的第十个月,并且我们知道前面每一个月包含多少天。没有这些值,虽然我们可以使用传统的计时方法(如月相)来跟踪特殊的季节性事件,但是计算机显然不具备这种能力。
|
||||
|
||||
计算机需要确定且明确定义的值,因此将值 `1970-01-01T00:00:00Z` 选择为 Unix 纪元的开始。每当 [POSIX][2] 计算机的时间不准确时,诸如网络时间协议(NTP)之类的服务就可以向其提供自 `1970-01-01T00:00:00Z` 以来的秒数,计算机可以将其转换为人类易于识别的日期。
|
||||
|
||||
日期和时间是在计算中要追踪的著名的复杂事物,主要是因为几乎所有标准都有例外。一个月并不总是有 30 天,一年也不总是有 365 天,甚至每年有多少秒钟也往往会有所不同。如果你正在寻找一个有趣而令人沮丧的编程练习,那么请尝试编程一个可靠的日历应用程序!
|
||||
|
||||
### 2、输入超过两个字母你就会觉得麻烦
|
||||
|
||||
众所周知,最常见的 Unix 命令都超简短。除了 `cd`、`ls` 和 `mv` 之类的命令外,还有一个命令简直不能再短了:`w`(它根据 `/var/run/utmp` 文件显示当前谁登录了)。
|
||||
|
||||
一方面,极短的命令似乎很不直观。新用户可能不会猜测到键入 `ls` 会<ruby>列出<rt>list</rt></ruby>目录。但是,一旦学习命令,它们肯定是越短越好。如果你整天都在终端上度过,那么你键入的击键次数越少就意味着你可以有更多的时间来完成工作。
|
||||
|
||||
幸运的是,单字母命令并不太多,因此你可以使用大多数字母作为别名。例如,我经常使用 Emacs,以至于我觉得 `emacs` 的输入时间太长,因此通过将下面这行添加到 `.bashrc` 文件中,将其别名为 `e`:
|
||||
|
||||
```
|
||||
alias e='emacs'
|
||||
```
|
||||
|
||||
你也可以临时为命令添加别名。例如,如果你在解决网络问题时发现自己反复运行 [firewall-cmd][3],则可以为当前会话创建别名:
|
||||
|
||||
```
|
||||
$ alias f='firewall-cmd'
|
||||
$ f
|
||||
usage: see firewall-cmd man page
|
||||
No option specified.
|
||||
```
|
||||
|
||||
只要你打开着终端,你的别名就会一直存在。当终端一旦关闭,它便会被遗忘。
|
||||
|
||||
### 3、做任何事都不应该单击两次以上
|
||||
|
||||
Linux 用户喜欢效率。尽管并非每个 Linux 用户都总是急于完成工作,但 Linux 桌面中有一些旨在减少完成任务所需的操作数量的惯例。这里有些例子。
|
||||
|
||||
* 在 KDE 文件管理器 Dolphin 中,单击即可打开文件或目录。假定如果要选择一个文件,则可以单击并拖动,也可以 `Ctrl + 点击`。这可能会使习惯于双击所有内容的用户感到困惑,但是一旦你尝试了单击操作,通常就无法返回费力的双击操作。
|
||||
* 在大多数 Linux 桌面上,单击鼠标中键可粘贴剪贴板的最新内容。
|
||||
* 在许多 Linux 桌面上,可以通过按 `Alt`、`Ctrl` 或 `Shift` 键来修改拖动动作。例如,`Alt + 拖动` 在 KDE 中移动窗口,而 GNOME 中的 `Ctrl + 拖动` 会复制文件而不是移动。
|
||||
|
||||
### 4、任何操作你都不会执行三次以上,因为第三次时你已经将它自动化了
|
||||
|
||||
请原谅我有点夸张,但是许多 Linux 用户期望他们的计算机比他们更努力地工作。虽然学习如何自动执行常见任务需要花费时间,但在 Linux 上它往往比在其它平台上更容易,因为 Linux 终端和 Linux 操作系统是如此紧密地集成在一起。最容易自动化的是你在终端中已经执行的操作,因为命令只是你在解释器中键入的字符串,而该解释器(终端)不会在乎你是手动键入字符串还是将其指向一个脚本。
|
||||
|
||||
例如,如果你发现自己经常将一组文件从一个位置移动到另一个位置,则或许可以将相同的指令序列用作一个脚本,你可以使用单个命令来触发该脚本。假设你每天早上手动执行此操作:
|
||||
|
||||
```
|
||||
$ cd Documents
|
||||
$ trash reports-latest.txt
|
||||
$ wget myserver.local/reports/daily/report-latest.txt
|
||||
$ cp report-latest.txt reports_daily/2019-31-10.log
|
||||
```
|
||||
|
||||
这是一个简单的序列,但是每天重复一次并不是消磨时间的最有效方法。做一点点抽象,你可以使用一个简单的脚本将其自动化:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
trash $HOME/Documents/reports-latest.txt
|
||||
|
||||
wget myserver.local/reports/daily/report-latest.txt \
|
||||
-P $HOME/Documents/udpates_daily/`date --iso-8601`.log
|
||||
|
||||
cp $HOME/Documents/udpates_daily/`date --iso-8601`.log \
|
||||
$HOME/Documents/reports-latest.txt
|
||||
```
|
||||
|
||||
你可以把你的脚本叫做 `get-reports.sh` 并在每天早晨手动启动它,或者甚至可以将其输入到 crontab 中,以便计算机可以执行此任务而无需你进行任何干预。
|
||||
|
||||
对于新用户来说,这可能会有点困扰,因为什么和什么是一体的并不总是很明显。例如,如果你经常发现自己打开图像并将其按比例缩小 50%,那么你可能习惯于执行以下操作:
|
||||
|
||||
1. 打开你的照片查看器或编辑器
|
||||
2. 缩放图像
|
||||
3. 将图像导出为修改后的文件
|
||||
4. 关闭应用程序
|
||||
|
||||
如果你一天要做几次,你可能会对这种重复感到厌倦。但是,由于你是在图形用户界面(GUI)中执行这些操作的,因此你需要知道如何对 GUI 编写脚本以使其自动化。某些应用程序,例如 [GIMP][4],具有丰富的脚本接口,但是其过程显然不同于仅修改一堆命令并将其存储到文件中那么简单。
|
||||
|
||||
再说一次,有时在命令行中有与你在 GUI 中所做的等效的操作。将文档从一种文本格式转换为另一种格式可以使用 [Pandoc][5],处理图像可以使用 [Image Magick][6],音乐和视频也可以通过命令行进行编辑和转换,等等。最大的问题是你需要知道要查找什么,通常是学习新的(有时是复杂的)命令。但是,在终端中按比例缩小图像比在 GUI 中显然更简单:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
convert "${1}" -scale 50% `basename "${1}" .jpg`_50.jpg
|
||||
```
|
||||
|
||||
这些麻烦、重复的任务值得研究。你永远不知道你的工作让计算机做起来是有多么的简单和快捷!
|
||||
|
||||
### 5、发行版之间跳来跳去
|
||||
|
||||
我在家里是一个热情的 Slackware 用户,而在工作时是一个 RHEL 用户。实际上,这不是事实,我现在在工作时是 Fedora 用户。除了有时候我使用 CentOS,偶尔我还会运行 [Mageia][7]。
|
||||
|
||||
![Debian on a PowerPC64 box, image CC BY SA Claudio Miranda][8]
|
||||
|
||||
*运行在 PowerPC64 机器上的 Debian*
|
||||
|
||||
发行版好不好无关紧要,成为 Linux 用户的极致乐趣之一是可以自由决定运行哪个发行版。乍一看,它们基本相同,令人耳目一新。但是根据你的心情,你可能更喜欢 CentOS 的稳定性而不是 Fedora 的不断更新,或者你可能有一天会真正享受 Mageia 的集中控制中心,然后又对原始的 [Debian][9] 配置文件进行模块化乐在其中,而有时你又会完全转向其他操作系统。
|
||||
|
||||
![OpenBSD, image CC BY SA Claudio Miranda][10]
|
||||
|
||||
*OpenBSD,不是 Linux 发行版*
|
||||
|
||||
关键是,Linux 发行版是激情项目,成为其他人的开源激情的一部分很有趣。
|
||||
|
||||
### 6、你对开源充满热情
|
||||
|
||||
无论你的经验如何,如果你是 Linux 用户,那么你无疑会对开源充满热情。无论你是每天通过[共创艺术品] [11]还是代码来表达你的热情,还是将其升华到只在自由而自在的环境中完成工作,你都生活并构筑于开源之上。因为有了千千万万个你,所以有了开源社区,社区因你而变得更加丰富。
|
||||
|
||||
有太多的东西我没有提到。作为 Linux 用户,还有什么可以出卖你的身份?让我们在评论中知道!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/signs-linux-user
|
||||
|
||||
作者:[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/tux_linux_penguin_code_binary.jpg?itok=TxGxW0KY (Tux with binary code background)
|
||||
[2]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
|
||||
[3]: https://opensource.com/article/19/7/make-linux-stronger-firewalls
|
||||
[4]: https://www.gimp.org/
|
||||
[5]: https://opensource.com/article/19/5/convert-markdown-to-word-pandoc
|
||||
[6]: https://opensource.com/article/17/8/imagemagick
|
||||
[7]: http://mageia.org
|
||||
[8]: https://opensource.com/sites/default/files/uploads/debian.png (Debian on a PowerPC64 box)
|
||||
[9]: http://debian.org
|
||||
[10]: https://opensource.com/sites/default/files/uploads/openbsd.jpg (OpenBSD)
|
||||
[11]: http://freesvg.org
|
@ -0,0 +1,222 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11666-1.html)
|
||||
[#]: subject: (How to remove duplicate lines from files with awk)
|
||||
[#]: via: (https://opensource.com/article/19/10/remove-duplicate-lines-files-awk)
|
||||
[#]: author: (Lazarus Lazaridis https://opensource.com/users/iridakos)
|
||||
|
||||
怎样使用 awk 删掉文件中重复的行
|
||||
======
|
||||
|
||||
> 学习怎样使用 awk 的 `!visited[$0]++` 在不重新排序或改变原排列顺序的前提下删掉重复的行。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/12/124322vwe3tq3wlw33tw1f.jpg)
|
||||
|
||||
假设你有一个文本文件,你需要删掉所有重复的行。
|
||||
|
||||
### TL;DR
|
||||
|
||||
*要保持原来的排列顺序*删掉重复行,使用:
|
||||
|
||||
```
|
||||
awk '!visited[$0]++' your_file > deduplicated_file
|
||||
```
|
||||
|
||||
### 工作原理
|
||||
|
||||
这个脚本维护一个关联数组,索引(键)为文件中去重后的行,每个索引对应的值为该行出现的次数。对于文件的每一行,如果这行(之前)出现的次数为 0,则值加 1,并打印这行,否则值加 1,不打印这行。
|
||||
|
||||
我之前不熟悉 `awk`,我想弄清楚这么短小的一个脚本是怎么实现的。我调研了下,下面是调研心得:
|
||||
|
||||
* 这个 awk “脚本” `!visited[$0]++` 对输入文件的*每一行*都执行。
|
||||
* `visited[]` 是一个[关联数组][2](又名[映射][3])类型的变量。`awk` 会在第一次执行时初始化它,因此我们不需要初始化。
|
||||
* `$0` 变量的值是当前正在被处理的行的内容。
|
||||
* `visited[$0]` 通过与 `$0`(正在被处理的行)相等的键来访问该映射中的值,即出现次数(我们在下面设置的)。
|
||||
* `!` 对表示出现次数的值取反:
|
||||
* 在 `awk` 中,[任意非零的数或任意非空的字符串的值是 `true`][4]。
|
||||
* [变量默认的初始值为空字符串][5],如果被转换为数字,则为 0。
|
||||
* 也就是说:
|
||||
* 如果 `visited[$0]` 的值是一个比 0 大的数,取反后被解析成 `false`。
|
||||
* 如果 `visited[$0]` 的值为等于 0 的数字或空字符串,取反后被解析成 `true` 。
|
||||
* `++` 表示变量 `visited[$0]` 的值加 1。
|
||||
* 如果该值为空,`awk` 自动把它转换为 `0`(数字) 后加 1。
|
||||
* 注意:加 1 操作是在我们取到了变量的值之后执行的。
|
||||
|
||||
总的来说,整个表达式的意思是:
|
||||
|
||||
* `true`:如果表示出现次数为 0 或空字符串
|
||||
* `false`:如果出现的次数大于 0
|
||||
|
||||
`awk` 由 [模式或表达式和一个与之关联的动作][6] 组成:
|
||||
|
||||
```
|
||||
<模式/表达式> { <动作> }
|
||||
```
|
||||
|
||||
如果匹配到了模式,就会执行后面的动作。如果省略动作,`awk` 默认会打印(`print`)输入。
|
||||
|
||||
> 省略动作等价于 `{print $0}`。
|
||||
|
||||
我们的脚本由一个 `awk` 表达式语句组成,省略了动作。因此这样写:
|
||||
|
||||
```
|
||||
awk '!visited[$0]++' your_file > deduplicated_file
|
||||
```
|
||||
|
||||
等于这样写:
|
||||
|
||||
```
|
||||
awk '!visited[$0]++ { print $0 }' your_file > deduplicated_file
|
||||
```
|
||||
|
||||
对于文件的每一行,如果表达式匹配到了,这行内容被打印到输出。否则,不执行动作,不打印任何东西。
|
||||
|
||||
### 为什么不用 uniq 命令?
|
||||
|
||||
`uniq` 命令仅能对相邻的行去重。这是一个示例:
|
||||
|
||||
```
|
||||
$ cat test.txt
|
||||
A
|
||||
A
|
||||
A
|
||||
B
|
||||
B
|
||||
B
|
||||
A
|
||||
A
|
||||
C
|
||||
C
|
||||
C
|
||||
B
|
||||
B
|
||||
A
|
||||
$ uniq < test.txt
|
||||
A
|
||||
B
|
||||
A
|
||||
C
|
||||
B
|
||||
A
|
||||
```
|
||||
|
||||
### 其他方法
|
||||
|
||||
#### 使用 sort 命令
|
||||
|
||||
我们也可以用下面的 [sort][7] 命令来去除重复的行,但是*原来的行顺序没有被保留*。
|
||||
|
||||
|
||||
```
|
||||
sort -u your_file > sorted_deduplicated_file
|
||||
```
|
||||
|
||||
#### 使用 cat + sort + cut
|
||||
|
||||
上面的方法会产出一个去重的文件,各行是基于内容进行排序的。[通过管道连接命令][8]可以解决这个问题。
|
||||
|
||||
|
||||
```
|
||||
cat -n your_file | sort -uk2 | sort -nk1 | cut -f2-
|
||||
```
|
||||
|
||||
**工作原理**
|
||||
|
||||
假设我们有下面一个文件:
|
||||
|
||||
```
|
||||
abc
|
||||
ghi
|
||||
abc
|
||||
def
|
||||
xyz
|
||||
def
|
||||
ghi
|
||||
klm
|
||||
```
|
||||
|
||||
`cat -n test.txt` 在每行前面显示序号:
|
||||
|
||||
```
|
||||
1 abc
|
||||
2 ghi
|
||||
3 abc
|
||||
4 def
|
||||
5 xyz
|
||||
6 def
|
||||
7 ghi
|
||||
8 klm
|
||||
```
|
||||
|
||||
`sort -uk2` 基于第二列(`k2` 选项)进行排序,对于第二列相同的值只保留一次(`u` 选项):
|
||||
|
||||
```
|
||||
1 abc
|
||||
4 def
|
||||
2 ghi
|
||||
8 klm
|
||||
5 xyz
|
||||
```
|
||||
|
||||
`sort -nk1` 基于第一列排序(`k1` 选项),把列的值作为数字来处理(`-n` 选项):
|
||||
|
||||
```
|
||||
1 abc
|
||||
2 ghi
|
||||
4 def
|
||||
5 xyz
|
||||
8 klm
|
||||
```
|
||||
|
||||
最后,`cut -f2-` 从第二列开始打印每一行,直到最后的内容(`-f2-` 选项:留意 `-` 后缀,它表示这行后面的内容都包含在内)。
|
||||
|
||||
```
|
||||
abc
|
||||
ghi
|
||||
def
|
||||
xyz
|
||||
klm
|
||||
```
|
||||
|
||||
### 参考
|
||||
|
||||
* [GNU awk 用户手册][9]
|
||||
* [awk 中的数组][2]
|
||||
* [Awk — 真值][4]
|
||||
* [Awk 表达式][5]
|
||||
* [Unix 怎么删除文件中重复的行?][10]
|
||||
* [不用排序去掉重复的行(去重)][11]
|
||||
* ['!a[$0]++' 工作原理][12]
|
||||
|
||||
以上为全文。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/remove-duplicate-lines-files-awk
|
||||
|
||||
作者:[Lazarus Lazaridis][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/iridakos
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_laptop_hack_work.png?itok=aSpcWkcl (Coding on a computer)
|
||||
[2]: http://kirste.userpage.fu-berlin.de/chemnet/use/info/gawk/gawk_12.html
|
||||
[3]: https://en.wikipedia.org/wiki/Associative_array
|
||||
[4]: https://www.gnu.org/software/gawk/manual/html_node/Truth-Values.html
|
||||
[5]: https://ftp.gnu.org/old-gnu/Manuals/gawk-3.0.3/html_chapter/gawk_8.html
|
||||
[6]: http://kirste.userpage.fu-berlin.de/chemnet/use/info/gawk/gawk_9.html
|
||||
[7]: http://man7.org/linux/man-pages/man1/sort.1.html
|
||||
[8]: https://stackoverflow.com/a/20639730/2292448
|
||||
[9]: https://www.gnu.org/software/gawk/manual/html_node/
|
||||
[10]: https://stackoverflow.com/questions/1444406/how-can-i-delete-duplicate-lines-in-a-file-in-unix
|
||||
[11]: https://stackoverflow.com/questions/11532157/remove-duplicate-lines-without-sorting
|
||||
[12]: https://unix.stackexchange.com/questions/159695/how-does-awk-a0-work/159734#159734
|
||||
[13]: https://opensource.com/sites/default/files/uploads/duplicate-cat.jpg (Duplicate cat)
|
||||
[14]: https://iridakos.com/about/
|
||||
[15]: http://creativecommons.org/licenses/by-nc/4.0/
|
@ -0,0 +1,242 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11684-1.html)
|
||||
[#]: subject: (Awk one-liners and scripts to help you sort text files)
|
||||
[#]: via: (https://opensource.com/article/19/11/how-sort-awk)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
帮助你排序文本文件的 Awk 命令行或脚本
|
||||
======
|
||||
|
||||
> Awk 是一个强大的工具,可以执行某些可能由其它常见实用程序(包括 `sort`)来完成的任务。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/17/095222q7m5da4h8facvmtv.jpg)
|
||||
|
||||
Awk 是个普遍存在的 Unix 命令,用于扫描和处理包含可预测模式的文本。但是,由于它具有函数功能,因此也可以合理地称之为编程语言。
|
||||
|
||||
令人困惑的是,有不止一个 awk。(或者,如果你认为只有一个,那么其它几个就是克隆。)有 `awk`(由Aho、Weinberger 和 Kernighan 编写的原始程序),然后有 `nawk` 、`mawk` 和 GNU 版本的 `gawk`。GNU 版本的 awk 是该实用程序的一个高度可移植的自由软件版本,具有几个独特的功能,因此本文是关于 GNU awk 的。
|
||||
|
||||
虽然它的正式名称是 `gawk`,但在 GNU+Linux 系统上,它的别名是 `awk`,并用作该命令的默认版本。 在其他没有带有 GNU awk 的系统上,你必须先安装它并将其称为 `gawk`,而不是 `awk`。本文互换使用术语 `awk` 和 `gawk`。
|
||||
|
||||
`awk` 既是命令语言又是编程语言,这使其成为一个强大的工具,可以处理原本留给 `sort`、`cut`、`uniq` 和其他常见实用程序的任务。幸运的是,开源中有很多冗余空间,因此,如果你面临是否使用 `awk` 的问题,答案可能是肯定的“随便”。
|
||||
|
||||
`awk` 的灵活之美在于,如果你已经确定使用 `awk` 来完成一项任务,那么无论接下来发生什么,你都可以继续使用 `awk`。这包括对数据排序而不是按交付给你的顺序的永恒需求。
|
||||
|
||||
### 样本数据集
|
||||
|
||||
在探索 `awk` 的排序方法之前,请生成要使用的样本数据集。保持简单,这样你就不会为极端情况和意想不到的复杂性所困扰。这是本文使用的样本集:
|
||||
|
||||
```
|
||||
Aptenodytes;forsteri;Miller,JF;1778;Emperor
|
||||
Pygoscelis;papua;Wagler;1832;Gentoo
|
||||
Eudyptula;minor;Bonaparte;1867;Little Blue
|
||||
Spheniscus;demersus;Brisson;1760;African
|
||||
Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
|
||||
Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
|
||||
Torvaldis;linux;Ewing,L;1996;Tux
|
||||
```
|
||||
|
||||
这是一个很小的数据集,但它提供了多种数据类型:
|
||||
|
||||
* 属名和种名,彼此相关但又是分开的
|
||||
* 姓,有时是以逗号开头的首字母缩写
|
||||
* 代表日期的整数
|
||||
* 任意术语
|
||||
* 所有字段均以分号分隔
|
||||
|
||||
根据你的教育背景,你可能会认为这是二维数组或表格,或者只是行分隔的数据集合。你如何看待它只是你的问题,而 `awk` 只认识文本。由你决定告诉 `awk` 你想如何解析它。
|
||||
|
||||
### 只想排序
|
||||
|
||||
如果你只想按特定的可定义字段(例如电子表格中的“单元格”)对文本数据集进行排序,则可以使用 [sort 命令][2]。
|
||||
|
||||
### 字段和记录
|
||||
|
||||
无论输入的格式如何,都必须在其中找到模式才可以专注于对你重要的数据部分。在此示例中,数据由两个因素定界:行和字段。每行都代表一个新的*记录*,就如你在电子表格或数据库转储中看到的一样。在每一行中,都有用分号(`;`)分隔的不同的*字段*(将其视为电子表格中的单元格)。
|
||||
|
||||
`awk` 一次只处理一条记录,因此,当你在构造发给 `awk` 的这指令时,你可以只关注一行记录。写下你想对一行数据执行的操作,然后在下一行进行测试(无论是心理上还是用 `awk` 进行测试),然后再进行其它的一些测试。最后,你要对你的 `awk` 脚本要处理的数据做好假设,以便可以按你要的数据结构提供给你数据。
|
||||
|
||||
在这个例子中,很容易看到每个字段都用分号隔开。为简单起见,假设你要按每行的第一字段对列表进行排序。
|
||||
|
||||
在进行排序之前,你必须能够让 `awk` 只关注在每行的第一个字段上,因此这是第一步。终端中 awk 命令的语法为 `awk`,后跟相关选项,最后是要处理的数据文件。
|
||||
|
||||
```
|
||||
$ awk --field-separator=";" '{print $1;}' penguins.list
|
||||
Aptenodytes
|
||||
Pygoscelis
|
||||
Eudyptula
|
||||
Spheniscus
|
||||
Megadyptes
|
||||
Eudyptes
|
||||
Torvaldis
|
||||
```
|
||||
|
||||
因为字段分隔符是对 Bash shell 具有特殊含义的字符,所以必须将分号括在引号中或在其前面加上反斜杠。此命令仅用于证明你可以专注于特定字段。你可以使用另一个字段的编号尝试相同的命令,以查看数据的另一个“列”的内容:
|
||||
|
||||
```
|
||||
$ awk --field-separator=";" '{print $3;}' penguins.list
|
||||
Miller,JF
|
||||
Wagler
|
||||
Bonaparte
|
||||
Brisson
|
||||
Milne-Edwards
|
||||
Viellot
|
||||
Ewing,L
|
||||
```
|
||||
|
||||
我们尚未进行任何排序,但这是良好的基础。
|
||||
|
||||
### 脚本编程
|
||||
|
||||
`awk` 不仅仅是命令,它是一种具有索引、数组和函数的编程语言。这很重要,因为这意味着你可以获取要排序的字段列表,将列表存储在内存中,进行处理,然后打印结果数据。对于诸如此类的一系列复杂操作,在文本文件中进行操作会更容易,因此请创建一个名为 `sort.awk` 的新文件并输入以下文本:
|
||||
|
||||
```
|
||||
#!/bin/gawk -f
|
||||
|
||||
BEGIN {
|
||||
FS=";";
|
||||
}
|
||||
```
|
||||
|
||||
这会将该文件建立为 `awk` 脚本,该脚本中包含执行的行。
|
||||
|
||||
`BEGIN` 语句是 `awk` 提供的特殊设置功能,用于只需要执行一次的任务。定义内置变量 `FS`,它代表<ruby>字段分隔符<rt>field separator</rt></ruby>,并且与你在 `awk` 命令中使用 `--field-separator` 设置的值相同,它只需执行一次,因此它包含在 `BEGIN` 语句中。
|
||||
|
||||
#### awk 中的数组
|
||||
|
||||
你已经知道如何通过使用 `$` 符号和字段编号来收集特定字段的值,但是在这种情况下,你需要将其存储在数组中而不是将其打印到终端。这是通过 `awk` 数组完成的。`awk` 数组的重要之处在于它包含键和值。 想象一下有关本文的内容;它看起来像这样:`author:"seth",title:"How to sort with awk",length:1200`。诸如作者、标题和长度之类的元素是键,跟着的内容为值。
|
||||
|
||||
在排序的上下文中这样做的好处是,你可以将任何字段分配为键,将任何记录分配为值,然后使用内置的 `awk` 函数 `asorti()`(按索引排序)按键进行排序。现在,随便假设你*只*想按第二个字段排序。
|
||||
|
||||
*没有*被特殊关键字 `BEGIN` 或 `END` 引起来的 `awk` 语句是在每个记录都要执行的循环。这是脚本的一部分,该脚本扫描数据中的模式并进行相应的处理。每次 `awk` 将注意力转移到一条记录上时,都会执行 `{}` 中的语句(除非以 `BEGIN` 或 `END` 开头)。
|
||||
|
||||
要将键和值添加到数组,请创建一个包含数组的变量(在本示例脚本中,我将其称为 `ARRAY`,虽然不是很原汁原味,但很清楚),然后在方括号中分配给它键,用等号(`=`)连接值。
|
||||
|
||||
```
|
||||
{ # dump each field into an array
|
||||
ARRAY[$2] = $R;
|
||||
}
|
||||
```
|
||||
|
||||
在此语句中,第二个字段的内容(`$2`)用作关键字,而当前记录(`$R`)用作值。
|
||||
|
||||
### asorti() 函数
|
||||
|
||||
除了数组之外,`awk` 还具有一些基本函数,你可以将它们用作常见任务的快速简便的解决方案。GNU awk中引入的函数之一 `asorti()` 提供了按键(*索引*)或值对数组进行排序的功能。
|
||||
|
||||
你只能在对数组进行填充后对其进行排序,这意味着此操作不能对每个新记录都触发,而只能在脚本的最后阶段进行。为此,`awk` 提供了特殊的 `END` 关键字。与 `BEGIN` 相反,`END` 语句仅在扫描了所有记录之后才触发一次。
|
||||
|
||||
将这些添加到你的脚本:
|
||||
|
||||
```
|
||||
END {
|
||||
asorti(ARRAY,SARRAY);
|
||||
# get length
|
||||
j = length(SARRAY);
|
||||
|
||||
for (i = 1; i <= j; i++) {
|
||||
printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`asorti()` 函数获取 `ARRAY` 的内容,按索引对其进行排序,然后将结果放入名为 `SARRAY` 的新数组(我在本文中发明的任意名称,表示“排序的 ARRAY”)。
|
||||
|
||||
接下来,将变量 `j`(另一个任意名称)分配给 `length()` 函数的结果,该函数计算 `SARRAY` 中的项数。
|
||||
|
||||
最后,使用 `for` 循环使用 `printf()` 函数遍历 `SARRAY` 中的每一项,以打印每个键,然后在 `ARRAY` 中打印该键的相应值。
|
||||
|
||||
### 运行该脚本
|
||||
|
||||
要运行你的 `awk` 脚本,先使其可执行:
|
||||
|
||||
```
|
||||
$ chmod +x sorter.awk
|
||||
```
|
||||
|
||||
然后针对 `penguin.list` 示例数据运行它:
|
||||
|
||||
```
|
||||
$ ./sorter.awk penguins.list
|
||||
antipodes Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
|
||||
chrysocome Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
|
||||
demersus Spheniscus;demersus;Brisson;1760;African
|
||||
forsteri Aptenodytes;forsteri;Miller,JF;1778;Emperor
|
||||
linux Torvaldis;linux;Ewing,L;1996;Tux
|
||||
minor Eudyptula;minor;Bonaparte;1867;Little Blue
|
||||
papua Pygoscelis;papua;Wagler;1832;Gentoo
|
||||
```
|
||||
|
||||
如你所见,数据按第二个字段排序。
|
||||
|
||||
这有点限制。最好可以在运行时灵活选择要用作排序键的字段,以便可以在任何数据集上使用此脚本并获得有意义的结果。
|
||||
|
||||
### 添加命令选项
|
||||
|
||||
你可以通过在脚本中使用字面值 `var` 将命令变量添加到 `awk` 脚本中。更改脚本,以使迭代子句在创建数组时使用 `var`:
|
||||
|
||||
```
|
||||
{ # dump each field into an array
|
||||
ARRAY[$var] = $R;
|
||||
}
|
||||
```
|
||||
|
||||
尝试运行该脚本,以便在执行脚本时使用 `-v var` 选项将其按第三字段排序:
|
||||
|
||||
```
|
||||
$ ./sorter.awk -v var=3 penguins.list
|
||||
Bonaparte Eudyptula;minor;Bonaparte;1867;Little Blue
|
||||
Brisson Spheniscus;demersus;Brisson;1760;African
|
||||
Ewing,L Torvaldis;linux;Ewing,L;1996;Tux
|
||||
Miller,JF Aptenodytes;forsteri;Miller,JF;1778;Emperor
|
||||
Milne-Edwards Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
|
||||
Viellot Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
|
||||
Wagler Pygoscelis;papua;Wagler;1832;Gentoo
|
||||
```
|
||||
|
||||
### 修正
|
||||
|
||||
本文演示了如何在纯 GNU awk 中对数据进行排序。你可以对脚本进行改进,以便对你有用,花一些时间在`gawk` 的手册页上研究 [awk 函数][3]并自定义脚本以获得更好的输出。
|
||||
|
||||
这是到目前为止的完整脚本:
|
||||
|
||||
```
|
||||
#!/usr/bin/awk -f
|
||||
# GPLv3 appears here
|
||||
# usage: ./sorter.awk -v var=NUM FILE
|
||||
|
||||
BEGIN { FS=";"; }
|
||||
|
||||
{ # dump each field into an array
|
||||
ARRAY[$var] = $R;
|
||||
}
|
||||
|
||||
END {
|
||||
asorti(ARRAY,SARRAY);
|
||||
# get length
|
||||
j = length(SARRAY);
|
||||
|
||||
for (i = 1; i <= j; i++) {
|
||||
printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/how-sort-awk
|
||||
|
||||
作者:[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/metrics_lead-steps-measure.png?itok=DG7rFZPk (Green graph of measurements)
|
||||
[2]: https://opensource.com/article/19/10/get-sorted-sort
|
||||
[3]: https://www.gnu.org/software/gawk/manual/html_node/Built_002din.html#Built_002din
|
@ -0,0 +1,85 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11632-1.html)
|
||||
[#]: subject: (Edit images on Fedora easily with GIMP)
|
||||
[#]: via: (https://fedoramagazine.org/edit-images-on-fedora-easily-with-gimp/)
|
||||
[#]: author: (Mehdi Haghgoo https://fedoramagazine.org/author/powergame/)
|
||||
|
||||
在 Fedora 上使用 GIMP 轻松编辑图像
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
GIMP(GNU Image Manipulation Program 的缩写)是自由开源的图像处理软件。它有很多的功能,从简单的图像编辑,到复杂的滤镜、脚本,甚至是动画,它是流行的商业同类软件的一款很好的替代品。
|
||||
|
||||
继续阅读来学习如何在 Fedora 上安装和使用 GIMP。这篇文章涉及基本的日常图像编辑工作。
|
||||
|
||||
### 安装 GIMP
|
||||
|
||||
GIMP 在官方 Fedora 存储库中可获得。为安装它,运行:
|
||||
|
||||
```
|
||||
sudo dnf install gimp
|
||||
```
|
||||
|
||||
### 单窗口模式
|
||||
|
||||
在你打开应用程序后,它显示带有工具箱和主编辑区的暗色主题窗口。注意,它有两种窗口模式,你可以通过选择“<ruby>窗口<rt>Windows</rt></ruby> -> <ruby>单窗口模式<rt>Single Window Mode</rt></ruby>”在其中切换。通过选中这个选项,用户界面的所有组件将显示在单个窗口中。否则,它们将是分离的。
|
||||
|
||||
### 加载图像
|
||||
|
||||
![][2]
|
||||
|
||||
为加载图像,转到“<ruby>文件<rt>File</rt></ruby> -> <ruby>打开<rt>Open</rt></ruby>”,然后选择你的文件并选择你的图像文件。
|
||||
|
||||
### 重新调整一个图像的大小
|
||||
|
||||
为重新调整图像大小,你可以基于一对参数重新调整大小,包括像素和百分比 —— 在编辑图像时,这两个参数很方便。
|
||||
|
||||
让我们假使我们需要缩小 Fedora 30 背景图像到它当前大小的 75%。为此,选择“<ruby>图像<rt> Image</rt></ruby> -> <ruby>比例<rt>Scale</rt></ruby>”,然后在比例对话框上,在单位下拉列表中选择“<ruby>百分比<rt>percentage</rt></ruby>”。接下来,输入 “75” 作为宽度或高度,然后按 Tab 键。默认情况下,其它尺寸将自动地调整大小,以相应地与更改的尺寸保持纵横比。现在,保存其它选项不变,并按比例。
|
||||
|
||||
![][3]
|
||||
|
||||
该图像缩小到其原始尺寸的 75%。
|
||||
|
||||
### 旋转图像
|
||||
|
||||
旋转是一种变换操作,因此,你可以从主菜单下的“<ruby>图像<rt>Image</rt></ruby> -> <ruby>变换<rt>Transform</rt></ruby>”下找到它,其中有图像旋转 90° 或 180° 的选项。在上述选项下也有垂直或水平翻转图像的选项。
|
||||
|
||||
让我们假使我们需要旋转图像 90°。在应用一次 90° 顺时针旋转和水平翻转后,我们的图像将看起来像这样:
|
||||
|
||||
![Transforming an image with GIMP][4]
|
||||
|
||||
### 添加文本
|
||||
|
||||
添加文本非常简单。只需要从工具箱中选择 “A” 图标,然后,在你的图像上,单击你想要添加文本的位置。如果工具箱不可见,从“<ruby>窗口<rt>Windows</rt></ruby> -> <ruby>新建工具箱<rt>New Toolbox</rt></ruby>”打开它。
|
||||
|
||||
当你编辑文本时,你可能注意到,文本对话框有字体自定义选项,包括字体系列、字体大小等等。
|
||||
|
||||
![Adding text to image in GIMP][5]
|
||||
|
||||
### 保存和导出
|
||||
|
||||
你可以从“<ruby>文件<rt>File</rt></ruby> -> <ruby>保存<rt>Save</rt></ruby>”或通过按 `Ctrl+S` 来将你的编辑保存为一个带有 `.xcf` 扩展名的 GIMP 工程。或者,你可以导出你的图像,例如,以 PNG 或 JPEG 格式。为导出图像,转到“<ruby>文件<rt>File</rt></ruby> -> <ruby>导出为<rt>Export As</rt></ruby>”或按 `Ctrl+Shift+E`,接下来,在你面前将产生一个你可以选择输出图像和名称的对话框。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/edit-images-on-fedora-easily-with-gimp/
|
||||
|
||||
作者:[Mehdi Haghgoo][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://fedoramagazine.org/author/powergame/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/10/gimp-magazine-816x346.jpg
|
||||
[2]: https://fedoramagazine.org/wp-content/uploads/2019/10/Screenshot-from-2019-10-25-11-00-44-300x165.png
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2019/10/Screenshot-from-2019-10-25-11-17-33-300x262.png
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2019/10/Screenshot-from-2019-10-25-11-41-28-300x243.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2019/10/Screenshot-from-2019-10-25-11-47-54-300x237.png
|
||||
|
@ -0,0 +1,345 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (hanwckf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11667-1.html)
|
||||
[#]: subject: (Debugging Software Deployments with strace)
|
||||
[#]: via: (https://theartofmachinery.com/2019/11/14/deployment_debugging_strace.html)
|
||||
[#]: author: (Simon Arneaud https://theartofmachinery.com)
|
||||
|
||||
在软件部署中使用 strace 进行调试
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/12/130413poennny2pbrgy9ot.jpg)
|
||||
|
||||
我的大部分工作都涉及到部署软件系统,这意味着我需要花费很多时间来解决以下问题:
|
||||
|
||||
* 这个软件可以在原开发者的机器上工作,但是为什么不能在我这里运行?
|
||||
* 这个软件昨天可以在我的机器上工作,但是为什么今天就不行?
|
||||
|
||||
这是一种调试的类型,但是与一般的软件调试有所不同。一般的调试通常只关心代码的逻辑,但是在软件部署中的调试关注的是程序的代码和它所在的运行环境之间的相互影响。即便问题的根源是代码的逻辑错误,但软件显然可以在别的机器上运行的事实意味着这类问题与运行环境密切相关。
|
||||
|
||||
所以,在软件部署过程中,我没有使用传统的调试工具(例如 `gdb`),而是选择了其它工具进行调试。我最喜欢的用来解决“为什么这个软件无法在这台机器上运行?”这类问题的工具就是 `strace`。
|
||||
|
||||
### 什么是 strace?
|
||||
|
||||
[strace][1] 是一个用来“追踪系统调用”的工具。它主要是一个 Linux 工具,但是你也可以在其它系统上使用类似的工具(例如 [DTrace][2] 和 [ktrace][3])。
|
||||
|
||||
它的基本用法非常简单。只需要在 `strace` 后面跟上你需要运行的命令,它就会显示出该命令触发的所有系统调用(你可能需要先安装好 `strace`):
|
||||
|
||||
```
|
||||
$ strace echo Hello
|
||||
...Snip lots of stuff...
|
||||
write(1, "Hello\n", 6) = 6
|
||||
close(1) = 0
|
||||
close(2) = 0
|
||||
exit_group(0) = ?
|
||||
+++ exited with 0 +++
|
||||
```
|
||||
|
||||
这些系统调用都是什么?它们就像是操作系统内核提供的 API。很久以前,软件拥有直接访问硬件的权限。如果软件需要在屏幕上显示一些东西,它将会与视频硬件的端口和内存映射寄存器纠缠不清。当多任务操作系统变得流行以后,这就导致了混乱的局面,因为不同的应用程序将“争夺”硬件,并且一个应用程序的错误可能致使其它应用程序崩溃,甚至导致整个系统崩溃。所以 CPU 开始支持多种不同的特权模式(或者称为“保护环”)。它们让操作系统内核在具有完全硬件访问权限的最高特权模式下运行,于此同时,其它在低特权模式下运行的应用程序必须通过向内核发起系统调用才能够与硬件进行交互。
|
||||
|
||||
在二进制级别上,发起系统调用相比简单的函数调用有一些区别,但是大部分程序都使用标准库提供的封装函数。例如,POSIX C 标准库包含一个 `write()` 函数,该函数包含用于进行 `write` 系统调用的所有与硬件体系结构相关的代码。
|
||||
|
||||
![][4]
|
||||
|
||||
简单来说,一个应用程序与其环境(计算机系统)的交互都是通过系统调用来完成的。所以当软件在一台机器上可以工作但是在另一台机器无法工作的时候,追踪系统调用是一个很好的查错方法。具体地说,你可以通过追踪系统调用分析以下典型操作:
|
||||
|
||||
* 控制台输入与输出 (IO)
|
||||
* 网络 IO
|
||||
* 文件系统访问以及文件 IO
|
||||
* 进程/线程生命周期管理
|
||||
* 原始内存管理
|
||||
* 访问特定的设备驱动
|
||||
|
||||
### 什么时候可以使用 strace?
|
||||
|
||||
理论上,`strace` 适用于任何用户空间程序,因为所有的用户空间程序都需要进行系统调用。`strace` 对于已编译的低级程序最有效果,但如果你可以避免运行时环境和解释器带来的大量额外输出,则仍然可以与 Python 等高级语言程序一起使用。
|
||||
|
||||
当软件在一台机器上正常工作,但在另一台机器上却不能正常工作,同时抛出了有关文件、权限或者不能运行某某命令等模糊的错误信息时,`strace` 往往能大显身手。不幸的是,它不能诊断高等级的问题,例如数字证书验证错误等。这些问题通常需要组合使用 `strace`(有时候是 [`ltrace`][5])和其它高级工具(例如使用 `openssl` 命令行工具调试数字证书错误)。
|
||||
|
||||
本文中的示例基于独立的服务器,但是对系统调用的追踪通常也可以在更复杂的部署平台上完成,仅需要找到合适的工具。
|
||||
|
||||
### 一个简单的例子
|
||||
|
||||
假设你正在尝试运行一个叫做 `foo` 的服务器应用程序,但是发生了以下情况:
|
||||
|
||||
```
|
||||
$ foo
|
||||
Error opening configuration file: No such file or directory
|
||||
```
|
||||
|
||||
显然,它没有找到你已经写好的配置文件。之所以会发生这种情况,是因为包管理工具有时候在编译应用程序时指定了自定义的路径,所以你应当遵循特定发行版提供的安装指南。如果错误信息告诉你正确的配置文件应该在什么地方,你就可以在几秒钟内解决这个问题,但如果没有告诉你呢?你该如何找到正确的路径?
|
||||
|
||||
如果你有权访问源代码,则可以通过阅读源代码来解决问题。这是一个好的备用计划,但不是最快的解决方案。你还可以使用类似 `gdb` 的单步调试器来观察程序的行为,但使用专门用于展示程序与系统环境交互作用的工具 `strace` 更加有效。
|
||||
|
||||
一开始, `strace` 产生的大量输出可能会让你不知所措,幸好你可以忽略其中大部分的无用信息。我经常使用 `-o` 参数把输出的追踪结果保存到单独的文件里:
|
||||
|
||||
```
|
||||
$ strace -o /tmp/trace foo
|
||||
Error opening configuration file: No such file or directory
|
||||
$ cat /tmp/trace
|
||||
execve("foo", ["foo"], 0x7ffce98dc010 /* 16 vars */) = 0
|
||||
brk(NULL) = 0x56363b3fb000
|
||||
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
|
||||
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
|
||||
fstat(3, {st_mode=S_IFREG|0644, st_size=25186, ...}) = 0
|
||||
mmap(NULL, 25186, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2f12cf1000
|
||||
close(3) = 0
|
||||
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
|
||||
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260A\2\0\0\0\0\0"..., 832) = 832
|
||||
fstat(3, {st_mode=S_IFREG|0755, st_size=1824496, ...}) = 0
|
||||
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2f12cef000
|
||||
mmap(NULL, 1837056, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2f12b2e000
|
||||
mprotect(0x7f2f12b50000, 1658880, PROT_NONE) = 0
|
||||
mmap(0x7f2f12b50000, 1343488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f2f12b50000
|
||||
mmap(0x7f2f12c98000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16a000) = 0x7f2f12c98000
|
||||
mmap(0x7f2f12ce5000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7f2f12ce5000
|
||||
mmap(0x7f2f12ceb000, 14336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2f12ceb000
|
||||
close(3) = 0
|
||||
arch_prctl(ARCH_SET_FS, 0x7f2f12cf0500) = 0
|
||||
mprotect(0x7f2f12ce5000, 16384, PROT_READ) = 0
|
||||
mprotect(0x56363b08b000, 4096, PROT_READ) = 0
|
||||
mprotect(0x7f2f12d1f000, 4096, PROT_READ) = 0
|
||||
munmap(0x7f2f12cf1000, 25186) = 0
|
||||
openat(AT_FDCWD, "/etc/foo/config.json", O_RDONLY) = -1 ENOENT (No such file or directory)
|
||||
dup(2) = 3
|
||||
fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
|
||||
brk(NULL) = 0x56363b3fb000
|
||||
brk(0x56363b41c000) = 0x56363b41c000
|
||||
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x8), ...}) = 0
|
||||
write(3, "Error opening configuration file"..., 60) = 60
|
||||
close(3) = 0
|
||||
exit_group(1) = ?
|
||||
+++ exited with 1 +++
|
||||
```
|
||||
|
||||
`strace` 输出的第一页通常是低级的进程启动过程。(你可以看到很多 `mmap`、`mprotect`、`brk` 调用,这是用来分配原始内存和映射动态链接库的。)实际上,在查找错误时,最好从下往上阅读 `strace` 的输出。你可以看到 `write` 调用在最后返回了错误信息。如果你向上找,你将会看到第一个失败的系统调用是 `openat`,它在尝试打开 `/etc/foo/config.json` 时抛出了 `ENOENT` (“No such file or directory”)的错误。现在我们已经知道了配置文件应该放在哪里。
|
||||
|
||||
这是一个简单的例子,但我敢说在 90% 的情况下,使用 `strace` 进行调试不需要更多复杂的工作。以下是完整的调试步骤:
|
||||
|
||||
1. 从程序中获得含糊不清的错误信息
|
||||
2. 使用 `strace` 运行程序
|
||||
3. 在输出中找到错误信息
|
||||
4. 往前追溯并找到第一个失败的系统调用
|
||||
|
||||
第四步中的系统调用很可能向你显示出问题所在。
|
||||
|
||||
### 小技巧
|
||||
|
||||
在开始更加复杂的调试之前,这里有一些有用的调试技巧帮助你高效使用 `strace`:
|
||||
|
||||
#### man 是你的朋友
|
||||
|
||||
在很多 *nix 操作系统中,你可以通过 `man syscalls` 查看系统调用的列表。你将会看到类似于 `brk(2)` 之类的东西,这意味着你可以通过运行 `man 2 brk` 得到与此相关的更多信息。
|
||||
|
||||
一个小问题:`man 2 fork` 会显示出在 GNU `libc` 里封装的 `fork()` 手册页,而 `fork()` 现在实际上是由 `clone` 系统调用实现的。`fork` 的语义与 `clone` 相同,但是如果我写了一个含有 `fork()` 的程序并使用 `strace` 去调试它,我将找不到任何关于 `fork` 调用的信息,只能看到 `clone` 调用。如果将源代码与 `strace` 的输出进行比较的时候,像这种问题会让人感到困惑。
|
||||
|
||||
#### 使用 -o 将输出保存到文件
|
||||
|
||||
`strace` 可以生成很多输出,所以将输出保存到单独的文件是很有帮助的(就像上面的例子一样)。它还能够在控制台中避免程序自身的输出与 `strace` 的输出发生混淆。
|
||||
|
||||
#### 使用 -s 查看更多的参数
|
||||
|
||||
你可能已经注意到,错误信息的第二部分没有出现在上面的例子中。这是因为 `strace` 默认仅显示字符串参数的前 32 个字节。如果你需要捕获更多参数,请向 `strace` 追加类似于 `-s 128` 之类的参数。
|
||||
|
||||
#### -y 使得追踪文件或套接字更加容易
|
||||
|
||||
“一切皆文件”意味着 *nix 系统通过文件描述符进行所有 IO 操作,不管是真实的文件还是通过网络或者进程间管道。这对于编程而言是很方便的,但是在追踪系统调用时,你将很难分辨出 `read` 和 `write` 的真实行为。
|
||||
|
||||
`-y` 参数使 `strace` 在注释中注明每个文件描述符的具体指向。
|
||||
|
||||
#### 使用 -p 附加到正在运行的进程中
|
||||
|
||||
正如我们将在后面的例子中看到的,有时候你想追踪一个正在运行的程序。如果你知道这个程序的进程号为 1337 (可以通过 `ps` 查询),则可以这样操作:
|
||||
|
||||
```
|
||||
$ strace -p 1337
|
||||
...system call trace output...
|
||||
```
|
||||
|
||||
你可能需要 root 权限才能运行。
|
||||
|
||||
#### 使用 -f 追踪子进程
|
||||
|
||||
`strace` 默认只追踪一个进程。如果这个进程产生了一个子进程,你将会看到创建子进程的系统调用(一般是 `clone`),但是你看不到子进程内触发的任何调用。
|
||||
|
||||
如果你认为在子进程中存在错误,则需要使用 `-f` 参数启用子进程追踪功能。这样做的缺点是输出的内容会让人更加困惑。当追踪一个进程时,`strace` 显示的是单个调用事件流。当追踪多个进程的时候,你将会看到以 `<unfinished ...>` 开始的初始调用,接着是一系列针对其它线程的调用,最后才出现以 `<... foocall resumed>` 结束的初始调用。此外,你可以使用 `-ff` 参数将所有的调用分离到不同的文件中(查看 [strace 手册][6] 获取更多信息)。
|
||||
|
||||
#### 使用 -e 进行过滤
|
||||
|
||||
正如你所看到的,默认的追踪输出是所有的系统调用。你可以使用 `-e` 参数过滤你需要追踪的调用(查看 [strace 手册][6])。这样做的好处是运行过滤后的 `strace` 比起使用 `grep` 进行二次过滤要更快。老实说,我大部分时间都不会被打扰。
|
||||
|
||||
#### 并非所有的错误都是不好的
|
||||
|
||||
一个简单而常用的例子是一个程序在多个位置搜索文件,例如 shell 搜索哪个 `bin/` 目录包含可执行文件:
|
||||
|
||||
```
|
||||
$ strace sh -c uname
|
||||
...
|
||||
stat("/home/user/bin/uname", 0x7ffceb817820) = -1 ENOENT (No such file or directory)
|
||||
stat("/usr/local/bin/uname", 0x7ffceb817820) = -1 ENOENT (No such file or directory)
|
||||
stat("/usr/bin/uname", {st_mode=S_IFREG|0755, st_size=39584, ...}) = 0
|
||||
...
|
||||
```
|
||||
|
||||
“错误信息之前的最后一次失败调用”这种启发式方法非常适合于查找错误。无论如何,自下而上地查找是有道理的。
|
||||
|
||||
#### C 编程指南非常有助于理解系统调用
|
||||
|
||||
标准 C 库函数调用不属于系统调用,但它们仅是系统调用之上的唯一一个薄层。所以如果你了解(甚至只是略知一二)如何使用 C 语言,那么阅读系统调用追踪信息就非常容易。例如,如果你在调试网络系统调用,你可以尝试略读 [Beej 经典的《网络编程指南》][7]。
|
||||
|
||||
### 一个更复杂的调试例子
|
||||
|
||||
就像我说的那样,简单的调试例子表现了我在大部分情况下如何使用 `strace`。然而,有时候需要一些更加细致的工作,所以这里有一个稍微复杂(且真实)的例子。
|
||||
|
||||
[bcron][8] 是一个任务调度器,它是经典 *nix `cron` 守护程序的另一种实现。它已经被安装到一台服务器上,但是当有人尝试编辑作业时间表时,发生了以下情况:
|
||||
|
||||
```
|
||||
# crontab -e -u logs
|
||||
bcrontab: Fatal: Could not create temporary file
|
||||
```
|
||||
|
||||
好的,现在 bcron 尝试写入一些文件,但是它失败了,也没有告诉我们原因。以下是 `strace` 的输出:
|
||||
|
||||
```
|
||||
# strace -o /tmp/trace crontab -e -u logs
|
||||
bcrontab: Fatal: Could not create temporary file
|
||||
# cat /tmp/trace
|
||||
...
|
||||
openat(AT_FDCWD, "bcrontab.14779.1573691864.847933", O_RDONLY) = 3
|
||||
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82049b4000
|
||||
read(3, "#Ansible: logsagg\n20 14 * * * lo"..., 8192) = 150
|
||||
read(3, "", 8192) = 0
|
||||
munmap(0x7f82049b4000, 8192) = 0
|
||||
close(3) = 0
|
||||
socket(AF_UNIX, SOCK_STREAM, 0) = 3
|
||||
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/bcron-spool"}, 110) = 0
|
||||
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82049b4000
|
||||
write(3, "156:Slogs\0#Ansible: logsagg\n20 1"..., 161) = 161
|
||||
read(3, "32:ZCould not create temporary f"..., 8192) = 36
|
||||
munmap(0x7f82049b4000, 8192) = 0
|
||||
close(3) = 0
|
||||
write(2, "bcrontab: Fatal: Could not creat"..., 49) = 49
|
||||
unlink("bcrontab.14779.1573691864.847933") = 0
|
||||
exit_group(111) = ?
|
||||
+++ exited with 111 +++
|
||||
```
|
||||
|
||||
在程序结束之前有一个 `write` 的错误信息,但是这次有些不同。首先,在此之前没有任何相关的失败系统调用。其次,我们看到这个错误信息是由 `read` 从别的地方读取而来的。这看起来像是真正的错误发生在别的地方,而 `bcrontab` 只是在转播这些信息。
|
||||
|
||||
如果你查阅了 `man 2 read`,你将会看到 `read` 的第一个参数 (`3`) 是一个文件描述符,这是 *nix 操作系统用于所有 IO 操作的句柄。你该如何知道文件描述符 3 代表什么?在这种情况下,你可以使用 `-y` 参数运行 `strace`(如上文所述),它将会在注释里告诉你文件描述符的具体指向,但是了解如何从上面这种输出中分析追踪结果是很有用的。
|
||||
|
||||
一个文件描述符可以来自于许多系统调用之一(这取决于它是用于控制台、网络套接字还是真实文件等的描述符),但不论如何,我们都可以搜索返回值为 `3` 的系统调用(例如,在 `strace` 的输出中查找 `=3`)。在这次 `strace` 中可以看到有两个这样的调用:最上面的 `openat` 以及中间的 `socket`。`openat` 打开一个文件,但是紧接着的 `close(3)` 表明其已经被关闭。(注意:文件描述符可以在打开并关闭后重复使用。)所以 `socket` 调用才是与此相关的(它是在 `read` 之前的最后一个),这告诉我们 `brcontab` 正在与一个网络套接字通信。在下一行,`connect` 表明文件描述符 3 是一个连接到 `/var/run/bcron-spool` 的 Unix 域套接字。
|
||||
|
||||
因此,我们需要弄清楚 Unix 套接字的另一侧是哪个进程在监听。有两个巧妙的技巧适用于在服务器部署中调试。一个是使用 `netstat` 或者较新的 `ss`。这两个命令都描述了当前系统中活跃的网络套接字,使用 `-l` 参数可以显示出处于监听状态的套接字,而使用 `-p` 参数可以得到正在使用该套接字的程序信息。(它们还有更多有用的选项,但是这两个已经足够完成工作了。)
|
||||
|
||||
```
|
||||
# ss -pl | grep /var/run/bcron-spool
|
||||
u_str LISTEN 0 128 /var/run/bcron-spool 1466637 * 0 users:(("unixserver",pid=20629,fd=3))
|
||||
```
|
||||
|
||||
这告诉我们 `/var/run/bcron-spool` 套接字的监听程序是 `unixserver` 这个命令,它的进程 ID 为 20629。(巧合的是,这个程序也使用文件描述符 `3` 去连接这个套接字。)
|
||||
|
||||
第二个常用的工具就是使用 `lsof` 查找相同的信息。它可以列出当前系统中打开的所有文件(或文件描述符)。或者,我们可以得到一个具体文件的信息:
|
||||
|
||||
```
|
||||
# lsof /var/run/bcron-spool
|
||||
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
||||
unixserve 20629 cron 3u unix 0x000000005ac4bd83 0t0 1466637 /var/run/bcron-spool type=STREAM
|
||||
```
|
||||
|
||||
进程 20629 是一个常驻进程,所以我们可以使用 `strace -o /tmp/trace -p 20629` 去查看该进程的系统调用。如果我们在另一个终端尝试编辑 cron 的计划任务表,就可以在错误发生时捕获到以下信息:
|
||||
|
||||
```
|
||||
accept(3, NULL, NULL) = 4
|
||||
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7faa47c44810) = 21181
|
||||
close(4) = 0
|
||||
accept(3, NULL, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
|
||||
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21181, si_uid=998, si_status=0, si_utime=0, si_stime=0} ---
|
||||
wait4(0, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED, NULL) = 21181
|
||||
wait4(0, 0x7ffe6bc36764, WNOHANG|WSTOPPED, NULL) = -1 ECHILD (No child processes)
|
||||
rt_sigaction(SIGCHLD, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, 8) = 0
|
||||
rt_sigreturn({mask=[]}) = 43
|
||||
accept(3, NULL, NULL) = 4
|
||||
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7faa47c44810) = 21200
|
||||
close(4) = 0
|
||||
accept(3, NULL, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
|
||||
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21200, si_uid=998, si_status=111, si_utime=0, si_stime=0} ---
|
||||
wait4(0, [{WIFEXITED(s) && WEXITSTATUS(s) == 111}], WNOHANG|WSTOPPED, NULL) = 21200
|
||||
wait4(0, 0x7ffe6bc36764, WNOHANG|WSTOPPED, NULL) = -1 ECHILD (No child processes)
|
||||
rt_sigaction(SIGCHLD, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, 8) = 0
|
||||
rt_sigreturn({mask=[]}) = 43
|
||||
accept(3, NULL, NULL
|
||||
```
|
||||
|
||||
(最后一个 `accept` 调用没有在追踪期间完成。)不幸的是,这次追踪没有包含我们想要的错误信息。我们没有观察到 `bcrontan` 往套接字发送或接受的任何信息。然而,我们看到了很多进程管理操作(`clone`、`wait4`、`SIGCHLD`,等等)。这个进程产生了子进程,我们猜测真实的工作是由子进程完成的。如果我们想捕获子进程的追踪信息,就必须往 `strace` 追加 `-f` 参数。以下是我们最终使用 `strace -f -o /tmp/trace -p 20629` 找到的错误信息:
|
||||
|
||||
```
|
||||
21470 openat(AT_FDCWD, "tmp/spool.21470.1573692319.854640", O_RDWR|O_CREAT|O_EXCL, 0600) = -1 EACCES (Permission denied)
|
||||
21470 write(1, "32:ZCould not create temporary f"..., 36) = 36
|
||||
21470 write(2, "bcron-spool[21470]: Fatal: logs:"..., 84) = 84
|
||||
21470 unlink("tmp/spool.21470.1573692319.854640") = -1 ENOENT (No such file or directory)
|
||||
21470 exit_group(111) = ?
|
||||
21470 +++ exited with 111 +++
|
||||
```
|
||||
|
||||
现在我们知道了进程 ID 21470 在尝试创建文件 `tmp/spool.21470.1573692319.854640` (相对于当前的工作目录)时得到了一个没有权限的错误。如果我们知道当前的工作目录,就可以得到完整路径并能指出为什么该进程无法在此处创建临时文件。不幸的是,这个进程已经退出了,所以我们不能使用 `lsof -p 21470` 去找出当前的工作目录,但是我们可以往前追溯,查找进程 ID 21470 使用哪个系统调用改变了它的工作目录。这个系统调用是 `chdir`(可以在搜索引擎很轻松地找到)。以下是一直往前追溯到服务器进程 ID 20629 的结果:
|
||||
|
||||
```
|
||||
20629 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7faa47c44810) = 21470
|
||||
...
|
||||
21470 execve("/usr/sbin/bcron-spool", ["bcron-spool"], 0x55d2460807e0 /* 27 vars */) = 0
|
||||
...
|
||||
21470 chdir("/var/spool/cron") = 0
|
||||
...
|
||||
21470 openat(AT_FDCWD, "tmp/spool.21470.1573692319.854640", O_RDWR|O_CREAT|O_EXCL, 0600) = -1 EACCES (Permission denied)
|
||||
21470 write(1, "32:ZCould not create temporary f"..., 36) = 36
|
||||
21470 write(2, "bcron-spool[21470]: Fatal: logs:"..., 84) = 84
|
||||
21470 unlink("tmp/spool.21470.1573692319.854640") = -1 ENOENT (No such file or directory)
|
||||
21470 exit_group(111) = ?
|
||||
21470 +++ exited with 111 +++
|
||||
```
|
||||
|
||||
(如果你在这里迷糊了,你可能需要阅读 [我之前有关 \*nix 进程管理和 shell 的文章][9])
|
||||
|
||||
现在 PID 为 20629 的服务器进程没有权限在 `/var/spool/cron/tmp/spool.21470.1573692319.854640` 创建文件。最可能的原因就是典型的 *nix 文件系统权限设置。让我们检查一下:
|
||||
|
||||
```
|
||||
# ls -ld /var/spool/cron/tmp/
|
||||
drwxr-xr-x 2 root root 4096 Nov 6 05:33 /var/spool/cron/tmp/
|
||||
# ps u -p 20629
|
||||
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||
cron 20629 0.0 0.0 2276 752 ? Ss Nov14 0:00 unixserver -U /var/run/bcron-spool -- bcron-spool
|
||||
```
|
||||
|
||||
这就是问题所在!这个服务进程以 `cron` 用户运行,但是只有 `root` 用户才有向 `/var/spool/cron/tmp/` 目录写入的权限。一个简单 `chown cron /var/spool/cron/tmp/` 命令就能让 `bcron` 正常工作。(如果不是这个问题,那么下一个最有可能的怀疑对象是诸如 SELinux 或者 AppArmor 之类的内核安全模块,因此我将会使用 `dmesg` 检查内核日志。)
|
||||
|
||||
### 总结
|
||||
|
||||
最初,系统调用追踪可能会让人不知所措,但是我希望我已经证明它们是调试一整套常见部署问题的快速方法。你可以设想一下尝试用单步调试器去调试多进程的 `bcron` 问题。
|
||||
|
||||
通过一连串的系统调用解决问题是需要练习的,但正如我说的那样,在大多数情况下,我只需要使用 `strace` 从下往上追踪并查找错误。不管怎样,`strace` 节省了我很多的调试时间。我希望这也对你有所帮助。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://theartofmachinery.com/2019/11/14/deployment_debugging_strace.html
|
||||
|
||||
作者:[Simon Arneaud][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[hanwckf](https://github.com/hanwckf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://theartofmachinery.com
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://strace.io/
|
||||
[2]: http://dtrace.org/blogs/about/
|
||||
[3]: https://man.openbsd.org/ktrace
|
||||
[4]: https://theartofmachinery.com/images/strace/system_calls.svg
|
||||
[5]: https://linux.die.net/man/1/ltrace
|
||||
[6]: https://linux.die.net/man/1/strace
|
||||
[7]: https://beej.us/guide/bgnet/html/index.html
|
||||
[8]: https://untroubled.org/bcron/
|
||||
[9]: https://theartofmachinery.com/2018/11/07/writing_a_nix_shell.html
|
201
published/201912/20191115 How to port an awk script to Python.md
Normal file
201
published/201912/20191115 How to port an awk script to Python.md
Normal file
@ -0,0 +1,201 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11654-1.html)
|
||||
[#]: subject: (How to port an awk script to Python)
|
||||
[#]: via: (https://opensource.com/article/19/11/awk-to-python)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
如何把 awk 脚本移植到 Python
|
||||
======
|
||||
|
||||
> 将一个 awk 脚本移植到 Python 主要在于代码风格而不是转译。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/08/095256ko6xdfwooe8zctfz.jpg)
|
||||
|
||||
脚本是解决问题的有效方法,而 awk 是编写脚本的出色语言。它特别擅长于简单的文本处理,它可以带你完成配置文件的某些复杂重写或目录中文件名的重新格式化。
|
||||
|
||||
### 何时从 awk 转向 Python
|
||||
|
||||
但是在某些方面,awk 的限制开始显现出来。它没有将文件分解为模块的真正概念,它缺乏质量错误报告,并且缺少了现在被认为是编程语言工作原理的其他内容。当编程语言的这些丰富功能有助于维护关键脚本时,移植将是一个不错的选择。
|
||||
|
||||
我最喜欢的完美移植 awk 的现代编程语言是 Python。
|
||||
|
||||
在将 awk 脚本移植到 Python 之前,通常值得考虑一下其原始使用场景。例如,由于 awk 的局限性,通常从 Bash 脚本调用 awk 代码,其中包括一些对 `sed`、`sort` 之类的其它命令行常见工具的调用。 最好将所有内容转换为一个一致的 Python 程序。有时,脚本会做出过于宽泛的假设,例如,即使实际上只运行一个文件,该代码也可能允许任意数量的文件。
|
||||
|
||||
在仔细考虑了上下文并确定了要用 Python 替代的东西之后,该编写代码了。
|
||||
|
||||
### 标准 awk 到 Python 功能
|
||||
|
||||
以下 Python 功能是有用的,需要记住:
|
||||
|
||||
```
|
||||
with open(some_file_name) as fpin:
|
||||
for line in fpin:
|
||||
pass # do something with line
|
||||
```
|
||||
|
||||
此代码将逐行循环遍历文件并处理这些行。
|
||||
|
||||
如果要访问行号(相当于 awk 的 `NR`),则可以使用以下代码:
|
||||
|
||||
```
|
||||
with open(some_file_name) as fpin:
|
||||
for nr, line in enumerate(fpin):
|
||||
pass # do something with line
|
||||
```
|
||||
|
||||
### 在 Python 中实现多文件的 awk 式行为
|
||||
|
||||
如果你需要能够遍历任意数量的文件同时保持行数的持续计数(类似 awk 的 `FNR`),则此循环可以做到这一点:
|
||||
|
||||
```
|
||||
def awk_like_lines(list_of_file_names):
|
||||
def _all_lines():
|
||||
for filename in list_of_file_names:
|
||||
with open(filename) as fpin:
|
||||
yield from fpin
|
||||
yield from enumerate(_all_lines())
|
||||
```
|
||||
|
||||
此语法使用 Python 的*生成器*和 `yield from` 来构建*迭代器*,该迭代器将遍历所有行并保持一个持久计数。
|
||||
|
||||
如果你需要同时使用 `FNR` 和 `NR`,这是一个更复杂的循环:
|
||||
|
||||
```
|
||||
def awk_like_lines(list_of_file_names):
|
||||
def _all_lines():
|
||||
for filename in list_of_file_names:
|
||||
with open(filename) as fpin:
|
||||
yield from enumerate(fpin)
|
||||
for nr, (fnr, line) in _all_lines:
|
||||
yield nr, fnr, line
|
||||
```
|
||||
|
||||
### 更复杂的 FNR、NR 和行数的 awk 行为
|
||||
|
||||
如果 `FNR`、`NR` 和行数这三个你全都需要,仍然会有一些问题。如果确实如此,则使用三元组(其中两个项目是数字)会导致混淆。命名参数可使该代码更易于阅读,因此最好使用 `dataclass`:
|
||||
|
||||
```
|
||||
import dataclass
|
||||
|
||||
@dataclass.dataclass(frozen=True)
|
||||
class AwkLikeLine:
|
||||
content: str
|
||||
fnr: int
|
||||
nr: int
|
||||
|
||||
def awk_like_lines(list_of_file_names):
|
||||
def _all_lines():
|
||||
for filename in list_of_file_names:
|
||||
with open(filename) as fpin:
|
||||
yield from enumerate(fpin)
|
||||
for nr, (fnr, line) in _all_lines:
|
||||
yield AwkLikeLine(nr=nr, fnr=fnr, line=line)
|
||||
```
|
||||
|
||||
你可能想知道,为什么不一直用这种方法呢?使用其它方式的的原因是总用这种方法太复杂了。如果你的目标是把一个通用库更容易地从 awk 移植到 Python,请考虑这样做。但是编写一个可以使你确切地了解特定情况所需的循环的方法通常更容易实现,也更容易理解(因而易于维护)。
|
||||
|
||||
### 理解 awk 字段
|
||||
|
||||
一旦有了与一行相对应的字符串,如果要转换 awk 程序,则通常需要将其分解为*字段*。Python 有几种方法可以做到这一点。这将把行按任意数量的连续空格拆分,返回一个字符串列表:
|
||||
|
||||
```
|
||||
line.split()
|
||||
```
|
||||
|
||||
如果需要另一个字段分隔符,比如以 `:` 分隔行,则需要 `rstrip` 方法来删除最后一个换行符:
|
||||
|
||||
```
|
||||
line.rstrip("\n").split(":")
|
||||
```
|
||||
|
||||
完成以下操作后,列表 `parts` 将存有分解的字符串:
|
||||
|
||||
```
|
||||
parts = line.rstrip("\n").split(":")
|
||||
```
|
||||
|
||||
这种拆分非常适合用来处理参数,但是我们处于[偏差一个的错误][2]场景中。现在 `parts[0]` 将对应于 awk 的 `$1`,`parts[1]` 将对应于 awk 的 `$2`,依此类推。之所以偏差一个,是因为 awk 计数“字段”从 1 开始,而 Python 从 0 开始计数。在 awk 中,`$0` 是整个行 —— 等同于 `line.rstrip("\n")`,而 awk 的 `NF`(字段数)更容易以 `len(parts)` 的形式得到。
|
||||
|
||||
### 移植 awk 字段到 Python
|
||||
|
||||
例如,让我们将这个单行代码“[如何使用 awk 从文件中删除重复行][3]”转换为 Python。
|
||||
|
||||
`awk` 中的原始代码是:
|
||||
|
||||
```
|
||||
awk '!visited[$0]++' your_file > deduplicated_file
|
||||
```
|
||||
|
||||
“真实的” Python 转换将是:
|
||||
|
||||
```
|
||||
import collections
|
||||
import sys
|
||||
|
||||
visited = collections.defaultdict(int)
|
||||
for line in open("your_file"):
|
||||
did_visit = visited[line]
|
||||
visited[line] += 1
|
||||
if not did_visit:
|
||||
sys.stdout.write(line)
|
||||
```
|
||||
|
||||
但是,Python 比 awk 具有更多的数据结构。与其计数访问次数(除了知道是否看到一行,我们不使用它),为什么不记录访问的行呢?
|
||||
|
||||
```
|
||||
import sys
|
||||
|
||||
visited = set()
|
||||
for line in open("your_file"):
|
||||
if line in visited:
|
||||
continue
|
||||
visited.add(line)
|
||||
sys.stdout.write(line)
|
||||
```
|
||||
|
||||
### 编写 Python 化的 awk 代码
|
||||
|
||||
Python 社区提倡编写 Python 化的代码,这意味着它要遵循公认的代码风格。更加 Python 化的方法将区分*唯一性*和输入/输出的关注点。此更改将使对代码进行单元测试更加容易:
|
||||
|
||||
```
|
||||
def unique_generator(things):
|
||||
visited = set()
|
||||
for thing in things:
|
||||
if thing in visited:
|
||||
continue
|
||||
visited.add(things)
|
||||
yield thing
|
||||
|
||||
import sys
|
||||
|
||||
for line in unique_generator(open("your_file")):
|
||||
sys.stdout.write(line)
|
||||
```
|
||||
|
||||
将所有逻辑置于输入/输出代码之外,可以更好地分离问题,并提高代码的可用性和可测试性。
|
||||
|
||||
### 结论:Python 可能是一个不错的选择
|
||||
|
||||
将 awk 脚本移植到 Python 时,通常是在考虑适当的 Python 代码风格时重新实现核心需求,而不是按条件/操作进行笨拙的音译。考虑原始上下文并产生高质量的 Python 解决方案。虽然有时候使用 awk 的 Bash 单行代码可以完成这项工作,但 Python 编码是通往更易于维护的代码的途径。
|
||||
|
||||
另外,如果你正在编写 awk 脚本,我相信您也可以学习 Python!如果你有任何疑问,请告诉我。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/awk-to-python
|
||||
|
||||
作者:[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/OSDC_women_computing_4.png?itok=VGZO8CxT (Woman sitting in front of her laptop)
|
||||
[2]: https://en.wikipedia.org/wiki/Off-by-one_error
|
||||
[3]: https://opensource.com/article/19/10/remove-duplicate-lines-files-awk
|
@ -1,40 +1,26 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11661-1.html)
|
||||
[#]: subject: (6 Methods to Quickly Check if a Website is up or down from the Linux Terminal)
|
||||
[#]: via: (https://www.2daygeek.com/linux-command-check-website-is-up-down-alive/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
6 Methods to Quickly Check if a Website is up or down from the Linux Terminal
|
||||
在 Linux 终端快速检测网站是否宕机的 6 个方法
|
||||
======
|
||||
|
||||
This tutorial shows you how to quickly check whether a given website is up (alive) or down from a Linux terminal.
|
||||
> 本教程教你怎样在 Linux 终端快速检测一个网站是否宕机。
|
||||
|
||||
You may already know some of these commands to verify about this, namely ping, curl, and wget.
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/10/093801u332115oocxz4531.jpg)
|
||||
|
||||
But we have added some other commands as well in this tutorial.
|
||||
你可能已经了解了一些类似的命令,像 `ping`、`curl` 和 `wget`。我们在本教程中又加入了一些其他命令。同时,我们也加入了不同的选项来检测单个和多个主机的信息。
|
||||
|
||||
Also, we have added various options to check this information for single host and multiple hosts.
|
||||
本文将帮助你检测网站是否宕机。但是如果你在维护一些网站,希望网站宕掉时得到实时的报警,我推荐你去使用实时网站监控工具。这种工具有很多,有些是免费的,大部分收费。根据你的需求,选择合适的工具。在后续的文章中我们会涉及这个主题。
|
||||
|
||||
This article will help you to check whether the website is up or down.
|
||||
### 方法 1:使用 fping 命令检测一个网站是否宕机
|
||||
|
||||
But if you maintain some websites and want to get real-time alerts when the website is down.
|
||||
|
||||
I recommend you to use real-time website monitoring tools. There are many tools for this, and some are free and most of them are paid.
|
||||
|
||||
So choose the preferred one based on your needs. We will cover this topic in our upcoming article.
|
||||
|
||||
### Method-1: How to Check if a Website is up or down Using the fping Command
|
||||
|
||||
**[fping command][1]** is a program such as ping, which uses the Internet Control Message Protocol (ICMP) echo request to determine whether a target host is responding.
|
||||
|
||||
fping differs from ping because it allows users to ping any number of host in parallel. Also, hosts can be entered from a text file.
|
||||
|
||||
fping sends an ICMP echo request, moves the next target in a round-robin fashion, and does not wait until the target host responds.
|
||||
|
||||
If a target host replies, it is noted as active and removed from the list of targets to check; if a target does not respond within a certain time limit and/or retry limit it is designated as unreachable.
|
||||
[fping 命令][1] 是一个类似 `ping` 的程序,使用互联网控制消息协议(ICMP)的<ruby>回应请求报文<rt>echo request</rt></ruby>来判断目标主机是否能回应。`fping` 与 `ping` 的不同之处在于它可以并行地 `ping` 任意数量的主机,也可以从一个文本文件读入主机名称。`fping` 发送一个 ICMP 回应请求后不等待目标主机响应,就以轮询模式向下一个目标主机发请求。如果一个目标主机有响应,那么它就被标记为存活的,然后从检查目标列表里去掉。如果一个目标主机在限定的时间和(或)重试次数内没有响应,则被指定为网站无法到达的。
|
||||
|
||||
```
|
||||
# fping 2daygeek.com linuxtechnews.com magesh.co.in
|
||||
@ -44,15 +30,9 @@ linuxtechnews.com is alive
|
||||
magesh.co.in is alive
|
||||
```
|
||||
|
||||
### Method-2: How to Quickly Check Whether a Website is up or down Using the http Command
|
||||
### 方法 2:使用 http 命令检测一个网站是否宕机
|
||||
|
||||
HTTPie (pronounced aitch-tee-tee-pie) is a command line HTTP client.
|
||||
|
||||
The **[httpie tool][2]** is a modern command line http client which makes CLI interaction with web services.
|
||||
|
||||
It provides a simple http command that allows for sending arbitrary HTTP requests using a simple and natural syntax, and displays colorized output.
|
||||
|
||||
HTTPie can be used for testing, debugging, and generally interacting with HTTP servers.
|
||||
HTTPie(读作 aitch-tee-tee-pie)是一个命令行 HTTP 客户端。[httpie][2] 是一个可以与 web 服务通过 CLI 进行交互的现代工具。httpie 工具提供了简单的 `http` 命令,可以通过发送简单的、自然语言语法的任意 HTTP 请求得到多彩的结果输出。HTTPie 可以用来对 HTTP 服务器进行测试、调试和基本的交互。
|
||||
|
||||
```
|
||||
# http 2daygeek.com
|
||||
@ -69,15 +49,9 @@ Transfer-Encoding: chunked
|
||||
Vary: Accept-Encoding
|
||||
```
|
||||
|
||||
### Method-3: How to Check if a Website is up or down Using the curl Command
|
||||
### 方法 3:使用 curl 命令检测一个网站是否宕机
|
||||
|
||||
**[curl command][3]** is a tool to transfer data from a server or to server, using one of the supported protocols (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP).
|
||||
|
||||
The command is designed to work without user interaction.
|
||||
|
||||
Also curl support proxy support, user authentication, FTP upload, HTTP post, SSL connections, cookies, file transfer resume, Metalink, and more.
|
||||
|
||||
curl is powered by libcurl for all transfer-related features.
|
||||
[curl 命令][3] 是一个用于在服务器间通过支持的协议(DICT、FILE、FTP、FTPS、GOPHER、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、POP3、POP3S、RTMP、RTSP、SCP、SFTP、SMTP、SMTPS、TELNET 和 TFTP)传输数据的工具。这个工具不支持用户交互。`curl` 也支持使用代理、用户认证、FTP 上传、HTTP POST 请求、SSL 连接、cookie、断点续传、Metalink 等等。`curl `由 libcurl 库提供所有与传输有关的能力。
|
||||
|
||||
```
|
||||
# curl -I https://www.magesh.co.in
|
||||
@ -95,14 +69,14 @@ server: cloudflare
|
||||
cf-ray: 535b74123ca4dbf3-LHR
|
||||
```
|
||||
|
||||
Use the following curl command if you want to see only the HTTP status code instead of entire output.
|
||||
如果你只想看 HTTP 状态码而不是返回的全部信息,用下面的 `curl` 命令:
|
||||
|
||||
```
|
||||
# curl -I "www.magesh.co.in" 2>&1 | awk '/HTTP\// {print $2}'
|
||||
200
|
||||
```
|
||||
|
||||
If you want to see if a given website is up or down, use the following Bash script.
|
||||
如果你想看一个网站是否宕机,用下面的 bash 脚本:
|
||||
|
||||
```
|
||||
# vi curl-url-check.sh
|
||||
@ -115,7 +89,7 @@ else
|
||||
fi
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# sh curl-url-check.sh
|
||||
@ -124,7 +98,7 @@ HTTP/2 200
|
||||
magesh.co.in is up
|
||||
```
|
||||
|
||||
Use the following shell script if you want to see the status of multiple websites.
|
||||
如果你想看多个网站的状态,使用下面的 shell 脚本:
|
||||
|
||||
```
|
||||
# vi curl-url-check-1.sh
|
||||
@ -141,7 +115,7 @@ echo "----------------------------------"
|
||||
done
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把上面脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# sh curl-url-check-1.sh
|
||||
@ -156,13 +130,9 @@ www.xyzzz.com is down
|
||||
----------------------------------
|
||||
```
|
||||
|
||||
### Method-4: How to Quickly Check Whether a Website is up or down Using the wget Command
|
||||
### 方法 4:使用 wget 命令检测一个网站是否宕机
|
||||
|
||||
**[wget command][4]** (formerly known as Geturl) is a Free, open source, command line download tool which is retrieving files using HTTP, HTTPS and FTP, the most widely-used Internet protocols.
|
||||
|
||||
It is a non-interactive command line tool and Its name is derived from World Wide Web and get.
|
||||
|
||||
wget handle download pretty much good compared with other tools, futures included working in background, recursive download, multiple file downloads, resume downloads, non-interactive downloads & large file downloads.
|
||||
[wget 命令][4](前身是 Geturl)是一个自由开源的命令行下载工具,通过 HTTP、HTTPS、FTP 和其他广泛使用的互联网协议获取文件。`wget` 是非交互式的命令行工具,由 World Wide Web 和 get 得名。`wget` 相对于其他工具来说更优秀,功能包括后台运行、递归下载、多文件下载、断点续传、非交互式下载和大文件下载。
|
||||
|
||||
```
|
||||
# wget -S --spider https://www.magesh.co.in
|
||||
@ -190,14 +160,14 @@ Remote file exists and could contain further links,
|
||||
but recursion is disabled -- not retrieving.
|
||||
```
|
||||
|
||||
Use the following wget command if you want to see only the HTTP status code instead of entire output.
|
||||
如果你只想看 HTTP 状态码而不是返回的全部结果,用下面的 `wget` 命令:
|
||||
|
||||
```
|
||||
# wget --spider -S "www.magesh.co.in" 2>&1 | awk '/HTTP\// {print $2}'
|
||||
200
|
||||
```
|
||||
|
||||
If you want to see if a given website is up or down, use the following Bash script.
|
||||
如果你想看一个网站是否宕机,用下面的 bash 脚本:
|
||||
|
||||
```
|
||||
# vi wget-url-check.sh
|
||||
@ -210,7 +180,7 @@ else
|
||||
fi
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# wget-url-check.sh
|
||||
@ -219,7 +189,7 @@ HTTP/1.1 200 OK
|
||||
Google.com is up
|
||||
```
|
||||
|
||||
Use the following shell script if you want to see the status of multiple websites.
|
||||
如果你想看多个网站的状态,使用下面的 shell 脚本:
|
||||
|
||||
```
|
||||
# vi curl-url-check-1.sh
|
||||
@ -236,7 +206,7 @@ echo "----------------------------------"
|
||||
done
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把上面脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# sh wget-url-check-1.sh
|
||||
@ -251,9 +221,9 @@ www.xyzzz.com is down
|
||||
----------------------------------
|
||||
```
|
||||
|
||||
### Method-5: How to Quickly Check Whether a Website is up or down Using the lynx Command
|
||||
### 方法 5:使用 lynx 命令检测一个网站是否宕机
|
||||
|
||||
**[lynx][5]** is a highly configurable text-based web browser for use on cursor-addressable character cell terminals. It’s the oldest web browser and it’s still in active development.
|
||||
[lynx][5] 是一个在<ruby>可寻址光标字符单元终端<rt>cursor-addressable character cell terminals</rt></ruby>上使用的基于文本的高度可配的 web 浏览器,它是最古老的 web 浏览器并且现在仍在活跃开发。
|
||||
|
||||
```
|
||||
# lynx -head -dump http://www.magesh.co.in
|
||||
@ -272,14 +242,14 @@ Server: cloudflare
|
||||
CF-RAY: 535fc5704a43e694-LHR
|
||||
```
|
||||
|
||||
Use the following lynx command if you want to see only the HTTP status code instead of entire output.
|
||||
如果你只想看 HTTP 状态码而不是返回的全部结果,用下面的 `lynx` 命令:
|
||||
|
||||
```
|
||||
# lynx -head -dump https://www.magesh.co.in 2>&1 | awk '/HTTP\// {print $2}'
|
||||
200
|
||||
```
|
||||
|
||||
If you want to see if a given website is up or down, use the following Bash script.
|
||||
如果你想看一个网站是否宕机,用下面的 bash 脚本:
|
||||
|
||||
```
|
||||
# vi lynx-url-check.sh
|
||||
@ -292,7 +262,7 @@ else
|
||||
fi
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# sh lynx-url-check.sh
|
||||
@ -301,7 +271,7 @@ HTTP/1.1 200 OK
|
||||
magesh.co.in is up
|
||||
```
|
||||
|
||||
Use the following shell script if you want to see the status of multiple websites.
|
||||
如果你想看多个网站的状态,使用下面的 shell 脚本:
|
||||
|
||||
```
|
||||
# vi lynx-url-check-1.sh
|
||||
@ -318,7 +288,7 @@ echo "----------------------------------"
|
||||
done
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把上面脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# sh lynx-url-check-1.sh
|
||||
@ -333,13 +303,9 @@ www.xyzzz.com is down
|
||||
----------------------------------
|
||||
```
|
||||
|
||||
### Method-6: How to Check if a Website is up or down Using the ping Command
|
||||
### 方法 6:使用 ping 命令检测一个网站是否宕机
|
||||
|
||||
**[ping command][1]** stands for (Packet Internet Groper) command is a networking utility that used to test the target of a host availability/connectivity on an Internet Protocol (IP) network.
|
||||
|
||||
It’s verify a host availability by sending Internet Control Message Protocol (ICMP) Echo Request packets to the target host and waiting for an ICMP Echo Reply.
|
||||
|
||||
It summarize statistical results based on the packets transmitted, packets received, packet loss, typically including the min/avg/max times.
|
||||
[ping 命令][1](Packet Internet Groper)是网络工具的代表,用于在互联网协议(IP)的网络中测试一个目标主机是否可用/可连接。通过向目标主机发送 ICMP 回应请求报文包并等待 ICMP 回应响应报文来检测主机的可用性。它基于已发送的包、接收到的包和丢失了的包来统计结果数据,通常包含最小/平均/最大响应时间。
|
||||
|
||||
```
|
||||
# ping -c 5 2daygeek.com
|
||||
@ -356,15 +322,9 @@ PING 2daygeek.com (104.27.157.177) 56(84) bytes of data.
|
||||
rtt min/avg/max/mdev = 170.668/213.824/250.295/28.320 ms
|
||||
```
|
||||
|
||||
### Method-7: How to Quickly Check Whether a Website is up or down Using the telnet Command
|
||||
### 附加 1:使用 telnet 命令检测一个网站是否宕机
|
||||
|
||||
The Telnet command is an old network protocol used to communicate with another host over a TCP/IP network using the TELNET protocol.
|
||||
|
||||
It uses port 23 to connect to other devices, such as computer and network equipment.
|
||||
|
||||
Telnet is not a secure protocol and is now not recommended to use because the data sent to the protocol is not encrypted and can be intercepted by hackers.
|
||||
|
||||
Everyone uses SSH protocol instead of telnet, which is encrypted and very secure.
|
||||
`telnet` 命令是一个使用 TELNET 协议用于 TCP/IP 网络中多个主机相互通信的古老的网络协议。它通过 23 端口连接其他设备如计算机和网络设备。`telnet` 是不安全的协议,现在由于用这个协议发送的数据没有经过加密可能被黑客拦截,所以不推荐使用。大家都使用经过加密且非常安全的 SSH 协议来代替 `telnet`。
|
||||
|
||||
```
|
||||
# telnet google.com 80
|
||||
@ -377,13 +337,11 @@ telnet> quit
|
||||
Connection closed.
|
||||
```
|
||||
|
||||
### Method-8: How to Check if a Website is up or down Using the Bash Script
|
||||
### 附加 2:使用 bash 脚本检测一个网站是否宕机
|
||||
|
||||
In simple words, a **[shell script][6]** is a file that contains a series of commands. The shell reads this file and executes the commands one by one as they are entered directly on the command line.
|
||||
简而言之,一个 [shell 脚本][6] 就是一个包含一系列命令的文件。shell 从文件读取内容按输入顺序逐行在命令行执行。为了让它更有效,我们添加一些条件。这也减轻了 Linux 管理员的负担。
|
||||
|
||||
To make this more useful we can add some conditions. This reduces the Linux admin task.
|
||||
|
||||
If you want to see the status of multiple websites using the wget command, use the following shell script.
|
||||
如果你想想用 `wget` 命令看多个网站的状态,使用下面的 shell 脚本:
|
||||
|
||||
```
|
||||
# vi wget-url-check-2.sh
|
||||
@ -399,7 +357,7 @@ fi
|
||||
done
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把上面脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# sh wget-url-check-2.sh
|
||||
@ -409,7 +367,7 @@ google.co.in is up
|
||||
www.xyzzz.com is down
|
||||
```
|
||||
|
||||
If you want to see the status of multiple websites using the curl command, use the following **[bash script][7]**.
|
||||
如果你想用 `wget` 命令看多个网站的状态,使用下面的 [shell 脚本][7]:
|
||||
|
||||
```
|
||||
# vi curl-url-check-2.sh
|
||||
@ -425,7 +383,7 @@ fi
|
||||
done
|
||||
```
|
||||
|
||||
Once you have added the above script to a file, run the file to see the output.
|
||||
当你把上面脚本内容添加到一个文件后,执行文件,查看结果:
|
||||
|
||||
```
|
||||
# sh curl-url-check-2.sh
|
||||
@ -441,8 +399,8 @@ via: https://www.2daygeek.com/linux-command-check-website-is-up-down-alive/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,136 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (hopefully2333)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11699-1.html)
|
||||
[#]: subject: (How internet security works: TLS, SSL, and CA)
|
||||
[#]: via: (https://opensource.com/article/19/11/internet-security-tls-ssl-certificate-authority)
|
||||
[#]: author: (Bryant Son https://opensource.com/users/brson)
|
||||
|
||||
互联网的安全是如何保证的:TLS、SSL 和 CA
|
||||
======
|
||||
|
||||
> 你的浏览器里的锁的图标的后面是什么?
|
||||
|
||||
![Lock][1]
|
||||
|
||||
每天你都会重复这件事很多次,访问网站,网站需要你用你的用户名或者电子邮件地址和你的密码来进行登录。银行网站、社交网站、电子邮件服务、电子商务网站和新闻网站。这里只在使用了这种机制的网站中列举了其中一小部分。
|
||||
|
||||
每次你登录进一个这种类型的网站时,你实际上是在说:“是的,我信任这个网站,所以我愿意把我的个人信息共享给它。”这些数据可能包含你的姓名、性别、实际地址、电子邮箱地址,有时候甚至会包括你的信用卡信息。
|
||||
|
||||
但是你怎么知道你可以信任这个网站?换个方式问,为了让你可以信任它,网站应该如何保护你的交易?
|
||||
|
||||
本文旨在阐述使网站变得安全的机制。我会首先论述 web 协议 http 和 https,以及<ruby>传输层安全<rt>Transport Layer Security</rt></ruby>(TLS)的概念,后者是<ruby>互联网协议<rt>Internet Protocol</rt></ruby>(IP)层中的加密协议之一。然后,我会解释<ruby>证书颁发机构<rt>certificate authority</rt></ruby>和自签名证书,以及它们如何帮助保护一个网站。最后,我会介绍一些开源的工具,你可以使用它们来创建和管理你的证书。
|
||||
|
||||
### 通过 https 保护路由
|
||||
|
||||
了解一个受保护的网站的最简单的方式就是在交互中观察它,幸运的是,在今天的互联网上,发现一个安全的网站远远比找到一个不安全的网站要简单。但是,因为你已经在 Opensource.com 这个网站上了,我会使用它来作为案例,无论你使用的是哪个浏览器,你应该在你的地址栏旁边看到一个像锁一样的图标。点击这个锁图标,你应该会看见一些和下面这个类似的东西。
|
||||
|
||||
![Certificate information][2]
|
||||
|
||||
默认情况下,如果一个网站使用的是 http 协议,那么它是不安全的。为通过网站主机的路由添加一个配置过的证书,可以把这个网站从一个不安全的 http 网站变为一个安全的 https 网站。那个锁图标通常表示这个网站是受 https 保护的。
|
||||
|
||||
点击证书来查看网站的 CA,根据你的浏览器,你可能需要下载证书来查看它。
|
||||
|
||||
![Certificate information][3]
|
||||
|
||||
在这里,你可以了解有关 Opensource.com 证书的信息。例如,你可以看到 CA 是 DigiCert,并以 Opensource.com 的名称提供给 Red Hat。
|
||||
|
||||
这个证书信息可以让终端用户检查该网站是否可以安全访问。
|
||||
|
||||
> 警告:如果你没有在网站上看到证书标志,或者如果你看见的标志显示这个网站不安全——请不要登录或者做任何需要你个人数据的操作。这种情况非常危险!
|
||||
|
||||
如果你看到的是警告标志,对于大多数面向公众开放的网站来说,这很少见,它通常意味着该证书已经过期或者是该证书是自签名的,而非通过一个受信任的第三方来颁发。在我们进入这些主题之前,我想解释一下 TLS 和 SSL。
|
||||
|
||||
### 带有 TLS 和 SSL 的互联网协议
|
||||
|
||||
TLS 是旧版<ruby>安全套接字层协议<rt>Secure Socket Layer</rt></ruby>(SSL)的最新版本。理解这一点的最好方法就是仔细理解互联网协议的不同协议层。
|
||||
|
||||
![IP layers][4]
|
||||
|
||||
我们知道当今的互联网是由 6 个层面组成的:物理层、数据链路层、网络层、传输层、安全层、应用层。物理层是基础,这一层是最接近实际的硬件设备的。应用层是最抽象的一层,是最接近终端用户的一层。安全层可以被认为是应用层的一部分,TLS 和 SSL,是被设计用来在一个计算机网络中提供通信安全的加密协议,它们位于安全层中。
|
||||
|
||||
这个过程可以确保终端用户使用网络服务时,通信的安全性和保密性。
|
||||
|
||||
### 证书颁发机构和自签名证书
|
||||
|
||||
<ruby>证书颁发机构<rt>Certificate authority</rt></ruby>(CA)是受信任的组织,它可以颁发数字证书。
|
||||
|
||||
TLS 和 SSL 可以使连接更安全,但是这个加密机制需要一种方式来验证它;这就是 SSL/TLS 证书。TLS 使用了一种叫做非对称加密的加密机制,这个机制有一对称为私钥和公钥的安全密钥。(这是一个非常复杂的主题,超出了本文的讨论范围,但是如果你想去了解这方面的东西,你可以阅读“[密码学和公钥密码基础体系简介][5]”)你要知道的基础内容是,证书颁发机构们,比如 GlobalSign、DigiCert 和 GoDaddy,它们是受人们信任的可以颁发证书的供应商,它们颁发的证书可以用于验证网站使用的 TLS/SSL 证书。网站使用的证书是导入到主机服务器里的,用于保护网站。
|
||||
|
||||
然而,如果你只是要测试一下正在开发中的网站或服务,CA 证书可能对你而言太昂贵或者是太复杂了。你必须有一个用于生产目的的受信任的证书,但是开发者和网站管理员需要有一种更简单的方式来测试网站,然后他们才能将其部署到生产环境中;这就是自签名证书的来源。
|
||||
|
||||
自签名证书是一种 TLS/SSL 证书,是由创建它的人而非受信任的 CA 机构颁发的。用电脑生成一个自签名证书很简单,它可以让你在无需购买昂贵的 CA 颁发的证书的情况下测试一个安全网站。虽然自签名证书肯定不能拿到生产环境中去使用,但对于开发和测试阶段来说,这是一种简单灵活的方法。
|
||||
|
||||
### 生成证书的开源工具
|
||||
|
||||
有几种开源工具可以用来管理 TLS/SSL 证书。其中最著名的就是 openssl,这个工具包含在很多 Linux 发行版中和 MacOS 中。当然,你也可以使用其他开源工具。
|
||||
|
||||
| 工具名 | 描述 | 许可证 |
|
||||
| --------- | ------------------------------------------------------------------------------ | --------------------------------- |
|
||||
| [OpenSSL][7] | 实现 TLS 和加密库的最著名的开源工具 | Apache License 2.0 |
|
||||
| [EasyRSA][8] | 用于构建 PKI CA 的命令行实用工具 | GPL v2 |
|
||||
| [CFSSL][9] | 来自 cloudflare 的 PKI/TLS 瑞士军刀 | BSD 2-Clause "Simplified" License |
|
||||
| [Lemur][10] | 来自<ruby>网飞<rt>Netflix</rt></ruby>的 TLS 创建工具 | Apache License 2.0 |
|
||||
|
||||
如果你的目的是扩展和对用户友好,网飞的 Lemur 是一个很有趣的选择。你在[网飞的技术博客][6]上可以查看更多有关它的信息。
|
||||
|
||||
### 如何创建一个 Openssl 证书
|
||||
|
||||
你可以靠自己来创建证书,下面这个案例就是使用 Openssl 生成一个自签名证书。
|
||||
|
||||
1、使用 `openssl` 命令行生成一个私钥:
|
||||
|
||||
```
|
||||
openssl genrsa -out example.key 2048
|
||||
```
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/4_openssl_generatekey.jpg)
|
||||
|
||||
2、使用在第一步中生成的私钥来创建一个<ruby>证书签名请求<rt>certificate signing request</rt></ruby>(CSR):
|
||||
|
||||
```
|
||||
openssl req -new -key example.key -out example.csr -subj "/C=US/ST=TX/L=Dallas/O=Red Hat/OU=IT/CN=test.example.com"
|
||||
```
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/5_openssl_generatecsr.jpg)
|
||||
|
||||
3、使用你的 CSR 和私钥创建一个证书:
|
||||
|
||||
```
|
||||
openssl x509 -req -days 366 -in example.csr -signkey example.key -out example.crt
|
||||
```
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/6_openssl_generatecert.jpg)
|
||||
|
||||
### 了解更多关于互联网安全的知识
|
||||
|
||||
如果你想要了解更多关于互联网安全和网站安全的知识,请看我为这篇文章一起制作的 Youtube 视频。
|
||||
|
||||
- <https://youtu.be/r0F1Hlcmjsk>
|
||||
|
||||
你有什么问题?发在评论里让我们知道。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/internet-security-tls-ssl-certificate-authority
|
||||
|
||||
作者:[Bryant Son][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[hopefully2333](https://github.com/hopefully2333)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/brson
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/security-lock-password.jpg?itok=KJMdkKum
|
||||
[2]: https://opensource.com/sites/default/files/uploads/1_certificatecheckwebsite.jpg
|
||||
[3]: https://opensource.com/sites/default/files/uploads/2_certificatedisplaywebsite.jpg
|
||||
[4]: https://opensource.com/sites/default/files/uploads/3_internetprotocol.jpg
|
||||
[5]: https://opensource.com/article/18/5/cryptography-pki
|
||||
[6]: https://medium.com/netflix-techblog/introducing-lemur-ceae8830f621
|
||||
[7]: https://www.openssl.org/
|
||||
[8]: https://github.com/OpenVPN/easy-rsa
|
||||
[9]: https://github.com/cloudflare/cfssl
|
||||
[10]: https://github.com/Netflix/lemur
|
@ -0,0 +1,138 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "hello-wn"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-11644-1.html"
|
||||
[#]: subject: "Top 10 Vim plugins for programming in multiple languages"
|
||||
[#]: via: "https://opensource.com/article/19/11/vim-plugins"
|
||||
[#]: author: "Maxim Burgerhout https://opensource.com/users/wzzrd"
|
||||
|
||||
多语言编程必备的十大 Vim 插件
|
||||
======
|
||||
|
||||
> 使用这 10 个 Vim 插件,可以让你在写代码或运维时,感觉更棒。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/05/062256bnauidfsf7155d1n.jpeg)
|
||||
|
||||
我使用 [Vim][2] 文本编辑器大约 20 年了。有一段时间,我一直在定制我的 Vim 配置,但在只有在最近两年我才会使用插件。
|
||||
|
||||
最近,当我重新安装系统时(就像我经常做的那样),我觉得这是一次好的机会,我想找出多种编程语言环境下的最佳 Vim 插件,以及如何将这些插件和每种语言结合起来。
|
||||
|
||||
有时,我会为特定的语言和配置使用特定的插件(例如,我只在 Ansible 配置中安装 Rocannon),在此不细讲了。不过下面介绍的 10 个 Vim 插件都是我的最爱,无论使用哪种编程语言,我几乎都会使用它们。
|
||||
|
||||
### 1、Volt
|
||||
|
||||
我的首选并不是一个插件,但是它可以替换类似于 [Vundle][3] 的插件,所以在此介绍。
|
||||
|
||||
[Volt][4] 是一个不依存于 Vim 的 Vim 插件管理器。你可以用它安装插件,并创建名为“profile”的插件组合。你可以使用一个简单的命令 `volt profile set myprofile` 启用新的配置。这样我可以做到这样的事情,如为 Python 配置单独启用 [indentpython][5] 插件。Volt 还提供了一种针对每个插件配置的简单方法,这些配置会在“profile”之间共享,因此只需要安装一次插件,就可以在多个“profile”之间使用。
|
||||
|
||||
Volt 还是相对较新且不够完美(比如,不管你想要使用多少个“profile”,每个插件只能有一个配置文件),但除此之外,我发现它非常方便、快速和简单。
|
||||
|
||||
![Volt plugin][6]
|
||||
|
||||
### 2、Vim-Rainbow
|
||||
|
||||
除了 Python,几乎所有的主流编程语言都使用括号(小括号、方括号和大括号)。通常,它们会嵌套使用多对括号,因此很难搞清楚某个括号的开闭区间。我发现自己经常要数小括号,尤其是在复杂的 Bash 脚本中,以确保无误。
|
||||
|
||||
这时候就需要 [vim-rainbow][7] 插件!它为每对括号设置不同的颜色,因此很容易识别出哪些括号是一对括号。它非常有用而且五彩斑斓。
|
||||
|
||||
![vim-rainbow plugin][8]
|
||||
|
||||
### 3、lightline
|
||||
|
||||
Vim 有很多这种插件,例如 [Powerline][9],它会在底部栏显示你正在处理的文件、光标所在的文件位置以及文件类型等信息。这些插件各有利弊,在简单比较后,我选择了 [lightline][10]。它相对较小,便于安装和扩展,并且不依赖于其他工具或插件。
|
||||
|
||||
![Lightline plugin][11]
|
||||
|
||||
### 4、NERDTree
|
||||
|
||||
[NERDTree][12] 是一个很经典的插件。在大型项目中,你可能很难找到想要编辑的内容所在文件的确切名称和路径。使用快捷键(我使用的是 `F7`,因为我在 `.vimrc` 中配置了这个快捷键),搜索窗会以垂直分屏的方式打开,就可以轻松找到所需文件并打开它。对于大型项目,这是必备插件。对于那些经常忘记文件名的人也很有用,比如我。
|
||||
|
||||
![NERDTree vim plugin][13]
|
||||
|
||||
### 5、NERD Commenter
|
||||
|
||||
程序员们在写代码时,有时会遇到一些难以调试的问题,导致他们想要注释或不执行某段代码。这时候就需要 [NERD Commenter][14] 出场了。选择代码段,按 `Leader 键 + cc`,代码就会被注释掉。(标准的 Vim Leader 键 是 `/` 字符。)按 `Leader 键 + cn`,取消注释。对于大多数文件类型,NERD Commenter 会自动使用正确的注释符。例如,如果你正在编辑 [BIND 区域文件][15],并将文件类型设置为 BIND 区域文件,Vim 会正确地使用 `;`(分号)字符进行注释。
|
||||
|
||||
![NERD Commenter][16]
|
||||
|
||||
### 6、Solarized
|
||||
|
||||
我喜欢我的 Vim 主题配色。我也喜欢终端的主题色。我一直在 Vim 上使用 [Solarized][17] 配色,并且将我的终端、文件夹配色和 Vim 设为一致。
|
||||
|
||||
但是,有时我会根据周边环境、屏幕亮度以及是否需要分享投屏,来切换明暗模式。
|
||||
|
||||
显然,你可以选择自己喜欢的任何配色方案,但我喜欢 `Solarized`,因为它有明暗模式功能,它可以简单快捷地切换两种模式。我的第二个选择是 [Monokai][18]。Volt 插件管理器让我可以轻松地在两者之间切换,因此我在 Python 编程时,使用 Monokai;Bash 编程时,使用 Solarized。
|
||||
|
||||
我没有给 Solarized 找相应的图片,因为本文中的所有其他图片都使用了 Solarized 中的浅色或深色效果,可以确认一下这些图片。
|
||||
|
||||
### 7、fzf
|
||||
|
||||
当寻找一个文件时,有时你想要一个文件浏览器,有时你只想在键盘上敲打出与文件名模糊匹配的内容,对吗?
|
||||
|
||||
[fzf][19](全称 “模糊查找器”)插件提供了这一功能。打出 `:FZF` 并输入文件名内容。不断缩短的列表将显示出与你输入的文件名内容相匹配的一些文件。我经常使用它,最近使用它的频率估计比使用 NERDTree 还多。缺点是这个插件依赖于 `fzf binary`,因此也必须安装这个依赖包。它适用于 Fedora、Debian 和 Arch,据我所知并不在 EPEL 中。
|
||||
|
||||
![fzf Vim plugin][20]
|
||||
|
||||
### 8、ack
|
||||
|
||||
有时,你需要搜索包含特定行或特定单词的文件。我真的很喜欢使用 [ack][21] 插件,最好与 `ag` 结合使用,它俩的组合又被称为 “[silver searcher][22]”。这一组合的速度非常快,覆盖了 `grep` 或 `vimgrep` 的绝大多数使用场景。缺点是你需要安装 `ack` 或 `ag` 才能正常运行。好消息是 Fedora 和 EPEL7 都可以使用 `ag` 和 `ack`。
|
||||
|
||||
![ack vim plugin][23]
|
||||
|
||||
### 9、gitgutter
|
||||
|
||||
大多数 IT 人员都使用 [Git][24] 和 Git 仓库中的文件进行工作。[gitgutter][25] 插件在行号附近添加了一列,通过符号显示该行的状态为:已更改(`~`)、已添加(`+`)或者已删除(`-`)。这有利于跟踪你所做的更改,并且可以使你专注于手头的任务,例如编写补丁来修复一个关键错误。
|
||||
|
||||
![gitgutter vim plugin][26]
|
||||
|
||||
### 10、Tag List
|
||||
|
||||
如果你在一个很大的文件中编写代码,会很容易忘记当前所在的位置,你可能需要上下滚动来查找某个功能。使用 [Tag List][27] 插件,只需要输入 `:Tlist`,就能垂直分屏显示出包含变量、类型、类和函数的代码,你可以轻松跳转到这些变量、类型、类和函数。这个功能对于多语言同样适用,例如 Java、Python 以及任何能够使用 `ctags` 功能的文件类型。
|
||||
|
||||
![Tag List vim plugin][28]
|
||||
|
||||
以上介绍的 10 个 Vim 插件使我作为系统管理员和兼职程序员的生活变得更轻松。你正在使用哪些 Vim 插件?请在评论中分享你最爱的插件。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/vim-plugins
|
||||
|
||||
作者:[Maxim Burgerhout][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[hello-wn][c]
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/wzzrd
|
||||
[b]: https://github.com/lujun9972
|
||||
[c]: https://github.com/hello-wn
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/openstack_python_vim_1.jpg?itok=lHQK5zpm "OpenStack source code (Python) in VIM"
|
||||
[2]: https://www.vim.org/
|
||||
[3]: https://github.com/VundleVim/Vundle.vim
|
||||
[4]: https://github.com/vim-volt/volt
|
||||
[5]: https://github.com/vim-scripts/indentpython.vim
|
||||
[6]: https://opensource.com/sites/default/files/uploads/vim-volt.gif "Volt plugin"
|
||||
[7]: http://github.com/frazrepo/vim-rainbow
|
||||
[8]: https://opensource.com/sites/default/files/uploads/vim-rainbox.png "vim-rainbow plugin"
|
||||
[9]: https://github.com/powerline/powerline
|
||||
[10]: http://github.com/itchyny/lightline.vim
|
||||
[11]: https://opensource.com/sites/default/files/uploads/lightline.png "Lightline plugin"
|
||||
[12]: http://github.com/scrooloose/nerdtree
|
||||
[13]: https://opensource.com/sites/default/files/uploads/nerdtree.gif "NERDTree vim plugin"
|
||||
[14]: http://github.com/scrooloose/nerdcommenter
|
||||
[15]: https://en.wikipedia.org/wiki/Zone_file#File_format
|
||||
[16]: https://opensource.com/sites/default/files/uploads/nerdcommenter.gif "NERD Commenter"
|
||||
[17]: https://github.com/altercation/vim-colors-solarized
|
||||
[18]: https://github.com/sickill/vim-monokai
|
||||
[19]: https://github.com/junegunn/fzf.vim
|
||||
[20]: https://opensource.com/sites/default/files/uploads/fzf.gif "fzf Vim plugin"
|
||||
[21]: https://github.com/mileszs/ack.vim
|
||||
[22]: https://github.com/ggreer/the_silver_searcher
|
||||
[23]: https://opensource.com/sites/default/files/uploads/ack.gif "ack vim plugin"
|
||||
[24]: https://opensource.com/resources/what-is-git
|
||||
[25]: https://github.com/airblade/vim-gitgutter
|
||||
[26]: https://opensource.com/sites/default/files/uploads/gitgutter.png "gitgutter vim plugin"
|
||||
[27]: https://github.com/vim-scripts/taglist.vim
|
||||
[28]: https://opensource.com/sites/default/files/uploads/taglist.gif "Tag List vim plugin) ) ) "
|
@ -0,0 +1,105 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11629-1.html)
|
||||
[#]: subject: (Switching from Python 2 to Python 3: What you need to know)
|
||||
[#]: via: (https://opensource.com/article/19/11/end-of-life-python-2)
|
||||
[#]: author: (Katie McLaughlin https://opensource.com/users/glasnt)
|
||||
|
||||
从 Python 2 切换到 Python 3 你所需要了解的
|
||||
======
|
||||
|
||||
> Python 2 将在几周内走到生命终点,这篇文章是你迁移到 Python 3 之前应该知道的。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/01/095336lbppn8qp1nnnwqqp.jpg)
|
||||
|
||||
从 2020 年 1 月 1 日开始,Python 2.7 将不再得到正式支持。在此日期之后,将会发布一个[最终错误修复][2]计划,但是仅此而已。
|
||||
|
||||
Python 2 的生命终点(EOL)对你意味着什么?如果正在运行着 Python 2,你需要迁移。
|
||||
|
||||
### 是谁决定 Python 2 的生命终点?
|
||||
|
||||
在 [2012][3] 年,维护 Python 编程语言的团队审查了其选项。有两个越来越不同的代码库,Python 2 和 Python 3。这两者都很流行,但是较新的版本并未得到广泛采用。
|
||||
|
||||
除了 Python 3 中完全重写的 Unicode 支持改变了处理数据的底层方式造成的断层,这个主要版本的变化还一次性出现了一些非向后兼容的更改。这种断层的决定成文于 [2006 年][4]。为了减轻该断层的影响,Python 2 继续保持了维护,并向后移植了一些 Python 3 的功能。为了进一步帮助社区过渡,EOL 日期[从 2015 年延长至 2020 年][5],又延长了五年。
|
||||
|
||||
该团队知道,维护不同的代码库是必须解决的麻烦。最终,他们[宣布了][6]一项决定:
|
||||
|
||||
>“我们是制作和照料 Python 编程语言的志愿者。我们已决定 2020 年 1 月 1 日将是我们停止使用 Python 2 的日子。这意味着在这一天之后,即使有人发现其中存在安全问题,我们也将不再对其进行改进。你应尽快升级到 Python 3。”
|
||||
|
||||
[Nick Coghlan][7] 是 CPython 的核心开发人员,也是 Python 指导委员会的现任成员,[在他的博客中添加了更多信息][8]。由 [Barry Warsaw][10](也是 Python 指导委员会的成员)撰写的 [PEP 404][9] 详细说明了 Python 2.8 永远不会面世的原因。
|
||||
|
||||
### 有人还在支持 Python 2 吗?
|
||||
|
||||
提供者和供应商对 Python 2 的支持会有所不同。[Google Cloud 宣布了][11]它计划未来如何支持 Python 2。红帽还[宣布了红帽企业 Linux(RHEL)的计划][12],而 AWS 宣布了 AWS 命令行界面和 [SDK][14] 的[次要版本更新要求][13]。
|
||||
|
||||
你还可以阅读 [Vicki Boykis][16] 在 Stack Overflow 撰写的博客文章“[为什么迁移到 Python 3 需要这么长时间?][15]”,其中她指出了采用 Python 3 缓慢的三个原因。
|
||||
|
||||
### 使用 Python 3 的原因
|
||||
|
||||
不管是否有持续的支持,尽快迁移到 Python 3 是一个好主意。Python 3 将继续受到支持,它具有 Python 2 所没有的一些非常优雅的东西。
|
||||
|
||||
最近发布的 [Python 3.8][17] 包含 [海象运算符][19]、[位置参数][20]和[自描述的格式化字符串][21]等[功能][18]。Python 3 的早期版本引入的[功能][22],例如 [异步 IO][23]、[格式化字符串][24]、[类型提示][25] 和 [pathlib][26],这里只提及了一点点。
|
||||
|
||||
下载最多的前 360 个软件包[已迁移到 Python 3][27]。你可以使用 [caniusepython3][28] 软件包检查你的 `requirements.txt` 文件,以查看你依赖的任何软件包是否尚未迁移。
|
||||
|
||||
### 将 Python 2 移植到 Python 3 的参考资源
|
||||
|
||||
有许多参考资源可简化你向 Python 3 的迁移。例如,“[将 Python 2 移植到 Python 3 指南][29]”列出了许多工具和技巧,可帮助你实现与 Python 2/3 单一源代码的兼容性。在 [Python3statement.org][30] 上也有一些有用的技巧。
|
||||
|
||||
[Dustin Ingram][31] 和 [Chris Wilcox][32] 在 [Cloud Next '19][33]上作了一个演讲,详细介绍了向 Python 3 过渡的一些动机和迁移模式。[Trey Hunner][34] 在 [PyCon 2018 演讲][35]上介绍了 Python 3 最有用的功能,鼓励你进行迁移,以便你可以利用它们。
|
||||
|
||||
### 加入我们!
|
||||
|
||||
距 2020 年 1 月 1 日仅有几周了。如果你需要每天提醒一下它即将到来的时间(并且你使用 Twitter 的话),请关注 [Python 2 日落倒计时][36] Twitter 机器人。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/end-of-life-python-2
|
||||
|
||||
作者:[Katie McLaughlin][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/glasnt
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/govt_a%20new%20dawn.png?itok=b4zU-VAY (A sunrise)
|
||||
[2]: https://www.python.org/dev/peps/pep-0373/#maintenance-releases
|
||||
[3]: https://github.com/python/peps/commit/a733bc927acbca16bfa3de486fb2c7d3f767a748
|
||||
[4]: https://www.python.org/dev/peps/pep-3000/#compatibility-and-transition
|
||||
[5]: https://github.com/python/peps/commit/f82462002b86feff36215b4230be28967039b0cc
|
||||
[6]: https://www.python.org/doc/sunset-python-2/
|
||||
[7]: https://twitter.com/ncoghlan_dev
|
||||
[8]: http://python-notes.curiousefficiency.org/en/latest/python3/questions_and_answers.html
|
||||
[9]: https://www.python.org/dev/peps/pep-0404/
|
||||
[10]: https://twitter.com/pumpichank
|
||||
[11]: https://cloud.google.com/python/docs/python2-sunset/?utm_source=osdc&utm_medium=blog&utm_campaign=pysunset
|
||||
[12]: https://access.redhat.com/solutions/4455511
|
||||
[13]: https://aws.amazon.com/blogs/developer/deprecation-of-python-2-6-and-python-3-3-in-botocore-boto3-and-the-aws-cli/
|
||||
[14]: https://aws.amazon.com/sdk-for-python/
|
||||
[15]: https://stackoverflow.blog/2019/11/14/why-is-the-migration-to-python-3-taking-so-long/
|
||||
[16]: https://twitter.com/vboykis
|
||||
[17]: https://www.python.org/downloads/
|
||||
[18]: https://docs.python.org/3.8/whatsnew/3.8.html
|
||||
[19]: https://docs.python.org/3.8/whatsnew/3.8.html#assignment-expressions
|
||||
[20]: https://docs.python.org/3.8/whatsnew/3.8.html#positional-only-parameters
|
||||
[21]: https://docs.python.org/3.8/whatsnew/3.8.html#f-strings-support-for-self-documenting-expressions-and-debugging
|
||||
[22]: https://docs.python.org/3.8/whatsnew/index.html
|
||||
[23]: https://docs.python.org/3.8/library/asyncio.html#module-asyncio
|
||||
[24]: https://docs.python.org/3.7/whatsnew/3.6.html#pep-498-formatted-string-literals
|
||||
[25]: https://docs.python.org/3.7/whatsnew/3.5.html#pep-484-type-hints
|
||||
[26]: https://docs.python.org/3.8/library/pathlib.html#module-pathlib
|
||||
[27]: http://py3readiness.org/
|
||||
[28]: https://pypi.org/project/caniusepython3/
|
||||
[29]: https://docs.python.org/3/howto/pyporting.html
|
||||
[30]: https://python3statement.org/practicalities/
|
||||
[31]: https://twitter.com/di_codes
|
||||
[32]: https://twitter.com/chriswilcox47
|
||||
[33]: https://www.youtube.com/watch?v=Bye7Rms0Vgw&utm_source=osdc&utm_medium=blog&utm_campaign=pysunset
|
||||
[34]: https://twitter.com/treyhunner
|
||||
[35]: https://www.youtube.com/watch?v=klaGx9Q_SOA
|
||||
[36]: https://twitter.com/python2sunset
|
@ -1,69 +1,63 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Bash Script to View System Information on Linux Every Time You Log into Shell)
|
||||
[#]: via: (https://www.2daygeek.com/bash-shell-script-view-linux-system-information/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "lxbwolf"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-11645-1.html"
|
||||
[#]: subject: "Bash Script to View System Information on Linux Every Time You Log into Shell"
|
||||
[#]: via: "https://www.2daygeek.com/bash-shell-script-view-linux-system-information/"
|
||||
[#]: author: "Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/"
|
||||
|
||||
Bash Script to View System Information on Linux Every Time You Log into Shell
|
||||
Bash 脚本实现每次登录到 Shell 时可以查看 Linux 系统信息
|
||||
======
|
||||
|
||||
There are several commands in Linux to obtain system information such as processor information, manufacturer name, and serial number, etc,.
|
||||
Linux 中有很多可以查看系统信息如处理器信息、生产商名字、序列号等的命令。你可能需要执行多个命令来收集这些信息。同时,记住所有的命令和他们的选项也是有难度。
|
||||
|
||||
You may need to run several commands to collect this information.
|
||||
你可以写一个 [shell 脚本](https://www.2daygeek.com/category/shell-script/) 基于你的需求来自定义显示的信息。
|
||||
|
||||
Also, it is very difficult to remember all the commands and their options.
|
||||
以前我们出于不同的目的需要写很多个 [bash 脚本](https://www.2daygeek.com/category/bash-script/)。
|
||||
|
||||
Instead you can write a **[shell script][1]** to customize the output based on your needs.
|
||||
现在我们写一个新的 shell 脚本,在每次登录到 shell 时显示需要的系统信息。
|
||||
|
||||
In the past we have written many **[bash scripts][2]** for a variety of purposes.
|
||||
这个j脚本有 6 部分,细节如下:
|
||||
|
||||
Today, we came up with a new shell script, which shows you the required system information every time you log into the shell.
|
||||
1. 通用系统信息
|
||||
2. CPU/内存当前使用情况
|
||||
3. 硬盘使用率超过 80%
|
||||
4. 列出系统 WWN 详情
|
||||
5. Oracle DB 实例
|
||||
6. 可更新的包
|
||||
|
||||
There are six parts to this script, and more details below.
|
||||
我们已经基于我们的需求把可能需要到的信息加到了每个部分。之后你可以基于自己的意愿修改这个脚本。
|
||||
|
||||
* **Part-1:** General System Information
|
||||
* **Part-2:** CPU/Memory Current Usage
|
||||
* **Part-3:** Disk Usage >80%
|
||||
* **Part-4:** List System WWN Details
|
||||
* **Part-5:** Oracle DB Instances
|
||||
* **Part-6:** Available Package Updates
|
||||
这个j脚本需要用到很多工具,其中大部分我们之前已经涉及到了。
|
||||
|
||||
你可以参照以前文章,了解工具详情。
|
||||
|
||||
* [inxi – 在 Linux 上检查硬件信息的绝佳工具][3]
|
||||
* [Dmidecode – 获取 Linux 系统硬件信息的简便方法][4]
|
||||
* [LSHW(硬件列表程序)– 在 Linux 上获取硬件信息的漂亮工具][5]
|
||||
* [hwinfo(硬件信息)– 在 Linux 上检测系统硬件信息的漂亮工具][6]
|
||||
* [python-hwinfo:使用标准 Linux 实用工具显示硬件信息摘要][7]
|
||||
* [如何使用 lspci、lsscsi、lsusb 和 lsblk 获取 Linux 系统设备信息][8]
|
||||
* [如何在 Linux 中检查系统硬件制造商、型号和序列号][9]
|
||||
* [如何在 Linux 中查找 HBA 卡的 WWN、WWNN 和 WWPN 号][10]
|
||||
* [如何从 Linux 命令行检查 HP iLO 固件版本][11]
|
||||
* [如何从 Linux 命令行检查无线网卡和 WiFi 信息][12]
|
||||
* [如何在 Linux 上检查 CPU 和硬盘温度][13]
|
||||
* [Hegemon – Linux 的模块化系统和硬件监视工具][14]
|
||||
* [如何在 Linux 上检查系统配置和硬件信息][15]
|
||||
|
||||
We’ve added potential information to each area based on our needs. You can further customize this script to your needs if you wish.
|
||||
如果你想为这个脚本增加其他的信息,请在评论去留下你的需求,以便我们帮助你。
|
||||
|
||||
There are many tools for this, most of which we have already covered.
|
||||
### Bash 脚本实现每次登录到 Shell 时可以查看 Linux 系统信息
|
||||
|
||||
To read them, go to the following articles.
|
||||
|
||||
* **[inxi – A Great Tool to Check Hardware Information on Linux][3]**
|
||||
* **[Dmidecode – Easy Way To Get Linux System Hardware Information][3]**
|
||||
* **[LSHW (Hardware Lister) – A Nifty Tool To Get A Hardware Information On Linux][3]**
|
||||
* **[hwinfo (Hardware Info) – A Nifty Tool To Detect System Hardware Information On Linux][3]**
|
||||
* **[python-hwinfo : Display Summary Of Hardware Information Using Standard Linux Utilities][3]**
|
||||
* **[How To Use lspci, lsscsi, lsusb, And lsblk To Get Linux System Devices Information][3]**
|
||||
* **[How To Check System Hardware Manufacturer, Model And Serial Number In Linux][3]**
|
||||
* **[How To Find WWN, WWNN and WWPN Number Of HBA Card In Linux][3]**
|
||||
* **[How to check HP iLO Firmware version from Linux command line][3]**
|
||||
* **[How to check Wireless network card and WiFi information from Linux Command Line][3]**
|
||||
* **[How to check CPU & Hard Disk temperature on Linux][3]**
|
||||
* **[Hegemon – A modular System & Hardware monitoring tool for Linux][3]**
|
||||
* **[How to Check System Configuration and Hardware Information on Linux][3]**
|
||||
|
||||
|
||||
|
||||
If anyone wants to add any other information in the script, please let us know your requirements in the comment section so that we can help you.
|
||||
|
||||
### Bash Script to View System Information on Linux Every Time You Log into the Shell
|
||||
|
||||
This basic script will bring the system information to your terminal whenever you log into the shell.
|
||||
这个脚本会在你每次登录 shell 时把系统信息打印到 terminal。
|
||||
|
||||
```
|
||||
#vi /opt/scripts/system-info.sh
|
||||
# vi /opt/scripts/system-info.sh
|
||||
```
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
echo -e "-------------------------------System Information----------------------------"
|
||||
echo -e "Hostname:\t\t"`hostname`
|
||||
@ -90,12 +84,12 @@ df -Ph | sed s/%//g | awk '{ if($5 > 80) print $0;}'
|
||||
echo ""
|
||||
|
||||
echo -e "-------------------------------For WWN Details-------------------------------"
|
||||
vserver=$(lscpu | grep vendor | wc -l)
|
||||
vserver=$(lscpu | grep Hypervisor | wc -l)
|
||||
if [ $vserver -gt 0 ]
|
||||
then
|
||||
echo "$(hostname) is a VM"
|
||||
else
|
||||
systool -c fc_host -v | egrep "(Class Device path | port_name |port_state)" > systool.out
|
||||
cat /sys/class/fc_host/host?/port_name
|
||||
fi
|
||||
echo ""
|
||||
|
||||
@ -120,41 +114,37 @@ echo -e "-----------------------------------------------------------------------
|
||||
fi
|
||||
```
|
||||
|
||||
Once the above script is added to a file. Set the executable permission for the “system-info.sh” file.
|
||||
把上面脚本内容保存到一个文件 `system-info.sh`,之后添加可执行权限:
|
||||
|
||||
```
|
||||
# chmod +x ~root/system-info.sh
|
||||
```
|
||||
|
||||
When the script is ready, add the file path at the end of the “.bash_profile” file in RHEL-based systems CentOS, Oracle Linux and Fedora.
|
||||
当脚本准备好后,把脚本文件的路径加到 `.bash_profile` 文件末尾(红帽系列的系统:CentOS、Oracle Linux 和 Fedora):
|
||||
|
||||
```
|
||||
# echo "/root/system-info.sh" >> ~root/.bash_profile
|
||||
```
|
||||
|
||||
To take this change effect, run the following command.
|
||||
执行以下命令,来让修改的内容生效:
|
||||
|
||||
```
|
||||
# source ~root/.bash_profile
|
||||
```
|
||||
|
||||
For Debian-based systems, you may need to add a file path to the “.profile” file.
|
||||
对于 Debian 系统的系统,你可能需要把文件路径加到 `.profile` 文件中:
|
||||
|
||||
```
|
||||
# echo "/root/system-info.sh" >> ~root/.profile
|
||||
```
|
||||
|
||||
Run the following command to take this change effect.
|
||||
运行以下命令使修改生效:
|
||||
|
||||
```
|
||||
# source ~root/.profile
|
||||
```
|
||||
|
||||
You may have seen an output like the one below when running the above “source” command.
|
||||
|
||||
From next time on-wards, you will get this information every time you log into the shell.
|
||||
|
||||
Alternatively, you can manually run this script at any time if you need to.
|
||||
你以前运行上面 `source` 命令时可能见过类似下面的输出。从下次开始,你在每次登录 shell 时会看到这些信息。当然,如果有必要你也可以随时手动执行这个脚本。
|
||||
|
||||
```
|
||||
-------------------------------System Information---------------------------
|
||||
@ -206,8 +196,8 @@ via: https://www.2daygeek.com/bash-shell-script-view-linux-system-information/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -216,3 +206,15 @@ via: https://www.2daygeek.com/bash-shell-script-view-linux-system-information/
|
||||
[1]: https://www.2daygeek.com/category/shell-script/
|
||||
[2]: https://www.2daygeek.com/category/bash-script/
|
||||
[3]: https://www.2daygeek.com/inxi-system-hardware-information-on-linux/
|
||||
[4]: https://www.2daygeek.com/dmidecode-get-print-display-check-linux-system-hardware-information/
|
||||
[5]: https://www.2daygeek.com/lshw-find-check-system-hardware-information-details-linux/
|
||||
[6]: https://www.2daygeek.com/hwinfo-check-display-detect-system-hardware-information-linux/
|
||||
[7]: https://www.2daygeek.com/python-hwinfo-check-display-system-hardware-configuration-information-linux/
|
||||
[8]: https://www.2daygeek.com/check-system-hardware-devices-bus-information-lspci-lsscsi-lsusb-lsblk-linux/
|
||||
[9]: https://www.2daygeek.com/how-to-check-system-hardware-manufacturer-model-and-serial-number-in-linux/
|
||||
[10]: https://www.2daygeek.com/how-to-find-wwn-wwnn-and-wwpn-number-of-hba-card-in-linux/
|
||||
[11]: https://www.2daygeek.com/how-to-check-hp-ilo-firmware-version-from-linux-command-line/
|
||||
[12]: https://www.2daygeek.com/linux-find-out-wireless-network-wifi-speed-signal-strength-quality/
|
||||
[13]: https://www.2daygeek.com/view-check-cpu-hard-disk-temperature-linux/
|
||||
[14]: https://www.2daygeek.com/hegemon-a-modular-system-and-hardware-monitoring-tool-for-linux/
|
||||
[15]: https://www.2daygeek.com/check-linux-hardware-information-system-configuration/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user