mirror of
https://github.com/LCTT/TranslateProject.git
synced 2026-08-23 04:03:29 +08:00
17
.travis.yml
17
.travis.yml
@@ -1,18 +1,27 @@
|
||||
language: c
|
||||
language: minimal
|
||||
install:
|
||||
- sudo apt-get install jq
|
||||
- git clone --depth=1 -b gh-pages https://github.com/LCTT/TranslateProject/ build && rm -rf build/.git
|
||||
script:
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then sh ./scripts/check.sh; fi'
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sh ./scripts/badge.sh; fi'
|
||||
- 'if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then sh ./scripts/status.sh; fi'
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- master
|
||||
# - status
|
||||
except:
|
||||
- gh-pages
|
||||
- gh-pages
|
||||
git:
|
||||
submodules: false
|
||||
depth: false
|
||||
deploy:
|
||||
provider: pages
|
||||
skip_cleanup: true
|
||||
github_token: $GITHUB_TOKEN
|
||||
local_dir: build
|
||||
on:
|
||||
branch: master
|
||||
branch:
|
||||
- master
|
||||
# - status
|
||||
|
||||
10
README.md
10
README.md
@@ -1,10 +1,10 @@
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
[](https://lctt.github.io/new)
|
||||
[](https://lctt.github.io/translating)
|
||||
[](https://github.com/LCTT/TranslateProject/tree/master/translated)
|
||||
[](https://github.com/LCTT/TranslateProject/tree/master/published)
|
||||
|
||||
[](https://travis-ci.org/LCTT/TranslateProject)
|
||||
[](https://travis-ci.com/LCTT/TranslateProject)
|
||||
[](https://github.com/LCTT/TranslateProject/graphs/contributors)
|
||||
[](https://github.com/LCTT/TranslateProject/pulls?q=is%3Apr+is%3Aclosed)
|
||||
|
||||
|
||||
65
published/20171027 Scout out code problems with SonarQube.md
Normal file
65
published/20171027 Scout out code problems with SonarQube.md
Normal file
@@ -0,0 +1,65 @@
|
||||
使用 SonarQube 追踪代码问题
|
||||
======
|
||||
> 通过不断分析代码以了解潜在的质量问题,开源的 SonarQube 项目支持了 DevOps 的“尽早发布和经常发布” 的思维模式。
|
||||
|
||||

|
||||
|
||||
越来越多的组织正在实施 [DevOps][1] 以便在通过中间开发和测试环境以后更快更好的将新代码引入到生产环境。虽然版本控制、持续集成和部署以及自动化测试都属于 DevOps 的范畴,但仍然存在一个关键问题:组织如何量化代码质量,而不仅仅是部署的速度?
|
||||
|
||||
[SonarQube][2] 是用来填补这个空隙的一种选择。它是一个开源平台,通过代码的自动化静态分析不断的检查代码质量。 SonarQube 支持 20 多种语言的分析,并在各种类型的项目中输出和存储问题。
|
||||
|
||||
SonarQube 同时也提供了一个可同时维护和管理不同项目、不同代码的集中的环境。可以为每个项目定制规则。持续的检查和分析代码的健康轨迹。
|
||||
|
||||
SonarQube 还可以集成到可持续集成和开发(CI/CD)流程中,协助和自动确定代码是否为生产环境做好了准备的过程。
|
||||
|
||||
### 它可以衡量什么
|
||||
|
||||
开箱即用,SonarQube 可以测量的关键指标,包括代码错误、<ruby>代码异味<rt>code smells</rt></ruby>、安全漏洞和重复的代码。
|
||||
|
||||
* **代码错误** 是代码中的一部分不正确或无法正常运行、可能会导致错误的结果,是指那些在代码发布到生产环境之前应该被修复的明显的错误。
|
||||
* [代码异味][3] 不同于代码错误,被检测到的代码是可能能正确执行并符合预期。然而,它不容易被修复,也不能被单元测试覆盖,却可能会导致一些未知的错误,或是一些其它的问题。从长期的可维护性来讲,立即修复代码异味是明智之举。通常在编写代码的时候,代码异味并不容易被发现,而 SonarQube 的静态分析是一种发现它们的很好的方式。
|
||||
* **安全漏洞** 正如听起来的一样:指的是现在的代码中可能存在的安全问题的缺陷。这些缺陷应该立即修复来防止黑客利用它们。
|
||||
* **重复的代码** 也和听起来的一样:指的是源代码中重复的部分。代码重复在软件设计中是一种很不好的做法。总的来说,如果对一部分代码进行更改而另一部分没有,则会导致一些维护性的问题。例如,识别重复的代码可以很容易的将重复的代码打包成一个库来重复的使用。
|
||||
|
||||
### 可自定义的选项
|
||||
|
||||
因为它是开源的,所以 SonarQube 鼓励用户开发和提供可定制的选项。目前有超过 60 个[插件][4] 可用于增强 SonarQube 开箱即用的分析功能。
|
||||
|
||||
大多数的插件是为了增加 SonarQube 可以分析的编程语言的数量。另一些插件可以分析一些额外的指标甚至包括一些显示的仪表盘视图。实际上,如果组织需要检查一些自定义指标,或是想要在自己的仪表盘和以特定的方式查看分析数据,或使用 SonarQube 不支持的编程语言,则可能存在一些自定义的选项可以使用。如果你想要的功能并不支持,SonarQube 源码的开放也为你自己开发新的功能提供了可能性。
|
||||
|
||||
用户还可以定制适用于每种特定编程语言分析器的规则。通过 SonarQube 用户界面,可以按语言和按项目选择和取消规则。这些为特定的项目指定的规则,可以很好的在一个集中的位置维护所有的数据和配置。
|
||||
|
||||
### 为什么它那么重要
|
||||
|
||||
SonarQube 为组织提供了一个集中的位置来管理和跟踪多个项目代码中的问题。它还可以把持续的检查与质量门限相结合。一旦项目分析过一次以后,更进一步的分析会参考软件最新的修改来更新原始的统计信息,以反映最新的变化。这些跟踪可以让用户看到问题解决的程度和速度。这与 “尽早发布并经常发布”不谋而合。
|
||||
|
||||
另外,SonarQube 可使用 [可持续集成流程][5],比如像 [Hudson][6] 和 [Jenkins][7] 这样的工具。这个质量门限可以很好的反映代码的整体运行状况,并且通过 Jenkins 等集成工具,在发布代码到生产环境时担任一个重要的角色。
|
||||
|
||||
本着 DevOps 的精神, SonarQube 可以量化代码质量,来达到组织内部的要求。为了加快代码生产和发布的周期,组织必须意识到它们自己的技术债务和软件问题。通过发现这些信息, SonarQube 可以帮助组织更快的生成高质量的软件。
|
||||
|
||||
### 想要了解更多吗?
|
||||
|
||||
SonarQube 基于 GUN 通用公共许可证发布,它的源码可以在 [GitHub][8] 上查看。越来越多的用户对 SonarQube 的特性和功能感兴趣。 [Twitter][9] 和 [Google][10] 上有活跃的社区。这些社区以及 [SonarQube 博客][11] 对任何有兴趣开始和使用 SonarQube 的人有很有帮助。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/10/sonarqube
|
||||
|
||||
作者:[Sophie Polson][a]
|
||||
译者:[Jamkr](https://github.com/Jamkr)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/sophiepolson
|
||||
[1]:https://en.wikipedia.org/wiki/DevOps
|
||||
[2]:https://www.sonarqube.org/
|
||||
[3]:https://en.wikipedia.org/wiki/Code_smell
|
||||
[4]:https://docs.sonarqube.org/display/PLUG/Plugin+Library
|
||||
[5]:https://jenkins.io/blog/2017/04/18/continuousdelivery-devops-sonarqube/
|
||||
[6]:https://en.wikipedia.org/wiki/Hudson_(software)
|
||||
[7]:https://en.wikipedia.org/wiki/Jenkins_(software)
|
||||
[8]:https://github.com/SonarSource/sonarqube
|
||||
[9]:https://twitter.com/SonarQube
|
||||
[10]:https://groups.google.com/forum/#!forum/sonarqube
|
||||
[11]:https://blog.sonarsource.com/
|
||||
@@ -0,0 +1,212 @@
|
||||
Bash 脚本中如何使用 here 文档将数据写入文件
|
||||
======
|
||||
|
||||
<ruby>here 文档<rt>here document</rt></ruby> (LCTT 译注:here 文档又称作 heredoc )不是什么特殊的东西,只是一种 I/O 重定向方式,它告诉 bash shell 从当前源读取输入,直到读取到只有分隔符的行。
|
||||
|
||||
![redirect output of here document to a text file][1]
|
||||
|
||||
这对于向 ftp、cat、echo、ssh 和许多其他有用的 Linux/Unix 命令提供指令很有用。 此功能适用于 bash 也适用于 Bourne、Korn、POSIX 这三种 shell。
|
||||
|
||||
### here 文档语法
|
||||
|
||||
语法是:
|
||||
|
||||
```
|
||||
command <<EOF
|
||||
cmd1
|
||||
cmd2 arg1
|
||||
EOF
|
||||
```
|
||||
|
||||
或者允许 shell 脚本中的 here 文档使用 `EOF<<-` 以自然的方式缩进:
|
||||
|
||||
```
|
||||
command <<-EOF
|
||||
msg1
|
||||
msg2
|
||||
$var on line
|
||||
EOF
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
command <<'EOF'
|
||||
cmd1
|
||||
cmd2 arg1
|
||||
$var won't expand as parameter substitution turned off
|
||||
by single quoting
|
||||
EOF
|
||||
```
|
||||
|
||||
或者 **重定向并将其覆盖** 到名为 `my_output_file.txt` 的文件中:
|
||||
|
||||
```
|
||||
command <<EOF > my_output_file.txt
|
||||
mesg1
|
||||
msg2
|
||||
msg3
|
||||
$var on $foo
|
||||
EOF
|
||||
```
|
||||
|
||||
或**重定向并将其追加**到名为 `my_output_file.txt` 的文件中:
|
||||
|
||||
```
|
||||
command <<EOF >> my_output_file.txt
|
||||
mesg1
|
||||
msg2
|
||||
msg3
|
||||
$var on $foo
|
||||
EOF
|
||||
```
|
||||
|
||||
### 示例
|
||||
|
||||
以下脚本将所需内容写入名为 `/tmp/output.txt` 的文件中:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
OUT=/tmp/output.txt
|
||||
|
||||
echo "Starting my script..."
|
||||
echo "Doing something..."
|
||||
|
||||
cat <<EOF >$OUT
|
||||
Status of backup as on $(date)
|
||||
Backing up files $HOME and /etc/
|
||||
EOF
|
||||
|
||||
echo "Starting backup using rsync..."
|
||||
```
|
||||
|
||||
你可以使用[cat命令][3]查看/tmp/output.txt文件:
|
||||
|
||||
```
|
||||
$ cat /tmp/output.txt
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
```
|
||||
Status of backup as on Thu Nov 16 17:00:21 IST 2017
|
||||
Backing up files /home/vivek and /etc/
|
||||
```
|
||||
|
||||
### 禁用路径名/参数/变量扩展、命令替换、算术扩展
|
||||
|
||||
像 `$HOME` 这类变量和像 `$(date)` 这类命令在脚本中会被解释为替换。 要禁用它,请使用带有 `'EOF'` 这样带有单引号的形式,如下所示:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
OUT=/tmp/output.txt
|
||||
|
||||
echo "Starting my script..."
|
||||
echo "Doing something..."
|
||||
# No parameter and variable expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word.
|
||||
# If any part of word is quoted, the delimiter is the result of quote removal on word, and the lines in the here-document
|
||||
# are not expanded. So EOF is quoted as follows
|
||||
cat <<'EOF' >$OUT
|
||||
Status of backup as on $(date)
|
||||
Backing up files $HOME and /etc/
|
||||
EOF
|
||||
|
||||
echo "Starting backup using rsync..."
|
||||
```
|
||||
|
||||
你可以使用 [cat 命令][3]查看 `/tmp/output.txt` 文件:
|
||||
|
||||
```
|
||||
$ cat /tmp/output.txt
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
```
|
||||
Status of backup as on $(date)
|
||||
Backing up files $HOME and /etc/
|
||||
|
||||
```
|
||||
|
||||
### 关于 tee 命令的使用
|
||||
|
||||
语法是:
|
||||
|
||||
```
|
||||
tee /tmp/filename <<EOF >/dev/null
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
$(cmd)
|
||||
$var on $foo
|
||||
EOF
|
||||
```
|
||||
|
||||
或者通过在单引号中引用 `EOF` 来禁用变量替换和命令替换:
|
||||
|
||||
```
|
||||
tee /tmp/filename <<'EOF' >/dev/null
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
$(cmd)
|
||||
$var on $foo
|
||||
EOF
|
||||
```
|
||||
|
||||
这是我更新的脚本:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
OUT=/tmp/output.txt
|
||||
|
||||
echo "Starting my script..."
|
||||
echo "Doing something..."
|
||||
|
||||
tee $OUT <<EOF >/dev/null
|
||||
Status of backup as on $(date)
|
||||
Backing up files $HOME and /etc/
|
||||
EOF
|
||||
|
||||
echo "Starting backup using rsync..."
|
||||
```
|
||||
|
||||
### 关于内存 here 文档的使用
|
||||
|
||||
这是我更新的脚本:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
OUT=/tmp/output.txt
|
||||
|
||||
## in memory here docs
|
||||
## thanks https://twitter.com/freebsdfrau
|
||||
exec 9<<EOF
|
||||
Status of backup as on $(date)
|
||||
Backing up files $HOME and /etc/
|
||||
EOF
|
||||
|
||||
## continue
|
||||
echo "Starting my script..."
|
||||
echo "Doing something..."
|
||||
|
||||
## do it
|
||||
cat <&9 >$OUT
|
||||
|
||||
echo "Starting backup using rsync..."
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cyberciti.biz/faq/using-heredoc-rediection-in-bash-shell-script-to-write-to-file/
|
||||
|
||||
作者:[Vivek Gite][a]
|
||||
译者:[Flowsnow](https://github.com/Flowsnow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.cyberciti.biz
|
||||
[1]: https://www.cyberciti.biz/media/new/faq/2017/11/redirect-output-of-here-document-to-a-text-file.jpg
|
||||
[2]: https://bash.cyberciti.biz/guide/Here_documents
|
||||
[3]: https//www.cyberciti.biz/faq/linux-unix-appleosx-bsd-cat-command-examples/
|
||||
71
published/20171229 Excellent Free Roguelike Games.md
Normal file
71
published/20171229 Excellent Free Roguelike Games.md
Normal file
@@ -0,0 +1,71 @@
|
||||
最棒的免费 Roguelike 游戏
|
||||
======
|
||||
|
||||

|
||||
|
||||
Roguelike 属于角色扮演游戏的一个子流派,它从字面上理解就是“类 Rogue 游戏”。Rogue 是一个地牢探索视频游戏,第一个版本由开发者 Michel Toy、Glenn Wichman 和 Ken Arnold 在 1980 年发布,由于其极易上瘾使得它从一众游戏中脱颖而出。整个游戏的目标是深入第 26 层,取回 Yendor 的护身符并回到地面,所有设定都基于龙与地下城的世界观。
|
||||
|
||||
Rogue 被认为是一个经典、极其困难并且让人废寝忘食的游戏。虽然它在大学校园中非常受欢迎,但并不十分畅销。在 Rogue 发布时,它并没有使用开源许可证,导致了爱好者们开发了许多克隆版本。
|
||||
|
||||
对于 Roguelike 游戏并没有一个明确的定义,但是此类游戏会拥有下述的典型特征:
|
||||
|
||||
* 高度魔幻的叙事背景;
|
||||
* 程序化生成关卡。游戏世界中的大部分地图在每次开始游戏时重新生成,也就意味着鼓励多周目;
|
||||
* 回合制的地牢探险和战斗;
|
||||
* 基于图块随机生成的图形;
|
||||
* 随机的战斗结果;
|
||||
* 永久死亡——死亡实际起作用,一旦死亡你就需要重新开始
|
||||
* 高难度
|
||||
|
||||
此篇文章收集了大量 Linux 平台可玩的 Roguelike 游戏。如果你享受提供真实紧张感的上瘾游戏体验,我衷心推荐你下载这些游戏。不要被其中很多游戏的原始画面吓退,一旦你沉浸其中你会很快忽略简陋的画面。记住,在 Roguelike 游戏中应是游戏机制占主导,画面只是一个加分项而不是必需项。
|
||||
|
||||
此处推荐 16 款游戏。所有的游戏都可免费下载,并且大部分采用开源许可证发布。
|
||||
|
||||
| Roguelike 游戏 | |
|
||||
| --- | --- |
|
||||
| [Dungeon Crawl Stone Soup][1] | Linley 的 Dungeon Crawl 的续作 |
|
||||
| [Prospector][2] | 基于科幻小说世界观的 Roguelike 游戏 |
|
||||
| [Dwarf Fortress][3] | 冒险和侏儒塔防 |
|
||||
| [NetHack][4] | 非常怪诞并且令人上瘾的龙与地下城风格冒险游戏 |
|
||||
| [Angband][5] | 沿着 Rogue 和 NetHack 的路线,它源于游戏 Moria 和 Umoria |
|
||||
| [Ancient Domains of Mystery][6] | 非常成熟的 Roguelike 游戏 |
|
||||
| [Tales of Maj’Eyal][7] | 特色的策略回合制战斗与先进的角色培养系统 |
|
||||
| [UnNetHack][8] | NetHack 的创新复刻 |
|
||||
| [Hydra Slayer][9] | 基于数学谜题的 Roguelike 游戏 |
|
||||
| [Cataclysm DDA][10] | 后启示录风格 Roguelike 游戏,设定于虚构的新英格兰乡下|
|
||||
| [Brogue][11] | Rogue 的正统续作 |
|
||||
| [Goblin Hack][12] | 受 NetHack 启发的游戏, 但密钥更少游戏流程更快 |
|
||||
| [Ascii Sector][13] | 拥有 Roguelike 动作系统的 2D 版贸易和太空飞行模拟器 |
|
||||
| [SLASH'EM][14] | Super Lotsa Added Stuff Hack - Extended Magic |
|
||||
| [Everything Is Fodder][15] | Seven Day Roguelike 比赛入口 |
|
||||
| [Woozoolike][16] | 7DRL 2017 比赛中一款简单的太空探索 Roguelike 游戏 |
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxlinks.com/excellent-free-roguelike-games/
|
||||
|
||||
作者:[Steve Emms][a]
|
||||
译者:[cycoe](https://github.com/cycoe)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linuxlinks.com/author/linuxlinks/
|
||||
[1]:https://www.linuxlinks.com/dungeoncrawlstonesoup/
|
||||
[2]:https://www.linuxlinks.com/Prospector-roguelike/
|
||||
[3]:https://www.linuxlinks.com/dwarffortress/
|
||||
[4]:https://www.linuxlinks.com/nethack/
|
||||
[5]:https://www.linuxlinks.com/angband/
|
||||
[6]:https://www.linuxlinks.com/ADOM/
|
||||
[7]:https://www.linuxlinks.com/talesofmajeyal/
|
||||
[8]:https://www.linuxlinks.com/unnethack/
|
||||
[9]:https://www.linuxlinks.com/hydra-slayer/
|
||||
[10]:https://www.linuxlinks.com/cataclysmdda/
|
||||
[11]:https://www.linuxlinks.com/brogue/
|
||||
[12]:https://www.linuxlinks.com/goblin-hack/
|
||||
[13]:https://www.linuxlinks.com/asciisector/
|
||||
[14]:https://www.linuxlinks.com/slashem/
|
||||
[15]:https://www.linuxlinks.com/everything-is-fodder/
|
||||
[16]:https://www.linuxlinks.com/Woozoolike/
|
||||
[17]:https://i2.wp.com/www.linuxlinks.com/wp-content/uploads/2017/12/dungeon.jpg?resize=300%2C200&ssl=1
|
||||
@@ -0,0 +1,104 @@
|
||||
使用 Docker 企业版搭建自己的私有注册服务器
|
||||
======
|
||||
|
||||
![docker trusted registry][1]
|
||||
|
||||
Docker 真的很酷,特别是和使用虚拟机相比,转移 Docker 镜像十分容易。如果你已准备好使用 Docker,那你肯定已从 [Docker Hub][2] 上拉取过完整的镜像。Docker Hub 是 Docker 的云端注册服务器服务,它包含成千上万个供选择的 Docker 镜像。如果你开发了自己的软件包并创建了自己的 Docker 镜像,那么你会想有自己私有的注册服务器。如果你有搭配着专有许可的镜像,或想为你的构建系统提供复杂的持续集成(CI)过程,则更应该拥有自己的私有注册服务器。
|
||||
|
||||
Docker 企业版包括 <ruby>Docker 可信注册服务器<rt>Docker Trusted Registry</rt></ruby>(DTR)。这是一个具有安全镜像管理功能的高可用的注册服务器,为在你自己的数据中心或基于云端的架构上运行而构建。在接下来,我们将了解到 DTR 是提供安全、可重用且连续的[软件供应链][3]的一个关键组件。你可以通过我们的[免费托管小样][4]立即开始使用,或者通过下载安装进行 30 天的免费试用。下面是开始自己安装的步骤。
|
||||
|
||||
### 配置 Docker 企业版
|
||||
|
||||
DTR 运行于通用控制面板(UCP)之上,所以开始前要安装一个单节点集群。如果你已经有了自己的 UCP 集群,可以跳过这一步。在你的 docker 托管主机上,运行以下命令:
|
||||
|
||||
```
|
||||
# 拉取并安装 UCP
|
||||
docker run -it -rm -v /var/run/docker.sock:/var/run/docker.sock -name ucp docker/ucp:latest install
|
||||
```
|
||||
|
||||
当 UCP 启动并运行后,在安装 DTR 之前你还有几件事要做。针对刚刚安装的 UCP 实例,打开浏览器。在日志输出的末尾应该有一个链接。如果你已经有了 Docker 企业版的许可证,那就在这个界面上输入它吧。如果你还没有,可以访问 [Docker 商店][5]获取 30 天的免费试用版。
|
||||
|
||||
准备好许可证后,你可能会需要改变一下 UCP 运行的端口。因为这是一个单节点集群,DTR 和 UCP 可能会以相同的端口运行它们的 web 服务。如果你拥有不只一个节点的 UCP 集群,这就不是问题,因为 DTR 会寻找有所需空闲端口的节点。在 UCP 中,点击“管理员设置 -> 集群配置”并修改控制器端口,比如 5443。
|
||||
|
||||
### 安装 DTR
|
||||
|
||||
我们要安装一个简单的、单节点的 DTR 实例。如果你要安装实际生产用途的 DTR,那么你会将其设置为高可用(HA)模式,即需要另一种存储介质,比如基于云端的对象存储或者 NFS(LCTT 译注:Network File System,网络文件系统)。因为目前安装的是一个单节点实例,我们依然使用默认的本地存储。
|
||||
|
||||
首先我们需要拉取 DTR 的 bootstrap 镜像。boostrap 镜像是一个微小的独立安装程序,包括了连接到 UCP 以及设置和启动 DTR 所需的所有容器、卷和逻辑网络。
|
||||
|
||||
使用命令:
|
||||
|
||||
```
|
||||
# 拉取并运行 DTR 引导程序
|
||||
docker run -it -rm docker/dtr:latest install -ucp-insecure-tls
|
||||
```
|
||||
|
||||
注意:默认情况下,UCP 和 DTR 都有自己的证书,系统无法识别。如果你已使用系统信任的 TLS 证书设置 UCP,则可以省略 `-ucp-insecure-tls` 选项。另外,你可以使用 `-ucp-ca` 选项来直接指定 UCP 的 CA 证书。
|
||||
|
||||
然后 DTR bootstrap 镜像会让你确定几项设置,比如 UCP 安装的 URL 地址以及管理员的用户名和密码。从拉取所有的 DTR 镜像到设置全部完成,只需要一到两分钟的时间。
|
||||
|
||||
### 保证一切安全
|
||||
|
||||
一切都准备好后,就可以向注册服务器推送或者从中拉取镜像了。在做这一步之前,让我们设置 TLS 证书,以便与 DTR 安全地通信。
|
||||
|
||||
在 Linux 上,我们可以使用以下命令(只需确保更改了 `DTR_HOSTNAME` 变量,来正确映射我们刚刚设置的 DTR):
|
||||
|
||||
```
|
||||
# 从 DTR 拉取 CA 证书(如果 curl 不可用,你可以使用 wget)
|
||||
DTR_HOSTNAME=< DTR 主机名>
|
||||
curl -k https://$(DTR_HOSTNAME)/ca > $(DTR_HOSTNAME).crt
|
||||
sudo mkdir /etc/docker/certs.d/$(DTR_HOSTNAME)
|
||||
sudo cp $(DTR_HOSTNAME) /etc/docker/certs.d/$(DTR_HOSTNAME)
|
||||
# 重启 docker 守护进程(在 Ubuntu 14.04 上,使用 `sudo service docker restart` 命令)
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
对于 Mac 和 Windows 版的 Docker,我们会以不同的方式安装客户端。转入“设置 -> 守护进程”,在“不安全的注册服务器”部分,输入你的 DTR 主机名。点击“应用”,docker 守护进程应在重启后可以良好使用。
|
||||
|
||||
### 推送和拉取镜像
|
||||
|
||||
现在我们需要设置一个仓库来存放镜像。这和 Docker Hub 有一点不同,如果你做的 docker 推送仓库中不存在,它会自动创建一个。要创建一个仓库,在浏览器中打开 `https://<Your DTR hostname>` 并在出现登录提示时使用你的管理员凭据登录。如果你向 UCP 添加了许可证,则 DTR 会自动获取该许可证。如果没有,请现在确认上传你的许可证。
|
||||
|
||||
进入刚才的网页之后,点击“新建仓库”按钮来创建新的仓库。
|
||||
|
||||
我们会创建一个用于存储 Alpine linux 的仓库,所以在名字输入处键入 “alpine”,点击“保存”(在 DTR 2.5 及更高版本中叫“创建”)。
|
||||
|
||||
现在我们回到 shell 界面输入以下命令:
|
||||
|
||||
```
|
||||
# 拉取 Alpine Linux 的最新版
|
||||
docker pull alpine:latest
|
||||
# 登入新的 DTR 实例
|
||||
docker login <Your DTR hostname>
|
||||
# 标记上 Alpine 使能推送其至你的 DTR
|
||||
docker tag alpine:latest <Your DTR hostname>/admin/alpine:latest
|
||||
# 向 DTR 推送镜像
|
||||
docker push <Your DTR hostname>/admin/alpine:latest
|
||||
```
|
||||
|
||||
就是这样!我们刚刚推送了最新的 Alpine Linux 的一份拷贝,重新打了标签以便将其存储到 DTR 中,并将其推送到我们的私有注册服务器。如果你想将镜像拉取至不同的 Docker 引擎中,按如上所示设置你的 DTR 证书,然后执行以下命令:
|
||||
|
||||
```
|
||||
# 从 DTR 中拉取镜像
|
||||
docker pull <Your DTR hostname>/admin/alpine:latest
|
||||
```
|
||||
|
||||
DTR 具有许多优秀的镜像管理功能,例如镜像的缓存、映像、扫描、签名甚至自动化供应链策略。这些功能我们在后期的博客文章中更详细的探讨。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://blog.docker.com/2018/01/dtr/
|
||||
|
||||
作者:[Patrick Devine][a]
|
||||
译者:[fuowang](https://github.com/fuowang)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://blog.docker.com/author/pdevine/
|
||||
[1]:https://i1.wp.com/blog.docker.com/wp-content/uploads/ccd278d2-29c2-4866-8285-c2fe60b4bd5e-1.jpg?resize=965%2C452&ssl=1
|
||||
[2]:https://hub.docker.com/
|
||||
[3]:https://blog.docker.com/2016/08/securing-enterprise-software-supply-chain-using-docker/
|
||||
[4]:https://www.docker.com/trial
|
||||
[5]:https://store.docker.com/search?offering=enterprise&page=1&q=&type=edition
|
||||
53
published/20180127 Write Dumb Code.md
Normal file
53
published/20180127 Write Dumb Code.md
Normal file
@@ -0,0 +1,53 @@
|
||||
写直白的代码
|
||||
====
|
||||
|
||||
为开源项目作贡献最好的方式是为它减少代码,我们应致力于写出让新手程序员无需注释就容易理解的代码,让维护者也无需花费太多精力就能着手维护。
|
||||
|
||||
在学生时代,我们会更多地用复杂巧妙的技术去挑战新的难题。首先我们会学习循环,然后是函数啊,类啊,等等。当我们到达一定高的程度,能用更高级的技术写更长的程序,我们会因此受到称赞。此刻我们发现老司机们用 monads 而新手们用 loop 作循环。
|
||||
|
||||
之后我们毕业找了工作,或者和他人合作开源项目。我们用在学校里学到的各种炫技寻求并骄傲地给出解决方案的代码实现。
|
||||
|
||||
*哈哈,我能扩展这个项目,并实现某牛 X 功能啦,我这里能用继承啦,我太聪明啦!*
|
||||
|
||||
我们实现了某个小的功能,并以充分的理由觉得自己做到了。现实项目中的编程却不是针对某某部分的功能而言。以我个人的经验而言,以前我很开心的去写代码,并骄傲地向世界展示我所知道的事情。有例为证,作为对某种编程技术的偏爱,这是用另一种元编程语言构建的一个 [线性代数语言][1],注意,这么多年以来一直没人愿意碰它。
|
||||
|
||||
在维护了更多的代码后,我的观点发生了变化。
|
||||
|
||||
1. 我们不应去刻意探求如何构建软件。软件是我们为解决问题所付出的代价,那才是我们真实的目的。我们应努力为了解决问题而构建较小的软件。
|
||||
2. 我们应使用尽可能简单的技术,那么更多的人就越可能会使用,并且无需理解我们所知的高级技术就能扩展软件的功能。当然,在我们不知道如何使用简单技术去实现时,我们也可以使用高级技术。
|
||||
|
||||
所有的这些例子都不是听来的故事。我遇到的大部分人会认同某些部分,但不知为什么,当我们向一个新项目贡献代码时又会忘掉这个初衷。直觉里用复杂技术去构建的念头往往会占据上风。
|
||||
|
||||
### 软件是种投入
|
||||
|
||||
你写的每行代码都要花费人力。写代码当然是需要时间的,也许你会认为只是你个人在奉献,然而这些代码在被审阅的时候也需要花时间理解,对于未来维护和开发人员来说,他们在维护和修改代码时同样要花费时间。否则他们完全可以用这时间出去晒晒太阳,或者陪伴家人。
|
||||
|
||||
所以,当你向某个项目贡献代码时,请心怀谦恭。就像是,你正和你的家人进餐时,餐桌上却没有足够的食物,你只索取你所需的部分,别人对你的自我约束将肃然起敬。以更少的代码去解决问题是很难的,你肩负重任的同时自然减轻了别人的重负。
|
||||
|
||||
### 技术越复杂越难维护
|
||||
|
||||
作为学生,逐渐使用高端技术证明了自己的价值。这体现在,首先我们有能力在开源项目中使用函数,接着是类,然后是高阶函数,monads 等等。我们向同行显示自己的解决方案时,常因自己所用技术高低而感到自豪或卑微。
|
||||
|
||||
而在现实中,和团队去解决问题时,情况发生了逆转。现在,我们致力于尽可能使用简单的代码去解决问题。简单方式解决问题使新手程序员能够以此扩展并解决其他问题。简单的代码让别人容易上手,效果立竿见影。我们藉以只用简单的技术去解决难题,从而展示自己的价值。
|
||||
|
||||
*看,我用循环替代了递归函数并且一样达到了我们的需求。当然我明白这是不够聪明的做法,不过我注意到新手同事在这里会遇上麻烦,我觉得这种改变将有所帮助吧。*
|
||||
|
||||
如果你是个好的程序员,你不需要证明你知道很多炫技。相应的,你可以通过用一个简单的方法解决一个问题来显示你的价值,并激发你的团队在未来的时间里去完善它。
|
||||
|
||||
### 当然,也请保持节制
|
||||
|
||||
话虽如此,过于遵循 “用简单的工具去构建” 的教条也会降低生产力。通常用递归会比用循环解决问题更简单,用类或 monad 才是正确的途径。还有两种情况另当别论,一是只是只为满足自我而创建的系统,或者是别人毫无构建经验的系统。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://matthewrocklin.com/blog/work/2018/01/27/write-dumb-code
|
||||
|
||||
作者:[Matthew Rocklin][a]
|
||||
译者:[plutoid](https://github.com/plutoid)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://matthewrocklin.com
|
||||
[1]:https://github.com/mrocklin/matrix-algebra
|
||||
@@ -0,0 +1,211 @@
|
||||
使用 Redis 和 Python 构建一个共享单车的应用程序
|
||||
======
|
||||
|
||||
> 学习如何使用 Redis 和 Python 构建一个位置感知的应用程序。
|
||||
|
||||

|
||||
|
||||
我经常出差。但不是一个汽车狂热分子,所以当我有空闲时,我更喜欢在城市中散步或者骑单车。我参观过的许多城市都有共享单车系统,你可以租个单车用几个小时。大多数系统都有一个应用程序来帮助用户定位和租用他们的单车,但对于像我这样的用户来说,在一个地方可以获得可租赁的城市中所有单车的信息会更有帮助。
|
||||
|
||||
为了解决这个问题并且展示开源的强大还有为 Web 应用程序添加位置感知的功能,我组合了可用的公开的共享单车数据、[Python][1] 编程语言以及开源的 [Redis][2] 内存数据结构服务,用来索引和查询地理空间数据。
|
||||
|
||||
由此诞生的共享单车应用程序包含来自很多不同的共享系统的数据,包括纽约市的 [Citi Bike][3] 共享单车系统(LCTT 译注:Citi Bike 是纽约市的一个私营公共单车系统。在 2013 年 5 月 27 日正式营运,是美国最大的公共单车系统。Citi Bike 的名称有两层意思。Citi 是计划赞助商花旗银行(CitiBank)的名字。同时,Citi 和英文中“城市(city)”一词的读音相同)。它利用了花旗单车系统提供的 <ruby>通用共享单车数据流<rt>General Bikeshare Feed</rt></ruby>,并利用其数据演示了一些使用 Redis 地理空间数据索引的功能。 花旗单车数据可按照 [花旗单车数据许可协议][4] 提供。
|
||||
|
||||
### 通用共享单车数据流规范
|
||||
|
||||
<ruby>通用共享单车数据流规范<rt>General Bikeshare Feed Specification</rt></ruby>(GBFS)是由 [北美共享单车协会][6] 开发的 [开放数据规范][5],旨在使地图程序和运输程序更容易的将共享单车系统添加到对应平台中。 目前世界上有 60 多个不同的共享系统使用该规范。
|
||||
|
||||
Feed 流由几个简单的 [JSON][7] 数据文件组成,其中包含系统状态的信息。 Feed 流以一个顶级 JSON 文件开头,其引用了子数据流的 URL:
|
||||
|
||||
```
|
||||
{
|
||||
"data": {
|
||||
"en": {
|
||||
"feeds": [
|
||||
{
|
||||
"name": "system_information",
|
||||
"url": "https://gbfs.citibikenyc.com/gbfs/en/system_information.json"
|
||||
},
|
||||
{
|
||||
"name": "station_information",
|
||||
"url": "https://gbfs.citibikenyc.com/gbfs/en/station_information.json"
|
||||
},
|
||||
. . .
|
||||
]
|
||||
}
|
||||
},
|
||||
"last_updated": 1506370010,
|
||||
"ttl": 10
|
||||
}
|
||||
```
|
||||
|
||||
第一步是使用 `system_information` 和 `station_information` 的数据将共享单车站的信息加载到 Redis 中。
|
||||
|
||||
`system_information` 提供系统 ID,系统 ID 是一个简短编码,可用于为 Redis 键名创建命名空间。 GBFS 规范没有指定系统 ID 的格式,但确保它是全局唯一的。许多共享单车数据流使用诸如“coast_bike_share”,“boise_greenbike” 或者 “topeka_metro_bikes” 这样的短名称作为系统 ID。其他的使用常见的有地理缩写,例如 NYC 或者 BA,并且使用通用唯一标识符(UUID)。 这个共享单车应用程序使用该标识符作为前缀来为指定系统构造唯一键。
|
||||
|
||||
`station_information` 数据流提供组成整个系统的共享单车站的静态信息。车站由具有多个字段的 JSON 对象表示。车站对象中有几个必填字段,用于提供物理单车站的 ID、名称和位置。还有几个可选字段提供有用的信息,例如最近的十字路口、可接受的付款方式。这是共享单车应用程序这一部分的主要信息来源。
|
||||
|
||||
### 建立数据库
|
||||
|
||||
我编写了一个示例应用程序 [load_station_data.py][8],它模仿后端进程中从外部源加载数据时会发生什么。
|
||||
|
||||
### 查找共享单车站
|
||||
|
||||
从 [GitHub 上 GBFS 仓库][5]中的 [systems.csv][9] 文件开始加载共享单车数据。
|
||||
|
||||
仓库中的 [systems.csv][9] 文件提供已注册的共享单车系统及可用的 GBFS 数据流的<ruby>发现 URL<rt>discovery URL</rt></ruby>。 这个发现 URL 是处理共享单车信息的起点。
|
||||
|
||||
`load_station_data` 程序获取系统文件中找到的每个发现 URL,并使用它来查找两个子数据流的 URL:系统信息和车站信息。 系统信息提供提供了一条关键信息:系统的唯一 ID。 (注意:系统 ID 也在 `systems.csv` 文件中提供,但文件中的某些标识符与数据流中的标识符不匹配,因此我总是从数据流中获取标识符。)系统上的详细信息,比如共享单车 URL、电话号码和电子邮件, 可以在程序的后续版本中添加,因此使用 `${system_id}:system_info` 这个键名将数据存储在 Redis 中。
|
||||
|
||||
### 载入车站数据
|
||||
|
||||
车站信息提供系统中每个车站的数据,包括该系统的位置。`load_station_data` 程序遍历车站数据流中的每个车站,并使用 `${system_id}:station:${station_id}` 形式的键名将每个车站的数据存储到 Redis 中。 使用 `GEOADD` 命令将每个车站的位置添加到共享单车的地理空间索引中。
|
||||
|
||||
### 更新数据
|
||||
|
||||
在后续运行中,我不希望代码从 Redis 中删除所有 Feed 数据并将其重新加载到空的 Redis 数据库中,因此我仔细考虑了如何处理数据的原地更新。
|
||||
|
||||
代码首先加载所有需要系统在内存中处理的共享单车站的信息数据集。 当加载了一个车站的信息时,该站就会按照 Redis 键名从内存中的车站集合中删除。 加载完所有车站数据后,我们就剩下一个包含该系统所有必须删除的车站数据的集合。
|
||||
|
||||
程序迭代处理该数据集,并创建一个事务删除车站的信息,从地理空间索引中删除该车站的键名,并从系统的车站列表中删除该车站。
|
||||
|
||||
### 代码重点
|
||||
|
||||
在[示例代码][8]中有一些值得注意的地方。 首先,使用 `GEOADD` 命令将所有数据项添加到地理空间索引中,而使用 `ZREM` 命令将其删除。 由于地理空间类型的底层实现使用了有序集合,因此需要使用 ZREM 删除数据项。 需要注意的是:为简单起见,示例代码演示了如何在单个 Redis 节点工作; 为了在集群环境中运行,需要重新构建事务块。
|
||||
|
||||
如果你使用的是 Redis 4.0(或更高版本),则可以在代码中使用 `DELETE` 和 `HMSET` 命令。 Redis 4.0 提供 `UNLINK` 命令作为 `DELETE` 命令的异步版本的替代。 `UNLINK` 命令将从键空间中删除键,但它会在另外的线程中回收内存。 在 Redis 4.0 中 [HMSET 命令已经被弃用了而且 HSET 命令现在接收可变参数][12](即,它接受的参数个数不定)。
|
||||
|
||||
### 通知客户端
|
||||
|
||||
处理结束时,会向依赖我们数据的客户端发送通知。 使用 Redis 发布/订阅机制,通知将通过 `geobike:station_changed` 通道和系统 ID 一起发出。
|
||||
|
||||
### 数据模型
|
||||
|
||||
在 Redis 中构建数据时,最重要的考虑因素是如何查询信息。 共享单车程序需要支持的两个主要查询是:
|
||||
|
||||
- 找到我们附近的车站
|
||||
- 显示车站相关的信息
|
||||
|
||||
Redis 提供了两种主要数据类型用于存储数据:哈希和有序集。 [哈希类型][13]很好地映射到表示车站的 JSON 对象;由于 Redis 哈希不使用固定的数据结构,因此它们可用于存储可变的车站信息。
|
||||
|
||||
当然,在地理位置上寻找站点需要地理空间索引来搜索相对于某些坐标的站点。 Redis 提供了[几个][14]使用[有序集][15]数据结构构建地理空间索引的命令。
|
||||
|
||||
我们使用 `${system_id}:station:${station_id}` 这种格式的键名存储车站相关的信息,使用 `${system_id}:stations:location` 这种格式的键名查找车站的地理空间索引。
|
||||
|
||||
### 获取用户位置
|
||||
|
||||
构建应用程序的下一步是确定用户的当前位置。 大多数应用程序通过操作系统提供的内置服务来实现此目的。 操作系统可以基于设备内置的 GPS 硬件为应用程序提供定位,或者从设备的可用 WiFi 网络提供近似的定位。
|
||||
|
||||
### 查找车站
|
||||
|
||||
找到用户的位置后,下一步是找到附近的共享单车站。 Redis 的地理空间功能可以返回用户当前坐标在给定距离内的所有车站信息。 以下是使用 Redis 命令行界面的示例。
|
||||
|
||||

|
||||
|
||||
想象一下,我正在纽约市第五大道的苹果零售店,我想要向市中心方向前往位于西 37 街的 MOOD 布料店,与我的好友 [Swatch][16] 相遇。 我可以坐出租车或地铁,但我更喜欢骑单车。 附近有没有我可以使用的单车共享站呢?
|
||||
|
||||
苹果零售店位于 40.76384,-73.97297。 根据地图显示,在零售店 500 英尺半径范围内(地图上方的蓝色)有两个单车站,分别是陆军广场中央公园南单车站和东 58 街麦迪逊单车站。
|
||||
|
||||
我可以使用 Redis 的 `GEORADIUS` 命令查询 500 英尺半径范围内的车站的 `NYC` 系统索引:
|
||||
|
||||
```
|
||||
127.0.0.1:6379> GEORADIUS NYC:stations:location -73.97297 40.76384 500 ft
|
||||
1) "NYC:station:3457"
|
||||
2) "NYC:station:281"
|
||||
```
|
||||
|
||||
Redis 使用地理空间索引中的元素作为特定车站的元数据的键名,返回在该半径内找到的两个共享单车站。 下一步是查找两个站的名称:
|
||||
|
||||
```
|
||||
127.0.0.1:6379> hget NYC:station:281 name
|
||||
"Grand Army Plaza & Central Park S"
|
||||
|
||||
127.0.0.1:6379> hget NYC:station:3457 name
|
||||
"E 58 St & Madison Ave"
|
||||
```
|
||||
|
||||
这些键名对应于上面地图上标识的车站。 如果需要,可以在 `GEORADIUS` 命令中添加更多标志来获取元素列表,每个元素的坐标以及它们与当前点的距离:
|
||||
|
||||
```
|
||||
127.0.0.1:6379> GEORADIUS NYC:stations:location -73.97297 40.76384 500 ft WITHDIST WITHCOORD ASC
|
||||
1) 1) "NYC:station:281"
|
||||
2) "289.1995"
|
||||
3) 1) "-73.97371262311935425"
|
||||
2) "40.76439830559216659"
|
||||
2) 1) "NYC:station:3457"
|
||||
2) "383.1782"
|
||||
3) 1) "-73.97209256887435913"
|
||||
2) "40.76302702144496237"
|
||||
```
|
||||
|
||||
查找与这些键名关联的名称会生成一个我可以从中选择的车站的有序列表。 Redis 不提供方向和路线的功能,因此我使用设备操作系统的路线功能绘制从当前位置到所选单车站的路线。
|
||||
|
||||
`GEORADIUS` 函数可以很轻松的在你喜欢的开发框架的 API 里实现,这样就可以向应用程序添加位置功能了。
|
||||
|
||||
### 其他的查询命令
|
||||
|
||||
除了 `GEORADIUS` 命令外,Redis 还提供了另外三个用于查询索引数据的命令:`GEOPOS`、`GEODIST` 和 `GEORADIUSBYMEMBER`。
|
||||
|
||||
`GEOPOS` 命令可以为 <ruby>地理哈希<rt>geohash</rt></ruby> 中的给定元素提供坐标(LCTT 译注:geohash 是一种将二维的经纬度编码为一位的字符串的一种算法,常用于基于距离的查找算法和推荐算法)。 例如,如果我知道西 38 街 8 号有一个共享单车站,ID 是 523,那么该站的元素名称是 `NYC:station:523`。 使用 Redis,我可以找到该站的经度和纬度:
|
||||
|
||||
```
|
||||
127.0.0.1:6379> geopos NYC:stations:location NYC:station:523
|
||||
1) 1) "-73.99138301610946655"
|
||||
2) "40.75466497634030105"
|
||||
```
|
||||
|
||||
`GEODIST` 命令提供两个索引元素之间的距离。 如果我想找到陆军广场中央公园南单车站与东 58 街麦迪逊单车站之间的距离,我会使用以下命令:
|
||||
|
||||
```
|
||||
127.0.0.1:6379> GEODIST NYC:stations:location NYC:station:281 NYC:station:3457 ft
|
||||
"671.4900"
|
||||
```
|
||||
|
||||
最后,`GEORADIUSBYMEMBER` 命令与 `GEORADIUS` 命令类似,但该命令不是采用一组坐标,而是采用索引的另一个成员的名称,并返回以该成员为中心的给定半径内的所有成员。 要查找陆军广场中央公园南单车站 1000 英尺范围内的所有车站,请输入以下内容:
|
||||
|
||||
```
|
||||
127.0.0.1:6379> GEORADIUSBYMEMBER NYC:stations:location NYC:station:281 1000 ft WITHDIST
|
||||
1) 1) "NYC:station:281"
|
||||
2) "0.0000"
|
||||
2) 1) "NYC:station:3132"
|
||||
2) "793.4223"
|
||||
3) 1) "NYC:station:2006"
|
||||
2) "911.9752"
|
||||
4) 1) "NYC:station:3136"
|
||||
2) "940.3399"
|
||||
5) 1) "NYC:station:3457"
|
||||
2) "671.4900"
|
||||
```
|
||||
|
||||
虽然此示例侧重于使用 Python 和 Redis 来解析数据并构建共享单车系统位置的索引,但可以很容易地衍生为定位餐馆、公共交通或者是开发人员希望帮助用户找到的任何其他类型的场所。
|
||||
|
||||
本文基于今年我在北卡罗来纳州罗利市的开源 101 会议上的[演讲][17]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/2/building-bikesharing-application-open-source-tools
|
||||
|
||||
作者:[Tague Griffith][a]
|
||||
译者:[Flowsnow](https://github.com/Flowsnow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/tague
|
||||
[1]: https://www.python.org/
|
||||
[2]: https://redis.io/
|
||||
[3]: https://www.citibikenyc.com/
|
||||
[4]: https://www.citibikenyc.com/data-sharing-policy
|
||||
[5]: https://github.com/NABSA/gbfs
|
||||
[6]: http://nabsa.net/
|
||||
[7]: https://www.json.org/
|
||||
[8]: https://gist.github.com/tague/5a82d96bcb09ce2a79943ad4c87f6e15
|
||||
[9]: https://github.com/NABSA/gbfs/blob/master/systems.csv
|
||||
[10]: https://redis.io/commands/unlink
|
||||
[11]: https://redis.io/commands/hmset
|
||||
[12]: https://raw.githubusercontent.com/antirez/redis/4.0/00-RELEASENOTES
|
||||
[13]: https://redis.io/topics/data-types#Hashes
|
||||
[14]: https://redis.io/commands#geo
|
||||
[15]: https://redis.io/topics/data-types-intro#redis-sorted-sets
|
||||
[16]: https://twitter.com/swatchthedog
|
||||
[17]: http://opensource101.com/raleigh/talks/building-location-aware-apps-open-source-tools/
|
||||
@@ -1,26 +1,34 @@
|
||||
DevOps应聘者应该准备回答的20个问题
|
||||
DevOps 应聘者应该准备回答的 20 个问题
|
||||
======
|
||||
|
||||
> 想要建立一个积极,富有成效的工作环境? 在招聘过程中要专注于寻找契合点。
|
||||
|
||||

|
||||
聘请一个不合适的人代价是很高的。根据Link人力资源的首席执行官Jörgen Sundberg的统计,招聘,雇佣一名新员工将会花费公司$240,000之多,当你进行了一次不合适的招聘:
|
||||
* 你失去了他们所知道的。
|
||||
* 你失去了他们认识的人
|
||||
|
||||
聘请一个不合适的人[代价是很高的][1]。根据 Link 人力资源的首席执行官 Jörgen Sundberg 的统计,招聘、雇佣一名新员工将会花费公司$240,000 之多,当你进行了一次不合适的招聘:
|
||||
|
||||
* 你失去了他们的知识技能。
|
||||
* 你失去了他们的人脉。
|
||||
* 你的团队将可能进入到一个组织发展的震荡阶段
|
||||
* 你的公司将会面临组织破裂的风险
|
||||
|
||||
当你失去一名员工的时候,你就像丢失了公司图谱中的一块。同样值得一提的是另一端的疼痛。应聘到一个错误工作岗位的员工会感受到很大的压力以及整个身心的不满意,甚至是健康问题。
|
||||
当你失去一名员工的时候,你就像丢失了公司版图中的一块。同样值得一提的是另一端的痛苦。应聘到一个错误工作岗位的员工会感受到很大的压力以及整个身心的不满意,甚至是健康问题。
|
||||
|
||||
另外一方面,当你招聘到合适的人时,新的员工将会:
|
||||
* 丰富公司现有的文化,使你的组织成为一个更好的工作场所。研究表明一个积极的工作文化能够帮助驱动一个更长久的财务业绩,而且如果你在一个欢快的环境中工 作,你更有可能在生活中做的更好。
|
||||
|
||||
* 丰富公司现有的文化,使你的组织成为一个更好的工作场所。研究表明一个积极的工作文化能够帮助更长久推动财务业绩增长,而且如果你在一个欢快的环境中工作,你更有可能在生活中做的更好。
|
||||
* 热爱和你的组织在一起工作。当人们热爱他们所在做的,他们会趋向于做的更好。
|
||||
|
||||
招聘适合的或者加强现有的文化在DevOps和敏捷团多中是必不可少的。也就是说雇佣到一个能够鼓励积极合作的人,以便来自不同背景,有着不同目标和工作方式的团队能够在一起有效的工作。你新雇佣的员工因应该能够帮助团队合作来充分发挥放大他们的价值同时也能够增加员工的满意度以及平衡组织目标的冲突。他或者她应该能够通过明智的选择工具和工作流来促进你的组织,文化就是一切。
|
||||
招聘以适合或加强现有的文化在 DevOps 和敏捷团多中是必不可少的。也就是说雇佣到一个能够鼓励积极合作的人,以便来自不同背景,有着不同目标和工作方式的团队能够在一起有效的工作。你新雇佣的员工应该能够帮助团队合作来充分发挥放大他们的价值,同时也能够增加员工的满意度以及平衡组织目标的冲突。他或者她应该能够通过明智的选择工具和工作流来促进你的组织,文化就是一切。
|
||||
|
||||
作为我们 2017 年 11 月发布的一篇文章 [DevOps 的招聘经理应该准备回答的 20 个问题][4] 的回应,这篇文章将会重点关注在如何招聘最适合的人。
|
||||
|
||||
作为我们2017年11月发布的一篇文章,[DevOps的招聘经理应该准备回答的20个问题][4],这篇文章将会重点关注在如何招聘最适合的人。
|
||||
### 为什么招聘走错了方向
|
||||
很多公司现在在用的典型的雇佣策略是基于人才过剩的基础上:
|
||||
|
||||
* 职位公告栏。
|
||||
* 关注和所需才能符合的应聘者。
|
||||
很多公司现在用的典型的雇佣策略是基于人才过剩的基础上:
|
||||
|
||||
* 在职位公告栏发布招聘。
|
||||
* 关注具有所需才能的应聘者。
|
||||
* 尽可能找多的候选者。
|
||||
* 通过面试淘汰弱者。
|
||||
* 通过正式的面试淘汰更多的弱者。
|
||||
@@ -30,37 +38,48 @@ DevOps应聘者应该准备回答的20个问题
|
||||

|
||||
|
||||
职位公告栏是有成千上万失业者人才过剩的经济大萧条时期发明的。在今天的求职市场上已经没有人才过剩了,然而我们仍然在使用基于此的招聘策略。
|
||||
|
||||

|
||||
|
||||
### 雇佣最合适的人员:运用文化和情感
|
||||
在人才过剩雇佣策略背后的思想是去设计工作岗位然后将人员安排进去。
|
||||
相反,做相反的事情:寻找将会积极融入你的商业文化的人才,然后为他们寻找他们热爱的最合适的岗位。要想如此实现,你必须能够围绕他们热情为他们创造工作岗位。
|
||||
**谁正在寻找一份工作?** 根据一份2016年对美国50,000名开发者的调查显示,[85.7%的受访对象][5]要么对新的机会不感兴趣,要么对于寻找新工作没有积极性。在寻找工作的那部分中,有将近[28.3%的求职者][5]来自于朋友的推荐。如果你只是在那些在找工作的人中寻找人才,你将会错过高端的人才。
|
||||
**运用团队力量去发现和寻找潜力的雇员**。列如,戴安娜是你的团队中的一名开发者,她所提供的机会即使她已经从事编程很多年而且在期间已经结识了很多从事热爱他们所从事的工作的人。难道你不认为她所推荐的潜在员工在技能,知识和智慧上要比HR所寻找的要优秀吗?在要求戴安娜分享她同伴之前,通知她即将到来的使命任务,向她阐明你要雇佣潜在有探索精神的团队,描述在将来会需要的知识领域。
|
||||
**雇员想要什么?**一份来自千禧年,婴儿潮实时期出生的人的对比综合性研究显示,20% 的人所想要的是相同的:
|
||||
|
||||
在人才过剩雇佣策略背后的思想是设计工作岗位然后将人员安排进去。
|
||||
|
||||
反而应该反过来:寻找将会积极融入你的商业文化的人才,然后为他们寻找他们热爱的最合适的岗位。要想实现这样的目标,你必须能够围绕他们热情为他们创造工作岗位。
|
||||
|
||||
**谁正在寻找一份工作?** 根据一份 2016 年对美国 50000 名开发者的调查显示,[85.7% 的受访对象][5]要么对新的机会不感兴趣,要么对于寻找新工作没有积极性。在寻找工作的那部分中,有将近 [28.3% 的求职者][5]来自于朋友的推荐。如果你只是在那些在找工作的人中寻找人才,你将会错过高端的人才。
|
||||
|
||||
**运用团队力量去发现和寻找潜力的雇员**。例如,戴安娜是你的团队中的一名开发者,她所能提供的机会是,她已经[从事编程很多年][6]而且在期间已经结识了很多从事热爱他们所从事的工作的人。难道你不认为她所推荐的潜在员工在技能、知识和智慧上要比 HR 所寻找的要优秀吗?在要求戴安娜分享她同伴之前,通知她即将到来的使命任务,向她阐明你要雇佣潜在有探索精神的团队,描述在将来会需要的知识领域。
|
||||
|
||||
**雇员想要什么?**一份来自千禧年婴儿潮时期出生的人的对比综合性研究显示,20% 的人所想要的是相同的:
|
||||
|
||||
1. 对组织产生积极的影响
|
||||
2. 帮助解决社交或者环境上的挑战
|
||||
3. 和一群有动力的人一起工作
|
||||
|
||||
### 面试的挑战
|
||||
面试应该是招聘者和应聘者双方为了寻找最合适的人才进行的一次双方之间的对话。将面试聚焦在企业文化和情感对话两个问题上:这个应聘者将会丰富你的企业文化并且会热爱和你在一起工作吗?你能够在工作中帮他们取得成功吗?
|
||||
**对于招聘经理来说:** 每一次的面试都是你学习如何将自己的组织变得对未来的团队成员更有吸引力,并且每次积极的面试多都可能是你发现人才(即使你不会雇佣)的机会。每个人都将会记得积极有效的面试的经历。即使他们不会被雇佣,他们将会和他们的朋友谈论这次经历,你竟会得到一个被推荐的机会。这又很大的好处:如果你无法吸引到这个人才,你也将会从中学习吸取经验并且改善。
|
||||
**对面试者来说**:每次的面试都是你释放激情的机会
|
||||
|
||||
### 助你释放潜在雇员激情的20个问题
|
||||
面试应该是招聘者和应聘者双方为了寻找最合适的人才进行的一次双方之间的对话。将面试聚焦在企业文化和情感对话两个问题上:这个应聘者将会丰富你的企业文化并且会热爱和你在一起工作吗?你能够在工作中帮他们取得成功吗?
|
||||
|
||||
**对于招聘经理来说:** 每一次的面试都是你学习如何将自己的组织变得对未来的团队成员更有吸引力,并且每次积极的面试都可能是你发现人才(即使你不会雇佣)的机会。每个人都将会记得积极有效的面试的经历。即使他们不会被雇佣,他们将会和他们的朋友谈论这次经历,你会得到一个被推荐的机会。这有很大的好处:如果你无法吸引到这个人才,你也将会从中学习吸取经验并且改善。
|
||||
|
||||
**对面试者来说**:每次的面试都是你释放激情的机会。
|
||||
|
||||
### 助你释放潜在雇员激情的 20 个问题
|
||||
|
||||
1. 你热爱什么?
|
||||
2. “今天早晨我已经迫不及待的要去工作”你怎么看待这句话?
|
||||
2. “今天早晨我已经迫不及待的要去工作”,你怎么看待这句话?
|
||||
3. 你曾经最快乐的是什么?
|
||||
4. 你曾经解决问题的最典型的例子是什么,你是如何解决的?
|
||||
5. 你如何看待配对学习?
|
||||
6. 你到达办公室和离开办公室心里最先想到的是什么?
|
||||
7. 你如果你有一次改变你之前或者现在的共工作的一件事的机会,将会是什么事?
|
||||
8. 当你在这工作的时候,你最兴奋去学习什么?
|
||||
7. 你如果你有一次改变你之前或者现在的工作中的一件事的机会,将会是什么事?
|
||||
8. 当你在工作的时候,你最乐于去学习什么?
|
||||
9. 你的梦想是什么,你如何去实现?
|
||||
10. 你在学会如何去实现你的追求的时候想要或者需要什么?
|
||||
11. 你的价值观是什么?
|
||||
12. 你是如何坚守自己的价值观的?
|
||||
13. 平衡在你的生活中意味着什么?
|
||||
13. 在你的生活中平衡意味着什么?
|
||||
14. 你最引以为傲的工作交流能力是什么?为什么?
|
||||
15. 你最喜欢营造什么样的环境?
|
||||
16. 你喜欢别人怎样对待你?
|
||||
@@ -70,14 +89,13 @@ DevOps应聘者应该准备回答的20个问题
|
||||
20. 如果你正在雇佣我,你将会问我什么问题?
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/3/questions-devops-employees-should-answer
|
||||
|
||||
作者:[Catherine Louis][a]
|
||||
译者:[FelixYFZ](https://github.com/FelixYFZ)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,447 @@
|
||||
17 种查看 Linux 物理内存的方法
|
||||
=======
|
||||
|
||||
大多数系统管理员在遇到性能问题时会检查 CPU 和内存利用率。Linux 中有许多实用程序可以用于检查物理内存。这些命令有助于我们检查系统中存在的物理内存,还允许用户检查各种方面的内存利用率。
|
||||
|
||||
我们大多数人只知道很少的命令,在本文中我们试图包含所有可能的命令。
|
||||
|
||||
你可能会想,为什么我想知道所有这些命令,而不是知道一些特定的和例行的命令呢。
|
||||
|
||||
不要觉得没用或对此有负面的看法,因为每个人都有不同的需求和看法,所以,对于那些在寻找其它目的的人,这对于他们非常有帮助。
|
||||
|
||||
### 什么是 RAM
|
||||
|
||||
计算机内存是能够临时或永久存储信息的物理设备。RAM 代表随机存取存储器,它是一种易失性存储器,用于存储操作系统,软件和硬件使用的信息。
|
||||
|
||||
有两种类型的内存可供选择:
|
||||
|
||||
* 主存
|
||||
* 辅助内存
|
||||
|
||||
主存是计算机的主存储器。CPU 可以直接读取或写入此内存。它固定在电脑的主板上。
|
||||
|
||||
* **RAM**:随机存取存储器是临时存储。关闭计算机后,此信息将消失。
|
||||
* **ROM**: 只读存储器是永久存储,即使系统关闭也能保存数据。
|
||||
|
||||
### 方法-1:使用 free 命令
|
||||
|
||||
`free` 显示系统中空闲和已用的物理内存和交换内存的总量,以及内核使用的缓冲区和缓存。它通过解析 `/proc/meminfo` 来收集信息。
|
||||
|
||||
**建议阅读:** [free – 在 Linux 系统中检查内存使用情况统计(空闲和已用)的标准命令][1]
|
||||
|
||||
```
|
||||
$ free -m
|
||||
total used free shared buff/cache available
|
||||
Mem: 1993 1681 82 81 228 153
|
||||
Swap: 12689 1213 11475
|
||||
|
||||
$ free -g
|
||||
total used free shared buff/cache available
|
||||
Mem: 1 1 0 0 0 0
|
||||
Swap: 12 1 11
|
||||
```
|
||||
|
||||
### 方法-2:使用 /proc/meminfo 文件
|
||||
|
||||
`/proc/meminfo` 是一个虚拟文本文件,它包含有关系统 RAM 使用情况的大量有价值的信息。
|
||||
|
||||
它报告系统上的空闲和已用内存(物理和交换)的数量。
|
||||
|
||||
```
|
||||
$ grep MemTotal /proc/meminfo
|
||||
MemTotal: 2041396 kB
|
||||
|
||||
$ grep MemTotal /proc/meminfo | awk '{print $2 / 1024}'
|
||||
1993.55
|
||||
|
||||
$ grep MemTotal /proc/meminfo | awk '{print $2 / 1024 / 1024}'
|
||||
1.94683
|
||||
```
|
||||
|
||||
### 方法-3:使用 top 命令
|
||||
|
||||
`top` 命令是 Linux 中监视实时系统进程的基本命令之一。它显示系统信息和运行的进程信息,如正常运行时间、平均负载、正在运行的任务、登录的用户数、CPU 数量和 CPU 利用率,以及内存和交换信息。运行 `top` 命令,然后按下 `E` 来使内存利用率以 MB 为单位显示。
|
||||
|
||||
**建议阅读:** [TOP 命令示例监视服务器性能][2]
|
||||
|
||||
```
|
||||
$ top
|
||||
|
||||
top - 14:38:36 up 1:59, 1 user, load average: 1.83, 1.60, 1.52
|
||||
Tasks: 223 total, 2 running, 221 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu(s): 48.6 us, 11.2 sy, 0.0 ni, 39.3 id, 0.3 wa, 0.0 hi, 0.5 si, 0.0 st
|
||||
MiB Mem : 1993.551 total, 94.184 free, 1647.367 used, 252.000 buff/cache
|
||||
MiB Swap: 12689.58+total, 11196.83+free, 1492.750 used. 306.465 avail Mem
|
||||
|
||||
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
|
||||
9908 daygeek 20 0 2971440 649324 39700 S 55.8 31.8 11:45.74 Web Content
|
||||
21942 daygeek 20 0 2013760 308700 69272 S 35.0 15.1 4:13.75 Web Content
|
||||
4782 daygeek 20 0 3687116 227336 39156 R 14.5 11.1 16:47.45 gnome-shell
|
||||
```
|
||||
|
||||
### 方法-4:使用 vmstat 命令
|
||||
|
||||
`vmstat` 是一个漂亮的标准工具,它报告 Linux 系统的虚拟内存统计信息。`vmstat` 报告有关进程、内存、分页、块 IO、陷阱和 CPU 活动的信息。它有助于 Linux 管理员在故障检修时识别系统瓶颈。
|
||||
|
||||
**建议阅读:** [vmstat – 一个报告虚拟内存统计信息的标准且漂亮的工具][3]
|
||||
|
||||
```
|
||||
$ vmstat -s | grep "total memory"
|
||||
2041396 K total memory
|
||||
|
||||
$ vmstat -s -S M | egrep -ie 'total memory'
|
||||
1993 M total memory
|
||||
|
||||
$ vmstat -s | awk '{print $1 / 1024 / 1024}' | head -1
|
||||
1.94683
|
||||
|
||||
```
|
||||
|
||||
### 方法-5:使用 nmon 命令
|
||||
|
||||
`nmon` 是另一个很棒的工具,用于在 Linux 终端上监视各种系统资源,如 CPU、内存、网络、磁盘、文件系统、NFS、top 进程、Power 的微分区和资源(Linux 版本和处理器)。
|
||||
|
||||
只需按下 `m` 键,即可查看内存利用率统计数据(缓存、活动、非活动、缓冲、空闲,以 MB 和百分比为单位)。
|
||||
|
||||
**建议阅读:** [nmon – Linux 中一个监视系统资源的漂亮的工具][4]
|
||||
|
||||
```
|
||||
┌nmon─14g──────[H for help]───Hostname=2daygeek──Refresh= 2secs ───07:24.44─────────────────┐
|
||||
│ Memory Stats ─────────────────────────────────────────────────────────────────────────────│
|
||||
│ RAM High Low Swap Page Size=4 KB │
|
||||
│ Total MB 32079.5 -0.0 -0.0 20479.0 │
|
||||
│ Free MB 11205.0 -0.0 -0.0 20479.0 │
|
||||
│ Free Percent 34.9% 100.0% 100.0% 100.0% │
|
||||
│ MB MB MB │
|
||||
│ Cached= 19763.4 Active= 9617.7 │
|
||||
│ Buffers= 172.5 Swapcached= 0.0 Inactive = 10339.6 │
|
||||
│ Dirty = 0.0 Writeback = 0.0 Mapped = 11.0 │
|
||||
│ Slab = 636.6 Commit_AS = 118.2 PageTables= 3.5 │
|
||||
│───────────────────────────────────────────────────────────────────────────────────────────│
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
└───────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 方法-6:使用 dmidecode 命令
|
||||
|
||||
`dmidecode` 是一个读取计算机 DMI 表内容的工具,它以人类可读的格式显示系统硬件信息。(DMI 意即桌面管理接口,也有人说是读取的是 SMBIOS —— 系统管理 BIOS)
|
||||
|
||||
此表包含系统硬件组件的描述,以及其它有用信息,如序列号、制造商信息、发布日期和 BIOS 修改等。
|
||||
|
||||
**建议阅读:** [Dmidecode – 获取 Linux 系统硬件信息的简便方法][5]
|
||||
|
||||
```
|
||||
# dmidecode -t memory | grep Size:
|
||||
Size: 8192 MB
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: 8192 MB
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: 8192 MB
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: 8192 MB
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
Size: No Module Installed
|
||||
```
|
||||
|
||||
只打印已安装的 RAM 模块。
|
||||
|
||||
```
|
||||
# dmidecode -t memory | grep Size: | grep -v "No Module Installed"
|
||||
Size: 8192 MB
|
||||
Size: 8192 MB
|
||||
Size: 8192 MB
|
||||
Size: 8192 MB
|
||||
```
|
||||
|
||||
汇总所有已安装的 RAM 模块。
|
||||
|
||||
```
|
||||
# dmidecode -t memory | grep Size: | grep -v "No Module Installed" | awk '{sum+=$2}END{print sum}'
|
||||
32768
|
||||
```
|
||||
|
||||
### 方法-7:使用 hwinfo 命令
|
||||
|
||||
`hwinfo` 意即硬件信息,它是另一个很棒的实用工具,用于探测系统中存在的硬件,并以人类可读的格式显示有关各种硬件组件的详细信息。
|
||||
|
||||
它报告有关 CPU、RAM、键盘、鼠标、图形卡、声音、存储、网络接口、磁盘、分区、BIOS 和网桥等的信息。
|
||||
|
||||
**建议阅读:** [hwinfo(硬件信息)– 一个在 Linux 系统上检测系统硬件信息的好工具][6]
|
||||
|
||||
```
|
||||
$ hwinfo --memory
|
||||
01: None 00.0: 10102 Main Memory
|
||||
[Created at memory.74]
|
||||
Unique ID: rdCR.CxwsZFjVASF
|
||||
Hardware Class: memory
|
||||
Model: "Main Memory"
|
||||
Memory Range: 0x00000000-0x7a4abfff (rw)
|
||||
Memory Size: 1 GB + 896 MB
|
||||
Config Status: cfg=new, avail=yes, need=no, active=unknown
|
||||
```
|
||||
|
||||
### 方法-8:使用 lshw 命令
|
||||
|
||||
`lshw`(代表 Hardware Lister)是一个小巧的工具,可以生成机器上各种硬件组件的详细报告,如内存配置、固件版本、主板配置、CPU 版本和速度、缓存配置、USB、网卡、显卡、多媒体、打印机、总线速度等。
|
||||
|
||||
它通过读取 `/proc` 目录和 DMI 表中的各种文件来生成硬件信息。
|
||||
|
||||
**建议阅读:** [LSHW (Hardware Lister) – 一个在 Linux 上获取硬件信息的好工具][7]
|
||||
|
||||
```
|
||||
$ sudo lshw -short -class memory
|
||||
[sudo] password for daygeek:
|
||||
H/W path Device Class Description
|
||||
==================================================
|
||||
/0/0 memory 128KiB BIOS
|
||||
/0/1 memory 1993MiB System memory
|
||||
```
|
||||
|
||||
### 方法-9:使用 inxi 命令
|
||||
|
||||
`inxi` 是一个很棒的工具,它可以检查 Linux 上的硬件信息,并提供了大量的选项来获取 Linux 系统上的所有硬件信息,这些特性是我在 Linux 上的其它工具中从未发现的。它是从 locsmif 编写的古老的但至今看来都异常灵活的 infobash 演化而来的。
|
||||
|
||||
`inxi` 是一个脚本,它可以快速显示系统硬件、CPU、驱动程序、Xorg、桌面、内核、GCC 版本、进程、RAM 使用情况以及各种其它有用的信息,还可以用于论坛技术支持和调试工具。
|
||||
|
||||
**建议阅读:** [inxi – 一个检查 Linux 上硬件信息的好工具][8]
|
||||
|
||||
```
|
||||
$ inxi -F | grep "Memory"
|
||||
Info: Processes: 234 Uptime: 3:10 Memory: 1497.3/1993.6MB Client: Shell (bash) inxi: 2.3.37
|
||||
```
|
||||
|
||||
### 方法-10:使用 screenfetch 命令
|
||||
|
||||
`screenfetch` 是一个 bash 脚本。它将自动检测你的发行版,并在右侧显示该发行版标识的 ASCII 艺术版本和一些有价值的信息。
|
||||
|
||||
**建议阅读:** [ScreenFetch – 以 ASCII 艺术标志在终端显示 Linux 系统信息][9]
|
||||
|
||||
```
|
||||
$ screenfetch
|
||||
./+o+- daygeek@ubuntu
|
||||
yyyyy- -yyyyyy+ OS: Ubuntu 17.10 artful
|
||||
://+//////-yyyyyyo Kernel: x86_64 Linux 4.13.0-37-generic
|
||||
.++ .:/++++++/-.+sss/` Uptime: 44m
|
||||
.:++o: /++++++++/:--:/- Packages: 1831
|
||||
o:+o+:++.`..`` `.-/oo+++++/ Shell: bash 4.4.12
|
||||
.:+o:+o/. `+sssoo+/ Resolution: 1920x955
|
||||
.++/+:+oo+o:` /sssooo. DE: GNOME
|
||||
/+++//+:`oo+o /::--:. WM: GNOME Shell
|
||||
\+/+o+++`o++o ++////. WM Theme: Adwaita
|
||||
.++.o+++oo+:` /dddhhh. GTK Theme: Azure [GTK2/3]
|
||||
.+.o+oo:. `oddhhhh+ Icon Theme: Papirus-Dark
|
||||
\+.++o+o``-````.:ohdhhhhh+ Font: Ubuntu 11
|
||||
`:o+++ `ohhhhhhhhyo++os: CPU: Intel Core i7-6700HQ @ 2x 2.592GHz
|
||||
.o:`.syhhhhhhh/.oo++o` GPU: llvmpipe (LLVM 5.0, 256 bits)
|
||||
/osyyyyyyo++ooo+++/ RAM: 1521MiB / 1993MiB
|
||||
````` +oo+++o\:
|
||||
`oo++.
|
||||
```
|
||||
|
||||
### 方法-11:使用 neofetch 命令
|
||||
|
||||
`neofetch` 是一个跨平台且易于使用的命令行(CLI)脚本,它收集你的 Linux 系统信息,并将其作为一张图片显示在终端上,也可以是你的发行版徽标,或者是你选择的任何 ascii 艺术。
|
||||
|
||||
**建议阅读:** [Neofetch – 以 ASCII 分发标志来显示 Linux 系统信息][10]
|
||||
|
||||
```
|
||||
$ neofetch
|
||||
.-/+oossssoo+/-. daygeek@ubuntu
|
||||
`:+ssssssssssssssssss+:` --------------
|
||||
-+ssssssssssssssssssyyssss+- OS: Ubuntu 17.10 x86_64
|
||||
.ossssssssssssssssssdMMMNysssso. Host: VirtualBox 1.2
|
||||
/ssssssssssshdmmNNmmyNMMMMhssssss/ Kernel: 4.13.0-37-generic
|
||||
+ssssssssshmydMMMMMMMNddddyssssssss+ Uptime: 47 mins
|
||||
/sssssssshNMMMyhhyyyyhmNMMMNhssssssss/ Packages: 1832
|
||||
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Shell: bash 4.4.12
|
||||
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ Resolution: 1920x955
|
||||
ossyNMMMNyMMhsssssssssssssshmmmhssssssso DE: ubuntu:GNOME
|
||||
ossyNMMMNyMMhsssssssssssssshmmmhssssssso WM: GNOME Shell
|
||||
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ WM Theme: Adwaita
|
||||
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Theme: Azure [GTK3]
|
||||
/sssssssshNMMMyhhyyyyhdNMMMNhssssssss/ Icons: Papirus-Dark [GTK3]
|
||||
+sssssssssdmydMMMMMMMMddddyssssssss+ Terminal: gnome-terminal
|
||||
/ssssssssssshdmNNNNmyNMMMMhssssss/ CPU: Intel i7-6700HQ (2) @ 2.591GHz
|
||||
.ossssssssssssssssssdMMMNysssso. GPU: VirtualBox Graphics Adapter
|
||||
-+sssssssssssssssssyyyssss+- Memory: 1620MiB / 1993MiB
|
||||
`:+ssssssssssssssssss+:`
|
||||
.-/+oossssoo+/-.
|
||||
```
|
||||
|
||||
### 方法-12:使用 dmesg 命令
|
||||
|
||||
`dmesg`(代表显示消息或驱动消息)是大多数类 Unix 操作系统上的命令,用于打印内核的消息缓冲区。
|
||||
|
||||
```
|
||||
$ dmesg | grep "Memory"
|
||||
[ 0.000000] Memory: 1985916K/2096696K available (12300K kernel code, 2482K rwdata, 4000K rodata, 2372K init, 2368K bss, 110780K reserved, 0K cma-reserved)
|
||||
[ 0.012044] x86/mm: Memory block size: 128MB
|
||||
```
|
||||
|
||||
### 方法-13:使用 atop 命令
|
||||
|
||||
`atop` 是一个用于 Linux 的 ASCII 全屏系统性能监视工具,它能报告所有服务器进程的活动(即使进程在间隔期间已经完成)。
|
||||
|
||||
它记录系统和进程活动以进行长期分析(默认情况下,日志文件保存 28 天),通过使用颜色等来突出显示过载的系统资源。它结合可选的内核模块 netatop 显示每个进程或线程的网络活动。
|
||||
|
||||
**建议阅读:** [Atop – 实时监控系统性能,资源,进程和检查资源利用历史][11]
|
||||
|
||||
```
|
||||
$ atop -m
|
||||
|
||||
ATOP - ubuntu 2018/03/31 19:34:08 ------------- 10s elapsed
|
||||
PRC | sys 0.47s | user 2.75s | | | #proc 219 | #trun 1 | #tslpi 802 | #tslpu 0 | #zombie 0 | clones 7 | | | #exit 4 |
|
||||
CPU | sys 7% | user 22% | irq 0% | | | idle 170% | wait 0% | | steal 0% | guest 0% | | curf 2.59GHz | curscal ?% |
|
||||
cpu | sys 3% | user 11% | irq 0% | | | idle 85% | cpu001 w 0% | | steal 0% | guest 0% | | curf 2.59GHz | curscal ?% |
|
||||
cpu | sys 4% | user 11% | irq 0% | | | idle 85% | cpu000 w 0% | | steal 0% | guest 0% | | curf 2.59GHz | curscal ?% |
|
||||
CPL | avg1 1.98 | | avg5 3.56 | avg15 3.20 | | | csw 14894 | | intr 6610 | | | numcpu 2 | |
|
||||
MEM | tot 1.9G | free 101.7M | cache 244.2M | dirty 0.2M | buff 6.9M | slab 92.9M | slrec 35.6M | shmem 97.8M | shrss 21.0M | shswp 3.2M | vmbal 0.0M | hptot 0.0M | hpuse 0.0M |
|
||||
SWP | tot 12.4G | free 11.6G | | | | | | | | | vmcom 7.9G | | vmlim 13.4G |
|
||||
PAG | scan 0 | steal 0 | | stall 0 | | | | | | | swin 3 | | swout 0 |
|
||||
DSK | sda | busy 0% | | read 114 | write 37 | KiB/r 21 | KiB/w 6 | | MBr/s 0.2 | MBw/s 0.0 | avq 6.50 | | avio 0.26 ms |
|
||||
NET | transport | tcpi 11 | tcpo 17 | udpi 4 | udpo 8 | tcpao 3 | tcppo 0 | | tcprs 3 | tcpie 0 | tcpor 0 | udpnp 0 | udpie 0 |
|
||||
NET | network | ipi 20 | | ipo 33 | ipfrw 0 | deliv 20 | | | | | icmpi 5 | | icmpo 0 |
|
||||
NET | enp0s3 0% | pcki 11 | pcko 28 | sp 1000 Mbps | si 1 Kbps | so 1 Kbps | | coll 0 | mlti 0 | erri 0 | erro 0 | drpi 0 | drpo 0 |
|
||||
NET | lo ---- | pcki 9 | pcko 9 | sp 0 Mbps | si 0 Kbps | so 0 Kbps | | coll 0 | mlti 0 | erri 0 | erro 0 | drpi 0 | drpo 0 |
|
||||
|
||||
PID TID MINFLT MAJFLT VSTEXT VSLIBS VDATA VSTACK VSIZE RSIZE PSIZE VGROW RGROW SWAPSZ RUID EUID MEM CMD 1/1
|
||||
2536 - 941 0 188K 127.3M 551.2M 144K 2.3G 281.2M 0K 0K 344K 6556K daygeek daygeek 14% Web Content
|
||||
2464 - 75 0 188K 187.7M 680.6M 132K 2.3G 226.6M 0K 0K 212K 42088K daygeek daygeek 11% firefox
|
||||
2039 - 4199 6 16K 163.6M 423.0M 132K 3.5G 220.2M 0K 0K 2936K 109.6M daygeek daygeek 11% gnome-shell
|
||||
10822 - 1 0 4K 16680K 377.0M 132K 3.4G 193.4M 0K 0K 0K 0K root root 10% java
|
||||
```
|
||||
|
||||
### 方法-14:使用 htop 命令
|
||||
|
||||
`htop` 是由 Hisham 用 ncurses 库开发的用于 Linux 的交互式进程查看器。与 `top` 命令相比,`htop` 有许多特性和选项。
|
||||
|
||||
**建议阅读:** [使用 Htop 命令监视系统资源][12]
|
||||
|
||||
```
|
||||
$ htop
|
||||
|
||||
1 [||||||||||||| 13.0%] Tasks: 152, 587 thr; 1 running
|
||||
2 [||||||||||||||||||||||||| 25.0%] Load average: 0.91 2.03 2.66
|
||||
Mem[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||1.66G/1.95G] Uptime: 01:14:53
|
||||
Swp[|||||| 782M/12.4G]
|
||||
|
||||
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
|
||||
2039 daygeek 20 0 3541M 214M 46728 S 36.6 10.8 22:36.77 /usr/bin/gnome-shell
|
||||
2045 daygeek 20 0 3541M 214M 46728 S 10.3 10.8 3:02.92 /usr/bin/gnome-shell
|
||||
2046 daygeek 20 0 3541M 214M 46728 S 8.3 10.8 3:04.96 /usr/bin/gnome-shell
|
||||
6080 daygeek 20 0 807M 37228 24352 S 2.1 1.8 0:11.99 /usr/lib/gnome-terminal/gnome-terminal-server
|
||||
2880 daygeek 20 0 2205M 164M 17048 S 2.1 8.3 7:16.50 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51:0|57:128|58:10000|63:0|65:400|66
|
||||
6125 daygeek 20 0 1916M 159M 92352 S 2.1 8.0 2:09.14 /usr/lib/firefox/firefox -contentproc -childID 7 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51:0|57:128|58:10000|63:0|65:400|66
|
||||
2536 daygeek 20 0 2335M 243M 26792 S 2.1 12.2 6:25.77 /usr/lib/firefox/firefox -contentproc -childID 1 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51:0|57:128|58:10000|63:0|65:400|66
|
||||
2653 daygeek 20 0 2237M 185M 20788 S 1.4 9.3 3:01.76 /usr/lib/firefox/firefox -contentproc -childID 4 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51:0|57:128|58:10000|63:0|65:400|66
|
||||
```
|
||||
|
||||
### 方法-15:使用 corefreq 实用程序
|
||||
|
||||
CoreFreq 是为 Intel 64 位处理器设计的 CPU 监控软件,支持的架构有 Atom、Core2、Nehalem、SandyBridge 和 superior,AMD 家族 0F。
|
||||
|
||||
CoreFreq 提供了一个框架来以高精确度检索 CPU 数据。
|
||||
|
||||
**建议阅读:** [CoreFreq – 一个用于 Linux 系统的强大的 CPU 监控工具][13]
|
||||
|
||||
```
|
||||
$ ./corefreq-cli -k
|
||||
Linux:
|
||||
|- Release [4.13.0-37-generic]
|
||||
|- Version [#42-Ubuntu SMP Wed Mar 7 14:13:23 UTC 2018]
|
||||
|- Machine [x86_64]
|
||||
Memory:
|
||||
|- Total RAM 2041396 KB
|
||||
|- Shared RAM 99620 KB
|
||||
|- Free RAM 108428 KB
|
||||
|- Buffer RAM 8108 KB
|
||||
|- Total High 0 KB
|
||||
|- Free High 0 KB
|
||||
```
|
||||
|
||||
### 方法-16:使用 glances 命令
|
||||
|
||||
Glances 是用 Python 编写的跨平台基于 curses(LCTT 译注:curses 是一个 Linux/Unix 下的图形函数库)的系统监控工具。我们可以说它一应俱全,就像在最小的空间含有最大的信息。它使用 psutil 库从系统中获取信息。
|
||||
|
||||
Glances 可以监视 CPU、内存、负载、进程列表、网络接口、磁盘 I/O、Raid、传感器、文件系统(和文件夹)、Docker、监视器、警报、系统信息、正常运行时间、快速预览(CPU、内存、负载)等。
|
||||
|
||||
**建议阅读:** [Glances (一应俱全)– 一个 Linux 的高级的实时系
|
||||
统性能监控工具][14]
|
||||
|
||||
```
|
||||
$ glances
|
||||
|
||||
ubuntu (Ubuntu 17.10 64bit / Linux 4.13.0-37-generic) - IP 192.168.1.6/24 Uptime: 1:08:40
|
||||
|
||||
CPU [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 90.6%] CPU - 90.6% nice: 0.0% ctx_sw: 4K MEM \ 78.4% active: 942M SWAP - 5.9% LOAD 2-core
|
||||
MEM [||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 78.0%] user: 55.1% irq: 0.0% inter: 1797 total: 1.95G inactive: 562M total: 12.4G 1 min: 4.35
|
||||
SWAP [|||| 5.9%] system: 32.4% iowait: 1.8% sw_int: 897 used: 1.53G buffers: 14.8M used: 749M 5 min: 4.38
|
||||
idle: 7.6% steal: 0.0% free: 431M cached: 273M free: 11.7G 15 min: 3.38
|
||||
|
||||
NETWORK Rx/s Tx/s TASKS 211 (735 thr), 4 run, 207 slp, 0 oth sorted automatically by memory_percent, flat view
|
||||
docker0 0b 232b
|
||||
enp0s3 12Kb 4Kb Systemd 7 Services loaded: 197 active: 196 failed: 1
|
||||
lo 616b 616b
|
||||
_h478e48e 0b 232b CPU% MEM% VIRT RES PID USER NI S TIME+ R/s W/s Command
|
||||
63.8 18.9 2.33G 377M 2536 daygeek 0 R 5:57.78 0 0 /usr/lib/firefox/firefox -contentproc -childID 1 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
|
||||
DefaultGateway 83ms 78.5 10.9 3.46G 217M 2039 daygeek 0 S 21:07.46 0 0 /usr/bin/gnome-shell
|
||||
8.5 10.1 2.32G 201M 2464 daygeek 0 S 8:45.69 0 0 /usr/lib/firefox/firefox -new-window
|
||||
DISK I/O R/s W/s 1.1 8.5 2.19G 170M 2653 daygeek 0 S 2:56.29 0 0 /usr/lib/firefox/firefox -contentproc -childID 4 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
|
||||
dm-0 0 0 1.7 7.2 2.15G 143M 2880 daygeek 0 S 7:10.46 0 0 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
|
||||
sda1 9.46M 12K 0.0 4.9 1.78G 97.2M 6125 daygeek 0 S 1:36.57 0 0 /usr/lib/firefox/firefox -contentproc -childID 7 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
|
||||
```
|
||||
|
||||
### 方法-17 : 使用 Gnome 系统监视器
|
||||
|
||||
Gnome 系统监视器是一个管理正在运行的进程和监视系统资源的工具。它向你显示正在运行的程序以及耗费的处理器时间,内存和磁盘空间。
|
||||
|
||||
![][16]
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/easy-ways-to-check-size-of-physical-memory-ram-in-linux/
|
||||
|
||||
作者:[Ramya Nuvvula][a]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.2daygeek.com/author/ramya/
|
||||
[1]:https://www.2daygeek.com/free-command-to-check-memory-usage-statistics-in-linux/
|
||||
[2]:https://www.2daygeek.com/top-command-examples-to-monitor-server-performance/
|
||||
[3]:https://www.2daygeek.com/linux-vmstat-command-examples-tool-report-virtual-memory-statistics/
|
||||
[4]:https://www.2daygeek.com/nmon-system-performance-monitor-system-resources-on-linux/
|
||||
[5]:https://www.2daygeek.com/dmidecode-get-print-display-check-linux-system-hardware-information/
|
||||
[6]:https://www.2daygeek.com/hwinfo-check-display-detect-system-hardware-information-linux/
|
||||
[7]:https://www.2daygeek.com/lshw-find-check-system-hardware-information-details-linux/
|
||||
[8]:https://www.2daygeek.com/inxi-system-hardware-information-on-linux/
|
||||
[9]:https://www.2daygeek.com/screenfetch-display-linux-systems-information-ascii-distribution-logo-terminal/
|
||||
[10]:https://www.2daygeek.com/neofetch-display-linux-systems-information-ascii-distribution-logo-terminal/
|
||||
[11]:https://www.2daygeek.com/atop-system-process-performance-monitoring-tool/
|
||||
[12]:https://www.2daygeek.com/htop-command-examples-to-monitor-system-resources/
|
||||
[13]:https://www.2daygeek.com/corefreq-linux-cpu-monitoring-tool/
|
||||
[14]:https://www.2daygeek.com/install-glances-advanced-real-time-linux-system-performance-monitoring-tool-on-centos-fedora-ubuntu-debian-opensuse-arch-linux/
|
||||
[15]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[16]:https://www.2daygeek.com/wp-content/uploads/2018/03/check-memory-information-using-gnome-system-monitor.png
|
||||
214
published/20180409 How to create LaTeX documents with Emacs.md
Normal file
214
published/20180409 How to create LaTeX documents with Emacs.md
Normal file
@@ -0,0 +1,214 @@
|
||||
如何使用 Emacs 创建 LaTeX 文档
|
||||
======
|
||||
> 这篇教程将带你遍历在 Emacs 使用强大的开源排版系统 LaTex 来创建文档的全过程。
|
||||
|
||||

|
||||
|
||||
一篇由 Aaron Cocker 写的很棒的文章 “[在 LaTeX 中创建文件的介绍][1]” 中,介绍了 [LaTeX 排版系统][3] 并描述了如何使用 [TeXstudio][4] 来创建 LaTeX 文档。同时,他也列举了一些很多用户觉得创建 LaTeX 文档很方便的编辑器。
|
||||
|
||||
[Greg Pittman][5] 对这篇文章的评论吸引了我:“当你第一次开始使用 LaTeX 时,他似乎是个很差劲的排版……” 事实也确实如此。LaTeX 包含了多种排版字体和调试,如果你漏了一个特殊的字符比如说感叹号,这会让很多用户感到沮丧,尤其是新手。在本文中,我将介绍如何使用 [GNU Emacs][6] 来创建 LaTeX 文档。
|
||||
|
||||
### 创建你的第一个文档
|
||||
|
||||
启动 Emacs:
|
||||
|
||||
```
|
||||
emacs -q --no-splash helloworld.org
|
||||
```
|
||||
|
||||
参数 `-q` 确保 Emacs 不会加载其他的初始化配置。参数 `--no-splash-screen` 防止 Emacs 打开多个窗口,确保只打开一个窗口,最后的参数 `helloworld.org` 表示你要创建的文件名为 `helloworld.org` 。
|
||||
|
||||
![Emacs startup screen][8]
|
||||
|
||||
*GNU Emacs 打开文件名为 helloworld.org 的窗口时的样子。*
|
||||
|
||||
现在让我们用 Emacs 添加一些 LaTeX 的标题吧:在菜单栏找到 “Org” 选项并选择 “Export/Publish”。
|
||||
|
||||
![template_flow.png][10]
|
||||
|
||||
*导入一个默认的模板*
|
||||
|
||||
在下一个窗口中,Emacs 同时提供了导入和导出一个模板。输入 `#`(“[#] Insert template”)来导入一个模板。这将会使光标跳转到一个带有 “Options category:” 提示的 mini-buffer 中。第一次你可能不知道这个类型的名字,但是你可以使用 `Tab` 键来查看所有的补全。输入 “default” 然后按回车,之后你就能看到如下的内容被插入了:
|
||||
|
||||
```
|
||||
#+TITLE: helloworld
|
||||
#+DATE: <2018-03-12 Mon>
|
||||
#+AUTHOR:
|
||||
#+EMAIL: makerpm@nubia
|
||||
#+OPTIONS: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
|
||||
#+OPTIONS: author:t c:nil creator:comment d:(not "LOGBOOK") date:t
|
||||
#+OPTIONS: e:t email:nil f:t inline:t num:t p:nil pri:nil stat:t
|
||||
#+OPTIONS: tags:t tasks:t tex:t timestamp:t toc:t todo:t |:t
|
||||
#+CREATOR: Emacs 25.3.1 (Org mode 8.2.10)
|
||||
#+DESCRIPTION:
|
||||
#+EXCLUDE_TAGS: noexport
|
||||
#+KEYWORDS:
|
||||
#+LANGUAGE: en
|
||||
#+SELECT_TAGS: export
|
||||
```
|
||||
|
||||
根据自己的需求修改标题、日期、作者和 email。我自己的话是下面这样的:
|
||||
|
||||
```
|
||||
#+TITLE: Hello World! My first LaTeX document
|
||||
#+DATE: \today
|
||||
#+AUTHOR: Sachin Patil
|
||||
#+EMAIL: psachin@redhat.com
|
||||
```
|
||||
|
||||
我们目前还不想创建一个目录,所以要将 `toc` 的值由 `t` 改为 `nil`,具体如下:
|
||||
|
||||
```
|
||||
#+OPTIONS: tags:t tasks:t tex:t timestamp:t toc:nil todo:t |:t
|
||||
```
|
||||
|
||||
现在让我们添加一个章节和段落吧。章节是由一个星号(`*`)开头。我们从 Aaron 的贴子(来自 [Lipsum Lorem Ipsum 生成器][11])复制一些文本过来:
|
||||
|
||||
```
|
||||
* Introduction
|
||||
|
||||
\paragraph{}
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras lorem
|
||||
nisi, tincidunt tempus sem nec, elementum feugiat ipsum. Nulla in
|
||||
diam libero. Nunc tristique ex a nibh egestas sollicitudin.
|
||||
|
||||
\paragraph{}
|
||||
Mauris efficitur vitae ex id egestas. Vestibulum ligula felis,
|
||||
pulvinar a posuere id, luctus vitae leo. Sed ac imperdiet orci, non
|
||||
elementum leo. Nullam molestie congue placerat. Phasellus tempor et
|
||||
libero maximus commodo.
|
||||
```
|
||||
|
||||
|
||||
![helloworld_file.png][13]
|
||||
|
||||
*helloworld.org 文件*
|
||||
|
||||
|
||||
将内容修改好后,我们要把它导出为 PDF 格式。再次在 “Org” 的菜单选项中选择 “Export/Publish”,但是这次,要输入 `l`(“export to LaTeX”),紧跟着输入 `o`(“as PDF file and open”)。这次操作不止会打开 PDF 文件让你浏览,同时也会将文件保存为 `helloworld.pdf`,并保存在与 `helloworld.org` 的同一个目录下。
|
||||
|
||||
![org_to_pdf.png][15]
|
||||
|
||||
*将 helloworld.org 导出为 helloworld.pdf*
|
||||
|
||||
![org_and_pdf_file.png][17]
|
||||
|
||||
*打开 helloworld.pdf 文件*
|
||||
|
||||
你也可以按下 `Alt + x` 键,然后输入 `org-latex-export-to-pdf` 来将 org 文件导出为 PDF 文件。可以使用 `Tab` 键来自动补全命令。
|
||||
|
||||
Emacs 也会创建 `helloworld.tex` 文件来让你控制具体的内容。
|
||||
|
||||
![org_tex_pdf.png][19]
|
||||
|
||||
*Emacs 在三个不同的窗口中分别打开 LaTeX,org 和 PDF 文档。*
|
||||
|
||||
你可以使用命令来将 `.tex` 文件转换为 `.pdf` 文件:
|
||||
|
||||
```
|
||||
pdflatex helloworld.tex
|
||||
```
|
||||
|
||||
你也可以将 `.org` 文件输出为 HTML 或是一个简单的文本格式的文件。我最喜欢 `.org` 文件的原因是他们可以被推送到 [GitHub][20] 上,然后同 markdown 一样被渲染。
|
||||
|
||||
### 创建一个 LaTeX 的 Beamer 简报
|
||||
|
||||
现在让我们更进一步,通过少量的修改上面的文档来创建一个 LaTeX [Beamer][21] 简报,如下所示:
|
||||
|
||||
```
|
||||
#+TITLE: LaTeX Beamer presentation
|
||||
#+DATE: \today
|
||||
#+AUTHOR: Sachin Patil
|
||||
#+EMAIL: psachin@redhat.com
|
||||
#+OPTIONS: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
|
||||
#+OPTIONS: author:t c:nil creator:comment d:(not "LOGBOOK") date:t
|
||||
#+OPTIONS: e:t email:nil f:t inline:t num:t p:nil pri:nil stat:t
|
||||
#+OPTIONS: tags:t tasks:t tex:t timestamp:t toc:nil todo:t |:t
|
||||
#+CREATOR: Emacs 25.3.1 (Org mode 8.2.10)
|
||||
#+DESCRIPTION:
|
||||
#+EXCLUDE_TAGS: noexport
|
||||
#+KEYWORDS:
|
||||
#+LANGUAGE: en
|
||||
#+SELECT_TAGS: export
|
||||
#+LATEX_CLASS: beamer
|
||||
#+BEAMER_THEME: Frankfurt
|
||||
#+BEAMER_INNER_THEME: rounded
|
||||
|
||||
|
||||
* Introduction
|
||||
*** Programming
|
||||
- Python
|
||||
- Ruby
|
||||
|
||||
*** Paragraph one
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing
|
||||
elit. Cras lorem nisi, tincidunt tempus sem nec, elementum feugiat
|
||||
ipsum. Nulla in diam libero. Nunc tristique ex a nibh egestas
|
||||
sollicitudin.
|
||||
|
||||
*** Paragraph two
|
||||
|
||||
Mauris efficitur vitae ex id egestas. Vestibulum
|
||||
ligula felis, pulvinar a posuere id, luctus vitae leo. Sed ac
|
||||
imperdiet orci, non elementum leo. Nullam molestie congue
|
||||
placerat. Phasellus tempor et libero maximus commodo.
|
||||
|
||||
* Thanks
|
||||
*** Links
|
||||
- Link one
|
||||
- Link two
|
||||
```
|
||||
|
||||
我们给标题增加了三行:
|
||||
|
||||
```
|
||||
#+LATEX_CLASS: beamer
|
||||
#+BEAMER_THEME: Frankfurt
|
||||
#+BEAMER_INNER_THEME: rounded
|
||||
```
|
||||
|
||||
导出为 PDF,按下 `Alt + x` 键后输入 `org-beamer-export-to-pdf`。
|
||||
|
||||
![latex_beamer_presentation.png][23]
|
||||
|
||||
*用 Emacs 和 Org 模式创建的 Latex Beamer 简报*
|
||||
|
||||
希望你会爱上使用 Emacs 来创建 LaTex 和 Beamer 文档(注意:使用快捷键比用鼠标更快些)。Emacs 的 Org 模式提供了比我在这篇文章中说的更多的功能,你可以在 [orgmode.org][24] 获取更多的信息.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/4/how-create-latex-documents-emacs
|
||||
|
||||
作者:[Sachin Patil][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[oneforalone](https://github.com/oneforalone)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/psachin
|
||||
[1]:https://opensource.com/article/17/6/introduction-latex
|
||||
[2]:https://opensource.com/users/aaroncocker
|
||||
[3]:https://www.latex-project.org
|
||||
[4]:http://www.texstudio.org/
|
||||
[5]:https://opensource.com/users/greg-p
|
||||
[6]:https://www.gnu.org/software/emacs/
|
||||
[7]:/file/392261
|
||||
[8]:https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/emacs_startup.png?itok=UnT4PgK5 (Emacs startup screen)
|
||||
[9]:/file/392266
|
||||
[10]:https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/insert_template_flow.png?itok=V_c2KipO (template_flow.png)
|
||||
[11]:https://www.lipsum.com/feed/html
|
||||
[12]:/file/392271
|
||||
[13]:https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/helloworld_file.png?itok=o8IX0TsJ (helloworld_file.png)
|
||||
[14]:/file/392276
|
||||
[15]:https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/org_to_pdf.png?itok=fNnC1Y-L (org_to_pdf.png)
|
||||
[16]:/file/392281
|
||||
[17]:https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/org_and_pdf_file.png?itok=HEhtw-cu (org_and_pdf_file.png)
|
||||
[18]:/file/392286
|
||||
[19]:https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/org_tex_pdf.png?itok=poZZV_tj (org_tex_pdf.png)
|
||||
[20]:https://github.com
|
||||
[21]:https://www.sharelatex.com/learn/Beamer
|
||||
[22]:/file/392291
|
||||
[23]:https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/latex_beamer_presentation.png?itok=rsPSeIuM (latex_beamer_presentation.png)
|
||||
[24]:https://orgmode.org/worg/org-tutorials/org-latex-export.html
|
||||
139
published/20180417 How To Browse Stack Overflow From Terminal.md
Normal file
139
published/20180417 How To Browse Stack Overflow From Terminal.md
Normal file
@@ -0,0 +1,139 @@
|
||||
如何在终端中浏览 Stack Overflow
|
||||
======
|
||||
|
||||

|
||||
|
||||
前段时间,我们写了一篇关于 [SoCLI][1] 的文章,它是一个从命令行搜索和浏览 Stack Overflow 网站的 python 脚本。今天,我们将讨论一个名为 “how2” 的类似工具。它是一个命令行程序,可以从终端浏览 Stack Overflow。你可以如你在 [Google 搜索][2]中那样直接用英语查询,然后它会使用 Google 和 Stackoverflow API 来搜索给定的查询。它是使用 NodeJS 编写的自由开源程序。
|
||||
|
||||
### 使用 how2 从终端浏览 Stack Overflow
|
||||
|
||||
由于 `how2` 是一个 NodeJS 包,我们可以使用 Npm 包管理器安装它。如果你尚未安装 Npm 和 NodeJS,请参考以下指南。
|
||||
|
||||
在安装 Npm 和 NodeJS 后,运行以下命令安装 how2。
|
||||
|
||||
```
|
||||
$ npm install -g how2
|
||||
```
|
||||
|
||||
现在让我们看下如何使用这个程序浏览 Stack Overflow。使用 `how2` 搜索 Stack Overflow 站点的典型用法是:
|
||||
|
||||
```
|
||||
$ how2 <search-query>
|
||||
```
|
||||
|
||||
例如,我将搜索如何创建 tgz 存档。
|
||||
|
||||
```
|
||||
$ how2 create archive tgz
|
||||
```
|
||||
|
||||
哎呀!我收到以下错误。
|
||||
|
||||
```
|
||||
/home/sk/.nvm/versions/node/v9.11.1/lib/node_modules/how2/node_modules/devnull/transports/transport.js:59
|
||||
Transport.prototype.__proto__ = EventEmitter.prototype;
|
||||
^
|
||||
|
||||
TypeError: Cannot read property 'prototype' of undefined
|
||||
at Object.<anonymous> (/home/sk/.nvm/versions/node/v9.11.1/lib/node_modules/how2/node_modules/devnull/transports/transport.js:59:46)
|
||||
at Module._compile (internal/modules/cjs/loader.js:654:30)
|
||||
at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
|
||||
at Module.load (internal/modules/cjs/loader.js:566:32)
|
||||
at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
|
||||
at Function.Module._load (internal/modules/cjs/loader.js:498:3)
|
||||
at Module.require (internal/modules/cjs/loader.js:598:17)
|
||||
at require (internal/modules/cjs/helpers.js:11:18)
|
||||
at Object.<anonymous> (/home/sk/.nvm/versions/node/v9.11.1/lib/node_modules/how2/node_modules/devnull/transports/stream.js:8:17)
|
||||
at Module._compile (internal/modules/cjs/loader.js:654:30)
|
||||
|
||||
```
|
||||
|
||||
我可能遇到了一个 bug。我希望它在未来版本中得到修复。但是,我在[这里][3]找到了一个临时方法。
|
||||
|
||||
|
||||
要临时修复此错误,你需要使用以下命令编辑 `transport.js`:
|
||||
|
||||
```
|
||||
$ vi /home/sk/.nvm/versions/node/v9.11.1/lib/node_modules/how2/node_modules/devnull/transports/transport.js
|
||||
```
|
||||
|
||||
此文件的实际路径将显示在错误输出中。用你自己的文件路径替换上述文件路径。然后找到以下行:
|
||||
|
||||
```
|
||||
var EventEmitter = process.EventEmitter;
|
||||
```
|
||||
|
||||
并用以下行替换它:
|
||||
|
||||
```
|
||||
var EventEmitter = require('events');
|
||||
```
|
||||
|
||||
按 `ESC` 并输入 `:wq` 以保存并退出文件。
|
||||
|
||||
现在再次搜索查询。
|
||||
|
||||
```
|
||||
$ how2 create archive tgz
|
||||
```
|
||||
|
||||
这是我的 Ubuntu 系统的示例输出。
|
||||
|
||||
![][5]
|
||||
|
||||
如果你要查找的答案未显示在上面的输出中,请按**空格键**键开始交互式搜索,你可以通过它查看 Stack Overflow 站点中的所有建议问题和答案。
|
||||
|
||||
![][6]
|
||||
|
||||
使用向上/向下箭头在结果之间移动。得到正确的答案/问题后,点击空格键或回车键在终端中打开它。
|
||||
|
||||
![][7]
|
||||
|
||||
要返回并退出,请按 `ESC`。
|
||||
|
||||
**搜索特定语言的答案**
|
||||
|
||||
如果你没有指定语言,它**默认为 Bash** unix 命令行,并立即为你提供最可能的答案。你还可以将结果缩小到特定语言,例如 perl、python、c、Java 等。
|
||||
|
||||
例如,使用 `-l` 标志仅搜索与 “Python” 语言相关的查询,如下所示。
|
||||
|
||||
```
|
||||
$ how2 -l python linked list
|
||||
```
|
||||
|
||||
![][8]
|
||||
|
||||
要获得快速帮助,请输入:
|
||||
|
||||
```
|
||||
$ how2 -h
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
`how2` 是一个基本的命令行程序,它可以快速搜索 Stack Overflow 中的问题和答案,而无需离开终端,并且它可以很好地完成这项工作。但是,它只是 Stack overflow 的 CLI 浏览器。对于一些高级功能,例如搜索投票最多的问题,使用多个标签搜索查询,彩色界面,提交新问题和查看问题统计信息等,**SoCLI** 做得更好。
|
||||
|
||||
就是这些了。希望这篇文章有用。我将很快写一篇新的指南。在此之前,请继续关注!
|
||||
|
||||
干杯!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-browse-stack-overflow-from-terminal/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](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/
|
||||
[1]:https://www.ostechnix.com/search-browse-stack-overflow-website-commandline/
|
||||
[2]:https://www.ostechnix.com/google-search-navigator-enhance-keyboard-navigation-in-google-search/
|
||||
[3]:https://github.com/santinic/how2/issues/79
|
||||
[4]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[5]:http://www.ostechnix.com/wp-content/uploads/2018/04/stack-overflow-1.png
|
||||
[6]:http://www.ostechnix.com/wp-content/uploads/2018/04/stack-overflow-2.png
|
||||
[7]:http://www.ostechnix.com/wp-content/uploads/2018/04/stack-overflow-3.png
|
||||
[8]:http://www.ostechnix.com/wp-content/uploads/2018/04/stack-overflow-4.png
|
||||
@@ -1,43 +1,41 @@
|
||||
关于安全,开发人员需要知道的
|
||||
======
|
||||
(to 校正:有些长句子理解得不好,望见谅)
|
||||
> 开发人员不需要成为安全专家, 但他们确实需要摆脱将安全视为一些不幸障碍的心态。
|
||||
|
||||

|
||||
|
||||
DevOps 并不意味着每个人都需要成为开发和运维方面的专家。尤其在大型组织中,其中角色往往更加专业化。相反,DevOps 思想在某种程度上更多地是关注问题的分离。在某种程度上,运维团队可以为开发人员(无论是在本地云还是在公共云中)部署平台,并且不受影响,这对两个团队来说都是好消息。开发人员可以获得高效的开发环境和自助服务,运维人员可以专注于保持基础管道运行和维护平台。
|
||||
|
||||
这是一种约定。开发者期望从运维人员那里得到一个稳定和实用的平台,运维人员希望开发者能够自己处理与开发应用相关的大部分任务。
|
||||
|
||||
也就是说,DevOps 还涉及更好的沟通、合作和透明度。如果它不仅仅是一种介于开发和运维之间的新型壁垒,它的效果会更好。运维人员需要对开发者想要和需要的工具类型以及他们通过监视和日志记录来编写更好应用程序所需的可见性保持敏感。相反,开发人员需要了解如何才能使底层基础设施更有效地使用,以及什么能够在夜间(字面上)保持操作。(to 校正:这里意思是不是在无人时候操作)
|
||||
也就是说,DevOps 还涉及更好的沟通、合作和透明度。如果它不仅仅是一种介于开发和运维之间的新型壁垒,它的效果会更好。运维人员需要对开发者想要和需要的工具类型以及他们通过监视和日志记录来编写更好应用程序所需的可见性保持敏感。另一方面,开发人员需要了解如何才能更有效地使用底层基础设施,以及什么能够使运维在夜间(字面上)保持运行。
|
||||
|
||||
同样的原则也适用于更广泛的 DevSecOps,这个术语明确地提醒我们,安全需要嵌入到整个 DevOps 管道中,从获取内容到编写应用程序、构建应用程序、测试应用程序以及在生产环境中运行它们。开发人员(和运维人员)不需要突然成为安全专家,除了他们的其它角色。但是,他们通常可以从对安全最佳实践(这可能不同于他们已经习惯的)的更高认识中获益,并从将安全视为一些不幸障碍的心态中转变出来。
|
||||
同样的原则也适用于更广泛的 DevSecOps,这个术语明确地提醒我们,安全需要嵌入到整个 DevOps 管道中,从获取内容到编写应用程序、构建应用程序、测试应用程序以及在生产环境中运行它们。开发人员(和运维人员)除了他们已有的角色不需要突然成为安全专家。但是,他们通常可以从对安全最佳实践(这可能不同于他们已经习惯的)的更高认识中获益,并从将安全视为一些不幸障碍的心态中转变出来。
|
||||
|
||||
以下是一些观察结果。
|
||||
|
||||
开放式 Web 应用程序安全项目(Open Web Application Security Project)([OWASP][1])[Top 10 列表]提供了一个窗口,可以了解 Web 应用程序中的主要漏洞。列表中的许多条目对 Web 程序员来说都很熟悉。跨站脚本(XSS)和注入漏洞是最常见的。但令人震惊的是,2007 年列表中的许多漏洞仍在 2017 年的列表中([PDF][3])。无论是培训还是工具,都有问题,许多相同的编码漏洞在不断出现。(to 校正:这句话不清楚)
|
||||
<ruby>开放式 Web 应用程序安全项目<rt>Open Web Application Security Project</rt></ruby>([OWASP][1])[Top 10 列表]提供了一个窗口,可以了解 Web 应用程序中的主要漏洞。列表中的许多条目对 Web 程序员来说都很熟悉。跨站脚本(XSS)和注入漏洞是最常见的。但令人震惊的是,2007 年列表中的许多漏洞仍在 2017 年的列表中([PDF][3])。无论是培训还是工具,都有问题,许多同样的编码漏洞一再出现。
|
||||
|
||||
新平台技术加剧了这种情况。例如,虽然容器不一定要求应用程序以不同的方式编写,但是它们与新模式(例如[微服务][4])相吻合,并且可以放大某些对于安全实践的影响。例如,我的同事 [Dan Walsh][5]([@rhatdan][6])写道:“计算机领域最大的误解是需要 root 权限来运行应用程序,问题是并不是所有开发者都认为他们需要 root,而是他们将这种假设构建到他们建设的服务中,即服务无法在非 root 情况下运行,而这降低了安全性。”
|
||||
新的平台技术加剧了这种情况。例如,虽然容器不一定要求应用程序以不同的方式编写,但是它们与新模式(例如[微服务][4])相吻合,并且可以放大某些对于安全实践的影响。例如,我的同事 [Dan Walsh][5]([@rhatdan][6])写道:“计算机领域最大的误解是需要 root 权限来运行应用程序,问题是并不是所有开发者都认为他们需要 root,而是他们将这种假设构建到他们建设的服务中,即服务无法在非 root 情况下运行,而这降低了安全性。”
|
||||
|
||||
默认使用 root 访问是一个好的实践吗?并不是。但它可能(也许)是一个可以防御的应用程序和系统,否则就会被其它方法完全隔离。但是,由于所有东西都连接在一起,没有真正的边界,多用户工作负载,拥有许多不同级别访问权限的用户,更不用说更加危险的环境了,那么快捷方式的回旋余地就更小了。
|
||||
|
||||
[自动化][7]应该是 DevOps 不可分割的一部分。自动化需要覆盖整个过程中,包括安全和合规性测试。代码是从哪里来的?是否涉及第三方技术、产品或容器映像?是否有已知的安全勘误表?是否有已知的常见代码缺陷?秘密和个人身份信息是否被隔离?如何进行身份认证?谁被授权部署服务和应用程序?
|
||||
[自动化][7]应该是 DevOps 不可分割的一部分。自动化需要覆盖整个过程中,包括安全和合规性测试。代码是从哪里来的?是否涉及第三方技术、产品或容器镜像?是否有已知的安全勘误表?是否有已知的常见代码缺陷?机密信息和个人身份信息是否被隔离?如何进行身份认证?谁被授权部署服务和应用程序?
|
||||
|
||||
你不是在写你自己的加密代码吧?
|
||||
你不是自己在写你的加密代码吧?
|
||||
|
||||
尽可能地自动化渗透测试。我提到过自动化没?它是使安全性持续的一个重要部分,而不是偶尔做一次的检查清单。
|
||||
|
||||
这听起来很难吗?可能有点。至少它是不同的。但是,作一名 [DevOpsDays OpenSpaces][8] 伦敦论坛的一名参与者对我说:“这只是技术测试。它既不神奇也不神秘。”他接着说,将安全作为一种更广泛地了解整个软件生命周期(这是一种不错的技能)的方法来参与进来并不难。他还建议参加事件响应练习或[捕获国旗练习][9]。你会发现它们很有趣。
|
||||
|
||||
本文基于作者将于 5 月 8 日至 10 日在旧金山举行的 [Red Hat Summit 2018][11] 上发表的演讲。_[5 月 7 日前注册][11]以节省 500 美元的注册。使用折扣代码**OPEN18**在支付页面应用折扣_
|
||||
|
||||
这听起来很难吗?可能有点。至少它是不同的。但是,一名 [DevOpsDays OpenSpaces][8] 伦敦论坛的参与者对我说:“这只是技术测试。它既不神奇也不神秘。”他接着说,将安全作为一种更广泛地了解整个软件生命周期的方法(这是一种不错的技能)来参与进来并不难。他还建议参加事件响应练习或[夺旗练习][9]。你会发现它们很有趣。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/4/what-developers-need-know-about-security
|
||||
|
||||
作者:[Gordon Haff][a]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
如何在 CentOS 中添加、启用和禁用一个仓库
|
||||
======
|
||||
|
||||
在基于 RPM 的系统上,例如 RHEL、CentOS 等,我们中的许多人使用 yum 包管理器来管理软件的安装、删除、更新、搜索等。
|
||||
|
||||
Linux 发行版的大部分软件都来自发行版官方仓库。官方仓库包含大量免费和开源的应用和软件。它很容易安装和使用。
|
||||
|
||||
由于一些限制和专有问题,基于 RPM 的发行版在其官方仓库中没有提供某些包。另外,出于稳定性考虑,它不会提供最新版本的核心包。
|
||||
|
||||
为了克服这种情况,我们需要安装或启用需要的第三方仓库。对于基于 RPM 的系统,有许多第三方仓库可用,但所建议使用的仓库很少,因为这些不会替换大量的基础包。
|
||||
|
||||
建议阅读:
|
||||
|
||||
- [在 RHEL/CentOS 系统中使用 YUM 命令管理包][1]
|
||||
- [在 Fedora 系统中使用 DNF (YUM 的分支) 命令来管理包][2]
|
||||
- [命令行包管理器和用法列表][3]
|
||||
- [Linux 包管理器的图形化工具][4]
|
||||
|
||||
这可以在基于 RPM 的系统上完成,比如 RHEL, CentOS, OEL, Fedora 等。
|
||||
|
||||
* Fedora 系统使用 `dnf config-manager [options] [section …]`
|
||||
* 其它基于 RPM 的系统使用 `yum-config-manager [options] [section …]`
|
||||
|
||||
### 如何列出启用的仓库
|
||||
|
||||
只需运行以下命令即可检查系统上启用的仓库列表。
|
||||
|
||||
对于 CentOS/RHEL/OLE 系统:
|
||||
|
||||
```
|
||||
# yum repolist
|
||||
Loaded plugins: fastestmirror, security
|
||||
Loading mirror speeds from cached hostfile
|
||||
repo id repo name status
|
||||
base CentOS-6 - Base 6,706
|
||||
extras CentOS-6 - Extras 53
|
||||
updates CentOS-6 - Updates 1,255
|
||||
repolist: 8,014
|
||||
```
|
||||
|
||||
对于 Fedora 系统:
|
||||
|
||||
```
|
||||
# dnf repolist
|
||||
```
|
||||
|
||||
### 如何在系统中添加一个新仓库
|
||||
|
||||
每个仓库通常都提供自己的 `.repo` 文件。要将此类仓库添加到系统中,使用 root 用户运行以下命令。在我们的例子中将添加 EPEL 仓库 和 IUS 社区仓库,见下文。
|
||||
|
||||
但是没有 `.repo` 文件可用于这些仓库。因此,我们使用以下方法进行安装。
|
||||
|
||||
对于 EPEL 仓库,因为它可以从 CentOS 额外仓库获得,所以运行以下命令来安装它。
|
||||
|
||||
```
|
||||
# yum install epel-release -y
|
||||
```
|
||||
|
||||
对于 IUS 社区仓库,运行以下 bash 脚本来安装。
|
||||
|
||||
```
|
||||
# curl 'https://setup.ius.io/' -o setup-ius.sh
|
||||
# sh setup-ius.sh
|
||||
```
|
||||
|
||||
如果你有 `.repo` 文件,在 RHEL/CentOS/OEL 中,只需运行以下命令来添加一个仓库。
|
||||
|
||||
```
|
||||
# yum-config-manager --add-repo http://www.example.com/example.repo
|
||||
|
||||
Loaded plugins: product-id, refresh-packagekit, subscription-manager
|
||||
adding repo from: http://www.example.com/example.repo
|
||||
grabbing file http://www.example.com/example.repo to /etc/yum.repos.d/example.repo
|
||||
example.repo | 413 B 00:00
|
||||
repo saved to /etc/yum.repos.d/example.repo
|
||||
```
|
||||
|
||||
对于 Fedora 系统,运行以下命令来添加一个仓库:
|
||||
|
||||
```
|
||||
# dnf config-manager --add-repo http://www.example.com/example.repo
|
||||
adding repo from: http://www.example.com/example.repo
|
||||
```
|
||||
|
||||
如果在添加这些仓库之后运行 `yum repolist` 命令,你就可以看到新添加的仓库了。Yes,我看到了。
|
||||
|
||||
注意:每当运行 `yum repolist` 命令时,该命令会自动从相应的仓库获取更新,并将缓存保存在本地系统中。
|
||||
|
||||
```
|
||||
# yum repolist
|
||||
|
||||
Loaded plugins: fastestmirror, security
|
||||
Loading mirror speeds from cached hostfile
|
||||
epel/metalink | 6.1 kB 00:00
|
||||
* epel: epel.mirror.constant.com
|
||||
* ius: ius.mirror.constant.com
|
||||
ius | 2.3 kB 00:00
|
||||
repo id repo name status
|
||||
base CentOS-6 - Base 6,706
|
||||
epel Extra Packages for Enterprise Linux 6 - x86_64 12,505
|
||||
extras CentOS-6 - Extras 53
|
||||
ius IUS Community Packages for Enterprise Linux 6 - x86_64 390
|
||||
updates CentOS-6 - Updates 1,255
|
||||
repolist: 20,909
|
||||
```
|
||||
|
||||
每个仓库都有多个渠道,比如测试(Testing)、开发(Dev)和存档(Archive)等。通过导航到仓库文件位置,你可以更好地理解这一点。
|
||||
|
||||
```
|
||||
# ls -lh /etc/yum.repos.d
|
||||
total 64K
|
||||
-rw-r--r-- 1 root root 2.0K Apr 12 02:44 CentOS-Base.repo
|
||||
-rw-r--r-- 1 root root 647 Apr 12 02:44 CentOS-Debuginfo.repo
|
||||
-rw-r--r-- 1 root root 289 Apr 12 02:44 CentOS-fasttrack.repo
|
||||
-rw-r--r-- 1 root root 630 Apr 12 02:44 CentOS-Media.repo
|
||||
-rw-r--r-- 1 root root 916 May 18 11:07 CentOS-SCLo-scl.repo
|
||||
-rw-r--r-- 1 root root 892 May 18 10:36 CentOS-SCLo-scl-rh.repo
|
||||
-rw-r--r-- 1 root root 6.2K Apr 12 02:44 CentOS-Vault.repo
|
||||
-rw-r--r-- 1 root root 7.9K Apr 12 02:44 CentOS-Vault.repo.rpmnew
|
||||
-rw-r--r-- 1 root root 957 May 18 10:41 epel.repo
|
||||
-rw-r--r-- 1 root root 1.1K Nov 4 2012 epel-testing.repo
|
||||
-rw-r--r-- 1 root root 1.2K Feb 23 2017 ius-archive.repo
|
||||
-rw-r--r-- 1 root root 1.2K Feb 23 2017 ius-dev.repo
|
||||
-rw-r--r-- 1 root root 1.1K May 18 10:41 ius.repo
|
||||
-rw-r--r-- 1 root root 1.2K Feb 23 2017 ius-testing.repo
|
||||
```
|
||||
|
||||
### 如何在系统中启用一个仓库
|
||||
|
||||
当你在默认情况下添加一个新仓库时,它将启用它们的稳定仓库,这就是为什么我们在运行 `yum repolist` 命令时获取了仓库信息。在某些情况下,如果你希望启用它们的测试、开发或存档仓库,使用以下命令。另外,我们还可以使用此命令启用任何禁用的仓库。
|
||||
|
||||
为了验证这一点,我们将启用 `epel-testing.repo`,运行下面的命令:
|
||||
|
||||
```
|
||||
# yum-config-manager --enable epel-testing
|
||||
|
||||
Loaded plugins: fastestmirror
|
||||
==================================================================================== repo: epel-testing =====================================================================================
|
||||
[epel-testing]
|
||||
bandwidth = 0
|
||||
base_persistdir = /var/lib/yum/repos/x86_64/6
|
||||
baseurl =
|
||||
cache = 0
|
||||
cachedir = /var/cache/yum/x86_64/6/epel-testing
|
||||
cost = 1000
|
||||
enabled = 1
|
||||
enablegroups = True
|
||||
exclude =
|
||||
failovermethod = priority
|
||||
ftp_disable_epsv = False
|
||||
gpgcadir = /var/lib/yum/repos/x86_64/6/epel-testing/gpgcadir
|
||||
gpgcakey =
|
||||
gpgcheck = True
|
||||
gpgdir = /var/lib/yum/repos/x86_64/6/epel-testing/gpgdir
|
||||
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
|
||||
hdrdir = /var/cache/yum/x86_64/6/epel-testing/headers
|
||||
http_caching = all
|
||||
includepkgs =
|
||||
keepalive = True
|
||||
mdpolicy = group:primary
|
||||
mediaid =
|
||||
metadata_expire = 21600
|
||||
metalink =
|
||||
mirrorlist = https://mirrors.fedoraproject.org/metalink?repo=testing-epel6&arch=x86_64
|
||||
mirrorlist_expire = 86400
|
||||
name = Extra Packages for Enterprise Linux 6 - Testing - x86_64
|
||||
old_base_cache_dir =
|
||||
password =
|
||||
persistdir = /var/lib/yum/repos/x86_64/6/epel-testing
|
||||
pkgdir = /var/cache/yum/x86_64/6/epel-testing/packages
|
||||
proxy = False
|
||||
proxy_dict =
|
||||
proxy_password =
|
||||
proxy_username =
|
||||
repo_gpgcheck = False
|
||||
retries = 10
|
||||
skip_if_unavailable = False
|
||||
ssl_check_cert_permissions = True
|
||||
sslcacert =
|
||||
sslclientcert =
|
||||
sslclientkey =
|
||||
sslverify = True
|
||||
throttle = 0
|
||||
timeout = 30.0
|
||||
username =
|
||||
```
|
||||
|
||||
运行 `yum repolist` 命令来检查是否启用了 “epel-testing”。它被启用了,我可以从列表中看到它。
|
||||
|
||||
```
|
||||
# yum repolist
|
||||
Loaded plugins: fastestmirror, security
|
||||
Determining fastest mirrors
|
||||
epel/metalink | 18 kB 00:00
|
||||
epel-testing/metalink | 17 kB 00:00
|
||||
* epel: mirror.us.leaseweb.net
|
||||
* epel-testing: mirror.us.leaseweb.net
|
||||
* ius: mirror.team-cymru.com
|
||||
base | 3.7 kB 00:00
|
||||
centos-sclo-sclo | 2.9 kB 00:00
|
||||
epel | 4.7 kB 00:00
|
||||
epel/primary_db | 6.0 MB 00:00
|
||||
epel-testing | 4.7 kB 00:00
|
||||
epel-testing/primary_db | 368 kB 00:00
|
||||
extras | 3.4 kB 00:00
|
||||
ius | 2.3 kB 00:00
|
||||
ius/primary_db | 216 kB 00:00
|
||||
updates | 3.4 kB 00:00
|
||||
updates/primary_db | 8.1 MB 00:00 ...
|
||||
repo id repo name status
|
||||
base CentOS-6 - Base 6,706
|
||||
centos-sclo-sclo CentOS-6 - SCLo sclo 495
|
||||
epel Extra Packages for Enterprise Linux 6 - x86_64 12,509
|
||||
epel-testing Extra Packages for Enterprise Linux 6 - Testing - x86_64 809
|
||||
extras CentOS-6 - Extras 53
|
||||
ius IUS Community Packages for Enterprise Linux 6 - x86_64 390
|
||||
updates CentOS-6 - Updates 1,288
|
||||
repolist: 22,250
|
||||
```
|
||||
|
||||
如果你想同时启用多个仓库,使用以下格式。这个命令将启用 epel、epel-testing 和 ius 仓库:
|
||||
|
||||
```
|
||||
# yum-config-manager --enable epel epel-testing ius
|
||||
```
|
||||
|
||||
对于 Fedora 系统,运行下面的命令来启用仓库:
|
||||
|
||||
```
|
||||
# dnf config-manager --set-enabled epel-testing
|
||||
```
|
||||
|
||||
### 如何在系统中禁用一个仓库
|
||||
|
||||
无论何时你在默认情况下添加一个新的仓库,它都会启用它们的稳定仓库,这就是为什么我们在运行 `yum repolist` 命令时获取了仓库信息。如果你不想使用仓库,那么可以通过下面的命令来禁用它。
|
||||
|
||||
为了验证这点,我们将要禁用 `epel-testing.repo` 和 `ius.repo`,运行以下命令:
|
||||
|
||||
```
|
||||
# yum-config-manager --disable epel-testing ius
|
||||
|
||||
Loaded plugins: fastestmirror
|
||||
==================================================================================== repo: epel-testing =====================================================================================
|
||||
[epel-testing]
|
||||
bandwidth = 0
|
||||
base_persistdir = /var/lib/yum/repos/x86_64/6
|
||||
baseurl =
|
||||
cache = 0
|
||||
cachedir = /var/cache/yum/x86_64/6/epel-testing
|
||||
cost = 1000
|
||||
enabled = 0
|
||||
enablegroups = True
|
||||
exclude =
|
||||
failovermethod = priority
|
||||
ftp_disable_epsv = False
|
||||
gpgcadir = /var/lib/yum/repos/x86_64/6/epel-testing/gpgcadir
|
||||
gpgcakey =
|
||||
gpgcheck = True
|
||||
gpgdir = /var/lib/yum/repos/x86_64/6/epel-testing/gpgdir
|
||||
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
|
||||
hdrdir = /var/cache/yum/x86_64/6/epel-testing/headers
|
||||
http_caching = all
|
||||
includepkgs =
|
||||
keepalive = True
|
||||
mdpolicy = group:primary
|
||||
mediaid =
|
||||
metadata_expire = 21600
|
||||
metalink =
|
||||
mirrorlist = https://mirrors.fedoraproject.org/metalink?repo=testing-epel6&arch=x86_64
|
||||
mirrorlist_expire = 86400
|
||||
name = Extra Packages for Enterprise Linux 6 - Testing - x86_64
|
||||
old_base_cache_dir =
|
||||
password =
|
||||
persistdir = /var/lib/yum/repos/x86_64/6/epel-testing
|
||||
pkgdir = /var/cache/yum/x86_64/6/epel-testing/packages
|
||||
proxy = False
|
||||
proxy_dict =
|
||||
proxy_password =
|
||||
proxy_username =
|
||||
repo_gpgcheck = False
|
||||
retries = 10
|
||||
skip_if_unavailable = False
|
||||
ssl_check_cert_permissions = True
|
||||
sslcacert =
|
||||
sslclientcert =
|
||||
sslclientkey =
|
||||
sslverify = True
|
||||
throttle = 0
|
||||
timeout = 30.0
|
||||
username =
|
||||
|
||||
========================================================================================= repo: ius =========================================================================================
|
||||
[ius]
|
||||
bandwidth = 0
|
||||
base_persistdir = /var/lib/yum/repos/x86_64/6
|
||||
baseurl =
|
||||
cache = 0
|
||||
cachedir = /var/cache/yum/x86_64/6/ius
|
||||
cost = 1000
|
||||
enabled = 0
|
||||
enablegroups = True
|
||||
exclude =
|
||||
failovermethod = priority
|
||||
ftp_disable_epsv = False
|
||||
gpgcadir = /var/lib/yum/repos/x86_64/6/ius/gpgcadir
|
||||
gpgcakey =
|
||||
gpgcheck = True
|
||||
gpgdir = /var/lib/yum/repos/x86_64/6/ius/gpgdir
|
||||
gpgkey = file:///etc/pki/rpm-gpg/IUS-COMMUNITY-GPG-KEY
|
||||
hdrdir = /var/cache/yum/x86_64/6/ius/headers
|
||||
http_caching = all
|
||||
includepkgs =
|
||||
keepalive = True
|
||||
mdpolicy = group:primary
|
||||
mediaid =
|
||||
metadata_expire = 21600
|
||||
metalink =
|
||||
mirrorlist = https://mirrors.iuscommunity.org/mirrorlist?repo=ius-centos6&arch=x86_64&protocol=http
|
||||
mirrorlist_expire = 86400
|
||||
name = IUS Community Packages for Enterprise Linux 6 - x86_64
|
||||
old_base_cache_dir =
|
||||
password =
|
||||
persistdir = /var/lib/yum/repos/x86_64/6/ius
|
||||
pkgdir = /var/cache/yum/x86_64/6/ius/packages
|
||||
proxy = False
|
||||
proxy_dict =
|
||||
proxy_password =
|
||||
proxy_username =
|
||||
repo_gpgcheck = False
|
||||
retries = 10
|
||||
skip_if_unavailable = False
|
||||
ssl_check_cert_permissions = True
|
||||
sslcacert =
|
||||
sslclientcert =
|
||||
sslclientkey =
|
||||
sslverify = True
|
||||
throttle = 0
|
||||
timeout = 30.0
|
||||
username =
|
||||
```
|
||||
|
||||
运行 `yum repolist` 命令检查 “epel-testing” 和 “ius” 仓库是否被禁用。它被禁用了,我不能看到那些仓库,除了 “epel”。
|
||||
|
||||
```
|
||||
# yum repolist
|
||||
Loaded plugins: fastestmirror, security
|
||||
Loading mirror speeds from cached hostfile
|
||||
* epel: mirror.us.leaseweb.net
|
||||
repo id repo name status
|
||||
base CentOS-6 - Base 6,706
|
||||
centos-sclo-sclo CentOS-6 - SCLo sclo 495
|
||||
epel Extra Packages for Enterprise Linux 6 - x86_64 12,505
|
||||
extras CentOS-6 - Extras 53
|
||||
updates CentOS-6 - Updates 1,288
|
||||
repolist: 21,051
|
||||
```
|
||||
|
||||
或者,我们可以运行以下命令查看详细信息:
|
||||
|
||||
```
|
||||
# yum repolist all | grep "epel*\|ius*"
|
||||
* epel: mirror.steadfast.net
|
||||
epel Extra Packages for Enterprise Linux 6 enabled: 12,509
|
||||
epel-debuginfo Extra Packages for Enterprise Linux 6 disabled
|
||||
epel-source Extra Packages for Enterprise Linux 6 disabled
|
||||
epel-testing Extra Packages for Enterprise Linux 6 disabled
|
||||
epel-testing-debuginfo Extra Packages for Enterprise Linux 6 disabled
|
||||
epel-testing-source Extra Packages for Enterprise Linux 6 disabled
|
||||
ius IUS Community Packages for Enterprise disabled
|
||||
ius-archive IUS Community Packages for Enterprise disabled
|
||||
ius-archive-debuginfo IUS Community Packages for Enterprise disabled
|
||||
ius-archive-source IUS Community Packages for Enterprise disabled
|
||||
ius-debuginfo IUS Community Packages for Enterprise disabled
|
||||
ius-dev IUS Community Packages for Enterprise disabled
|
||||
ius-dev-debuginfo IUS Community Packages for Enterprise disabled
|
||||
ius-dev-source IUS Community Packages for Enterprise disabled
|
||||
ius-source IUS Community Packages for Enterprise disabled
|
||||
ius-testing IUS Community Packages for Enterprise disabled
|
||||
ius-testing-debuginfo IUS Community Packages for Enterprise disabled
|
||||
ius-testing-source IUS Community Packages for Enterprise disabled
|
||||
```
|
||||
|
||||
对于 Fedora 系统,运行以下命令来启用一个仓库:
|
||||
|
||||
```
|
||||
# dnf config-manager --set-disabled epel-testing
|
||||
```
|
||||
|
||||
或者,可以通过手动编辑适当的 repo 文件来完成。为此,打开相应的 repo 文件并将值从 `enabled=0` 改为 `enabled=1`(启用仓库)或从 `enabled=1` 变为 `enabled=0`(禁用仓库)。
|
||||
|
||||
即从:
|
||||
|
||||
```
|
||||
[epel]
|
||||
name=Extra Packages for Enterprise Linux 6 - $basearch
|
||||
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
|
||||
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
|
||||
failovermethod=priority
|
||||
enabled=0
|
||||
gpgcheck=1
|
||||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
|
||||
```
|
||||
改为:
|
||||
|
||||
```
|
||||
[epel]
|
||||
name=Extra Packages for Enterprise Linux 6 - $basearch
|
||||
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
|
||||
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
|
||||
failovermethod=priority
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-add-enable-disable-a-repository-dnf-yum-config-manager-on-linux/
|
||||
|
||||
作者:[Prakash Subramanian][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.2daygeek.com/author/prakash/
|
||||
[1]:https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
|
||||
[2]:https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
|
||||
[3]:https://www.2daygeek.com/list-of-command-line-package-manager-for-linux/
|
||||
[4]:https://www.2daygeek.com/list-of-graphical-frontend-tool-for-linux-package-manager/
|
||||
File diff suppressed because it is too large
Load Diff
77
published/20180626 8 great pytest plugins.md
Normal file
77
published/20180626 8 great pytest plugins.md
Normal file
@@ -0,0 +1,77 @@
|
||||
8 个很棒的 pytest 插件
|
||||
======
|
||||
|
||||
> Python 测试工具最好的一方面是其强大的生态系统。这里列出了八个最好的插件。
|
||||
|
||||

|
||||
|
||||
我们是 [pytest][1] 的忠实粉丝,并将其作为工作和开源项目的默认 Python 测试工具。在本月的 Python 专栏中,我们分享了为什么我们喜欢 `pytest` 以及一些让 `pytest` 测试工作更有趣的插件。
|
||||
|
||||
### 什么是 pytest?
|
||||
|
||||
正如该工具的网站所说,“pytest 框架可以轻松地编写小型测试,也能进行扩展以支持应用和库的复杂功能测试。”
|
||||
|
||||
`pytest` 允许你在任何名为 `test_*.py` 的文件中定义测试,并将其定义为以 `test_*` 开头的函数。然后,pytest 将在整个项目中查找所有测试,并在控制台中运行 `pytest` 时自动运行这些测试。pytest 接受[标志和参数][2],它们可以在测试运行器停止时更改,这些包含如何输出结果,运行哪些测试以及输出中包含哪些信息。它还包括一个 `set_trace()` 函数,它可以进入到你的测试中。它会暂停您的测试, 并允许你与变量进行交互,不然你只能在终端中“四处翻弄”来调试你的项目。
|
||||
|
||||
`pytest` 最好的一方面是其强大的插件生态系统。因为 `pytest` 是一个非常流行的测试库,所以多年来创建了许多插件来扩展、定制和增强其功能。这八个插件是我们的最爱。
|
||||
|
||||
### 8 个很棒的插件
|
||||
|
||||
#### 1、pytest-sugar
|
||||
|
||||
[pytest-sugar][3] 改变了 `pytest` 的默认外观,添加了一个进度条,并立即显示失败的测试。它不需要配置,只需 `pip install pytest-sugar`,用 `pytest` 运行测试,来享受更漂亮、更有用的输出。
|
||||
|
||||
#### 2、pytest-cov
|
||||
|
||||
[pytest-cov][4] 在 `pytest` 中增加了覆盖率支持,来显示哪些代码行已经测试过,哪些还没有。它还将包括项目的测试覆盖率。
|
||||
|
||||
#### 3、pytest-picked
|
||||
|
||||
[pytest-picked][5] 对你已经修改但尚未提交 `git` 的代码运行测试。安装库并运行 `pytest --picked` 来仅测试自上次提交后已更改的文件。
|
||||
|
||||
#### 4、pytest-instafail
|
||||
|
||||
[pytest-instafail][6] 修改 `pytest` 的默认行为来立即显示失败和错误,而不是等到 `pytest` 完成所有测试。
|
||||
|
||||
#### 5、pytest-tldr
|
||||
|
||||
一个全新的 `pytest` 插件,可以将输出限制为你需要的东西。`pytest-tldr`(`tldr` 代表 “too long, didn't read” —— 太长,不想读),就像 pytest-sugar 一样,除基本安装外不需要配置。不像 pytest 的默认输出那么详细,[pytest-tldr][7] 将默认输出限制为失败测试的回溯信息,并忽略了一些令人讨厌的颜色编码。添加 `-v` 标志会为喜欢它的人返回更详细的输出。
|
||||
|
||||
#### 6、pytest-xdist
|
||||
|
||||
[pytest-xdist][8] 允许你通过 `-n` 标志并行运行多个测试:例如,`pytest -n 2` 将在两个 CPU 上运行你的测试。这可以显著加快你的测试速度。它还包括 `--looponfail` 标志,它将自动重新运行你的失败测试。
|
||||
|
||||
#### 7、pytest-django
|
||||
|
||||
[pytest-django][9] 为 Django 应用和项目添加了 `pytest` 支持。具体来说,`pytest-django` 引入了使用 pytest fixture 测试 Django 项目的能力,而省略了导入 `unittest` 和复制/粘贴其他样板测试代码的需要,并且比标准的 Django 测试套件运行得更快。
|
||||
|
||||
#### 8、django-test-plus
|
||||
|
||||
[django-test-plus][10] 并不是专门为 `pytest` 开发,但它现在支持 `pytest`。它包含自己的 `TestCase` 类,你的测试可以继承该类,并使你能够使用较少的按键来输出频繁的测试案例,例如检查特定的 HTTP 错误代码。
|
||||
|
||||
我们上面提到的库绝不是你扩展 `pytest` 的唯一选择。有用的 pytest 插件的前景是广阔的。查看 [pytest 插件兼容性][11]页面来自行探索。你最喜欢哪些插件?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/6/pytest-plugins
|
||||
|
||||
作者:[Jeff Triplett][a1], [Lacery Williams Henschel][a2]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a1]:https://opensource.com/users/jefftriplett
|
||||
[a2]:https://opensource.com/users/laceynwilliams
|
||||
[1]:https://docs.pytest.org/en/latest/
|
||||
[2]:https://docs.pytest.org/en/latest/usage.html
|
||||
[3]:https://github.com/Frozenball/pytest-sugar
|
||||
[4]:https://github.com/pytest-dev/pytest-cov
|
||||
[5]:https://github.com/anapaulagomes/pytest-picked
|
||||
[6]:https://github.com/pytest-dev/pytest-instafail
|
||||
[7]:https://github.com/freakboy3742/pytest-tldr
|
||||
[8]:https://github.com/pytest-dev/pytest-xdist
|
||||
[9]:https://pytest-django.readthedocs.io/en/latest/
|
||||
[10]:https://django-test-plus.readthedocs.io/en/latest/
|
||||
[11]:https://plugincompat.herokuapp.com/
|
||||
@@ -0,0 +1,103 @@
|
||||
如何在 Anbox 上安装 Google Play 商店及启用 ARM 支持
|
||||
======
|
||||
|
||||

|
||||
|
||||
[Anbox][1] (Anroid in a Box)是一个自由开源工具,它允许你在 Linux 上运行 Android 应用程序。它的工作原理是在 LXC 容器中运行 Android 运行时环境,重新创建 Android 的目录结构作为可挂载的 loop 镜像,同时使用本机 Linux 内核来执行应用。
|
||||
|
||||
据其网站所述,它的主要特性是安全性、性能、集成和趋同(不同外形尺寸缩放)。
|
||||
|
||||
使用 Anbox,每个 Android 应用或游戏就像系统应用一样都在一个单独的窗口中启动,它们的行为或多或少类似于常规窗口,显示在启动器中,可以平铺等等。
|
||||
|
||||
默认情况下,Anbox 没有 Google Play 商店或 ARM 应用支持。要安装应用,你必须下载每个应用的 APK 并使用 `adb` 手动安装。此外,默认情况下不能使用 Anbox 安装 ARM 应用或游戏 —— 尝试安装 ARM 应用会显示以下错误:
|
||||
|
||||
```
|
||||
Failed to install PACKAGE.NAME.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]
|
||||
|
||||
```
|
||||
|
||||
你可以在 Anbox 中手动设置 Google Play 商店和 ARM 应用支持(通过 libhoudini),但这是一个非常复杂的过程。为了更容易地在 Anbox 上安装 Google Play 商店和 Google Play 服务,并让它支持 ARM 应用程序和游戏(使用 libhoudini),[geeks-r-us.de][2](文章是德语)上的人创建了一个自动执行这些任务的脚本。
|
||||
|
||||
在使用之前,我想明确指出,即使在集成 libhoudini 来支持 ARM 后,也并非所有 Android 应用和游戏都能在 Anbox 中运行。某些 Android 应用和游戏可能根本不会出现在 Google Play 商店中,而一些应用和游戏可能可以安装但无法使用。此外,某些应用可能无法使用某些功能。
|
||||
|
||||
### 安装 Google Play 商店并在 Anbox 上启用 ARM 应用/游戏支持
|
||||
|
||||
如果你的 Linux 桌面上尚未安装 Anbox,这些说明显然不起作用。如果你还没有,请按照[此处][7]的安装说明安装 Anbox。此外,请确保在安装 Anbox 之后,使用此脚本之前至少运行一次 `anbox.appmgr`,以避免遇到问题。另外,确保在执行下面的脚本时 Anbox 没有运行(我怀疑这是导致评论中提到的这个[问题][8]的原因)。
|
||||
|
||||
1、 安装所需的依赖项(wget、lzip、unzip 和 squashfs-tools)。
|
||||
|
||||
在 Debian、Ubuntu 或 Linux Mint 中,使用此命令安装所需的依赖项:
|
||||
|
||||
```
|
||||
sudo apt install wget lzip unzip squashfs-tools
|
||||
```
|
||||
|
||||
2、 下载并运行脚本,在 Anbox 上自动下载并安装 Google Play 商店(和 Google Play 服务)和 libhoudini(用于 ARM 应用/游戏支持)。
|
||||
|
||||
**警告:永远不要在不知道它做什么的情况下运行不是你写的脚本。在运行此脚本之前,请查看其[代码][4]。**
|
||||
|
||||
要下载脚本,使其可执行并在 Linux 桌面上运行,请在终端中使用以下命令:
|
||||
|
||||
```
|
||||
wget https://raw.githubusercontent.com/geeks-r-us/anbox-playstore-installer/master/install-playstore.sh
|
||||
chmod +x install-playstore.sh
|
||||
sudo ./install-playstore.sh
|
||||
```
|
||||
|
||||
3、要让 Google Play 商店在 Anbox 中运行,你需要启用 Google Play 商店和 Google Play 服务的所有权限
|
||||
|
||||
为此,请运行Anbox:
|
||||
|
||||
```
|
||||
anbox.appmgr
|
||||
```
|
||||
|
||||
然后进入“设置 > 应用 > Google Play 服务 > 权限”并启用所有可用权限。对 Google Play 商店也一样!
|
||||
|
||||

|
||||
|
||||
你现在应该可以使用 Google 帐户登录 Google Play 商店了。
|
||||
|
||||
如果未启用 Google Play 商店和 Google Play 服务的所有权限,你可能会在尝试登录 Google 帐户时可能会遇到问题,并显示以下错误消息:“Couldn't sign in. There was a problem communicating with Google servers. Try again later“,如你在下面的截图中看到的那样:
|
||||
|
||||

|
||||
|
||||
登录后,你可以停用部分 Google Play 商店/Google Play 服务权限。
|
||||
|
||||
**如果你在 Anbox 上登录 Google 帐户时遇到一些连接问题**,请确保 `anbox-bride.sh` 正在运行:
|
||||
|
||||
启动它:
|
||||
|
||||
```
|
||||
sudo /snap/anbox/current/bin/anbox-bridge.sh start
|
||||
```
|
||||
重启它:
|
||||
|
||||
```
|
||||
sudo /snap/anbox/current/bin/anbox-bridge.sh restart
|
||||
```
|
||||
|
||||
根据[此用户][9]的说法,如果 Anbox 仍然存在连接问题,你可能还需要安装 dnsmasq 包。但是在我的 Ubuntu 18.04 桌面上不需要这样做。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxuprising.com/2018/07/anbox-how-to-install-google-play-store.html
|
||||
|
||||
作者:[Logix][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://plus.google.com/118280394805678839070
|
||||
[1]:https://anbox.io/
|
||||
[2]:https://geeks-r-us.de/2017/08/26/android-apps-auf-dem-linux-desktop/
|
||||
[3]:https://github.com/geeks-r-us/anbox-playstore-installer/
|
||||
[4]:https://github.com/geeks-r-us/anbox-playstore-installer/blob/master/install-playstore.sh
|
||||
[5]:https://docs.anbox.io/userguide/install.html
|
||||
[6]:https://github.com/anbox/anbox/issues/118#issuecomment-295270113
|
||||
[7]:https://github.com/anbox/anbox/blob/master/docs/install.md
|
||||
[8]:https://www.linuxuprising.com/2018/07/anbox-how-to-install-google-play-store.html?showComment=1533506821283#c4415289781078860898
|
||||
[9]:https://github.com/anbox/anbox/issues/118#issuecomment-295270113
|
||||
@@ -0,0 +1,67 @@
|
||||
一个用于家庭项目的单用户、轻量级操作系统
|
||||
======
|
||||
> 业余爱好者应该了解一下 RISC OS 的五个原因。
|
||||
|
||||

|
||||
|
||||
究竟什么是 RISC OS?嗯,它不是一种新的 Linux。它也不是有些人认为的 Windows。事实上,它发布于 1987 年,它比它们任何一个都要古老。但你看到它时不一定会意识到这一点。
|
||||
|
||||
其点击式图形用户界面在底部为活动的程序提供一个固定面板和一个图标栏。因此,它看起来像 Windows 95,并且比它早了 8 年。
|
||||
|
||||
这个操作系统最初是为 [Acorn Archimedes][1] 编写的。这台机器中的 Acorn RISC Machines CPU 是全新的硬件,因此需要在其上运行全新的软件。这是最早的 ARM 芯片上的系统,早于任何人想到的 Android 或 [Armbian][2] 之前。
|
||||
|
||||
虽然 Acorn 桌面最终消失了,但 ARM 芯片继续征服世界。在这里,RISC OS 一直有一个优点 —— 通常在嵌入式设备中,你从来没有真正地意识到它。RISC OS 过去长期以来一直是一个完全专有的操作系统。但近年来,该抄系统的所有者已经开始将源代码发布到一个名为 [RISC OS Open][3] 的项目中。
|
||||
|
||||
### 1、你可以将它安装在树莓派上
|
||||
|
||||
树莓派的官方操作系统 [Raspbian][4] 实际上非常棒(如果你对摆弄不同技术上新奇的东西不感兴趣,那么你可能最初也不会选择树莓派)。由于 RISC OS 是专门为 ARM 编写的,因此它可以在各种小型计算机上运行,包括树莓派的各个型号。
|
||||
|
||||
### 2、它超轻量级
|
||||
|
||||
我的树莓派上安装的 RISC 系统占用了几百兆 —— 这是在我加载了数十个程序和游戏之后。它们大多数时候不超过 1 兆。
|
||||
|
||||
如果你真的节俭,RISC OS Pico 可用在 16MB SD 卡上。如果你要在嵌入式系统或物联网项目中鼓捣某些东西,这是很完美的。当然,16MB 实际上比压缩到 512KB 的老 Archimedes 的 ROM 要多得多。但我想 30 年间内存技术的发展,我们可以稍微放宽一下了。
|
||||
|
||||
### 3、它非常适合复古游戏
|
||||
|
||||
当 Archimedes 处于鼎盛时期时,ARM CPU 的速度比 Apple Macintosh 和 Commodore Amiga 中的 Motorola 68000 要快几倍,它也完全吸了新的 386 技术。这使得它成为对游戏开发者有吸引力的一个平台,他们希望用这个星球上最强大的桌面计算机来支撑他们的东西。
|
||||
|
||||
那些游戏的许多拥有者都非常慷慨,允许业余爱好者免费下载他们的老作品。虽然 RISC OS 和硬件已经发展了,但只需要进行少量的调整就可以让它们运行起来。
|
||||
|
||||
如果你有兴趣探索这个,[这里有一个指南][5]让这些游戏在你的树莓派上运行。
|
||||
|
||||
### 4、它有 BBC BASIC
|
||||
|
||||
就像过去一样,按下 `F12` 进入命令行,输入 `*BASIC`,就可以看到一个完整的 BBC BASIC 解释器。
|
||||
|
||||
对于那些在 80 年代没有接触过它的人,请让我解释一下:BBC BASIC 是当时我们很多人的第一个编程语言,因为它专门教孩子如何编码。当时有大量的书籍和杂志文章教我们编写自己的简单但高度可玩的游戏。
|
||||
|
||||
几十年后,对于一个想要在学校假期做点什么的有技术头脑的孩子而言,在 BBC BASIC 上编写自己的游戏仍然是一个很棒的项目。但很少有孩子在家里有 BBC micro。那么他们应该怎么做呢?
|
||||
|
||||
当然,你可以在每台家用电脑上运行解释器,但是当别人需要使用它时就不能用了。那么为什么不使用装有 RISC OS 的树莓派呢?
|
||||
|
||||
### 5、它是一个简单的单用户操作系统
|
||||
|
||||
RISC OS 不像 Linux 一样有自己的用户和超级用户访问权限。它有一个用户并可以完全访问整个机器。因此,它可能不是跨企业部署的最佳日常驱动,甚至不适合给老人家做银行业务。但是,如果你正在寻找可以用来修改和鼓捣的东西,那绝对是太棒了。你和机器之间没有那么多障碍,所以你可以直接闯进去。
|
||||
|
||||
### 扩展阅读
|
||||
|
||||
如果你想了解有关此操作系统的更多信息,请查看 [RISC OS Open][3],或者将镜像烧到闪存到卡上并开始使用它。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/7/gentle-intro-risc-os
|
||||
|
||||
作者:[James Mawson][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/dxmjames
|
||||
[1]:https://en.wikipedia.org/wiki/Acorn_Archimedes
|
||||
[2]:https://www.armbian.com/
|
||||
[3]:https://www.riscosopen.org/content/
|
||||
[4]:https://www.raspbian.org/
|
||||
[5]:https://www.riscosopen.org/wiki/documentation/show/Introduction%20to%20RISC%20OS
|
||||
@@ -0,0 +1,86 @@
|
||||
2018 年 5 款最好的 Linux 游戏
|
||||
======
|
||||
|
||||

|
||||
|
||||
Linux 可能不会很快成为游戏玩家选择的平台 —— Valve Steam Machines 的失败似乎是对这一点的深刻提醒 —— 但这并不意味着该平台没有稳定增长,并且拥有相当多的优秀游戏。
|
||||
|
||||
从独立单机到辉煌的 RPG(角色扮演),2018 年已经可以称得上是 Linux 游戏的丰收年,在这里,我们将列出迄今为止最喜欢的五款。
|
||||
|
||||
你是否在寻找优秀的 Linux 游戏却又不想挥霍金钱?来看看我们的最佳 [免费 Linux 游戏][1] 名单吧!
|
||||
|
||||
### 1、<ruby>永恒之柱 2:死亡之火<rt>Pillars of Eternity II: Deadfire</rt></ruby>
|
||||
|
||||
![best-linux-games-2018-pillars-of-eternity-2-deadfire][2]
|
||||
|
||||
其中一款最能代表近年来 cRPG 的复兴,它让传统的 Bethesda RPG 看起来更像是轻松的动作冒险游戏。在磅礴的《<ruby>永恒之柱<rt>Pillars of Eternity</rt></ruby>》系列的最新作品中,当你和船员在充满冒险和危机的岛屿周围航行时,你会发现自己更像是一个海盗。
|
||||
|
||||
在混合了海战元素的基础上,《死亡之火》延续了前作丰富的游戏剧情和出色的文笔,同时在美丽的画面和手绘背景的基础上更进一步。
|
||||
|
||||
这是一款毫无疑问的令人印象深刻的硬核 RPG ,可能会让一些人对它产生抵触情绪,不过那些接受它的人会投入几个月的时间沉迷其中。
|
||||
|
||||
### 2、<ruby>杀戮尖塔<rt>Slay the Spire</rt></ruby>
|
||||
|
||||
![best-linux-games-2018-slay-the-spire][3]
|
||||
|
||||
《杀戮尖塔》仍处于早期阶段,却已经成为年度最佳游戏之一,它是一款采用 deck-building 玩法的卡牌游戏,由充满活力的视觉风格和 rogue-like 机制加以点缀,即便在一次次令人愤怒的(但可能是应受的)死亡之后,你还会再次投入其中。
|
||||
|
||||
每次游戏都有无尽的卡牌组合和不同的布局,《杀戮尖塔》就像是近年来所有令人震撼的独立游戏的最佳具现 —— 卡牌游戏和永久死亡冒险模式合二为一。
|
||||
|
||||
再强调一次,它仍处于早期阶段,所以它只会变得越来越好!
|
||||
|
||||
### 3、<ruby>战斗机甲<rt>Battletech</rt></ruby>
|
||||
|
||||
![best-linux-games-2018-battletech][4]
|
||||
|
||||
这是我们榜单上像“大片”一样的游戏,《战斗机甲》是一款星际战争游戏(基于桌面游戏),你将装载一个机甲战队并引导它们进行丰富的回合制战斗。
|
||||
|
||||
战斗发生在一系列的地形上,从寒冷的荒地到阳光普照的地带,你将用巨大的热武器装备你的四人小队,与对手小队作战。如果你觉得这听起来有点“机械战士”的味道,那么你想的没错,只不过这次更注重战术安排而不是直接行动。
|
||||
|
||||
除了让你在宇宙冲突中指挥的战役外,多人模式也可能会耗费你数不清的时间。
|
||||
|
||||
### 4、<ruby>死亡细胞<rt>Dead Cells</rt></ruby>
|
||||
|
||||
![best-linux-games-2018-dead-cells][5]
|
||||
|
||||
这款游戏称得上是年度最佳平台动作游戏。Roguelike 游戏《死亡细胞》将你带入一个黑暗(却色彩绚丽)的世界,在那里进行攻击和躲避以通过程序生成的关卡。它有点像 2D 的《<ruby>黑暗之魂<rt>Dark Souls</rt></ruby>》,如果《黑暗之魂》也充满五彩缤纷的颜色的话。
|
||||
|
||||
《死亡细胞》是无情的,只有精确而灵敏的控制才会让你避开死亡,而在两次运行期间的升级系统又会确保你总是有一些进步的成就感。
|
||||
|
||||
《死亡细胞》的像素风、动画效果和游戏机制都达到了巅峰,它及时地提醒我们,在没有 3D 图形的过度使用下游戏可以制作成什么样子。
|
||||
|
||||
|
||||
### 5、<ruby>叛逆机械师<rt>Iconoclasts</rt></ruby>
|
||||
|
||||
![best-linux-games-2018-iconoclasts][6]
|
||||
|
||||
这款游戏不像上面提到的几款那样为人所知,它是一款可爱风格的游戏,可以看作是《死亡细胞》不那么惊悚、更可爱的替代品。玩家将扮演成罗宾,一个发现自己处于政治扭曲的外星世界后开始了逃亡的女孩。
|
||||
|
||||
尽管你的角色将在非线性的关卡中行动,游戏却有着扣人心弦的游戏剧情,罗宾会获得各种各样充满想象力的提升,其中最重要的是她的扳手,从发射炮弹到解决巧妙的环境问题,你几乎可以用它来做任何事。
|
||||
|
||||
《叛逆机械师》是一个充满快乐与活力的平台游戏,融合了《<ruby>洛克人<rt>Megaman</rt></ruby>》的战斗和《<ruby>银河战士<rt>Metroid</rt></ruby>》的探索。如果你借鉴了那两部伟大的作品,可能不会比它做得更好。
|
||||
|
||||
### 总结
|
||||
|
||||
以上就是我们选出的 2018 年最佳的 Linux 游戏。有哪些我们错过的游戏精华?请在评论区告诉我们!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.maketecheasier.com/best-linux-games/
|
||||
|
||||
作者:[Robert Zak][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[seriouszyx](https://github.com/seriouszyx)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.maketecheasier.com/author/robzak/
|
||||
[1]:https://www.maketecheasier.com/open-source-linux-games/
|
||||
[2]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-pillars-of-eternity-2-deadfire.jpg (best-linux-games-2018-pillars-of-eternity-2-deadfire)
|
||||
[3]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-slay-the-spire.jpg (best-linux-games-2018-slay-the-spire)
|
||||
[4]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-battletech.jpg (best-linux-games-2018-battletech)
|
||||
[5]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-dead-cells.jpg (best-linux-games-2018-dead-cells)
|
||||
[6]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-iconoclasts.jpg (best-linux-games-2018-iconoclasts)
|
||||
|
||||
|
||||
@@ -1,40 +1,41 @@
|
||||
SDKMAN – 轻松管理多个软件开发套件 (SDK) 的命令行工具
|
||||
SDKMAN:轻松管理多个软件开发套件 (SDK) 的命令行工具
|
||||
======
|
||||
|
||||

|
||||
|
||||
你是否是一个经常在不同的 SDK 下安装和测试应用的开发者?我有一个好消息要告诉你!**SDKMAN**,一个可以帮你轻松管理多个 SDK 的命令行工具。它为安装、切换、列出和移除 SDK 提供了一个简便的方式。有了 SDKMAN,你可以在任何类 Unix 的操作系统上轻松地并行管理多个 SDK 的多个版本。它允许开发者为 JVM 安装不同的 SDK,例如 Java、Groovy、Scala、Kotlin 和 Ceylon、Ant、Gradle、Grails、Maven、SBT、Spark、Spring Boot、Vert.x,以及许多其他支持的 SDK。SDKMAN 是免费、轻量、开源、使用 **Bash** 编写的程序。
|
||||
你是否是一个经常在不同的 SDK 下安装和测试应用的开发者?我有一个好消息要告诉你!给你介绍一下 **SDKMAN**,一个可以帮你轻松管理多个 SDK 的命令行工具。它为安装、切换、列出和移除 SDK 提供了一个简便的方式。有了 SDKMAN,你可以在任何类 Unix 的操作系统上轻松地并行管理多个 SDK 的多个版本。它允许开发者为 JVM 安装不同的 SDK,例如 Java、Groovy、Scala、Kotlin 和 Ceylon、Ant、Gradle、Grails、Maven、SBT、Spark、Spring Boot、Vert.x,以及许多其他支持的 SDK。SDKMAN 是免费、轻量、开源、使用 **Bash** 编写的程序。
|
||||
|
||||
### 安装 SDKMAN
|
||||
|
||||
安装 SDKMAN 很简单。首先,确保你已经安装了 **zip** 和 **unzip** 这两个应用。它们在大多数的 Linux 发行版的默认仓库中。
|
||||
安装 SDKMAN 很简单。首先,确保你已经安装了 `zip` 和 `unzip` 这两个应用。它们在大多数的 Linux 发行版的默认仓库中。
|
||||
例如,在基于 Debian 的系统上安装 unzip,只需要运行:
|
||||
|
||||
```
|
||||
$ sudo apt-get install zip unzip
|
||||
|
||||
```
|
||||
|
||||
然后使用下面的命令安装 SDKMAN:
|
||||
|
||||
```
|
||||
$ curl -s "https://get.sdkman.io" | bash
|
||||
|
||||
```
|
||||
|
||||
在安装完成之后,运行以下命令:
|
||||
|
||||
```
|
||||
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
|
||||
|
||||
```
|
||||
|
||||
如果你希望自定义安装到其他位置,例如 **/usr/local/**,你可以这样做:
|
||||
如果你希望自定义安装到其他位置,例如 `/usr/local/`,你可以这样做:
|
||||
|
||||
```
|
||||
$ export SDKMAN_DIR="/usr/local/sdkman" && curl -s "https://get.sdkman.io" | bash
|
||||
|
||||
```
|
||||
|
||||
确保你的用户有足够的权限访问这个目录。
|
||||
|
||||
最后,在安装完成后使用下面的命令检查一下:
|
||||
|
||||
```
|
||||
$ sdk version
|
||||
==== BROADCAST =================================================================
|
||||
@@ -44,7 +45,6 @@ $ sdk version
|
||||
================================================================================
|
||||
|
||||
SDKMAN 5.7.2+323
|
||||
|
||||
```
|
||||
|
||||
恭喜你!SDKMAN 已经安装完成了。让我们接下来看如何安装和管理 SDKs 吧。
|
||||
@@ -52,12 +52,13 @@ SDKMAN 5.7.2+323
|
||||
### 管理多个 SDK
|
||||
|
||||
查看可用的 SDK 清单,运行:
|
||||
|
||||
```
|
||||
$ sdk list
|
||||
|
||||
```
|
||||
|
||||
将会输出:
|
||||
|
||||
```
|
||||
================================================================================
|
||||
Available Candidates
|
||||
@@ -79,18 +80,18 @@ used to pilot any type of process which can be described in terms of targets and
|
||||
tasks.
|
||||
|
||||
: $ sdk install ant
|
||||
|
||||
```
|
||||
|
||||
就像你看到的,SDK 每次列出众多 SDK 中的一个,以及该 SDK 的描述信息、官方网址和安装命令。按回车键继续下一个。
|
||||
|
||||
安装一个新的 SDK,例如 Java JDK,运行:
|
||||
|
||||
```
|
||||
$ sdk install java
|
||||
|
||||
```
|
||||
|
||||
将会输出:
|
||||
|
||||
```
|
||||
Downloading: java 8.0.172-zulu
|
||||
|
||||
@@ -106,30 +107,30 @@ Installing: java 8.0.172-zulu
|
||||
Done installing!
|
||||
|
||||
Setting java 8.0.172-zulu as default.
|
||||
|
||||
```
|
||||
|
||||
如果你安装了多个 SDK,它将会提示你是否想要将当前安装的版本设置为 **默认版本**。回答 **Yes** 将会把当前版本设置为默认版本。
|
||||
如果你安装了多个 SDK,它将会提示你是否想要将当前安装的版本设置为 **默认版本**。回答 `Yes` 将会把当前版本设置为默认版本。
|
||||
|
||||
使用以下命令安装一个 SDK 的其他版本:
|
||||
|
||||
使用以下命令安装一个 SDK 的其他版本:
|
||||
```
|
||||
$ sdk install ant 1.10.1
|
||||
|
||||
```
|
||||
|
||||
如果你之前已经在本地安装了一个 SDK,你可以像下面这样设置它为本地版本。
|
||||
|
||||
```
|
||||
$ sdk install groovy 3.0.0-SNAPSHOT /path/to/groovy-3.0.0-SNAPSHOT
|
||||
|
||||
```
|
||||
|
||||
列出一个 SDK 的多个版本:
|
||||
|
||||
```
|
||||
$ sdk list ant
|
||||
|
||||
```
|
||||
|
||||
将会输出
|
||||
将会输出:
|
||||
|
||||
```
|
||||
================================================================================
|
||||
Available Ant Versions
|
||||
@@ -145,32 +146,31 @@ Available Ant Versions
|
||||
* - installed
|
||||
> - currently in use
|
||||
================================================================================
|
||||
|
||||
```
|
||||
|
||||
像我之前说的,如果你安装了多个版本,SDKMAN 会提示你是否想要设置当前安装的版本为 **默认版本**。你可以回答 Yes 设置它为默认版本。当然,你也可以在稍后使用下面的命令设置:
|
||||
|
||||
```
|
||||
$ sdk default ant 1.9.9
|
||||
|
||||
```
|
||||
|
||||
上面的命令将会设置 Apache Ant 1.9.9 为默认版本。
|
||||
|
||||
你可以根据自己的需要选择使用任何已安装的 SDK 版本,仅需运行以下命令:
|
||||
你可以根据自己的需要选择使用任何已安装的 SDK 版本,仅需运行以下命令:
|
||||
|
||||
```
|
||||
$ sdk use ant 1.9.9
|
||||
|
||||
```
|
||||
|
||||
检查某个具体 SDK 当前的版本号,例如 Java,运行:
|
||||
|
||||
```
|
||||
$ sdk current java
|
||||
|
||||
Using java version 8.0.172-zulu
|
||||
|
||||
```
|
||||
|
||||
检查所有当下在使用的 SDK 版本号,运行:
|
||||
|
||||
```
|
||||
$ sdk current
|
||||
|
||||
@@ -178,36 +178,35 @@ Using:
|
||||
|
||||
ant: 1.10.1
|
||||
java: 8.0.172-zulu
|
||||
|
||||
```
|
||||
|
||||
升级过时的 SDK,运行:
|
||||
|
||||
```
|
||||
$ sdk upgrade scala
|
||||
|
||||
```
|
||||
|
||||
你也可以检查所有的 SDKs 中还有哪些是过时的。
|
||||
你也可以检查所有的 SDK 中还有哪些是过时的。
|
||||
|
||||
```
|
||||
$ sdk upgrade
|
||||
|
||||
```
|
||||
|
||||
SDKMAN 有离线模式,可以让 SDKMAN 在离线时也正常运作。你可以使用下面的命令在任何时间开启或者关闭离线模式:
|
||||
|
||||
```
|
||||
$ sdk offline enable
|
||||
|
||||
$ sdk offline disable
|
||||
|
||||
```
|
||||
|
||||
要移除已安装的 SDK,运行:
|
||||
|
||||
```
|
||||
$ sdk uninstall ant 1.9.9
|
||||
|
||||
```
|
||||
|
||||
要了解更多的细节,参阅帮助章节。
|
||||
|
||||
```
|
||||
$ sdk help
|
||||
|
||||
@@ -231,72 +230,68 @@ update
|
||||
flush <broadcast|archives|temp>
|
||||
|
||||
candidate : the SDK to install: groovy, scala, grails, gradle, kotlin, etc.
|
||||
use list command for comprehensive list of candidates
|
||||
eg: $ sdk list
|
||||
use list command for comprehensive list of candidates
|
||||
eg: $ sdk list
|
||||
|
||||
version : where optional, defaults to latest stable if not provided
|
||||
eg: $ sdk install groovy
|
||||
|
||||
eg: $ sdk install groovy
|
||||
```
|
||||
|
||||
### 更新 SDKMAN
|
||||
|
||||
如果有可用的新版本,可以使用下面的命令安装:
|
||||
|
||||
```
|
||||
$ sdk selfupdate
|
||||
|
||||
```
|
||||
|
||||
SDKMAN 会定期检查更新,以及让你了解如何更新的指令。
|
||||
SDKMAN 会定期检查更新,并给出让你了解如何更新的指令。
|
||||
|
||||
```
|
||||
WARNING: SDKMAN is out-of-date and requires an update.
|
||||
|
||||
$ sdk update
|
||||
Adding new candidates(s): scala
|
||||
|
||||
```
|
||||
|
||||
### 清除缓存
|
||||
|
||||
建议时不时的清理缓存(包括那些下载的 SDK 的二进制文件)。仅需运行下面的命令就可以了:
|
||||
建议时不时的清理缓存(包括那些下载的 SDK 的二进制文件)。仅需运行下面的命令就可以了:
|
||||
|
||||
```
|
||||
$ sdk flush archives
|
||||
|
||||
```
|
||||
|
||||
它也可以用于清理空的文件夹,节省一点空间:
|
||||
|
||||
```
|
||||
$ sdk flush temp
|
||||
|
||||
```
|
||||
|
||||
### 卸载 SDKMAN
|
||||
|
||||
如果你觉得不需要或者不喜欢 SDKMAN,可以使用下面的命令删除。
|
||||
|
||||
```
|
||||
$ tar zcvf ~/sdkman-backup_$(date +%F-%kh%M).tar.gz -C ~/ .sdkman
|
||||
$ rm -rf ~/.sdkman
|
||||
|
||||
```
|
||||
最后打开你的 **.bashrc**,**.bash_profile** 和/或者 **.profile**,找到并删除下面这几行。
|
||||
最后打开你的 `.bashrc`、`.bash_profile` 和/或者 `.profile`,找到并删除下面这几行。
|
||||
|
||||
```
|
||||
#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
|
||||
export SDKMAN_DIR="/home/sk/.sdkman"
|
||||
[[ -s "/home/sk/.sdkman/bin/sdkman-init.sh" ]] && source "/home/sk/.sdkman/bin/sdkman-init.sh"
|
||||
|
||||
```
|
||||
|
||||
如果你使用的是 ZSH,就从 **.zshrc** 中删除上面这一行。
|
||||
如果你使用的是 ZSH,就从 `.zshrc` 中删除上面这一行。
|
||||
|
||||
这就是所有的内容了。我希望 SDKMAN 可以帮到你。还有更多的干货即将到来。敬请期待!
|
||||
|
||||
祝近祺!
|
||||
|
||||
|
||||
:)
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/sdkman-a-cli-tool-to-easily-manage-multiple-software-development-kits/
|
||||
@@ -304,7 +299,7 @@ via: https://www.ostechnix.com/sdkman-a-cli-tool-to-easily-manage-multiple-softw
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[dianbanjiu](https://github.com/dianbanjiu)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
i3 窗口管理器使 Linux 更美好
|
||||
======
|
||||
|
||||
> 通过键盘操作的 i3 平铺窗口管理器使用 Linux 桌面。
|
||||
|
||||

|
||||
|
||||
Linux(和一般的开源软件)最美好的一点是自由 —— 可以在不同的替代方案中进行选择以满足我们的需求。
|
||||
|
||||
我使用 Linux 已经很长时间了,但我从来没有对可选用的桌面环境完全满意过。直到去年,[Xfce][1] 还是我认为在功能和性能之间的平和最接近满意的一个桌面环境。然后我发现了 [i3][2],这是一个改变了我的生活的惊人的软件。
|
||||
|
||||
i3 是一个平铺窗口管理器。窗口管理器的目标是控制窗口系统中窗口的外观和位置。窗口管理器通常用作功能齐全的桌面环境 (如 GONME 或 Xfce ) 的一部分,但也有一些可以用作独立的应用程序。
|
||||
|
||||
平铺式窗口管理器会自动排列窗口,以不重叠的方式占据整个屏幕。其他流行的平铺式窗口管理器还有 [wmii][3] 和 [xmonad][4] 。
|
||||
|
||||
![i3 tiled window manager screenshot][6]
|
||||
|
||||
*带有三个的 i3 屏幕截图*
|
||||
|
||||
为了获得更好的 Linux 桌面体验,以下是我使用和推荐 i3 窗口管理器的五个首要原因。
|
||||
|
||||
### 1、极简艺术
|
||||
|
||||
i3 速度很快。它既不冗杂、也不花哨。它的设计简单而高效。作为开发人员,我重视这些功能,因为我可以使用更多的功能以丰富我最喜欢的开发工具,或者使用容器或虚拟机在本地测试内容。
|
||||
|
||||
此外, i3 是一个窗口管理器,与功能齐全的桌面环境不同,它并不规定您应该使用的应用程序。您是否想使用 Xfce 的 Thunar 作为文件管理器?GNOME 的 gedit 去编辑文本? i3 并不在乎。选择对您的工作流最有意义的工具,i3 将以相同的方式管理它们。
|
||||
|
||||
### 2、屏幕实际使用面积
|
||||
|
||||
作为平铺式窗口管理器,i3 将自动 “平铺”,以不重叠的方式定位窗口,类似于在墙上放置瓷砖。因为您不需要担心窗口定位,i3 一般会更好地利用您的屏幕空间。它还可以让您更快地找到您需要的东西。
|
||||
|
||||
对于这种情况有很多有用的例子。例如,系统管理员可以打开多个终端来同时监视或在不同的远程系统上工作;开发人员可以使用他们最喜欢的 IDE 或编辑器和几个终端来测试他们的程序。
|
||||
|
||||
此外,i3 具有灵活性。如果您需要为特定窗口提供更多空间,请启用全屏模式或切换到其他布局,如堆叠或选项卡式(标签式)。
|
||||
|
||||
### 3、键盘式工作流程
|
||||
|
||||
i3 广泛使用键盘快捷键来控制环境的不同方面。其中包括打开终端和其他程序、调整大小和定位窗口、更改布局,甚至退出 i3。当您开始使用 i3 时,您需要记住其中的一些快捷方式才能使用,随着时间的推移,您会使用更多的快捷方式。
|
||||
|
||||
主要好处是,您不需要经常在键盘和鼠标之间切换。通过练习,您将提高工作流程的速度和效率。
|
||||
|
||||
例如, 要打开新的终端,请按 `<SUPER>+<ENTER>`。由于窗口是自动定位的,您可以立即开始键入命令。结合一个很好的终端文本编辑器(如 Vim)和一个以面向键盘的浏览器,形成一个完全由键盘驱动的工作流程。
|
||||
|
||||
在 i3 中,您可以为所有内容定义快捷方式。下面是一些示例:
|
||||
|
||||
* 打开终端
|
||||
* 打开浏览器
|
||||
* 更改布局
|
||||
* 调整窗口大小
|
||||
* 控制音乐播放器
|
||||
* 切换工作区
|
||||
|
||||
现在我已经习惯了这个工作形式,我已无法回到了常规的桌面环境。
|
||||
|
||||
### 4、灵活
|
||||
|
||||
i3 力求极简,使用很少的系统资源,但这并不意味着它不能变漂亮。i3 是灵活且可通过多种方式进行自定义以改善视觉体验。因为 i3 是一个窗口管理器,所以它没有提供启用自定义的工具,你需要外部工具来实现这一点。一些例子:
|
||||
|
||||
* 用 `feh` 定义桌面的背景图片。
|
||||
* 使用合成器管理器,如 `compton` 以启用窗口淡入淡出和透明度等效果。
|
||||
* 用 `dmenu` 或 `rofi` 以启用可从键盘快捷方式启动的可自定义菜单。
|
||||
* 用 `dunst` 用于桌面通知。
|
||||
|
||||
i3 是可完全配置的,您可以通过更新默认配置文件来控制它的各个方面。从更改所有键盘快捷键,到重新定义工作区的名称,再到修改状态栏,您都可以使 i3 以任何最适合您需要的方式运行。
|
||||
|
||||
![i3 with rofi menu and dunst desktop notifications][8]
|
||||
|
||||
*i3 与 `rofi` 菜单和 `dunst` 桌面通知。*
|
||||
|
||||
最后,对于更高级的用户,i3 提供了完整的进程间通信([IPC][9])接口,允许您使用偏好的语言来开发脚本或程序,以实现更多的自定义选项。
|
||||
|
||||
### 5、工作空间
|
||||
|
||||
在 i3 中,工作区是对窗口进行分组的一种简单方法。您可以根据您的工作流以不同的方式对它们进行分组。例如,您可以将浏览器放在一个工作区上,终端放在另一个工作区上,将电子邮件客户端放在第三个工作区上等等。您甚至可以更改 i3 的配置,以便始终将特定应用程序分配给它们自己的工作区。
|
||||
|
||||
切换工作区既快速又简单。像 i3 中的惯例,使用键盘快捷方式执行此操作。按 `<SUPER>+num` 切换到工作区 `num` 。如果您养成了始终将应用程序组的窗口分配到同一个工作区的习惯,则可以在它们之间快速切换,这使得工作区成为非常有用的功能。
|
||||
|
||||
此外,还可以使用工作区来控制多监视器环境,其中每个监视器都有个初始工作区。如果切换到该工作区,则切换到该监视器,而无需让手离开键盘。
|
||||
|
||||
最后,i3 中还有另一种特殊类型的工作空间:the scratchpad(便笺簿)。它是一个不可见的工作区,通过按快捷方式显示在其他工作区的中间。这是一种访问您经常使用的窗口或程序的方便方式,如电子邮件客户端或音乐播放器。
|
||||
|
||||
### 尝试一下吧
|
||||
|
||||
如果您重视简洁和效率,并且不惮于使用键盘,i3 就是您的窗口管理器。有人说是为高级用户准备的,但情况不一定如此。你需要学习一些基本的快捷方式来度过开始的阶段,不久就会越来越自然并且不假思索地使用它们。
|
||||
|
||||
这篇文章只是浅浅谈及了 i3 能做的事情。欲了解更多详情,请参阅 [i3 的文档][10]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/8/i3-tiling-window-manager
|
||||
|
||||
作者:[Ricardo Gerardi][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[lixinyuxx](https://github.com/lixinyuxx)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/rgerardi
|
||||
[1]:https://xfce.org/
|
||||
[2]:https://i3wm.org/
|
||||
[3]:https://code.google.com/archive/p/wmii/
|
||||
[4]:https://xmonad.org/
|
||||
[5]:/file/406476
|
||||
[6]:https://opensource.com/sites/default/files/uploads/i3_screenshot.png "i3 tiled window manager screenshot"
|
||||
[7]:/file/405161
|
||||
[8]:https://opensource.com/sites/default/files/uploads/rofi_dunst.png "i3 with rofi menu and dunst desktop notifications"
|
||||
[9]:https://i3wm.org/docs/ipc.html
|
||||
[10]:https://i3wm.org/docs/userguide.html
|
||||
@@ -1,9 +1,9 @@
|
||||
如何在 Linux 中快速地通过 HTTP 访问文件和文件夹
|
||||
如何在 Linux 中快速地通过 HTTP 提供文件访问服务
|
||||
======
|
||||
|
||||

|
||||
|
||||
今天,我有很多方法来通过网络浏览器为局域网中的其他系统提供单个文件或整个目录访问。我在我的 Ubuntu 测试机上测试了这些方法,它们和下面描述的那样运行正常。如果你想知道如何在类 Unix 操作系统中通过 HTTP 轻松快速地访问文件和文件夹,以下方法之一肯定会有所帮助。
|
||||
如今,我有很多方法来通过 Web 浏览器为局域网中的其他系统提供单个文件或整个目录的访问。我在我的 Ubuntu 测试机上测试了这些方法,它们如下面描述的那样运行正常。如果你想知道如何在类 Unix 操作系统中通过 HTTP 轻松快速地提供文件和文件夹的访问服务,以下方法之一肯定会有所帮助。
|
||||
|
||||
### 在 Linux 中通过 HTTP 访问文件和文件夹
|
||||
|
||||
@@ -13,50 +13,59 @@
|
||||
|
||||
我们写了一篇简要的指南来设置一个简单的 http 服务器,以便在以下链接中即时共享文件和目录。如果你有一个安装了 Python 的系统,这个方法非常方便。
|
||||
|
||||
- [如何使用 simpleHTTPserver 设置一个简单的文件服务器](https://www.ostechnix.com/how-to-setup-a-file-server-in-minutes-using-python/)
|
||||
|
||||
#### 方法 2 - 使用 Quickserve(Python)
|
||||
|
||||
此方法针对 Arch Linux 及其衍生版。有关详细信息,请查看下面的链接。
|
||||
|
||||
- [如何在 Arch Linux 中即时共享文件和文件夹](https://www.ostechnix.com/instantly-share-files-folders-arch-linux/)
|
||||
|
||||
#### 方法 3 - 使用 Ruby
|
||||
|
||||
在此方法中,我们使用 Ruby 在类 Unix 系统中通过 HTTP 提供文件和文件夹访问。按照以下链接中的说明安装 Ruby 和 Rails。
|
||||
|
||||
- [在 CentOS 和 Ubuntu 中安装 Ruby on Rails](https://www.ostechnix.com/install-ruby-rails-ubuntu-16-04/)
|
||||
|
||||
安装 Ruby 后,进入要通过网络共享的目录,例如 ostechnix:
|
||||
|
||||
```
|
||||
$ cd ostechnix
|
||||
|
||||
```
|
||||
|
||||
并运行以下命令:
|
||||
|
||||
```
|
||||
$ ruby -run -ehttpd . -p8000
|
||||
[2018-08-10 16:02:55] INFO WEBrick 1.4.2
|
||||
[2018-08-10 16:02:55] INFO ruby 2.5.1 (2018-03-29) [x86_64-linux]
|
||||
[2018-08-10 16:02:55] INFO WEBrick::HTTPServer#start: pid=5859 port=8000
|
||||
|
||||
```
|
||||
|
||||
确保在路由器或防火墙中打开端口 8000。如果该端口已被其他一些服务使用,那么请使用不同的端口。
|
||||
|
||||
现在你可以使用 URL 从任何远程系统访问此文件夹的内容 - **http:// <ip-address>:8000**。
|
||||
现在你可以使用 URL 从任何远程系统访问此文件夹的内容 - `http:// <ip-address>:8000`。
|
||||
|
||||

|
||||
|
||||
要停止共享,请按 **CTRL+C**。
|
||||
要停止共享,请按 `CTRL+C`。
|
||||
|
||||
#### 方法 4 - 使用 Http-server(NodeJS)
|
||||
|
||||
[**Http-server**][1] 是一个用 NodeJS 编写的简单的可用于生产的命令行 http-server。它不需要要配置,可用于通过 Web 浏览器即时共享文件和目录。
|
||||
[Http-server][1] 是一个用 NodeJS 编写的简单的可用于生产环境的命令行 http 服务器。它不需要配置,可用于通过 Web 浏览器即时共享文件和目录。
|
||||
|
||||
按如下所述安装 NodeJS。
|
||||
|
||||
- [如何在 Linux 上安装 NodeJS](https://www.ostechnix.com/install-node-js-linux/)
|
||||
|
||||
安装 NodeJS 后,运行以下命令安装 http-server。
|
||||
|
||||
```
|
||||
$ npm install -g http-server
|
||||
|
||||
```
|
||||
|
||||
现在进入任何目录并通过 HTTP 共享其内容,如下所示。
|
||||
|
||||
```
|
||||
$ cd ostechnix
|
||||
|
||||
@@ -67,80 +76,81 @@ Available on:
|
||||
http://192.168.225.24:8000
|
||||
http://192.168.225.20:8000
|
||||
Hit CTRL-C to stop the server
|
||||
|
||||
```
|
||||
|
||||
现在你可以使用 URL 从任何远程系统访问此文件夹的内容 - **http:// <ip-address>:8000**。
|
||||
现在你可以使用 URL 从任何远程系统访问此文件夹的内容 - `http:// <ip-address>:8000`。
|
||||
|
||||

|
||||
|
||||
要停止共享,请按 **CTRL+C**。
|
||||
要停止共享,请按 `CTRL+C`。
|
||||
|
||||
#### 方法 5 - 使用 Miniserve(Rust)
|
||||
|
||||
[**Miniserve**][2] 是另一个命令行程序,它允许你通过 HTTP 快速访问文件。它是一个非常快速,易于使用的跨平台程序,它用 **Rust** 编程语言编写。与上面的程序/方法不同,它提供身份验证支持,因此你可以为共享设置用户名和密码。
|
||||
[**Miniserve**][2] 是另一个命令行程序,它允许你通过 HTTP 快速访问文件。它是一个非常快速、易于使用的跨平台程序,它用 Rust 编程语言编写。与上面的程序/方法不同,它提供身份验证支持,因此你可以为共享设置用户名和密码。
|
||||
|
||||
按下面的链接在 Linux 系统中安装 Rust。
|
||||
|
||||
- [在 Linux 上安装 Rust 编程语言](https://www.ostechnix.com/install-rust-programming-language-in-linux/)
|
||||
|
||||
安装 Rust 后,运行以下命令安装 miniserve:
|
||||
|
||||
```
|
||||
$ cargo install miniserve
|
||||
|
||||
```
|
||||
|
||||
或者,你可以在[**发布页**][3]下载二进制文件并使其可执行。
|
||||
或者,你可以在其[发布页][3]下载二进制文件并使其可执行。
|
||||
|
||||
```
|
||||
$ chmod +x miniserve-linux
|
||||
|
||||
```
|
||||
|
||||
然后,你可以使用命令运行它(假设 miniserve 二进制文件下载到当前的工作目录中):
|
||||
|
||||
```
|
||||
$ ./miniserve-linux <path-to-share>
|
||||
|
||||
```
|
||||
|
||||
**用法**
|
||||
|
||||
要提供目录访问:
|
||||
|
||||
```
|
||||
$ miniserve <path-to-directory>
|
||||
|
||||
```
|
||||
|
||||
**示例:**
|
||||
|
||||
```
|
||||
$ miniserve /home/sk/ostechnix/
|
||||
miniserve v0.2.0
|
||||
Serving path /home/sk/ostechnix at http://[::]:8080, http://localhost:8080
|
||||
Quit by pressing CTRL-C
|
||||
|
||||
```
|
||||
|
||||
现在,你可以在本地系统使用 URL – **<http://localhost:8080>** 访问共享,或者在远程系统使用 URL – **http:// <ip-address>:8080** 访问。
|
||||
现在,你可以在本地系统使用 URL – `http://localhost:8080` 访问共享,或者在远程系统使用 URL – `http://<ip-address>:8080` 访问。
|
||||
|
||||
要提供单个文件访问:
|
||||
|
||||
```
|
||||
$ miniserve <path-to-file>
|
||||
|
||||
```
|
||||
|
||||
**示例:**
|
||||
|
||||
```
|
||||
$ miniserve ostechnix/file.txt
|
||||
|
||||
```
|
||||
|
||||
带用户名和密码提供文件/文件夹访问:
|
||||
|
||||
```
|
||||
$ miniserve --auth joe:123 <path-to-share>
|
||||
|
||||
```
|
||||
|
||||
绑定到多个接口:
|
||||
|
||||
```
|
||||
$ miniserve -i 192.168.225.1 -i 10.10.0.1 -i ::1 -- <path-to-share>
|
||||
|
||||
```
|
||||
|
||||
如你所见,我只给出了 5 种方法。但是,本指南末尾附带的链接中还提供了几种方法。也去测试一下它们。此外,收藏并时不时重新访问它来检查将来是否有新的方法。
|
||||
@@ -149,7 +159,9 @@ $ miniserve -i 192.168.225.1 -i 10.10.0.1 -i ::1 -- <path-to-share>
|
||||
|
||||
干杯!
|
||||
|
||||
### 资源
|
||||
|
||||
- [单行静态 http 服务器大全](https://gist.github.com/willurd/5720255)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -158,7 +170,7 @@ via: https://www.ostechnix.com/how-to-quickly-serve-files-and-folders-over-http-
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
Dropbox 在 Linux 上终止除了 Ext4 之外所有文件系统的同步支持
|
||||
======
|
||||
|
||||
> Dropbox 正考虑将同步支持限制为少数几种文件系统类型:Windows 的 NTFS、macOS 的 HFS+/APFS 和 Linux 的 Ext4。
|
||||
|
||||
![Dropbox ends support for various file system types][1]
|
||||
|
||||
[Dropbox][2] 是最受欢迎的 [Linux 中的云服务][3]之一。很多人都在使用 Linux 下的 Dropbox 同步客户端。但是,最近,一些用户在他们的 Dropbox Linux 桌面客户端上收到一条警告说:
|
||||
|
||||
> “移动 Dropbox 文件夹位置,
|
||||
> Dropbox 将在 11 月停止同步“
|
||||
|
||||
### Dropbox 将仅支持少量文件系统
|
||||
|
||||
一个 [Reddit 主题][4]强调了一位用户在 [Dropbox 论坛][5]上查询了该消息后的公告,该消息被社区管理员标记为意外新闻。这是[回复][6]中的内容:
|
||||
|
||||
> “大家好,在 2018 年 11 月 7 日,我们会结束 Dropbox 在某些不常见文件系统的同步支持。支持的文件系统是 Windows 的 NTFS、macOS 的 HFS+ 或 APFS,以及Linux 的 Ext4。
|
||||
>
|
||||
> [Dropbox 官方论坛][6]
|
||||
|
||||
![Dropbox official confirmation over limitation on supported file systems][7]
|
||||
|
||||
*Dropbox 官方确认支持文件系统的限制*
|
||||
|
||||
此举旨在提供稳定和一致的体验。Dropbox 还更新了其[桌面要求][8]。
|
||||
|
||||
### 那你该怎么办?
|
||||
|
||||
如果你在不受支持的文件系统上使用 Dropbox 进行同步,那么应该考虑更改位置。
|
||||
|
||||
Linux 仅支持 Ext4 文件系统。但这并不是一个令人担忧的新闻,因为你可能已经在使用 Ext4 文件系统了。
|
||||
|
||||
在 Ubuntu 或其他基于 Ubuntu 的发行版上,打开磁盘应用并查看 Linux 系统所在分区的文件系统。
|
||||
|
||||
![Check file system type on Ubuntu][9]
|
||||
|
||||
*检查 Ubuntu 上的文件系统类型*
|
||||
|
||||
如果你的系统上没有安装磁盘应用,那么可以[使用命令行了解文件系统类型][10]。
|
||||
|
||||
如果你使用的是 Ext4 文件系统并仍然收到来自 Dropbox 的警告,请检查你是否有可能收到通知的非活动计算机/设备。如果是,[将该系统与你的 Dropbox 帐户取消连接][11]。
|
||||
|
||||
### Dropbox 也不支持加密的 Ext4 吗?
|
||||
|
||||
一些用户还报告说他们在加密 Ext4 文件系统同步时也收到了警告。那么,这是否意味着 Linux 的 Dropbox 客户端只支持未加密的 Ext4 文件系统?这方面 Dropbox 没有官方声明。
|
||||
|
||||
你使用的是什么文件系统?你也收到了警告吗?如果你在收到警告后仍不确定该怎么做,你应该前往该方案的[官方帮助中心页面][12]。
|
||||
|
||||
请在下面的评论中告诉我们你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/dropbox-linux-ext4-only/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[1]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/08/dropbox-filesystem-support-featured.png?w=800&ssl=1
|
||||
[2]: https://www.dropbox.com/
|
||||
[3]: https://itsfoss.com/cloud-services-linux/
|
||||
[4]: https://www.reddit.com/r/linux/comments/966xt0/linux_dropbox_client_will_stop_syncing_on_any/
|
||||
[5]: https://www.dropboxforum.com/t5/Syncing-and-uploads/
|
||||
[6]: https://www.dropboxforum.com/t5/Syncing-and-uploads/Linux-Dropbox-client-warn-me-that-it-ll-stop-syncing-in-Nov-why/m-p/290065/highlight/true#M42255
|
||||
[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/08/dropbox-stopping-file-system-supports.jpeg?w=800&ssl=1
|
||||
[8]: https://www.dropbox.com/help/desktop-web/system-requirements#desktop
|
||||
[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/08/check-file-system-type-ubuntu.jpg?w=800&ssl=1
|
||||
[10]: https://www.thegeekstuff.com/2011/04/identify-file-system-type/
|
||||
[11]: https://www.dropbox.com/help/mobile/unlink-relink-computer-mobile
|
||||
[12]: https://www.dropbox.com/help/desktop-web/cant-establish-secure-connection#location
|
||||
@@ -0,0 +1,100 @@
|
||||
顶级 Linux 开发者推荐的编程书籍
|
||||
======
|
||||
|
||||

|
||||
|
||||
> 毫无疑问,Linux 是由那些拥有深厚计算机知识背景而且才华横溢的程序员发明的。让那些大名鼎鼎的 Linux 程序员向如今的开发者分享一些曾经带领他们登堂入室的好书和技术参考资料吧,你会不会也读过其中几本呢?
|
||||
|
||||
Linux,毫无争议的属于 21 世纪的操作系统。虽然 Linus Torvalds 在建立开源社区这件事上做了很多工作和社区决策,不过那些网络专家和开发者愿意接受 Linux 的原因还是因为它卓越的代码质量和高可用性。Torvalds 是个编程天才,同时必须承认他还是得到了很多其他同样极具才华的开发者的无私帮助。
|
||||
|
||||
就此我咨询了 Torvalds 和其他一些顶级 Linux 开发者,有哪些书籍帮助他们走上了成为顶级开发者的道路,下面请听我一一道来。
|
||||
|
||||
### 熠熠生辉的 C 语言
|
||||
|
||||
Linux 是在大约上世纪 90 年代开发出来的,与它一起问世的还有其他一些完成基础功能的开源软件。与此相应,那时的开发者使用的工具和语言反映了那个时代的印记,也就是说 C 语言。可能 [C 语言不再流行了][1],可对于很多已经建功立业的开发者来说,C 语言是他们的第一个在实际开发中使用的语言,这一点也在他们推选的对他们有着深远影响的书单中反映出来。
|
||||
|
||||
Torvalds 说,“你不应该再选用我那个时代使用的语言或者开发方式”,他的开发道路始于 BASIC,然后转向机器码(“甚至都不是汇编语言,而是真真正正的‘二进制’机器码”,他解释道),再然后转向汇编语言和 C 语言。
|
||||
|
||||
“任何人都不应该再从这些语言开始进入开发这条路了”,他补充道。“这些语言中的一些今天已经没有什么意义(如 BASIC 和机器语言)。尽管 C 还是一个主流语言,我也不推荐你从它开始。”
|
||||
|
||||
并不是他不喜欢 C。不管怎样,Linux 是用 [GNU C 语言][2]写就的。“我始终认为 C 是一个伟大的语言,它有着非常简单的语法,对于很多方向的开发都很合适,但是我怀疑你会遇到重重挫折,从你的第一个‘Hello World’程序开始到你真正能开发出能用的东西当中有很大一步要走”。他认为,用现在的标准,如果作为入门语言的话,从 C 语言开始的代价太大。
|
||||
|
||||
在他那个时代,Torvalds 的唯一选择的书就只能是 Brian W. Kernighan 和 Dennis M. Ritchie 合著的《<ruby>[C 编程语言,第二版][3]<rt>C Programming Language, 2nd Edition</rt></ruby>》,它在编程圈内也被尊称为 K&R。“这本书简单精炼,但是你要先有编程的背景才能欣赏它”,Torvalds 说到。
|
||||
|
||||
Torvalds 并不是唯一一个推荐 K&R 的开源开发者。以下几位也同样引用了这本他们认为值得推荐的书籍,他们有:Linux 和 Oracle 虚拟化开发副总裁 Wim Coekaerts;Linux 开发者 Alan Cox;Google 云 CTO Brian Stevens;Canonical 技术运营部副总裁 Pete Graner。
|
||||
|
||||
如果你今日还想同 C 语言较量一番的话,Samba 的共同创始人 Jeremy Allison 推荐《<ruby>[C 程序设计新思维][4]<rt>21st Century C: C Tips from the New School</rt></ruby>》。他还建议,同时也去阅读一本比较旧但是写的更详细的《<ruby>[C 专家编程][5]<rt>Expert C Programming: Deep C Secrets</rt></ruby>》和有着 20 年历史的《<ruby>[POSIX 多线程编程][6]<rt>Programming with POSIX Threads</rt></ruby>》。
|
||||
|
||||
### 如果不选 C 语言, 那选什么?
|
||||
|
||||
Linux 开发者推荐的书籍自然都是他们认为适合今时今日的开发项目的语言工具。这也折射了开发者自身的个人偏好。例如,Allison 认为年轻的开发者应该在《<ruby>[Go 编程语言][7]<rt>The Go Programming Language</rt></ruby>》和《<ruby>[Rust 编程][8]<rt>Rust with Programming Rust</rt></ruby>》的帮助下去学习 Go 语言和 Rust 语言。
|
||||
|
||||
但是超越编程语言来考虑问题也不无道理(尽管这些书传授了你编程技巧)。今日要做些有意义的开发工作的话,"要从那些已经完成了 99% 显而易见工作的框架开始,然后你就能围绕着它开始写脚本了", Torvalds 推荐了这种做法。
|
||||
|
||||
“坦率来说,语言本身远远没有围绕着它的基础架构重要”,他继续道,“可能你会从 Java 或者 Kotlin 开始,但那是因为你想为自己的手机开发一个应用,因此安卓 SDK 成为了最佳的选择,又或者,你对游戏开发感兴趣,你选择了一个游戏开发引擎来开始,而通常它们有着自己的脚本语言”。
|
||||
|
||||
这里提及的基础架构包括那些和操作系统本身相关的编程书籍。
|
||||
Garner 在读完了大名鼎鼎的 K&R 后又拜读了 W. Richard Steven 的《<ruby>[Unix 网络编程][10]<rt>Unix Network Programming</rt></ruby>》。特别是,Steven 的《<ruby>[TCP/IP 详解,卷1:协议][11]<rt>TCP/IP Illustrated, Volume 1: The Protocols</rt></ruby>》在出版了 30 年之后仍然被认为是必读之书。因为 Linux 开发很大程度上和[和网络基础架构有关][12],Garner 也推荐了很多 O'Reilly 在 [Sendmail][13]、[Bash][14]、[DNS][15] 以及 [IMAP/POP][16] 等方面的书。
|
||||
|
||||
Coekaerts 也是 Maurice Bach 的《<ruby>[UNIX 操作系统设计][17]<rt>The Design of the Unix Operation System</rt></ruby>》的书迷之一。James Bottomley 也是这本书的推崇者,作为一个 Linux 内核开发者,当 Linux 刚刚问世时 James 就用 Bach 的这本书所传授的知识将它研究了个底朝天。
|
||||
|
||||
### 软件设计知识永不过时
|
||||
|
||||
尽管这样说有点太局限在技术领域。Stevens 还是说到,“所有的开发者都应该在开始钻研语法前先研究如何设计,《<ruby>[设计心理学][18]<rt>The Design of Everyday Things</rt></ruby>》是我的最爱”。
|
||||
|
||||
Coekaerts 喜欢 Kernighan 和 Rob Pike 合著的《<ruby>[程序设计实践][19]<rt>The Practic of Programming</rt></ruby>》。这本关于设计实践的书当 Coekaerts 还在学校念书的时候还未出版,他说道,“但是我把它推荐给每一个人”。
|
||||
|
||||
不管何时,当你问一个长期从事于开发工作的开发者他最喜欢的计算机书籍时,你迟早会听到一个名字和一本书:Donald Knuth 和他所著的《<ruby>[计算机程序设计艺术(1-4A)][20]<rt>The Art of Computer Programming, Volumes 1-4A</rt></ruby>》。VMware 首席开源官 Dirk Hohndel,认为这本书尽管有永恒的价值,但他也承认,“今时今日并非极其有用”。(LCTT 译注:不代表译者观点)
|
||||
|
||||
### 读代码。大量的读。
|
||||
|
||||
编程书籍能教会你很多,也请别错过另外一个在开源社区特有的学习机会:《<ruby>[代码阅读方法与实践][21]<rt>Code Reading: The Open Source Perspective</rt></ruby>》。那里有不可计数的代码例子阐述如何解决编程问题(以及如何让你陷入麻烦……)。Stevens 说,谈到磨炼编程技巧,在他的书单里排名第一的“书”是 Unix 的源代码。
|
||||
|
||||
“也请不要忽略从他人身上学习的各种机会。” Cox 道,“我是在一个计算机俱乐部里和其他人一起学的 BASIC,在我看来,这仍然是一个学习的最好办法”,他从《<ruby>[精通 ZX81 机器码][22]<rt>Mastering machine code on your ZX81</rt></ruby>》这本书和 Honeywell L66 B 编译器手册里学习到了如何编写机器码,但是学习技术这点来说,单纯阅读和与其他开发者在工作中共同学习仍然有着很大的不同。
|
||||
|
||||
Cox 说,“我始终认为最好的学习方法是和一群人一起试图去解决你们共同关心的一些问题并从中找到快乐,这和你是 5 岁还是 55 岁无关”。
|
||||
|
||||
最让我吃惊的是这些顶级 Linux 开发者都是在非常底层级别开始他们的开发之旅的,甚至不是从汇编语言或 C 语言,而是从机器码开始开发。毫无疑问,这对帮助开发者理解计算机在非常微观的底层级别是怎么工作的起了非常大的作用。
|
||||
|
||||
那么现在你准备好尝试一下硬核 Linux 开发了吗?Greg Kroah-Hartman,这位 Linux 内核稳定分支的维护者,推荐了 Steve Oualline 的《<ruby>[实用 C 语言编程][23]<rt>Practical C Programming</rt></ruby>》和 Samuel harbison 与 Guy Steels 合著的《<ruby>[C 语言参考手册][24]<rt>C: A Reference Manual</rt></ruby>》。接下来请阅读<ruby>[如何进行 Linux 内核开发][25]<rt>HOWTO do Linux kernel development</rt></ruby>,到这时,就像 Kroah-Hartman 所说,你已经准备好启程了。
|
||||
|
||||
于此同时,还请你刻苦学习并大量编码,最后祝你在跟随顶级 Linux 开发者脚步的道路上好运相随。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.hpe.com/us/en/insights/articles/top-linux-developers-recommended-programming-books-1808.html
|
||||
|
||||
作者:[Steven Vaughan-Nichols][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[DavidChenLiang](https://github.com/DavidChenLiang)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.hpe.com/us/en/insights/contributors/steven-j-vaughan-nichols.html
|
||||
[1]:https://www.codingdojo.com/blog/7-most-in-demand-programming-languages-of-2018/
|
||||
[2]:https://www.gnu.org/software/gnu-c-manual/
|
||||
[3]:https://amzn.to/2nhyjEO
|
||||
[4]:https://amzn.to/2vsL8k9
|
||||
[5]:https://amzn.to/2KBbWn9
|
||||
[6]:https://amzn.to/2M0rfeR
|
||||
[7]:https://amzn.to/2nhyrnMe
|
||||
[8]:http://shop.oreilly.com/product/0636920040385.do
|
||||
[9]:https://www.hpe.com/us/en/resources/storage/containers-for-dummies.html?jumpid=in_510384402_linuxbooks_containerebook0818
|
||||
[10]:https://amzn.to/2MfpbyC
|
||||
[11]:https://amzn.to/2MpgrTn
|
||||
[12]:https://www.hpe.com/us/en/insights/articles/how-to-see-whats-going-on-with-your-linux-system-right-now-1807.html
|
||||
[13]:http://shop.oreilly.com/product/9780596510299.do
|
||||
[14]:http://shop.oreilly.com/product/9780596009656.do
|
||||
[15]:http://shop.oreilly.com/product/9780596100575.do
|
||||
[16]:http://shop.oreilly.com/product/9780596000127.do
|
||||
[17]:https://amzn.to/2vsCJgF
|
||||
[18]:https://amzn.to/2APzt3Z
|
||||
[19]:https://www.amazon.com/Practice-Programming-Addison-Wesley-Professional-Computing/dp/020161586X/ref=as_li_ss_tl?ie=UTF8&linkCode=sl1&tag=thegroovycorpora&linkId=e6bbdb1ca2182487069bf9089fc8107e&language=en_US
|
||||
[20]:https://amzn.to/2OknFsJ
|
||||
[21]:https://amzn.to/2M4VVL3
|
||||
[22]:https://amzn.to/2OjccJA
|
||||
[23]:http://shop.oreilly.com/product/9781565923065.do
|
||||
[24]:https://amzn.to/2OjzgrT
|
||||
[25]:https://www.kernel.org/doc/html/v4.16/process/howto.html
|
||||
@@ -0,0 +1,72 @@
|
||||
Joplin:开源加密笔记及待办事项应用
|
||||
======
|
||||
|
||||
> [Joplin][1] 是一个自由开源的笔记和待办事项应用,可用于 Linux、Windows、macOS、Android 和 iOS。它的主要功能包括端到端加密,Markdown 支持以及通过 NextCloud、Dropbox、OneDrive 或 WebDAV 等第三方服务进行同步。
|
||||
|
||||

|
||||
|
||||
在 Joplin 中你可以用 Markdown 格式(支持数学符号和复选框)记笔记,桌面程序有 3 种视图:Markdown 代码、Markdown 预览或两者并排。你可以在笔记中添加附件(使用图像预览)或在外部 Markdown 编辑器中编辑它们并在每次保存文件时自动在 Joplin 中更新它们。
|
||||
|
||||
这个应用应该可以很好地处理大量笔记,它允许你将笔记组织到笔记本中、添加标签和搜索。你还可以按更新日期、创建日期或标题对笔记进行排序。每个笔记本可以包含笔记、待办事项或两者,你可以轻松添加其他笔记的链接(在桌面应用中右键单击笔记并选择 “Copy Markdown link”,然后在笔记中添加链接)。
|
||||
|
||||
Joplin 中的待办事项支持警报,但在 Ubuntu 18.04 上,此功能我无法使用。
|
||||
|
||||
其他 Joplin 功能包括:
|
||||
|
||||
* Firefox 和 Chrome 中可选的 Web Clipper 扩展(在 Joplin 桌面应用中进入 “Tools > Web clipper options” 以启用剪切服务并找到 Chrome/Firefox 扩展程序的下载链接),它可以剪切简单或完整的页面、剪切选中的区域或者截图。
|
||||
* 可选命令行客户端。
|
||||
* 导入 Enex 文件(Evernote 导出格式)和 Markdown 文件。
|
||||
* 导出 JEX 文件(Joplin 导出格式)、PDF 和原始文件。
|
||||
* 离线优先,因此即使没有互联网连接,所有数据也始终可在设备上查看。
|
||||
* 地理位置支持。
|
||||
|
||||
[![Joplin notes checkboxes link to other note][2]][3]
|
||||
|
||||
*Joplin 带有显示复选框和指向另一个笔记链接的隐藏侧边栏*
|
||||
|
||||
虽然它没有提供与 Evernote 一样多的功能,但 Joplin 是一个强大的开源 Evernote 替代品。Joplin 包含所有基本功能,除了它是开源软件之外,它还包括加密支持,你还可以选择用于同步的服务。
|
||||
|
||||
该应用实际上被设计为 Evernote 替代品,因此它可以导入完整的 Evernote 笔记本、笔记、标签、附件和笔记元数据,如作者、创建和更新时间或地理位置。
|
||||
|
||||
Joplin 开发重点关注的另一个方面是避免与特定公司或服务挂钩。这就是为什么该应用提供多种同步方案,如 NextCloud、Dropbox、oneDrive 和 WebDav,同时也容易支持新的服务。如果你改变主意,也很容易从一种服务切换到另一种服务。
|
||||
|
||||
我注意到 Joplin 默认情况下不使用加密,你必须在设置中启用此功能。进入 “Tools> Encryption options” 并在这里启用 Joplin 端到端加密。
|
||||
|
||||
### 下载 Joplin
|
||||
|
||||
- [下载 Joplin][7]
|
||||
|
||||
Joplin 适用于 Linux、Windows、macOS、Android 和 iOS。在 Linux 上,还有 AppImage 和 Aur 包。
|
||||
|
||||
要在 Linux 上运行 Joplin AppImage,请双击它并选择 “Make executable and run”(如果文件管理器支持这个)。如果不支持,你需要使用你的文件管理器使它可执行(应该类似这样:“右键单击>属性>权限>允许作为程序执行”,但这可能会因你使用的文件管理器而有所不同),或者从命令行:
|
||||
|
||||
```
|
||||
chmod +x /path/to/Joplin-*-x86_64.AppImage
|
||||
```
|
||||
|
||||
用你下载 Joplin 的路径替换 `/path/to/`。现在,你可以双击 Joplin Appimage 文件来启动它。
|
||||
|
||||
提示:如果你将 Joplin 集成到你的菜单中,而它的图标没有显示在你 dock 或应用切换器中,你可以打开 Joplin 的桌面文件(如果你使用 appimagekit 集成,它应该在 `~/.local/share/applications/appimagekit-joplin.desktop`)并在文件末尾添加 `StartupWMClass=Joplin` 其他不变来修复。
|
||||
|
||||
Joplin 有一个命令行客户端,它可以[使用 npm 安装][5](对于 Debian、Ubuntu 或 Linux Mint,请参阅[如何安装和配置 Node.js 和 npm][6])。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxuprising.com/2018/08/joplin-encrypted-open-source-note.html
|
||||
|
||||
作者:[Logix][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://plus.google.com/118280394805678839070
|
||||
[1]:https://joplin.cozic.net/
|
||||
[2]:https://3.bp.blogspot.com/-y9JKL1F89Vo/W3_0dkZjzQI/AAAAAAAABcI/hQI7GAx6i_sMcel4mF0x4uxBrMO88O59wCLcBGAs/s640/joplin-notes-markdown.png (Joplin notes checkboxes link to other note)
|
||||
[3]:https://3.bp.blogspot.com/-y9JKL1F89Vo/W3_0dkZjzQI/AAAAAAAABcI/hQI7GAx6i_sMcel4mF0x4uxBrMO88O59wCLcBGAs/s1600/joplin-notes-markdown.png
|
||||
[4]:https://github.com/laurent22/joplin/issues/338
|
||||
[5]:https://joplin.cozic.net/terminal/
|
||||
[6]:https://www.linuxuprising.com/2018/04/how-to-install-and-configure-nodejs-and.html
|
||||
|
||||
[7]: https://joplin.cozic.net/#installation
|
||||
162
published/20180831 Test containers with Python and Conu.md
Normal file
162
published/20180831 Test containers with Python and Conu.md
Normal file
@@ -0,0 +1,162 @@
|
||||
用 Python 和 Conu 测试容器
|
||||
======
|
||||
|
||||

|
||||
|
||||
越来越多的开发人员使用容器开发和部署他们的应用。这意味着可以轻松地测试容器也变得很重要。[Conu][1] (container utilities 的简写) 是一个 Python 库,让你编写容器测试变得简单。本文向你介绍如何使用它测试容器。
|
||||
|
||||
### 开始吧
|
||||
|
||||
首先,你需要一个容器程序来测试。为此,以下命令创建一个包含一个容器的 Dockerfile 和一个被容器伺服的 Flask 应用程序的文件夹。
|
||||
|
||||
```bash
|
||||
$ mkdir container_test
|
||||
$ cd container_test
|
||||
$ touch Dockerfile
|
||||
$ touch app.py
|
||||
```
|
||||
|
||||
将以下代码复制到 `app.py` 文件中。这是惯常的基本 Flask 应用,它返回字符串 “Hello Container World!”。
|
||||
|
||||
```python
|
||||
from flask import Flask
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/')
|
||||
def hello_world():
|
||||
return 'Hello Container World!'
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True,host='0.0.0.0')
|
||||
```
|
||||
|
||||
### 创建和构建测试容器
|
||||
|
||||
为了构建测试容器,将以下指令添加到 Dockerfile。
|
||||
|
||||
```dockerfile
|
||||
FROM registry.fedoraproject.org/fedora-minimal:latest
|
||||
RUN microdnf -y install python3-flask && microdnf clean all
|
||||
ADD ./app.py /srv
|
||||
CMD ["python3", "/srv/app.py"]
|
||||
```
|
||||
|
||||
然后使用 Docker CLI 工具构建容器。
|
||||
|
||||
```bash
|
||||
$ sudo dnf -y install docker
|
||||
$ sudo systemctl start docker
|
||||
$ sudo docker build . -t flaskapp_container
|
||||
```
|
||||
|
||||
提示:只有在系统上未安装 Docker 时才需要前两个命令。
|
||||
|
||||
构建之后使用以下命令运行容器。
|
||||
|
||||
```bash
|
||||
$ sudo docker run -p 5000:5000 --rm flaskapp_container
|
||||
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
|
||||
* Restarting with stat
|
||||
* Debugger is active!
|
||||
* Debugger PIN: 473-505-51
|
||||
```
|
||||
|
||||
最后,使用 `curl` 检查 Flask 应用程序是否在容器内正确运行:
|
||||
|
||||
```bash
|
||||
$ curl http://127.0.0.1:5000
|
||||
Hello Container World!
|
||||
```
|
||||
|
||||
现在,flaskapp_container 正在运行并准备好进行测试,你可以使用 `Ctrl+C` 将其停止。
|
||||
|
||||
### 创建测试脚本
|
||||
|
||||
在编写测试脚本之前,必须安装 `conu`。在先前创建的 `container_test` 目录中,运行以下命令。
|
||||
|
||||
```bash
|
||||
$ python3 -m venv .venv
|
||||
$ source .venv/bin/activate
|
||||
(.venv)$ pip install --upgrade pip
|
||||
(.venv)$ pip install conu
|
||||
$ touch test_container.py
|
||||
```
|
||||
|
||||
然后将以下脚本复制并保存在 `test_container.py` 文件中。
|
||||
|
||||
```python
|
||||
import conu
|
||||
|
||||
PORT = 5000
|
||||
|
||||
with conu.DockerBackend() as backend:
|
||||
image = backend.ImageClass("flaskapp_container")
|
||||
options = ["-p", "5000:5000"]
|
||||
container = image.run_via_binary(additional_opts=options)
|
||||
|
||||
try:
|
||||
# Check that the container is running and wait for the flask application to start.
|
||||
assert container.is_running()
|
||||
container.wait_for_port(PORT)
|
||||
|
||||
# Run a GET request on / port 5000.
|
||||
http_response = container.http_request(path="/", port=PORT)
|
||||
|
||||
# Check the response status code is 200
|
||||
assert http_response.ok
|
||||
|
||||
# Get the response content
|
||||
response_content = http_response.content.decode("utf-8")
|
||||
|
||||
# Check that the "Hello Container World!" string is served.
|
||||
assert "Hello Container World!" in response_content
|
||||
|
||||
# Get the logs from the container
|
||||
logs = [line for line in container.logs()]
|
||||
# Check the the Flask application saw the GET request.
|
||||
assert b'"GET / HTTP/1.1" 200 -' in logs[-1]
|
||||
|
||||
finally:
|
||||
container.stop()
|
||||
container.delete()
|
||||
```
|
||||
|
||||
#### 测试设置
|
||||
|
||||
这个脚本首先设置 `conu` 使用 Docker 作为后端来运行容器。然后它设置容器镜像以使用你在本教程第一部分中构建的 flaskapp_container。
|
||||
|
||||
下一步是配置运行容器所需的选项。在此示例中,Flask 应用在端口5000上提供内容。于是你需要暴露此端口并将其映射到主机上的同一端口。
|
||||
|
||||
最后,用这个脚本启动容器,现在可以测试了。
|
||||
|
||||
#### 测试方法
|
||||
|
||||
在测试容器之前,检查容器是否正在运行并准备就绪。示范脚本使用 `container.is_running` 和 `container.wait_for_port`。这些方法可确保容器正在运行,并且服务在预设端口上可用。
|
||||
|
||||
`container.http_request` 是 [request][2] 库的包装器,可以方便地在测试期间发送 HTTP 请求。这个方法返回[requests.Responseobject][3],因此可以轻松地访问响应的内容以进行测试。
|
||||
|
||||
`conu` 还可以访问容器日志。又一次,这在测试期间非常有用。在上面的示例中,`container.logs` 方法返回容器日志。你可以使用它们断言打印了特定日志,或者,例如在测试期间没有异常被引发。
|
||||
|
||||
`conu` 提供了许多与容器接合的有用方法。[文档][4]中提供了完整的 API 列表。你还可以参考 [GitHub][5] 上提供的示例。
|
||||
|
||||
运行本教程所需的所有代码和文件也可以在 [GitHub][6] 上获得。 对于想要进一步采用这个例子的读者,你可以看看使用 [pytest][7] 来运行测试并构建一个容器测试套件。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/test-containers-python-conu/
|
||||
|
||||
作者:[Clément Verna][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[GraveAccent](https://github.com/GraveAccent)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/cverna/
|
||||
[1]: https://github.com/user-cont/conu
|
||||
[2]: http://docs.python-requests.org/en/master/
|
||||
[3]: http://docs.python-requests.org/en/master/api/#requests.Response
|
||||
[4]: https://conu.readthedocs.io/en/latest/index.html
|
||||
[5]: https://github.com/user-cont/conu/tree/master/docs/source/examples
|
||||
[6]: https://github.com/cverna/container_test_script
|
||||
[7]: https://docs.pytest.org/en/latest/
|
||||
@@ -0,0 +1,251 @@
|
||||
在 Linux 中怎么运行 MS-DOS 游戏和程序
|
||||
======
|
||||
|
||||

|
||||
|
||||
你是否想过尝试一些经典的 MS-DOS 游戏和像 Turbo C++ 这样的废弃的 C++ 编译器?这篇教程将会介绍如何使用 DOSBox 在 Linux 环境下运行 MS-DOS 的游戏和程序。DOSBox 是一个 x86 平台的 DOS 模拟器,可以用来运行经典的 DOS 游戏和程序。 DOSBox 可以模拟带有声音、图形、鼠标、操纵杆和调制解调器等的因特尔 x86 电脑,它允许你运行许多旧的 MS-DOS 游戏和程序,这些游戏和程序根本无法在任何现代 PC 和操作系统上运行,例如 Microsoft Windows XP 及更高版本、Linux 和FreeBSD。 DOSBox 是免费的,使用 C++ 编程语言编写并在 GPL 下分发。
|
||||
|
||||
### 在 Linux 上安装 DOSBox
|
||||
|
||||
DOSBox 在大多数 Linux 发行版的默认仓库中都能找的到。
|
||||
|
||||
在 Arch Linux 及其衍生版如 Antergos、Manjaro Linux 上:
|
||||
|
||||
```
|
||||
$ sudo pacman -S dosbox
|
||||
```
|
||||
|
||||
在 Debian、Ubuntu、Linux Mint 上:
|
||||
|
||||
```
|
||||
$ sudo apt-get install dosbox
|
||||
```
|
||||
|
||||
在 Fedora 上:
|
||||
|
||||
```
|
||||
$ sudo dnf install dosbox
|
||||
```
|
||||
|
||||
### 配置 DOSBox
|
||||
|
||||
DOSBox 是一个开箱即用的软件,它不需要进行初始化配置。它的配置文件位于 `~/.dosbox` 文件夹中,名为 `dosbox-x.xx.conf`。 在此配置文件中,你可以编辑/修改各种设置,例如以全屏模式启动 DOSBox,全屏使用双缓冲,设置首选分辨率,鼠标灵敏度,启用或禁用声音,扬声器,操纵杆等等。如前所述,默认设置即可正常工作。你可以不用进行任何更改。
|
||||
|
||||
### 在 Linux 中运行 MS-DOS 上的游戏和程序
|
||||
|
||||
在终端运行以下命令启动 DOSBox:
|
||||
|
||||
```
|
||||
$ dosbox
|
||||
```
|
||||
|
||||
下图就是 DOSBox 的界面
|
||||
|
||||

|
||||
|
||||
正如你所看到的,DOSBox 带有自己的类似 DOS 的命令提示符和一个虚拟的 `Z:\` 的驱动器,如果你熟悉 MS-DOS 的话,你会发现在 DOSBox 环境下工作不会有任何问题。
|
||||
|
||||
这是 `dir` 命令(在 Linux 中等同于 `ls` 命令)的输出:
|
||||
|
||||

|
||||
|
||||
如果你是第一次使用 DOSBox,你可以通过在 DOSBox 提示符中输入以下命令来查看关于 DOSBox 的简介:
|
||||
|
||||
```
|
||||
intro
|
||||
```
|
||||
|
||||
在介绍部分按回车进入下一页。
|
||||
|
||||
要查看 DOS 中最常用命令的列表,请使用此命令:
|
||||
|
||||
```
|
||||
help
|
||||
```
|
||||
|
||||
要查看 DOSBox 中所有支持的命令的列表,请键入:
|
||||
|
||||
```
|
||||
help /all
|
||||
```
|
||||
|
||||
记好了这些命令应该在 DOSBox 提示符中使用,而不是在 Linux 终端中使用。
|
||||
|
||||
DOSBox 还支持一些实用的键盘组合键。下图是能有效使用 DOSBox 的默认键盘快捷键。
|
||||
|
||||

|
||||
|
||||
要退出 DOSBox,只需键入如下命令并按回车:
|
||||
|
||||
```
|
||||
exit
|
||||
```
|
||||
|
||||
默认情况下,DOSBox 开始运行时的正常屏幕窗口大小如上所示。
|
||||
|
||||
要直接在全屏启动 DOSBox,请编辑 `dosbox-x.xx.conf` 文件并将`fullscreen` 变量的值设置为 `enable`。 之后,DOSBox 将以全屏模式启动。 如果要返回正常屏幕,请按 `ALT+ENTER`。
|
||||
|
||||
希望你掌握了 DOSBox 的这些基本用法。
|
||||
|
||||
让我们继续安装一些 DOS 程序和游戏。
|
||||
|
||||
首先,我们需要在 Linux 系统中创建目录来保存程序和游戏。我将创建两个名为 `~/dosprograms` 和 `~/dosgames` 的目录,第一个用于存储程序,后者用于存储游戏。
|
||||
|
||||
```
|
||||
$ mkdir ~/dosprograms ~/dosgames
|
||||
```
|
||||
|
||||
出于本指南的目的,我将向你展示如何安装 Turbo C++ 程序和 Mario 游戏。我们首先将看到如何安装 Turbo。
|
||||
|
||||
下载最后版本的 Turbo C++ 编译器并将其解压到 `~/dosprograms` 目录中。 我已经将 Turbo C++ 保存在在我的 `~/dosprograms/TC/` 目录中了。
|
||||
|
||||
```
|
||||
$ ls dosprograms/tc/
|
||||
|
||||
BGI BIN CLASSLIB DOC EXAMPLES FILELIST.DOC INCLUDE LIB README README.COM
|
||||
```
|
||||
|
||||
运行 DOSBox:
|
||||
|
||||
```
|
||||
$ dosbox
|
||||
```
|
||||
|
||||
将 `~/dosprograms` 目录挂载为 DOSBox 中的虚拟驱动器 `C:\`
|
||||
|
||||
```
|
||||
Z:\>mount c ~/dosprograms
|
||||
```
|
||||
|
||||
你会看到类似下面的输出:
|
||||
|
||||
```
|
||||
Drive C is mounted as local directory /home/sk/dosprograms.
|
||||
```
|
||||
|
||||
|
||||

|
||||
|
||||
现在,使用命令切换到 C 盘:
|
||||
|
||||
```
|
||||
Z:\>c:
|
||||
```
|
||||
|
||||
然后切换到 `tc/bin` 目录:
|
||||
|
||||
```
|
||||
Z:\>cd tc/bin
|
||||
```
|
||||
|
||||
最后,运行 Turbo C++ 可执行文件:
|
||||
|
||||
```
|
||||
Z:\>tc.exe
|
||||
```
|
||||
|
||||
**备注:**只需输入前几个字母,然后按回车键可以自动填充文件名。
|
||||
|
||||

|
||||
|
||||
你现在将进入 Turbo C++ 控制台。
|
||||
|
||||

|
||||
|
||||
创建新文件(`ATL + F`)并开始编程:
|
||||
|
||||

|
||||
|
||||
你可以同样安装和运行其他经典 DOS 程序。
|
||||
|
||||
**故障排除:**
|
||||
|
||||
运行 Turbo C++ 或其他任何 DOS 程序时,你可能会遇到以下错误:
|
||||
|
||||
```
|
||||
DOSBox switched to max cycles, because of the setting: cycles=auto. If the game runs too fast try a fixed cycles amount in DOSBox's options. Exit to error: DRC64:Unhandled memory reference
|
||||
```
|
||||
|
||||
要解决此问题,编辑 `~/.dosbox/dosbox-x.xx.conf` 文件:
|
||||
|
||||
```
|
||||
$ nano ~/.dosbox/dosbox-0.74.conf
|
||||
```
|
||||
|
||||
找到以下变量:
|
||||
|
||||
```
|
||||
core=auto
|
||||
```
|
||||
|
||||
并更改其值为:
|
||||
|
||||
```
|
||||
core=normal
|
||||
```
|
||||
|
||||
现在,让我们看看如何运行基于DOS的游戏,例如 **Mario Bros VGA**。
|
||||
|
||||
从 [这里][1] 下载 Mario 游戏,并将其解压到 Linux 中的 `~/dosgames` 目录。
|
||||
|
||||
运行 DOSBox:
|
||||
|
||||
```
|
||||
$ dosbox
|
||||
```
|
||||
|
||||
我们刚才使用了虚拟驱动器 `C:` 来运行 DOS 程序。现在让我们使用 `D:` 作为虚拟驱动器来运行游戏。
|
||||
|
||||
在 DOSBox 提示符下,运行以下命令将 `~/dosgames` 目录挂载为虚拟驱动器 `D`:
|
||||
|
||||
```
|
||||
Z:\>mount d ~/dosgames
|
||||
```
|
||||
|
||||
进入驱动器 `D:`:
|
||||
|
||||
```
|
||||
Z:\>d:
|
||||
```
|
||||
|
||||
然后进入 mario 游戏目录并运行 `mario.exe` 文件来启动游戏。
|
||||
|
||||
```
|
||||
D:\>cd mario
|
||||
D:\>mario.exe
|
||||
```
|
||||
|
||||

|
||||
|
||||
开始玩游戏:
|
||||
|
||||

|
||||
|
||||
你可以同样像上面所说的那样运行任何基于 DOS 的游戏。 [点击这里] [2]查看可以使用 DOSBox 运行的游戏的完整列表。
|
||||
|
||||
### 总结
|
||||
|
||||
尽管 DOSBox 并不能作为 MS-DOS 的完全替代品,并且还缺少 MS-DOS 中的许多功能,但它足以安装和运行大多数的 DOS 游戏和程序。
|
||||
|
||||
有关更多详细信息,请参阅官方 [DOSBox手册][3]。
|
||||
|
||||
这就是全部内容。希望这对你有用。更多优秀指南即将到来。 敬请关注!
|
||||
|
||||
干杯!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-run-ms-dos-games-and-programs-in-linux/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[way-ww](https://github.com/way-ww)
|
||||
校对:[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.dosgames.com/game/mario-bros-vga
|
||||
[2]: https://www.dosbox.com/comp_list.php
|
||||
[3]: https://www.dosbox.com/DOSBoxManual.html
|
||||
222
published/20180907 6.828 lab tools guide.md
Normal file
222
published/20180907 6.828 lab tools guide.md
Normal file
@@ -0,0 +1,222 @@
|
||||
Caffeinated 6.828:实验工具指南
|
||||
======
|
||||
|
||||
熟悉你的环境对高效率的开发和调试来说是至关重要的。本文将为你简单概述一下 JOS 环境和非常有用的 GDB 和 QEMU 命令。话虽如此,但你仍然应该去阅读 GDB 和 QEMU 手册,来理解这些强大的工具如何使用。
|
||||
|
||||
### 调试小贴士
|
||||
|
||||
#### 内核
|
||||
|
||||
GDB 是你的朋友。使用 `qemu-gdb target`(或它的变体 `qemu-gdb-nox`)使 QEMU 等待 GDB 去绑定。下面在调试内核时用到的一些命令,可以去查看 GDB 的资料。
|
||||
|
||||
如果你遭遇意外的中断、异常、或三重故障,你可以使用 `-d` 参数要求 QEMU 去产生一个详细的中断日志。
|
||||
|
||||
调试虚拟内存问题时,尝试 QEMU 的监视命令 `info mem`(提供内存高级概述)或 `info pg`(提供更多细节内容)。注意,这些命令仅显示**当前**页表。
|
||||
|
||||
(在实验 4 以后)去调试多个 CPU 时,使用 GDB 的线程相关命令,比如 `thread` 和 `info threads`。
|
||||
|
||||
#### 用户环境(在实验 3 以后)
|
||||
|
||||
GDB 也可以去调试用户环境,但是有些事情需要注意,因为 GDB 无法区分开多个用户环境或区分开用户环境与内核环境。
|
||||
|
||||
你可以使用 `make run-name`(或编辑 `kern/init.c` 目录)来指定 JOS 启动的用户环境,为使 QEMU 等待 GDB 去绑定,使用 `run-name-gdb` 的变体。
|
||||
|
||||
你可以符号化调试用户代码,就像调试内核代码一样,但是你要告诉 GDB,哪个符号表用到符号文件命令上,因为它一次仅能够使用一个符号表。提供的 `.gdbinit` 用于加载内核符号表 `obj/kern/kernel`。对于一个用户环境,这个符号表在它的 ELF 二进制文件中,因此你可以使用 `symbol-file obj/user/name` 去加载它。不要从任何 `.o` 文件中加载符号,因为它们不会被链接器迁移进去(库是静态链接进 JOS 用户二进制文件中的,因此这些符号已经包含在每个用户二进制文件中了)。确保你得到了正确的用户二进制文件;在不同的二进制文件中,库函数被链接为不同的 EIP,而 GDB 并不知道更多的内容!
|
||||
|
||||
(在实验 4 以后)因为 GDB 绑定了整个虚拟机,所以它可以将时钟中断看作为一种控制转移。这使得从底层上不可能实现步进用户代码,因为一个时钟中断无形中保证了片刻之后虚拟机可以再次运行。因此可以使用 `stepi` 命令,因为它阻止了中断,但它仅可以步进一个汇编指令。断点一般来说可以正常工作,但要注意,因为你可能在不同的环境(完全不同的一个二进制文件)上遇到同一个 EIP。
|
||||
|
||||
### 参考
|
||||
|
||||
#### JOS makefile
|
||||
|
||||
JOS 的 GNUmakefile 包含了在各种方式中运行的 JOS 的许多假目标。所有这些目标都配置 QEMU 去监听 GDB 连接(`*-gdb` 目标也等待这个连接)。要在运行中的 QEMU 上启动它,只需要在你的实验目录中简单地运行 `gdb ` 即可。我们提供了一个 `.gdbinit` 文件,它可以在 QEMU 中自动指向到 GDB、加载内核符号文件、以及在 16 位和 32 位模式之间切换。退出 GDB 将关闭 QEMU。
|
||||
|
||||
* `make qemu`
|
||||
|
||||
在一个新窗口中构建所有的东西并使用 VGA 控制台和你的终端中的串行控制台启动 QEMU。想退出时,既可以关闭 VGA 窗口,也可以在你的终端中按 `Ctrl-c` 或 `Ctrl-a x`。
|
||||
* `make qemu-nox`
|
||||
|
||||
和 `make qemu` 一样,但仅使用串行控制台来运行。想退出时,按下 `Ctrl-a x`。这种方式在通过 SSH 拨号连接到 Athena 上时非常有用,因为 VGA 窗口会占用许多带宽。
|
||||
* `make qemu-gdb`
|
||||
|
||||
和 `make qemu` 一样,但它与任意时间被动接受 GDB 不同,而是暂停第一个机器指令并等待一个 GDB 连接。
|
||||
* `make qemu-nox-gdb`
|
||||
|
||||
它是 `qemu-nox` 和 `qemu-gdb` 目标的组合。
|
||||
* `make run-nam`
|
||||
|
||||
(在实验 3 以后)运行用户程序 _name_。例如,`make run-hello` 运行 `user/hello.c`。
|
||||
* `make run-name-nox`,`run-name-gdb`, `run-name-gdb-nox`
|
||||
|
||||
(在实验 3 以后)与 `qemu` 目标变量对应的 `run-name` 的变体。
|
||||
|
||||
makefile 也接受几个非常有用的变量:
|
||||
|
||||
* `make V=1 …`
|
||||
|
||||
详细模式。输出正在运行的每个命令,包括参数。
|
||||
* `make V=1 grade`
|
||||
|
||||
在评级测试失败后停止,并将 QEMU 的输出放入 `jos.out` 文件中以备检查。
|
||||
* `make QEMUEXTRA=' _args_ ' …`
|
||||
|
||||
指定传递给 QEMU 的额外参数。
|
||||
|
||||
#### JOS obj/
|
||||
|
||||
在构建 JOS 时,makefile 也产生一些额外的输出文件,这些文件在调试时非常有用:
|
||||
|
||||
* `obj/boot/boot.asm`、`obj/kern/kernel.asm`、`obj/user/hello.asm`、等等。
|
||||
|
||||
引导加载器、内核、和用户程序的汇编代码列表。
|
||||
* `obj/kern/kernel.sym`、`obj/user/hello.sym`、等等。
|
||||
|
||||
内核和用户程序的符号表。
|
||||
* `obj/boot/boot.out`、`obj/kern/kernel`、`obj/user/hello`、等等。
|
||||
|
||||
内核和用户程序链接的 ELF 镜像。它们包含了 GDB 用到的符号信息。
|
||||
|
||||
#### GDB
|
||||
|
||||
完整的 GDB 命令指南请查看 [GDB 手册][1]。下面是一些在 6.828 课程中非常有用的命令,它们中的一些在操作系统开发之外的领域几乎用不到。
|
||||
|
||||
* `Ctrl-c`
|
||||
|
||||
在当前指令处停止机器并打断进入到 GDB。如果 QEMU 有多个虚拟的 CPU,所有的 CPU 都会停止。
|
||||
* `c`(或 `continue`)
|
||||
|
||||
继续运行,直到下一个断点或 `Ctrl-c`。
|
||||
* `si`(或 `stepi`)
|
||||
|
||||
运行一个机器指令。
|
||||
* `b function` 或 `b file:line`(或 `breakpoint`)
|
||||
|
||||
在给定的函数或行上设置一个断点。
|
||||
* `b * addr`(或 `breakpoint`)
|
||||
|
||||
在 EIP 的 addr 处设置一个断点。
|
||||
* `set print pretty`
|
||||
|
||||
启用数组和结构的美化输出。
|
||||
* `info registers`
|
||||
|
||||
输出通用寄存器 `eip`、`eflags`、和段选择器。更多更全的机器寄存器状态转储,查看 QEMU 自己的 `info registers` 命令。
|
||||
* `x/ N x addr`
|
||||
|
||||
以十六进制显示虚拟地址 addr 处开始的 N 个词的转储。如果 N 省略,默认为 1。addr 可以是任何表达式。
|
||||
* `x/ N i addr`
|
||||
|
||||
显示从 addr 处开始的 N 个汇编指令。使用 `$eip` 作为 addr 将显示当前指令指针寄存器中的指令。
|
||||
* `symbol-file file`
|
||||
|
||||
(在实验 3 以后)切换到符号文件 file 上。当 GDB 绑定到 QEMU 后,它并不是虚拟机中进程边界内的一部分,因此我们要去告诉它去使用哪个符号。默认情况下,我们配置 GDB 去使用内核符号文件 `obj/kern/kernel`。如果机器正在运行用户代码,比如是 `hello.c`,你就需要使用 `symbol-file obj/user/hello` 去切换到 hello 的符号文件。
|
||||
|
||||
QEMU 将每个虚拟 CPU 表示为 GDB 中的一个线程,因此你可以使用 GDB 中所有的线程相关的命令去查看或维护 QEMU 的虚拟 CPU。
|
||||
|
||||
* `thread n`
|
||||
|
||||
GDB 在一个时刻只关注于一个线程(即:CPU)。这个命令将关注的线程切换到 n,n 是从 0 开始编号的。
|
||||
* `info threads`
|
||||
|
||||
列出所有的线程(即:CPU),包括它们的状态(活动还是停止)和它们在什么函数中。
|
||||
|
||||
|
||||
#### QEMU
|
||||
|
||||
QEMU 包含一个内置的监视器,它能够有效地检查和修改机器状态。想进入到监视器中,在运行 QEMU 的终端中按入 `Ctrl-a c` 即可。再次按下 `Ctrl-a c` 将切换回串行控制台。
|
||||
|
||||
监视器命令的完整参考资料,请查看 [QEMU 手册][2]。下面是 6.828 课程中用到的一些有用的命令:
|
||||
|
||||
* `xp/ N x paddr`
|
||||
|
||||
显示从物理地址 paddr 处开始的 N 个词的十六进制转储。如果 N 省略,默认为 1。这是 GDB 的 `x` 命令模拟的物理内存。
|
||||
* `info registers`
|
||||
|
||||
显示机器内部寄存器状态的一个完整转储。实践中,对于段选择器,这将包含机器的 _隐藏_ 段状态和局部、全局、和中断描述符表加任务状态寄存器。隐藏状态是在加载段选择器后,虚拟的 CPU 从 GDT/LDT 中读取的信息。下面是实验 1 中 JOS 内核处于运行中时的 CS 信息和每个字段的含义:
|
||||
|
||||
```c
|
||||
CS =0008 10000000 ffffffff 10cf9a00 DPL=0 CS32 [-R-]
|
||||
```
|
||||
|
||||
* `CS =0008`
|
||||
|
||||
代码选择器可见部分。我们使用段 0x8。这也告诉我们参考全局描述符表(0x8&4=0),并且我们的 CPL(当前权限级别)是 0x8&3=0。
|
||||
* `10000000`
|
||||
|
||||
这是段基址。线性地址 = 逻辑地址 + 0x10000000。
|
||||
* `ffffffff`
|
||||
|
||||
这是段限制。访问线性地址 0xffffffff 以上将返回段违规异常。
|
||||
* `10cf9a00`
|
||||
|
||||
段的原始标志,QEMU 将在接下来的几个字段中解码这些对我们有用的标志。
|
||||
* `DPL=0`
|
||||
|
||||
段的权限级别。一旦代码以权限 0 运行,它将就能够加载这个段。
|
||||
* `CS32`
|
||||
|
||||
这是一个 32 位代码段。对于数据段(不要与 DS 寄存器混淆了),另外的值还包括 `DS`,而对于本地描述符表是 `LDT`。
|
||||
* `[-R-]`
|
||||
|
||||
这个段是只读的。
|
||||
|
||||
* `info mem`
|
||||
|
||||
(在实验 2 以后)显示映射的虚拟内存和权限。比如:
|
||||
|
||||
```
|
||||
ef7c0000-ef800000 00040000 urw
|
||||
efbf8000-efc00000 00008000 -rw
|
||||
```
|
||||
|
||||
这告诉我们从 0xef7c0000 到 0xef800000 的 0x00040000 字节的内存被映射为读取/写入/用户可访问,而映射在 0xefbf8000 到 0xefc00000 之间的内存权限是读取/写入,但是仅限于内核可访问。
|
||||
|
||||
* `info pg`
|
||||
|
||||
(在实验 2 以后)显示当前页表结构。它的输出类似于 `info mem`,但与页目录条目和页表条目是有区别的,并且为每个条目给了单独的权限。重复的 PTE 和整个页表被折叠为一个单行。例如:
|
||||
|
||||
```
|
||||
VPN range Entry Flags Physical page
|
||||
[00000-003ff] PDE[000] -------UWP
|
||||
[00200-00233] PTE[200-233] -------U-P 00380 0037e 0037d 0037c 0037b 0037a ..
|
||||
[00800-00bff] PDE[002] ----A--UWP
|
||||
[00800-00801] PTE[000-001] ----A--U-P 0034b 00349
|
||||
[00802-00802] PTE[002] -------U-P 00348
|
||||
```
|
||||
|
||||
这里各自显示了两个页目录条目、虚拟地址范围 0x00000000 到 0x003fffff 以及 0x00800000 到 0x00bfffff。 所有的 PDE 都存在于内存中、可写入、并且用户可访问,而第二个 PDE 也是可访问的。这些页表中的第二个映射了三个页、虚拟地址范围 0x00800000 到 0x00802fff,其中前两个页是存在于内存中的、可写入、并且用户可访问的,而第三个仅存在于内存中,并且用户可访问。这些 PTE 的第一个条目映射在物理页 0x34b 处。
|
||||
|
||||
QEMU 也有一些非常有用的命令行参数,使用 `QEMUEXTRA` 变量可以将参数传递给 JOS 的 makefile。
|
||||
|
||||
* `make QEMUEXTRA='-d int' ...`
|
||||
|
||||
记录所有的中断和一个完整的寄存器转储到 `qemu.log` 文件中。你可以忽略前两个日志条目、“SMM: enter” 和 “SMM: after RMS”,因为这些是在进入引导加载器之前生成的。在这之后的日志条目看起来像下面这样:
|
||||
|
||||
```
|
||||
4: v=30 e=0000 i=1 cpl=3 IP=001b:00800e2e pc=00800e2e SP=0023:eebfdf28 EAX=00000005
|
||||
EAX=00000005 EBX=00001002 ECX=00200000 EDX=00000000
|
||||
ESI=00000805 EDI=00200000 EBP=eebfdf60 ESP=eebfdf28
|
||||
...
|
||||
```
|
||||
|
||||
第一行描述了中断。`4:` 只是一个日志记录计数器。`v` 提供了十六进程的向量号。`e` 提供了错误代码。`i=1` 表示它是由一个 `int` 指令(相对一个硬件产生的中断而言)产生的。剩下的行的意思很明显。对于一个寄存器转储而言,接下来看到的就是寄存器信息。
|
||||
|
||||
注意:如果你运行的是一个 0.15 版本之前的 QEMU,日志将写入到 `/tmp` 目录,而不是当前目录下。
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://pdos.csail.mit.edu/6.828/2018/labguide.html
|
||||
|
||||
作者:[csail.mit][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://pdos.csail.mit.edu
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://sourceware.org/gdb/current/onlinedocs/gdb/
|
||||
[2]: http://wiki.qemu.org/download/qemu-doc.html#pcsys_005fmonitor
|
||||
233
published/20180911 Tools Used in 6.828.md
Normal file
233
published/20180911 Tools Used in 6.828.md
Normal file
@@ -0,0 +1,233 @@
|
||||
Caffeinated 6.828:使用的工具
|
||||
======
|
||||
|
||||
在这个课程中你将使用两套工具:一个是 x86 模拟器 QEMU,它用来运行你的内核;另一个是编译器工具链,包括汇编器、链接器、C 编译器,以及调试器,它们用来编译和测试你的内核。本文有你需要去下载和安装你自己的副本相关信息。本课程假定你熟悉所有出现的 Unix 命令的用法。
|
||||
|
||||
我们强烈推荐你使用一个 Debathena 机器去做你的实验,比如 athena.dialup.mit.edu。如果你使用运行在 Linux 上的 MIT Athena 机器,那么本课程所需要的所有软件工具都在 6.828 的存储中:只需要输入 `add -f 6.828` 就可以访问它们。
|
||||
|
||||
如果你不使用 Debathena 机器,我们建议你使用一台 Linux 虚拟机。如果是这样,你可以在你的 Linux 虚拟机上构建和安装工具。我们将在下面介绍如何在 Linux 和 MacOS 计算上来构建和安装工具。
|
||||
|
||||
在 [Cygwin][1] 的帮助下,在 Windows 中运行这个开发环境也是可行的。安装 cygwin,并确保安装了 flex 和 bison 包(它们在开发 header 软件包分类下面)。
|
||||
|
||||
对于 6.828 中使用的工具中的有用的命令,请参考[实验工具指南][2]。
|
||||
|
||||
### 编译器工具链
|
||||
|
||||
“编译器工具链“ 是一套程序,包括一个 C 编译器、汇编器和链接器,使用它们来将代码转换成可运行的二进制文件。你需要一个能够生成在 32 位 Intel 架构(x86 架构)上运行的 ELF 二进制格式程序的编译器工具链。
|
||||
|
||||
#### 测试你的编译器工具链
|
||||
|
||||
现代的 Linux 和 BSD UNIX 发行版已经为 6.828 提供了一个合适的工具链。去测试你的发行版,可以输入如下的命令:
|
||||
|
||||
```
|
||||
% objdump -i
|
||||
```
|
||||
|
||||
第二行应该是 `elf32-i386`。
|
||||
|
||||
```
|
||||
% gcc -m32 -print-libgcc-file-name
|
||||
```
|
||||
|
||||
这个命令应该会输出如 `/usr/lib/gcc/i486-linux-gnu/version/libgcc.a` 或 `/usr/lib/gcc/x86_64-linux-gnu/version/32/libgcc.a` 这样的东西。
|
||||
|
||||
如果这些命令都运行成功,说明你的工具链都已安装,你不需要去编译你自己的工具链。
|
||||
|
||||
如果 `gcc` 命令失败,你可能需要去安装一个开发环境。在 Ubuntu Linux 上,输入如下的命令:
|
||||
|
||||
```
|
||||
% sudo apt-get install -y build-essential gdb
|
||||
```
|
||||
|
||||
在 64 位的机器上,你可能需要去安装一个 32 位的支持库。链接失败的表现是有一个类似于 “`__udivdi3` not found” 和 “`__muldi3` not found” 的错误信息。在 Ubuntu Linux 上,输入如下的命令去尝试修复这个问题:
|
||||
|
||||
```
|
||||
% sudo apt-get install gcc-multilib
|
||||
```
|
||||
|
||||
#### 使用一个虚拟机
|
||||
|
||||
获得一个兼容的工具链的最容易的另外的方法是,在你的计算机上安装一个现代的 Linux 发行版。使用虚拟化平台,Linux 可以与你正常的计算环境和平共处。安装一个 Linux 虚拟机共有两步。首先,去下载一个虚拟化平台。
|
||||
|
||||
* [VirtualBox][3](对 Mac、Linux、Windows 免费)— [下载地址][3]
|
||||
* [VMware Player][4](对 Linux 和 Windows 免费,但要求注册)
|
||||
* [VMware Fusion][5](可以从 IS&T 免费下载)。
|
||||
|
||||
VirtualBox 有点慢并且灵活性欠佳,但它免费!
|
||||
|
||||
虚拟化平台安装完成后,下载一个你选择的 Linux 发行版的引导磁盘镜像。
|
||||
|
||||
* 我们使用的是 [Ubuntu 桌面版][6]。
|
||||
|
||||
这将下载一个命名类似于 `ubuntu-10.04.1-desktop-i386.iso` 的文件。启动你的虚拟化平台并创建一个新(32 位)的虚拟机。使用下载的 Ubuntu 镜像作为一个引导磁盘;安装过程在不同的虚拟机上有所不同,但都很简单。就像上面一样输入 `objdump -i`,去验证你的工具是否已安装。你将在虚拟机中完成你的工作。
|
||||
|
||||
#### 构建你自己的编译器工具链
|
||||
|
||||
你需要花一些时间来设置,但是比起一个虚拟机来说,它的性能要稍好一些,并且让你工作在你熟悉的环境中(Unix/MacOS)。对于 MacOS 命令,你可以快进到文章的末尾部分去看。
|
||||
|
||||
##### Linux
|
||||
|
||||
通过将下列行添加到 `conf/env.mk` 中去使用你自己的工具链:
|
||||
|
||||
```
|
||||
GCCPREFIX=
|
||||
```
|
||||
|
||||
我们假设你将工具链安装到了 `/usr/local` 中。你将需要大量的空间(大约 1 GB)去编译工具。如果你空间不足,在它的 `make install` 步骤之后删除它们的目录。
|
||||
|
||||
下载下列包:
|
||||
|
||||
+ ftp://ftp.gmplib.org/pub/gmp-5.0.2/gmp-5.0.2.tar.bz2
|
||||
+ https://www.mpfr.org/mpfr-3.1.2/mpfr-3.1.2.tar.bz2
|
||||
+ http://www.multiprecision.org/downloads/mpc-0.9.tar.gz
|
||||
+ http://ftpmirror.gnu.org/binutils/binutils-2.21.1.tar.bz2
|
||||
+ http://ftpmirror.gnu.org/gcc/gcc-4.6.4/gcc-core-4.6.4.tar.bz2
|
||||
+ http://ftpmirror.gnu.org/gdb/gdb-7.3.1.tar.bz2
|
||||
|
||||
(你可能也在使用这些包的最新版本。)解包并构建。安装到 `/usr/local` 中,它是我们建议的。要安装到不同的目录,如 `$PFX`,注意相应修改。如果有问题,可以看下面。
|
||||
|
||||
```c
|
||||
export PATH=$PFX/bin:$PATH
|
||||
export LD_LIBRARY_PATH=$PFX/lib:$LD_LIBRARY_PATH
|
||||
|
||||
tar xjf gmp-5.0.2.tar.bz2
|
||||
cd gmp-5.0.2
|
||||
./configure --prefix=$PFX
|
||||
make
|
||||
make install # This step may require privilege (sudo make install)
|
||||
cd ..
|
||||
|
||||
tar xjf mpfr-3.1.2.tar.bz2
|
||||
cd mpfr-3.1.2
|
||||
./configure --prefix=$PFX --with-gmp=$PFX
|
||||
make
|
||||
make install # This step may require privilege (sudo make install)
|
||||
cd ..
|
||||
|
||||
tar xzf mpc-0.9.tar.gz
|
||||
cd mpc-0.9
|
||||
./configure --prefix=$PFX --with-gmp=$PFX --with-mpfr=$PFX
|
||||
make
|
||||
make install # This step may require privilege (sudo make install)
|
||||
cd ..
|
||||
|
||||
|
||||
tar xjf binutils-2.21.1.tar.bz2
|
||||
cd binutils-2.21.1
|
||||
./configure --prefix=$PFX --target=i386-jos-elf --disable-werror
|
||||
make
|
||||
make install # This step may require privilege (sudo make install)
|
||||
cd ..
|
||||
|
||||
i386-jos-elf-objdump -i
|
||||
# Should produce output like:
|
||||
# BFD header file version (GNU Binutils) 2.21.1
|
||||
# elf32-i386
|
||||
# (header little endian, data little endian)
|
||||
# i386...
|
||||
|
||||
|
||||
tar xjf gcc-core-4.6.4.tar.bz2
|
||||
cd gcc-4.6.4
|
||||
mkdir build # GCC will not compile correctly unless you build in a separate directory
|
||||
cd build
|
||||
../configure --prefix=$PFX --with-gmp=$PFX --with-mpfr=$PFX --with-mpc=$PFX \
|
||||
--target=i386-jos-elf --disable-werror \
|
||||
--disable-libssp --disable-libmudflap --with-newlib \
|
||||
--without-headers --enable-languages=c MAKEINFO=missing
|
||||
make all-gcc
|
||||
make install-gcc # This step may require privilege (sudo make install-gcc)
|
||||
make all-target-libgcc
|
||||
make install-target-libgcc # This step may require privilege (sudo make install-target-libgcc)
|
||||
cd ../..
|
||||
|
||||
i386-jos-elf-gcc -v
|
||||
# Should produce output like:
|
||||
# Using built-in specs.
|
||||
# COLLECT_GCC=i386-jos-elf-gcc
|
||||
# COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/i386-jos-elf/4.6.4/lto-wrapper
|
||||
# Target: i386-jos-elf
|
||||
|
||||
|
||||
tar xjf gdb-7.3.1.tar.bz2
|
||||
cd gdb-7.3.1
|
||||
./configure --prefix=$PFX --target=i386-jos-elf --program-prefix=i386-jos-elf- \
|
||||
--disable-werror
|
||||
make all
|
||||
make install # This step may require privilege (sudo make install)
|
||||
cd ..
|
||||
```
|
||||
|
||||
**Linux 排错:**
|
||||
|
||||
Q:我不能运行 `make install`,因为我在这台机器上没有 root 权限。
|
||||
|
||||
A:我们的指令假定你是安装到了 `/usr/local` 目录中。但是,在你的环境中可能并不是这样做的。如果你仅能够在你的家目录中安装代码。那么在上面的命令中,使用 `--prefix=$HOME` 去替换 `--prefix=/usr/local`。你也需要修改你的 `PATH` 和 `LD_LIBRARY_PATH` 环境变量,以通知你的 shell 这个工具的位置。例如:
|
||||
|
||||
```
|
||||
export PATH=$HOME/bin:$PATH
|
||||
export LD_LIBRARY_PATH=$HOME/lib:$LD_LIBRARY_PATH
|
||||
```
|
||||
|
||||
在你的 `~/.bashrc` 文件中输入这些行,以便于你登入后不需要每次都输入它们。
|
||||
|
||||
Q:我构建失败了,错误信息是 “library not found”。
|
||||
|
||||
A:你需要去设置你的 `LD_LIBRARY_PATH`。环境变量必须包含 `PREFIX/lib` 目录(例如 `/usr/local/lib`)。
|
||||
|
||||
##### MacOS
|
||||
|
||||
首先从 Mac OSX 上安装开发工具开始:`xcode-select --install` 。
|
||||
|
||||
你可以从 homebrew 上安装 qemu 的依赖,但是不能去安装 qemu,因为我们需要安装打了 6.828 补丁的 qemu。
|
||||
|
||||
```
|
||||
brew install $(brew deps qemu)
|
||||
```
|
||||
|
||||
gettext 工具并不能把它已安装的二进制文件添加到路径中,因此你需要去运行:
|
||||
|
||||
```
|
||||
PATH=${PATH}:/usr/local/opt/gettext/bin make install
|
||||
```
|
||||
|
||||
完成后,开始安装 qemu。
|
||||
|
||||
### QEMU 模拟器
|
||||
|
||||
[QEMU][8] 是一个现代化的、并且速度非常快的 PC 模拟器。QEMU 的 2.3.0 版本是设置在 Athena 上的 6.828 中的 x86 机器存储中的(`add -f 6.828`)。
|
||||
|
||||
不幸的是,QEMU 的调试功能虽然很强大,但是有点不成熟,因此我们强烈建议你使用我们打过 6.828 补丁的版本,而不是发行版自带的版本。这个安装在 Athena 上的 QEMU 版本已经打过补丁了。构建你自己的、打 6.828 补丁的 QEMU 版本的过程如下:
|
||||
|
||||
1. 克隆 IAP 6.828 QEMU 的 git 仓库:`git clone https://github.com/mit-pdos/6.828-qemu.git qemu`。
|
||||
2. 在 Linux 上,你或许需要安装几个库。我们成功地在 Debian/Ubuntu 16.04 上构建 6.828 版的 QEMU 需要安装下列的库:libsdl1.2-dev、libtool-bin、libglib2.0-dev、libz-dev 和 libpixman-1-dev。
|
||||
3. 配置源代码(方括号中是可选参数;用你自己的真实路径替换 `PFX`)
|
||||
1. Linux:`./configure --disable-kvm --disable-werror [--prefix=PFX] [--target-list="i386-softmmu x86_64-softmmu"]`。
|
||||
2. OS X:`./configure --disable-kvm --disable-werror --disable-sdl [--prefix=PFX] [--target-list="i386-softmmu x86_64-softmmu"]`。`prefix` 参数指定安装 QEMU 的位置;如果不指定,将缺省安装 QEMU 到 `/usr/local` 目录中。`target-list` 参数将简单地简化 QEMU 所支持的架构。
|
||||
4. 运行 `make && make install`。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://pdos.csail.mit.edu/6.828/2018/tools.html
|
||||
|
||||
作者:[csail.mit][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://pdos.csail.mit.edu
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://www.cygwin.com
|
||||
[2]: labguide.html
|
||||
[3]: http://www.oracle.com/us/technologies/virtualization/oraclevm/
|
||||
[4]: http://www.vmware.com/products/player/
|
||||
[5]: http://www.vmware.com/products/fusion/
|
||||
[6]: http://www.ubuntu.com/download/desktop
|
||||
[8]: http://www.nongnu.org/qemu/
|
||||
[9]: mailto:6828-staff@lists.csail.mit.edu
|
||||
[10]: https://i.creativecommons.org/l/by/3.0/us/88x31.png
|
||||
[11]: https://creativecommons.org/licenses/by/3.0/us/
|
||||
[12]: https://pdos.csail.mit.edu/6.828/2018/index.html
|
||||
@@ -0,0 +1,388 @@
|
||||
在命令行使用 Pandoc 进行文件转换
|
||||
======
|
||||
|
||||
> 这篇指南介绍如何使用 Pandoc 将文档转换为多种不同的格式。
|
||||
|
||||

|
||||
|
||||
Pandoc 是一个命令行工具,用于将文件从一种标记语言转换为另一种标记语言。标记语言使用标签来标记文档的各个部分。常用的标记语言包括 Markdown、ReStructuredText、HTML、LaTex、ePub 和 Microsoft Word DOCX。
|
||||
|
||||
简单来说,[Pandoc][1] 允许你将一些文件从一种标记语言转换为另一种标记语言。典型的例子包括将 Markdown 文件转换为演示文稿、LaTeX,PDF 甚至是 ePub。
|
||||
|
||||
本文将解释如何使用 Pandoc 从单一标记语言(在本文中为 Markdown)生成多种格式的文档,引导你完成从 Pandoc 安装,到展示如何创建多种类型的文档,再到提供有关如何编写易于移植到其他格式的文档的提示。
|
||||
|
||||
文中还将解释使用元信息文件对文档内容和元信息(例如,作者姓名、使用的模板、书目样式等)进行分离的意义。
|
||||
|
||||
### Pandoc 安装和要求
|
||||
|
||||
Pandoc 默认安装在大多数 Linux 发行版中。本教程使用 pandoc-2.2.3.2 和 pandoc-citeproc-0.14.3。如果不打算生成 PDF,那么这两个包就足够了。但是,我建议也安装 texlive,这样就可以选择生成 PDF 了。
|
||||
|
||||
通过以下命令在 Linux 上安装这些程序:
|
||||
|
||||
```
|
||||
sudo apt-get install pandoc pandoc-citeproc texlive
|
||||
```
|
||||
|
||||
您可以在 Pandoc 的网站上找到其他平台的 [安装说明][2]。
|
||||
|
||||
我强烈建议安装 [pandoc-crossref][3],这是一个“用于对图表,方程式,表格和交叉引用进行编号的过滤器”。最简单的安装方式是下载 [预构建的可执行文件][4],但也可以通过以下命令从 Haskell 的软件包管理器 cabal 安装它:
|
||||
|
||||
```
|
||||
cabal update
|
||||
cabal install pandoc-crossref
|
||||
```
|
||||
|
||||
如果需要额外的 Haskell [安装信息][5],请参考 pandoc-crossref 的 GitHub 仓库。
|
||||
|
||||
### 几个例子
|
||||
|
||||
我将通过解释如何生成三种类型的文档来演示 Pandoc 的工作原理:
|
||||
|
||||
- 由包含数学公式的 LaTeX 文件创建的网页
|
||||
- 由 Markdown 文件生成的 Reveal.js 幻灯片
|
||||
- 混合 Markdown 和 LaTeX 的合同文件
|
||||
|
||||
#### 创建一个包含数学公式的网站
|
||||
|
||||
Pandoc 的优势之一是以不同的输出文件格式显示数学公式。例如,我们可以从包含一些数学符号(用 LaTeX 编写)的 LaTeX 文档(名为 `math.tex`)生成一个网页。
|
||||
|
||||
`math.tex` 文档如下所示:
|
||||
|
||||
```
|
||||
% Pandoc math demos
|
||||
|
||||
$a^2 + b^2 = c^2$
|
||||
|
||||
$v(t) = v_0 + \frac{1}{2}at^2$
|
||||
|
||||
$\gamma = \frac{1}{\sqrt{1 - v^2/c^2}}$
|
||||
|
||||
$\exists x \forall y (Rxy \equiv Ryx)$
|
||||
|
||||
$p \wedge q \models p$
|
||||
|
||||
$\Box\diamond p\equiv\diamond p$
|
||||
|
||||
$\int_{0}^{1} x dx = \left[ \frac{1}{2}x^2 \right]_{0}^{1} = \frac{1}{2}$
|
||||
|
||||
$e^x = \sum_{n=0}^\infty \frac{x^n}{n!} = \lim_{n\rightarrow\infty} (1+x/n)^n$
|
||||
```
|
||||
|
||||
通过输入以下命令将 LaTeX 文档转换为名为 `mathMathML.html` 的网站:
|
||||
|
||||
```
|
||||
pandoc math.tex -s --mathml -o mathMathML.html
|
||||
```
|
||||
|
||||
参数 `-s` 告诉 Pandoc 生成一个独立的网页(而不是网页片段,因此它将包括 HTML 中的 head 和 body 标签),`-mathml` 参数强制 Pandoc 将 LaTeX 中的数学公式转换成 MathML,从而可以由现代浏览器进行渲染。
|
||||
|
||||

|
||||
|
||||
看一下 [网页效果][6] 和 [代码][7],代码仓库中的 Makefile 使得运行更加简单。
|
||||
|
||||
#### 制作一个 Reveal.js 幻灯片
|
||||
|
||||
使用 Pandoc 从 Markdown 文件生成简单的演示文稿很容易。幻灯片包含顶级幻灯片和下面的嵌套幻灯片。可以通过键盘控制演示文稿,从一个顶级幻灯片跳转到下一个顶级幻灯片,或者显示顶级幻灯片下面的嵌套幻灯片。 这种结构在基于 HTML 的演示文稿框架中很常见。
|
||||
|
||||
创建一个名为 `SLIDES` 的幻灯片文档(参见 [代码仓库][8])。首先,在 `%` 后面添加幻灯片的元信息(例如,标题、作者和日期):
|
||||
|
||||
```
|
||||
% Case Study
|
||||
% Kiko Fernandez Reyes
|
||||
% Sept 27, 2017
|
||||
```
|
||||
|
||||
这些元信息同时也创建了第一张幻灯片。要添加更多幻灯片,使用 Markdown 的一级标题(在下面例子中的第5行,参考 [Markdown 的一级标题][9] )生成顶级幻灯片。
|
||||
|
||||
例如,可以通过以下命令创建一个标题为 “Case Study”、顶级幻灯片名为 “Wine Management System” 的演示文稿:
|
||||
|
||||
```
|
||||
% Case Study
|
||||
% Kiko Fernandez Reyes
|
||||
% Sept 27, 2017
|
||||
|
||||
# Wine Management System
|
||||
```
|
||||
|
||||
使用 Markdown 的二级标题将内容(比如包含一个新管理系统的说明和实现的幻灯片)放入刚刚创建的顶级幻灯片。下面添加另外两张幻灯片(在下面例子中的第 7 行和 14 行 ,参考 [Markdown 的二级标题][9] )。
|
||||
|
||||
- 第一个二级幻灯片的标题为 “Idea”,并显示瑞士国旗的图像
|
||||
- 第二个二级幻灯片的标题为 “Implementation”
|
||||
|
||||
```
|
||||
% Case Study
|
||||
% Kiko Fernandez Reyes
|
||||
% Sept 27, 2017
|
||||
|
||||
# Wine Management System
|
||||
|
||||
## <img src="img/SwissFlag.png" style="vertical-align:middle"/> Idea
|
||||
|
||||
## Implementation
|
||||
```
|
||||
|
||||
我们现在有一个顶级幻灯片(`#Wine Management System`),其中包含两张幻灯片(`## Idea` 和 `## Implementation`)。
|
||||
|
||||
通过创建一个由符号 `>` 开头的 Markdown 列表,在这两张幻灯片中添加一些内容。在上面代码的基础上,在第一张幻灯片中添加两个项目(第 9-10 行),第二张幻灯片中添加五个项目(第 16-20 行):
|
||||
|
||||
```
|
||||
% Case Study
|
||||
% Kiko Fernandez Reyes
|
||||
% Sept 27, 2017
|
||||
|
||||
# Wine Management System
|
||||
|
||||
## <img src="img/SwissFlag.png" style="vertical-align:middle"/> Idea
|
||||
|
||||
>- Swiss love their **wine** and cheese
|
||||
>- Create a *simple* wine tracker system
|
||||
|
||||

|
||||
|
||||
## Implementation
|
||||
|
||||
>- Bottles have a RFID tag
|
||||
>- RFID reader (emits and read signal)
|
||||
>- **Raspberry Pi**
|
||||
>- **Server (online shop)**
|
||||
>- Mobile app
|
||||
```
|
||||
|
||||
上面的代码添加了马特洪峰的图像,也可以使用纯 Markdown 语法或添加 HTML 标签来改进幻灯片。
|
||||
|
||||
要生成幻灯片,Pandoc 需要引用 Reveal.js 库,因此它必须与 `SLIDES` 文件位于同一文件夹中。生成幻灯片的命令如下所示:
|
||||
|
||||
```
|
||||
pandoc -t revealjs -s --self-contained SLIDES \
|
||||
-V theme=white -V slideNumber=true -o index.html
|
||||
```
|
||||
|
||||

|
||||
|
||||
上面的 Pandoc 命令使用了以下参数:
|
||||
|
||||
- `-t revealjs` 表示将输出一个 revealjs 演示文稿
|
||||
- `-s` 告诉 Pandoc 生成一个独立的文档
|
||||
- `--self-contained` 生成没有外部依赖关系的 HTML 文件
|
||||
- `-V` 设置以下变量:
|
||||
- `theme=white` 将幻灯片的主题设为白色
|
||||
- `slideNumber=true` 显示幻灯片编号
|
||||
- `-o index.html` 在名为 `index.html` 的文件中生成幻灯片
|
||||
|
||||
为了简化操作并避免键入如此长的命令,创建以下 Makefile:
|
||||
|
||||
```
|
||||
all: generate
|
||||
|
||||
generate:
|
||||
pandoc -t revealjs -s --self-contained SLIDES \
|
||||
-V theme=white -V slideNumber=true -o index.html
|
||||
|
||||
clean: index.html
|
||||
rm index.html
|
||||
|
||||
.PHONY: all clean generate
|
||||
```
|
||||
|
||||
可以在 [这个仓库][8] 中找到所有代码。
|
||||
|
||||
#### 制作一份多种格式的合同
|
||||
|
||||
假设你正在准备一份文件,并且(这样的情况现在很常见)有些人想用 Microsoft Word 格式,其他人使用自由软件,想要 ODT 格式,而另外一些人则需要 PDF。你不必使用 OpenOffice 或 LibreOffice 来生成 DOCX 或 PDF 格式的文件,可以用 Markdown 创建一份文档(如果需要高级格式,可以使用一些 LaTeX 语法),并生成任何这些文件类型。
|
||||
|
||||
和以前一样,首先声明文档的元信息(标题、作者和日期):
|
||||
|
||||
```
|
||||
% Contract Agreement for Software X
|
||||
% Kiko Fernandez-Reyes
|
||||
% August 28th, 2018
|
||||
```
|
||||
|
||||
然后在 Markdown 中编写文档(如果需要高级格式,则添加 LaTeX)。例如,创建一个固定间隔的表格(在 LaTeX 中用 `\hspace{3cm}` 声明)以及客户端和承包商应填写的行(在 LaTeX 中用 `\hrulefill` 声明)。之后,添加一个用 Markdown 编写的表格。
|
||||
|
||||
创建的文档如下所示:
|
||||
|
||||

|
||||
|
||||
创建此文档的代码如下:
|
||||
|
||||
```
|
||||
% Contract Agreement for Software X
|
||||
% Kiko Fernandez-Reyes
|
||||
% August 28th, 2018
|
||||
|
||||
...
|
||||
|
||||
### Work Order
|
||||
|
||||
\begin{table}[h]
|
||||
\begin{tabular}{ccc}
|
||||
The Contractor & \hspace{3cm} & The Customer \\
|
||||
& & \\
|
||||
& & \\
|
||||
\hrulefill & \hspace{3cm} & \hrulefill \\
|
||||
%
|
||||
Name & \hspace{3cm} & Name \\
|
||||
& & \\
|
||||
& & \\
|
||||
\hrulefill & \hspace{3cm} & \hrulefill \\
|
||||
...
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\vspace{1cm}
|
||||
|
||||
+--------------------------------------------|----------|-------------+
|
||||
| Type of Service | Cost | Total |
|
||||
+:===========================================+=========:+:===========:+
|
||||
| Game Engine | 70.0 | 70.0 |
|
||||
| | | |
|
||||
+--------------------------------------------|----------|-------------+
|
||||
| | | |
|
||||
+--------------------------------------------|----------|-------------+
|
||||
| Extra: Comply with defined API functions | 10.0 | 10.0 |
|
||||
| and expected returned format | | |
|
||||
+--------------------------------------------|----------|-------------+
|
||||
| | | |
|
||||
+--------------------------------------------|----------|-------------+
|
||||
| **Total Cost** | | **80.0** |
|
||||
+--------------------------------------------|----------|-------------+
|
||||
```
|
||||
|
||||
要生成此文档所需的三种不同输出格式,编写如下的 Makefile:
|
||||
|
||||
```
|
||||
DOCS=contract-agreement.md
|
||||
|
||||
all: $(DOCS)
|
||||
pandoc -s $(DOCS) -o $(DOCS:md=pdf)
|
||||
pandoc -s $(DOCS) -o $(DOCS:md=docx)
|
||||
pandoc -s $(DOCS) -o $(DOCS:md=odt)
|
||||
|
||||
clean:
|
||||
rm *.pdf *.docx *.odt
|
||||
|
||||
.PHONY: all clean
|
||||
```
|
||||
|
||||
4 到 7 行是生成三种不同输出格式的具体命令:
|
||||
|
||||
如果有多个 Markdown 文件并想将它们合并到一个文档中,需要按照希望它们出现的顺序编写命令。例如,在撰写本文时,我创建了三个文档:一个介绍文档、三个示例和一些高级用法。以下命令告诉 Pandoc 按指定的顺序将这些文件合并在一起,并生成一个名为 document.pdf 的 PDF 文件。
|
||||
|
||||
```
|
||||
pandoc -s introduction.md examples.md advanced-uses.md -o document.pdf
|
||||
```
|
||||
|
||||
### 模板和元信息
|
||||
|
||||
编写复杂的文档并非易事,你需要遵循一系列独立于内容的规则,例如使用特定的模板、编写摘要、嵌入特定字体,甚至可能要声明关键字。所有这些都与内容无关:简单地说,它就是元信息。
|
||||
|
||||
Pandoc 使用模板生成不同的输出格式。例如,有一个 LaTeX 的模板,还有一个 ePub 的模板,等等。这些模板的元信息中有未赋值的变量。使用以下命令找出 Pandoc 模板中可用的元信息:
|
||||
|
||||
```
|
||||
pandoc -D FORMAT
|
||||
```
|
||||
|
||||
例如,LaTex 的模版是:
|
||||
|
||||
```
|
||||
pandoc -D latex
|
||||
```
|
||||
|
||||
按照以下格式输出:
|
||||
|
||||
```
|
||||
$if(title)$
|
||||
\title{$title$$if(thanks)$\thanks{$thanks$}$endif$}
|
||||
$endif$
|
||||
$if(subtitle)$
|
||||
\providecommand{\subtitle}[1]{}
|
||||
\subtitle{$subtitle$}
|
||||
$endif$
|
||||
$if(author)$
|
||||
\author{$for(author)$$author$$sep$ \and $endfor$}
|
||||
$endif$
|
||||
$if(institute)$
|
||||
\providecommand{\institute}[1]{}
|
||||
\institute{$for(institute)$$institute$$sep$ \and $endfor$}
|
||||
$endif$
|
||||
\date{$date$}
|
||||
$if(beamer)$
|
||||
$if(titlegraphic)$
|
||||
\titlegraphic{\includegraphics{$titlegraphic$}}
|
||||
$endif$
|
||||
$if(logo)$
|
||||
\logo{\includegraphics{$logo$}}
|
||||
$endif$
|
||||
$endif$
|
||||
|
||||
\begin{document}
|
||||
```
|
||||
|
||||
如你所见,输出的内容中有标题、致谢、作者、副标题和机构模板变量(还有许多其他可用的变量)。可以使用 YAML 元区块轻松设置这些内容。 在下面例子的第 1-5 行中,我们声明了一个 YAML 元区块并设置了一些变量(使用上面合同协议的例子):
|
||||
|
||||
```
|
||||
---
|
||||
title: Contract Agreement for Software X
|
||||
author: Kiko Fernandez-Reyes
|
||||
date: August 28th, 2018
|
||||
---
|
||||
|
||||
(continue writing document as in the previous example)
|
||||
```
|
||||
|
||||
这样做非常奏效,相当于以前的代码:
|
||||
|
||||
```
|
||||
% Contract Agreement for Software X
|
||||
% Kiko Fernandez-Reyes
|
||||
% August 28th, 2018
|
||||
```
|
||||
|
||||
然而,这样做将元信息与内容联系起来,也即 Pandoc 将始终使用此信息以新格式输出文件。如果你将要生成多种文件格式,最好要小心一点。例如,如果你需要以 ePub 和 HTML 的格式生成合同,并且 ePub 和 HTML 需要不同的样式规则,该怎么办?
|
||||
|
||||
考虑一下这些情况:
|
||||
|
||||
- 如果你只是尝试嵌入 YAML 变量 `css:style-epub.css`,那么将从 HTML 版本中移除该变量。这不起作用。
|
||||
- 复制文档显然也不是一个好的解决方案,因为一个版本的更改不会与另一个版本同步。
|
||||
- 你也可以像下面这样将变量添加到 Pandoc 命令中:
|
||||
|
||||
```
|
||||
pandoc -s -V css=style-epub.css document.md document.epub
|
||||
pandoc -s -V css=style-html.css document.md document.html
|
||||
```
|
||||
|
||||
我的观点是,这样做很容易从命令行忽略这些变量,特别是当你需要设置数十个变量时(这可能出现在编写复杂文档的情况中)。现在,如果将它们放在同一文件中(`meta.yaml` 文件),则只需更新或创建新的元信息文件即可生成所需的输出格式。然后你会编写这样的命令:
|
||||
|
||||
```
|
||||
pandoc -s meta-pub.yaml document.md document.epub
|
||||
pandoc -s meta-html.yaml document.md document.html
|
||||
```
|
||||
|
||||
这是一个更简洁的版本,你可以从单个文件更新所有元信息,而无需更新文档的内容。
|
||||
|
||||
### 结语
|
||||
|
||||
通过以上的基本示例,我展示了 Pandoc 在将 Markdown 文档转换为其他格式方面是多么出色。
|
||||
|
||||
------
|
||||
|
||||
via: https://opensource.com/article/18/9/intro-pandoc
|
||||
|
||||
作者:[Kiko Fernandez-Reyes][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[jlztan](https://github.com/jlztan)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/kikofernandez
|
||||
[1]: https://pandoc.org/
|
||||
[2]: http://pandoc.org/installing.html
|
||||
[3]: https://hackage.haskell.org/package/pandoc-crossref
|
||||
[4]: https://github.com/lierdakil/pandoc-crossref/releases/tag/v0.3.2.1
|
||||
[5]: https://github.com/lierdakil/pandoc-crossref#installation
|
||||
[6]: http://pandoc.org/demo/mathMathML.html
|
||||
[7]: https://github.com/kikofernandez/pandoc-examples/tree/master/math
|
||||
[8]: https://github.com/kikofernandez/pandoc-examples/tree/master/slides
|
||||
[9]: https://daringfireball.net/projects/markdown/syntax#header
|
||||
@@ -0,0 +1,67 @@
|
||||
IssueHunt:一个新的开源软件打赏平台
|
||||
======
|
||||
|
||||
![IssueHunt][4]
|
||||
|
||||
许多开源开发者和公司都在努力解决的问题之一就是资金问题。社区中有一种假想,甚至是期望,必须免费提供自由开源软件(FOSS)。但即使是 FOSS 也需要资金来继续开发。如果我们不建立让软件持续开发的系统,我们怎能期待更高质量的软件?
|
||||
|
||||
我们已经写了一篇关于[开源资金平台][1]的文章来试图解决这个缺点,截至今年 7 月,市场上出现了一个新的竞争者,旨在帮助填补这个空白:[IssueHunt][2]。
|
||||
|
||||
### IssueHunt: 开源软件打赏平台
|
||||
|
||||
![IssueHunt website][3]
|
||||
|
||||
IssueHunt 提供了一种服务,对自由开发者的开源代码贡献进行支付。它通过所谓的赏金来实现:给予解决特定问题的任何人财务奖励。这些奖励的资金来自任何愿意捐赠以修复任何特定 bug 或添加功能的人。
|
||||
|
||||
如果你想修复的某个开源软件存在问题,你可以根据自己选择的方式提供奖励金额。
|
||||
|
||||
想要自己的产品被争抢解决么?在 IssueHunt 上向任何解决问题的人提供奖金就好了。就这么简单。
|
||||
|
||||
如果你是程序员,则可以浏览未解决的问题。解决这个问题(如果你可以的话),在 GitHub 存储库上提交拉取请求,如果你的拉取请求被合并,那么你就会得到了钱。
|
||||
|
||||
#### IssueHunt 最初是 Boostnote 的内部项目
|
||||
|
||||
当笔记应用 [Boostnote][5] 背后的开发人员联系社区为他们的产品做出贡献时,该产品出现了。
|
||||
|
||||
在使用 IssueHunt 的前两年,Boostnote 通过数百名贡献者和压倒性的捐款收到了超过 8,400 个 Github star。
|
||||
|
||||
该产品非常成功,团队决定将其开放给社区的其他成员。
|
||||
|
||||
如今,[列表中在使用这个服务的项目][6]提供了数千美元的赏金。
|
||||
|
||||
Boostnote 号称有 [$2,800 的总赏金][7],而 Settings Sync,以前称为 Visual Studio Code Settings Sync,提供了[超过 $1,600 的赏金][8]。
|
||||
|
||||
还有其他服务提供类似于 IssueHunt 在此提供的内容。也许最引人注目的是 [Bountysource][9],它提供与 IssueHunt 类似的赏金服务,同时还提供类似于 [Librepay][10] 的订阅支付处理。
|
||||
|
||||
#### 你怎么看待 IssueHunt?
|
||||
|
||||
在撰写本文时,IssueHunt 还处于起步阶段,但我非常高兴看到这个项目在这些年里的成果。
|
||||
|
||||
我不知道你会怎么看,但我非常乐意为 FOSS 付款。如果产品质量高,并为我的生活增添价值,那么我很乐意向开发者支付产品费用。特别是 FOSS 的开发者正在创造尊重我自由的产品。
|
||||
|
||||
话虽如此,我一定会关注 IssueHunt 的继续前进,我可以用自己的钱或者在需要贡献的地方传播这个它来支持社区。
|
||||
|
||||
但你怎么看?你是否同意我的看法,或者你认为软件应该免费提供,并且应该在志愿者的基础上做出贡献?请在下面的评论中告诉我们你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/issuehunt/
|
||||
|
||||
作者:[Phillip Prado][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/phillip/
|
||||
[1]: https://itsfoss.com/open-source-funding-platforms/
|
||||
[2]: https://issuehunt.io
|
||||
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/09/issuehunt-website.png?w=799&ssl=1
|
||||
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/09/issuehunt.jpg?w=800&ssl=1
|
||||
[5]: https://itsfoss.com/boostnote-linux-review/
|
||||
[6]: https://issuehunt.io/repos
|
||||
[7]: https://issuehunt.io/repos/53266139
|
||||
[8]: https://issuehunt.io/repos/47984369
|
||||
[9]: https://www.bountysource.com/
|
||||
[10]: https://liberapay.com/
|
||||
@@ -1,17 +1,17 @@
|
||||
将 Grails 与 jQuery 和 DataTables 一起使用
|
||||
在 Grails 中使用 jQuery 和 DataTables
|
||||
======
|
||||
|
||||
本文介绍如何构建一个基于 Grails 的数据浏览器来可视化复杂的表格数据。
|
||||
> 本文介绍如何构建一个基于 Grails 的数据浏览器来可视化复杂的表格数据。
|
||||
|
||||

|
||||
|
||||
我是 [Grails][1] 的忠实粉丝。当然,我主要是热衷于利用命令行工具来探索和分析数据的数据人。数据人经常需要_查看_数据,这也意味着他们通常拥有优秀的数据浏览器。利用 Grails,[jQuery][2],以及 [DataTables jQuery 插件][3],我们可以制作出非常友好的表格数据浏览器。
|
||||
我是 [Grails][1] 的忠实粉丝。当然,我主要是热衷于利用命令行工具来探索和分析数据的数据从业人员。数据从业人员经常需要*查看*数据,这也意味着他们通常拥有优秀的数据浏览器。利用 Grails、[jQuery][2],以及 [DataTables jQuery 插件][3],我们可以制作出非常友好的表格数据浏览器。
|
||||
|
||||
[DataTables 网站][3]提供了许多“食谱风格”的教程文档,展示了如何组合一些优秀的示例应用程序,这些程序包含了完成一些非常漂亮的东西所必要的 JavaScript,HTML,以及偶尔出现的 [PHP][4]。但对于那些宁愿使用 Grails 作为后端的人来说,有必要进行一些说明示教。此外,样本程序中使用的数据是虚构公司的员工的单个平面表数据,因此处理这些复杂的表关系可以作为读者的一个练习项目。
|
||||
[DataTables 网站][3]提供了许多“食谱式”的教程文档,展示了如何组合一些优秀的示例应用程序,这些程序包含了完成一些非常漂亮的东西所必要的 JavaScript、HTML,以及偶尔出现的 [PHP][4]。但对于那些宁愿使用 Grails 作为后端的人来说,有必要进行一些说明示教。此外,样本程序中使用的数据是一个虚构公司的员工的单个平面表格数据,因此处理这些复杂的表关系可以作为读者的一个练习项目。
|
||||
|
||||
本文中,我们将创建具有略微复杂的数据结构和 DataTables 浏览器的 Grails 应用程序。我们将介绍 Grails 标准 [Groovy][5]-fied Java Hibernate 标准。我已将代码托管在 [GitHub][6] 上方便大家访问,因此本文主要是对代码细节的解读。
|
||||
本文中,我们将创建具有略微复杂的数据结构和 DataTables 浏览器的 Grails 应用程序。我们将介绍 Grails 标准,它是 [Groovy][5] 式的 Java Hibernate 标准。我已将代码托管在 [GitHub][6] 上方便大家访问,因此本文主要是对代码细节的解读。
|
||||
|
||||
首先,你需要配置 Java,Groovy,Grails 的使用环境。对于 Grails,我倾向于使用终端窗口和 [Vim][7],本文也使用它们。为获得现代 Java,建议下载并安装 Linux 发行版提供的 [Open Java Development Kit][8] (OpenJDK)(应该是 Java 8,9,10或11,撰写本文时,我正在使用 Java 8)。从我的角度来看,获取最新的 Groovy 和 Grails 的最佳方法是使用 [SKDMAN!][9]。
|
||||
首先,你需要配置 Java、Groovy、Grails 的使用环境。对于 Grails,我倾向于使用终端窗口和 [Vim][7],本文也使用它们。为获得现代的 Java 环境,建议下载并安装 Linux 发行版提供的 [Open Java Development Kit][8] (OpenJDK)(应该是 Java 8、9、10 或 11 之一,撰写本文时,我正在使用 Java 8)。从我的角度来看,获取最新的 Groovy 和 Grails 的最佳方法是使用 [SDKMAN!][9]。
|
||||
|
||||
从未尝试过 Grails 的读者可能需要做一些背景资料阅读。作为初学者,推荐文章 [创建你的第一个 Grails 应用程序][10]。
|
||||
|
||||
@@ -34,7 +34,7 @@ grails create-domain-class com.nuevaconsulting.embrow.Employeecd embrowgrails cr
|
||||
|
||||
这种方式构建的域类没有属性,因此必须按如下方式编辑它们:
|
||||
|
||||
Position 域类:
|
||||
`Position` 域类:
|
||||
|
||||
```
|
||||
package com.nuevaconsulting.embrow
|
||||
@@ -51,7 +51,7 @@ class Position {
|
||||
}com.Stringint startingstatic constraintsnullableblankstarting nullable
|
||||
```
|
||||
|
||||
Office 域类:
|
||||
`Office` 域类:
|
||||
|
||||
```
|
||||
package com.nuevaconsulting.embrow
|
||||
@@ -72,7 +72,7 @@ class Office {
|
||||
}
|
||||
```
|
||||
|
||||
Enployee 域类:
|
||||
`Enployee` 域类:
|
||||
|
||||
```
|
||||
package com.nuevaconsulting.embrow
|
||||
@@ -98,7 +98,7 @@ class Employee {
|
||||
}
|
||||
```
|
||||
|
||||
请注意,虽然 Position 和 Office 域类使用了预定义的 Groovy 类型 String 以及 int,但 Employee 域类定义了 Position 和 Office 字段(以及预定义的 Date)。这会导致创建数据库表,其中存储的 Employee 实例中包含了指向存储 Position 和 Office 实例表的引用或者外键。
|
||||
请注意,虽然 `Position` 和 `Office` 域类使用了预定义的 Groovy 类型 `String` 以及 `int`,但 `Employee` 域类定义了 `Position` 和 `Office` 字段(以及预定义的 `Date`)。这会导致创建数据库表,其中存储的 `Employee` 实例中包含了指向存储 `Position` 和 `Office` 实例表的引用或者外键。
|
||||
|
||||
现在你可以生成控制器,视图,以及其他各种测试组件:
|
||||
|
||||
@@ -108,7 +108,7 @@ grails generate-all com.nuevaconsulting.embrow.Office
|
||||
grails generate-all com.nuevaconsulting.embrow.Employeegrails generateall com.grails generateall com.grails generateall com.
|
||||
```
|
||||
|
||||
此时,你已经准备好基本的 create-read-update-delete(CRUD)应用程序。我在**grails-app/init/com/nuevaconsulting/BootStrap.groovy**中包含了一些基础数据来填充表格。
|
||||
此时,你已经准备好了一个基本的增删改查(CRUD)应用程序。我在 `grails-app/init/com/nuevaconsulting/BootStrap.groovy` 中包含了一些基础数据来填充表格。
|
||||
|
||||
如果你用如下命令来启动应用程序:
|
||||
|
||||
@@ -116,43 +116,44 @@ grails generate-all com.nuevaconsulting.embrow.Employeegrails generateall com.gr
|
||||
grails run-app
|
||||
```
|
||||
|
||||
在浏览器输入**<http://localhost:8080/:>**,你将会看到如下界面:
|
||||
在浏览器输入 `http://localhost:8080/`,你将会看到如下界面:
|
||||
|
||||
![Embrow home screen][12]
|
||||
|
||||
Embrow 应用程序主界面。
|
||||
*Embrow 应用程序主界面。*
|
||||
|
||||
单击 OfficeController,会跳转到如下界面:
|
||||
单击 “OfficeController” 链接,会跳转到如下界面:
|
||||
|
||||
![Office list][14]
|
||||
|
||||
Office 列表
|
||||
*Office 列表*
|
||||
|
||||
注意,此表由 **OfficeController index** 生成,并由视图 `office/index.gsp` 显示。
|
||||
注意,此表由 `OfficeController` 的 `index` 方式生成,并由视图 `office/index.gsp` 显示。
|
||||
|
||||
同样,单击 **EmployeeController** 跳转到如下界面:
|
||||
同样,单击 “EmployeeController” 链接 跳转到如下界面:
|
||||
|
||||
![Employee controller][16]
|
||||
|
||||
employee controller
|
||||
*employee 控制器*
|
||||
|
||||
好吧,这很丑陋: Position 和 Office 链接是什么?
|
||||
|
||||
上面的命令 `generate-all` 生成的视图创建了一个叫 **index.gsp** 的文件,它使用 Grails <f:table/> 标签,该标签默认会显示类名(**com.nuevaconsulting.embrow.Position**)和持久化示例标识符(**30**)。这个操作可以自定义用来产生更好看的东西,并且自动生成链接,自动生成分页以及自动生成可拍序列的一些非常简洁直观的东西。
|
||||
上面的命令 `generate-all` 生成的视图创建了一个叫 `index.gsp` 的文件,它使用 Grails `<f:table/>` 标签,该标签默认会显示类名(`com.nuevaconsulting.embrow.Position`)和持久化示例标识符(`30`)。这个操作可以自定义用来产生更好看的东西,并且自动生成链接,自动生成分页以及自动生成可排序列的一些非常简洁直观的东西。
|
||||
|
||||
但该员工信息浏览器功能也是有限的。例如,如果想查找 position 信息中包含 “dev” 的员工该怎么办?如果要组合排序,以姓氏为主排序关键字,office 为辅助排序关键字,该怎么办?或者,你需要将已排序的数据导出到电子表格或 PDF 文档以便通过电子邮件发送给无法访问浏览器的人,该怎么办?
|
||||
但该员工信息浏览器功能也是有限的。例如,如果想查找 “position” 信息中包含 “dev” 的员工该怎么办?如果要组合排序,以姓氏为主排序关键字,“office” 为辅助排序关键字,该怎么办?或者,你需要将已排序的数据导出到电子表格或 PDF 文档以便通过电子邮件发送给无法访问浏览器的人,该怎么办?
|
||||
|
||||
jQuery DataTables 插件提供了这些所需的功能。允许你创建一个完成的表格数据浏览器。
|
||||
|
||||
### 创建员工信息浏览器视图和控制器的方法
|
||||
|
||||
要基于 jQuery DataTables 创建员工信息浏览器,你必须先完成以下两个任务:
|
||||
1. 创建 Grails 视图,其中包含启用 DataTable 所需的 HTML 和 JavaScript
|
||||
|
||||
1. 创建 Grails 视图,其中包含启用 DataTable 所需的 HTML 和 JavaScript
|
||||
2. 给 Grails 控制器增加一个方法来控制新视图。
|
||||
|
||||
#### 员工信息浏览器视图
|
||||
|
||||
在目录 **embrow/grails-app/views/employee** 中,首先复制 **index.gsp** 文件,重命名为 **browser.gsp**:
|
||||
在目录 `embrow/grails-app/views/employee` 中,首先复制 `index.gsp` 文件,重命名为 `browser.gsp`:
|
||||
|
||||
```
|
||||
cd Projects
|
||||
@@ -160,7 +161,7 @@ cd embrow/grails-app/views/employee
|
||||
cp gsp browser.gsp
|
||||
```
|
||||
|
||||
此刻,你自定义新的 **browser.gsp** 文件来添加相关的 jQuery DataTables 代码。
|
||||
此刻,你自定义新的 `browser.gsp` 文件来添加相关的 jQuery DataTables 代码。
|
||||
|
||||
通常,在可能的时候,我喜欢从内容提供商处获得 JavaScript 和 CSS;在下面这行后面:
|
||||
|
||||
@@ -185,7 +186,7 @@ cp gsp browser.gsp
|
||||
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.print.min.js "></script>
|
||||
```
|
||||
|
||||
然后删除 **index.gsp** 中提供数据分页的代码:
|
||||
然后删除 `index.gsp` 中提供数据分页的代码:
|
||||
|
||||
```
|
||||
<div id="list-employee" class="content scaffold-list" role="main">
|
||||
@@ -253,7 +254,7 @@ $(this).html('<input type="text" size="15" placeholder="' + title + '?" />');
|
||||
});titletitletitletitletitle
|
||||
```
|
||||
|
||||
接下来,定义表模型。 这是提供所有表选项的地方,包括界面的滚动,而不是分页,根据 dom 字符串提供的装饰,将数据导出为 CSV 和其他格式的能力,以及建立与服务器的 Ajax 连接。 请注意,使用 Groovy GString 调用 Grails **createLink()** 的方法创建 URL,在 **EmployeeController** 中指向 **browserLister** 操作。同样有趣的是表格列的定义。此信息将发送到后端,后端查询数据库并返回相应的记录。
|
||||
接下来,定义表模型。这是提供所有表选项的地方,包括界面的滚动,而不是分页,根据 DOM 字符串提供的装饰,将数据导出为 CSV 和其他格式的能力,以及建立与服务器的 AJAX 连接。 请注意,使用 Groovy GString 调用 Grails `createLink()` 的方法创建 URL,在 `EmployeeController` 中指向 `browserLister` 操作。同样有趣的是表格列的定义。此信息将发送到后端,后端查询数据库并返回相应的记录。
|
||||
|
||||
```
|
||||
var table = $('#employee_dt').DataTable( {
|
||||
@@ -302,7 +303,7 @@ that.search(this.value).draw();
|
||||
|
||||

|
||||
|
||||
这是另一个屏幕截图,显示了过滤和多列排序(寻找 position 包括字符 “dev” 的员工,先按 office 排序,然后按姓氏排序):
|
||||
这是另一个屏幕截图,显示了过滤和多列排序(寻找 “position” 包括字符 “dev” 的员工,先按 “office” 排序,然后按姓氏排序):
|
||||
|
||||

|
||||
|
||||
@@ -314,37 +315,37 @@ that.search(this.value).draw();
|
||||
|
||||

|
||||
|
||||
好的,视图部分看起来非常简单; 因此,控制器必须做所有繁重的工作,对吧? 让我们来看看…
|
||||
好的,视图部分看起来非常简单;因此,控制器必须做所有繁重的工作,对吧? 让我们来看看……
|
||||
|
||||
#### 控制器 browserLister 操作
|
||||
|
||||
回想一下,我们看到过这个字符串
|
||||
回想一下,我们看到过这个字符串:
|
||||
|
||||
```
|
||||
"${createLink(controller: 'employee', action: 'browserLister')}"
|
||||
```
|
||||
|
||||
对于从 DataTables 模型中调用 Ajax 的 URL,是在 Grails 服务器上动态创建 HTML 链接,其 Grails 标记背后通过调用 [createLink()][17] 的方法实现的。这会最终产生一个指向 **EmployeeController** 的链接,位于:
|
||||
对于从 DataTables 模型中调用 AJAX 的 URL,是在 Grails 服务器上动态创建 HTML 链接,其 Grails 标记背后通过调用 [createLink()][17] 的方法实现的。这会最终产生一个指向 `EmployeeController` 的链接,位于:
|
||||
|
||||
```
|
||||
embrow/grails-app/controllers/com/nuevaconsulting/embrow/EmployeeController.groovy
|
||||
```
|
||||
|
||||
特别是控制器方法 **browserLister()**。我在代码中留了一些 print 语句,以便在运行时能够在终端看到中间结果。
|
||||
特别是控制器方法 `browserLister()`。我在代码中留了一些 `print` 语句,以便在运行时能够在终端看到中间结果。
|
||||
|
||||
```
|
||||
def browserLister() {
|
||||
// Applies filters and sorting to return a list of desired employees
|
||||
```
|
||||
|
||||
首先,打印出传递给 **browserLister()** 的参数。我通常使用此代码开始构建控制器方法,以便我完全清楚我的控制器正在接收什么。
|
||||
首先,打印出传递给 `browserLister()` 的参数。我通常使用此代码开始构建控制器方法,以便我完全清楚我的控制器正在接收什么。
|
||||
|
||||
```
|
||||
println "employee browserLister params $params"
|
||||
println()
|
||||
```
|
||||
|
||||
接下来,处理这些参数以使它们更加有用。首先,jQuery DataTables 参数,一个名为 **jqdtParams**的 Groovy 映射:
|
||||
接下来,处理这些参数以使它们更加有用。首先,jQuery DataTables 参数,一个名为 `jqdtParams` 的 Groovy 映射:
|
||||
|
||||
```
|
||||
def jqdtParams = [:]
|
||||
@@ -363,7 +364,7 @@ println "employee dataTableParams $jqdtParams"
|
||||
println()
|
||||
```
|
||||
|
||||
接下来,列数据,一个名为 **columnMap**的 Groovy 映射:
|
||||
接下来,列数据,一个名为 `columnMap` 的 Groovy 映射:
|
||||
|
||||
```
|
||||
def columnMap = jqdtParams.columns.collectEntries { k, v ->
|
||||
@@ -386,7 +387,7 @@ println "employee columnMap $columnMap"
|
||||
println()
|
||||
```
|
||||
|
||||
接下来,从 **columnMap** 中检索的所有列表,以及在视图中应如何排序这些列表,Groovy 列表分别称为 **allColumnList**和 **orderList**:
|
||||
接下来,从 `columnMap` 中检索的所有列表,以及在视图中应如何排序这些列表,Groovy 列表分别称为 `allColumnList` 和 `orderList` :
|
||||
|
||||
```
|
||||
def allColumnList = columnMap.keySet() as List
|
||||
@@ -395,7 +396,7 @@ def orderList = jqdtParams.order.collect { k, v -> [allColumnList[v.column as In
|
||||
println "employee orderList $orderList"
|
||||
```
|
||||
|
||||
我们将使用 Grails 的 Hibernate 标准实现来实际选择要显示的元素以及它们的排序和分页。标准要求过滤器关闭; 在大多数示例中,这是作为标准实例本身的创建的一部分给出的,但是在这里我们预先定义过滤器闭包。请注意,在这种情况下,“date hired” 过滤器的相对复杂的解释被视为一年并应用于建立日期范围,并使用 **createAlias** 以允许我们进入相关类别 Position 和 Office:
|
||||
我们将使用 Grails 的 Hibernate 标准实现来实际选择要显示的元素以及它们的排序和分页。标准要求过滤器关闭;在大多数示例中,这是作为标准实例本身的创建的一部分给出的,但是在这里我们预先定义过滤器闭包。请注意,在这种情况下,“date hired” 过滤器的相对复杂的解释被视为一年并应用于建立日期范围,并使用 `createAlias` 以允许我们进入相关类别 `Position` 和 `Office`:
|
||||
|
||||
```
|
||||
def filterer = {
|
||||
@@ -424,14 +425,14 @@ def filterer = {
|
||||
}
|
||||
```
|
||||
|
||||
是时候应用上述内容了。第一步是获取分页代码所需的所有 Employee 实例的总数:
|
||||
是时候应用上述内容了。第一步是获取分页代码所需的所有 `Employee` 实例的总数:
|
||||
|
||||
```
|
||||
def recordsTotal = Employee.count()
|
||||
println "employee recordsTotal $recordsTotal"
|
||||
```
|
||||
|
||||
接下来,将过滤器应用于 Employee 实例以获取过滤结果的计数,该结果将始终小于或等于总数(同样,这是针对分页代码):
|
||||
接下来,将过滤器应用于 `Employee` 实例以获取过滤结果的计数,该结果将始终小于或等于总数(同样,这是针对分页代码):
|
||||
|
||||
```
|
||||
def c = Employee.createCriteria()
|
||||
@@ -467,7 +468,7 @@ def filterer = {
|
||||
|
||||
要完全清楚,JTable 中的分页代码管理三个计数:数据集中的记录总数,应用过滤器后得到的数字,以及要在页面上显示的数字(显示是滚动还是分页)。 排序应用于所有过滤的记录,并且分页应用于那些过滤的记录的块以用于显示目的。
|
||||
|
||||
接下来,处理命令返回的结果,在每行中创建指向 Employee,Position 和 Office 实例的链接,以便用户可以单击这些链接以获取相关实例的所有详细信息:
|
||||
接下来,处理命令返回的结果,在每行中创建指向 `Employee`、`Position` 和 `Office` 实例的链接,以便用户可以单击这些链接以获取相关实例的所有详细信息:
|
||||
|
||||
```
|
||||
def dollarFormatter = new DecimalFormat('$##,###.##')
|
||||
@@ -490,14 +491,15 @@ def filterer = {
|
||||
}
|
||||
```
|
||||
|
||||
大功告成
|
||||
大功告成。
|
||||
|
||||
如果你熟悉 Grails,这可能看起来比你原先想象的要多,但这里没有火箭式的一步到位方法,只是很多分散的操作步骤。但是,如果你没有太多接触 Grails(或 Groovy),那么需要了解很多新东西 - 闭包,代理和构建器等等。
|
||||
|
||||
在那种情况下,从哪里开始? 最好的地方是了解 Groovy 本身,尤其是 [Groovy closures][18] 和 [Groovy delegates and builders][19]。然后再去阅读上面关于 Grails 和 Hibernate 条件查询的建议阅读文章。
|
||||
|
||||
### 结语
|
||||
|
||||
jQuery DataTables 为 Grails 制作了很棒的表格数据浏览器。对视图进行编码并不是太棘手,但DataTables 文档中提供的 PHP 示例提供的功能仅到此位置。特别是,它们不是用 Grails 程序员编写的,也不包含探索使用引用其他类(实质上是查找表)的元素的更精细的细节。
|
||||
jQuery DataTables 为 Grails 制作了很棒的表格数据浏览器。对视图进行编码并不是太棘手,但 DataTables 文档中提供的 PHP 示例提供的功能仅到此位置。特别是,它们不是用 Grails 程序员编写的,也不包含探索使用引用其他类(实质上是查找表)的元素的更精细的细节。
|
||||
|
||||
我使用这种方法制作了几个数据浏览器,允许用户选择要查看和累积记录计数的列,或者只是浏览数据。即使在相对适度的 VPS 上的百万行表中,性能也很好。
|
||||
|
||||
@@ -512,7 +514,7 @@ via: https://opensource.com/article/18/9/using-grails-jquery-and-datatables
|
||||
作者:[Chris Hermansen][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[jrg](https://github.com/jrglinux)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -528,11 +530,11 @@ via: https://opensource.com/article/18/9/using-grails-jquery-and-datatables
|
||||
[9]: http://sdkman.io/
|
||||
[10]: http://guides.grails.org/creating-your-first-grails-app/guide/index.html
|
||||
[11]: https://opensource.com/file/410061
|
||||
[12]: https://opensource.com/sites/default/files/uploads/screen_1.png "Embrow home screen"
|
||||
[12]: https://opensource.com/sites/default/files/uploads/screen_1.png
|
||||
[13]: https://opensource.com/file/410066
|
||||
[14]: https://opensource.com/sites/default/files/uploads/screen_2.png "Office list screenshot"
|
||||
[14]: https://opensource.com/sites/default/files/uploads/screen_2.png
|
||||
[15]: https://opensource.com/file/410071
|
||||
[16]: https://opensource.com/sites/default/files/uploads/screen3.png "Employee controller screenshot"
|
||||
[16]: https://opensource.com/sites/default/files/uploads/screen3.png
|
||||
[17]: https://gsp.grails.org/latest/ref/Tags/createLink.html
|
||||
[18]: http://groovy-lang.org/closures.html
|
||||
[19]: http://groovy-lang.org/dsls.html
|
||||
@@ -0,0 +1,98 @@
|
||||
容器技术对 DevOps 的一些启发
|
||||
======
|
||||
|
||||
> 容器技术的使用支撑了目前 DevOps 三大主要实践:工作流、及时反馈、持续学习。
|
||||
|
||||

|
||||
|
||||
有人说容器技术与 DevOps 二者在发展的过程中是互相促进的关系。得益于 DevOps 设计理念的流行,容器生态系统在设计上与组件选择上也有相应发展。同时,由于容器技术在生产环境中的使用,反过来也促进了 DevOps 三大主要实践:[支撑 DevOps 的三个实践][1]。
|
||||
|
||||
### 工作流
|
||||
|
||||
#### 容器中的工作流
|
||||
|
||||
每个容器都可以看成一个独立的运行环境,对于容器内部,不需要考虑外部的宿主环境、集群环境,以及其它基础设施。在容器内部,每个功能看起来都是以传统的方式运行。从外部来看,容器内运行的应用一般作为整个应用系统架构的一部分:比如 web API、web app 用户界面、数据库、任务执行、缓存系统、垃圾回收等。运维团队一般会限制容器的资源使用,并在此基础上建立完善的容器性能监控服务,从而降低其对基础设施或者下游其他用户的影响。
|
||||
|
||||
#### 现实中的工作流
|
||||
|
||||
那些跟“容器”一样业务功能独立的团队,也可以借鉴这种容器思维。因为无论是在现实生活中的工作流(代码发布、构建基础设施,甚至制造 [《杰森一家》中的斯贝斯利太空飞轮][2] 等),还是技术中的工作流(开发、测试、运维、发布)都使用了这样的线性工作流,一旦某个独立的环节或者工作团队出现了问题,那么整个下游都会受到影响,虽然使用这种线性的工作流有效降低了工作耦合性。
|
||||
|
||||
#### DevOps 中的工作流
|
||||
|
||||
DevOps 中的第一条原则,就是掌控整个执行链路的情况,努力理解系统如何协同工作,并理解其中出现的问题如何对整个过程产生影响。为了提高流程的效率,团队需要持续不断的找到系统中可能存在的性能浪费以及问题,并最终修复它们。
|
||||
|
||||
> 践行这样的工作流后,可以避免将一个已知缺陷带到工作流的下游,避免局部优化导致可能的全局性能下降,要不断探索如何优化工作流,持续加深对于系统的理解。
|
||||
|
||||
> —— Gene Kim,《[支撑 DevOps 的三个实践][3]》,IT 革命,2017.4.25
|
||||
|
||||
### 反馈
|
||||
|
||||
#### 容器中的反馈
|
||||
|
||||
除了限制容器的资源,很多产品还提供了监控和通知容器性能指标的功能,从而了解当容器工作不正常时,容器内部处于什么样的状态。比如目前[流行的][5] [Prometheus][4],可以用来收集容器和容器集群中相应的性能指标数据。容器本身特别适用于分隔应用系统,以及打包代码和其运行环境,但同时也带来了不透明的特性,这时,从中快速收集信息来解决其内部出现的问题就显得尤为重要了。
|
||||
|
||||
#### 现实中的反馈
|
||||
|
||||
在现实中,从始至终同样也需要反馈。一个高效的处理流程中,及时的反馈能够快速地定位事情发生的时间。反馈的关键词是“快速”和“相关”。当一个团队被淹没在大量不相关的事件时,那些真正需要快速反馈的重要信息很容易被忽视掉,并向下游传递形成更严重的问题。想象下[如果露西和埃塞尔][6]能够很快地意识到:传送带太快了,那么制作出的巧克力可能就没什么问题了(尽管这样就不那么搞笑了)。(LCTT 译注:露西和埃塞尔是上世纪 50 年代的著名黑白情景喜剧《我爱露西》中的主角)
|
||||
|
||||
#### DevOps 中的反馈
|
||||
|
||||
DevOps 中的第二条原则,就是快速收集所有相关的有用信息,这样在问题影响到其它开发流程之前就可以被识别出。DevOps 团队应该努力去“优化下游”,以及快速解决那些可能会影响到之后团队的问题。同工作流一样,反馈也是一个持续的过程,目标是快速的获得重要的信息以及当问题出现后能够及时地响应。
|
||||
|
||||
> 快速的反馈对于提高技术的质量、可用性、安全性至关重要。
|
||||
|
||||
> —— Gene Kim 等人,《DevOps 手册:如何在技术组织中创造世界级的敏捷性,可靠性和安全性》,IT 革命,2016
|
||||
|
||||
### 持续学习
|
||||
|
||||
#### 容器中的持续学习
|
||||
|
||||
践行第三条原则“持续学习”是一个不小的挑战。在不需要掌握太多边缘的或难以理解的东西的情况下,容器技术让我们的开发工程师和运营团队依然可以安全地进行本地和生产环境的测试,这在之前是难以做到的。即便是一些激进的实验,容器技术仍然让我们轻松地进行版本控制、记录和分享。
|
||||
|
||||
#### 现实中的持续学习
|
||||
|
||||
举个我自己的例子:多年前,作为一个年轻、初出茅庐的系统管理员(仅仅工作三周),我被安排对一个运行着某个大学核心 IT 部门网站的 Apache 虚拟主机配置进行更改。由于没有方便的测试环境,我直接在生产站点上修改配置,当时觉得配置没问题就发布了,几分钟后,我无意中听到了隔壁同事说:
|
||||
|
||||
“等会,网站挂了?”
|
||||
|
||||
“没错,怎么回事?”
|
||||
|
||||
很多人蒙圈了……
|
||||
|
||||
在被嘲讽之后(真实的嘲讽),我一头扎在工作台上,赶紧撤销我之前的更改。当天下午晚些时候,部门主管 —— 我老板的老板的老板 —— 来到我的工位询问发生了什么事。“别担心,”她告诉我。“我们不会责怪你,这是一个错误,现在你已经学会了。”
|
||||
|
||||
而在容器中,这种情形在我的笔记本上就很容易测试了,并且也很容易在部署生产环境之前,被那些经验老道的团队成员发现。
|
||||
|
||||
#### DevOps 中的持续学习
|
||||
|
||||
持续学习文化的一部分是我们每个人都希望通过一些改变从而能够提高一些东西,并勇敢地通过实验来验证我们的想法。对于 DevOps 团队来说,失败无论对团队还是个人来说都是成长而不是惩罚,所以不要畏惧失败。团队中的每个成员不断学习、共享,也会不断提升其所在团队与组织的水平。
|
||||
|
||||
随着系统越来越被细分,我们更需要将注意力集中在具体的点上:上面提到的两条原则主要关注整体流程,而持续学习关注的则是整个项目、人员、团队、组织的未来。它不仅对流程产生了影响,还对流程中的每个人产生影响。
|
||||
|
||||
> 实验和冒险让我们能够不懈地改进我们的工作,但也要求我们尝试之前未用过的工作方式。
|
||||
|
||||
> —— Gene Kim 等人,《[凤凰计划:让你了解 IT、DevOps 以及如何取得商业成功][7]》,IT 革命,2013
|
||||
|
||||
### 容器技术带给 DevOps 的启迪
|
||||
|
||||
有效地应用容器技术可以学习 DevOps 的三条原则:工作流,反馈以及持续学习。从整体上看应用程序和基础设施,而不是对容器外的东西置若罔闻,教会我们考虑到系统的所有部分,了解其上游和下游影响,打破隔阂,并作为一个团队工作,以提升整体表现和深度了解整个系统。通过努力提供及时准确的反馈,我们可以在组织内部创建有效的反馈机制,以便在问题发生影响之前发现问题。最后,提供一个安全的环境来尝试新的想法并从中学习,教会我们创造一种文化,在这种文化中,失败一方面促进了我们知识的增长,另一方面通过有根据的猜测,可以为复杂的问题带来新的、优雅的解决方案。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/9/containers-can-teach-us-devops
|
||||
|
||||
作者:[Chris Hermansen][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[littleji](https://github.com/littleji)
|
||||
校对:[pityonline](https://github.com/pityonline), [wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/clhermansen
|
||||
[1]: https://itrevolution.com/the-three-ways-principles-underpinning-devops/
|
||||
[2]: https://en.wikipedia.org/wiki/The_Jetsons
|
||||
[3]: http://itrevolution.com/the-three-ways-principles-underpinning-devops
|
||||
[4]: https://prometheus.io/
|
||||
[5]: https://opensource.com/article/18/9/prometheus-operational-advantage
|
||||
[6]: https://www.youtube.com/watch?v=8NPzLBSBzPI
|
||||
[7]: https://itrevolution.com/book/the-phoenix-project/
|
||||
@@ -0,0 +1,259 @@
|
||||
使用 Pandoc 将你的书转换成网页和电子书
|
||||
======
|
||||
|
||||
> 通过 Markdown 和 Pandoc,可以做到编写一次,发布两次。
|
||||
|
||||

|
||||
|
||||
Pandoc 是一个命令行工具,用于将文件从一种标记语言转换为另一种标记语言。在我 [对 Pandoc 的简介][1] 一文中,我演示了如何把 Markdown 编写的文本转换为网页、幻灯片和 PDF。
|
||||
|
||||
在这篇后续文章中,我将深入探讨 [Pandoc][2],展示如何从同一个 Markdown 源文件生成网页和 ePub 格式的电子书。我将使用我即将发布的电子书《[面向对象思想的 GRASP 原则][3]》为例进行讲解,这本电子书正是通过以下过程创建的。
|
||||
|
||||
首先,我将解释这本书使用的文件结构,然后介绍如何使用 Pandoc 生成网页并将其部署在 GitHub 上;最后,我演示了如何生成对应的 ePub 格式电子书。
|
||||
|
||||
你可以在我的 GitHub 仓库 [Programming Fight Club][4] 中找到相应代码。
|
||||
|
||||
### 设置图书结构
|
||||
|
||||
我用 Markdown 语法完成了所有的写作,你也可以使用 HTML 标记,但是当 Pandoc 将 Markdown 转换为 ePub 文档时,引入的 HTML 标记越多,出现问题的风险就越高。我的书按照每章一个文件的形式进行组织,用 Markdown 的 `H1` 标记(`#`)声明每章的标题。你也可以在每个文件中放置多个章节,但将它们放在单独的文件中可以更轻松地查找内容并在以后进行更新。
|
||||
|
||||
元信息遵循类似的模式,每种输出格式都有自己的元信息文件。元信息文件定义有关文档的信息,例如要添加到 HTML 中的文本或 ePub 的许可证。我将所有 Markdown 文档存储在名为 `parts` 的文件夹中(这对于用来生成网页和 ePub 的 Makefile 非常重要)。下面以一个例子进行说明,让我们看一下目录,前言和关于本书(分为 `toc.md`、`preface.md` 和 `about.md` 三个文件)这三部分,为清楚起见,我们将省略其余的章节。
|
||||
|
||||
关于本书这部分内容的开头部分类似:
|
||||
|
||||
```
|
||||
# About this book {-}
|
||||
|
||||
## Who should read this book {-}
|
||||
|
||||
Before creating a complex software system one needs to create a solid foundation.
|
||||
General Responsibility Assignment Software Principles (GRASP) are guidelines to assign
|
||||
responsibilities to software classes in object-oriented programming.
|
||||
```
|
||||
|
||||
每一章完成后,下一步就是添加元信息来设置网页和 ePub 的格式。
|
||||
|
||||
### 生成网页
|
||||
|
||||
#### 创建 HTML 元信息文件
|
||||
|
||||
我创建的网页的元信息文件(`web-metadata.yaml`)是一个简单的 YAML 文件,其中包含 `<head> ` 标签中的作者、标题、和版权等信息,以及 HTML 文件中开头和结尾的内容。
|
||||
|
||||
我建议(至少)包括 `web-metadata.yaml` 文件中的以下字段:
|
||||
|
||||
```
|
||||
---
|
||||
title: <a href="/grasp-principles/toc/">GRASP principles for the Object-oriented mind</a>
|
||||
author: Kiko Fernandez-Reyes
|
||||
rights: 2017 Kiko Fernandez-Reyes, CC-BY-NC-SA 4.0 International
|
||||
header-includes:
|
||||
- |
|
||||
```{=html}
|
||||
<link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Gentium+Basic|Inconsolata" rel="stylesheet">
|
||||
```
|
||||
include-before:
|
||||
- |
|
||||
```{=html}
|
||||
<p>If you like this book, please consider
|
||||
spreading the word or
|
||||
<a href="https://www.buymeacoffee.com/programming">
|
||||
buying me a coffee
|
||||
</a>
|
||||
</p>
|
||||
```
|
||||
include-after:
|
||||
- |
|
||||
```{=html}
|
||||
<div class="footnotes">
|
||||
<hr>
|
||||
<div class="container">
|
||||
<nav class="pagination" role="pagination">
|
||||
<ul>
|
||||
<p>
|
||||
<span class="page-number">Designed with</span> ❤️ <span class="page-number"> from Uppsala, Sweden</span>
|
||||
</p>
|
||||
<p>
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a>
|
||||
</p>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
---
|
||||
```
|
||||
|
||||
下面几个变量需要注意一下:
|
||||
|
||||
- `header-includes` 变量包含将要嵌入 `<head>` 标签的 HTML 文本。
|
||||
- 调用变量后的下一行必须是 `- |`。再往下一行必须以与 `|` 对齐的三个反引号开始,否则 Pandoc 将无法识别。`{= html}` 告诉 Pandoc 其中的内容是原始文本,不应该作为 Markdown 处理。(为此,需要检查 Pandoc 中的 `raw_attribute` 扩展是否已启用。要进行此检查,键入 `pandoc --list-extensions | grep raw` 并确保返回的列表包含名为 `+ raw_html` 的项目,加号表示已启用。)
|
||||
- 变量 `include-before` 在网页开头添加一些 HTML 文本,此处我请求读者帮忙宣传我的书或给我打赏。
|
||||
- `include-after` 变量在网页末尾添加原始 HTML 文本,同时显示我的图书许可证。
|
||||
|
||||
这些只是其中一部分可用的变量,查看 HTML 中的模板变量(我的文章 [Pandoc简介][1] 中介绍了如何查看 LaTeX 的模版变量,查看 HTML 模版变量的过程是相同的)对其余变量进行了解。
|
||||
|
||||
#### 将网页分成多章
|
||||
|
||||
网页可以作为一个整体生成,这会产生一个包含所有内容的长页面;也可以分成多章,我认为这样会更容易阅读。我将解释如何将网页划分为多章,以便读者不会被长网页吓到。
|
||||
|
||||
为了使网页易于在 GitHub Pages 上部署,需要创建一个名为 `docs` 的根文件夹(这是 GitHub Pages 默认用于渲染网页的根文件夹)。然后我们需要为 `docs` 下的每一章创建文件夹,将 HTML 内容放在各自的文件夹中,将文件内容放在名为 `index.html` 的文件中。
|
||||
|
||||
例如,`about.md` 文件将转换成名为 `index.html` 的文件,该文件位于名为 `about`(`about/index.html`)的文件夹中。这样,当用户键入 `http://<your-website.com>/about/` 时,文件夹中的 `index.html` 文件将显示在其浏览器中。
|
||||
|
||||
下面的 `Makefile` 将执行上述所有操作:
|
||||
|
||||
```
|
||||
# Your book files
|
||||
DEPENDENCIES= toc preface about
|
||||
|
||||
# Placement of your HTML files
|
||||
DOCS=docs
|
||||
|
||||
all: web
|
||||
|
||||
web: setup $(DEPENDENCIES)
|
||||
@cp $(DOCS)/toc/index.html $(DOCS)
|
||||
|
||||
|
||||
# Creation and copy of stylesheet and images into
|
||||
# the assets folder. This is important to deploy the
|
||||
# website to Github Pages.
|
||||
setup:
|
||||
@mkdir -p $(DOCS)
|
||||
@cp -r assets $(DOCS)
|
||||
|
||||
|
||||
# Creation of folder and index.html file on a
|
||||
# per-chapter basis
|
||||
|
||||
$(DEPENDENCIES):
|
||||
@mkdir -p $(DOCS)/$@
|
||||
@pandoc -s --toc web-metadata.yaml parts/$@.md \
|
||||
-c /assets/pandoc.css -o $(DOCS)/$@/index.html
|
||||
|
||||
clean:
|
||||
@rm -rf $(DOCS)
|
||||
|
||||
.PHONY: all clean web setup
|
||||
```
|
||||
|
||||
选项 `- c /assets/pandoc.css` 声明要使用的 CSS 样式表,它将从 `/assets/pandoc.cs` 中获取。也就是说,在 `<head>` 标签内,Pandoc 会添加这样一行:
|
||||
|
||||
```
|
||||
<link rel="stylesheet" href="/assets/pandoc.css">
|
||||
```
|
||||
|
||||
使用下面的命令生成网页:
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
根文件夹现在应该包含如下所示的文件结构:
|
||||
|
||||
```
|
||||
.---parts
|
||||
| |--- toc.md
|
||||
| |--- preface.md
|
||||
| |--- about.md
|
||||
|
|
||||
|---docs
|
||||
|--- assets/
|
||||
|--- index.html
|
||||
|--- toc
|
||||
| |--- index.html
|
||||
|
|
||||
|--- preface
|
||||
| |--- index.html
|
||||
|
|
||||
|--- about
|
||||
|--- index.html
|
||||
|
||||
```
|
||||
|
||||
#### 部署网页
|
||||
|
||||
通过以下步骤将网页部署到 GitHub 上:
|
||||
|
||||
1. 创建一个新的 GitHub 仓库
|
||||
2. 将内容推送到新创建的仓库
|
||||
3. 找到仓库设置中的 GitHub Pages 部分,选择 `Source` 选项让 GitHub 使用主分支的内容
|
||||
|
||||
你可以在 [GitHub Pages][5] 的网站上获得更多详细信息。
|
||||
|
||||
[我的书的网页][6] 便是通过上述过程生成的,可以在网页上查看结果。
|
||||
|
||||
### 生成电子书
|
||||
|
||||
#### 创建 ePub 格式的元信息文件
|
||||
|
||||
ePub 格式的元信息文件 `epub-meta.yaml` 和 HTML 元信息文件是类似的。主要区别在于 ePub 提供了其他模板变量,例如 `publisher` 和 `cover-image` 。ePub 格式图书的样式表可能与网页所用的不同,在这里我使用一个名为 `epub.css` 的样式表。
|
||||
|
||||
```
|
||||
---
|
||||
title: 'GRASP principles for the Object-oriented Mind'
|
||||
publisher: 'Programming Language Fight Club'
|
||||
author: Kiko Fernandez-Reyes
|
||||
rights: 2017 Kiko Fernandez-Reyes, CC-BY-NC-SA 4.0 International
|
||||
cover-image: assets/cover.png
|
||||
stylesheet: assets/epub.css
|
||||
...
|
||||
```
|
||||
|
||||
将以下内容添加到之前的 `Makefile` 中:
|
||||
|
||||
```
|
||||
epub:
|
||||
@pandoc -s --toc epub-meta.yaml \
|
||||
$(addprefix parts/, $(DEPENDENCIES:=.md)) -o $(DOCS)/assets/book.epub
|
||||
```
|
||||
|
||||
用于产生 ePub 格式图书的命令从 HTML 版本获取所有依赖项(每章的名称),向它们添加 Markdown 扩展,并在它们前面加上每一章的文件夹路径,以便让 Pandoc 知道如何进行处理。例如,如果 `$(DEPENDENCIES` 变量只包含 “前言” 和 “关于本书” 两章,那么 `Makefile` 将会这样调用:
|
||||
|
||||
```
|
||||
@pandoc -s --toc epub-meta.yaml \
|
||||
parts/preface.md parts/about.md -o $(DOCS)/assets/book.epub
|
||||
```
|
||||
|
||||
Pandoc 将提取这两章的内容,然后进行组合,最后生成 ePub 格式的电子书,并放在 `Assets` 文件夹中。
|
||||
|
||||
这是使用此过程创建 ePub 格式电子书的一个 [示例][7]。
|
||||
|
||||
### 过程总结
|
||||
|
||||
从 Markdown 文件创建网页和 ePub 格式电子书的过程并不困难,但有很多细节需要注意。遵循以下大纲可能使你更容易使用 Pandoc。
|
||||
|
||||
- HTML 图书:
|
||||
- 使用 Markdown 语法创建每章内容
|
||||
- 添加元信息
|
||||
- 创建一个 `Makefile` 将各个部分组合在一起
|
||||
- 设置 GitHub Pages
|
||||
- 部署
|
||||
- ePub 电子书:
|
||||
- 使用之前创建的每一章内容
|
||||
- 添加新的元信息文件
|
||||
- 创建一个 `Makefile` 以将各个部分组合在一起
|
||||
- 设置 GitHub Pages
|
||||
- 部署
|
||||
|
||||
|
||||
------
|
||||
|
||||
via: https://opensource.com/article/18/10/book-to-website-epub-using-pandoc
|
||||
|
||||
作者:[Kiko Fernandez-Reyes][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[jlztan](https://github.com/jlztan)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/kikofernandez
|
||||
[1]: https://linux.cn/article-10228-1.html
|
||||
[2]: https://pandoc.org/
|
||||
[3]: https://www.programmingfightclub.com/
|
||||
[4]: https://github.com/kikofernandez/programmingfightclub
|
||||
[5]: https://pages.github.com/
|
||||
[6]: https://www.programmingfightclub.com/grasp-principles/
|
||||
[7]: https://github.com/kikofernandez/programmingfightclub/raw/master/docs/web_assets/demo.epub
|
||||
@@ -1,22 +1,23 @@
|
||||
适用于小型企业的 4 个开源发票工具
|
||||
======
|
||||
用基于 web 的发票软件管理你的账单,完成收款,十分简单。
|
||||
|
||||
> 用基于 web 的发票软件管理你的账单,轻松完成收款,十分简单。
|
||||
|
||||

|
||||
|
||||
无论您开办小型企业的原因是什么,保持业务发展的关键是可以盈利。收款也就意味着向客户提供发票。
|
||||
|
||||
使用 LibreOffice Writer 或 LibreOffice Calc 提供发票很容易,但有时候你需要的不止这些。从更专业的角度看。一种跟进发票的方法。提醒你何时跟进你发出的发票。
|
||||
使用 LibreOffice Writer 或 LibreOffice Calc 提供发票很容易,但有时候你需要的不止这些。从更专业的角度看,一种跟进发票的方法,可以提醒你何时跟进你发出的发票。
|
||||
|
||||
在这里有各种各样的商业闭源发票管理工具。但是开源界的产品和相对应的闭源商业工具比起来,并不差,没准还更灵活。
|
||||
在这里有各种各样的商业闭源的发票管理工具。但是开源的产品和相对应的闭源商业工具比起来,并不差,没准还更灵活。
|
||||
|
||||
让我们一起了解这 4 款基于 web 的开源发票工具,它们很适用于预算紧张的自由职业者和小型企业。2014 年,我在本文的[早期版本][1]中提到了其中两个工具。这 4 个工具用起来都很简单,并且你可以在任何设备上使用它们。
|
||||
|
||||
### Invoice Ninja
|
||||
|
||||
我不是很喜欢 ninja 这个词。尽管如此,我喜欢 [Invoice Ninja][2]。非常喜欢。它将功能融合在一个简单的界面,其中包含一组功能,可让创建,管理和向客户、消费者发送发票。
|
||||
我不是很喜欢 ninja (忍者)这个词。尽管如此,我喜欢 [Invoice Ninja][2]。非常喜欢。它将功能融合在一个简单的界面,其中包含一组可让你创建、管理和向客户、消费者发送发票的功能。
|
||||
|
||||
您可以轻松配置多个客户端,跟进付款和未结清的发票,生成报价并用电子邮件发送发票。Invoice Ninja 与其竞争对手不同,它[集成][3]了超过 40 个流行支付方式,包括 PayPal,Stripe,WePay 以及 Apple Pay。
|
||||
您可以轻松配置多个客户端,跟进付款和未结清的发票,生成报价并用电子邮件发送发票。Invoice Ninja 与其竞争对手不同,它[集成][3]了超过 40 个流行支付方式,包括 PayPal、Stripe、WePay 以及 Apple Pay。
|
||||
|
||||
[下载][4]一个可以安装到自己服务器上的版本,或者获取一个[托管版][5]的账户,都可以使用 Invoice Ninja。它有免费版,也有每月 8 美元的收费版。
|
||||
|
||||
@@ -34,7 +35,7 @@ InvoicePlane 不仅可以生成或跟进发票。你还可以为任务或商品
|
||||
|
||||
[OpenSourceBilling][9] 被它的开发者称赞为“非常简单的计费软件”,当之无愧。它拥有最简洁的交互界面,配置使用起来轻而易举。
|
||||
|
||||
OpenSourceBilling 因它的商业智能仪表盘脱颖而出,它可以跟进跟进你当前和以前的发票,以及任何没有支付的款项。它以图表的形式整理信息,使之很容易阅读。
|
||||
OpenSourceBilling 因它的商业智能仪表盘脱颖而出,它可以跟进你当前和以前的发票,以及任何没有支付的款项。它以图表的形式整理信息,使之很容易阅读。
|
||||
|
||||
你可以在发票上配置很多信息。只需点几下鼠标按几下键盘,即可添加项目、税率、客户名称以及付款条件。OpenSourceBilling 将这些信息保存在你所有的发票当中,不管新发票还是旧发票。
|
||||
|
||||
@@ -57,7 +58,7 @@ via: https://opensource.com/article/18/10/open-source-invoicing-tools
|
||||
作者:[Scott Nesbitt][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[fuowang](https://github.com/fuowang)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
Greg Kroah-Hartman 解释内核社区是如何使 Linux 安全的
|
||||
============
|
||||
|
||||

|
||||
|
||||
> 内核维护者 Greg Kroah-Hartman 谈论内核社区如何保护 Linux 不遭受损害。
|
||||
|
||||
由于 Linux 使用量持续扩大,内核社区去提高这个世界上使用最广泛的技术 —— Linux 内核的安全性的重要性越来越高。安全不仅对企业客户很重要,它对消费者也很重要,因为 80% 的移动设备都使用了 Linux。在本文中,Linux 内核维护者 Greg Kroah-Hartman 带我们了解内核社区如何应对威胁。
|
||||
|
||||
### bug 不可避免
|
||||
|
||||

|
||||
|
||||
*Greg Kroah-Hartman [Linux 基金会][1]*
|
||||
|
||||
正如 Linus Torvalds 曾经说过的,大多数安全问题都是 bug 造成的,而 bug 又是软件开发过程的一部分。是软件就有 bug。
|
||||
|
||||
Kroah-Hartman 说:“就算是 bug,我们也不知道它是安全的 bug 还是不安全的 bug。我修复的一个著名 bug,在三年后才被 Red Hat 认定为安全漏洞“。
|
||||
|
||||
在消除 bug 方面,内核社区没有太多的办法,只能做更多的测试来寻找 bug。内核社区现在已经有了自己的安全团队,它们是由熟悉内核核心的内核开发者组成。
|
||||
|
||||
Kroah-Hartman 说:”当我们收到一个报告时,我们就让参与这个领域的核心开发者去修复它。在一些情况下,他们可能是同一个人,让他们进入安全团队可以更快地解决问题“。但他也强调,内核所有部分的开发者都必须清楚地了解这些问题,因为内核是一个可信环境,它必须被保护起来。
|
||||
|
||||
Kroah-Hartman 说:”一旦我们修复了它,我们就将它放到我们的栈分析规则中,以便于以后不再重新出现这个 bug。“
|
||||
|
||||
除修复 bug 之外,内核社区也不断加固内核。Kroah-Hartman 说:“我们意识到,我们需要一些主动的缓减措施,因此我们需要加固内核。”
|
||||
|
||||
Kees Cook 和其他一些人付出了巨大的努力,带来了一直在内核之外的加固特性,并将它们合并或适配到内核中。在每个内核发行后,Cook 都对所有新的加固特性做一个总结。但是只加固内核是不够的,供应商们必须要启用这些新特性来让它们充分发挥作用,但他们并没有这么做。
|
||||
|
||||
Kroah-Hartman [每周发布一个稳定版内核][5],而为了长期的支持,公司们只从中挑选一个,以便于设备制造商能够利用它。但是,Kroah-Hartman 注意到,除了 Google Pixel 之外,大多数 Android 手机并不包含这些额外的安全加固特性,这就意味着,所有的这些手机都是有漏洞的。他说:“人们应该去启用这些加固特性”。
|
||||
|
||||
Kroah-Hartman 说:“我购买了基于 Linux 内核 4.4 的所有旗舰级手机,去查看它们中哪些确实升级了新特性。结果我发现只有一家公司升级了它们的内核。……我在整个供应链中努力去解决这个问题,因为这是一个很棘手的问题。它涉及许多不同的组织 —— SoC 制造商、运营商等等。关键点是,需要他们把我们辛辛苦苦设计的内核去推送给大家。”
|
||||
|
||||
好消息是,与消费电子产品不一样,像 Red Hat 和 SUSE 这样的大供应商,在企业环境中持续对内核进行更新。使用容器、pod 和虚拟化的现代系统做到这一点更容易了。无需停机就可以毫不费力地更新和重启。事实上,现在来保证系统安全相比过去容易多了。
|
||||
|
||||
### Meltdown 和 Spectre
|
||||
|
||||
没有任何一个关于安全的讨论能够避免提及 Meltdown 和 Spectre 缺陷。内核社区一直致力于修改新发现的和已查明的安全漏洞。不管怎样,Intel 已经因为这些事情改变了它们的策略。
|
||||
|
||||
Kroah-Hartman 说:“他们已经重新研究如何处理安全 bug,以及如何与社区合作,因为他们知道他们做错了。内核已经修复了几乎所有大的 Spectre 问题,但是还有一些小问题仍在处理中”。
|
||||
|
||||
好消息是,这些 Intel 漏洞使得内核社区正在变得更好。Kroah-Hartman 说:“我们需要做更多的测试。对于最新一轮的安全补丁,在它们被发布之前,我们自己花了四个月时间来测试它们,因为我们要防止这个安全问题在全世界扩散。而一旦这些漏洞在真实的世界中被利用,将让我们认识到我们所依赖的基础设施是多么的脆弱,我们多年来一直在做这种测试,这确保了其它人不会遭到这些 bug 的伤害。所以说,Intel 的这些漏洞在某种程度上让内核社区变得更好了”。
|
||||
|
||||
对安全的日渐关注也为那些有才华的人创造了更多的工作机会。由于安全是个极具吸引力的领域,那些希望在内核空间中有所建树的人,安全将是他们一个很好的起点。
|
||||
|
||||
Kroah-Hartman 说:“如果有人想从事这方面的工作,我们有大量的公司愿意雇佣他们。我知道一些开始去修复 bug 的人已经被他们雇佣了。”
|
||||
|
||||
你可以在下面链接的视频上查看更多的内容:
|
||||
|
||||
[视频](https://youtu.be/jkGVabyMh1I)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/2018/10/greg-kroah-hartman-explains-how-kernel-community-securing-linux-0
|
||||
|
||||
作者:[SWAPNIL BHARTIYA][a]
|
||||
选题:[oska874][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linux.com/users/arnieswap
|
||||
[b]:https://github.com/oska874
|
||||
[1]:https://www.linux.com/licenses/category/linux-foundation
|
||||
[2]:https://www.linux.com/licenses/category/creative-commons-zero
|
||||
[3]:https://www.linux.com/files/images/greg-k-hpng
|
||||
[4]:https://www.linux.com/files/images/kernel-securityjpg-0
|
||||
[5]:https://www.kernel.org/category/releases.html
|
||||
@@ -0,0 +1,191 @@
|
||||
Python 函数式编程:不可变数据结构
|
||||
======
|
||||
|
||||
> 不可变性可以帮助我们更好地理解我们的代码。下面我将讲述如何在不牺牲性能的条件下来实现它。
|
||||
|
||||

|
||||
|
||||
在这个由两篇文章构成的系列中,我将讨论如何将函数式编程方法论中的思想引入至 Python 中,来充分发挥这两个领域的优势。
|
||||
|
||||
本文(也就是第一篇文章)中,我们将探讨不可变数据结构的优势。第二部分会探讨如何在 `toolz` 库的帮助下,用 Python 实现高层次的函数式编程理念。
|
||||
|
||||
为什么要用函数式编程?因为变化的东西更难推理。如果你已经确信变化会带来麻烦,那很棒。如果你还没有被说服,在文章结束时,你会明白这一点的。
|
||||
|
||||
我们从思考正方形和矩形开始。如果我们抛开实现细节,单从接口的角度考虑,正方形是矩形的子类吗?
|
||||
|
||||
子类的定义基于[里氏替换原则][1]。一个子类必须能够完成超类所做的一切。
|
||||
|
||||
如何为矩形定义接口?
|
||||
|
||||
```
|
||||
from zope.interface import Interface
|
||||
|
||||
class IRectangle(Interface):
|
||||
def get_length(self):
|
||||
"""正方形能做到"""
|
||||
def get_width(self):
|
||||
"""正方形能做到"""
|
||||
def set_dimensions(self, length, width):
|
||||
"""啊哦"""
|
||||
```
|
||||
|
||||
如果我们这么定义,那正方形就不能成为矩形的子类:如果长度和宽度不等,它就无法对 `set_dimensions` 方法做出响应。
|
||||
|
||||
另一种方法,是选择将矩形做成不可变对象。
|
||||
|
||||
```
|
||||
class IRectangle(Interface):
|
||||
def get_length(self):
|
||||
"""正方形能做到"""
|
||||
def get_width(self):
|
||||
"""正方形能做到"""
|
||||
def with_dimensions(self, length, width):
|
||||
"""返回一个新矩形"""
|
||||
```
|
||||
|
||||
现在,我们可以将正方形视为矩形了。在调用 `with_dimensions` 时,它可以返回一个新的矩形(它不一定是个正方形),但它本身并没有变,依然是一个正方形。
|
||||
|
||||
这似乎像是个学术问题 —— 直到我们认为正方形和矩形可以在某种意义上看做一个容器的侧面。在理解了这个例子以后,我们会处理更传统的容器,以解决更现实的案例。比如,考虑一下随机存取数组。
|
||||
|
||||
我们现在有 `ISquare` 和 `IRectangle`,而且 `ISequere` 是 `IRectangle` 的子类。
|
||||
|
||||
我们希望把矩形放进随机存取数组中:
|
||||
|
||||
```
|
||||
class IArrayOfRectangles(Interface):
|
||||
def get_element(self, i):
|
||||
"""返回一个矩形"""
|
||||
def set_element(self, i, rectangle):
|
||||
"""'rectangle' 可以是任意 IRectangle 对象"""
|
||||
```
|
||||
|
||||
我们同样希望把正方形放进随机存取数组:
|
||||
|
||||
```
|
||||
class IArrayOfSquare(Interface):
|
||||
def get_element(self, i):
|
||||
"""返回一个正方形"""
|
||||
def set_element(self, i, square):
|
||||
"""'square' 可以是任意 ISquare 对象"""
|
||||
```
|
||||
|
||||
尽管 `ISquare` 是 `IRectangle` 的子集,但没有任何一个数组可以同时实现 `IArrayOfSquare` 和 `IArrayOfRectangle`.
|
||||
|
||||
为什么不能呢?假设 `bucket` 实现了这两个类的功能。
|
||||
|
||||
```
|
||||
>>> rectangle = make_rectangle(3, 4)
|
||||
>>> bucket.set_element(0, rectangle) # 这是 IArrayOfRectangle 中的合法操作
|
||||
>>> thing = bucket.get_element(0) # IArrayOfSquare 要求 thing 必须是一个正方形
|
||||
>>> assert thing.height == thing.width
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
AssertionError
|
||||
```
|
||||
|
||||
无法同时实现这两类功能,意味着这两个类无法构成继承关系,即使 `ISquare` 是 `IRectangle` 的子类。问题来自 `set_element` 方法:如果我们实现一个只读的数组,那 `IArrayOfSquare` 就可以是 `IArrayOfRectangle` 的子类了。
|
||||
|
||||
在可变的 `IRectangle` 和可变的 `IArrayOf*` 接口中,可变性都会使得对类型和子类的思考变得更加困难 —— 放弃变换的能力,意味着我们的直觉所希望的类型间关系能够成立了。
|
||||
|
||||
可变性还会带来作用域方面的影响。当一个共享对象被两个地方的代码改变时,这种问题就会发生。一个经典的例子是两个线程同时改变一个共享变量。不过在单线程程序中,即使在两个相距很远的地方共享一个变量,也是一件简单的事情。从 Python 语言的角度来思考,大多数对象都可以从很多位置来访问:比如在模块全局变量,或在一个堆栈跟踪中,或者以类属性来访问。
|
||||
|
||||
如果我们无法对共享做出约束,那我们可能要考虑对可变性来进行约束了。
|
||||
|
||||
这是一个不可变的矩形,它利用了 [attr][2] 库:
|
||||
|
||||
```
|
||||
@attr.s(frozen=True)
|
||||
class Rectange(object):
|
||||
length = attr.ib()
|
||||
width = attr.ib()
|
||||
@classmethod
|
||||
def with_dimensions(cls, length, width):
|
||||
return cls(length, width)
|
||||
```
|
||||
|
||||
这是一个正方形:
|
||||
|
||||
```
|
||||
@attr.s(frozen=True)
|
||||
class Square(object):
|
||||
side = attr.ib()
|
||||
@classmethod
|
||||
def with_dimensions(cls, length, width):
|
||||
return Rectangle(length, width)
|
||||
```
|
||||
|
||||
使用 `frozen` 参数,我们可以轻易地使 `attrs` 创建的类成为不可变类型。正确实现 `__setitem__` 方法的工作都交给别人完成了,对我们是不可见的。
|
||||
|
||||
修改对象仍然很容易;但是我们不可能改变它的本质。
|
||||
|
||||
```
|
||||
too_long = Rectangle(100, 4)
|
||||
reasonable = attr.evolve(too_long, length=10)
|
||||
```
|
||||
|
||||
[Pyrsistent][3] 能让我们拥有不可变的容器。
|
||||
|
||||
```
|
||||
# 由整数构成的向量
|
||||
a = pyrsistent.v(1, 2, 3)
|
||||
# 并非由整数构成的向量
|
||||
b = a.set(1, "hello")
|
||||
```
|
||||
|
||||
尽管 `b` 不是一个由整数构成的向量,但没有什么能够改变 `a` 只由整数构成的性质。
|
||||
|
||||
如果 `a` 有一百万个元素呢?`b` 会将其中的 999999 个元素复制一遍吗?`Pyrsistent` 具有“大 O”性能保证:所有操作的时间复杂度都是 `O(log n)`. 它还带有一个可选的 C 语言扩展,以在“大 O”性能之上进行提升。
|
||||
|
||||
修改嵌套对象时,会涉及到“变换器”的概念:
|
||||
|
||||
```
|
||||
blog = pyrsistent.m(
|
||||
title="My blog",
|
||||
links=pyrsistent.v("github", "twitter"),
|
||||
posts=pyrsistent.v(
|
||||
pyrsistent.m(title="no updates",
|
||||
content="I'm busy"),
|
||||
pyrsistent.m(title="still no updates",
|
||||
content="still busy")))
|
||||
new_blog = blog.transform(["posts", 1, "content"],
|
||||
"pretty busy")
|
||||
```
|
||||
|
||||
`new_blog` 现在将是如下对象的不可变等价物:
|
||||
|
||||
```
|
||||
{'links': ['github', 'twitter'],
|
||||
'posts': [{'content': "I'm busy",
|
||||
'title': 'no updates'},
|
||||
{'content': 'pretty busy',
|
||||
'title': 'still no updates'}],
|
||||
'title': 'My blog'}
|
||||
```
|
||||
|
||||
不过 `blog` 依然不变。这意味着任何拥有旧对象引用的人都没有受到影响:转换只会有局部效果。
|
||||
|
||||
当共享行为猖獗时,这会很有用。例如,函数的默认参数:
|
||||
|
||||
```
|
||||
def silly_sum(a, b, extra=v(1, 2)):
|
||||
extra = extra.extend([a, b])
|
||||
return sum(extra)
|
||||
```
|
||||
|
||||
在本文中,我们了解了为什么不可变性有助于我们来思考我们的代码,以及如何在不带来过大性能负担的条件下实现它。下一篇,我们将学习如何借助不可变对象来实现强大的程序结构。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/10/functional-programming-python-immutable-data-structures
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[StdioA](https://github.com/StdioA)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[1]: https://en.wikipedia.org/wiki/Liskov_substitution_principle
|
||||
[2]: https://www.attrs.org/en/stable/
|
||||
[3]: https://pyrsistent.readthedocs.io/en/latest/
|
||||
@@ -0,0 +1,159 @@
|
||||
Terminalizer:一个记录您终端活动并且生成 Gif 图像的工具
|
||||
====
|
||||
|
||||
今天我们要讨论一个广为人知的主题,我们也围绕这个主题写过许多的文章,因此我不会针对这个如何记录终端会话流程给出太多具体的资料。
|
||||
|
||||
我们可以使用脚本命令来记录 Linux 的终端会话,这也是大家公认的一种办法。不过今天我们将来介绍一个能起到相同作用的工具 —— Terminalizer。
|
||||
|
||||
这个工具可以帮助我们记录用户的终端活动,以帮助我们从输出的文件中找到有用的信息。
|
||||
|
||||
### 什么是 Terminlizer
|
||||
|
||||
用户可以用 Terminlizer 记录他们的终端活动并且生成一个 Gif 图像。它是一个允许高度定制的 CLI 工具。用户可以在网络播放器、在线播放器上用链接分享他们记录下的文件。
|
||||
|
||||
**推荐阅读:**
|
||||
|
||||
- [Script – 一个记录您终端对话的简单工具][1]
|
||||
- [在 Linux 上自动记录/捕捉所有用户的终端对话][2]
|
||||
- [Teleconsole – 一个能立即与任何人分享您终端对话的工具][3]
|
||||
- [tmate – 立即与任何人分享您的终端对话][4]
|
||||
- [Peek – 在 Linux 里制造一个 Gif 记录器][5]
|
||||
- [Kgif – 一个能生成 Gif 图片,以记录窗口活动的简单 Shell 脚本][6]
|
||||
- [Gifine – 在 Ubuntu/Debian 里快速制造一个 Gif 视频][7]
|
||||
|
||||
目前没有发行版拥有官方软件包来安装此实用程序,不过我们可以用 Node.js 来安装它。
|
||||
|
||||
### 如何在 Linux 上安装 Node.js
|
||||
|
||||
安装 Node.js 有许多种方法。我们在这里将会教您一个常用的方法。
|
||||
|
||||
在 Ubuntu/LinuxMint 上可以使用 [APT-GET 命令][8] 或者 [APT 命令][9] 来安装 Node.js。
|
||||
|
||||
```
|
||||
$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
$ sudo apt-get install -y nodejs
|
||||
```
|
||||
|
||||
在 Debian 上使用 [APT-GET 命令][8] 或者 [APT 命令][9] 来安装 Node.js。
|
||||
|
||||
```
|
||||
# curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||
# apt-get install -y nodejs
|
||||
```
|
||||
|
||||
在 RHEL/CentOS 上,使用 [YUM 命令][10] 来安装。
|
||||
|
||||
```
|
||||
$ sudo curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
|
||||
$ sudo yum install epel-release
|
||||
$ sudo yum -y install nodejs
|
||||
```
|
||||
|
||||
在 Fedora 上,用 [DNF 命令][11] 来安装 tmux。
|
||||
|
||||
```
|
||||
$ sudo dnf install nodejs
|
||||
```
|
||||
|
||||
在 Arch Linux 上,用 [Pacman 命令][12] 来安装 tmux。
|
||||
|
||||
```
|
||||
$ sudo pacman -S nodejs npm
|
||||
```
|
||||
|
||||
在 openSUSE 上,用 [Zypper Command][13] 来安装 tmux。
|
||||
|
||||
```
|
||||
$ sudo zypper in nodejs6
|
||||
```
|
||||
|
||||
### 如何安装 Terminalizer
|
||||
|
||||
您已经安装了 Node.js 这个先决软件包,现在是时候在您的系统上安装 Terminalizer 了。简单执行如下的 `npm` 命令即可安装。
|
||||
|
||||
```
|
||||
$ sudo npm install -g terminalizer
|
||||
```
|
||||
|
||||
### 如何使用 Terminalizer
|
||||
|
||||
您只需要执行如下的命令,即可使用 Terminalizer 记录您的终端会话活动。您可以敲击 `CTRL+D` 来结束并且保存记录。
|
||||
|
||||
```
|
||||
# terminalizer record 2g-session
|
||||
|
||||
defaultConfigPath
|
||||
The recording session is started
|
||||
Press CTRL+D to exit and save the recording
|
||||
```
|
||||
|
||||
这将会将您记录的会话保存成一个 YAML 文件,在这个例子里,我的文件名将会是 2g-session-activity.yml。
|
||||
|
||||
![][15]
|
||||
|
||||
```
|
||||
# logout
|
||||
Successfully Recorded
|
||||
The recording data is saved into the file:
|
||||
/home/daygeek/2g-session.yml
|
||||
You can edit the file and even change the configurations.
|
||||
```
|
||||
|
||||
![][16]
|
||||
|
||||
### 如何播放记录下来的文件
|
||||
|
||||
使用以下命令来播放您记录的 YAML 文件。在以下操作中,请确保您已经用了您的文件名来替换 “2g-session”。
|
||||
|
||||
```
|
||||
# terminalizer play 2g-session
|
||||
```
|
||||
|
||||
将记录的文件渲染成 Gif 图像。
|
||||
|
||||
```
|
||||
# terminalizer render 2g-session
|
||||
```
|
||||
|
||||
注意: 以下的两个命令在此版本尚且不可用,或许在下一版本这两个命令将会付诸使用。
|
||||
|
||||
如果您想要将记录的文件分享给其他人,您可以将您的文件上传到在线播放器,并且将链接分享给对方。
|
||||
|
||||
```
|
||||
terminalizer share 2g-session
|
||||
```
|
||||
|
||||
为记录的文件生成一个网络播放器。
|
||||
|
||||
```
|
||||
# terminalizer generate 2g-session
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/terminalizer-a-tool-to-record-your-terminal-and-generate-animated-gif-images/
|
||||
|
||||
作者:[Prakash Subramanian][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[thecyanbird](https://github.com/thecyanbird)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/prakash/
|
||||
[1]: https://www.2daygeek.com/script-command-record-save-your-terminal-session-activity-linux/
|
||||
[2]: https://www.2daygeek.com/automatically-record-all-users-terminal-sessions-activity-linux-script-command/
|
||||
[3]: https://www.2daygeek.com/teleconsole-share-terminal-session-instantly-to-anyone-in-seconds/
|
||||
[4]: https://www.2daygeek.com/tmate-instantly-share-your-terminal-session-to-anyone-in-seconds/
|
||||
[5]: https://www.2daygeek.com/peek-create-animated-gif-screen-recorder-capture-arch-linux-mint-fedora-ubuntu/
|
||||
[6]: https://www.2daygeek.com/kgif-create-animated-gif-file-active-window-screen-recorder-capture-arch-linux-mint-fedora-ubuntu-debian-opensuse-centos/
|
||||
[7]: https://www.2daygeek.com/gifine-create-animated-gif-vedio-recorder-linux-mint-debian-ubuntu/
|
||||
[8]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[9]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[10]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
|
||||
[11]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
|
||||
[12]: https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
|
||||
[13]: https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
|
||||
[14]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[15]: https://www.2daygeek.com/wp-content/uploads/2018/10/terminalizer-record-2g-session-1.gif
|
||||
[16]: https://www.2daygeek.com/wp-content/uploads/2018/10/terminalizer-play-2g-session.gif
|
||||
@@ -0,0 +1,118 @@
|
||||
服务器的 LinuxBoot:告别 UEFI、拥抱开源
|
||||
============
|
||||
|
||||
[LinuxBoot][13] 是私有的 [UEFI][15] 固件的开源 [替代品][14]。它发布于去年,并且现在已经得到主流的硬件生产商的认可成为他们产品的默认固件。去年,LinuxBoot 已经被 Linux 基金会接受并[纳入][16]开源家族。
|
||||
|
||||
这个项目最初是由 Ron Minnich 在 2017 年 1 月提出,它是 LinuxBIOS 的创造人,并且在 Google 领导 [coreboot][17] 的工作。
|
||||
|
||||
Google、Facebook、[Horizon Computing Solutions][18]、和 [Two Sigma][19] 共同合作,在运行 Linux 的服务器上开发 [LinuxBoot 项目][20](以前叫 [NERF][21])。
|
||||
|
||||
它的开放性允许服务器用户去很容易地定制他们自己的引导脚本、修复问题、构建他们自己的 [运行时环境][22] 和用他们自己的密钥去 [刷入固件][23],而不需要等待供应商的更新。
|
||||
|
||||
下面是第一次使用 NERF BIOS 去引导 [Ubuntu Xenial][24] 的视频:
|
||||
|
||||
[点击看视频](https://youtu.be/HBkZAN3xkJg)
|
||||
|
||||
我们来讨论一下它与 UEFI 相比在服务器硬件方面的其它优势。
|
||||
|
||||
### LinuxBoot 超越 UEFI 的优势
|
||||
|
||||

|
||||
|
||||
下面是一些 LinuxBoot 超越 UEFI 的主要优势:
|
||||
|
||||
#### 启动速度显著加快
|
||||
|
||||
它能在 20 秒钟以内完成服务器启动,而 UEFI 需要几分钟的时间。
|
||||
|
||||
#### 显著的灵活性
|
||||
|
||||
LinuxBoot 可以用在 Linux 支持的各种设备、文件系统和协议上。
|
||||
|
||||
#### 更加安全
|
||||
|
||||
相比 UEFI 而言,LinuxBoot 在设备驱动程序和文件系统方面进行更加严格的检查。
|
||||
|
||||
我们可能争辩说 UEFI 是使用 [EDK II][25] 而部分开源的,而 LinuxBoot 是部分闭源的。但有人[提出][26],即便有像 EDK II 这样的代码,但也没有做适当的审查级别和像 [Linux 内核][27] 那样的正确性检查,并且在 UEFI 的开发中还大量使用闭源组件。
|
||||
|
||||
另一方面,LinuxBoot 有非常小的二进制文件,它仅用了大约几百 KB,相比而言,而 UEFI 的二进制文件有 32 MB。
|
||||
|
||||
严格来说,LinuxBoot 与 UEFI 不一样,更适合于[可信计算基础][28]。
|
||||
|
||||
LinuxBoot 有一个基于 [kexec][30] 的引导加载器,它不支持启动 Windows/非 Linux 内核,但这影响并不大,因为主流的云都是基于 Linux 的服务器。
|
||||
|
||||
### LinuxBoot 的采用者
|
||||
|
||||
自 2011 年, [Facebook][32] 发起了[开源计算项目(OCP)][31],它的一些服务器是基于[开源][33]设计的,目的是构建的数据中心更加高效。LinuxBoot 已经在下面列出的几个开源计算硬件上做了测试:
|
||||
|
||||
* Winterfell
|
||||
* Leopard
|
||||
* Tioga Pass
|
||||
|
||||
更多 [OCP][34] 硬件在[这里][35]有一个简短的描述。OCP 基金会通过[开源系统固件][36]运行一个专门的固件项目。
|
||||
|
||||
支持 LinuxBoot 的其它一些设备有:
|
||||
|
||||
* [QEMU][9] 仿真的 [Q35][10] 系统
|
||||
* [Intel S2600wf][11]
|
||||
* [Dell R630][12]
|
||||
|
||||
上个月底(2018 年 9 月 24 日),[Equus 计算解决方案][37] [宣布][38] 发行它的 [白盒开放式™][39] M2660 和 M2760 服务器,作为它们的定制的、成本优化的、开放硬件服务器和存储平台的一部分。它们都支持 LinuxBoot 灵活定制服务器的 BIOS,以提升安全性和设计一个非常快的纯净的引导体验。
|
||||
|
||||
### 你认为 LinuxBoot 怎么样?
|
||||
|
||||
LinuxBoot 在 [GitHub][40] 上有很丰富的文档。你喜欢它与 UEFI 不同的特性吗?由于 LinuxBoot 的开放式开发和未来,你愿意使用 LinuxBoot 而不是 UEFI 去启动你的服务器吗?请在下面的评论区告诉我们吧。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/linuxboot-uefi/
|
||||
|
||||
作者:[Avimanyu Bandyopadhyay][a]
|
||||
选题:[oska874][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://itsfoss.com/author/avimanyu/
|
||||
[b]:https://github.com/oska874
|
||||
[1]:https://itsfoss.com/linuxboot-uefi/#
|
||||
[2]:https://itsfoss.com/linuxboot-uefi/#
|
||||
[3]:https://itsfoss.com/linuxboot-uefi/#
|
||||
[4]:https://itsfoss.com/linuxboot-uefi/#
|
||||
[5]:https://itsfoss.com/linuxboot-uefi/#
|
||||
[6]:https://itsfoss.com/linuxboot-uefi/#
|
||||
[7]:https://itsfoss.com/author/avimanyu/
|
||||
[8]:https://itsfoss.com/linuxboot-uefi/#comments
|
||||
[9]:https://en.wikipedia.org/wiki/QEMU
|
||||
[10]:https://wiki.qemu.org/Features/Q35
|
||||
[11]:https://trmm.net/S2600
|
||||
[12]:https://trmm.net/NERF#Installing_on_a_Dell_R630
|
||||
[13]:https://www.linuxboot.org/
|
||||
[14]:https://www.phoronix.com/scan.php?page=news_item&px=LinuxBoot-OSFC-2018-State
|
||||
[15]:https://itsfoss.com/check-uefi-or-bios/
|
||||
[16]:https://www.linuxfoundation.org/blog/2018/01/system-startup-gets-a-boost-with-new-linuxboot-project/
|
||||
[17]:https://en.wikipedia.org/wiki/Coreboot
|
||||
[18]:http://www.horizon-computing.com/
|
||||
[19]:https://www.twosigma.com/
|
||||
[20]:https://trmm.net/LinuxBoot_34c3
|
||||
[21]:https://trmm.net/NERF
|
||||
[22]:https://trmm.net/LinuxBoot_34c3#Runtimes
|
||||
[23]:http://www.tech-faq.com/flashing-firmware.html
|
||||
[24]:https://itsfoss.com/features-ubuntu-1604/
|
||||
[25]:https://www.tianocore.org/
|
||||
[26]:https://media.ccc.de/v/34c3-9056-bringing_linux_back_to_server_boot_roms_with_nerf_and_heads
|
||||
[27]:https://medium.com/@bhumikagoyal/linux-kernel-development-cycle-52b4c55be06e
|
||||
[28]:https://en.wikipedia.org/wiki/Trusted_computing_base
|
||||
[29]:https://itsfoss.com/adobe-alternatives-linux/
|
||||
[30]:https://en.wikipedia.org/wiki/Kexec
|
||||
[31]:https://en.wikipedia.org/wiki/Open_Compute_Project
|
||||
[32]:https://github.com/facebook
|
||||
[33]:https://github.com/opencomputeproject
|
||||
[34]:https://www.networkworld.com/article/3266293/lan-wan/what-is-the-open-compute-project.html
|
||||
[35]:http://hyperscaleit.com/ocp-server-hardware/
|
||||
[36]:https://www.opencompute.org/projects/open-system-firmware
|
||||
[37]:https://www.equuscs.com/
|
||||
[38]:http://www.dcvelocity.com/products/Software_-_Systems/20180924-equus-compute-solutions-introduces-whitebox-open-m2660-and-m2760-servers/
|
||||
[39]:https://www.equuscs.com/servers/whitebox-open/
|
||||
[40]:https://github.com/linuxboot/linuxboot
|
||||
@@ -1,4 +1,5 @@
|
||||
# KeeWeb – 一个开源且跨平台的密码管理工具
|
||||
KeeWeb:一个开源且跨平台的密码管理工具
|
||||
======
|
||||
|
||||

|
||||
|
||||
@@ -6,64 +7,60 @@
|
||||
|
||||
**KeePass** 就是一个这样的开源密码管理工具,它有一个官方客户端,但功能非常简单。也有许多 PC 端和手机端的其他密码管理工具,并且与 KeePass 存储加密密码的文件格式兼容。其中一个就是 **KeeWeb**。
|
||||
|
||||
KeeWeb 是一个开源、跨平台的密码管理工具,具有云同步,键盘快捷键和插件等功能。KeeWeb使用 Electron 框架,这意味着它可以在 Windows,Linux 和 Mac OS 上运行。
|
||||
KeeWeb 是一个开源、跨平台的密码管理工具,具有云同步,键盘快捷键和插件等功能。KeeWeb使用 Electron 框架,这意味着它可以在 Windows、Linux 和 Mac OS 上运行。
|
||||
|
||||
### KeeWeb 的使用
|
||||
|
||||
有两种方式可以使用 KeeWeb。第一种无需安装,直接在网页上使用,第二中就是在本地系统中安装 KeeWeb 客户端。
|
||||
|
||||
**在网页上使用 KeeWeb**
|
||||
#### 在网页上使用 KeeWeb
|
||||
|
||||
如果不想在系统中安装应用,可以去 [**https://app.keeweb.info/**][1] 使用KeeWeb。
|
||||
如果不想在系统中安装应用,可以去 [https://app.keeweb.info/][1] 使用KeeWeb。
|
||||
|
||||

|
||||
|
||||
网页端具有桌面客户端的所有功能,当然也需要联网才能进行使用。
|
||||
|
||||
**在计算机中安装 KeeWeb**
|
||||
#### 在计算机中安装 KeeWeb
|
||||
|
||||
如果喜欢客户端的舒适性和离线可用性,也可以将其安装在系统中。
|
||||
|
||||
如果使用Ubuntu/Debian,你可以去 [**releases pages**][2] 下载 KeeWeb 最新的 **.deb ** 文件,然后通过下面的命令进行安装:
|
||||
如果使用 Ubuntu/Debian,你可以去 [发布页][2] 下载 KeeWeb 最新的 .deb 文件,然后通过下面的命令进行安装:
|
||||
|
||||
```
|
||||
$ sudo dpkg -i KeeWeb-1.6.3.linux.x64.deb
|
||||
|
||||
```
|
||||
|
||||
如果用的是 Arch,在 [**AUR**][3] 上也有 KeeWeb,可以使用任何 AUR 助手进行安装,例如 [**Yay**][4]:
|
||||
如果用的是 Arch,在 [AUR][3] 上也有 KeeWeb,可以使用任何 AUR 助手进行安装,例如 [Yay][4]:
|
||||
|
||||
```
|
||||
$ yay -S keeweb
|
||||
|
||||
```
|
||||
|
||||
安装后,从菜单中或应用程序启动器启动 KeeWeb。默认界面长这样:
|
||||
安装后,从菜单中或应用程序启动器启动 KeeWeb。默认界面如下:
|
||||
|
||||

|
||||
|
||||
### 总体布局
|
||||
|
||||
KeeWeb 界面主要显示所有密码的列表,在左侧展示所有标签。单击标签将对密码进行过滤,只显示带有那个标签的密码。在右侧,显示所选帐户的所有字段。你可以设置用户名,密码,网址,或者添加自定义的备注。你甚至可以创建自己的字段并将其标记为安全字段,这在存储信用卡信息等内容时非常有用。你只需单击即可复制密码。 KeeWeb 还显示账户的创建和修改日期。已删除的密码会保留在回收站中,可以在其中还原或永久删除。
|
||||
KeeWeb 界面主要显示所有密码的列表,在左侧展示所有标签。单击标签将对密码进行筛选,只显示带有那个标签的密码。在右侧,显示所选帐户的所有字段。你可以设置用户名、密码、网址,或者添加自定义的备注。你甚至可以创建自己的字段并将其标记为安全字段,这在存储信用卡信息等内容时非常有用。你只需单击即可复制密码。 KeeWeb 还显示账户的创建和修改日期。已删除的密码会保留在回收站中,可以在其中还原或永久删除。
|
||||
|
||||

|
||||
|
||||
### KeeWeb 功能
|
||||
|
||||
**云同步**
|
||||
#### 云同步
|
||||
|
||||
KeeWeb 的主要功能之一是支持各种远程位置和云服务。除了加载本地文件,你可以从以下位置打开文件:
|
||||
|
||||
```
|
||||
1. WebDAV Servers
|
||||
2. Google Drive
|
||||
3. Dropbox
|
||||
4. OneDrive
|
||||
```
|
||||
|
||||
这意味着如果你使用多台计算机,就可以在它们之间同步密码文件,因此不必担心某台设备无法访问所有密码。
|
||||
|
||||
**密码生成器**
|
||||
#### 密码生成器
|
||||
|
||||

|
||||
|
||||
@@ -71,13 +68,13 @@ KeeWeb 的主要功能之一是支持各种远程位置和云服务。除了加
|
||||
|
||||
为此,KeeWeb 有一个内置密码生成器,可以生成特定长度、包含指定字符的自定义密码。
|
||||
|
||||
**插件**
|
||||
#### 插件
|
||||
|
||||

|
||||
|
||||
你可以使用插件扩展 KeeWeb 的功能。 其中一些插件用于更改界面语言,而其他插件则添加新功能,例如访问 **<https://haveibeenpwned.com>** 以查看密码是否暴露。
|
||||
你可以使用插件扩展 KeeWeb 的功能。其中一些插件用于更改界面语言,而其他插件则添加新功能,例如访问 https://haveibeenpwned.com 以查看密码是否暴露。
|
||||
|
||||
**本地备份**
|
||||
#### 本地备份
|
||||
|
||||

|
||||
|
||||
@@ -94,7 +91,7 @@ via: https://www.ostechnix.com/keeweb-an-open-source-cross-platform-password-man
|
||||
作者:[EDITOR][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[jlztan](https://github.com/jlztan)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
在 Fedora 上使用 Steam play 和 Proton 来玩 Windows 游戏
|
||||
在 Fedora 上使用 Steam play 和 Proton 来玩 Windows 游戏
|
||||
======
|
||||
|
||||

|
||||
|
||||
几周前,Steam 宣布要给 Steam Play 增加一个新组件,用于支持在 Linux 平台上使用 Proton 来玩 Windows 的游戏,这个组件是 WINE 的一个分支。这个功能仍然处于测试阶段,且并非对所有游戏都有效。这里有一些关于 Steam 和 Proton 的细节。
|
||||
之前,Steam [宣布][1]要给 Steam Play 增加一个新组件,用于支持在 Linux 平台上使用 Proton 来玩 Windows 的游戏,这个组件是 WINE 的一个分支。这个功能仍然处于测试阶段,且并非对所有游戏都有效。这里有一些关于 Steam 和 Proton 的细节。
|
||||
|
||||
据 Steam 网站称,测试版本中有以下这些新功能:
|
||||
|
||||
@@ -13,29 +13,27 @@
|
||||
* 改进了对游戏控制器的支持,游戏自动识别所有 Steam 支持的控制器,比起游戏的原始版本,能够获得更多开箱即用的控制器兼容性。
|
||||
* 和 vanilla WINE 比起来,游戏的多线程性能得到了极大的提高。
|
||||
|
||||
|
||||
|
||||
### 安装
|
||||
|
||||
如果你有兴趣,想尝试一下 Steam 和 Proton。请按照下面这些简单的步骤进行操作。(请注意,如果你已经安装了最新版本的 Steam,可以忽略启用 Steam 测试版这个第一步。在这种情况下,你不再需要通过 Steam 测试版来使用 Proton。)
|
||||
|
||||
打开 Steam 并登陆到你的帐户,这个截屏示例显示的是在使用 Proton 之前仅支持22个游戏。
|
||||
打开 Steam 并登陆到你的帐户,这个截屏示例显示的是在使用 Proton 之前仅支持 22 个游戏。
|
||||
|
||||
![][3]
|
||||
|
||||
现在点击客户端顶部的 Steam 选项,这会显示一个下拉菜单。然后选择设置。
|
||||
现在点击客户端顶部的 “Steam” 选项,这会显示一个下拉菜单。然后选择“设置”。
|
||||
|
||||
![][4]
|
||||
|
||||
现在弹出了设置窗口,选择账户选项,并在 Beta participation 旁边,点击更改。
|
||||
现在弹出了设置窗口,选择“账户”选项,并在 “参与 Beta 测试” 旁边,点击“更改”。
|
||||
|
||||
![][5]
|
||||
|
||||
现在将 None 更改为 Steam Beta Update。
|
||||
现在将 “None” 更改为 “Steam Beta Update”。
|
||||
|
||||
![][6]
|
||||
|
||||
点击确定,然后系统会提示你重新启动。
|
||||
点击“确定”,然后系统会提示你重新启动。
|
||||
|
||||
![][7]
|
||||
|
||||
@@ -43,11 +41,11 @@
|
||||
|
||||
![][8]
|
||||
|
||||
在重新启动之后,返回到上面的设置窗口。这次你会看到一个新选项。确定有为提供支持的游戏使用 Stream Play 这个复选框,让所有的游戏都使用 Steam Play 进行运行,而不是 steam 中游戏特定的选项。兼容性工具应该是 Proton。
|
||||
在重新启动之后,返回到上面的设置窗口。这次你会看到一个新选项。确定勾选了“为提供支持的游戏使用 Stream Play” 、“让所有的游戏都使用 Steam Play 运行”,“使用这个工具替代 Steam 中游戏特定的选项”。这个兼容性工具应该就是 Proton。
|
||||
|
||||
![][9]
|
||||
|
||||
Steam 客户端会要求你重新启动,照做,然后重新登陆你的 Steam 账户,你的 Linux 的游戏库就能得到扩展了。
|
||||
Steam 客户端会要求你重新启动,照做,然后重新登录你的 Steam 账户,你的 Linux 的游戏库就能得到扩展了。
|
||||
|
||||
![][10]
|
||||
|
||||
@@ -69,7 +67,7 @@ Steam 客户端会要求你重新启动,照做,然后重新登陆你的 Stea
|
||||
|
||||
![][16]
|
||||
|
||||
一些游戏可能会受到 Proton 测试性质的影响,在下面这个叫 Chantelise 游戏中,没有了声音并且帧率很低。请记住这个功能仍然在测试阶段,Fedora 不会对结果负责。如果你想要了解更多,社区已经创建了一个 Google 文档,这个文档里有已经测试过的游戏的列表。
|
||||
一些游戏可能会受到 Proton 测试性质的影响,在这个叫 Chantelise 游戏中,没有了声音并且帧率很低。请记住这个功能仍然在测试阶段,Fedora 不会对结果负责。如果你想要了解更多,社区已经创建了一个 Google 文档,这个文档里有已经测试过的游戏的列表。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -79,25 +77,25 @@ via: https://fedoramagazine.org/play-windows-games-steam-play-proton/
|
||||
作者:[Francisco J. Vergara Torres][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[hopefully2333](https://github.com/hopefully2333)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/patxi/
|
||||
[1]: https://steamcommunity.com/games/221410/announcements/detail/1696055855739350561
|
||||
[2]: https://fedoramagazine.org/third-party-repositories-fedora/
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2018/09/listOfGamesLinux-300x197.png
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2018/09/1-300x169.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2018/09/2-300x196.png
|
||||
[6]: https://fedoramagazine.org/wp-content/uploads/2018/09/4-300x272.png
|
||||
[7]: https://fedoramagazine.org/wp-content/uploads/2018/09/6-300x237.png
|
||||
[8]: https://fedoramagazine.org/wp-content/uploads/2018/09/7-300x126.png
|
||||
[9]: https://fedoramagazine.org/wp-content/uploads/2018/09/10-300x237.png
|
||||
[10]: https://fedoramagazine.org/wp-content/uploads/2018/09/12-300x196.png
|
||||
[11]: https://fedoramagazine.org/wp-content/uploads/2018/09/13-300x196.png
|
||||
[12]: https://fedoramagazine.org/wp-content/uploads/2018/09/14-300x195.png
|
||||
[13]: https://fedoramagazine.org/wp-content/uploads/2018/09/15-300x196.png
|
||||
[14]: https://fedoramagazine.org/wp-content/uploads/2018/09/16-300x195.png
|
||||
[15]: https://fedoramagazine.org/wp-content/uploads/2018/09/Screenshot-from-2018-08-30-15-14-59-300x169.png
|
||||
[16]: https://fedoramagazine.org/wp-content/uploads/2018/09/Screenshot-from-2018-08-30-15-19-34-300x169.png
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2018/09/listOfGamesLinux-768x505.png
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2018/09/1-768x432.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2018/09/2-768x503.png
|
||||
[6]: https://fedoramagazine.org/wp-content/uploads/2018/09/4.png
|
||||
[7]: https://fedoramagazine.org/wp-content/uploads/2018/09/6.png
|
||||
[8]: https://fedoramagazine.org/wp-content/uploads/2018/09/7.png
|
||||
[9]: https://fedoramagazine.org/wp-content/uploads/2018/09/10.png
|
||||
[10]: https://fedoramagazine.org/wp-content/uploads/2018/09/12-768x503.png
|
||||
[11]: https://fedoramagazine.org/wp-content/uploads/2018/09/13-768x501.png
|
||||
[12]: https://fedoramagazine.org/wp-content/uploads/2018/09/14-768x498.png
|
||||
[13]: https://fedoramagazine.org/wp-content/uploads/2018/09/15-768x501.png
|
||||
[14]: https://fedoramagazine.org/wp-content/uploads/2018/09/16-768x500.png
|
||||
[15]: https://fedoramagazine.org/wp-content/uploads/2018/09/Screenshot-from-2018-08-30-15-14-59-768x432.png
|
||||
[16]: https://fedoramagazine.org/wp-content/uploads/2018/09/Screenshot-from-2018-08-30-15-19-34-768x432.png
|
||||
[17]: https://docs.google.com/spreadsheets/d/1DcZZQ4HL_Ol969UbXJmFG8TzOHNnHoj8Q1f8DIFe8-8/edit#gid=1003113831
|
||||
@@ -1,34 +1,35 @@
|
||||
5 个适合系统管理员使用的告警可视化工具
|
||||
======
|
||||
这些开源的工具能够通过输出帮助用户了解系统的运行状况,并对可能发生的潜在问题作出告警。
|
||||
|
||||
> 这些开源的工具能够通过输出帮助用户了解系统的运行状况,并对可能发生的潜在问题作出告警。
|
||||
|
||||

|
||||
|
||||
你大概已经已经知道告警可视化工具是用来做什么的了。下面我们就要来说一下,为什么要讨论这样的工具,甚至某些系统专门将可视化作为特有的功能。
|
||||
你大概已经知道(或猜到)<ruby>告警可视化<rt>alerting and visualization</rt></ruby>工具是用来做什么的了。下面我们就要来说一下,为什么要讨论这样的工具,甚至某些系统专门将可视化作为特有的功能。
|
||||
|
||||
可观察性的概念来自控制理论,这个概念描述了我们通过对系统的输入和系统的输出来了解系统的能力。本文将重点介绍具有可观察性的输出组件。
|
||||
<ruby>可观察性<rt>Observability</rt></ruby>的概念来自<ruby>控制理论<rt>control theory</ruby>,这个概念描述了我们通过对系统的输入和输出来了解其的能力。本文将重点介绍具有可观察性的输出组件。
|
||||
|
||||
告警可视化工具可以对系统的输出进行分析,进而对输出的信息结构化。告警实际上是对系统异常状态的描述,而可视化则是让用户能够直观理解的结构化表示。
|
||||
告警可视化工具可以对其它系统的输出进行分析,进而对输出的信息进行结构化表示。告警实际上是对系统异常状态的描述,而可视化则是让用户能够直观理解的结构化表示。
|
||||
|
||||
### 常见的可视化告警
|
||||
|
||||
#### 告警
|
||||
|
||||
首先要明确一下告警的含义。在人员无法响应告警内容情况下,不应该发送告警。包括那些发给多个人,但只有其中少数人可以响应的告警,以及系统中的每个异常都触发的告警。因为这样会产生告警疲劳,告警接收者也往往会对这些过多的告警采取忽视的态度。
|
||||
首先要明确一下<ruby>告警<rt>alert</rt></ruby>的含义。在人员无法响应告警内容情况下,不应该发送告警 —— 包括那些发给多个人但只有其中少数人可以响应的告警,以及系统中的每个异常都触发的告警。因为这样会产生告警疲劳,告警接收者也往往会对这些过多的告警采取忽视的态度 —— 直到系统恶化到以少见的方式告警。
|
||||
|
||||
例如,如果管理员每天都会收到告警系统发来的数百封告警邮件,他就很容易会忽略告警系统的所有邮件。除非问题真正发生,并且受到了客户或上级的询问时,管理员才会重新重视告警信息。在这种情况下,告警已经失去了原有的意义和用途。
|
||||
例如,如果管理员每天都会收到告警系统发来的数百封告警邮件,他就很容易会忽略告警系统的所有邮件。除非他真的看到问题发生,或者受到了客户或上级的询问时,管理员才会重新重视告警信息。在这种情况下,告警已经失去了原有的意义和用途。
|
||||
|
||||
告警不是一个持续的信息流或者状态更新。告警的目的在于暴露系统无法自动恢复的问题,而且告警应该只发送给最有可能解决问题的人员。超出这个定义的内容都不应该作为告警,否则将会对实际工作造成不良的影响。
|
||||
|
||||
不同的告警体系都会有各自的告警类型,因此不能用优先级(P1-P5)或者诸如“信息”、“警告”、“严重”之类的字眼来一概而论,而应该使用一些通用的分类方式来对复杂系统事件进行描述。
|
||||
不同的告警体系都会有各自的告警类型,因此不能用优先级(P1-P5)或者诸如“信息”、“警告”、“严重”之类的字眼来一概而论,下面我会介绍一些新兴的复杂系统的事件响应中出现的通用分类方式。
|
||||
|
||||
刚才我提到了一个“信息”这个告警类型,但实际上告警不应该是一个信息,尽管有些人可能会不这样认为。但我觉得如果一个告警没有发送给任何一个人,它就不应该是警报,而只是一些在系统中被视为警报的数据点,代表了一些应该知晓但不需要响应的事件。它更应该作为告警可视化工具的一部分,而不是会导致触发告警的事件。《[实用监控][1]》是这个领域的必读书籍,其作者 Mike Julian 在书中就介绍了他自己关于告警的看法。
|
||||
刚才我提到了一个“信息”这个告警类型,但实际上告警不应该是一个信息,尽管有些人可能会不这样认为。但我觉得如果一个告警没有发送给任何一个人,它就不应该是警报,而只是一些在许多系统中被视为警报的数据点,代表了一些应该知晓但不需要响应的事件。它更应该作为告警可视化工具的一部分,而不是会导致触发告警的事件。《[实用监控][1]》是这个领域的必读书籍,其作者 Mike Julian 在书中就介绍了他自己关于告警的看法。
|
||||
|
||||
而非信息警报则代表告警需要被响应以及需要相关的操作。我将这些告警大致分为内部故障和外部故障两种类型,而对于大多数公司来说,通常会有两个以上的级别来确定响应告警的优先级。系统性能下降就是一种故障,因为这种现象对用户的影响通常都是未知的。
|
||||
而非信息警报则代表告警需要被响应以及需要相关的操作。我将这些告警大致分为内部故障和外部故障两种类型,而对于大多数公司来说,通常会有两个以上的级别来确定响应告警的优先级。系统性能下降就是一种故障,因为其对用户的影响通常都是未知的。
|
||||
|
||||
内部故障比外部故障的优先级低,但也需要快速响应。内部故障通常包括公司员工使用的内部系统或仅对公司员工可见的应用故障。
|
||||
|
||||
外部则包括任何会产生业务影响的系统故障,但不包括影响系统更新的故障。外部故障一般包括客户端应用故障、数据库故障和导致系统可用性或一致性失效的网络故障,这些都会影响用户的正常使用。对于不直接影响用户的依赖组件故障也属于外部故障,随着应用程序的不断运行,一旦依赖组件发生故障,系统的性能也会受到波及。这种情况对于使用某些外部服务或数据源的系统来说很常见,尽管这些外部服务或数据源对于可能不涉及到系统的主要功能,但是当系统在处理相关依赖组件的错误时可能会出现较明显的延迟。
|
||||
外部故障则包括任何马上会产生业务影响的系统故障,但不包括影响系统更新的故障。外部故障一般包括客户所面临的应用故障、数据库故障和导致系统可用性或一致性失效的网络故障,这些都会影响用户的正常使用。对于不直接影响用户的依赖组件故障也属于外部故障,随着应用程序的不断运行,一旦依赖组件发生故障,系统的性能也会受到波及。这种情况对于使用某些外部服务或数据源的系统来说很常见,尽管这些外部服务或数据源对于可能不涉及到系统的主要功能,但是当系统在处理相关依赖组件的错误时可能会出现较明显的延迟。
|
||||
|
||||
### 可视化
|
||||
|
||||
@@ -36,11 +37,11 @@
|
||||
|
||||
#### 折线图
|
||||
|
||||
折线图可能是最常见的可视化方式了,它可以让用户很直观地按照时间维度了解系统的情况。系统中每个不同的指标都会以一条独立的折线在图表中体现。但当同一个图表中同时存在多条折线时,就可能会对阅读有所影响(如下图所示),所以大多数情况下都可以选择仅查看其中的少数几条折线,而不是让所有折线同时显示。如果某个指标的数值产生了大于正常范围的波动,就会很容易发现。例如下图中异常的紫线、黄线、浅蓝线。
|
||||
折线图可能是最常见的可视化方式了,它可以让用户很直观地按照时间维度了解系统的情况。系统中每个单一或聚合的指标都会以一条折线在图表中体现。但当同一个图表中同时存在多条折线时,就可能会对阅读有所影响(如下图所示),所以大多数情况下都可以选择仅查看其中的少数几条折线,而不是让所有折线同时显示。如果某个指标的数值产生了大于正常范围的波动,就会很容易发现。例如下图中异常的紫线、黄线、浅蓝线。
|
||||
|
||||

|
||||
|
||||
折线图的另一个用法是可以将多条折线堆积起来以显示它们之间的关系。例如对于通过折线图反映服务器的请求数量,可以单独显示每台服务器上的请求,也可以把多台服务器的数据合在一起显示。这就可以在同一个图表中灵活查看整个系统中每个实例的情况了。
|
||||
折线图的另一个用法是可以将多条折线堆叠起来以显示它们之间的关系。例如对于通过折线图反映服务器的请求数量,可以单独看到每台服务器上的请求,也可以聚合在一起看。这就可以在同一个图表中灵活查看整个系统以及每个实例的情况了。
|
||||
|
||||

|
||||
|
||||
@@ -54,7 +55,7 @@
|
||||
|
||||
#### 仪表图
|
||||
|
||||
还有一种常见的可视化方式是仪表图,用户可以通过仪表图快速了解单个指标。仪表一般用于单个指标的显示,例如车速表代表汽车的行驶速度、油量表代表油箱中的汽油量等等。大多数的仪表图都有一个共通点,就是会划分出所示指标的对应状态。如下图所示,绿色表示正常的状态,橙色表示不良的状态,而红色则表示极差的状态。中间一行则模拟了真实仪表的显示情况。
|
||||
还有一种常见的可视化方式是仪表图,用户可以通过仪表图快速了解单个指标。仪表一般用于单个指标的显示,例如车速表代表汽车的行驶速度、油量表代表油箱中的汽油量等等。大多数的仪表图都有一个共通点,就是会划分出所示指标的对应状态。如下图所示,绿色表示正常的状态,橙色表示不良的状态,而红色则表示极差的状态。下图中间一行模拟了真实仪表的显示情况。
|
||||
|
||||

|
||||
|
||||
@@ -76,29 +77,29 @@
|
||||
|
||||
如果你的电脑出现问题,得多亏 Stack Exchange 你才能在网上查到解决办法。Stack Exchange 以众包问答的模式运营着很多不同类型的网站。其中就有广受开发者欢迎的 [Stack Overflow][5],以及运维方面有名的 [Super User][6]。除此以外,从育儿经验到科幻小说、从哲学讨论到单车论坛,Stack Exchange 都有涉猎。
|
||||
|
||||
Stack Exchange 开源了它的开源告警管理系统 [Bosun][7],同时也发布了使用 [AlertManager][8] 的 Prometheus 系统。这两个系统有共通点。Bosun 和 Prometheus 一样使用 Golang 开发,但 Bosun 比 Prometheus 更为强大,因为它可以使用<ruby>权值聚合<rt>metrics aggregation</rt></ruby>以外的方式与系统交互。Bosun 还可以从日志收集系统中提取数据,并且支持 Graphite、InfluxDB、OpenTSDB 和 Elasticsearch。
|
||||
Stack Exchange 开源了它的告警管理系统 [Bosun][7],同时也发布了 Prometheus 及其 [AlertManager][8] 系统。这两个系统有共通点。Bosun 和 Prometheus 一样使用 Golang 开发,但 Bosun 比 Prometheus 更为强大,因为它可以使用<ruby>指标聚合<rt>metrics aggregation</rt></ruby>以外的方式与系统交互。Bosun 还可以从日志和事件收集系统中提取数据,并且支持 Graphite、InfluxDB、OpenTSDB 和 Elasticsearch。
|
||||
|
||||
Bosun 的架构包括一个二进制服务文件,以及一个诸如 OpenTSDB 的后端、Redis 以及 [scollector agents][9]。 scollector agents 会自动检测主机上正在运行的服务,并反馈这些进程和其它的系统资源情况。这些数据将发送到后端。随后 Bosun 二进制服务文件会向后端发起查询,确定是否需要触发告警。也可以通过 [Grafana][10] 这些工具通过一个通用接口查询 Bosun 的底层后端。而 Redis 则用于存储 Bosun 的状态信息和元数据。
|
||||
Bosun 的架构包括一个单一的服务器的二进制文件,一个诸如 OpenTSDB 的后端、Redis 以及 [scollector 代理][9]。 scollector 代理会自动检测主机上正在运行的服务,并反馈这些进程和其它的系统资源的情况。这些数据将发送到后端。随后 Bosun 的二进制服务文件会向后端发起查询,确定是否需要触发告警。也可以通过 [Grafana][10] 这些工具通过一个通用接口查询 Bosun 的底层后端。而 Redis 则用于存储 Bosun 的状态信息和元数据。
|
||||
|
||||
Bosun 有一个非常巧妙的功能,就是可以根据历史数据来测试告警。这是我几年前在使用 Prometheus 的时候就非常需要的功能,当时我有一个异常的数据需要产生告警,但没有一个可以用于测试的简便方法。为了确保告警能够正常触发,我不得不造出对应的数据来进行测试。而 Bosun 让这个步骤的耗时大大缩短。
|
||||
|
||||
Bosun 更是涵盖了所有常用过的功能,包括简单的图形化表示和告警的创建。它还带有强大的用于编写告警规则的表达式语言。但 Bosun 默认只带有电子邮件通知配置和 HTTP 通知配置,因此如果需要连接到 Slack 或其它工具,就需要对配置作出更大程度的定制化。类似于 Prometheus,Bosun 还可以使用模板通知,你可以使用 HTML 和 CSS 来创建你所需要的电子邮件通知。
|
||||
Bosun 更是涵盖了所有常用过的功能,包括简单的图形化表示和告警的创建。它还带有强大的用于编写告警规则的表达式语言。但 Bosun 默认只带有电子邮件通知配置和 HTTP 通知配置,因此如果需要连接到 Slack 或其它工具,就需要对配置作出更大程度的定制化([其文档中有][11])。类似于 Prometheus,Bosun 还可以使用模板通知,你可以使用 HTML 和 CSS 来创建你所需要的电子邮件通知。
|
||||
|
||||
#### Cabot
|
||||
|
||||
[Cabot][12] 由 [Arachnys][13] 公司开发。你或许对 Arachnys 公司并不了解,但它很有影响力:Arachnys 公司构建了一个基于云的先进解决方案,用于防范金融犯罪。在以前的公司,我也曾经参与过类似“[了解你的客户][14]”的工作。但大多数公司都认为与恐怖组织产生联系会造成相当不好的影响,因为恐怖组织可能会利用自己的系统来筹集资金。而这些解决方案将有助于防范欺诈类犯罪,尽管这类犯罪情节相对较轻,但仍然也会对机构产生风险。
|
||||
[Cabot][12] 由 [Arachnys][13] 公司开发。你或许对 Arachnys 公司并不了解,但它很有影响力:Arachnys 公司构建了一个基于云的先进解决方案,用于防范金融犯罪。在之前的公司时,我也曾经参与过类似“[了解你的客户][14](KYC)”的工作。大多数公司都认为与恐怖组织产生联系会造成相当不好的影响,因为恐怖组织可能会利用自己的系统来筹集资金。而这些解决方案将有助于防范欺诈类犯罪,尽管这类犯罪情节相对较轻,但仍然也会对机构产生风险。
|
||||
|
||||
Arachnys 公司为什么要开发 Cabot 呢?其实只是因为 Arachnys 的开发人员对 [Nagios][15] 不太熟悉。Cabot 的出现对很多人来说都是一个好消息,它基于 Django 和 Bootstrap 开发,因此如果相对这个项目做出自己的贡献,门槛并不高。另外值得一提的是,Cabot 这个名字来源于开发者的狗。
|
||||
Arachnys 公司为什么要开发 Cabot 呢?其实只是因为 Arachnys 的开发人员对 [Nagios][15] 不太熟悉。Cabot 的出现对很多人来说都是一个好消息,它基于 Django 和 Bootstrap 开发,因此如果想对这个项目做出自己的贡献,门槛并不高。(另外值得一提的是,Cabot 这个名字来源于开发者的狗。)
|
||||
|
||||
与 Bosun 类似,Cabot 也不对数据进行收集,而是使用监控对象的 API 提供的数据。因此,Cabot 告警的模式是 pull 而不是 push。它通过访问每个监控对象的 API,根据特定的指标检索所需的数据,然后将告警数据使用 Redis 缓存,进而持久化存储到 Postgres 数据库。
|
||||
与 Bosun 类似,Cabot 也不对数据进行收集,而是使用监控对象的 API 提供的数据。因此,Cabot 告警的模式是拉取而不是推送。它通过访问每个监控对象的 API,根据特定的指标检索所需的数据,然后将告警数据使用 Redis 缓存,进而持久化存储到 Postgres 数据库。
|
||||
|
||||
Cabot 的一个较为少见的特点是,它原生支持 [Graphite][16],同时也支持 [Jenkins][17]。Jenkins 在这里被视为一个集中式的 cron,它会以对待故障的方式去对待构建失败的状况。构建失败当然没有系统故障那么紧急,但一旦出现构建失败,还是需要团队采取措施去处理,毕竟并不是每个人在收到构建失败的电子邮件时都会亲自去检查 Jenkins。
|
||||
Cabot 的一个较为少见的特点是,它原生支持 [Graphite][16],同时也支持 [Jenkins][17]。Jenkins 在这里被视为一个集中式的定时任务,它会以对待故障的方式去对待构建失败的状况。构建失败当然没有系统故障那么紧急,但一旦出现构建失败,还是需要团队采取措施去处理,毕竟并不是每个人在收到构建失败的电子邮件时都会亲自去检查 Jenkins。
|
||||
|
||||
Cabot 另一个有趣的功能是它可以接入 Google 日历安排值班人员,这个称为 Rota 的功能用处很大,希望其它告警系统也能加入类似的功能。Cabot 目前仅支持安排主备联系人,但还有继续改进的空间。它自己的文档也提到,如果需要全面的功能,更应该考虑付费的解决方案。
|
||||
|
||||
#### StatsAgg
|
||||
|
||||
[Pearson][19] 作为一家开发了 [StatsAgg][18] 告警平台的出版公司,这是极为罕见的,当然也很值得敬佩。除此以外,Pearson 还运营着另外几个网站,以及和 [O'Reilly Media][20] 合资的企业。但我仍然会将它视为出版教学书籍的公司。
|
||||
[Pearson][19] 作为一家开发了 [StatsAgg][18] 告警平台的出版公司,这是极为罕见的,当然也很值得敬佩。除此以外,Pearson 还运营着另外几个网站以及和 [O'Reilly Media][20] 合资的企业。但我仍然会将它视为出版教学书籍的公司。
|
||||
|
||||
StatsAgg 除了是一个告警平台,还是一个指标聚合平台,甚至也有点类似其它系统的代理。StatsAgg 支持通过 Graphite、StatsD、InfluxDB 和 OpenTSDB 输入数据,也支持将其转发到各种平台。但随着中心服务的负载不断增加,风险也不断增大。尽管如此,如果 StatsAgg 的基础架构足够强壮,即使后端存储平台出现故障,也不会对它产生告警的过程造成影响。
|
||||
|
||||
@@ -108,15 +109,15 @@ StatsAgg 是用 Java 开发的,为了尽可能降低复杂性,它仅包括
|
||||
|
||||
#### Grafana
|
||||
|
||||
[Grafana][10] 的知名度很高,它也被广泛采用。每当我需要用到数据面板的时候,我总是会想到它,因为它比我使用过的任何一款类似的产品都要好。Grafana 由 Torkel Ödegaard 在圣诞节期间开发,并在 2014 年 1 月发布。在短短几年之间,它已经有了长足的发展。Grafana 基于 Kibana 开发,Torkel 开启了新的分支并将其命名为 Grafana。
|
||||
[Grafana][10] 的知名度很高,它也被广泛采用。每当我需要用到数据面板的时候,我总是会想到它,因为它比我使用过的任何一款类似的产品都要好。Grafana 由 Torkel Ödegaard 开发的,像 Cabot 一样,也是在圣诞节期间开发的,并在 2014 年 1 月发布。在短短几年之间,它已经有了长足的发展。Grafana 基于 Kibana 开发,Torkel 开启了新的分支并将其命名为 Grafana。
|
||||
|
||||
Grafana 着重体现了实用性已经数据呈现的美观性。它可以原生地从 Graphite、Elasticsearch、OpenTSDB、Prometheus 和 InfluxDB 收集数据。此外有一个 Grafana 商用版插件可以从更多数据源获取数据,尽管这个插件没有开源,但 Grafana 的生态系统提供的各种数据源已经足够了。
|
||||
Grafana 着重体现了实用性以及数据呈现的美观性。它天生就可以从 Graphite、Elasticsearch、OpenTSDB、Prometheus 和 InfluxDB 收集数据。此外有一个 Grafana 商用版插件可以从更多数据源获取数据,但是其他数据源插件也并非没有开源版本,Grafana 的插件生态系统已经提供了各种数据源。
|
||||
|
||||
Grafana 提供了一个集系统各种数据于一身的平台。它通过 web 来展示数据,任何人都有机会访问到相关信息,因此需要使用身份验证来对访问进行限制。Grafana 还支持不同类型的可视化方式,包括集成告警可视化的功能。
|
||||
Grafana 能做什么呢?Grafana 提供了一个中心化的了解系统的方式。它通过 web 来展示数据,任何人都有机会访问到相关信息,当然也可以使用身份验证来对访问进行限制。Grafana 使用各种可视化方式来提供对系统一目了然的了解。Grafana 还支持不同类型的可视化方式,包括集成告警可视化的功能。
|
||||
|
||||
现在你可以更直观地设置告警了。通过Grafana,可以查看图表,还可以设置系统性能下降触发告警的阈值,并告诉 Grafana 应该如何发送告警。这是一个对告警体系非常强大的补充。告警平台不一定会因此而被取代,但告警系统一定会由此得到更多启发和发展。
|
||||
现在你可以更直观地设置告警了。通过 Grafana,可以查看图表,还可以查看由于系统性能下降而触发告警的位置,单击要触发报警的位置,并告诉 Grafana 将告警发送何处。这是一个对告警平台非常强大的补充。告警平台不一定会因此而被取代,但告警系统一定会由此得到更多启发和发展。
|
||||
|
||||
Grafana 还引入了很多团队协作的功能。不同用户之间能够共享数据面板,你不再需要为 [Kubernetes][21] 集群创建独立的数据面板,因为由 Kubernetes 开发者和 Grafana 开发者共同维护的一些数据面板已经可以即插即用。
|
||||
Grafana 还引入了很多团队协作的功能。不同用户之间能够共享数据面板,你不再需要为 [Kubernetes][21] 集群创建独立的数据面板,因为由 Kubernetes 开发者和 Grafana 开发者共同维护的一些数据面板已经可用了。
|
||||
|
||||
团队协作过程中一个重要的功能是注释。注释功能允许用户将上下文添加到图表当中,其他用户就可以通过上下文更直观地理解图表。当团队成员在处理某个事件,并且需要沟通和理解时,这个功能就十分重要了。将所有相关信息都放在需要的位置,可以让整个团队中快速达成共识。在团队需要调查故障原因和定位事件责任时,这个功能就可以发挥作用了。
|
||||
|
||||
@@ -131,7 +132,7 @@ via: https://opensource.com/article/18/10/alerting-and-visualization-tools-sysad
|
||||
作者:[Dan Barker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
Lisp 是怎么成为上帝的编程语言的
|
||||
======
|
||||
|
||||
当程序员们谈论各类编程语言的相对优势时,他们通常会采用相当平淡的措词,就好像这些语言是一条工具带上的各种工具似的 —— 有适合写操作系统的,也有适合把其它程序黏在一起来完成特殊工作的。这种讨论方式非常合理;不同语言的能力不同。不声明特定用途就声称某门语言比其他语言更优秀只能导致侮辱性的无用争论。
|
||||
|
||||
但有一门语言似乎受到和用途无关的特殊尊敬:那就是 Lisp。即使是恨不得给每个说出形如“某某语言比其他所有语言都好”这类话的人都来一拳的键盘远征军们,也会承认 Lisp 处于另一个层次。 Lisp 超越了用于评判其他语言的实用主义标准,因为普通程序员并不使用 Lisp 编写实用的程序 —— 而且,多半他们永远也不会这么做。然而,人们对 Lisp 的敬意是如此深厚,甚至于到了这门语言会时而被加上神话属性的程度。
|
||||
|
||||
大家都喜欢的网络漫画合集 xkcd 就至少在两组漫画中如此描绘过 Lisp:[其中一组漫画][1]中,某人得到了某种 Lisp 启示,而这好像使他理解了宇宙的基本构架。
|
||||
|
||||

|
||||
|
||||
在[另一组漫画][2]中,一个穿着长袍的老程序员给他的徒弟递了一沓圆括号,说这是“文明时代的优雅武器”,暗示着 Lisp 就像原力那样拥有各式各样的神秘力量。
|
||||
|
||||

|
||||
|
||||
另一个绝佳例子是 Bob Kanefsky 的滑稽剧插曲,《上帝就在人间》。这部剧叫做《永恒之火》,撰写于 1990 年代中期;剧中描述了上帝必然是使用 Lisp 创造世界的种种原因。完整的歌词可以在 [GNU 幽默合集][3]中找到,如下是一段摘抄:
|
||||
|
||||
> 因为上帝用祂的 Lisp 代码
|
||||
|
||||
> 让树叶充满绿意。
|
||||
|
||||
> 分形的花儿和递归的根:
|
||||
|
||||
> 我见过的奇技淫巧之中没什么比这更可爱。
|
||||
|
||||
> 当我对着雪花深思时,
|
||||
|
||||
> 从未见过两片相同的,
|
||||
|
||||
> 我知道,上帝偏爱那一门
|
||||
|
||||
> 名字是四个字母的语言。
|
||||
|
||||
(LCTT 译注:参见 “四个字母”,参见:[四字神名](https://zh.wikipedia.org/wiki/%E5%9B%9B%E5%AD%97%E7%A5%9E%E5%90%8D),致谢 [no1xsyzy](https://github.com/LCTT/TranslateProject/issues/11320))
|
||||
|
||||
以下这句话我实在不好在人前说;不过,我还是觉得,这样一种 “Lisp 是奥术魔法”的文化模因实在是有史以来最奇异、最迷人的东西。Lisp 是象牙塔的产物,是人工智能研究的工具;因此,它对于编程界的俗人而言总是陌生的,甚至是带有神秘色彩的。然而,当今的程序员们[开始怂恿彼此,“在你死掉之前至少试一试 Lisp”][4],就像这是一种令人恍惚入迷的致幻剂似的。尽管 Lisp 是广泛使用的编程语言中第二古老的(只比 Fortran 年轻一岁)[^1] ,程序员们也仍旧在互相怂恿。想象一下,如果你的工作是为某种组织或者团队推广一门新的编程语言的话,忽悠大家让他们相信你的新语言拥有神力难道不是绝佳的策略吗?—— 但你如何能够做到这一点呢?或者,换句话说,一门编程语言究竟是如何变成人们口中“隐晦知识的载体”的呢?
|
||||
|
||||
Lisp 究竟是怎么成为这样的?
|
||||
|
||||
![Byte 杂志封面,1979年八月。][5]
|
||||
|
||||
*Byte 杂志封面,1979年八月。*
|
||||
|
||||
### 理论 A :公理般的语言
|
||||
|
||||
Lisp 的创造者<ruby>约翰·麦卡锡<rt>John McCarthy</rt></ruby>最初并没有想过把 Lisp 做成优雅、精炼的计算法则结晶。然而,在一两次运气使然的深谋远虑和一系列优化之后,Lisp 的确变成了那样的东西。 <ruby>保罗·格雷厄姆<rt>Paul Graham</rt></ruby>(我们一会儿之后才会聊到他)曾经这么写道, 麦卡锡通过 Lisp “为编程作出的贡献就像是欧几里得对几何学所做的贡献一般” [^2]。人们可能会在 Lisp 中看出更加隐晦的含义 —— 因为麦卡锡创造 Lisp 时使用的要素实在是过于基础,基础到连弄明白他到底是创造了这门语言、还是发现了这门语言,都是一件难事。
|
||||
|
||||
最初, 麦卡锡产生要造一门语言的想法,是在 1956 年的<ruby>达特茅斯人工智能夏季研究项目<rt>Darthmouth Summer Research Project on Artificial Intelligence</rt></ruby>上。夏季研究项目是个持续数周的学术会议,直到现在也仍旧在举行;它是此类会议之中最早开始举办的会议之一。 麦卡锡当初还是个达特茅斯的数学助教,而“<ruby>人工智能<rt>artificial intelligence</rt></ruby>(AI)”这个词事实上就是他建议举办该会议时发明的 [^3]。在整个会议期间大概有十人参加 [^4]。他们之中包括了<ruby>艾伦·纽厄尔<rt>Allen Newell</rt></ruby>和<ruby>赫伯特·西蒙<rt>Herbert Simon</rt></ruby>,两名隶属于<ruby>兰德公司<rt>RAND Corporation</rt></ruby>和<ruby>卡内基梅隆大学<rt>Carnegie Mellon</rt></ruby>的学者。这两人不久之前设计了一门语言,叫做 IPL。
|
||||
|
||||
当时,纽厄尔和西蒙正试图制作一套能够在命题演算中生成证明的系统。两人意识到,用电脑的原生指令集编写这套系统会非常困难;于是他们决定创造一门语言——他们的原话是“<ruby>伪代码<rt>pseudo-code</rt></ruby>”,这样,他们就能更加轻松自然地表达这台“<ruby>逻辑理论机器<rt>Logic Theory Machine</rt></ruby>”的底层逻辑了 [^5]。这门语言叫做 IPL,即“<ruby>信息处理语言<rt>Information Processing Language</rt></ruby>”;比起我们现在认知中的编程语言,它更像是一种高层次的汇编语言方言。 纽厄尔和西蒙提到,当时人们开发的其它“伪代码”都抓着标准数学符号不放 —— 也许他们指的是 Fortran [^6];与此不同的是,他们的语言使用成组的符号方程来表示命题演算中的语句。通常,用 IPL 写出来的程序会调用一系列的汇编语言宏,以此在这些符号方程列表中对表达式进行变换和求值。
|
||||
|
||||
麦卡锡认为,一门实用的编程语言应该像 Fortran 那样使用代数表达式;因此,他并不怎么喜欢 IPL [^7]。然而,他也认为,在给人工智能领域的一些问题建模时,符号列表会是非常好用的工具 —— 而且在那些涉及演绎的问题上尤其有用。麦卡锡的渴望最终被诉诸行动;他要创造一门代数的列表处理语言 —— 这门语言会像 Fortran 一样使用代数表达式,但拥有和 IPL 一样的符号列表处理能力。
|
||||
|
||||
当然,今日的 Lisp 可不像 Fortran。在会议之后的几年中,麦卡锡关于“理想的列表处理语言”的见解似乎在逐渐演化。到 1957 年,他的想法发生了改变。他那时候正在用 Fortran 编写一个能下国际象棋的程序;越是长时间地使用 Fortran ,麦卡锡就越确信其设计中存在不当之处,而最大的问题就是尴尬的 `IF` 声明 [^8]。为此,他发明了一个替代品,即条件表达式 `true`;这个表达式会在给定的测试通过时返回子表达式 `A` ,而在测试未通过时返回子表达式 `B` ,*而且*,它只会对返回的子表达式进行求值。在 1958 年夏天,当麦卡锡设计一个能够求导的程序时,他意识到,他发明的 `true` 条件表达式让编写递归函数这件事变得更加简单自然了 [^9]。也是这个求导问题让麦卡锡创造了 `maplist` 函数;这个函数会将其它函数作为参数并将之作用于指定列表的所有元素 [^10]。在给项数多得叫人抓狂的多项式求导时,它尤其有用。
|
||||
|
||||
然而,以上的所有这些,在 Fortran 中都是没有的;因此,在 1958 年的秋天,麦卡锡请来了一群学生来实现 Lisp。因为他那时已经成了一名麻省理工助教,所以,这些学生可都是麻省理工的学生。当麦卡锡和学生们最终将他的主意变为能运行的代码时,这门语言得到了进一步的简化。这之中最大的改变涉及了 Lisp 的语法本身。最初,麦卡锡在设计语言时,曾经试图加入所谓的 “M 表达式”;这是一层语法糖,能让 Lisp 的语法变得类似于 Fortran。虽然 M 表达式可以被翻译为 S 表达式 —— 基础的、“用圆括号括起来的列表”,也就是 Lisp 最著名的特征 —— 但 S 表达式事实上是一种给机器看的低阶表达方法。唯一的问题是,麦卡锡用方括号标记 M 表达式,但他的团队在麻省理工使用的 IBM 026 键盘打孔机的键盘上根本没有方括号 [^11]。于是 Lisp 团队坚定不移地使用着 S 表达式,不仅用它们表示数据列表,也拿它们来表达函数的应用。麦卡锡和他的学生们还作了另外几样改进,包括将数学符号前置;他们也修改了内存模型,这样 Lisp 实质上就只有一种数据类型了 [^12]。
|
||||
|
||||
到 1960 年,麦卡锡发表了他关于 Lisp 的著名论文,《用符号方程表示的递归函数及它们的机器计算》。那时候,Lisp 已经被极大地精简,而这让麦卡锡意识到,他的作品其实是“一套优雅的数学系统”,而非普通的编程语言 [^13]。他后来这么写道,对 Lisp 的许多简化使其“成了一种描述可计算函数的方式,而且它比图灵机或者一般情况下用于递归函数理论的递归定义更加简洁” [^14]。在他的论文中,他不仅使用 Lisp 作为编程语言,也将它当作一套用于研究递归函数行为方式的表达方法。
|
||||
|
||||
通过“从一小撮规则中逐步实现出 Lisp”的方式,麦卡锡将这门语言介绍给了他的读者。后来,保罗·格雷厄姆在短文《<ruby>[Lisp 之根][6]<rt>The Roots of Lisp</rt></ruby>》中用更易读的语言回顾了麦卡锡的步骤。格雷厄姆只用了七种原始运算符、两种函数写法,以及使用原始运算符定义的六个稍微高级一点的函数来解释 Lisp。毫无疑问,Lisp 的这种只需使用极少量的基本规则就能完整说明的特点加深了其神秘色彩。格雷厄姆称麦卡锡的论文为“使计算公理化”的一种尝试 [^15]。我认为,在思考 Lisp 的魅力从何而来时,这是一个极好的切入点。其它编程语言都有明显的人工构造痕迹,表现为 `While`,`typedef`,`public static void` 这样的关键词;而 Lisp 的设计却简直像是纯粹计算逻辑的鬼斧神工。Lisp 的这一性质,以及它和晦涩难懂的“递归函数理论”的密切关系,使它具备了获得如今声望的充分理由。
|
||||
|
||||
### 理论 B:属于未来的机器
|
||||
|
||||
Lisp 诞生二十年后,它成了著名的《<ruby>[黑客词典][7]<rt>Hacker’s Dictionary</rt></ruby>》中所说的,人工智能研究的“母语”。Lisp 在此之前传播迅速,多半是托了语法规律的福 —— 不管在怎么样的电脑上,实现 Lisp 都是一件相对简单直白的事。而学者们之后坚持使用它乃是因为 Lisp 在处理符号表达式这方面有巨大的优势;在那个时代,人工智能很大程度上就意味着符号,于是这一点就显得十分重要。在许多重要的人工智能项目中都能见到 Lisp 的身影。这些项目包括了 [SHRDLU 自然语言程序][8]、[Macsyma 代数系统][9] 和 [ACL2 逻辑系统][10]。
|
||||
|
||||
然而,在 1970 年代中期,人工智能研究者们的电脑算力开始不够用了。PDP-10 就是一个典型。这个型号在人工智能学界曾经极受欢迎;但面对这些用 Lisp 写的 AI 程序,它的 18 位地址空间一天比一天显得吃紧 [^16]。许多的 AI 程序在设计上可以与人互动。要让这些既极度要求硬件性能、又有互动功能的程序在分时系统上优秀发挥,是很有挑战性的。麻省理工的<ruby>彼得·杜奇<rt>Peter Deutsch</rt></ruby>给出了解决方案:那就是针对 Lisp 程序来特别设计电脑。就像是我那[关于 Chaosnet 的上一篇文章][11]所说的那样,这些<ruby>Lisp 计算机<rt>Lisp machines</rt></ruby>会给每个用户都专门分配一个为 Lisp 特别优化的处理器。到后来,考虑到硬核 Lisp 程序员的需求,这些计算机甚至还配备上了完全由 Lisp 编写的开发环境。在当时那样一个小型机时代已至尾声而微型机的繁盛尚未完全到来的尴尬时期,Lisp 计算机就是编程精英们的“高性能个人电脑”。
|
||||
|
||||
有那么一会儿,Lisp 计算机被当成是未来趋势。好几家公司雨后春笋般出现,追着赶着要把这项技术商业化。其中最成功的一家叫做 Symbolics,由麻省理工 AI 实验室的前成员创立。上世纪八十年代,这家公司生产了所谓的 3600 系列计算机,它们当时在 AI 领域和需要高性能计算的产业中应用极广。3600 系列配备了大屏幕、位图显示、鼠标接口,以及[强大的图形与动画软件][12]。它们都是惊人的机器,能让惊人的程序运行起来。例如,之前在推特上跟我聊过的机器人研究者 Bob Culley,就能用一台 1985 年生产的 Symbolics 3650 写出带有图形演示的寻路算法。他向我解释说,在 1980 年代,位图显示和面向对象编程(能够通过 [Flavors 扩展][13]在 Lisp 计算机上使用)都刚刚出现。Symbolics 站在时代的最前沿。
|
||||
|
||||
![Bob Culley 的寻路程序。][14]
|
||||
|
||||
*Bob Culley 的寻路程序。*
|
||||
|
||||
而以上这一切导致 Symbolics 的计算机奇贵无比。在 1983 年,一台 Symbolics 3600 能卖 111,000 美金 [^16]。所以,绝大部分人只可能远远地赞叹 Lisp 计算机的威力和操作员们用 Lisp 编写程序的奇妙技术。不止他们赞叹,从 1979 年到 1980 年代末,Byte 杂志曾经多次提到过 Lisp 和 Lisp 计算机。在 1979 年八月发行的、关于 Lisp 的一期特别杂志中,杂志编辑激情洋溢地写道,麻省理工正在开发的计算机配备了“大坨大坨的内存”和“先进的操作系统” [^17];他觉得,这些 Lisp 计算机的前途是如此光明,以至于它们的面世会让 1978 和 1977 年 —— 诞生了 Apple II、Commodore PET 和 TRS-80 的两年 —— 显得黯淡无光。五年之后,在 1985 年,一名 Byte 杂志撰稿人描述了为“复杂精巧、性能强悍的 Symbolics 3670”编写 Lisp 程序的体验,并力劝读者学习 Lisp,称其为“绝大数人工智能工作者的语言选择”,和将来的通用编程语言 [^18]。
|
||||
|
||||
我问过<ruby>保罗·麦克琼斯<rt>Paul McJones</rt></ruby>(他在<ruby>山景城<rt>Mountain View<rt></ruby>的<ruby>计算机历史博物馆<rt>Computer History Museum</rt></ruby>做了许多 Lisp 的[保护工作][15]),人们是什么时候开始将 Lisp 当作高维生物的赠礼一样谈论的呢?他说,这门语言自有的性质毋庸置疑地促进了这种现象的产生;然而,他也说,Lisp 上世纪六七十年代在人工智能领域得到的广泛应用,很有可能也起到了作用。当 1980 年代到来、Lisp 计算机进入市场时,象牙塔外的某些人由此接触到了 Lisp 的能力,于是传说开始滋生。时至今日,很少有人还记得 Lisp 计算机和 Symbolics 公司;但 Lisp 得以在八十年代一直保持神秘,很大程度上要归功于它们。
|
||||
|
||||
### 理论 C:学习编程
|
||||
|
||||
1985 年,两位麻省理工的教授,<ruby>哈尔·阿伯尔森<rt>Harold "Hal" Abelson</rt></ruby>和<ruby>杰拉尔德·瑟斯曼<rt>Gerald Sussman</rt></ruby>,外加瑟斯曼的妻子<ruby>朱莉·瑟斯曼<rt>Julie Sussman</rt></ruby>,出版了一本叫做《<ruby>计算机程序的构造和解释<rt>Structure and Interpretation of Computer Programs</rt></ruby>》的教科书。这本书用 Scheme(一种 Lisp 方言)向读者们示范了如何编程。它被用于教授麻省理工入门编程课程长达二十年之久。出于直觉,我认为 SICP(这本书的名字通常缩写为 SICP)倍增了 Lisp 的“神秘要素”。SICP 使用 Lisp 描绘了深邃得几乎可以称之为哲学的编程理念。这些理念非常普适,可以用任意一种编程语言展现;但 SICP 的作者们选择了 Lisp。结果,这本阴阳怪气、卓越不凡、吸引了好几代程序员(还成了一种[奇特的模因][16])的著作臭名远扬之后,Lisp 的声望也顺带被提升了。Lisp 已不仅仅是一如既往的“麦卡锡的优雅表达方式”;它现在还成了“向你传授编程的不传之秘的语言”。
|
||||
|
||||
SICP 究竟有多奇怪这一点值得好好说;因为我认为,时至今日,这本书的古怪之处和 Lisp 的古怪之处是相辅相成的。书的封面就透着一股古怪。那上面画着一位朝着桌子走去,准备要施法的巫师或者炼金术士。他的一只手里抓着一副测径仪 —— 或者圆规,另一只手上拿着个球,上书“eval”和“apply”。他对面的女人指着桌子;在背景中,希腊字母 λ (lambda)漂浮在半空,释放出光芒。
|
||||
|
||||
![SICP 封面上的画作][17]
|
||||
|
||||
*SICP 封面上的画作。*
|
||||
|
||||
说真的,这上面画的究竟是怎么一回事?为什么桌子会长着动物的腿?为什么这个女人指着桌子?墨水瓶又是干什么用的?我们是不是该说,这位巫师已经破译了宇宙的隐藏奥秘,而所有这些奥秘就蕴含在 eval/apply 循环和 Lambda 演算之中?看似就是如此。单单是这张图片,就一定对人们如今谈论 Lisp 的方式产生了难以计量的影响。
|
||||
|
||||
然而,这本书的内容通常并不比封面正常多少。SICP 跟你读过的所有计算机科学教科书都不同。在引言中,作者们表示,这本书不只教你怎么用 Lisp 编程 —— 它是关于“现象的三个焦点:人的心智、复数的计算机程序,和计算机”的作品 [^19]。在之后,他们对此进行了解释,描述了他们对如下观点的坚信:编程不该被当作是一种计算机科学的训练,而应该是“<ruby>程序性认识论<rt>procedural epistemology</rt></ruby>”的一种新表达方式 [^20]。程序是将那些偶然被送入计算机的思想组织起来的全新方法。这本书的第一章简明地介绍了 Lisp,但是之后的绝大部分都在讲述更加抽象的概念。其中包括了对不同编程范式的讨论,对于面向对象系统中“时间”和“一致性”的讨论;在书中的某一处,还有关于通信的基本限制可能会如何带来同步问题的讨论 —— 而这些基本限制在通信中就像是光速不变在相对论中一样关键 [^21]。都是些高深难懂的东西。
|
||||
|
||||
以上这些并不是说这是本糟糕的书;这本书其实棒极了。在我读过的所有作品中,这本书对于重要的编程理念的讨论是最为深刻的;那些理念我琢磨了很久,却一直无力用文字去表达。一本入门编程教科书能如此迅速地开始描述面向对象编程的根本缺陷,和函数式语言“将可变状态降到最少”的优点,实在是一件让人印象深刻的事。而这种描述之后变为了另一种震撼人心的讨论:某种(可能类似于今日的 [RxJS][18] 的)流范式能如何同时具备两者的优秀特性。SICP 用和当初麦卡锡的 Lisp 论文相似的方式提纯出了高级程序设计的精华。你读完这本书之后,会立即想要将它推荐给你的程序员朋友们;如果他们找到这本书,看到了封面,但最终没有阅读的话,他们就只会记住长着动物腿的桌子上方那神秘的、根本的、给予魔法师特殊能力的、写着 eval/apply 的东西。话说回来,书上这两人的鞋子也让我印象颇深。
|
||||
|
||||
然而,SICP 最重要的影响恐怕是,它将 Lisp 由一门怪语言提升成了必要的教学工具。在 SICP 面世之前,人们互相推荐 Lisp,以学习这门语言为提升编程技巧的途径。1979 年的 Byte 杂志 Lisp 特刊印证了这一事实。之前提到的那位编辑不仅就麻省理工的新 Lisp 计算机大书特书,还说,Lisp 这门语言值得一学,因为它“代表了分析问题的另一种视角” [^22]。但 SICP 并未只把 Lisp 作为其它语言的陪衬来使用;SICP 将其作为*入门*语言。这就暗含了一种论点,那就是,Lisp 是最能把握计算机编程基础的语言。可以认为,如今的程序员们彼此怂恿“在死掉之前至少试试 Lisp”的时候,他们很大程度上是因为 SICP 才这么说的。毕竟,编程语言 [Brainfuck][19] 想必同样也提供了“分析问题的另一种视角”;但人们学习 Lisp 而非学习 Brainfuck,那是因为他们知道,前者的那种 Lisp 视角在二十年中都被看作是极其有用的,有用到麻省理工在给他们的本科生教其它语言之前,必然会先教 Lisp。
|
||||
|
||||
### Lisp 的回归
|
||||
|
||||
在 SICP 出版的同一年,<ruby>本贾尼·斯特劳斯特卢普<rt>Bjarne Stroustrup</rt></ruby>发布了 C++ 语言的首个版本,它将面向对象编程带到了大众面前。几年之后,Lisp 计算机的市场崩盘,AI 寒冬开始了。在下一个十年的变革中, C++ 和后来的 Java 成了前途无量的语言,而 Lisp 被冷落,无人问津。
|
||||
|
||||
理所当然地,确定人们对 Lisp 重新燃起热情的具体时间并不可能;但这多半是保罗·格雷厄姆发表他那几篇声称 Lisp 是首选入门语言的短文之后的事了。保罗·格雷厄姆是 Y-Combinator 的联合创始人和《Hacker News》的创始者,他这几篇短文有很大的影响力。例如,在短文《<ruby>[胜于平庸][20]<rt>Beating the Averages</rt></ruby>》中,他声称 Lisp 宏使 Lisp 比其它语言更强。他说,因为他在自己创办的公司 Viaweb 中使用 Lisp,他得以比竞争对手更快地推出新功能。至少,[一部分程序员][21]被说服了。然而,庞大的主流程序员群体并未换用 Lisp。
|
||||
|
||||
实际上出现的情况是,Lisp 并未流行,但越来越多 Lisp 式的特性被加入到广受欢迎的语言中。Python 有了列表推导式。C# 有了 Linq。Ruby……嗯,[Ruby 是 Lisp 的一种][22]。就如格雷厄姆之前在 2001 年提到的那样,“在一系列常用语言中所体现出的‘默认语言’正越发朝着 Lisp 的方向演化” [^23]。尽管其它语言变得越来越像 Lisp,Lisp 本身仍然保留了其作为“很少人了解但是大家都该学的神秘语言”的特殊声望。在 1980 年,Lisp 的诞生二十周年纪念日上,麦卡锡写道,Lisp 之所以能够存活这么久,是因为它具备“编程语言领域中的某种近似局部最优” [^24]。这句话并未充分地表明 Lisp 的真正影响力。Lisp 能够存活超过半个世纪之久,并非因为程序员们一年年地勉强承认它就是最好的编程工具;事实上,即使绝大多数程序员根本不用它,它还是存活了下来。多亏了它的起源和它的人工智能研究用途,说不定还要多亏 SICP 的遗产,Lisp 一直都那么让人着迷。在我们能够想象上帝用其它新的编程语言创造世界之前,Lisp 都不会走下神坛。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
[^1]: John McCarthy, “History of Lisp”, 14, Stanford University, February 12, 1979, accessed October 14, 2018, http://jmc.stanford.edu/articles/lisp/lisp.pdf
|
||||
|
||||
[^2]: Paul Graham, “The Roots of Lisp”, 1, January 18, 2002, accessed October 14, 2018, http://languagelog.ldc.upenn.edu/myl/llog/jmc.pdf.
|
||||
|
||||
[^3]: Martin Childs, “John McCarthy: Computer scientist known as the father of AI”, The Independent, November 1, 2011, accessed on October 14, 2018, https://www.independent.co.uk/news/obituaries/john-mccarthy-computer-scientist-known-as-the-father-of-ai-6255307.html.
|
||||
|
||||
[^4]: Lisp Bulletin History. http://www.artinfo-musinfo.org/scans/lb/lb3f.pdf
|
||||
|
||||
[^5]: Allen Newell and Herbert Simon, “Current Developments in Complex Information Processing,” 19, May 1, 1956, accessed on October 14, 2018, http://bitsavers.org/pdf/rand/ipl/P-850_Current_Developments_In_Complex_Information_Processing_May56.pdf.
|
||||
|
||||
[^6]: ibid.
|
||||
|
||||
[^7]: Herbert Stoyan, “Lisp History”, 43, Lisp Bulletin #3, December 1979, accessed on October 14, 2018, http://www.artinfo-musinfo.org/scans/lb/lb3f.pdf
|
||||
|
||||
[^8]: McCarthy, “History of Lisp”, 5.
|
||||
|
||||
[^9]: ibid.
|
||||
|
||||
[^10]: McCarthy “History of Lisp”, 6.
|
||||
|
||||
[^11]: Stoyan, “Lisp History”, 45
|
||||
|
||||
[^12]: McCarthy, “History of Lisp”, 8.
|
||||
|
||||
[^13]: McCarthy, “History of Lisp”, 2.
|
||||
|
||||
[^14]: McCarthy, “History of Lisp”, 8.
|
||||
|
||||
[^15]: Graham, “The Roots of Lisp”, 11.
|
||||
|
||||
[^16]: Guy Steele and Richard Gabriel, “The Evolution of Lisp”, 22, History of Programming Languages 2, 1993, accessed on October 14, 2018, http://www.dreamsongs.com/Files/HOPL2-Uncut.pdf. 2
|
||||
|
||||
[^17]: Carl Helmers, “Editorial”, Byte Magazine, 154, August 1979, accessed on October 14, 2018, https://archive.org/details/byte-magazine-1979-08/page/n153.
|
||||
|
||||
[^18]: Patrick Winston, “The Lisp Revolution”, 209, April 1985, accessed on October 14, 2018, https://archive.org/details/byte-magazine-1985-04/page/n207.
|
||||
|
||||
[^19]: Harold Abelson, Gerald Jay. Sussman, and Julie Sussman, Structure and Interpretation of Computer Programs (Cambridge, Mass: MIT Press, 2010), xiii.
|
||||
|
||||
[^20]: Abelson, xxiii.
|
||||
|
||||
[^21]: Abelson, 428.
|
||||
|
||||
[^22]: Helmers, 7.
|
||||
|
||||
[^23]: Paul Graham, “What Made Lisp Different”, December 2001, accessed on October 14, 2018, http://www.paulgraham.com/diff.html.
|
||||
|
||||
[^24]: John McCarthy, “Lisp—Notes on its past and future”, 3, Stanford University, 1980, accessed on October 14, 2018, http://jmc.stanford.edu/articles/lisp20th/lisp20th.pdf.
|
||||
|
||||
via: https://twobithistory.org/2018/10/14/lisp.html
|
||||
|
||||
作者:[Two-Bit History][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Northurland](https://github.com/Northurland)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://twobithistory.org
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://xkcd.com/224/
|
||||
[2]: https://xkcd.com/297/
|
||||
[3]: https://www.gnu.org/fun/jokes/eternal-flame.en.html
|
||||
[4]: https://www.reddit.com/r/ProgrammerHumor/comments/5c14o6/xkcd_lisp/d9szjnc/
|
||||
[5]: https://twobithistory.org/images/byte_lisp.jpg
|
||||
[6]: http://languagelog.ldc.upenn.edu/myl/llog/jmc.pdf
|
||||
[7]: https://en.wikipedia.org/wiki/Jargon_File
|
||||
[8]: https://hci.stanford.edu/winograd/shrdlu/
|
||||
[9]: https://en.wikipedia.org/wiki/Macsyma
|
||||
[10]: https://en.wikipedia.org/wiki/ACL2
|
||||
[11]: https://twobithistory.org/2018/09/30/chaosnet.html
|
||||
[12]: https://youtu.be/gV5obrYaogU?t=201
|
||||
[13]: https://en.wikipedia.org/wiki/Flavors_(programming_language)
|
||||
[14]: https://twobithistory.org/images/symbolics.jpg
|
||||
[15]: http://www.softwarepreservation.org/projects/LISP/
|
||||
[16]: https://knowyourmeme.com/forums/meme-research/topics/47038-structure-and-interpretation-of-computer-programs-hugeass-image-dump-for-evidence
|
||||
[17]: https://twobithistory.org/images/sicp.jpg
|
||||
[18]: https://rxjs-dev.firebaseapp.com/
|
||||
[19]: https://en.wikipedia.org/wiki/Brainfuck
|
||||
[20]: http://www.paulgraham.com/avg.html
|
||||
[21]: https://web.archive.org/web/20061004035628/http://wiki.alu.org/Chris-Perkins
|
||||
[22]: http://www.randomhacks.net/2005/12/03/why-ruby-is-an-acceptable-lisp/
|
||||
@@ -0,0 +1,247 @@
|
||||
如何使用 chkconfig 和 systemctl 命令启用或禁用 Linux 服务
|
||||
======
|
||||
|
||||
对于 Linux 管理员来说这是一个重要(美妙)的话题,所以每个人都必须知道,并练习怎样才能更高效的使用它们。
|
||||
|
||||
在 Linux 中,无论何时当你安装任何带有服务和守护进程的包,系统默认会把这些服务的初始化及 systemd 脚本添加进去,不过此时它们并没有被启用。
|
||||
|
||||
我们需要手动的开启或者关闭那些服务。Linux 中有三个著名的且一直在被使用的初始化系统。
|
||||
|
||||
### 什么是初始化系统?
|
||||
|
||||
在以 Linux/Unix 为基础的操作系统上,`init` (初始化的简称) 是内核引导系统启动过程中第一个启动的进程。
|
||||
|
||||
`init` 的进程 id (pid)是 1,除非系统关机否则它将会一直在后台运行。
|
||||
|
||||
`init` 首先根据 `/etc/inittab` 文件决定 Linux 运行的级别,然后根据运行级别在后台启动所有其他进程和应用程序。
|
||||
|
||||
BIOS、MBR、GRUB 和内核程序在启动 `init` 之前就作为 Linux 的引导程序的一部分开始工作了。
|
||||
|
||||
下面是 Linux 中可以使用的运行级别(从 0~6 总共七个运行级别):
|
||||
|
||||
* `0`:关机
|
||||
* `1`:单用户模式
|
||||
* `2`:多用户模式(没有NFS)
|
||||
* `3`:完全的多用户模式
|
||||
* `4`:系统未使用
|
||||
* `5`:图形界面模式
|
||||
* `6`:重启
|
||||
|
||||
下面是 Linux 系统中最常用的三个初始化系统:
|
||||
|
||||
* System V(Sys V)
|
||||
* Upstart
|
||||
* systemd
|
||||
|
||||
### 什么是 System V(Sys V)?
|
||||
|
||||
System V(Sys V)是类 Unix 系统第一个也是传统的初始化系统。`init` 是内核引导系统启动过程中第一支启动的程序,它是所有程序的父进程。
|
||||
|
||||
大部分 Linux 发行版最开始使用的是叫作 System V(Sys V)的传统的初始化系统。在过去的几年中,已经发布了好几个初始化系统以解决标准版本中的设计限制,例如:launchd、Service Management Facility、systemd 和 Upstart。
|
||||
|
||||
但是 systemd 已经被几个主要的 Linux 发行版所采用,以取代传统的 SysV 初始化系统。
|
||||
|
||||
### 什么是 Upstart?
|
||||
|
||||
Upstart 是一个基于事件的 `/sbin/init` 守护进程的替代品,它在系统启动过程中处理任务和服务的启动,在系统运行期间监视它们,在系统关机的时候关闭它们。
|
||||
|
||||
它最初是为 Ubuntu 而设计,但是它也能够完美的部署在其他所有 Linux系统中,用来代替古老的 System-V。
|
||||
|
||||
Upstart 被用于 Ubuntu 从 9.10 到 Ubuntu 14.10 和基于 RHEL 6 的系统,之后它被 systemd 取代。
|
||||
|
||||
### 什么是 systemd?
|
||||
|
||||
systemd 是一个新的初始化系统和系统管理器,它被用于所有主要的 Linux 发行版,以取代传统的 SysV 初始化系统。
|
||||
|
||||
systemd 兼容 SysV 和 LSB 初始化脚本。它可以直接替代 SysV 初始化系统。systemd 是被内核启动的第一个程序,它的 PID 是 1。
|
||||
|
||||
systemd 是所有程序的父进程,Fedora 15 是第一个用 systemd 取代 upstart 的发行版。`systemctl` 用于命令行,它是管理 systemd 的守护进程/服务的主要工具,例如:(开启、重启、关闭、启用、禁用、重载和状态)
|
||||
|
||||
systemd 使用 .service 文件而不是 bash 脚本(SysVinit 使用的)。systemd 将所有守护进程添加到 cgroups 中排序,你可以通过浏览 `/cgroup/systemd` 文件查看系统等级。
|
||||
|
||||
### 如何使用 chkconfig 命令启用或禁用引导服务?
|
||||
|
||||
`chkconfig` 实用程序是一个命令行工具,允许你在指定运行级别下启动所选服务,以及列出所有可用服务及其当前设置。
|
||||
|
||||
此外,它还允许我们从启动中启用或禁用服务。前提是你有超级管理员权限(root 或者 `sudo`)运行这个命令。
|
||||
|
||||
所有的服务脚本位于 `/etc/rd.d/init.d`文件中
|
||||
|
||||
### 如何列出运行级别中所有的服务
|
||||
|
||||
`--list` 参数会展示所有的服务及其当前状态(启用或禁用服务的运行级别):
|
||||
|
||||
```
|
||||
# chkconfig --list
|
||||
NetworkManager 0:off 1:off 2:on 3:on 4:on 5:on 6:off
|
||||
abrt-ccpp 0:off 1:off 2:off 3:on 4:off 5:on 6:off
|
||||
abrtd 0:off 1:off 2:off 3:on 4:off 5:on 6:off
|
||||
acpid 0:off 1:off 2:on 3:on 4:on 5:on 6:off
|
||||
atd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
|
||||
auditd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
|
||||
.
|
||||
.
|
||||
```
|
||||
|
||||
### 如何查看指定服务的状态
|
||||
|
||||
如果你想查看运行级别下某个服务的状态,你可以使用下面的格式匹配出需要的服务。
|
||||
|
||||
比如说我想查看运行级别中 `auditd` 服务的状态
|
||||
|
||||
```
|
||||
# chkconfig --list| grep auditd
|
||||
auditd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
|
||||
```
|
||||
|
||||
### 如何在指定运行级别中启用服务
|
||||
|
||||
使用 `--level` 参数启用指定运行级别下的某个服务,下面展示如何在运行级别 3 和运行级别 5 下启用 `httpd` 服务。
|
||||
|
||||
|
||||
```
|
||||
# chkconfig --level 35 httpd on
|
||||
```
|
||||
|
||||
### 如何在指定运行级别下禁用服务
|
||||
|
||||
同样使用 `--level` 参数禁用指定运行级别下的服务,下面展示的是在运行级别 3 和运行级别 5 中禁用 `httpd` 服务。
|
||||
|
||||
```
|
||||
# chkconfig --level 35 httpd off
|
||||
```
|
||||
|
||||
### 如何将一个新服务添加到启动列表中
|
||||
|
||||
`-–add` 参数允许我们添加任何新的服务到启动列表中,默认情况下,新添加的服务会在运行级别 2、3、4、5 下自动开启。
|
||||
|
||||
```
|
||||
# chkconfig --add nagios
|
||||
```
|
||||
|
||||
### 如何从启动列表中删除服务
|
||||
|
||||
可以使用 `--del` 参数从启动列表中删除服务,下面展示的是如何从启动列表中删除 Nagios 服务。
|
||||
|
||||
```
|
||||
# chkconfig --del nagios
|
||||
```
|
||||
|
||||
### 如何使用 systemctl 命令启用或禁用开机自启服务?
|
||||
|
||||
`systemctl` 用于命令行,它是一个用来管理 systemd 的守护进程/服务的基础工具,例如:(开启、重启、关闭、启用、禁用、重载和状态)。
|
||||
|
||||
所有服务创建的 unit 文件位与 `/etc/systemd/system/`。
|
||||
|
||||
### 如何列出全部的服务
|
||||
|
||||
使用下面的命令列出全部的服务(包括启用的和禁用的)。
|
||||
|
||||
```
|
||||
# systemctl list-unit-files --type=service
|
||||
UNIT FILE STATE
|
||||
arp-ethers.service disabled
|
||||
auditd.service enabled
|
||||
autovt@.service enabled
|
||||
blk-availability.service disabled
|
||||
brandbot.service static
|
||||
chrony-dnssrv@.service static
|
||||
chrony-wait.service disabled
|
||||
chronyd.service enabled
|
||||
cloud-config.service enabled
|
||||
cloud-final.service enabled
|
||||
cloud-init-local.service enabled
|
||||
cloud-init.service enabled
|
||||
console-getty.service disabled
|
||||
console-shell.service disabled
|
||||
container-getty@.service static
|
||||
cpupower.service disabled
|
||||
crond.service enabled
|
||||
.
|
||||
.
|
||||
150 unit files listed.
|
||||
```
|
||||
|
||||
使用下面的格式通过正则表达式匹配出你想要查看的服务的当前状态。下面是使用 `systemctl` 命令查看 `httpd` 服务的状态。
|
||||
|
||||
```
|
||||
# systemctl list-unit-files --type=service | grep httpd
|
||||
httpd.service disabled
|
||||
```
|
||||
|
||||
### 如何让指定的服务开机自启
|
||||
|
||||
使用下面格式的 `systemctl` 命令启用一个指定的服务。启用服务将会创建一个符号链接,如下可见:
|
||||
|
||||
```
|
||||
# systemctl enable httpd
|
||||
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
|
||||
```
|
||||
|
||||
运行下列命令再次确认服务是否被启用。
|
||||
|
||||
```
|
||||
# systemctl is-enabled httpd
|
||||
enabled
|
||||
```
|
||||
|
||||
### 如何禁用指定的服务
|
||||
|
||||
运行下面的命令禁用服务将会移除你启用服务时所创建的符号链接。
|
||||
|
||||
```
|
||||
# systemctl disable httpd
|
||||
Removed symlink /etc/systemd/system/multi-user.target.wants/httpd.service.
|
||||
```
|
||||
|
||||
运行下面的命令再次确认服务是否被禁用。
|
||||
|
||||
```
|
||||
# systemctl is-enabled httpd
|
||||
disabled
|
||||
```
|
||||
|
||||
### 如何查看系统当前的运行级别
|
||||
|
||||
使用 `systemctl` 命令确认你系统当前的运行级别,`runlevel` 命令仍然可在 systemd 下工作,不过,运行级别对于 systemd 来说是一个历史遗留的概念。所以我建议你全部使用 `systemctl` 命令。
|
||||
|
||||
我们当前处于运行级别 3, 它等同于下面显示的 `multi-user.target`。
|
||||
|
||||
```
|
||||
# systemctl list-units --type=target
|
||||
UNIT LOAD ACTIVE SUB DESCRIPTION
|
||||
basic.target loaded active active Basic System
|
||||
cloud-config.target loaded active active Cloud-config availability
|
||||
cryptsetup.target loaded active active Local Encrypted Volumes
|
||||
getty.target loaded active active Login Prompts
|
||||
local-fs-pre.target loaded active active Local File Systems (Pre)
|
||||
local-fs.target loaded active active Local File Systems
|
||||
multi-user.target loaded active active Multi-User System
|
||||
network-online.target loaded active active Network is Online
|
||||
network-pre.target loaded active active Network (Pre)
|
||||
network.target loaded active active Network
|
||||
paths.target loaded active active Paths
|
||||
remote-fs.target loaded active active Remote File Systems
|
||||
slices.target loaded active active Slices
|
||||
sockets.target loaded active active Sockets
|
||||
swap.target loaded active active Swap
|
||||
sysinit.target loaded active active System Initialization
|
||||
timers.target loaded active active Timers
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
via: https://www.2daygeek.com/how-to-enable-or-disable-services-on-boot-in-linux-using-chkconfig-and-systemctl-command/
|
||||
|
||||
|
||||
作者:[Prakash Subramanian][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[way-ww](https://github.com/way-ww)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
|
||||
[a]: https://www.2daygeek.com/author/prakash/
|
||||
[b]: https://github.com/lujun9972
|
||||
@@ -1,9 +1,9 @@
|
||||
Chrony – 一个类 Unix 系统可选的 NTP 客户端和服务器
|
||||
Chrony:一个类 Unix 系统上 NTP 客户端和服务器替代品
|
||||
======
|
||||
|
||||

|
||||
|
||||
在这个教程中,我们会讨论如何安装和配置 **Chrony**,一个类 Unix 系统上可选的 NTP 客户端和服务器。Chrony 可以更快的同步系统时钟,具有更好的时钟准确度,并且它对于那些不是一直在线的系统很有帮助。Chrony 是免费、开源的,并且支持 GNU/Linux 和 BSD 衍生版比如 FreeBSD,NetBSD,macOS 和 Solaris 等。
|
||||
在这个教程中,我们会讨论如何安装和配置 **Chrony**,一个类 Unix 系统上 NTP 客户端和服务器的替代品。Chrony 可以更快的同步系统时钟,具有更好的时钟准确度,并且它对于那些不是一直在线的系统很有帮助。Chrony 是自由开源的,并且支持 GNU/Linux 和 BSD 衍生版(比如 FreeBSD、NetBSD)、macOS 和 Solaris 等。
|
||||
|
||||
### 安装 Chrony
|
||||
|
||||
@@ -13,7 +13,7 @@ Chrony 可以从大多数 Linux 发行版的默认软件库中获得。如果你
|
||||
$ sudo pacman -S chrony
|
||||
```
|
||||
|
||||
在 Debian,Ubuntu,Linux Mint 上:
|
||||
在 Debian、Ubuntu、Linux Mint 上:
|
||||
|
||||
```
|
||||
$ sudo apt-get install chrony
|
||||
@@ -25,7 +25,7 @@ $ sudo apt-get install chrony
|
||||
$ sudo dnf install chrony
|
||||
```
|
||||
|
||||
当安装完成后,如果之前没有启动过的话需启动 **chronyd.service** 守护进程:
|
||||
当安装完成后,如果之前没有启动过的话需启动 `chronyd.service` 守护进程:
|
||||
|
||||
```
|
||||
$ sudo systemctl start chronyd.service
|
||||
@@ -37,7 +37,7 @@ $ sudo systemctl start chronyd.service
|
||||
$ sudo systemctl enable chronyd.service
|
||||
```
|
||||
|
||||
为了确认 Chronyd.service 已经启动,运行:
|
||||
为了确认 `chronyd.service` 已经启动,运行:
|
||||
|
||||
```
|
||||
$ sudo systemctl status chronyd.service
|
||||
@@ -71,7 +71,7 @@ Oct 17 10:35:06 ubuntuserver chronyd[2482]: Selected source 106.10.186.200
|
||||
|
||||
### 配置 Chrony
|
||||
|
||||
NTP 客户端需要知道它要连接到哪个 NTP 服务器来获取当前时间。我们可以直接在 NTP 配置文件中的 **server** 或者 **pool** 项指定 NTP 服务器。通常,默认的配置文件位于 **/etc/chrony/chrony.conf** 或者 **/etc/chrony.conf**,取决于 Linux 发行版版本。为了更可靠的时间同步,建议指定至少三个服务器。
|
||||
NTP 客户端需要知道它要连接到哪个 NTP 服务器来获取当前时间。我们可以直接在该 NTP 配置文件中的 `server` 或者 `pool` 项指定 NTP 服务器。通常,默认的配置文件位于 `/etc/chrony/chrony.conf` 或者 `/etc/chrony.conf`,取决于 Linux 发行版版本。为了更可靠的同步时间,建议指定至少三个服务器。
|
||||
|
||||
下面几行是我的 Ubuntu 18.04 LTS 服务器上的一个示例。
|
||||
|
||||
@@ -87,19 +87,19 @@ pool 2.ubuntu.pool.ntp.org iburst maxsources 2
|
||||
[...]
|
||||
```
|
||||
|
||||
从上面的输出中你可以看到,[**NTP Pool Project**][1] 已经被设置成为了默认的时间服务器。对于那些好奇的人,NTP Pool project 是一个时间服务器集群,用来为全世界千万个客户端提供 NTP 服务。它是 Ubuntu 以及其他主流 Linux 发行版的默认时间服务器。
|
||||
从上面的输出中你可以看到,[NTP 服务器池项目][1] 已经被设置成为了默认的时间服务器。对于那些好奇的人,NTP 服务器池项目是一个时间服务器集群,用来为全世界千万个客户端提供 NTP 服务。它是 Ubuntu 以及其他主流 Linux 发行版的默认时间服务器。
|
||||
|
||||
在这里,
|
||||
* **iburst** 选项用来加速初始的同步过程
|
||||
* **maxsources** 代表 NTP 源的最大数量
|
||||
* `iburst` 选项用来加速初始的同步过程
|
||||
* `maxsources` 代表 NTP 源的最大数量
|
||||
|
||||
请确保你选择的 NTP 服务器是同步的、稳定的、离你的位置较近的,以便使用这些 NTP 源来提升时间准确度。
|
||||
|
||||
### 在命令行中管理 Chronyd
|
||||
|
||||
Chrony 有一个命令行工具叫做 **chronyc** 用来控制和监控 **chrony** 守护进程(chronyd)。
|
||||
chrony 有一个命令行工具叫做 `chronyc` 用来控制和监控 chrony 守护进程(`chronyd`)。
|
||||
|
||||
为了检查是否 **chrony** 已经同步,我们可以使用下面展示的 **tracking** 命令。
|
||||
为了检查是否 chrony 已经同步,我们可以使用下面展示的 `tracking` 命令。
|
||||
|
||||
```
|
||||
$ chronyc tracking
|
||||
@@ -135,7 +135,7 @@ MS Name/IP address Stratum Poll Reach LastRx Last sample
|
||||
^- ns2.pulsation.fr 2 10 377 311 -75ms[ -73ms] +/- 250ms
|
||||
```
|
||||
|
||||
Chronyc 工具可以对每个源进行统计,比如使用 **sourcestats** 命令获得漂移速率和进行偏移估计。
|
||||
`chronyc` 工具可以对每个源进行统计,比如使用 `sourcestats` 命令获得漂移速率和进行偏移估计。
|
||||
|
||||
```
|
||||
$ chronyc sourcestats
|
||||
@@ -152,7 +152,7 @@ sin1.m-d.net 29 13 83m +0.049 6.060 -8466us 9940us
|
||||
ns2.pulsation.fr 32 17 88m +0.784 9.834 -62ms 22ms
|
||||
```
|
||||
|
||||
如果你的系统没有连接到 Internet,你需要告知 Chrony 系统没有连接到 Internet。为了这样做,运行:
|
||||
如果你的系统没有连接到互联网,你需要告知 Chrony 系统没有连接到 互联网。为了这样做,运行:
|
||||
|
||||
```
|
||||
$ sudo chronyc offline
|
||||
@@ -174,7 +174,7 @@ $ chronyc activity
|
||||
|
||||
可以看到,我的所有源此时都是离线状态。
|
||||
|
||||
一旦你连接到 Internet,只需要使用命令告知 Chrony 你的系统已经回到在线状态:
|
||||
一旦你连接到互联网,只需要使用命令告知 Chrony 你的系统已经回到在线状态:
|
||||
|
||||
```
|
||||
$ sudo chronyc online
|
||||
@@ -193,11 +193,10 @@ $ chronyc activity
|
||||
0 sources with unknown address
|
||||
```
|
||||
|
||||
所有选项和参数的详细解释,请参考帮助手册。
|
||||
所有选项和参数的详细解释,请参考其帮助手册。
|
||||
|
||||
```
|
||||
$ man chronyc
|
||||
|
||||
$ man chronyd
|
||||
```
|
||||
|
||||
@@ -206,7 +205,6 @@ $ man chronyd
|
||||
保持关注!
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/chrony-an-alternative-ntp-client-and-server-for-unix-like-systems/
|
||||
@@ -214,7 +212,7 @@ via: https://www.ostechnix.com/chrony-an-alternative-ntp-client-and-server-for-u
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[zianglei](https://github.com/zianglei)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
设计更快的网页(二):图片替换
|
||||
======
|
||||

|
||||
|
||||

|
||||
|
||||
欢迎回到我们为了构建更快网页所写的系列文章。上一篇[文章][1]讨论了只通过图片压缩实现这个目标的方法。这个例子从一开始有 1.2MB 的“浏览器脂肪”,然后它减轻到了 488.9KB 的大小。但这还不够快!那么本文继续来给浏览器“减肥”。你可能在这个过程中会认为我们所做的事情有点疯狂,但一旦完成,你就会明白为什么要这么做了。
|
||||
|
||||
@@ -21,17 +21,15 @@ $ sudo dnf install inkscape
|
||||
|
||||
![Getfedora 的页面,对其中的图片做了标记][5]
|
||||
|
||||
这次分析更好地以图形方式完成,这也就是它从屏幕截图开始的原因。上面的截图标记了页面中的所有图形元素。Fedora 网站团队已经针对两种情况措施(也有可能是四种,这样更好)来替换图像了。社交媒体的图标变成了字体的字形,而语言选择器变成了 SVG.
|
||||
这次分析以图形方式完成更好,这也就是它从屏幕截图开始的原因。上面的截图标记了页面中的所有图形元素。Fedora 网站团队已经针对两种情况措施(也有可能是四种,这样更好)来替换图像了。社交媒体的图标变成了字体的字形,而语言选择器变成了 SVG.
|
||||
|
||||
我们有几个可以替换的选择:
|
||||
|
||||
|
||||
+ CSS3
|
||||
+ 字体
|
||||
+ SVG
|
||||
+ HTML5 Canvas
|
||||
|
||||
|
||||
#### HTML5 Canvas
|
||||
|
||||
简单来说,HTML5 Canvas 是一种 HTML 元素,它允许你借助脚本语言(通常是 JavaScript)在上面绘图,不过它现在还没有被广泛使用。因为它可以使用脚本语言来绘制,所以这个元素也可以用来做动画。这里有一些使用 HTML Canvas 实现的实例,比如[三角形模式][6]、[动态波浪][7]和[字体动画][8]。不过,在这种情况下,似乎这也不是最好的选择。
|
||||
@@ -42,7 +40,7 @@ $ sudo dnf install inkscape
|
||||
|
||||
#### 字体
|
||||
|
||||
另外一种方式是使用字体来装饰网页,[Fontawesome][9] 在这方面很流行。比如,在这个例子中你可以使用字体来替换“风味”和“旋转”的图标。这种方法有一个负面影响,但解决起来很容易,我们会在本系列的下一部分中来介绍。
|
||||
另外一种方式是使用字体来装饰网页,[Fontawesome][9] 在这方面很流行。比如,在这个例子中你可以使用字体来替换“Flavor”和“Spin”的图标。这种方法有一个负面影响,但解决起来很容易,我们会在本系列的下一部分中来介绍。
|
||||
|
||||
#### SVG
|
||||
|
||||
@@ -94,13 +92,13 @@ inkscape:connector-curvature="0" />
|
||||
|
||||
![Inkscape - 激活节点工具][10]
|
||||
|
||||
这个例子中有五个不必要的节点——就是直线中间的那些。要删除它们,你可以使用已激活的节点工具依次选中它们,并按下 **Del** 键。然后,选中这条线的定义节点,并使用工具栏的工具把它们重新做成角。
|
||||
这个例子中有五个不必要的节点——就是直线中间的那些。要删除它们,你可以使用已激活的节点工具依次选中它们,并按下 `Del` 键。然后,选中这条线的定义节点,并使用工具栏的工具把它们重新做成角。
|
||||
|
||||
![Inkscape - 将节点变成角的工具][11]
|
||||
|
||||
如果不修复这些角,我们还有方法可以定义这条曲线,这条曲线会被保存,也就会增加文件体积。你可以手动清理这些节点,因为它无法有效的自动完成。现在,你已经为下一阶段做好了准备。
|
||||
|
||||
使用_另存为_功能,并选择_优化的 SVG_。这会弹出一个窗口,你可以在里面选择移除或保留哪些成分。
|
||||
使用“另存为”功能,并选择“优化的 SVG”。这会弹出一个窗口,你可以在里面选择移除或保留哪些成分。
|
||||
|
||||
![Inkscape - “另存为”“优化的 SVG”][12]
|
||||
|
||||
@@ -121,7 +119,7 @@ insgesamt 928K
|
||||
-rw-rw-r--. 1 user user 112K 19. Feb 19:05 greyscale-pattern-opti.svg.gz
|
||||
```
|
||||
|
||||
这是我为可视化这个主题所做的一个小测试的输出。你可能应该看到光栅图形——PNG——已经被压缩,不能再被压缩了。而 SVG,一个 XML 文件正相反。它是文本文件,所以可被压缩至原来的四分之一不到。因此,现在它的体积要比 PNG 小 50 KB 左右。
|
||||
这是我为可视化这个主题所做的一个小测试的输出。你可能应该看到光栅图形——PNG——已经被压缩,不能再被压缩了。而 SVG,它是一个 XML 文件正相反。它是文本文件,所以可被压缩至原来的四分之一不到。因此,现在它的体积要比 PNG 小 50 KB 左右。
|
||||
|
||||
现代浏览器可以以原生方式处理压缩文件。所以,许多 Web 服务器都打开了 mod_deflate (Apache) 和 gzip (Nginx) 模式。这样我们就可以在传输过程中节省空间。你可以在[这儿][13]看看你的服务器是不是启用了它。
|
||||
|
||||
@@ -129,18 +127,16 @@ insgesamt 928K
|
||||
|
||||
首先,没有人希望每次都要用 Inkscape 来优化 SVG. 你可以在命令行中脱离 GUI 来运行 Inkscape,但你找不到选项来将 Inkscape SVG 转换成优化的 SVG. 用这种方式只能导出光栅图像。但是我们替代品:
|
||||
|
||||
* SVGO (看起来开发过程已经不活跃了)
|
||||
* Scour
|
||||
* SVGO (看起来开发过程已经不活跃了)
|
||||
* Scour
|
||||
|
||||
|
||||
|
||||
本例中我们使用 scour 来进行优化。先来安装它:
|
||||
本例中我们使用 `scour` 来进行优化。先来安装它:
|
||||
|
||||
```
|
||||
$ sudo dnf install scour
|
||||
```
|
||||
|
||||
要想自动优化 SVG 文件,请运行 scour,就像这样:
|
||||
要想自动优化 SVG 文件,请运行 `scour`,就像这样:
|
||||
|
||||
```
|
||||
[user@localhost ]$ scour INPUT.svg OUTPUT.svg -p 3 --create-groups --renderer-workaround --strip-xml-prolog --remove-descriptive-elements --enable-comment-stripping --disable-embed-rasters --no-line-breaks --enable-id-stripping --shorten-ids
|
||||
@@ -156,13 +152,13 @@ via: https://fedoramagazine.org/design-faster-web-pages-part-2-image-replacement
|
||||
作者:[Sirko Kemter][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[StdioA](https://github.com/StdioA)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/gnokii/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://wp.me/p3XX0v-5fJ
|
||||
[1]: https://linux.cn/article-10166-1.html
|
||||
[2]: https://fedoramagazine.org/howto-use-sudo/
|
||||
[3]: https://fedoramagazine.org/?s=Inkscape
|
||||
[4]: https://getfedora.org
|
||||
@@ -0,0 +1,120 @@
|
||||
如何弄清 Linux 系统运行何种系统管理程序
|
||||
======
|
||||
|
||||
虽然我们经常听到<ruby>系统管理器<rt>System Manager</rt></ruby>这词,但很少有人深究其确切意义。现在我们将向你展示其区别。
|
||||
|
||||
我会尽自己所能来解释清楚一切。我们大多都知道 System V 和 systemd 两种系统管理器。 System V (简写 SysV) 是老式系统所使用的古老且传统的初始化系统及系统管理器。
|
||||
|
||||
Systemd 是全新的初始化系统及系统管理器,并且已被大部分主流 Linux 发行版所采用。
|
||||
|
||||
Linux 系统中主要有三种有名而仍在使用的初始化系统。大多数 Linux 发行版都使用其中之一。
|
||||
|
||||
### 什么是初始化系统管理器?
|
||||
|
||||
在基于 Linux/Unix 的操作系统中,`init` (初始化的简称) 是内核启动系统时开启的第一个进程。
|
||||
|
||||
它持有的进程 ID(PID)号为 1,其在后台一直运行着,直到关机。
|
||||
|
||||
`init` 会查找 `/etc/inittab` 文件中相应配置信息来确定系统的运行级别,然后根据运行级别在后台启动所有的其它进程和应用。
|
||||
|
||||
作为 Linux 启动过程的一部分,BIOS、MBR、GRUB 和内核进程在此进程之前就被激活了。
|
||||
|
||||
下面列出的是 Linux 的可用运行级别(存在七个运行级别,从 0 到 6)。
|
||||
|
||||
* `0`:停机
|
||||
* `1`:单用户模式
|
||||
* `2`:多用户,无 NFS(LCTT 译注:NFS 即 Network File System,网络文件系统)
|
||||
* `3`:全功能多用户模式
|
||||
* `4`:未使用
|
||||
* `5`:X11(GUI – 图形用户界面)
|
||||
* `6`:重启
|
||||
|
||||
下面列出的是 Linux 系统中广泛使用的三种初始化系统。
|
||||
|
||||
* System V (Sys V):是类 Unix 操作系统传统的也是首款初始化系统。
|
||||
* Upstart:基于事件驱动,是 `/sbin/init` 守护进程的替代品。
|
||||
* Systemd:是一款全新的初始化系统及系统管理器,它被所有主流的 Linux 发行版实现/采用,以替代传统的 SysV 初始化系统。
|
||||
|
||||
### 什么是 System V (Sys V)?
|
||||
|
||||
System V(Sys V)是类 Unix 操作系统传统的也是首款初始化系统。`init` 是系统由内核启动期间启动的第一个进程,它是所有进程的父进程。
|
||||
|
||||
起初,大多数 Linux 发行版都使用名为 System V(SysV)的传统的初始化系统。多年来,为了解决标准版本中的设计限制,发布了几个替代的初始化系统,例如 launchd、Service Management Facility、systemd 和 Upstart。
|
||||
|
||||
但只有 systemd 最终被几个主流 Linux 发行版所采用,以替代传统的 SysV。
|
||||
|
||||
### 什么是 Upstart?
|
||||
|
||||
Upstart 基于事件驱动,是 `/sbin/init` 守护进程的替代品。用来在启动期间控制任务和服务的启动,在关机期间停止它们,及在系统运行过程中监视它们。
|
||||
|
||||
它最初是为 Ubuntu 发行版开发的,但也可以在所有的 Linux 发行版中部署运行,以替代古老的 System V 初始化系统。
|
||||
|
||||
它用于 Ubuntu 9.10 到 14.10 版本和基于 RHEL 6 的系统中,之后的被 systemd 取代了。
|
||||
|
||||
### 什么是 systemd?
|
||||
|
||||
systemd 是一款全新的初始化系统及系统管理器,它被所有主流的 Linux 发行版实现/采用,以替代传统的 SysV 初始化系统。
|
||||
|
||||
systemd 与 SysV 和 LSB(LCTT 译注:Linux Standards Base) 初始化脚本兼容。它可以作为 SysV 初始化系统的直接替代品。其是内核启动的第一个进程并占有数字 1 的 PID,它是所有进程的父进程。
|
||||
|
||||
Fedora 15 是第一个采用 systemd 而不是 upstart 的发行版。[systemctl][3] 是一款命令行工具,它是管理 systemd 守护进程/服务(如 `start`、`restart`、`stop`、`enable`、`disable`、`reload` 和 `status`)的主要工具。
|
||||
|
||||
systemd 使用 `.service` 文件而不是(SysV 初始化系统使用的) bash 脚本。systemd 把所有守护进程按顺序排列到自己 Cgroups (LCTT 译注:Cgroups 是 control groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源,如:cpu、memory、IO 等的机制。最初由 Google 的工程师提出,后来被整合进 Linux 内核。Cgroups 也是 LXC 为实现虚拟化所使用的资源管理手段,可以说没有 cgroups 就没有 LXC)中,所以通过查看 `/cgroup/systemd` 文件就可以查看系统层次结构。
|
||||
|
||||
### 在 Linux 上如何识别出系统管理器
|
||||
|
||||
在系统上运行如下命令来查看运行着什么系统管理器:
|
||||
|
||||
(LCTT 译注:原文繁冗啰嗦,翻译时进行了裁剪整理。)
|
||||
|
||||
#### 方法 1:使用 ps 命令
|
||||
|
||||
`ps` – 显示当前进程快照。`ps` 会显示选定的活动进程的信息。其输出不能确切区分出是 System V(SysV) 还是 upstart,所以我建议使用其它方法。
|
||||
|
||||
```
|
||||
# ps -p1 | grep "init\|upstart\|systemd"
|
||||
1 ? 00:00:00 init
|
||||
```
|
||||
|
||||
#### 方法 2:使用 rpm 命令
|
||||
|
||||
RPM 即 Red Hat Package Manager (红帽包管理),是一款功能强大的[安装包管理][1]命令行工具,在基于 Red Hat 的发行版中使用,如 RHEL、CentOS、Fedora、openSUSE 和 Mageia。此工具可以在系统/服务上对软件进行安装、更新、删除、查询及验证等操作。通常 RPM 文件都带有 `.rpm` 后缀。
|
||||
|
||||
RPM 会使用必要的库和依赖库来构建软件,并且不会与系统上安装的其它包冲突。
|
||||
|
||||
```
|
||||
# rpm -qf /sbin/init
|
||||
SysVinit-2.86-17.el5
|
||||
```
|
||||
|
||||
#### 方法 3:使用 /sbin/init 文件
|
||||
|
||||
`/sbin/init` 程序会将根文件系统从内存加载或切换到磁盘。
|
||||
|
||||
这是启动过程的主要部分。这个进程开始时的运行级别为 “N”(无)。`/sbin/init` 程序会按照 `/etc/inittab` 配制文件的描述来初始化系统。
|
||||
|
||||
```
|
||||
# /sbin/init --version
|
||||
init (upstart 0.6.5)
|
||||
Copyright (C) 2010 Canonical Ltd.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
```
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-determine-which-init-system-manager-is-running-on-linux-system/
|
||||
|
||||
作者:[Prakash Subramanian][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://www.2daygeek.com/author/prakash/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/category/package-management/
|
||||
[2]: https://www.2daygeek.com/rpm-command-examples/
|
||||
[3]: https://www.2daygeek.com/how-to-check-all-running-services-in-linux/
|
||||
@@ -1,10 +1,11 @@
|
||||
在 Fedora 上使用 Pitivi 编辑你的视频
|
||||
在 Fedora 上使用 Pitivi 编辑视频
|
||||
======
|
||||
|
||||

|
||||
想制作一部你本周末冒险的视频吗?视频编辑有很多选择。但是,如果你在寻找一个容易上手的视频编辑器,并且也可以在官方 Fedora 仓库中找到,请尝试一下[Pitivi][1]。
|
||||
|
||||
Pitivi 是一个使用 GStreamer 框架的开源非线性视频编辑器。在 Fedora 下开箱即用,Pitivi 支持 OGG、WebM 和一系列其他格式。此外,通过 gstreamer 插件可以获得更多视频格式支持。Pitivi 也与 GNOME 桌面紧密集成,因此相比其他新的程序,它的 UI 在 Fedora Workstation 上会感觉很熟悉。
|
||||
想制作一部你本周末冒险的视频吗?视频编辑有很多选择。但是,如果你在寻找一个容易上手的视频编辑器,并且也可以在官方 Fedora 仓库中找到,请尝试一下 [Pitivi][1]。
|
||||
|
||||
Pitivi 是一个使用 GStreamer 框架的开源非线性视频编辑器。在 Fedora 下开箱即用,Pitivi 支持 OGG、WebM 和一系列其他格式。此外,通过 GStreamer 插件可以获得更多视频格式支持。Pitivi 也与 GNOME 桌面紧密集成,因此相比其他新的程序,它的 UI 在 Fedora Workstation 上会感觉很熟悉。
|
||||
|
||||
### 在 Fedora 上安装 Pitivi
|
||||
|
||||
@@ -20,7 +21,7 @@ sudo dnf install pitivi
|
||||
|
||||
### 基本编辑
|
||||
|
||||
Pitivi 内置了多种工具,可以快速有效地编辑剪辑。只需将视频、音频和图像导入 Pitivi 媒体库,然后将它们拖到时间线上即可。此外,除了时间线上的简单淡入淡出过渡之外,pitivi 还允许你轻松地将剪辑的各个部分分割、修剪和分组。
|
||||
Pitivi 内置了多种工具,可以快速有效地编辑剪辑。只需将视频、音频和图像导入 Pitivi 媒体库,然后将它们拖到时间线上即可。此外,除了时间线上的简单淡入淡出过渡之外,Pitivi 还允许你轻松地将剪辑的各个部分分割、修剪和分组。
|
||||
|
||||
![][3]
|
||||
|
||||
@@ -40,7 +41,7 @@ via: https://fedoramagazine.org/edit-your-videos-with-pitivi-on-fedora/
|
||||
作者:[Ryan Lerch][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,15 +1,15 @@
|
||||
什么是 SRE?它和 DevOps 是怎么关联的?
|
||||
=====
|
||||
|
||||
大型企业里 SRE 角色比较常见,不过小公司也需要 SRE。
|
||||
> 大型企业里 SRE 角色比较常见,不过小公司也需要 SRE。
|
||||
|
||||

|
||||
|
||||
虽然站点可靠性工程师(SRE)角色在近几年变得流行起来,但是很多人 —— 甚至是软件行业里的 —— 还不知道 SRE 是什么或者 SRE 都干些什么。为了搞清楚这些问题,这篇文章解释了 SRE 的含义,还有 SRE 怎样关联 DevOps,以及在工程师团队规模不大的组织里 SRE 该如何工作。
|
||||
虽然<ruby>站点可靠性工程师<rt>site reliability engineer</rt></ruby>(SRE)角色在近几年变得流行起来,但是很多人 —— 甚至是软件行业里的 —— 还不知道 SRE 是什么或者 SRE 都干些什么。为了搞清楚这些问题,这篇文章解释了 SRE 的含义,还有 SRE 怎样关联 DevOps,以及在工程师团队规模不大的组织里 SRE 该如何工作。
|
||||
|
||||
### 什么是站点可靠性工程?
|
||||
|
||||
谷歌的几个工程师写的《 [SRE:谷歌运维解密][1]》被认为是站点可靠性工程的权威书籍。谷歌的工程副总裁 Ben Treynor Sloss 在二十一世纪初[创造了这个术语][2]。他是这样定义的:“当你让软件工程师设计运维功能时,SRE 就产生了。”
|
||||
谷歌的几个工程师写的《[SRE:谷歌运维解密][1]》被认为是站点可靠性工程的权威书籍。谷歌的工程副总裁 Ben Treynor Sloss 在二十一世纪初[创造了这个术语][2]。他是这样定义的:“当你让软件工程师设计运维功能时,SRE 就产生了。”
|
||||
|
||||
虽然系统管理员从很久之前就在写代码,但是过去的很多时候系统管理团队是手动管理机器的。当时他们管理的机器可能有几十台或者上百台,不过当这个数字涨到了几千甚至几十万的时候,就不能简单的靠人去解决问题了。规模如此大的情况下,很明显应该用代码去管理机器(以及机器上运行的软件)。
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
### SRE 和 DevOps
|
||||
|
||||
站点可靠性工程的核心,就是对 DevOps 范例的实践。[DevOps 的定义][3]有很多种方式。开发团队(“devs”)和运维(“ops”)团队相互分离的传统模式下,写代码的团队在服务交付给用户使用之后就不再对服务状态负责了。开发团队“把代码扔到墙那边”让运维团队去部署和支持。
|
||||
站点可靠性工程的核心,就是对 DevOps 范例的实践。[DevOps 的定义][3]有很多种方式。开发团队(“dev”)和运维(“ops”)团队相互分离的传统模式下,写代码的团队在将服务交付给用户使用之后就不再对服务状态负责了。开发团队“把代码扔到墙那边”让运维团队去部署和支持。
|
||||
|
||||
这种情况会导致大量失衡。开发和运维的目标总是不一致 —— 开发希望用户体验到“最新最棒”的代码,但是运维想要的是变更尽量少的稳定系统。运维是这样假定的,任何变更都可能引发不稳定,而不做任何变更的系统可以一直保持稳定。(减少软件的变更次数并不是避免故障的唯一因素,认识到这一点很重要。例如,虽然你的 web 应用保持不变,但是当用户数量涨到十倍时,服务可能就会以各种方式出问题。)
|
||||
|
||||
DevOps 理念认为通过合并这两个岗位就能够消灭争论。如果开发团队时刻都想把新代码部署上线,那么他们也必须对新代码引起的故障负责。就像亚马逊的 [Werner Vogels 说的][4]那样,“谁开发,谁运维”(生产环境)。但是开发人员已经有一大堆问题了。他们不断的被推动着去开发老板要的产品功能。再让他们去了解基础设施,包括如何部署、配置还有监控服务,这对他们的要求有点太多了。所以就需要 SRE 了。
|
||||
|
||||
开发一个 web 应用的时候经常是很多人一起参与。有用户界面设计师,图形设计师,前端工程师,后端工程师,还有许多其他工种(视技术选型的具体情况而定)。如何管理写好的代码也是需求之一(例如部署,配置,监控)—— 这是 SRE 的专业领域。但是,就像前端工程师受益于后端领域的知识一样(例如从数据库获取数据的方法),SRE 理解部署系统的工作原理,知道如何满足特定的代码或者项目的具体需求。
|
||||
开发一个 web 应用的时候经常是很多人一起参与。有用户界面设计师、图形设计师、前端工程师、后端工程师,还有许多其他工种(视技术选型的具体情况而定)。如何管理写好的代码也是需求之一(例如部署、配置、监控)—— 这是 SRE 的专业领域。但是,就像前端工程师受益于后端领域的知识一样(例如从数据库获取数据的方法),SRE 理解部署系统的工作原理,知道如何满足特定的代码或者项目的具体需求。
|
||||
|
||||
所以 SRE 不仅仅是“写代码的运维工程师”。相反,SRE 是开发团队的成员,他们有着不同的技能,特别是在发布部署、配置管理、监控、指标等方面。但是,就像前端工程师必须知道如何从数据库中获取数据一样,SRE 也不是只负责这些领域。为了提供更容易升级、管理和监控的产品,整个团队共同努力。
|
||||
|
||||
@@ -37,7 +37,7 @@ DevOps 理念认为通过合并这两个岗位就能够消灭争论。如果开
|
||||
|
||||
让开发人员做 SRE 最显著的优点是,团队规模变大的时候也能很好的扩展。而且,开发人员将会全面地了解应用的特性。但是,许多初创公司的基础设施包含了各种各样的 SaaS 产品,这种多样性在基础设施上体现的最明显,因为连基础设施本身也是多种多样。然后你们在某个基础设施上引入指标系统、站点监控、日志分析、容器等等。这些技术解决了一部分问题,也增加了复杂度。开发人员除了要了解应用程序的核心技术(比如开发语言),还要了解上述所有技术和服务。最终,掌握所有的这些技术让人无法承受。
|
||||
|
||||
另一种方案是聘请专家专职做 SRE。他们专注于发布部署、配置管理、监控和指标,可以节省开发人员的时间。这种方案的缺点是,SRE 的时间必须分配给多个不同的应用(就是说 SRE 需要贯穿整个工程部门)。 这可能意味着 SRE 没时间对任何应用深入学习,然而他们可以站在一个能看到服务全貌的高度,知道各个部分是怎么组合在一起的。 这个“ 三万英尺高的视角”可以帮助 SRE 从系统整体上考虑,哪些薄弱环节需要优先修复。
|
||||
另一种方案是聘请专家专职做 SRE。他们专注于发布部署、配置管理、监控和指标,可以节省开发人员的时间。这种方案的缺点是,SRE 的时间必须分配给多个不同的应用(就是说 SRE 需要贯穿整个工程部门)。 这可能意味着 SRE 没时间对任何应用深入学习,然而他们可以站在一个能看到服务全貌的高度,知道各个部分是怎么组合在一起的。 这个“三万英尺高的视角”可以帮助 SRE 从系统整体上考虑,哪些薄弱环节需要优先修复。
|
||||
|
||||
有一个关键信息我还没提到:其他的工程师。他们可能很渴望了解发布部署的原理,也很想尽全力学会使用指标系统。而且,雇一个 SRE 可不是一件简单的事儿。因为你要找的是一个既懂系统管理又懂软件工程的人。(我之所以明确地说软件工程而不是说“能写代码”,是因为除了写代码之外软件工程还包括很多东西,比如编写良好的测试或文档。)
|
||||
|
||||
@@ -54,7 +54,7 @@ via: https://opensource.com/article/18/10/sre-startup
|
||||
作者:[Craig Sebenik][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[BeliteX](https://github.com/belitex)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,38 +1,39 @@
|
||||
如何在 Rasspberry Pi 上搭建 WordPress
|
||||
如何在树莓派上搭建 WordPress
|
||||
======
|
||||
|
||||
这篇简单的教程可以让你在 Rasspberry Pi 上运行你的 WordPress 网站。
|
||||
> 这篇简单的教程可以让你在树莓派上运行你的 WordPress 网站。
|
||||
|
||||

|
||||
|
||||
WordPress 是一个非常受欢迎的开源博客平台和内容管理平台(CMS)。它很容易搭建,而且还有一个活跃的开发者社区构建网站、创建主题和插件供其他人使用。
|
||||
|
||||
虽然通过一键式 WordPress 设置获得托管包很容易,但通过命令行就可以在 Linux 服务器上设置自己的托管包,而且 Raspberry Pi 是一种用来尝试它并顺便学习一些东西的相当好的途径。
|
||||
虽然通过一键式 WordPress 设置获得托管包很容易,但也可以简单地通过命令行在 Linux 服务器上设置自己的托管包,而且树莓派是一种用来尝试它并顺便学习一些东西的相当好的途径。
|
||||
|
||||
使用一个 web 堆栈的四个部分是 Linux、Apache、MySQL 和 PHP。这里是你对它们每一个需要了解的。
|
||||
一个经常使用的 Web 套件的四个部分是 Linux、Apache、MySQL 和 PHP。这里是你对它们每一个需要了解的。
|
||||
|
||||
### Linux
|
||||
|
||||
Raspberry Pi 上运行的系统是 Raspbian,这是一个基于 Debian,优化地可以很好的运行在 Raspberry Pi 硬件上的 Linux 发行版。你有两个选择:桌面版或是精简版。桌面版有一个熟悉的桌面还有很多教育软件和编程工具,像是 LibreOffice 套件、Mincraft,还有一个 web 浏览器。精简版本没有桌面环境,因此它只有命令行以及一些必要的软件。
|
||||
树莓派上运行的系统是 Raspbian,这是一个基于 Debian,为运行在树莓派硬件上而优化的很好的 Linux 发行版。你有两个选择:桌面版或是精简版。桌面版有一个熟悉的桌面还有很多教育软件和编程工具,像是 LibreOffice 套件、Mincraft,还有一个 web 浏览器。精简版本没有桌面环境,因此它只有命令行以及一些必要的软件。
|
||||
|
||||
这篇教程在两个版本上都可以使用,但是如果你使用的是精简版,你必须要有另外一台电脑去访问你的站点。
|
||||
|
||||
### Apache
|
||||
|
||||
Apache 是一个受欢迎的 web 服务器应用,你可以安装在你的 Raspberry Pi 上伺服你的 web 页面。就其自身而言,Apache 可以通过 HTTP 提供静态 HTML 文件。使用额外的模块,它也可以使用像是 PHP 的脚本语言提供动态网页。
|
||||
Apache 是一个受欢迎的 web 服务器应用,你可以安装在你的树莓派上伺服你的 web 页面。就其自身而言,Apache 可以通过 HTTP 提供静态 HTML 文件。使用额外的模块,它也可以使用像是 PHP 的脚本语言提供动态网页。
|
||||
|
||||
安装 Apache 非常简单。打开一个终端窗口,然后输入下面的命令:
|
||||
|
||||
```
|
||||
sudo apt install apache2 -y
|
||||
```
|
||||
Apache 默认放了一个测试文件在一个 web 目录中,你可以从你的电脑或是你网络中的其他计算机进行访问。只需要打开 web 浏览器,然后输入地址 **<http://localhost>**。或者(特别是你使用的是 Raspbian Lite 的话)输入你的 Pi 的 IP 地址代替 **localhost**。你应该会在你的浏览器窗口中看到这样的内容:
|
||||
|
||||
Apache 默认放了一个测试文件在一个 web 目录中,你可以从你的电脑或是你网络中的其他计算机进行访问。只需要打开 web 浏览器,然后输入地址 `<http://localhost>`。或者(特别是你使用的是 Raspbian Lite 的话)输入你的树莓派的 IP 地址代替 `localhost`。你应该会在你的浏览器窗口中看到这样的内容:
|
||||
|
||||

|
||||
|
||||
这意味着你的 Apache 已经开始工作了!
|
||||
|
||||
这个默认的网页仅仅是你文件系统里的一个文件。它在你本地的 **/var/www/html/index/html**。你可以使用 [Leafpad][2] 文本编辑器写一些 HTML 去替换这个文件的内容。
|
||||
这个默认的网页仅仅是你文件系统里的一个文件。它在你本地的 `/var/www/html/index/html`。你可以使用 [Leafpad][2] 文本编辑器写一些 HTML 去替换这个文件的内容。
|
||||
|
||||
```
|
||||
cd /var/www/html/
|
||||
@@ -43,27 +44,27 @@ sudo leafpad index.html
|
||||
|
||||
### MySQL
|
||||
|
||||
MySQL (显然是 "my S-Q-L" 或者 "my sequel") 是一个很受欢迎的数据库引擎。就像 PHP,它被非常广泛的应用于网页服务,这也是为什么像 WordPress 一样的项目选择了它,以及这些项目是为何如此受欢迎。
|
||||
MySQL(读作 “my S-Q-L” 或者 “my sequel”)是一个很受欢迎的数据库引擎。就像 PHP,它被非常广泛的应用于网页服务,这也是为什么像 WordPress 一样的项目选择了它,以及这些项目是为何如此受欢迎。
|
||||
|
||||
在一个终端窗口中输入以下命令安装 MySQL 服务:
|
||||
在一个终端窗口中输入以下命令安装 MySQL 服务(LCTT 译注:实际上安装的是 MySQL 分支 MariaDB):
|
||||
|
||||
```
|
||||
sudo apt-get install mysql-server -y
|
||||
```
|
||||
|
||||
WordPress 使用 MySQL 存储文章、页面、用户数据、还有许多其他的内容。
|
||||
WordPress 使用 MySQL 存储文章、页面、用户数据、还有许多其他的内容。
|
||||
|
||||
### PHP
|
||||
|
||||
PHP 是一个预处理器:它是在服务器通过网络浏览器接受网页请求是运行的代码。它解决那些需要展示在网页上的内容,然后发送这些网页到浏览器上。,不像静态的 HTML,PHP 能在不同的情况下展示不同的内容。PHP 是一个在 web 上非常受欢迎的语言;很多像 Facebook 和 Wikipedia 的项目都使用 PHP 编写。
|
||||
PHP 是一个预处理器:它是在服务器通过网络浏览器接受网页请求是运行的代码。它解决那些需要展示在网页上的内容,然后发送这些网页到浏览器上。不像静态的 HTML,PHP 能在不同的情况下展示不同的内容。PHP 是一个在 web 上非常受欢迎的语言;很多像 Facebook 和 Wikipedia 的项目都使用 PHP 编写。
|
||||
|
||||
安装 PHP 和 MySQL 的插件:
|
||||
安装 PHP 和 MySQL 的插件:
|
||||
|
||||
```
|
||||
sudo apt-get install php php-mysql -y
|
||||
```
|
||||
|
||||
删除 **index.html**,然后创建 **index.php**:
|
||||
删除 `index.html`,然后创建 `index.php`:
|
||||
|
||||
```
|
||||
sudo rm index.html
|
||||
@@ -82,16 +83,16 @@ sudo leafpad index.php
|
||||
|
||||
### WordPress
|
||||
|
||||
你可以使用 **wget** 命令从 [wordpress.org][3] 下载 WordPress。最新的 WordPress 总是使用 [wordpress.org/latest.tar.gz][4] 这个网址,所以你可以直接抓取这些文件,而无需到网页里面查看,现在的版本是 4.9.8。
|
||||
你可以使用 `wget` 命令从 [wordpress.org][3] 下载 WordPress。最新的 WordPress 总是使用 [wordpress.org/latest.tar.gz][4] 这个网址,所以你可以直接抓取这些文件,而无需到网页里面查看,现在的版本是 4.9.8。
|
||||
|
||||
确保你在 **/var/www/html** 目录中,然后删除里面的所有内容:
|
||||
确保你在 `/var/www/html` 目录中,然后删除里面的所有内容:
|
||||
|
||||
```
|
||||
cd /var/www/html/
|
||||
sudo rm *
|
||||
```
|
||||
|
||||
使用 **wget** 下载 WordPress,然后提取里面的内容,并移动提取的 WordPress 目录中的内容移动到 **html** 目录下:
|
||||
使用 `wget` 下载 WordPress,然后提取里面的内容,并移动提取的 WordPress 目录中的内容移动到 `html` 目录下:
|
||||
|
||||
```
|
||||
sudo wget http://wordpress.org/latest.tar.gz
|
||||
@@ -99,13 +100,13 @@ sudo tar xzf latest.tar.gz
|
||||
sudo mv wordpress/* .
|
||||
```
|
||||
|
||||
现在可以删除压缩包和空的 **wordpress** 目录:
|
||||
现在可以删除压缩包和空的 `wordpress` 目录了:
|
||||
|
||||
```
|
||||
sudo rm -rf wordpress latest.tar.gz
|
||||
```
|
||||
|
||||
运行 **ls** 或者 **tree -L 1** 命令显示 WordPress 项目下包含的内容:
|
||||
运行 `ls` 或者 `tree -L 1` 命令显示 WordPress 项目下包含的内容:
|
||||
|
||||
```
|
||||
.
|
||||
@@ -132,9 +133,9 @@ sudo rm -rf wordpress latest.tar.gz
|
||||
3 directories, 16 files
|
||||
```
|
||||
|
||||
这是 WordPress 的默认安装源。在 **wp-content** 目录中,你可以编辑你的自定义安装。
|
||||
这是 WordPress 的默认安装源。在 `wp-content` 目录中,你可以编辑你的自定义安装。
|
||||
|
||||
你现在应该把所有文件的所有权改为 Apache 用户:
|
||||
你现在应该把所有文件的所有权改为 Apache 的运行用户 `www-data`:
|
||||
|
||||
```
|
||||
sudo chown -R www-data: .
|
||||
@@ -152,24 +153,27 @@ sudo mysql_secure_installation
|
||||
|
||||
你将会被问到一系列的问题。这里原来没有设置密码,但是在下一步你应该设置一个。确保你记住了你输入的密码,后面你需要使用它去连接你的 WordPress。按回车确认下面的所有问题。
|
||||
|
||||
当它完成之后,你将会看到 "All done!" 和 "Thanks for using MariaDB!" 的信息。
|
||||
当它完成之后,你将会看到 “All done!” 和 “Thanks for using MariaDB!” 的信息。
|
||||
|
||||
在终端窗口运行 **mysql** 命令:
|
||||
在终端窗口运行 `mysql` 命令:
|
||||
|
||||
```
|
||||
sudo mysql -uroot -p
|
||||
```
|
||||
输入你创建的 root 密码。你将看到 “Welcome to the MariaDB monitor.” 的欢迎信息。在 **MariaDB [(none)] >** 提示处使用以下命令,为你 WordPress 的安装创建一个数据库:
|
||||
|
||||
输入你创建的 root 密码(LCTT 译注:不是 Linux 系统的 root 密码,是 MySQL 的 root 密码)。你将看到 “Welcome to the MariaDB monitor.” 的欢迎信息。在 “MariaDB [(none)] >” 提示处使用以下命令,为你 WordPress 的安装创建一个数据库:
|
||||
|
||||
```
|
||||
create database wordpress;
|
||||
```
|
||||
|
||||
注意声明最后的分号,如果命令执行成功,你将看到下面的提示:
|
||||
|
||||
```
|
||||
Query OK, 1 row affected (0.00 sec)
|
||||
```
|
||||
把 数据库权限交给 root 用户在声明的底部输入密码:
|
||||
|
||||
把数据库权限交给 root 用户在声明的底部输入密码:
|
||||
|
||||
```
|
||||
GRANT ALL PRIVILEGES ON wordpress.* TO 'root'@'localhost' IDENTIFIED BY 'YOURPASSWORD';
|
||||
@@ -181,13 +185,13 @@ GRANT ALL PRIVILEGES ON wordpress.* TO 'root'@'localhost' IDENTIFIED BY 'YOURPAS
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
按 **Ctrl+D** 退出 MariaDB 提示,返回到 Bash shell。
|
||||
按 `Ctrl+D` 退出 MariaDB 提示符,返回到 Bash shell。
|
||||
|
||||
### WordPress 配置
|
||||
|
||||
在你的 Raspberry Pi 打开网页浏览器,地址栏输入 **<http://localhost>**。选择一个你想要在 WordPress 使用的语言,然后点击 **继续**。你将会看到 WordPress 的欢迎界面。点击 **让我们开始吧** 按钮。
|
||||
在你的 树莓派 打开网页浏览器,地址栏输入 `http://localhost`。选择一个你想要在 WordPress 使用的语言,然后点击“Continue”。你将会看到 WordPress 的欢迎界面。点击 “Let's go!” 按钮。
|
||||
|
||||
按照下面这样填写基本的站点信息:
|
||||
按照下面这样填写基本的站点信息:
|
||||
|
||||
```
|
||||
Database Name: wordpress
|
||||
@@ -197,22 +201,23 @@ Database Host: localhost
|
||||
Table Prefix: wp_
|
||||
```
|
||||
|
||||
点击 **提交** 继续,然后点击 **运行安装**。
|
||||
点击 “Submit” 继续,然后点击 “Run the install”。
|
||||
|
||||

|
||||
|
||||
按下面的格式填写:为你的站点设置一个标题、创建一个用户名和密码、输入你的 email 地址。点击 **安装 WordPress** 按钮,然后使用你刚刚创建的账号登录,你现在已经登录,而且你的站点已经设置好了,你可以在浏览器地址栏输入 **<http://localhost/wp-admin>** 查看你的网站。
|
||||
按下面的格式填写:为你的站点设置一个标题、创建一个用户名和密码、输入你的 email 地址。点击 “Install WordPress” 按钮,然后使用你刚刚创建的账号登录,你现在已经登录,而且你的站点已经设置好了,你可以在浏览器地址栏输入 `http://localhost/wp-admin` 查看你的网站。
|
||||
|
||||
### 永久链接
|
||||
|
||||
更改你的永久链接,使得你的 URLs 更加友好是一个很好的想法。
|
||||
更改你的永久链接设置,使得你的 URL 更加友好是一个很好的想法。
|
||||
|
||||
要这样做,首先登录你的 WordPress ,进入仪表盘。进入 **设置**,**永久链接**。选择 **文章名** 选项,然后点击 **保存更改**。接着你需要开启 Apache 的 **改写** 模块。
|
||||
要这样做,首先登录你的 WordPress ,进入仪表盘。进入 “Settings”,“Permalinks”。选择 “Post name” 选项,然后点击 “Save Changes”。接着你需要开启 Apache 的 `rewrite` 模块。
|
||||
|
||||
```
|
||||
sudo a2enmod rewrite
|
||||
```
|
||||
你还需要告诉虚拟托管服务,站点允许改写请求。为你的虚拟主机编辑 Apache 配置文件
|
||||
|
||||
你还需要告诉虚拟托管服务,站点允许改写请求。为你的虚拟主机编辑 Apache 配置文件:
|
||||
|
||||
```
|
||||
sudo leafpad /etc/apache2/sites-available/000-default.conf
|
||||
@@ -226,7 +231,7 @@ sudo leafpad /etc/apache2/sites-available/000-default.conf
|
||||
</Directory>
|
||||
```
|
||||
|
||||
确保其中有像这样的内容 **< VirtualHost \*:80>**
|
||||
确保其中有像这样的内容 `<VirtualHost *:80>`:
|
||||
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
@@ -244,17 +249,16 @@ sudo systemctl restart apache2
|
||||
|
||||
### 下一步?
|
||||
|
||||
WordPress 是可以高度自定义的。在网站顶部横幅处点击你的站点名,你就会进入仪表盘,。在这里你可以修改主题、添加页面和文章、编辑菜单、添加插件、以及许多其他的事情。
|
||||
WordPress 是可以高度自定义的。在网站顶部横幅处点击你的站点名,你就会进入仪表盘。在这里你可以修改主题、添加页面和文章、编辑菜单、添加插件、以及许多其他的事情。
|
||||
|
||||
这里有一些你可以在 Raspberry Pi 的网页服务上尝试的有趣的事情:
|
||||
这里有一些你可以在树莓派的网页服务上尝试的有趣的事情:
|
||||
|
||||
* 添加页面和文章到你的网站
|
||||
* 从外观菜单安装不同的主题
|
||||
* 自定义你的网站主题或是创建你自己的
|
||||
* 使用你的网站服务向你的网络上的其他人显示有用的信息
|
||||
|
||||
|
||||
不要忘记,Raspberry Pi 是一台 Linux 电脑。你也可以使用相同的结构在运行着 Debian 或者 Ubuntu 的服务器上安装 WordPress。
|
||||
不要忘记,树莓派是一台 Linux 电脑。你也可以使用相同的结构在运行着 Debian 或者 Ubuntu 的服务器上安装 WordPress。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -263,7 +267,7 @@ via: https://opensource.com/article/18/10/setting-wordpress-raspberry-pi
|
||||
作者:[Ben Nuttall][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[dianbanjiu](https://github.com/dianbanjiu)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
使用Python的toolz库开始函数式编程
|
||||
使用 Python 的 toolz 库开始函数式编程
|
||||
======
|
||||
|
||||
toolz库允许你操作函数,使其更容易理解,更容易测试代码。
|
||||
> toolz 库允许你操作函数,使其更容易理解,更容易测试代码。
|
||||
|
||||

|
||||
|
||||
@@ -20,7 +20,11 @@ def add_one_word(words, word):
|
||||
|
||||
这个函数假设它的第一个参数是一个不可变的类似字典的对象,它返回一个新的类似字典的在相关位置递增的对象:这就是一个简单的频率计数器。
|
||||
|
||||
但是,只有将它应用于单词流并做归纳时才有用。 我们可以使用内置模块 `functools` 中的归纳器。 `functools.reduce(function, stream, initializer)`
|
||||
但是,只有将它应用于单词流并做*归纳*时才有用。 我们可以使用内置模块 `functools` 中的归纳器。
|
||||
|
||||
```
|
||||
functools.reduce(function, stream, initializer)
|
||||
```
|
||||
|
||||
我们想要一个函数,应用于流,并且能能返回频率计数。
|
||||
|
||||
@@ -30,14 +34,12 @@ def add_one_word(words, word):
|
||||
add_all_words = curry(functools.reduce, add_one_word)
|
||||
```
|
||||
|
||||
使用此版本,我们需要提供初始化程序。 但是,我们不能只将 `pyrsistent.m` 函数添加到 `curry` 函数中中; 因为这个顺序是错误的。
|
||||
使用此版本,我们需要提供初始化程序。但是,我们不能只将 `pyrsistent.m` 函数添加到 `curry` 函数中; 因为这个顺序是错误的。
|
||||
|
||||
```
|
||||
add_all_words_flipped = flip(add_all_words)
|
||||
```
|
||||
|
||||
The `flip` higher-level function returns a function that calls the original, with arguments flipped.
|
||||
|
||||
`flip` 这个高阶函数返回一个调用原始函数的函数,并且翻转参数顺序。
|
||||
|
||||
```
|
||||
@@ -46,7 +48,7 @@ get_all_words = add_all_words_flipped(pyrsistent.m())
|
||||
|
||||
我们利用 `flip` 自动调整其参数的特性给它一个初始值:一个空字典。
|
||||
|
||||
现在我们可以执行 `get_all_words(word_stream)` 这个函数来获取频率字典。 但是,我们如何获得一个单词流呢? Python文件是行流的。
|
||||
现在我们可以执行 `get_all_words(word_stream)` 这个函数来获取频率字典。 但是,我们如何获得一个单词流呢? Python 文件是按行供流的。
|
||||
|
||||
```
|
||||
def to_words(lines):
|
||||
@@ -60,9 +62,9 @@ def to_words(lines):
|
||||
words_from_file = toolz.compose(get_all_words, to_words)
|
||||
```
|
||||
|
||||
在这种情况下,组合只是使两个函数很容易阅读:首先将文件的行流应用于 `to_words`,然后将 `get_all_words` 应用于 `to_words` 的结果。 散文似乎与代码相反。
|
||||
在这种情况下,组合只是使两个函数很容易阅读:首先将文件的行流应用于 `to_words`,然后将 `get_all_words` 应用于 `to_words` 的结果。 但是文字上读起来似乎与代码执行相反。
|
||||
|
||||
当我们开始认真对待可组合性时,这很重要。 有时可以将代码编写为一个单元序列,单独测试每个单元,最后将它们全部组合。 如果有几个组合元素时,组合的顺序可能就很难理解。
|
||||
当我们开始认真对待可组合性时,这很重要。有时可以将代码编写为一个单元序列,单独测试每个单元,最后将它们全部组合。如果有几个组合元素时,组合的顺序可能就很难理解。
|
||||
|
||||
`toolz` 库借用了 Unix 命令行的做法,并使用 `pipe` 作为执行相同操作的函数,但顺序相反。
|
||||
|
||||
@@ -70,17 +72,13 @@ words_from_file = toolz.compose(get_all_words, to_words)
|
||||
words_from_file = toolz.pipe(to_words, get_all_words)
|
||||
```
|
||||
|
||||
Now it reads more intuitively: Pipe the input into `to_words`, and pipe the results into `get_all_words`. On a command line, the equivalent would look like this:
|
||||
|
||||
现在读起来更直观了:将输入传递到 `to_words`,并将结果传递给 `get_all_words`。 在命令行上,等效写法如下所示:
|
||||
|
||||
```
|
||||
$ cat files | to_words | get_all_words
|
||||
```
|
||||
|
||||
The `toolz` library allows us to manipulate functions, slicing, dicing, and composing them to make our code easier to understand and to test.
|
||||
|
||||
`toolz` 库允许我们操作函数,切片,分割和组合,以使我们的代码更容易理解和测试。
|
||||
`toolz` 库允许我们操作函数,切片、分割和组合,以使我们的代码更容易理解和测试。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -89,10 +87,10 @@ via: https://opensource.com/article/18/10/functional-programming-python-toolz
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Flowsnow](https://github.com/Flowsnow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[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/article/18/10/functional-programming-python-immutable-data-structures
|
||||
[1]: https://linux.cn/article-10222-1.html
|
||||
@@ -1,30 +1,19 @@
|
||||
2018 年 10 月在 COPR 中值得尝试的 4 个很酷的新项目
|
||||
COPR 仓库中 4 个很酷的新软件(2018.10)
|
||||
======
|
||||
|
||||

|
||||
|
||||
COPR是软件的个人存储库的[集合] [1],它不在标准的 Fedora 仓库中携带。某些软件不符合允许轻松打包的标准。或者它可能不符合其他 Fedora 标准,尽管它是免费和开源的。COPR 可以在标准的 Fedora 包之外提供这些项目。COPR 中的软件不受 Fedora 基础设施的支持,或者是由项目自己签名的。但是,它是尝试新的或实验性软件的一种很好的方法。
|
||||
COPR 是软件的个人存储库的[集合] [1],它包含那些不在标准的 Fedora 仓库中的软件。某些软件不符合允许轻松打包的标准。或者它可能不符合其他 Fedora 标准,尽管它是自由开源的。COPR 可以在标准的 Fedora 包之外提供这些项目。COPR 中的软件不受 Fedora 基础设施的支持,或者是由项目自己背书的。但是,它是尝试新的或实验性软件的一种很好的方法。
|
||||
|
||||
这是 COPR 中一组新的有趣项目。
|
||||
|
||||
### GitKraken
|
||||
[编者按:这些项目里面有一个兵不适合通过 COPR 分发,所以从本文中 也删除了。相关的评论也删除了,以免误导读者。对此带来的不便,我们深表歉意。]
|
||||
|
||||
[GitKraken][2] 是一个有用的 git 客户端,它适合喜欢图形界面而非命令行的用户,并提供你期望的所有功能。此外,GitKraken 可以创建仓库和文件,并具有内置编辑器。GitKraken 的一个有用功能是暂存行或者文件,并快速切换分支。但是,在某些情况下,在遇到较大项目时会有性能问题。
|
||||
|
||||
![][3]
|
||||
|
||||
#### 安装说明
|
||||
|
||||
该仓库目前为 Fedora 27、28、29 、Rawhide 以及 OpenSUSE Tumbleweed 提供 GitKraken。要安装 GitKraken,请使用以下命令:
|
||||
|
||||
```
|
||||
sudo dnf copr enable elken/gitkraken
|
||||
sudo dnf install gitkraken
|
||||
```
|
||||
(LCTT 译注:本文后来移除了对“GitKraken”项目的介绍。)
|
||||
|
||||
### Music On Console
|
||||
|
||||
[Music On Console][4] 播放器或称为 mocp,是一个简单的控制台音频播放器。它有一个类似于 “Midnight Commander” 的界面,并且很容易使用。你只需进入包含音乐的目录,然后选择要播放的文件或目录。此外,mocp 提供了一组命令,允许直接从命令行进行控制。
|
||||
[Music On Console][4] 播放器(简称 mocp)是一个简单的控制台音频播放器。它有一个类似于 “Midnight Commander” 的界面,并且很容易使用。你只需进入包含音乐的目录,然后选择要播放的文件或目录。此外,mocp 提供了一组命令,允许直接从命令行进行控制。
|
||||
|
||||
![][5]
|
||||
|
||||
@@ -39,7 +28,7 @@ sudo dnf install moc
|
||||
|
||||
### cnping
|
||||
|
||||
[Cnping][6]是小型的图形化 ping IPv4 工具,可用于可视化显示 RTT 的变化。它提供了一个选项来控制每个数据包之间的间隔以及发送的数据大小。除了显示的图表外,cnping 还提供 RTT 和丢包的基本统计数据。
|
||||
[Cnping][6] 是小型的图形化 ping IPv4 工具,可用于可视化显示 RTT 的变化。它提供了一个选项来控制每个数据包之间的间隔以及发送的数据大小。除了显示的图表外,cnping 还提供 RTT 和丢包的基本统计数据。
|
||||
|
||||
![][7]
|
||||
|
||||
@@ -54,7 +43,7 @@ sudo dnf install cnping
|
||||
|
||||
### Pdfsandwich
|
||||
|
||||
[Pdfsandwich][8] 是将文本添加到图像形式的文本 PDF 文件 (如扫描书籍) 的工具。它使用光学字符识别 (OCR) 创建一个额外的图层, 包含了原始页面已识别的文本。这对于复制和处理文本很有用。
|
||||
[Pdfsandwich][8] 是将文本添加到图像形式的文本 PDF 文件 (如扫描书籍) 的工具。它使用光学字符识别 (OCR) 创建一个额外的图层, 包含了原始页面已识别的文本。这对于复制和处理文本很有用。
|
||||
|
||||
#### 安装说明
|
||||
|
||||
@@ -72,7 +61,7 @@ via: https://fedoramagazine.org/4-cool-new-projects-try-copr-october-2018/
|
||||
作者:[Dominik Turecek][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,11 +1,11 @@
|
||||
使用 Calcurse 在 Linux 命令行中组织任务
|
||||
======
|
||||
|
||||
使用 Calcurse 了解你的日历和待办事项列表。
|
||||
> 使用 Calcurse 了解你的日历和待办事项列表。
|
||||
|
||||

|
||||
|
||||
你是否需要复杂,功能丰富的图形或 Web 程序才能保持井井有条?我不这么认为。正确的命令行工具可以完成工作并且做得很好。
|
||||
你是否需要复杂、功能丰富的图形或 Web 程序才能保持井井有条?我不这么认为。合适的命令行工具可以完成工作并且做得很好。
|
||||
|
||||
当然,说出命令行这个词可能会让一些 Linux 用户感到害怕。对他们来说,命令行是未知领域。
|
||||
|
||||
@@ -15,54 +15,51 @@
|
||||
|
||||
### 获取软件
|
||||
|
||||
如果你喜欢编译代码(我通常不喜欢),你可以从[Calcurse 网站][1]获取源码。否则,根据你的 Linux 发行版获取[二进制安装程序][2]。你甚至可以从 Linux 发行版的软件包管理器中获取 Calcurse。检查一下不会有错的。
|
||||
如果你喜欢编译代码(我通常不喜欢),你可以从 [Calcurse 网站][1]获取源码。否则,根据你的 Linux 发行版获取[二进制安装程序][2]。你甚至可以从 Linux 发行版的软件包管理器中获取 Calcurse。检查一下不会有错的。
|
||||
|
||||
编译或安装 Calcurse 后(两者都不用太长时间),你就可以开始使用了。
|
||||
|
||||
### 使用 Calcurse
|
||||
|
||||
打开终端并输入 **calcurse**。
|
||||
打开终端并输入 `calcurse`。
|
||||
|
||||

|
||||
|
||||
Calcurse 的界面由三个面板组成:
|
||||
|
||||
* 预约(屏幕左侧)
|
||||
* 日历(右上角)
|
||||
* 待办事项清单(右下角)
|
||||
* <ruby>预约<rt>Appointments</rt></ruby>(屏幕左侧)
|
||||
* <ruby>日历<rt>Calendar</rt></ruby>(右上角)
|
||||
* <ruby>待办事项清单<rt>TODO</rt></ruby>(右下角)
|
||||
|
||||
按键盘上的 `Tab` 键在面板之间移动。要在面板添加新项目,请按下 `a`。Calcurse 将指导你完成添加项目所需的操作。
|
||||
|
||||
一个有趣的地方地是预约和日历面板配合工作。你选中日历面板并添加一个预约。在那里,你选择一个预约的日期。完成后,你回到预约面板,你就看到了。
|
||||
|
||||
|
||||
按键盘上的 Tab 键在面板之间移动。要在面板添加新项目,请按下 **a**。Calcurse 将指导你完成添加项目所需的操作。
|
||||
|
||||
一个有趣的地方地预约和日历面板一起生效。你选中日历面板并添加一个预约。在那里,你选择一个预约的日期。完成后,你回到预约面板。我知道。。。
|
||||
|
||||
按下 **a** 设置开始时间,持续时间(以分钟为单位)和预约说明。开始时间和持续时间是可选的。Calcurse 在它们到期的那天显示预约。
|
||||
按下 `a` 设置开始时间、持续时间(以分钟为单位)和预约说明。开始时间和持续时间是可选的。Calcurse 在它们到期的那天显示预约。
|
||||
|
||||

|
||||
|
||||
一天的预约看起来像:
|
||||
一天的预约看起来像这样:
|
||||
|
||||

|
||||
|
||||
待办事项列表独立运作。选中待办面板并(再次)按下 **a**。输入任务的描述,然后设置优先级(1 表示最高,9 表示最低)。Calcurse 会在待办事项面板中列出未完成的任务。
|
||||
待办事项列表独立运作。选中待办面板并(再次)按下 `a`。输入任务的描述,然后设置优先级(1 表示最高,9 表示最低)。Calcurse 会在待办事项面板中列出未完成的任务。
|
||||
|
||||

|
||||
|
||||
如果你的任务有很长的描述,那么 Calcurse 会截断它。你可以使用键盘上的向上或向下箭头键浏览任务,然后按下 **v** 查看描述。
|
||||
如果你的任务有很长的描述,那么 Calcurse 会截断它。你可以使用键盘上的向上或向下箭头键浏览任务,然后按下 `v` 查看描述。
|
||||
|
||||

|
||||
|
||||
Calcurse 将其信息以文本形式保存在你的主目录下名为 **.calcurse** 的隐藏文件夹中,例如 **/home/scott/.calcurse**。如果 Calcurse 停止工作,那也很容易找到你的信息。
|
||||
Calcurse 将其信息以文本形式保存在你的主目录下名为 `.calcurse` 的隐藏文件夹中,例如 `/home/scott/.calcurse`。如果 Calcurse 停止工作,那也很容易找到你的信息。
|
||||
|
||||
### 其他有用的功能
|
||||
|
||||
Calcurse 其他的功能包括设置重复预约的功能。要执行此操作,找出要重复的预约,然后在预约面板中按下 **r**。系统会要求你设置频率(例如,每天或每周)以及你希望重复预约的时间。
|
||||
Calcurse 其他的功能包括设置重复预约的功能。要执行此操作,找出要重复的预约,然后在预约面板中按下 `r`。系统会要求你设置频率(例如,每天或每周)以及你希望重复预约的时间。
|
||||
|
||||
你还可以导入 [ICAL][3] 格式的日历或以 ICAL 或 [PCAL][4] 格式导出数据。使用 ICAL,你可以与其他日历程序共享数据。使用 PCAL,你可以生成日历的 Postscript 版本。
|
||||
|
||||
你还可以将许多命令行参数传递给 Calcurse。你可以[在文档中][5]阅读它们。
|
||||
你还可以将许多命令行参数传递给 Calcurse。你可以[在文档中][5]了解它们。
|
||||
|
||||
虽然很简单,但 Calcurse 可以帮助你保持井井有条。你需要更加关注自己的任务和预约,但是你将能够更好地关注你需要做什么以及你需要做的方向。
|
||||
|
||||
@@ -73,7 +70,7 @@ via: https://opensource.com/article/18/10/calcurse
|
||||
作者:[Scott Nesbitt][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
监测数据库的健康和行为:有哪些重要指标?
|
||||
======
|
||||
|
||||
> 对数据库的监测可能过于困难或者没有找到关键点。本文将讲述如何正确的监测数据库。
|
||||
|
||||

|
||||
|
||||
我们没有对数据库讨论过多少。在这个充满监测仪器的时代,我们监测我们的应用程序、基础设施、甚至我们的用户,但有时忘记我们的数据库也值得被监测。这很大程度是因为数据库表现的很好,以至于我们单纯地信任它能把任务完成的很好。信任固然重要,但能够证明它的表现确实如我们所期待的那样就更好了。
|
||||
|
||||

|
||||
|
||||
### 为什么监测你的数据库?
|
||||
|
||||
监测数据库的原因有很多,其中大多数原因与监测系统的任何其他部分的原因相同:了解应用程序的各个组件中发生的什么,会让你成为更了解情况的,能够做出明智决策的开发人员。
|
||||
|
||||

|
||||
|
||||
更具体地说,数据库是系统健康和行为的重要标志。数据库中的异常行为能够指出应用程序中出现问题的区域。另外,当应用程序中有异常行为时,你可以利用数据库的指标来迅速完成排除故障的过程。
|
||||
|
||||
### 问题
|
||||
|
||||
最轻微的调查揭示了监测数据库的一个问题:数据库有很多指标。说“很多”只是轻描淡写,如果你是<ruby>史高治<rt>Scrooge McDuck</rt></ruby>(LCTT 译注:史高治,唐老鸭的舅舅,以一毛不拔著称),你不会放过任何一个可用的指标。如果这是<ruby>摔角狂热<rt>Wrestlemania</rt></ruby> 比赛,那么指标就是折叠椅。监测所有指标似乎并不实用,那么你如何决定要监测哪些指标?
|
||||
|
||||

|
||||
|
||||
### 解决方案
|
||||
|
||||
开始监测数据库的最好方式是认识一些基础的数据库指标。这些指标为理解数据库的行为创造了良好的开端。
|
||||
|
||||
### 吞吐量:数据库做了多少?
|
||||
|
||||
开始检测数据库的最好方法是跟踪它所接到请求的数量。我们对数据库有较高期望;期望它能稳定的存储数据,并处理我们抛给它的所有查询,这些查询可能是一天一次大规模查询,或者是来自用户一天到晚的数百万次查询。吞吐量可以告诉我们数据库是否如我们期望的那样工作。
|
||||
|
||||
你也可以将请求按照类型(读、写、服务器端、客户端等)分组,以开始分析流量。
|
||||
|
||||
### 执行时间:数据库完成工作需要多长时间?
|
||||
|
||||
这个指标看起来很明显,但往往被忽视了。你不仅想知道数据库收到了多少请求,还想知道数据库在每个请求上花费了多长时间。 然而,参考上下文来讨论执行时间非常重要:像 InfluxDB 这样的时间序列数据库中的慢与像 MySQL 这样的关系型数据库中的慢不一样。InfluxDB 中的慢可能意味着毫秒,而 MySQL 的 `SLOW_QUERY` 变量的默认值是 10 秒。
|
||||
|
||||

|
||||
|
||||
监测执行时间和提高执行时间不一样,所以如果你的应用程序中有其他问题需要修复,那么请注意在优化上花费时间的诱惑。
|
||||
|
||||
### 并发性:数据库同时做了多少工作?
|
||||
|
||||
一旦你知道数据库正在处理多少请求以及每个请求需要多长时间,你就需要添加一层复杂性以开始从这些指标中获得实际值。
|
||||
|
||||
如果数据库接收到十个请求,并且每个请求需要十秒钟来完成,那么数据库是忙碌了 100 秒、10 秒,还是介于两者之间?并发任务的数量改变了数据库资源的使用方式。当你考虑连接和线程的数量等问题时,你将开始对数据库指标有更全面的了解。
|
||||
|
||||
并发性还能影响延迟,这不仅包括任务完成所需的时间(执行时间),还包括任务在处理之前需要等待的时间。
|
||||
|
||||
### 利用率:数据库繁忙的时间百分比是多少?
|
||||
|
||||
利用率是由吞吐量、执行时间和并发性的峰值所确定的数据库可用的频率,或者数据库太忙而不能响应请求的频率。
|
||||
|
||||

|
||||
|
||||
该指标对于确定数据库的整体健康和性能特别有用。如果只能在 80% 的时间内响应请求,则可以重新分配资源、进行优化工作,或者进行更改以更接近高可用性。
|
||||
|
||||
### 好消息
|
||||
|
||||
监测和分析似乎非常困难,特别是因为我们大多数人不是数据库专家,我们可能没有时间去理解这些指标。但好消息是,大部分的工作已经为我们做好了。许多数据库都有一个内部性能数据库(Postgres:`pg_stats`、CouchDB:`Runtime_Statistics`、InfluxDB:`_internal` 等),数据库工程师设计该数据库来监测与该特定数据库有关的指标。你可以看到像慢速查询的数量一样广泛的内容,或者像数据库中每个事件的平均微秒一样详细的内容。
|
||||
|
||||
### 结论
|
||||
|
||||
数据库创建了足够的指标以使我们需要长时间研究,虽然内部性能数据库充满了有用的信息,但并不总是使你清楚应该关注哪些指标。从吞吐量、执行时间、并发性和利用率开始,它们为你提供了足够的信息,使你可以开始了解你的数据库中的情况。
|
||||
|
||||

|
||||
|
||||
你在监视你的数据库吗?你发现哪些指标有用?告诉我吧!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/10/database-metrics-matter
|
||||
|
||||
作者:[Katy Farmer][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[ChiZelin](https://github.com/ChiZelin)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/thekatertot
|
||||
[b]: https://github.com/lujun9972
|
||||
@@ -1,13 +1,13 @@
|
||||
理解 Linux 链接 (二)
|
||||
理解 Linux 链接(二)
|
||||
======
|
||||
> 我们继续这个系列,来看一些你所不知道的微妙之处。
|
||||
|
||||

|
||||
|
||||
在[本系列的第一篇文章中][1],我们认识了硬链接,软链接,知道在很多时候链接是非常有用的。链接看起来比较简单,但是也有一些不易察觉的奇怪的地方需要注意。这就是我们这篇文章中要讲的。例如,像一下我们在前一篇文章中创建的指向 `libblah` 的链接。请注意,我们是如何从目标文件夹中创建链接的。
|
||||
在[本系列的第一篇文章中][1],我们认识了硬链接、软链接,知道在很多时候链接是非常有用的。链接看起来比较简单,但是也有一些不易察觉的奇怪的地方需要注意。这就是我们这篇文章中要讲的。例如,像一下我们在前一篇文章中创建的指向 `libblah` 的链接。请注意,我们是如何从目标文件夹中创建链接的。
|
||||
|
||||
```
|
||||
cd /usr/local/lib
|
||||
|
||||
ln -s /usr/lib/libblah
|
||||
```
|
||||
|
||||
@@ -15,35 +15,32 @@ ln -s /usr/lib/libblah
|
||||
|
||||
```
|
||||
cd /usr/lib
|
||||
|
||||
ln -s libblah /usr/local/lib
|
||||
```
|
||||
|
||||
也就是说,从原始文件夹内到目标文件夹之间的链接将不起作用。
|
||||
|
||||
出现这种情况的原因是 `ln` 会把它当作是你在 `/usr/local/lib` 中创建一个到 `/usr/local/lib` 的链接,并在 `/usr/local/lib` 中创建了从 `libblah` 到 `libblah` 的一个链接。这是因为所有链接文件获取的是文件的名称(`libblah`),而不是文件的路径,最终的结果将会产生一个坏的链接。
|
||||
出现这种情况的原因是 `ln` 会把它当作是你在 `/usr/local/lib` 中创建一个到 `/usr/local/lib` 的链接,并在 `/usr/local/lib` 中创建了从 `libblah` 到 `libblah` 的一个链接。这是因为所有链接文件获取的是文件的名称(`libblah),而不是文件的路径,最终的结果将会产生一个坏的链接。
|
||||
|
||||
然而,请看下面的这种情况。
|
||||
|
||||
```
|
||||
cd /usr/lib
|
||||
|
||||
ln -s /usr/lib/libblah /usr/local/lib
|
||||
```
|
||||
|
||||
是可以工作的。奇怪的事情又来了,不管你在文件系统的任何位置执行指令,它都可以好好的工作。使用绝对路径,也就是说,指定整个完整的路径,从根目录(`/`)开始到需要的文件或者是文件夹,是最好的实现方式。
|
||||
是可以工作的。奇怪的事情又来了,不管你在文件系统的任何位置执行这个指令,它都可以好好的工作。使用绝对路径,也就是说,指定整个完整的路径,从根目录(`/`)开始到需要的文件或者是文件夹,是最好的实现方式。
|
||||
|
||||
其它需要注意的事情是,只要 `/usr/lib` 和 `/usr/local/lib` 在一个分区上,做一个如下的硬链接:
|
||||
|
||||
```
|
||||
cd /usr/lib
|
||||
|
||||
ln libblah /usr/local/lib
|
||||
```
|
||||
|
||||
也是可以工作的,因为硬链接不依赖于指向文件系统内的文件来工作。
|
||||
|
||||
如果硬链接不起作用,那么可能是你想跨分区之间建立一个硬链接。就比如说,你有分区A上有文件 `fileA` ,并且把这个分区挂载到 `/path/to/partitionA/directory` 目录,而你又想从 `fileA` 链接到分区B上 `/path/to/partitionB/directory` 目录,这样是行不通的。
|
||||
如果硬链接不起作用,那么可能是你想跨分区之间建立一个硬链接。就比如说,你有分区 A 上有文件 `fileA` ,并且把这个分区挂载到 `/path/to/partitionA/directory` 目录,而你又想从 `fileA` 链接到分区 B 上 `/path/to/partitionB/directory` 目录,这样是行不通的。
|
||||
|
||||
```
|
||||
ln /path/to/partitionA/directory/file /path/to/partitionB/directory
|
||||
@@ -63,15 +60,15 @@ ln -s /path/to/some/directory /path/to/some/other/directory
|
||||
|
||||
这将在 `/path/to/some/other/directory` 中创建 `/path/to/some/directory` 的链接,没有任何问题。
|
||||
|
||||
当你使用硬链接做同样的事情的时候,会提示你一个错误,说不允许那么做。而不允许这么做的原因量会导致无休止的递归:如果你在目录A中有一个目录B,然后你在目录B中链接A,就会出现同样的情况,在目录A中,目录A包含了目录B,而在目录B中又包含了A,然后又包含了B,等等无穷无尽。
|
||||
当你使用硬链接做同样的事情的时候,会提示你一个错误,说不允许那么做。而不允许这么做的原因量会导致无休止的递归:如果你在目录 A 中有一个目录 B,然后你在目录 B 中链接 A,就会出现同样的情况,在目录 A 中,目录 A 包含了目录 B,而在目录 B 中又包含了 A,然后又包含了 B,等等无穷无尽。
|
||||
|
||||
当然你可以在递归中使用软链接,但你为什么要那样做呢?
|
||||
|
||||
### 我应该使用硬链接还是软链接呢?
|
||||
|
||||
通常,你可以在任何地方使用软链接做任何事情。实际上,在有些情况下你只能使用软软链接。话说回来,硬链接的效率要稍高一些:它们占用的磁盘空间更少,访问速度更快。在大多数的机器上, 发你可以忽略这一点点的差异,因为:在磁盘空间越来越大,访问速度越来越快的今天,空间和速度的差异可以忽略不计。不过,如果你是在一个有小存储和低功耗的处理器上使用嵌入式系统上使用 linux, 则可能需要考虑使用硬链接。
|
||||
通常,你可以在任何地方使用软链接做任何事情。实际上,在有些情况下你只能使用软链接。话说回来,硬链接的效率要稍高一些:它们占用的磁盘空间更少,访问速度更快。在大多数的机器上,你可以忽略这一点点的差异,因为:在磁盘空间越来越大,访问速度越来越快的今天,空间和速度的差异可以忽略不计。不过,如果你是在一个有小存储和低功耗的处理器上使用嵌入式系统上使用 Linux, 则可能需要考虑使用硬链接。
|
||||
|
||||
另一个使用硬链接的原因是硬链接不容易破碎。假设你有一个软链接,而你意外的移动或者删除了它指向的文件,那么你的软链接将会破碎,并指向了一个不存在的东西。这种情况是不会发生在硬链接中的,因为硬链接直接指向的是磁盘上的数据。实际上,磁盘上的空间不不会被标记为空闲,除非最后一个指向它的硬链接把它从文件系统中擦除掉。
|
||||
另一个使用硬链接的原因是硬链接不容易损坏。假设你有一个软链接,而你意外的移动或者删除了它指向的文件,那么你的软链接将会损坏,并指向了一个不存在的东西。这种情况是不会发生在硬链接中的,因为硬链接直接指向的是磁盘上的数据。实际上,磁盘上的空间不会被标记为空闲,除非最后一个指向它的硬链接把它从文件系统中擦除掉。
|
||||
|
||||
软链接,在另一方面比硬链接可以做更多的事情,而且可以指向任何东西,可以是文件或目录。它也可以指向不在同一个分区上的文件和目录。仅这两个不同,我们就可以做出唯一的选择了。
|
||||
|
||||
@@ -79,7 +76,7 @@ ln -s /path/to/some/directory /path/to/some/other/directory
|
||||
|
||||
现在我们已经介绍了文件和目录以及操作它们的工具,你是否已经准备好转到这些工具,可以浏览目录层次结构,可以查找文件中的数据,也可以检查目录。这就是我们下一期中要做的事情。下期见。
|
||||
|
||||
你可以通过Linux 基金会和edX [Linux 简介][2]了解更多关于Linux的免费课程。
|
||||
你可以通过 Linux 基金会和 edX “[Linux 简介][2]”了解更多关于 Linux 的免费课程。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -87,12 +84,12 @@ via: https://www.linux.com/blog/2018/10/understanding-linux-links-part-2
|
||||
|
||||
作者:[Paul Brown][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[Jamkr](https://github.com/Jamkr)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/bro66
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.linux.com/blog/intro-to-linux/2018/10/linux-links-part-1
|
||||
[1]: https://linux.cn/article-10173-1.html
|
||||
[2]: https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
|
||||
@@ -0,0 +1,122 @@
|
||||
让系统崩溃的黑天鹅分类
|
||||
======
|
||||
|
||||
> 在严重的故障发生之前,找到引起问题的异常事件,并修复它。
|
||||
|
||||

|
||||
|
||||
<ruby>黑天鹅<rt>Black swan</rt></ruby>用来比喻造成严重影响的小概率事件(比如 2008 年的金融危机)。在生产环境的系统中,黑天鹅是指这样的事情:它引发了你不知道的问题,造成了重大影响,不能快速修复或回滚,也不能用值班说明书上的其他标准响应来解决。它是事发几年后你还在给新人说起的事件。
|
||||
|
||||
从定义上看,黑天鹅是不可预测的,不过有时候我们能找到其中的一些模式,针对有关联的某一类问题准备防御措施。
|
||||
|
||||
例如,大部分故障的直接原因是变更(代码、环境或配置)。虽然这种方式触发的 bug 是独特的、不可预测的,但是常见的金丝雀发布对避免这类问题有一定的作用,而且自动回滚已经成了一种标准止损策略。
|
||||
|
||||
随着我们的专业性不断成熟,一些其他的问题也正逐渐变得容易理解,被归类到某种风险并有普适的预防策略。
|
||||
|
||||
### 公布出来的黑天鹅事件
|
||||
|
||||
所有科技公司都有生产环境的故障,只不过并不是所有公司都会分享他们的事故分析。那些公开讨论事故的公司帮了我们的忙。下列事故都描述了某一类问题,但它们绝对不是只一个孤例。我们的系统中都有黑天鹅在潜伏着,只是有些人还不知道而已。
|
||||
|
||||
#### 达到上限
|
||||
|
||||
达到任何类型的限制都会引发严重事故。这类问题的一个典型例子是 2017 年 2 月 [Instapaper 的一次服务中断][1]。我把这份事故报告给任何一个运维工作者看,他们读完都会脊背发凉。Instapaper 生产环境的数据库所在的文件系统有 2 TB 的大小限制,但是数据库服务团队并不知情。在没有任何报错的情况下,数据库不再接受任何写入了。完全恢复需要好几天,而且还得迁移数据库。
|
||||
|
||||
资源限制有各式各样的触发场景。Sentry 遇到了 [Postgres 的最大事务 ID 限制][2]。Platform.sh 遇到了[管道缓冲区大小限制][3]。SparkPost [触发了 AWS 的 DDoS 保护][4]。Foursquare 在他们的一个 [MongoDB 耗尽内存][5]时遭遇了性能骤降。
|
||||
|
||||
提前了解系统限制的一个办法是定期做测试。好的压力测试(在生产环境的副本上做)应该包含写入事务,并且应该把每一种数据存储都写到超过当前生产环境的容量。压力测试时很容易忽略的是次要存储(比如 Zookeeper)。如果你是在测试时遇到了资源限制,那么你还有时间去解决问题。鉴于这种资源限制问题的解决方案可能涉及重大的变更(比如数据存储拆分),所以时间是非常宝贵的。
|
||||
|
||||
说到云产品的使用,如果你的服务产生了异常的负载,或者你用的产品或功能还没有被广泛使用(比如老旧的或者新兴的),那么你遇到资源上限的风险很大。对这些云产品做一下压力测试是值得的。不过,做之前要提醒一下你的云服务提供商。
|
||||
|
||||
最后,知道了哪里有限制之后,要增加监控(和对应文档),这样你才能知道系统在什么时候接近了资源上限。不要寄希望于那些还在维护服务的人会记得。
|
||||
|
||||
#### 扩散的慢请求
|
||||
|
||||
> “这个世界的关联性远比我们想象中更大。所以我们看到了更多 Nassim Taleb 所说的‘黑天鹅事件’ —— 即罕见事件以更高的频率离谱地发生了,因为世界是相互关联的”
|
||||
> —— [Richard Thaler][6]
|
||||
|
||||
HostedGraphite 的负载均衡器并没有托管在 AWS 上,却[被 AWS 的服务中断给搞垮了][7],他们关于这次事故原因的分析报告很好地诠释了分布式计算系统之间存在多么大的关联。在这个事件里,负载均衡器的连接池被来自 AWS 上的客户访问占满了,因为这些连接很耗时。同样的现象还会发生在应用的线程、锁、数据库连接上 —— 任何能被慢操作占满的资源。
|
||||
|
||||
这个 HostedGraphite 的例子中,慢速连接是外部系统施加的,不过慢速连接经常是由内部某个系统的饱和所引起的,饱和与慢操作的级联,拖慢了系统中的其他部分。[Spotify 的一个事故][8]就说明了这样的传播 —— 流媒体服务的前端被另一个微服务的饱和所影响,造成健康检查失败。强制给所有请求设置超时时间,以及限制请求队列的长度,可以预防这一类故障传播。这样即使有问题,至少你的服务还能承担一些流量,而且因为整体上你的系统里故障的部分更少了,恢复起来也会更快。
|
||||
|
||||
重试的间隔应该用指数退避来限制一下,并加入一些时间抖动。Square 有一次服务中断是 [Redis 存储的过载][9],原因是有一段代码对失败的事务重试了 500 次,没有任何重试退避的方案,也说明了过度重试的潜在风险。另外,针对这种情况,[断路器][10]设计模式也是有用的。
|
||||
|
||||
应该设计出监控仪表盘来清晰地展示所有资源的[使用率、饱和度和报错][11],这样才能快速发现问题。
|
||||
|
||||
#### 突发的高负载
|
||||
|
||||
系统在异常高的负载下经常会发生故障。用户天然会引发高负载,不过也常常是由系统引发的。午夜突发的 cron 定时任务是老生常谈了。如果程序让移动客户端同时去获取更新,这些客户端也会造成突发的大流量(当然,给这种请求加入时间抖动会好很多)。
|
||||
|
||||
在预定时刻同时发生的事件并不是突发大流量的唯一原因。Slack 经历过一次短时间内的[多次服务中断][12],原因是非常多的客户端断开连接后立即重连,造成了突发的大负载。 CircleCI 也经历过一次[严重的服务中断][13],当时 Gitlab 从故障中恢复了,所以数据库里积累了大量的构建任务队列,服务变得饱和而且缓慢。
|
||||
|
||||
几乎所有的服务都会受突发的高负载所影响。所以对这类可能出现的事情做应急预案 —— 并测试一下预案能否正常工作 —— 是必须的。客户端退避和[减载][14]通常是这些方案的核心。
|
||||
|
||||
如果你的系统必须不间断地接收数据,并且数据不能被丢掉,关键是用可伸缩的方式把数据缓冲到队列中,后续再处理。
|
||||
|
||||
#### 自动化系统是复杂的系统
|
||||
|
||||
> “复杂的系统本身就是有风险的系统”
|
||||
> —— [Richard Cook, MD][15]
|
||||
|
||||
过去几年里软件的运维操作趋势是更加自动化。任何可能降低系统容量的自动化操作(比如擦除磁盘、退役设备、关闭服务)都应该谨慎操作。这类自动化操作的故障(由于系统有 bug 或者有不正确的调用)能很快地搞垮你的系统,而且可能很难恢复。
|
||||
|
||||
谷歌的 Christina Schulman 和 Etienne Perot 在[用安全规约协助保护你的数据中心][16]的演讲中给了一些例子。其中一次事故是将谷歌整个内部的内容分发网络(CDN)提交给了擦除磁盘的自动化系统。
|
||||
|
||||
Schulman 和 Perot 建议使用一个中心服务来管理规约,限制破坏性自动化操作的速度,并能感知到系统状态(比如避免在最近有告警的服务上执行破坏性的操作)。
|
||||
|
||||
自动化系统在与运维人员(或其他自动化系统)交互时,也可能造成严重事故。[Reddit][17] 遭遇过一次严重的服务中断,当时他们的自动化系统重启了一个服务,但是这个服务是运维人员停掉做维护的。一旦有了多个自动化系统,它们之间潜在的交互就变得异常复杂和不可预测。
|
||||
|
||||
所有的自动化系统都把日志输出到一个容易搜索的中心存储上,能帮助到对这类不可避免的意外情况的处理。自动化系统总是应该具备这样一种机制,即允许快速地关掉它们(完全关掉或者只关掉其中一部分操作或一部分目标)。
|
||||
|
||||
### 防止黑天鹅事件
|
||||
|
||||
可能在等着击垮系统的黑天鹅可不止上面这些。有很多其他的严重问题是能通过一些技术来避免的,像金丝雀发布、压力测试、混沌工程、灾难测试和模糊测试 —— 当然还有冗余性和弹性的设计。但是即使用了这些技术,有时候你的系统还是会有故障。
|
||||
|
||||
为了确保你的组织能有效地响应,在服务中断期间,请保证关键技术人员和领导层有办法沟通协调。例如,有一种你可能需要处理的烦人的事情,那就是网络完全中断。拥有故障时仍然可用的通信通道非常重要,这个通信通道要完全独立于你们自己的基础设施及对其的依赖。举个例子,假如你使用 AWS,那么把故障时可用的通信服务部署在 AWS 上就不明智了。在和你的主系统无关的地方,运行电话网桥或 IRC 服务器是比较好的方案。确保每个人都知道这个通信平台,并练习使用它。
|
||||
|
||||
另一个原则是,确保监控和运维工具对生产环境系统的依赖尽可能的少。将控制平面和数据平面分开,你才能在系统不健康的时候做变更。不要让数据处理和配置变更或监控使用同一个消息队列,比如,应该使用不同的消息队列实例。在 [SparkPost: DNS 挂掉的那一天][4] 这个演讲中,Jeremy Blosser 讲了一个这类例子,很关键的工具依赖了生产环境的 DNS 配置,但是生产环境的 DNS 出了问题。
|
||||
|
||||
### 对抗黑天鹅的心理学
|
||||
|
||||
处理生产环境的重大事故时会产生很大的压力。为这些场景制定结构化的事故管理流程确实是有帮助的。很多科技公司([包括谷歌][18])成功地使用了联邦应急管理局事故指挥系统的某个版本。对于每一个值班的人,遇到了他们无法独立解决的重大问题时,都应该有一个明确的寻求协助的方法。
|
||||
|
||||
对于那些持续很长时间的事故,有一点很重要,要确保工程师不会连续工作到不合理的时长,确保他们不会不吃不睡(没有报警打扰的睡觉)。疲惫不堪的工程师很容易犯错或者漏掉了可能更快解决故障的信息。
|
||||
|
||||
### 了解更多
|
||||
|
||||
关于黑天鹅(或者以前的黑天鹅)事件以及应对策略,还有很多其他的事情可以说。如果你想了解更多,我强烈推荐你去看这两本书,它们是关于生产环境中的弹性和稳定性的:Susan Fowler 写的《[生产微服务][19]》,还有 Michael T. Nygard 的 《[Release It!][20]》。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/10/taxonomy-black-swans
|
||||
|
||||
作者:[Laura Nolan][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[BeliteX](https://github.com/belitex)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/lauranolan
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://medium.com/making-instapaper/instapaper-outage-cause-recovery-3c32a7e9cc5f
|
||||
[2]: https://blog.sentry.io/2015/07/23/transaction-id-wraparound-in-postgres.html
|
||||
[3]: https://medium.com/@florian_7764/technical-post-mortem-of-the-august-incident-82ab4c3d6547
|
||||
[4]: https://www.usenix.org/conference/srecon18americas/presentation/blosser
|
||||
[5]: https://groups.google.com/forum/#!topic/mongodb-user/UoqU8ofp134
|
||||
[6]: https://en.wikipedia.org/wiki/Richard_Thaler
|
||||
[7]: https://blog.hostedgraphite.com/2018/03/01/spooky-action-at-a-distance-how-an-aws-outage-ate-our-load-balancer/
|
||||
[8]: https://labs.spotify.com/2013/06/04/incident-management-at-spotify/
|
||||
[9]: https://medium.com/square-corner-blog/incident-summary-2017-03-16-2f65be39297
|
||||
[10]: https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern
|
||||
[11]: http://www.brendangregg.com/usemethod.html
|
||||
[12]: https://slackhq.com/this-was-not-normal-really
|
||||
[13]: https://circleci.statuspage.io/incidents/hr0mm9xmm3x6
|
||||
[14]: https://www.youtube.com/watch?v=XNEIkivvaV4
|
||||
[15]: https://web.mit.edu/2.75/resources/random/How%20Complex%20Systems%20Fail.pdf
|
||||
[16]: https://www.usenix.org/conference/srecon18americas/presentation/schulman
|
||||
[17]: https://www.reddit.com/r/announcements/comments/4y0m56/why_reddit_was_down_on_aug_11/
|
||||
[18]: https://landing.google.com/sre/book/chapters/managing-incidents.html
|
||||
[19]: http://shop.oreilly.com/product/0636920053675.do
|
||||
[20]: https://www.oreilly.com/library/view/release-it/9781680500264/
|
||||
[21]: https://www.usenix.org/conference/lisa18/presentation/nolan
|
||||
[22]: https://www.usenix.org/conference/lisa18
|
||||
@@ -3,33 +3,34 @@
|
||||
|
||||

|
||||
|
||||
管道命令的作用是将一个命令/程序/进程的输出发送给另一个命令/程序/进程,以便将输出结果进行进一步的处理。我们可以通过使用管道命令把多个命令组合起来,使一个命令的标准输入或输出重定向到另一个命令。两个或多个 Linux 命令之间的竖线字符(|)表示在命令之间使用管道命令。管道命令的一般语法如下所示:
|
||||
管道命令的作用是将一个命令/程序/进程的输出发送给另一个命令/程序/进程,以便将输出结果进行进一步的处理。我们可以通过使用管道命令把多个命令组合起来,使一个命令的标准输入或输出重定向到另一个命令。两个或多个 Linux 命令之间的竖线字符(`|`)表示在命令之间使用管道命令。管道命令的一般语法如下所示:
|
||||
|
||||
```
|
||||
Command-1 | Command-2 | Command-3 | …| Command-N
|
||||
```
|
||||
|
||||
`Ultimate Plumber`(简称 `UP`)是一个命令行工具,它可以用于即时预览管道命令结果。如果你在使用 Linux 时经常会用到管道命令,就可以通过它更好地运用管道命令了。它可以预先显示执行管道命令后的结果,而且是即时滚动地显示,让你可以轻松构建复杂的管道。
|
||||
Ultimate Plumber(简称 UP)是一个命令行工具,它可以用于即时预览管道命令结果。如果你在使用 Linux 时经常会用到管道命令,就可以通过它更好地运用管道命令了。它可以预先显示执行管道命令后的结果,而且是即时滚动地显示,让你可以轻松构建复杂的管道。
|
||||
|
||||
下文将会介绍如何安装 `UP` 并用它将复杂管道命令的编写变得简单。
|
||||
下文将会介绍如何安装 UP 并用它将复杂管道命令的编写变得简单。
|
||||
|
||||
|
||||
**重要警告:**
|
||||
|
||||
在生产环境中请谨慎使用 `UP`!在使用它的过程中,有可能会在无意中删除重要数据,尤其是搭配 `rm` 或 `dd` 命令时需要更加小心。勿谓言之不预。
|
||||
在生产环境中请谨慎使用 UP!在使用它的过程中,有可能会在无意中删除重要数据,尤其是搭配 `rm` 或 `dd` 命令时需要更加小心。勿谓言之不预。
|
||||
|
||||
### 使用 Ultimate Plumber 即时预览管道命令
|
||||
|
||||
下面给出一个简单的例子介绍 `UP` 的使用方法。如果需要将 `lshw` 命令的输出传递给 `UP`,只需要在终端中输入以下命令,然后回车:
|
||||
下面给出一个简单的例子介绍 `up` 的使用方法。如果需要将 `lshw` 命令的输出传递给 `up`,只需要在终端中输入以下命令,然后回车:
|
||||
|
||||
```
|
||||
$ lshw |& up
|
||||
```
|
||||
|
||||
你会在屏幕顶部看到一个输入框,如下图所示。
|
||||
|
||||

|
||||
|
||||
在输入命令的过程中,输入管道符号并回车,就可以立即执行已经输入了的命令。`Ultimate Plumber` 会在下方的可滚动窗口中即时显示管道命令的输出。在这种状态下,你可以通过 `PgUp`/`PgDn` 键或 `ctrl + ←`/`ctrl + →` 组合键来查看结果。
|
||||
在输入命令的过程中,输入管道符号并回车,就可以立即执行已经输入了的命令。Ultimate Plumber 会在下方的可滚动窗口中即时显示管道命令的输出。在这种状态下,你可以通过 `PgUp`/`PgDn` 键或 `ctrl + ←`/`ctrl + →` 组合键来查看结果。
|
||||
|
||||
当你满意执行结果之后,可以使用 `ctrl + x` 组合键退出 `UP`。而退出前编写的管道命令则会保存在当前工作目录的文件中,并命名为 `up1.sh`。如果这个文件名已经被占用,就会命名为 `up2.sh`、`up3.sh` 等等以此类推,直到第 1000 个文件。如果你不需要将管道命令保存输出,只需要使用 `ctrl + c` 组合键退出即可。
|
||||
|
||||
@@ -41,29 +42,29 @@ $ cat up2.sh
|
||||
grep network -A5 | grep : | cut -d: -f2- | paste - -
|
||||
```
|
||||
|
||||
如果通过管道发送到 `UP` 的命令运行时间太长,终端窗口的左上角会显示一个波浪号(~)字符,这就表示 `UP` 在等待前一个命令的输出结果作为输入。在这种情况下,你可能需要使用 `ctrl + s` 组合键暂时冻结 `UP` 的输入缓冲区大小。在需要解冻的时候,使用 `ctrl + q` 组合键即可。`Ultimate Plumber` 的输入缓冲区大小一般为 40 MB,到达这个限制之后,屏幕的左上角会显示一个加号。
|
||||
如果通过管道发送到 `up` 的命令运行时间太长,终端窗口的左上角会显示一个波浪号(~)字符,这就表示 `up` 在等待前一个命令的输出结果作为输入。在这种情况下,你可能需要使用 `ctrl + s` 组合键暂时冻结 `up` 的输入缓冲区大小。在需要解冻的时候,使用 `ctrl + q` 组合键即可。Ultimate Plumber 的输入缓冲区大小一般为 40 MB,到达这个限制之后,屏幕的左上角会显示一个加号。
|
||||
|
||||
以下是 `up` 命令的一个简单演示:
|
||||
|
||||
以下是 `UP` 命令的一个简单演示:
|
||||

|
||||
|
||||
### 安装 Ultimate Plumber
|
||||
|
||||
喜欢这个工具的话,你可以在你的 Linux 系统上安装使用。安装过程也相当简单,只需要在终端里执行以下两个命令就可以安装 `UP` 了。
|
||||
喜欢这个工具的话,你可以在你的 Linux 系统上安装使用。安装过程也相当简单,只需要在终端里执行以下两个命令就可以安装 `up` 了。
|
||||
|
||||
首先从 Ultimate Plumber 的[发布页面][1]下载最新的二进制文件,并将放在你系统的某个路径下,例如`/usr/local/bin/`。
|
||||
首先从 Ultimate Plumber 的[发布页面][1]下载最新的二进制文件,并将放在你系统的某个路径下,例如 `/usr/local/bin/`。
|
||||
|
||||
```
|
||||
$ sudo wget -O /usr/local/bin/up wget https://github.com/akavel/up/releases/download/v0.2.1/up
|
||||
```
|
||||
|
||||
然后向 `UP` 二进制文件赋予可执行权限:
|
||||
然后向 `up` 二进制文件赋予可执行权限:
|
||||
|
||||
```
|
||||
$ sudo chmod a+x /usr/local/bin/up
|
||||
```
|
||||
|
||||
至此,你已经完成了 `UP` 的安装,可以开始编写你的管道命令了。
|
||||
|
||||
至此,你已经完成了 `up` 的安装,可以开始编写你的管道命令了。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -73,7 +74,7 @@ via: https://www.ostechnix.com/ultimate-plumber-writing-linux-pipes-with-instant
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
设计更快的网页(三):字体和 CSS 转换
|
||||
设计更快的网页(三):字体和 CSS 调整
|
||||
======
|
||||
|
||||

|
||||
|
||||
欢迎回到我们为了构建更快网页所写的系列文章。本系列的[第一][1]和[第二][2]部分讲述了如何通过优化和替换图片来减少浏览器脂肪。本部分会着眼于在 CSS([层叠式样式表][3])和字体中减掉更多的脂肪。
|
||||
欢迎回到我们为了构建更快网页所写的系列文章。本系列的[第一部分][1]和[第二部分][2]讲述了如何通过优化和替换图片来减少浏览器脂肪。本部分会着眼于在 CSS([层叠式样式表][3])和字体中减掉更多的脂肪。
|
||||
|
||||
### CSS 转换
|
||||
### 调整 CSS
|
||||
|
||||
首先,我们先来看看问题的源头。CSS 的出现曾是技术的一大进步。你可以用一个集中式的样式表来装饰多个网页。如今很多 Web 开发者都会使用 Bootstrap 这样的框架。
|
||||
|
||||
@@ -35,7 +35,7 @@ Font-awesome CSS 代表了包含未使用样式的极端。这个页面中只用
|
||||
current free version 912 glyphs/icons, smallest set ttf 30.9KB, woff 14.7KB, woff2 12.2KB, svg 107.2KB, eot 31.2
|
||||
```
|
||||
|
||||
所以问题是,你需要所有的字形吗?很可能不需要。你可以通过 [FontForge][10] 来摆脱这些无用字形,但这需要很大的工作量。你还可以用 [Fontello][11]. 你可以使用公共实例,也可以配置你自己的版本,因为它是自由软件,可以在 [Github][12] 上找到。
|
||||
所以问题是,你需要所有的字形吗?很可能不需要。你可以通过 [FontForge][10] 来去除这些无用字形,但这需要很大的工作量。你还可以用 [Fontello][11]. 你可以使用公共实例,也可以配置你自己的版本,因为它是自由软件,可以在 [Github][12] 上找到。
|
||||
|
||||
这种自定义字体集的缺点在于,你必须自己来托管字体文件。你也没法使用其它在线服务来提供更新。但与更快的性能相比,这可能算不上一个缺点。
|
||||
|
||||
@@ -53,14 +53,14 @@ via: https://fedoramagazine.org/design-faster-web-pages-part-3-font-css-tweaks/
|
||||
作者:[Sirko Kemter][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[StdioA](https://github.com/StdioA)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/gnokii/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/design-faster-web-pages-part-1-image-compression/
|
||||
[2]: https://fedoramagazine.org/design-faster-web-pages-part-2-image-replacement/
|
||||
[1]: https://linux.cn/article-10166-1.html
|
||||
[2]: https://linux.cn/article-10217-1.html
|
||||
[3]: https://en.wikipedia.org/wiki/Cascading_Style_Sheets
|
||||
[4]: https://getfedora.org
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2018/02/CSS_delivery_tool_-_Examine_how_a_page_uses_CSS_-_2018-02-24_15.00.46.png
|
||||
@@ -1,32 +1,28 @@
|
||||
Python 机器学习的必备技巧
|
||||
======
|
||||
|
||||
> 尝试使用 Python 掌握机器学习、人工智能和深度学习。
|
||||
|
||||

|
||||
|
||||
想要入门机器学习并不难。除了<ruby>大规模网络公开课<rt>Massive Open Online Courses</rt></ruby>(MOOCs)之外,还有很多其它优秀的免费资源。下面我分享一些我觉得比较有用的方法。
|
||||
想要入门机器学习并不难。除了<ruby>大规模网络公开课<rt>Massive Open Online Courses</rt></ruby>(MOOC)之外,还有很多其它优秀的免费资源。下面我分享一些我觉得比较有用的方法。
|
||||
|
||||
1. 阅览一些关于这方面的视频、文章或者书籍,例如 [The Master Algorithm: How the Quest for the Ultimate Learning Machine Will Remake Our World][29],你肯定会喜欢这些[关于机器学习的互动页面][30]。
|
||||
|
||||
2. 对于“机器学习”、“人工智能”、“深度学习”、“数据科学”、“计算机视觉”和“机器人技术”这一堆新名词,你需要知道它们之前的区别。你可以阅览这些领域的专家们的演讲,例如[数据科学家 Brandon Rohrer 的这个视频][1]。
|
||||
|
||||
3. 明确你自己的学习目标,并选择合适的 [Coursera 课程][3],或者参加高校的网络公开课。例如[华盛顿大学的课程][4]就很不错。
|
||||
|
||||
4. 关注优秀的博客:例如 [KDnuggets][32] 的博客、[Mark Meloon][33] 的博客、[Brandon Rohrer][34] 的博客、[Open AI][35] 的博客,这些都值得推荐。
|
||||
|
||||
5. 如果你对在线课程有很大兴趣,后文中会有如何[正确选择 MOOC 课程][31]的指导。
|
||||
|
||||
6. 最重要的是,培养自己对这些技术的兴趣。加入一些优秀的社交论坛,专注于阅读和了解,将这些技术的背景知识和发展方向理解透彻,并积极思考在日常生活和工作中如何应用机器学习或数据科学的原理。例如建立一个简单的回归模型来预测下一次午餐的成本,又或者是从电力公司的网站上下载历史电费数据,在 Excel 中进行简单的时序分析以发现某种规律。在你对这些技术产生了浓厚兴趣之后,可以观看以下这个视频。
|
||||
1. 从一些 YouTube 上的好视频开始,阅览一些关于这方面的文章或者书籍,例如 《[主算法:终极学习机器的探索将如何重塑我们的世界][29]》,而且我觉得你肯定会喜欢这些[关于机器学习的很酷的互动页面][30]。
|
||||
2. 对于“<ruby>机器学习<rt>machine learning</rt></ruby>”、“<ruby>人工智能<rt>artificial intelligence</rt></ruby>”、“<ruby>深度学习<rt>deep learning</rt></ruby>”、“<ruby>数据科学<rt>data science</rt></ruby>”、“<ruby>计算机视觉<rt>computer vision</rt></ruby>”和“<ruby>机器人技术<rt>robotics</rt></ruby>”这一堆新名词,你需要知道它们之间的区别。你可以阅览或聆听这些领域的专家们的演讲,例如这位有影响力的[数据科学家 Brandon Rohrer 的精彩视频][1]。或者这个讲述了数据科学相关的[各种角色之间的区别][2]的视频。
|
||||
3. 明确你自己的学习目标,并选择合适的 [Coursera 课程][3],或者参加高校的网络公开课,例如[华盛顿大学的课程][4]就很不错。
|
||||
4. 关注优秀的博客:例如 [KDnuggets][32] 的博客、[Mark Meloon][33] 的博客、[Brandon Rohrer][34] 的博客、[Open AI][35] 的研究博客,这些都值得推荐。
|
||||
5. 如果你热衷于在线课程,后文中会有如何[正确选择 MOOC 课程][31]的指导。
|
||||
6. 最重要的是,培养自己对这些技术的兴趣。加入一些优秀的社交论坛,不要被那些耸人听闻的头条和新闻所吸引,专注于阅读和了解,将这些技术的背景知识和发展方向理解透彻,并积极思考在日常生活和工作中如何应用机器学习或数据科学的原理。例如建立一个简单的回归模型来预测下一次午餐的成本,又或者是从电力公司的网站上下载历史电费数据,在 Excel 中进行简单的时序分析以发现某种规律。在你对这些技术产生了浓厚兴趣之后,可以观看以下这个视频。
|
||||
|
||||
<https://www.youtube.com/embed/IpGxLWOIZy4>
|
||||
|
||||
### Python 是机器学习和人工智能方面的最佳语言吗?
|
||||
|
||||
除非你是一名专业的研究一些复杂算法纯理论证明的研究人员,否则,对于一个机器学习的入门者来说,需要熟悉至少一种高级编程语言一家相关的专业知识。因为大多数情况下都是需要考虑如何将机器学习算法应用于解决实际问题,而这需要有一定的编程能力作为基础。
|
||||
除非你是一名专业的研究一些复杂算法纯理论证明的研究人员,否则,对于一个机器学习的入门者来说,需要熟悉至少一种高级编程语言。因为大多数情况下都是需要考虑如何将现有的机器学习算法应用于解决实际问题,而这需要有一定的编程能力作为基础。
|
||||
|
||||
哪一种语言是数据科学的最佳语言?这个讨论一直没有停息过。对于这方面,你可以提起精神来看一下 FreeCodeCamp 上这一篇关于[数据科学语言][6]的文章,又或者是 KDnuggets 关于 [Python 和 R][7] 之间的深入探讨。
|
||||
哪一种语言是数据科学的最佳语言?这个讨论一直没有停息过。对于这方面,你可以提起精神来看一下 FreeCodeCamp 上这一篇关于[数据科学语言][6]的文章,又或者是 KDnuggets 关于 [Python 和 R 之争][7]的深入探讨。
|
||||
|
||||
目前人们普遍认为 Python 在开发、部署、维护各方面的效率都是比较高的。与 Java、C 和 C++ 这些较为传统的语言相比,Python 的语法更为简单和高级。而且 Python 拥有活跃的社区群体、广泛的开源文化、数百个专用于机器学习的优质代码库,以及来自业界巨头(包括Google、Dropbox、Airbnb 等)的强大技术支持。
|
||||
目前人们普遍认为 Python 在开发、部署、维护各方面的效率都是比较高的。与 Java、C 和 C++ 这些较为传统的语言相比,Python 的语法更为简单和高级。而且 Python 拥有活跃的社区群体、广泛的开源文化、数百个专用于机器学习的优质代码库,以及来自业界巨头(包括 Google、Dropbox、Airbnb 等)的强大技术支持。
|
||||
|
||||
### 基础 Python 库
|
||||
|
||||
@@ -46,7 +42,7 @@ Pandas 是 Python 生态中用于进行通用数据分析的最受欢迎的库
|
||||
* 选择数据子集
|
||||
* 跨行列计算
|
||||
* 查找并补充缺失的数据
|
||||
* 将操作应用于数据中的独立组
|
||||
* 将操作应用于数据中的独立分组
|
||||
* 按照多种格式转换数据
|
||||
* 组合多个数据集
|
||||
* 高级时间序列功能
|
||||
@@ -68,7 +64,7 @@ Pandas 是 Python 生态中用于进行通用数据分析的最受欢迎的库
|
||||
|
||||
#### Scikit-learn
|
||||
|
||||
Scikit-learn 是机器学习方面通用的重要 Python 包。它实现了多种[分类][16]、[回归][17]和[聚类][18]算法,包括[支持向量机][19]、[随机森林][20]、[梯度增强][21]、[k-means 算法][22]和 [DBSCAN 算法][23],可以与 Python 的数值库 NumPy 和科学计算库 [SciPy][24] 结合使用。它通过兼容的接口提供了有监督和无监督的学习算法。Scikit-learn 的强壮性让它可以稳定运行在生产环境中,同时它在易用性、代码质量、团队协作、文档和性能等各个方面都有良好的表现。可以参考这篇基于 Scikit-learn 的[机器学习入门][25],或者这篇基于 Scikit-learn 的[简单机器学习用例演示][26]。
|
||||
Scikit-learn 是机器学习方面通用的重要 Python 包。它实现了多种[分类][16]、[回归][17]和[聚类][18]算法,包括[支持向量机][19]、[随机森林][20]、[梯度增强][21]、[k-means 算法][22]和 [DBSCAN 算法][23],可以与 Python 的数值库 NumPy 和科学计算库 [SciPy][24] 结合使用。它通过兼容的接口提供了有监督和无监督的学习算法。Scikit-learn 的强壮性让它可以稳定运行在生产环境中,同时它在易用性、代码质量、团队协作、文档和性能等各个方面都有良好的表现。可以参考[这篇基于 Scikit-learn 的机器学习入门][25],或者[这篇基于 Scikit-learn 的简单机器学习用例演示][26]。
|
||||
|
||||
本文使用 [CC BY-SA 4.0][28] 许可,在 [Heartbeat][27] 上首发。
|
||||
|
||||
@@ -79,7 +75,7 @@ via: https://opensource.com/article/18/10/machine-learning-python-essential-hack
|
||||
作者:[Tirthajyoti Sarkar][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
我们如何得知安装的包来自哪个仓库?
|
||||
==========
|
||||
|
||||
有时候你可能想知道安装的软件包来自于哪个仓库。这将帮助你在遇到包冲突问题时进行故障排除。
|
||||
|
||||
因为[第三方仓库][1]拥有最新版本的软件包,所以有时候当你试图安装一些包的时候会出现兼容性的问题。
|
||||
|
||||
在 Linux 上一切都是可能的,因为你可以安装一个即使在你的发行版系统上不能使用的包。
|
||||
|
||||
你也可以安装一个最新版本的包,即使你的发行版系统仓库还没有这个版本,怎么做到的呢?
|
||||
|
||||
这就是为什么出现了第三方仓库。它们允许用户从库中安装所有可用的包。
|
||||
|
||||
几乎所有的发行版系统都允许第三方软件库。一些发行版还会官方推荐一些不会取代基础仓库的第三方仓库,例如 CentOS 官方推荐安装 [EPEL 库][2]。
|
||||
|
||||
下面是常用的仓库列表和它们的详细信息。
|
||||
|
||||
* CentOS: [EPEL][2]、[ELRepo][3] 等是 [Centos 社区认证仓库](4)。
|
||||
* Fedora: [RPMfusion 仓库][5] 是经常被很多 [Fedora][6] 用户使用的仓库。
|
||||
* ArchLinux: ArchLinux 社区仓库包含了来自于 Arch 用户仓库的可信用户审核通过的软件包。
|
||||
* openSUSE: [Packman 仓库][7] 为 openSUSE 提供了各种附加的软件包,特别是但不限于那些在 openSUSE Build Service 应用黑名单上的与多媒体相关的应用和库。它是 openSUSE 软件包的最大外部软件库。
|
||||
* Ubuntu:个人软件包归档(PPA)是一种软件仓库。开发者们可以创建这种仓库来分发他们的软件。你可以在 PPA 导航页面找到相关信息。同时,你也可以启用 Cananical 合作伙伴软件仓库。
|
||||
|
||||
### 仓库是什么?
|
||||
|
||||
软件仓库是存储特定的应用程序的软件包的集中场所。
|
||||
|
||||
所有的 Linux 发行版都在维护他们自己的仓库,并允许用户在他们的机器上获取和安装包。
|
||||
|
||||
每个厂商都提供了各自的包管理工具来管理它们的仓库,例如搜索、安装、更新、升级、删除等等。
|
||||
|
||||
除了 RHEL 和 SUSE 以外大部分 Linux 发行版都是自由软件。要访问付费的仓库,你需要购买其订阅服务。
|
||||
|
||||
### 为什么我们需要启用第三方仓库?
|
||||
|
||||
在 Linux 里,并不建议从源代码安装包,因为这样做可能会在升级软件和系统的时候产生很多问题,这也是为什么我们建议从库中安装包而不是从源代码安装。
|
||||
|
||||
### 在 RHEL/CentOS 系统上我们如何得知安装的软件包来自哪个仓库?
|
||||
|
||||
这可以通过很多方法实现。我们会给你所有可能的选择,你可以选择一个对你来说最合适的。
|
||||
|
||||
#### 方法-1:使用 yum 命令
|
||||
|
||||
RHEL 和 CentOS 系统使用 RPM 包,因此我们能够使用 [Yum 包管理器][8] 来获得信息。
|
||||
|
||||
YUM 即 “Yellodog Updater, Modified” 是适用于基于 RPM 的系统例如 RHEL 和 CentOS 的一个开源命令行前端包管理工具。
|
||||
|
||||
`yum` 是从发行版仓库和其他第三方库中获取、安装、删除、查询和管理 RPM 包的一个主要工具。
|
||||
|
||||
```
|
||||
# yum info apachetop
|
||||
Loaded plugins: fastestmirror
|
||||
Loading mirror speeds from cached hostfile
|
||||
* epel: epel.mirror.constant.com
|
||||
Installed Packages
|
||||
Name : apachetop
|
||||
Arch : x86_64
|
||||
Version : 0.15.6
|
||||
Release : 1.el7
|
||||
Size : 65 k
|
||||
Repo : installed
|
||||
From repo : epel
|
||||
Summary : A top-like display of Apache logs
|
||||
URL : https://github.com/tessus/apachetop
|
||||
License : BSD
|
||||
Description : ApacheTop watches a logfile generated by Apache (in standard common or
|
||||
: combined logformat, although it doesn't (yet) make use of any of the extra
|
||||
: fields in combined) and generates human-parsable output in realtime.
|
||||
```
|
||||
|
||||
`apachetop` 包来自 EPEL 仓库。
|
||||
|
||||
#### 方法-2:使用 yumdb 命令
|
||||
|
||||
`yumdb info` 提供了类似于 `yum info` 的信息但是它又提供了包校验和数据、类型、用户信息(谁安装的软件包)。从 yum 3.2.26 开始,yum 已经开始在 rpmdatabase 之外存储额外的信息(user 表示软件是用户安装的,dep 表示它是作为依赖项引入的)。
|
||||
|
||||
```
|
||||
# yumdb info lighttpd
|
||||
Loaded plugins: fastestmirror
|
||||
lighttpd-1.4.50-1.el7.x86_64
|
||||
checksum_data = a24d18102ed40148cfcc965310a516050ed437d728eeeefb23709486783a4d37
|
||||
checksum_type = sha256
|
||||
command_line = --enablerepo=epel install lighttpd apachetop aria2 atop axel
|
||||
from_repo = epel
|
||||
from_repo_revision = 1540756729
|
||||
from_repo_timestamp = 1540757483
|
||||
installed_by = 0
|
||||
origin_url = https://epel.mirror.constant.com/7/x86_64/Packages/l/lighttpd-1.4.50-1.el7.x86_64.rpm
|
||||
reason = user
|
||||
releasever = 7
|
||||
var_contentdir = centos
|
||||
var_infra = stock
|
||||
var_uuid = ce328b07-9c0a-4765-b2ad-59d96a257dc8
|
||||
```
|
||||
|
||||
`lighttpd` 包来自 EPEL 仓库。
|
||||
|
||||
#### 方法-3:使用 rpm 命令
|
||||
|
||||
[RPM 命令][9] 即 “Red Hat Package Manager” 是一个适用于基于 Red Hat 的系统(例如 RHEL、CentOS、Fedora、openSUSE & Mageia)的强大的命令行包管理工具。
|
||||
|
||||
这个工具允许你在你的 Linux 系统/服务器上安装、更新、移除、查询和验证软件。RPM 文件具有 .rpm 后缀名。RPM 包是用必需的库和依赖关系构建的,不会与系统上安装的其他包冲突。
|
||||
|
||||
```
|
||||
# rpm -qi apachetop
|
||||
Name : apachetop
|
||||
Version : 0.15.6
|
||||
Release : 1.el7
|
||||
Architecture: x86_64
|
||||
Install Date: Mon 29 Oct 2018 06:47:49 AM EDT
|
||||
Group : Applications/Internet
|
||||
Size : 67020
|
||||
License : BSD
|
||||
Signature : RSA/SHA256, Mon 22 Jun 2015 09:30:26 AM EDT, Key ID 6a2faea2352c64e5
|
||||
Source RPM : apachetop-0.15.6-1.el7.src.rpm
|
||||
Build Date : Sat 20 Jun 2015 09:02:37 PM EDT
|
||||
Build Host : buildvm-22.phx2.fedoraproject.org
|
||||
Relocations : (not relocatable)
|
||||
Packager : Fedora Project
|
||||
Vendor : Fedora Project
|
||||
URL : https://github.com/tessus/apachetop
|
||||
Summary : A top-like display of Apache logs
|
||||
Description :
|
||||
ApacheTop watches a logfile generated by Apache (in standard common or
|
||||
combined logformat, although it doesn't (yet) make use of any of the extra
|
||||
fields in combined) and generates human-parsable output in realtime.
|
||||
```
|
||||
|
||||
`apachetop` 包来自 EPEL 仓库。
|
||||
|
||||
#### 方法-4:使用 repoquery 命令
|
||||
|
||||
`repoquery` 是一个从 YUM 库查询信息的程序,类似于 rpm 查询。
|
||||
|
||||
```
|
||||
# repoquery -i httpd
|
||||
|
||||
Name : httpd
|
||||
Version : 2.4.6
|
||||
Release : 80.el7.centos.1
|
||||
Architecture: x86_64
|
||||
Size : 9817285
|
||||
Packager : CentOS BuildSystem
|
||||
Group : System Environment/Daemons
|
||||
URL : http://httpd.apache.org/
|
||||
Repository : updates
|
||||
Summary : Apache HTTP Server
|
||||
Source : httpd-2.4.6-80.el7.centos.1.src.rpm
|
||||
Description :
|
||||
The Apache HTTP Server is a powerful, efficient, and extensible
|
||||
web server.
|
||||
```
|
||||
|
||||
`httpd` 包来自 CentOS updates 仓库。
|
||||
|
||||
### 在 Fedora 系统上我们如何得知安装的包来自哪个仓库?
|
||||
|
||||
DNF 是 “Dandified yum” 的缩写。DNF 是使用 hawkey/libsolv 库作为后端的下一代 yum 包管理器(yum 的分支)。从 Fedora 18 开始 Aleš Kozumplík 开始开发 DNF,并最终在 Fedora 22 上得以应用/启用。
|
||||
|
||||
[dnf 命令][10] 用于在 Fedora 22 以及之后的系统上安装、更新、搜索和删除包。它会自动解决依赖并使安装包的过程变得顺畅,不会出现任何问题。
|
||||
|
||||
```
|
||||
$ dnf info tilix
|
||||
Last metadata expiration check: 27 days, 10:00:23 ago on Wed 04 Oct 2017 06:43:27 AM IST.
|
||||
Installed Packages
|
||||
Name : tilix
|
||||
Version : 1.6.4
|
||||
Release : 1.fc26
|
||||
Arch : x86_64
|
||||
Size : 3.6 M
|
||||
Source : tilix-1.6.4-1.fc26.src.rpm
|
||||
Repo : @System
|
||||
From repo : updates
|
||||
Summary : Tiling terminal emulator
|
||||
URL : https://github.com/gnunn1/tilix
|
||||
License : MPLv2.0 and GPLv3+ and CC-BY-SA
|
||||
Description : Tilix is a tiling terminal emulator with the following features:
|
||||
:
|
||||
: - Layout terminals in any fashion by splitting them horizontally or vertically
|
||||
: - Terminals can be re-arranged using drag and drop both within and between
|
||||
: windows
|
||||
: - Terminals can be detached into a new window via drag and drop
|
||||
: - Input can be synchronized between terminals so commands typed in one
|
||||
: terminal are replicated to the others
|
||||
: - The grouping of terminals can be saved and loaded from disk
|
||||
: - Terminals support custom titles
|
||||
: - Color schemes are stored in files and custom color schemes can be created by
|
||||
: simply creating a new file
|
||||
: - Transparent background
|
||||
: - Supports notifications when processes are completed out of view
|
||||
:
|
||||
: The application was written using GTK 3 and an effort was made to conform to
|
||||
: GNOME Human Interface Guidelines (HIG).
|
||||
```
|
||||
|
||||
`tilix` 包来自 Fedora updates 仓库。
|
||||
|
||||
### 在 openSUSE 系统上我们如何得知安装的包来自哪个仓库?
|
||||
|
||||
Zypper 是一个使用 libzypp 的命令行包管理器。[Zypper 命令][11] 提供了存储库访问、依赖处理、包安装等功能。
|
||||
|
||||
```
|
||||
$ zypper info nano
|
||||
|
||||
Loading repository data...
|
||||
Reading installed packages...
|
||||
|
||||
|
||||
Information for package nano:
|
||||
-----------------------------
|
||||
Repository : Main Repository (OSS)
|
||||
Name : nano
|
||||
Version : 2.4.2-5.3
|
||||
Arch : x86_64
|
||||
Vendor : openSUSE
|
||||
Installed Size : 1017.8 KiB
|
||||
Installed : No
|
||||
Status : not installed
|
||||
Source package : nano-2.4.2-5.3.src
|
||||
Summary : Pico editor clone with enhancements
|
||||
Description :
|
||||
GNU nano is a small and friendly text editor. It aims to emulate
|
||||
the Pico text editor while also offering a few enhancements.
|
||||
```
|
||||
|
||||
`nano` 包来自于 openSUSE Main 仓库(OSS)。
|
||||
|
||||
### 在 ArchLinux 系统上我们如何得知安装的包来自哪个仓库?
|
||||
|
||||
[Pacman 命令][12] 即包管理器工具(package manager utility ),是一个简单的用来安装、构建、删除和管理 Arch Linux 软件包的命令行工具。Pacman 使用 libalpm 作为后端来执行所有的操作。
|
||||
|
||||
```
|
||||
# pacman -Ss chromium
|
||||
extra/chromium 48.0.2564.116-1
|
||||
The open-source project behind Google Chrome, an attempt at creating a safer, faster, and more stable browser
|
||||
extra/qt5-webengine 5.5.1-9 (qt qt5)
|
||||
Provides support for web applications using the Chromium browser project
|
||||
community/chromium-bsu 0.9.15.1-2
|
||||
A fast paced top scrolling shooter
|
||||
community/chromium-chromevox latest-1
|
||||
Causes the Chromium web browser to automatically install and update the ChromeVox screen reader extention. Note: This
|
||||
package does not contain the extension code.
|
||||
community/fcitx-mozc 2.17.2313.102-1
|
||||
Fcitx Module of A Japanese Input Method for Chromium OS, Windows, Mac and Linux (the Open Source Edition of Google Japanese
|
||||
Input)
|
||||
```
|
||||
|
||||
`chromium` 包来自 ArchLinux extra 仓库。
|
||||
|
||||
或者,我们可以使用以下选项获得关于包的详细信息。
|
||||
|
||||
```
|
||||
# pacman -Si chromium
|
||||
Repository : extra
|
||||
Name : chromium
|
||||
Version : 48.0.2564.116-1
|
||||
Description : The open-source project behind Google Chrome, an attempt at creating a safer, faster, and more stable browser
|
||||
Architecture : x86_64
|
||||
URL : http://www.chromium.org/
|
||||
Licenses : BSD
|
||||
Groups : None
|
||||
Provides : None
|
||||
Depends On : gtk2 nss alsa-lib xdg-utils bzip2 libevent libxss icu libexif libgcrypt ttf-font systemd dbus
|
||||
flac snappy speech-dispatcher pciutils libpulse harfbuzz libsecret libvpx perl perl-file-basedir
|
||||
desktop-file-utils hicolor-icon-theme
|
||||
Optional Deps : kdebase-kdialog: needed for file dialogs in KDE
|
||||
gnome-keyring: for storing passwords in GNOME keyring
|
||||
kwallet: for storing passwords in KWallet
|
||||
Conflicts With : None
|
||||
Replaces : None
|
||||
Download Size : 44.42 MiB
|
||||
Installed Size : 172.44 MiB
|
||||
Packager : Evangelos Foutras
|
||||
Build Date : Fri 19 Feb 2016 04:17:12 AM IST
|
||||
Validated By : MD5 Sum SHA-256 Sum Signature
|
||||
```
|
||||
|
||||
`chromium` 包来自 ArchLinux extra 仓库。
|
||||
|
||||
### 在基于 Debian 的系统上我们如何得知安装的包来自哪个仓库?
|
||||
|
||||
在基于 Debian 的系统例如 Ubuntu、LinuxMint 上可以使用两种方法实现。
|
||||
|
||||
#### 方法-1:使用 apt-cache 命令
|
||||
|
||||
[apt-cache 命令][13] 可以显示存储在 APT 内部数据库的很多信息。这些信息是一种缓存,因为它们是从列在 `source.list` 文件里的不同的源中获得的。这个过程发生在 apt 更新操作期间。
|
||||
|
||||
```
|
||||
$ apt-cache policy python3
|
||||
python3:
|
||||
Installed: 3.6.3-0ubuntu2
|
||||
Candidate: 3.6.3-0ubuntu3
|
||||
Version table:
|
||||
3.6.3-0ubuntu3 500
|
||||
500 http://in.archive.ubuntu.com/ubuntu artful-updates/main amd64 Packages
|
||||
*** 3.6.3-0ubuntu2 500
|
||||
500 http://in.archive.ubuntu.com/ubuntu artful/main amd64 Packages
|
||||
100 /var/lib/dpkg/status
|
||||
```
|
||||
|
||||
`python3` 包来自 Ubuntu updates 仓库。
|
||||
|
||||
#### 方法-2:使用 apt 命令
|
||||
|
||||
[APT 命令][14] 即 “Advanced Packaging Tool”,是 `apt-get` 命令的替代品,就像 DNF 是如何取代 YUM 一样。它是具有丰富功能的命令行工具并将所有的功能例如 `apt-cache`、`apt-search`、`dpkg`、`apt-cdrom`、`apt-config`、`apt-ket` 等包含在一个命令(APT)中,并且还有几个独特的功能。例如我们可以通过 APT 轻松安装 .dpkg 包,但我们不能使用 `apt-get` 命令安装,更多类似的功能都被包含进了 APT 命令。`apt-get` 因缺失了很多未被解决的特性而被 `apt` 取代。
|
||||
|
||||
```
|
||||
$ apt -a show notepadqq
|
||||
Package: notepadqq
|
||||
Version: 1.3.2-1~artful1
|
||||
Priority: optional
|
||||
Section: editors
|
||||
Maintainer: Daniele Di Sarli
|
||||
Installed-Size: 1,352 kB
|
||||
Depends: notepadqq-common (= 1.3.2-1~artful1), coreutils (>= 8.20), libqt5svg5 (>= 5.2.1), libc6 (>= 2.14), libgcc1 (>= 1:3.0), libqt5core5a (>= 5.9.0~beta), libqt5gui5 (>= 5.7.0), libqt5network5 (>= 5.2.1), libqt5printsupport5 (>= 5.2.1), libqt5webkit5 (>= 5.6.0~rc), libqt5widgets5 (>= 5.2.1), libstdc++6 (>= 5.2)
|
||||
Download-Size: 356 kB
|
||||
APT-Sources: http://ppa.launchpad.net/notepadqq-team/notepadqq/ubuntu artful/main amd64 Packages
|
||||
Description: Notepad++-like editor for Linux
|
||||
Text editor with support for multiple programming
|
||||
languages, multiple encodings and plugin support.
|
||||
|
||||
Package: notepadqq
|
||||
Version: 1.2.0-1~artful1
|
||||
Status: install ok installed
|
||||
Priority: optional
|
||||
Section: editors
|
||||
Maintainer: Daniele Di Sarli
|
||||
Installed-Size: 1,352 kB
|
||||
Depends: notepadqq-common (= 1.2.0-1~artful1), coreutils (>= 8.20), libqt5svg5 (>= 5.2.1), libc6 (>= 2.14), libgcc1 (>= 1:3.0), libqt5core5a (>= 5.9.0~beta), libqt5gui5 (>= 5.7.0), libqt5network5 (>= 5.2.1), libqt5printsupport5 (>= 5.2.1), libqt5webkit5 (>= 5.6.0~rc), libqt5widgets5 (>= 5.2.1), libstdc++6 (>= 5.2)
|
||||
Homepage: http://notepadqq.altervista.org
|
||||
Download-Size: unknown
|
||||
APT-Manual-Installed: yes
|
||||
APT-Sources: /var/lib/dpkg/status
|
||||
Description: Notepad++-like editor for Linux
|
||||
Text editor with support for multiple programming
|
||||
languages, multiple encodings and plugin support.
|
||||
```
|
||||
|
||||
`notepadqq` 包来自 Launchpad PPA。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-do-we-find-out-the-installed-packages-came-from-which-repository/
|
||||
|
||||
作者:[Prakash Subramanian][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[zianglei](https://github.com/zianglei)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/prakash/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/category/repository/
|
||||
[2]: https://www.2daygeek.com/install-enable-epel-repository-on-rhel-centos-scientific-linux-oracle-linux/
|
||||
[3]: https://www.2daygeek.com/install-enable-elrepo-on-rhel-centos-scientific-linux/
|
||||
[4]: https://www.2daygeek.com/additional-yum-repositories-for-centos-rhel-fedora-systems/
|
||||
[5]: https://www.2daygeek.com/install-enable-rpm-fusion-repository-on-centos-fedora-rhel/
|
||||
[6]: https://fedoraproject.org/wiki/Third_party_repositories
|
||||
[7]: https://www.2daygeek.com/install-enable-packman-repository-on-opensuse-leap/
|
||||
[8]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
|
||||
[9]: https://www.2daygeek.com/rpm-command-examples/
|
||||
[10]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
|
||||
[11]: https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
|
||||
[12]: https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
|
||||
[13]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[14]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
@@ -0,0 +1,58 @@
|
||||
8 个出没于终端中的吓人命令
|
||||
======
|
||||
|
||||
> 欢迎来到 Linux 令人毛骨悚然的一面。
|
||||
|
||||

|
||||
|
||||
又是一年中的这个时候:天气变冷了、树叶变色了,各处的孩子都化妆成了小鬼、妖精和僵尸。(LCTT 译注:本文原发表于万圣节)但你知道吗, Unix (和 Linux) 和它们的各个分支也充满了令人毛骨悚然的东西?让我们来看一下我们所熟悉和喜爱的操作系统的一些令人毛骨悚然的一面。
|
||||
|
||||
### 半神(守护进程)
|
||||
|
||||
如果没有潜伏于系统中的各种<ruby>守护进程<rt>daemon</rt></ruby>,那么 Unix 就没什么不同。守护进程是运行在后台的进程,并为用户和操作系统本身提供有用的服务,比如 SSH、FTP、HTTP 等等。
|
||||
|
||||
### 僵尸(僵尸进程)
|
||||
|
||||
不时出现的僵尸进程是一种被杀死但是拒绝离开的进程。当它出现时,无疑你只能选择你有的工具来赶走它。僵尸进程通常表明产生它的进程出现了问题。
|
||||
|
||||
### 杀死(kill)
|
||||
|
||||
你不仅可以使用 `kill` 来干掉一个僵尸进程,你还可以用它杀死任何对你系统产生负面影响的进程。有一个使用太多 RAM 或 CPU 周期的进程?使用 `kill` 命令杀死它。
|
||||
|
||||
### 猫(cat)
|
||||
|
||||
`cat` 和猫科动物无关,但是与文件操作有关:`cat` 是 “concatenate” 的缩写。你甚至可以使用这个方便的命令来查看文件的内容。
|
||||
|
||||
### 尾巴(tail)
|
||||
|
||||
当你想要查看文件中最后 n 行时,`tail` 命令很有用。当你想要监控一个文件时,它也很棒。
|
||||
|
||||
### 巫师(which)
|
||||
|
||||
哦,不,它不是巫师(witch)的一种。而是打印传递给它的命令所在的文件位置的命令。例如,`which python` 将在你系统上打印每个版本的 Python 的位置。
|
||||
|
||||
### 地下室(crypt)
|
||||
|
||||
`crypt` 命令,以前称为 `mcrypt`,当你想要加密(encrypt)文件的内容时,它是很方便的,这样除了你之外没有人可以读取它。像大多数 Unix 命令一样,你可以单独使用 `crypt` 或在系统脚本中调用它。
|
||||
|
||||
### 切碎(shred)
|
||||
|
||||
当你不仅要删除文件还想要确保没有人能够恢复它时,`shred` 命令很方便。使用 `rm` 命令删除文件是不够的。你还需要覆盖该文件以前占用的空间。这就是 `shred` 的用武之地。
|
||||
|
||||
这些只是你会在 Unix 中发现的一部分令人毛骨悚然的东西。你还知道其他诡异的命令么?请随时告诉我。
|
||||
|
||||
万圣节快乐!(LCTT:可惜我们翻译完了,只能将恐怖的感觉延迟了 :D)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/10/spookier-side-unix-linux
|
||||
|
||||
作者:[Patrick H.Mullins][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/pmullins
|
||||
[b]: https://github.com/lujun9972
|
||||
@@ -0,0 +1,73 @@
|
||||
KRS:一个收集 Kubernetes 资源统计数据的新工具
|
||||
======
|
||||
|
||||
> 零配置工具简化了信息收集,例如在某个命名空间中运行了多少个 pod。
|
||||
|
||||

|
||||
|
||||
最近我在纽约的 O'Reilly Velocity 就 [Kubernetes 应用故障排除][1]的主题发表了演讲,并且在积极的反馈和讨论的推动下,我决定重新审视这个领域的工具。结果,除了 [kubernetes-incubator/spartakus][2] 和 [kubernetes/kube-state-metrics][3] 之外,我们还没有太多的轻量级工具来收集资源统计数据(例如命名空间中的 pod 或服务的数量)。所以,我在回家的路上开始编写一个小工具 —— 创造性地命名为 `krs`,它是 Kubernetes Resource Stats 的简称 ,它允许你收集这些统计数据。
|
||||
|
||||
你可以通过两种方式使用 [mhausenblas/krs][5]:
|
||||
|
||||
* 直接在命令行(有 Linux、Windows 和 MacOS 的二进制文件),以及
|
||||
* 在集群中使用 [launch.sh][4] 脚本部署,该脚本动态创建适当的基于角色的访问控制(RBAC) 权限。
|
||||
|
||||
提醒你,它还在早期,并且还在开发中。但是,`krs` 的 0.1 版本提供以下功能:
|
||||
|
||||
* 在每个命名空间的基础上,它定期收集资源统计信息(支持 pod、部署和服务)。
|
||||
* 它以 [OpenMetrics 格式][6]公开这些统计。
|
||||
* 它可以直接通过二进制文件使用,也可以在包含所有依赖项的容器化设置中使用。
|
||||
|
||||
目前,你需要安装并配置 `kubectl`,因为 `krs` 依赖于执行 `kubectl get all` 命令来收集统计数据。(另一方面,谁会使用 Kubernetes 但没有安装 `kubectl` 呢?)
|
||||
|
||||
使用 `krs` 很简单。[下载][7]适合你平台的二进制文件,并按如下方式执行:
|
||||
|
||||
```
|
||||
$ krs thenamespacetowatch
|
||||
# HELP pods Number of pods in any state, for example running
|
||||
# TYPE pods gauge
|
||||
pods{namespace="thenamespacetowatch"} 13
|
||||
# HELP deployments Number of deployments
|
||||
# TYPE deployments gauge
|
||||
deployments{namespace="thenamespacetowatch"} 6
|
||||
# HELP services Number of services
|
||||
# TYPE services gauge
|
||||
services{namespace="thenamespacetowatch"} 4
|
||||
```
|
||||
|
||||
这将在前台启动 `krs`,从名称空间 `thenamespacetowatch` 收集资源统计信息,并分别在标准输出中以 OpenMetrics 格式输出它们,以供你进一步处理。
|
||||
|
||||
![krs screenshot][9]
|
||||
|
||||
*krs 实战截屏*
|
||||
|
||||
也许你会问,Michael,为什么它不能做一些有用的事(例如将指标存储在 S3 中)?因为 [Unix 哲学][10]。
|
||||
|
||||
对于那些想知道他们是否可以直接使用 Prometheus 或 [kubernetes/kube-state-metrics][3] 来完成这项任务的人:是的,你可以,为什么不行呢? `krs` 的重点是作为已有工具的轻量级且易于使用的替代品 —— 甚至可能在某些方面略微互补。
|
||||
|
||||
本文最初发表在 [Medium 的 ITNext][11] 上,并获得授权转载。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/kubernetes-resource-statistics
|
||||
|
||||
作者:[Michael Hausenblas][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mhausenblas
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://troubleshooting.kubernetes.sh/
|
||||
[2]: https://github.com/kubernetes-incubator/spartakus
|
||||
[3]: https://github.com/kubernetes/kube-state-metrics
|
||||
[4]: https://github.com/mhausenblas/krs/blob/master/launch.sh
|
||||
[5]: https://github.com/mhausenblas/krs
|
||||
[6]: https://openmetrics.io/
|
||||
[7]: https://github.com/mhausenblas/krs/releases
|
||||
[8]: /file/412706
|
||||
[9]: https://opensource.com/sites/default/files/uploads/krs_screenshot.png (krs screenshot)
|
||||
[10]: http://harmful.cat-v.org/cat-v/
|
||||
[11]: https://itnext.io/kubernetes-resource-statistics-e8247f92b45c
|
||||
@@ -0,0 +1,111 @@
|
||||
CPod:一个开源、跨平台播客应用
|
||||
======
|
||||
|
||||
播客是一个很好的娱乐和获取信息的方式。事实上,我会听十几个不同的播客,包括技术、神秘事件、历史和喜剧。当然,[Linux 播客][1]也在此列表中。
|
||||
|
||||
今天,我们将看一个简单的跨平台应用来收听你的播客。
|
||||
|
||||
![][2]
|
||||
|
||||
*推荐的播客和播客搜索*
|
||||
|
||||
### 应用程序
|
||||
|
||||
[CPod][3] 是 [Zack Guard(z-------------)][4] 的作品。**它是一个 [Election][5] 程序**,这使它能够在大多数操作系统(Linux、Windows、Mac OS)上运行。
|
||||
|
||||
> 一个小事:CPod 最初被命名为 Cumulonimbus。
|
||||
|
||||
应用的大部分被两个面板占用,来显示内容和选项。屏幕左侧的小条让你可以使用应用的不同功能。CPod 的不同栏目包括主页、队列、订阅、浏览和设置。
|
||||
|
||||
![cpod settings][6]
|
||||
|
||||
*设置*
|
||||
|
||||
### CPod 的功能
|
||||
|
||||
以下是 CPod 提供的功能列表:
|
||||
|
||||
* 简洁,干净的设计
|
||||
* 可在主流计算机平台上使用
|
||||
* 有 Snap 包
|
||||
* 搜索 iTunes 的播客目录
|
||||
* 可下载也可无需下载就播放节目
|
||||
* 查看播客信息和节目
|
||||
* 搜索播客的个别节目
|
||||
* 深色模式
|
||||
* 改变播放速度
|
||||
* 键盘快捷键
|
||||
* 将你的播客订阅与 gpodder.net 同步
|
||||
* 导入和导出订阅
|
||||
* 根据长度、日期、下载状态和播放进度对订阅进行排序
|
||||
* 在应用启动时自动获取新节目
|
||||
* 多语言支持
|
||||
|
||||
|
||||
![search option in cpod application][7]
|
||||
|
||||
*搜索 ZFS 节目*
|
||||
|
||||
### 在 Linux 上体验 CPod
|
||||
|
||||
我最后在两个系统上安装了 CPod:ArchLabs 和 Windows。[Arch 用户仓库][8] 中有两个版本的 CPod。但是,它们都已过时,一个是版本 1.14.0,另一个是 1.22.6。最新版本的 CPod 是 1.27.0。由于 ArchLabs 和 Windows 之间的版本差异,我的体验有所不同。在本文中,我将重点关注 1.27.0,因为它是最新且功能最多的。
|
||||
|
||||
我马上能够找到我最喜欢的播客。我可以粘贴 RSS 源的 URL 来添加 iTunes 列表中没有的那些播客。
|
||||
|
||||
找到播客的特定节目也很容易。例如,我最近在寻找 [Late Night Linux][9] 中的一集,这集中他们在谈论 [ZFS][10]。我点击播客,在搜索框中输入 “ZFS” 然后找到了它。
|
||||
|
||||
我很快发现播放一堆播客节目的最简单方法是将它们添加到队列中。一旦它们进入队列,你可以流式传输或下载它们。你也可以通过拖放重新排序它们。每集在播放时,它会显示可视化的声波以及节目摘要。
|
||||
|
||||
### 安装 CPod
|
||||
|
||||
在 [GitHub][11] 上,你可以下载适用于 Linux 的 AppImage 或 Deb 文件,适用于 Windows 的 .exe 文件或适用于 Mac OS 的 .dmg 文件。
|
||||
|
||||
你可以使用 [Snap][12] 安装 CPod。你需要做的就是使用以下命令:
|
||||
|
||||
```
|
||||
sudo snap install cpod
|
||||
```
|
||||
|
||||
就像我之前说的那样,CPod 的 [Arch 用户仓库][8]的版本已经过时了。我已经给其中一个打包者发了消息。如果你使用 Arch(或基于 Arch 的发行版),我建议你这样做。
|
||||
|
||||
![cpod for Linux pidcasts][13]
|
||||
|
||||
*播放其中一个我最喜欢的播客*
|
||||
|
||||
### 最后的想法
|
||||
|
||||
总的来说,我喜欢 CPod。它外观漂亮,使用简单。事实上,我更喜欢原来的名字(Cumulonimbus),但是它有点拗口。
|
||||
|
||||
我刚刚在程序中遇到两个问题。首先,我希望每个播客都有评分。其次,在打开黑暗模式后,根据长度、日期、下载状态和播放进度对剧集进行排序的菜单不起作用。
|
||||
|
||||
你有没有用过 CPod?如果没有,你最喜欢的播客应用是什么?你最喜欢的播客有哪些?请在下面的评论中告诉我们。
|
||||
|
||||
如果你发现这篇文章很有意思,请花一点时间在社交媒体、Hacker News 或 [Reddit][14] 上分享它。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/cpod-podcast-app/
|
||||
|
||||
作者:[John Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/john/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/linux-podcasts/
|
||||
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/10/cpod1.1.jpg?w=800&ssl=1
|
||||
[3]: https://github.com/z-------------/CPod
|
||||
[4]: https://github.com/z-------------
|
||||
[5]: https://electronjs.org/
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/10/cpod2.1.png?w=800&ssl=1
|
||||
[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/10/cpod4.1.jpg?w=800&ssl=1
|
||||
[8]: https://aur.archlinux.org/packages/?O=0&K=cpod
|
||||
[9]: https://latenightlinux.com/
|
||||
[10]: https://itsfoss.com/what-is-zfs/
|
||||
[11]: https://github.com/z-------------/CPod/releases
|
||||
[12]: https://snapcraft.io/cumulonimbus
|
||||
[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/10/cpod3.1.jpg?w=800&ssl=1
|
||||
[14]: http://reddit.com/r/linuxusersgroup
|
||||
@@ -0,0 +1,229 @@
|
||||
命令行快速技巧:如何定位一个文件
|
||||
======
|
||||
|
||||

|
||||
|
||||
我们都会有文件存储在电脑里 —— 目录、相片、源代码等等。它们是如此之多。也无疑超出了我的记忆范围。要是毫无目标,找到正确的那一个可能会很费时间。在这篇文章里我们来看一下如何在命令行里找到需要的文件,特别是快速找到你想要的那一个。
|
||||
|
||||
好消息是 Linux 命令行专门设计了很多非常有用的命令行工具在你的电脑上查找文件。下面我们看一下它们其中三个:`ls`、`tree` 和 `find`。
|
||||
|
||||
### ls
|
||||
|
||||
如果你知道文件在哪里,你只需要列出它们或者查看有关它们的信息,`ls` 就是为此而生的。
|
||||
|
||||
只需运行 `ls` 就可以列出当下目录中所有可见的文件和目录:
|
||||
|
||||
```
|
||||
$ ls
|
||||
Documents Music Pictures Videos notes.txt
|
||||
```
|
||||
|
||||
添加 `-l` 选项可以查看文件的相关信息。同时再加上 `-h` 选项,就可以用一种人们易读的格式查看文件的大小:
|
||||
|
||||
```
|
||||
$ ls -lh
|
||||
total 60K
|
||||
drwxr-xr-x 2 adam adam 4.0K Nov 2 13:07 Documents
|
||||
drwxr-xr-x 2 adam adam 4.0K Nov 2 13:07 Music
|
||||
drwxr-xr-x 2 adam adam 4.0K Nov 2 13:13 Pictures
|
||||
drwxr-xr-x 2 adam adam 4.0K Nov 2 13:07 Videos
|
||||
-rw-r--r-- 1 adam adam 43K Nov 2 13:12 notes.txt
|
||||
```
|
||||
|
||||
`ls` 也可以搜索一个指定位置:
|
||||
|
||||
```
|
||||
$ ls Pictures/
|
||||
trees.png wallpaper.png
|
||||
```
|
||||
|
||||
或者一个指定文件 —— 即便只跟着名字的一部分:
|
||||
|
||||
```
|
||||
$ ls *.txt
|
||||
notes.txt
|
||||
```
|
||||
|
||||
少了点什么?想要查看一个隐藏文件?没问题,使用 `-a` 选项:
|
||||
|
||||
```
|
||||
$ ls -a
|
||||
. .bash_logout .bashrc Documents Pictures notes.txt
|
||||
.. .bash_profile .vimrc Music Videos
|
||||
```
|
||||
|
||||
`ls` 还有很多其他有用的选项,你可以把它们组合在一起获得你想要的效果。可以使用以下命令了解更多:
|
||||
|
||||
```
|
||||
$ man ls
|
||||
```
|
||||
|
||||
### tree
|
||||
|
||||
如果你想查看你的文件的树状结构,`tree` 是一个不错的选择。可能你的系统上没有默认安装它,你可以使用包管理 DNF 手动安装:
|
||||
|
||||
```
|
||||
$ sudo dnf install tree
|
||||
```
|
||||
|
||||
如果不带任何选项或者参数地运行 `tree`,将会以当前目录开始,显示出包含其下所有目录和文件的一个树状图。提醒一下,这个输出可能会非常大,因为它包含了这个目录下的所有目录和文件:
|
||||
|
||||
```
|
||||
$ tree
|
||||
.
|
||||
|-- Documents
|
||||
| |-- notes.txt
|
||||
| |-- secret
|
||||
| | `-- christmas-presents.txt
|
||||
| `-- work
|
||||
| |-- project-abc
|
||||
| | |-- README.md
|
||||
| | |-- do-things.sh
|
||||
| | `-- project-notes.txt
|
||||
| `-- status-reports.txt
|
||||
|-- Music
|
||||
|-- Pictures
|
||||
| |-- trees.png
|
||||
| `-- wallpaper.png
|
||||
|-- Videos
|
||||
`-- notes.txt
|
||||
```
|
||||
|
||||
如果列出的太多了,使用 `-L` 选项,并在其后加上你想查看的层级数,可以限制列出文件的层级:
|
||||
|
||||
```
|
||||
$ tree -L 2
|
||||
.
|
||||
|-- Documents
|
||||
| |-- notes.txt
|
||||
| |-- secret
|
||||
| `-- work
|
||||
|-- Music
|
||||
|-- Pictures
|
||||
| |-- trees.png
|
||||
| `-- wallpaper.png
|
||||
|-- Videos
|
||||
`-- notes.txt
|
||||
```
|
||||
|
||||
你也可以显示一个指定目录的树状图:
|
||||
|
||||
```
|
||||
$ tree Documents/work/
|
||||
Documents/work/
|
||||
|-- project-abc
|
||||
| |-- README.md
|
||||
| |-- do-things.sh
|
||||
| `-- project-notes.txt
|
||||
`-- status-reports.txt
|
||||
```
|
||||
|
||||
如果使用 `tree` 列出的是一个很大的树状图,你可以把它跟 `less` 组合使用:
|
||||
|
||||
```
|
||||
$ tree | less
|
||||
```
|
||||
|
||||
再一次,`tree` 有很多其他的选项可以使用,你可以把他们组合在一起发挥更强大的作用。man 手册页有所有这些选项:
|
||||
|
||||
```
|
||||
$ man tree
|
||||
```
|
||||
|
||||
### find
|
||||
|
||||
那么如果不知道文件在哪里呢?就让我们来找到它们吧!
|
||||
|
||||
要是你的系统中没有 `find`,你可以使用 DNF 安装它:
|
||||
|
||||
```
|
||||
$ sudo dnf install findutils
|
||||
```
|
||||
|
||||
运行 `find` 时如果没有添加任何选项或者参数,它将会递归列出当前目录下的所有文件和目录。
|
||||
|
||||
```
|
||||
$ find
|
||||
.
|
||||
./Documents
|
||||
./Documents/secret
|
||||
./Documents/secret/christmas-presents.txt
|
||||
./Documents/notes.txt
|
||||
./Documents/work
|
||||
./Documents/work/status-reports.txt
|
||||
./Documents/work/project-abc
|
||||
./Documents/work/project-abc/README.md
|
||||
./Documents/work/project-abc/do-things.sh
|
||||
./Documents/work/project-abc/project-notes.txt
|
||||
./.bash_logout
|
||||
./.bashrc
|
||||
./Videos
|
||||
./.bash_profile
|
||||
./.vimrc
|
||||
./Pictures
|
||||
./Pictures/trees.png
|
||||
./Pictures/wallpaper.png
|
||||
./notes.txt
|
||||
./Music
|
||||
```
|
||||
|
||||
但是 `find` 真正强大的是你可以使用文件名进行搜索:
|
||||
|
||||
```
|
||||
$ find -name do-things.sh
|
||||
./Documents/work/project-abc/do-things.sh
|
||||
```
|
||||
|
||||
或者仅仅是名字的一部分 —— 像是文件后缀。我们来找一下所有的 .txt 文件:
|
||||
|
||||
```
|
||||
$ find -name "*.txt"
|
||||
./Documents/secret/christmas-presents.txt
|
||||
./Documents/notes.txt
|
||||
./Documents/work/status-reports.txt
|
||||
./Documents/work/project-abc/project-notes.txt
|
||||
./notes.txt
|
||||
```
|
||||
|
||||
你也可以根据大小寻找文件。如果你的空间不足的时候,这种方法也许特别有用。现在来列出所有大于 1 MB 的文件:
|
||||
|
||||
```
|
||||
$ find -size +1M
|
||||
./Pictures/trees.png
|
||||
./Pictures/wallpaper.png
|
||||
```
|
||||
|
||||
当然也可以搜索一个具体的目录。假如我想在我的 Documents 文件夹下找一个文件,而且我知道它的名字里有 “project” 这个词:
|
||||
|
||||
```
|
||||
$ find Documents -name "*project*"
|
||||
Documents/work/project-abc
|
||||
Documents/work/project-abc/project-notes.txt
|
||||
```
|
||||
|
||||
除了文件它还显示目录。你可以限制仅搜索查询文件:
|
||||
|
||||
```
|
||||
$ find Documents -name "*project*" -type f
|
||||
Documents/work/project-abc/project-notes.txt
|
||||
```
|
||||
|
||||
最后再一次,`find` 还有很多供你使用的选项,要是你想使用它们,man 手册页绝对可以帮到你:
|
||||
|
||||
```
|
||||
$ man find
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/commandline-quick-tips-locate-file/
|
||||
|
||||
作者:[Adam Šamalík][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[dianbanjiu](https://github.com/dianbanjiu)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/asamalik/
|
||||
[b]: https://github.com/lujun9972
|
||||
@@ -0,0 +1,171 @@
|
||||
pydbgen:一个数据库随机生成器
|
||||
======
|
||||
|
||||
> 用这个简单的工具生成带有多表的大型数据库,让你更好地用 SQL 研究数据科学。
|
||||
|
||||

|
||||
|
||||
在研究数据科学的过程中,最麻烦的往往不是算法或者技术,而是如何获取到一批原始数据。尽管网上有很多真实优质的数据集可以用于机器学习,然而在学习 SQL 时却不是如此。
|
||||
|
||||
对于数据科学来说,熟悉 SQL 的重要性不亚于了解 Python 或 R 编程。如果想收集诸如姓名、年龄、信用卡信息、地址这些信息用于机器学习任务,在 Kaggle 上查找专门的数据集比使用足够大的真实数据库要容易得多。
|
||||
|
||||
如果有一个简单的工具或库来帮助你生成一个大型数据库,表里还存放着大量你需要的数据,岂不美哉?
|
||||
|
||||
不仅仅是数据科学的入门者,即使是经验丰富的软件测试人员也会需要这样一个简单的工具,只需编写几行代码,就可以通过随机(但是是假随机)生成任意数量但有意义的数据集。
|
||||
|
||||
因此,我要推荐这个名为 [pydbgen][1] 的轻量级 Python 库。在后文中,我会简要说明这个库的相关内容,你也可以[阅读它的文档][2]详细了解更多信息。
|
||||
|
||||
### pydbgen 是什么
|
||||
|
||||
`pydbgen` 是一个轻量的纯 Python 库,它可以用于生成随机但有意义的数据记录(包括姓名、地址、信用卡号、日期、时间、公司名称、职位、车牌号等等),存放在 Pandas Dataframe 对象中,并保存到 SQLite 数据库或 Excel 文件。
|
||||
|
||||
### 如何安装 pydbgen
|
||||
|
||||
目前 1.0.5 版本的 pydbgen 托管在 PyPI(<ruby>Python 包索引存储库<rt>Python Package Index repository</rt></ruby>)上,并且对 [Faker][3] 有依赖关系。安装 pydbgen 只需要执行命令:
|
||||
|
||||
```
|
||||
pip install pydbgen
|
||||
```
|
||||
|
||||
已经在 Python 3.6 环境下测试安装成功,但在 Python 2 环境下无法正常安装。
|
||||
|
||||
### 如何使用 pydbgen
|
||||
|
||||
在使用 `pydbgen` 之前,首先要初始化 `pydb` 对象。
|
||||
|
||||
```
|
||||
import pydbgen
|
||||
from pydbgen import pydbgen
|
||||
myDB=pydbgen.pydb()
|
||||
```
|
||||
|
||||
随后就可以调用 `pydb` 对象公开的各种内部函数了。可以按照下面的例子,输出随机的美国城市和车牌号码:
|
||||
|
||||
```
|
||||
myDB.city_real()
|
||||
>> 'Otterville'
|
||||
for _ in range(10):
|
||||
print(myDB.license_plate())
|
||||
>> 8NVX937
|
||||
6YZH485
|
||||
XBY-564
|
||||
SCG-2185
|
||||
XMR-158
|
||||
6OZZ231
|
||||
CJN-850
|
||||
SBL-4272
|
||||
TPY-658
|
||||
SZL-0934
|
||||
```
|
||||
|
||||
另外,如果你输入的是 `city()` 而不是 `city_real()`,返回的将会是虚构的城市名。
|
||||
|
||||
```
|
||||
print(myDB.gen_data_series(num=8,data_type='city'))
|
||||
>>
|
||||
New Michelle
|
||||
Robinborough
|
||||
Leebury
|
||||
Kaylatown
|
||||
Hamiltonfort
|
||||
Lake Christopher
|
||||
Hannahstad
|
||||
West Adamborough
|
||||
```
|
||||
|
||||
### 生成随机的 Pandas Dataframe
|
||||
|
||||
你可以指定生成数据的数量和种类,但需要注意的是,返回结果均为字符串或文本类型。
|
||||
|
||||
```
|
||||
testdf=myDB.gen_dataframe(5,['name','city','phone','date'])
|
||||
testdf
|
||||
```
|
||||
|
||||
最终产生的 Dataframe 类似下图所示。
|
||||
|
||||

|
||||
|
||||
### 生成数据库表
|
||||
|
||||
你也可以指定生成数据的数量和种类,而返回结果是数据库中的文本或者变长字符串类型。在生成过程中,你可以指定对应的数据库文件名和表名。
|
||||
|
||||
```
|
||||
myDB.gen_table(db_file='Testdb.DB',table_name='People',
|
||||
|
||||
fields=['name','city','street_address','email'])
|
||||
```
|
||||
|
||||
上面的例子种生成了一个能被 MySQL 和 SQLite 支持的 `.db` 文件。下图则显示了这个文件中的数据表在 SQLite 可视化客户端中打开的画面。
|
||||
|
||||

|
||||
|
||||
### 生成 Excel 文件
|
||||
|
||||
和上面的其它示例类似,下面的代码可以生成一个具有随机数据的 Excel 文件。值得一提的是,通过将 `phone_simple` 参数设为 `False` ,可以生成较长较复杂的电话号码。如果你想要提高自己在数据提取方面的能力,不妨尝试一下这个功能。
|
||||
|
||||
```
|
||||
myDB.gen_excel(num=20,fields=['name','phone','time','country'],
|
||||
phone_simple=False,filename='TestExcel.xlsx')
|
||||
```
|
||||
|
||||
最终的结果类似下图所示:
|
||||
|
||||

|
||||
|
||||
### 生成随机电子邮箱地址
|
||||
|
||||
`pydbgen` 内置了一个 `realistic_email` 方法,它基于种子来生成随机的电子邮箱地址。如果你不想在网络上使用真实的电子邮箱地址时,这个功能可以派上用场。
|
||||
|
||||
```
|
||||
for _ in range(10):
|
||||
print(myDB.realistic_email('Tirtha Sarkar'))
|
||||
>>
|
||||
Tirtha_Sarkar@gmail.com
|
||||
Sarkar.Tirtha@outlook.com
|
||||
Tirtha_S48@verizon.com
|
||||
Tirtha_Sarkar62@yahoo.com
|
||||
Tirtha.S46@yandex.com
|
||||
Tirtha.S@att.com
|
||||
Sarkar.Tirtha60@gmail.com
|
||||
TirthaSarkar@zoho.com
|
||||
Sarkar.Tirtha@protonmail.com
|
||||
Tirtha.S@comcast.net
|
||||
```
|
||||
|
||||
### 未来的改进和用户贡献
|
||||
|
||||
目前的版本中并不完美。如果你发现了 pydbgen 的 bug 导致它在运行期间发生崩溃,请向我反馈。如果你打算对这个项目贡献代码,[也随时欢迎你][1]。当然现在也还有很多改进的方向:
|
||||
|
||||
* pydbgen 作为随机数据生成器,可以集成一些机器学习或统计建模的功能吗?
|
||||
* pydbgen 是否会添加可视化功能?
|
||||
|
||||
一切皆有可能!
|
||||
|
||||
如果你有任何问题或想法想要分享,都可以通过 [tirthajyoti@gmail.com][4] 与我联系。如果你像我一样对机器学习和数据科学感兴趣,也可以添加我的 [LinkedIn][5] 或在 [Twitter][6] 上关注我。另外,还可以在我的 [GitHub][7] 上找到更多 Python、R 或 MATLAB 的有趣代码和机器学习资源。
|
||||
|
||||
本文以 [CC BY-SA 4.0][9] 许可在 [Towards Data Science][8] 首发。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/pydbgen-random-database-table-generator
|
||||
|
||||
作者:[Tirthajyoti Sarkar][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/tirthajyoti
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/tirthajyoti/pydbgen
|
||||
[2]: http://pydbgen.readthedocs.io/en/latest/
|
||||
[3]: https://faker.readthedocs.io/en/latest/index.html
|
||||
[4]: mailto:tirthajyoti@gmail.com
|
||||
[5]: https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/
|
||||
[6]: https://twitter.com/tirthajyotiS
|
||||
[7]: https://github.com/tirthajyoti?tab=repositories
|
||||
[8]: https://towardsdatascience.com/introducing-pydbgen-a-random-dataframe-database-table-generator-b5c7bdc84be5
|
||||
[9]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
102
published/20181105 Revisiting the Unix philosophy in 2018.md
Normal file
102
published/20181105 Revisiting the Unix philosophy in 2018.md
Normal file
@@ -0,0 +1,102 @@
|
||||
2018 重温 Unix 哲学
|
||||
======
|
||||
> 在现代微服务环境中,构建小型、单一的应用程序的旧策略又再一次流行了起来。
|
||||
|
||||

|
||||
|
||||
1984 年,Rob Pike 和 Brian W. Kernighan 在 AT&T 贝尔实验室技术期刊上发表了名为 “[Unix 环境编程][1]” 的文章,其中他们使用 BSD 的 `cat -v` 例子来认证 Unix 哲学。简而言之,Unix 哲学是:构建小型、单一的应用程序 —— 不管用什么语言 —— 只做一件小而美的事情,用 `stdin` / `stdout` 进行通信,并通过管道进行连接。
|
||||
|
||||
听起来是不是有点耳熟?
|
||||
|
||||
是的,我也这么认为。这就是 James Lewis 和 Martin Fowler 给出的 [微服务的定义][2] 。
|
||||
|
||||
> 简单来说,微服务架构的风格是将单个 应用程序开发为一套小型服务的方法,每个服务都运行在它的进程中,并用轻量级机制进行通信,通常是 HTTP 资源 API 。
|
||||
|
||||
虽然一个 *nix 程序或者是一个微服务本身可能非常局限甚至不是很有用,但是当这些独立工作的单元组合在一起的时候就显示出了它们真正的好处和强大。
|
||||
|
||||
### *nix程序 vs 微服务
|
||||
|
||||
下面的表格对比了 *nix 环境中的程序(例如 `cat` 或 `lsof`)与微服务环境中的程序。
|
||||
|
||||
| | *nix 程序 | 微服务 |
|
||||
| ------------- | ------------------------- | ----------------------- |
|
||||
| 执行单元 | 程序使用 `stdin`/`stdout` | 使用 HTTP 或 gRPC API |
|
||||
| 数据流 | 管道 | ? |
|
||||
| 可配置和参数化 | 命令行参数、环境变量和配置文件 | JSON/YAML 文档 |
|
||||
| 发现 | 包管理器、man、make | DNS、环境变量、OpenAPI |
|
||||
|
||||
让我们详细的看看每一行。
|
||||
|
||||
#### 执行单元
|
||||
|
||||
*nix 系统(如 Linux)中的执行单元是一个可执行的文件(二进制或者是脚本),理想情况下,它们从 `stdin` 读取输入并将输出写入 `stdout`。而微服务通过暴露一个或多个通信接口来提供服务,比如 HTTP 和 gRPC API。在这两种情况下,你都会发现无状态示例(本质上是纯函数行为)和有状态示例,除了输入之外,还有一些内部(持久)状态决定发生了什么。
|
||||
|
||||
#### 数据流
|
||||
|
||||
传统的,*nix 程序能够通过管道进行通信。换句话说,我们要感谢 [Doug McIlroy][3],你不需要创建临时文件来传递,而可以在每个进程之间处理无穷无尽的数据流。据我所知,除了我在 [2017 年做的基于 Apache Kafka 小实验][4],没有什么能比得上管道化的微服务了。
|
||||
|
||||
#### 可配置和参数化
|
||||
|
||||
你是如何配置程序或者服务的,无论是永久性的服务还是即时的服务?是的,在 *nix 系统上,你通常有三种方法:命令行参数、环境变量,或全面的配置文件。在微服务架构中,典型的做法是用 YAML(或者甚至是 JSON)文档,定制好一个服务的布局和配置以及依赖的组件和通信、存储和运行时配置。例如 [Kubernetes 资源定义][5]、[Nomad 工作规范][6] 或 [Docker 编排][7] 文档。这些可能参数化也可能不参数化;也就是说,除非你知道一些模板语言,像 Kubernetes 中的 [Helm][8],否则你会发现你使用了很多 `sed -i` 这样的命令。
|
||||
|
||||
#### 发现
|
||||
|
||||
你怎么知道有哪些程序和服务可用,以及如何使用它们?在 *nix 系统中通常都有一个包管理器和一个很好用的 man 页面;使用它们,应该能够回答你所有的问题。在微服务的设置中,在寻找一个服务的时候会相对更自动化一些。除了像 [Airbnb 的 SmartStack][9] 或 [Netflix 的 Eureka][10] 等可以定制以外,通常还有基于环境变量或基于 DNS 的[方法][11],允许您动态的发现服务。同样重要的是,事实上 [OpenAPI][12] 为 HTTP API 提供了一套标准文档和设计模式,[gRPC][13] 为一些耦合性强的高性能项目也做了同样的事情。最后非常重要的一点是,考虑到开发者经验(DX),应该从写一份好的 [Makefile][14] 开始,并以编写符合 [风格][15] 的文档结束。
|
||||
|
||||
### 优点和缺点
|
||||
|
||||
*nix 系统和微服务都提供了许多挑战和机遇。
|
||||
|
||||
#### 模块性
|
||||
|
||||
要设计一个简洁、有清晰的目的,并且能够很好地和其它模块配合的某个东西是很困难的。甚至是在不同版本中实现并引入相应的异常处理流程都很困难的。在微服务中,这意味着重试逻辑和超时机制,或者将这些功能外包到<ruby>服务网格<rt>service mesh</rt></ruby>是不是一个更好的选择呢?这确实比较难,可如果你做好了,那它的可重用性是巨大的。
|
||||
|
||||
#### 可观测性
|
||||
|
||||
在一个<ruby>独石<rt>monolith</rt></ruby>(2018 年)或是一个试图做任何事情的大型程序(1984 年),当情况恶化的时候,应当能够直接的找到问题的根源。但是在一个
|
||||
|
||||
```
|
||||
yes | tr \\n x | head -c 450m | grep n
|
||||
```
|
||||
|
||||
或者在一个微服务设置中请求一个路径,例如,涉及 20 个服务,你怎么弄清楚是哪个服务的问题?幸运的是,我们有很多标准,特别是 [OpenCensus][16] 和 [OpenTracing][17]。如果您希望转向微服务,可预测性仍然可能是最大的问题。
|
||||
|
||||
#### 全局状态
|
||||
|
||||
对于 *nix 程序来说可能不是一个大问题,但在微服务中,全局状态仍然是一个需要讨论的问题。也就是说,如何确保有效的管理本地化(持久性)的状态以及尽可能在少做变更的情况下使全局保持一致。
|
||||
|
||||
### 总结一下
|
||||
|
||||
最后,问题仍然是:你是否在使用合适的工具来完成特定的工作?也就是说,以同样的方式实现一个特定的 *nix 程序在某些时候或者阶段会是一个更好的选择,它是可能在你的组织或工作过程中的一个[最好的选择][18]。无论如何,我希望这篇文章可以让你看到 Unix 哲学和微服务之间许多强有力的相似之处。也许我们可以从前者那里学到一些东西使后者受益。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/revisiting-unix-philosophy-2018
|
||||
|
||||
作者:[Michael Hausenblas][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Jamskr](https://github.com/Jamskr)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mhausenblas
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://harmful.cat-v.org/cat-v/
|
||||
[2]: https://martinfowler.com/articles/microservices.html
|
||||
[3]: https://en.wikipedia.org/wiki/Douglas_McIlroy
|
||||
[4]: https://speakerdeck.com/mhausenblas/distributed-named-pipes-and-other-inter-services-communication
|
||||
[5]: http://kubernetesbyexample.com/
|
||||
[6]: https://www.nomadproject.io/docs/job-specification/index.html
|
||||
[7]: https://docs.docker.com/compose/overview/
|
||||
[8]: https://helm.sh/
|
||||
[9]: https://github.com/airbnb/smartstack-cookbook
|
||||
[10]: https://github.com/Netflix/eureka
|
||||
[11]: https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services
|
||||
[12]: https://www.openapis.org/
|
||||
[13]: https://grpc.io/
|
||||
[14]: https://suva.sh/posts/well-documented-makefiles/
|
||||
[15]: https://www.linux.com/news/improve-your-writing-gnu-style-checkers
|
||||
[16]: https://opencensus.io/
|
||||
[17]: https://opentracing.io/
|
||||
[18]: https://robertnorthard.com/devops-days-well-architected-monoliths-are-okay/
|
||||
305
published/20181105 Some Good Alternatives To ‘du- Command.md
Normal file
305
published/20181105 Some Good Alternatives To ‘du- Command.md
Normal file
@@ -0,0 +1,305 @@
|
||||
几个用于替代 du 命令的更好选择
|
||||
======
|
||||
|
||||

|
||||
|
||||
大家对 `du` 命令应该都不陌生,它可以在类 Unix 系统中对文件和目录的空间使用情况进行计算和汇总。如果你也经常需要使用 `du` 命令,你会对以下内容感兴趣的。我发现了五个可以替代原有的 `du` 命令的更好的工具。当然,如果后续有更多更好的选择,我会继续列出来。如果你有其它推荐,也欢迎在评论中留言。
|
||||
|
||||
### ncdu
|
||||
|
||||
`ncdu` 作为普通 `du` 的替代品,这在 Linux 社区中已经很流行了。`ncdu` 正是基于开发者们对 `du` 的性能不满意而被开发出来的。`ncdu` 是一个使用 C 语言和 ncurses 接口开发的简易快速的磁盘用量分析器,可以用来查看目录或文件在本地或远程系统上占用磁盘空间的情况。如果你有兴趣查看关于 `ncdu` 的详细介绍,可以浏览《[如何在 Linux 上使用 ncdu 查看磁盘占用量][9]》这一篇文章。
|
||||
|
||||
### tin-summer
|
||||
|
||||
tin-summer 是使用 Rust 语言编写的自由开源工具,它可以用于查找占用磁盘空间的文件,它也是 `du` 命令的另一个替代品。由于使用了多线程,因此 tin-summer 在计算大目录的大小时会比 `du` 命令快得多。tin-summer 与 `du` 命令之间的区别是前者读取文件的大小,而后者则读取磁盘使用情况。
|
||||
|
||||
tin-summer 的开发者认为它可以替代 `du`,因为它具有以下优势:
|
||||
|
||||
* 在大目录的操作速度上比 `du` 更快;
|
||||
* 在显示结果上默认采用易读格式;
|
||||
* 可以使用正则表达式排除文件或目录;
|
||||
* 可以对输出进行排序和着色处理;
|
||||
* 可扩展,等等。
|
||||
|
||||
**安装 tin-summer**
|
||||
|
||||
要安装 tin-summer,只需要在终端中执行以下命令:
|
||||
|
||||
```
|
||||
$ curl -LSfs https://japaric.github.io/trust/install.sh | sh -s -- --git vmchale/tin-summer
|
||||
```
|
||||
|
||||
你也可以使用 `cargo` 软件包管理器安装 tin-summer,但你需要在系统上先安装 Rust。在 Rust 已经安装好的情况下,执行以下命令:
|
||||
|
||||
```
|
||||
$ cargo install tin-summer
|
||||
```
|
||||
|
||||
如果上面提到的这两种方法都不能成功安装 tin-summer,还可以从它的[软件发布页][1]下载最新版本的二进制文件编译,进行手动安装。
|
||||
|
||||
**用法**
|
||||
|
||||
(LCTT 译注:tin-summer 的命令名为 `sn`)
|
||||
|
||||
如果需要查看当前工作目录的文件大小,可以执行以下命令:
|
||||
|
||||
```
|
||||
$ sn f
|
||||
749 MB ./.rustup/toolchains
|
||||
749 MB ./.rustup
|
||||
147 MB ./.cargo/bin
|
||||
147 MB ./.cargo
|
||||
900 MB .
|
||||
```
|
||||
|
||||
不需要进行额外声明,它也是默认以易读的格式向用户展示数据。在使用 `du` 命令的时候,则必须加上额外的 `-h` 参数才能得到同样的效果。
|
||||
|
||||
只需要按以下的形式执行命令,就可以查看某个特定目录的文件大小。
|
||||
|
||||
```
|
||||
$ sn f <path-to-the-directory>
|
||||
```
|
||||
|
||||
还可以对输出结果进行排序,例如下面的命令可以输出指定目录中最大的 5 个文件或目录:
|
||||
|
||||
```
|
||||
$ sn sort /home/sk/ -n5
|
||||
749 MB /home/sk/.rustup
|
||||
749 MB /home/sk/.rustup/toolchains
|
||||
147 MB /home/sk/.cargo
|
||||
147 MB /home/sk/.cargo/bin
|
||||
2.6 MB /home/sk/mcelog
|
||||
900 MB /home/sk/
|
||||
```
|
||||
|
||||
顺便一提,上面结果中的最后一行是指定目录 `/home/sk` 的总大小。所以不要惊讶为什么输入的是 5 而实际输出了 6 行结果。
|
||||
|
||||
在当前目录下查找带有构建工程的目录,可以使用以下命令:
|
||||
|
||||
```
|
||||
$ sn ar
|
||||
```
|
||||
|
||||
tin-summer 同样支持查找指定大小的带有构建工程的目录。例如执行以下命令可以查找到大小在 100 MB 以上的带有构建工程的目录:
|
||||
|
||||
```
|
||||
$ sn ar -t100M
|
||||
```
|
||||
|
||||
如上文所说,tin-summer 在操作大目录的时候速度比较快,因此在操作小目录的时候,速度会相对比较慢一些。不过它的开发者已经表示,将会在以后的版本中优化这个缺陷。
|
||||
|
||||
要获取相关的帮助,可以执行以下命令:
|
||||
|
||||
```
|
||||
$ sn --help
|
||||
```
|
||||
|
||||
如果想要更详尽的介绍,可以查看[这个项目的 GitHub 页面][10]。
|
||||
|
||||
### dust
|
||||
|
||||
`dust` (含义是 `du` + `rust` = `dust`)使用 Rust 编写,是一个免费、开源的更直观的 `du` 工具。它可以在不需要 `head` 或`sort` 命令的情况下即时显示目录占用的磁盘空间。与 tin-summer 一样,它会默认情况以易读的格式显示每个目录的大小。
|
||||
|
||||
**安装 dust**
|
||||
|
||||
由于 `dust` 也是使用 Rust 编写,因此它也可以通过 `cargo` 软件包管理器进行安装:
|
||||
|
||||
```
|
||||
$ cargo install du-dust
|
||||
```
|
||||
|
||||
也可以从它的[软件发布页][2]下载最新版本的二进制文件,并按照以下步骤安装。在写这篇文章的时候,最新的版本是 0.3.1。
|
||||
|
||||
```
|
||||
$ wget https://github.com/bootandy/dust/releases/download/v0.3.1/dust-v0.3.1-x86_64-unknown-linux-gnu.tar.gz
|
||||
```
|
||||
|
||||
抽取文件:
|
||||
|
||||
```
|
||||
$ tar -xvf dust-v0.3.1-x86_64-unknown-linux-gnu.tar.gz
|
||||
```
|
||||
|
||||
最后将可执行文件复制到你的 `$PATH`(例如 `/usr/local/bin`)下:
|
||||
|
||||
```
|
||||
$ sudo mv dust /usr/local/bin/
|
||||
```
|
||||
|
||||
**用法**
|
||||
|
||||
需要查看当前目录及所有子目录下的文件大小,可以执行以下命令:
|
||||
|
||||
```
|
||||
$ dust
|
||||
```
|
||||
|
||||
输出示例:
|
||||
|
||||

|
||||
|
||||
带上 `-p` 参数可以按照从当前目录起始的完整目录显示。
|
||||
|
||||
```
|
||||
$ dust -p
|
||||
```
|
||||
|
||||
![dust 2][4]
|
||||
|
||||
如果需要查看多个目录的大小,只需要同时列出这些目录,并用空格分隔开即可:
|
||||
|
||||
```
|
||||
$ dust <dir1> <dir2>
|
||||
```
|
||||
|
||||
下面再多举几个例子,例如:
|
||||
|
||||
显示文件的长度:
|
||||
|
||||
```
|
||||
$ dust -s
|
||||
```
|
||||
|
||||
只显示 10 个目录:
|
||||
|
||||
```
|
||||
$ dust -n 10
|
||||
```
|
||||
|
||||
查看当前目录下最多 3 层子目录:
|
||||
|
||||
```
|
||||
$ dust -d 3
|
||||
```
|
||||
|
||||
查看帮助:
|
||||
|
||||
```
|
||||
$ dust -h
|
||||
```
|
||||
|
||||
如果想要更详尽的介绍,可以查看[这个项目的 GitHub 页面][11]。
|
||||
|
||||
### diskus
|
||||
|
||||
`diskus` 也是使用 Rust 编写的一个小型、快速的开源工具,它可以用于替代 `du -sh` 命令。`diskus` 将会计算当前目录下所有文件的总大小,它的效果相当于 `du -sh` 或 `du -sh --bytes`,但其开发者表示 `diskus` 的运行速度是 `du -sh` 的 9 倍。
|
||||
|
||||
**安装 diskus**
|
||||
|
||||
`diskus` 已经存放于 <ruby>Arch Linux 社区用户软件仓库<rt>Arch Linux User-community Repository</rt></ruby>([AUR][5])当中,可以通过任何一种 AUR 帮助工具(例如 [`yay`][6])把它安装在基于 Arch 的系统上:
|
||||
|
||||
```
|
||||
$ yay -S diskus
|
||||
```
|
||||
|
||||
对于 Ubuntu 及其衍生发行版,可以在 `diskus` 的[软件发布页][7]上下载最新版的软件包并安装:
|
||||
|
||||
```
|
||||
$ wget "https://github.com/sharkdp/diskus/releases/download/v0.3.1/diskus_0.3.1_amd64.deb"
|
||||
|
||||
$ sudo dpkg -i diskus_0.3.1_amd64.deb
|
||||
```
|
||||
|
||||
还可以使用 `cargo` 软件包管理器安装 `diskus`,但必须在系统上先安装 Rust 1.29+。
|
||||
|
||||
安装好 Rust 之后,就可以使用以下命令安装 `diskus`:
|
||||
|
||||
```
|
||||
$ cargo install diskus
|
||||
```
|
||||
|
||||
**用法**
|
||||
|
||||
在通常情况下,如果需要查看某个目录的大小,我会使用形如 `du -sh` 的命令。
|
||||
|
||||
```
|
||||
$ du -sh dir
|
||||
```
|
||||
|
||||
这里的 `-s` 参数表示显示总大小。
|
||||
|
||||
如果使用 `diskus`,直接就可以显示当前目录的总大小。
|
||||
|
||||
```
|
||||
$ diskus
|
||||
```
|
||||
|
||||

|
||||
|
||||
我使用 `diskus` 查看 Arch Linux 系统上各个目录的总大小,这个工具的速度确实比 `du -sh` 快得多。但是它目前只能显示当前目录的大小。
|
||||
|
||||
要获取相关的帮助,可以执行以下命令:
|
||||
|
||||
```
|
||||
$ diskus -h
|
||||
```
|
||||
|
||||
如果想要更详尽的介绍,可以查看[这个项目的 GitHub 页面][12]。
|
||||
|
||||
### duu
|
||||
|
||||
`duu` 是 Directory Usage Utility 的缩写。它是使用 Python 编写的查看指定目录大小的工具。它具有跨平台的特性,因此在 Windows、Mac OS 和 Linux 系统上都能够使用。
|
||||
|
||||
**安装 duu**
|
||||
|
||||
安装这个工具之前需要先安装 Python 3。不过目前很多 Linux 发行版的默认软件仓库中都带有 Python 3,所以这个依赖并不难解决。
|
||||
|
||||
Python 3 安装完成后,从 `duu` 的[软件发布页][8]下载其最新版本。
|
||||
|
||||
```
|
||||
$ wget https://github.com/jftuga/duu/releases/download/2.20/duu.py
|
||||
```
|
||||
|
||||
**用法**
|
||||
|
||||
要查看当前目录的大小,只需要执行以下命令:
|
||||
|
||||
```
|
||||
$ python3 duu.py
|
||||
```
|
||||
|
||||
输出示例:
|
||||
|
||||

|
||||
|
||||
从上图可以看出,`duu` 会显示当前目录下文件的数量情况,按照 Byte、KB、MB 单位显示这些文件的总大小,以及每个文件的大小。
|
||||
|
||||
如果需要查看某个目录的大小,只需要声明目录的绝对路径即可:
|
||||
|
||||
```
|
||||
$ python3 duu.py /home/sk/Downloads/
|
||||
```
|
||||
|
||||
如果想要更详尽的介绍,可以查看[这个项目的 GitHub 页面][13]。
|
||||
|
||||
以上就是 `du` 命令的五种替代方案,希望这篇文章能够帮助到你。就我自己而言,我并不会在这五种工具之间交替使用,我更喜欢使用 `ncdu`。欢迎在下面的评论区发表你对这些工具的评论。
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/some-good-alternatives-to-du-command/
|
||||
|
||||
作者:[SK][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://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/vmchale/tin-summer/releases
|
||||
[2]: https://github.com/bootandy/dust/releases
|
||||
[3]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[4]: http://www.ostechnix.com/wp-content/uploads/2018/11/dust-2.png
|
||||
[5]: https://aur.archlinux.org/packages/diskus-bin/
|
||||
[6]: https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
|
||||
[7]: https://github.com/sharkdp/diskus/releases
|
||||
[8]: https://github.com/jftuga/duu/releases
|
||||
[9]: https://www.ostechnix.com/check-disk-space-usage-linux-using-ncdu/
|
||||
[10]: https://github.com/vmchale/tin-summer
|
||||
[11]: https://github.com/bootandy/dust
|
||||
[12]: https://github.com/sharkdp/diskus
|
||||
[13]: https://github.com/jftuga/duu
|
||||
|
||||
92
published/20181107 Gitbase- Exploring git repos with SQL.md
Normal file
92
published/20181107 Gitbase- Exploring git repos with SQL.md
Normal file
@@ -0,0 +1,92 @@
|
||||
gitbase:用 SQL 查询 Git 仓库
|
||||
======
|
||||
|
||||
> gitbase 是一个使用 go 开发的的开源项目,它实现了在 Git 仓库上执行 SQL 查询。
|
||||
|
||||

|
||||
|
||||
Git 已经成为了代码版本控制的事实标准,但尽管 Git 相当普及,对代码仓库的深入分析的工作难度却没有因此而下降;而 SQL 在大型代码库的查询方面则已经是一种久经考验的语言,因此诸如 Spark 和 BigQuery 这样的项目都采用了它。
|
||||
|
||||
所以,source{d} 很顺理成章地将这两种技术结合起来,就产生了 gitbase(LCTT 译注:source{d} 是一家开源公司,本文作者是该公司开发者关系副总裁)。gitbase 是一个<ruby>代码即数据<rt>code-as-data</rt></ruby>的解决方案,可以使用 SQL 对 git 仓库进行大规模分析。
|
||||
|
||||
[gitbase][1] 是一个完全开源的项目。它站在了很多巨人的肩上,因此得到了足够的发展竞争力。下面就来介绍一下其中的一些“巨人”。
|
||||
|
||||

|
||||
|
||||
*[gitbase playground][2] 为 gitbase 提供了一个可视化的操作环境。*
|
||||
|
||||
### 用 Vitess 解析 SQL
|
||||
|
||||
gitbase 通过 SQL 与用户进行交互,因此需要能够遵循 MySQL 协议来对通过网络传入的 SQL 请求作出解析和理解,万幸由 YouTube 建立的 [Vitess][3] 项目已经在这一方面给出了解决方案。Vitess 是一个横向扩展的 MySQL 数据库集群系统。
|
||||
|
||||
我们只是使用了这个项目中的部分重要代码,并将其转化为一个可以让任何人在数分钟以内编写出一个 MySQL 服务器的[开源程序][4],就像我在 [justforfunc][5] 视频系列中展示的 [CSVQL][6] 一样,它可以使用 SQL 操作 CSV 文件。
|
||||
|
||||
### 用 go-git 读取 git 仓库
|
||||
|
||||
在成功解析 SQL 请求之后,还需要对数据集中的 git 仓库进行查询才能返回结果。因此,我们还结合使用了 source{d} 最成功的 [go-git][7] 仓库。go-git 是使用纯 go 语言编写的具有高度可扩展性的 git 实现。
|
||||
|
||||
借此我们就可以很方便地将存储在磁盘上的代码仓库保存为 [siva][8] 文件格式(这同样是 source{d} 的一个开源项目),也可以通过 `git clone` 来对代码仓库进行复制。
|
||||
|
||||
### 使用 enry 检测语言、使用 babelfish 解析文件
|
||||
|
||||
gitbase 集成了我们开源的语言检测项目 [enry][9] 以及代码解析项目 [babelfish][10],因此在分析 git 仓库历史代码的能力也相当强大。babelfish 是一个自托管服务,普适于各种源代码解析,并将代码文件转换为<ruby>通用抽象语法树<rt>Universal Abstract Syntax Tree</rt></ruby>(UAST)。
|
||||
|
||||
这两个功能在 gitbase 中可以被用户以函数 `LANGUAGE` 和 `UAST` 调用,诸如“查找上个月最常被修改的函数的名称”这样的请求就需要通过这两个功能实现。
|
||||
|
||||
### 提高性能
|
||||
|
||||
gitbase 可以对非常大的数据集进行分析,例如来自 GitHub 高达 3 TB 源代码的 Public Git Archive([公告][11])。面临的工作量如此巨大,因此每一点性能都必须运用到极致。于是,我们也使用到了 Rubex 和 Pilosa 这两个项目。
|
||||
|
||||
#### 使用 Rubex 和 Oniguruma 优化正则表达式速度
|
||||
|
||||
[Rubex][12] 是 go 的正则表达式标准库包的一个准替代品。之所以说它是准替代品,是因为它没有在 `regexp.Regexp` 类中实现 `LiteralPrefix` 方法,直到现在都还没有。
|
||||
|
||||
Rubex 的高性能是由于使用 [cgo][14] 调用了 [Oniguruma][13],它是一个高度优化的 C 代码库。
|
||||
|
||||
#### 使用 Pilosa 索引优化查询速度
|
||||
|
||||
索引几乎是每个关系型数据库都拥有的特性,但 Vitess 由于不需要用到索引,因此并没有进行实现。
|
||||
|
||||
于是我们引入了 [Pilosa][15] 这个开源项目。Pilosa 是一个使用 go 实现的分布式位图索引,可以显著提升跨多个大型数据集的查询的速度。通过 Pilosa,gitbase 才得以在巨大的数据集中进行查询。
|
||||
|
||||
### 总结
|
||||
|
||||
我想用这一篇文章来对开源社区表达我衷心的感谢,让我们能够不负众望的在短时间内完成 gitbase 的开发。我们 source{d} 的每一位成员都是开源的拥护者,github.com/src-d 下的每一行代码都是见证。
|
||||
|
||||
你想使用 gitbase 吗?最简单快捷的方式是从 sourced.tech/engine 下载 source{d} 引擎,就可以通过单个命令运行 gitbase 了。
|
||||
|
||||
想要了解更多,可以听听我在 [Go SF 大会][16]上的演讲录音。
|
||||
|
||||
本文在 [Medium][17] 首发,并经许可在此发布。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/gitbase
|
||||
|
||||
作者:[Francesc Campoy][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/francesc
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/src-d/gitbase
|
||||
[2]: https://github.com/src-d/gitbase-web
|
||||
[3]: https://github.com/vitessio/vitess
|
||||
[4]: https://github.com/src-d/go-mysql-server
|
||||
[5]: http://justforfunc.com/
|
||||
[6]: https://youtu.be/bcRDXAraprk
|
||||
[7]: https://github.com/src-d/go-git
|
||||
[8]: https://github.com/src-d/siva
|
||||
[9]: https://github.com/src-d/enry
|
||||
[10]: https://github.com/bblfsh/bblfshd
|
||||
[11]: https://blog.sourced.tech/post/announcing-pga/
|
||||
[12]: https://github.com/moovweb/rubex
|
||||
[13]: https://github.com/kkos/oniguruma
|
||||
[14]: https://golang.org/cmd/cgo/
|
||||
[15]: https://github.com/pilosa/pilosa
|
||||
[16]: https://www.meetup.com/golangsf/events/251690574/
|
||||
[17]: https://medium.com/sourcedtech/gitbase-exploring-git-repos-with-sql-95ec0986386c
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
在 Linux 中如何查找一个命令或进程的执行时间
|
||||
======
|
||||
|
||||

|
||||
|
||||
在类 Unix 系统中,你可能知道一个命令或进程开始执行的时间,以及[一个进程运行了多久][1]。 但是,你如何知道这个命令或进程何时结束或者它完成运行所花费的总时长呢? 在类 Unix 系统中,这是非常容易的! 有一个专门为此设计的程序名叫 **GNU time**。 使用 `time` 程序,我们可以轻松地测量 Linux 操作系统中命令或程序的总执行时间。 `time` 命令在大多数 Linux 发行版中都有预装,所以你不必去安装它。
|
||||
|
||||
### 在 Linux 中查找一个命令或进程的执行时间
|
||||
|
||||
要测量一个命令或程序的执行时间,运行:
|
||||
|
||||
```
|
||||
$ /usr/bin/time -p ls
|
||||
```
|
||||
|
||||
或者,
|
||||
|
||||
```
|
||||
$ time ls
|
||||
```
|
||||
|
||||
输出样例:
|
||||
|
||||
```
|
||||
dir1 dir2 file1 file2 mcelog
|
||||
|
||||
real 0m0.007s
|
||||
user 0m0.001s
|
||||
sys 0m0.004s
|
||||
```
|
||||
|
||||
```
|
||||
$ time ls -a
|
||||
. .bash_logout dir1 file2 mcelog .sudo_as_admin_successful
|
||||
.. .bashrc dir2 .gnupg .profile .wget-hsts
|
||||
.bash_history .cache file1 .local .stack
|
||||
|
||||
real 0m0.008s
|
||||
user 0m0.001s
|
||||
sys 0m0.005s
|
||||
```
|
||||
|
||||
以上命令显示出了 `ls` 命令的总执行时间。 你可以将 `ls` 替换为任何命令或进程,以查找总的执行时间。
|
||||
|
||||
输出详解:
|
||||
|
||||
1. `real` —— 指的是命令或程序所花费的总时间
|
||||
2. `user` —— 指的是在用户模式下程序所花费的时间
|
||||
3. `sys` —— 指的是在内核模式下程序所花费的时间
|
||||
|
||||
|
||||
|
||||
我们也可以将命令限制为仅运行一段时间。参考如下教程了解更多细节:
|
||||
|
||||
- [在 Linux 中如何让一个命令运行特定的时长](https://www.ostechnix.com/run-command-specific-time-linux/)
|
||||
|
||||
### time 与 /usr/bin/time
|
||||
|
||||
你可能注意到了, 我们在上面的例子中使用了两个命令 `time` 和 `/usr/bin/time` 。 所以,你可能会想知道他们的不同。
|
||||
|
||||
首先, 让我们使用 `type` 命令看看 `time` 命令到底是什么。对于那些我们不了解的 Linux 命令,`type` 命令用于查找相关命令的信息。 更多详细信息,[请参阅本指南][2]。
|
||||
|
||||
```
|
||||
$ type -a time
|
||||
time is a shell keyword
|
||||
time is /usr/bin/time
|
||||
```
|
||||
|
||||
正如你在上面的输出中看到的一样,`time` 是两个东西:
|
||||
|
||||
* 一个是 BASH shell 中内建的关键字
|
||||
* 一个是可执行文件,如 `/usr/bin/time`
|
||||
|
||||
由于 shell 关键字的优先级高于可执行文件,当你没有给出完整路径只运行 `time` 命令时,你运行的是 shell 内建的命令。 但是,当你运行 `/usr/bin/time` 时,你运行的是真正的 **GNU time** 命令。 因此,为了执行真正的命令你可能需要给出完整路径。
|
||||
|
||||
在大多数 shell 中如 BASH、ZSH、CSH、KSH、TCSH 等,内建的关键字 `time` 是可用的。 `time` 关键字的选项少于该可执行文件,你可以使用的唯一选项是 `-p`。
|
||||
|
||||
你现在知道了如何使用 `time` 命令查找给定命令或进程的总执行时间。 想进一步了解 GNU time 工具吗? 继续阅读吧!
|
||||
|
||||
### 关于 GNU time 程序的简要介绍
|
||||
|
||||
GNU time 程序运行带有给定参数的命令或程序,并在命令完成后将系统资源使用情况汇总到标准输出。 与 `time` 关键字不同,GNU time 程序不仅显示命令或进程的执行时间,还显示内存、I/O 和 IPC 调用等其他资源。
|
||||
|
||||
`time` 命令的语法是:
|
||||
|
||||
```
|
||||
/usr/bin/time [options] command [arguments...]
|
||||
```
|
||||
|
||||
上述语法中的 `options` 是指一组可以与 `time` 命令一起使用去执行特定功能的选项。 下面给出了可用的选项:
|
||||
|
||||
* `-f, –format` —— 使用此选项可以根据需求指定输出格式。
|
||||
* `-p, –portability` —— 使用简要的输出格式。
|
||||
* `-o file, –output=FILE` —— 将输出写到指定文件中而不是到标准输出。
|
||||
* `-a, –append` —— 将输出追加到文件中而不是覆盖它。
|
||||
* `-v, –verbose` —— 此选项显示 `time` 命令输出的详细信息。
|
||||
* `–quiet` – 此选项可以防止 `time` 命令报告程序的状态.
|
||||
|
||||
当不带任何选项使用 GNU time 命令时,你将看到以下输出。
|
||||
|
||||
```
|
||||
$ /usr/bin/time wc /etc/hosts
|
||||
9 28 273 /etc/hosts
|
||||
0.00user 0.00system 0:00.00elapsed 66%CPU (0avgtext+0avgdata 2024maxresident)k
|
||||
0inputs+0outputs (0major+73minor)pagefaults 0swaps
|
||||
```
|
||||
|
||||
如果你用 shell 关键字 `time` 运行相同的命令, 输出会有一点儿不同:
|
||||
|
||||
```
|
||||
$ time wc /etc/hosts
|
||||
9 28 273 /etc/hosts
|
||||
|
||||
real 0m0.006s
|
||||
user 0m0.001s
|
||||
sys 0m0.004s
|
||||
```
|
||||
|
||||
有时,你可能希望将系统资源使用情况输出到文件中而不是终端上。 为此, 你可以使用 `-o` 选项,如下所示。
|
||||
|
||||
```
|
||||
$ /usr/bin/time -o file.txt ls
|
||||
dir1 dir2 file1 file2 file.txt mcelog
|
||||
```
|
||||
|
||||
正如你看到的,`time` 命令不会显示到终端上。因为我们将输出写到了`file.txt` 的文件中。 让我们看一下这个文件的内容:
|
||||
|
||||
```
|
||||
$ cat file.txt
|
||||
0.00user 0.00system 0:00.00elapsed 66%CPU (0avgtext+0avgdata 2512maxresident)k
|
||||
0inputs+0outputs (0major+106minor)pagefaults 0swaps
|
||||
```
|
||||
|
||||
当你使用 `-o` 选项时, 如果你没有一个名为 `file.txt` 的文件,它会创建一个并把输出写进去。如果文件存在,它会覆盖文件原来的内容。
|
||||
|
||||
你可以使用 `-a` 选项将输出追加到文件后面,而不是覆盖它的内容。
|
||||
|
||||
```
|
||||
$ /usr/bin/time -a file.txt ls
|
||||
```
|
||||
|
||||
`-f` 选项允许用户根据自己的喜好控制输出格式。 比如说,以下命令的输出仅显示用户,系统和总时间。
|
||||
|
||||
```
|
||||
$ /usr/bin/time -f "\t%E real,\t%U user,\t%S sys" ls
|
||||
dir1 dir2 file1 file2 mcelog
|
||||
0:00.00 real, 0.00 user, 0.00 sys
|
||||
```
|
||||
|
||||
请注意 shell 中内建的 `time` 命令并不具有 GNU time 程序的所有功能。
|
||||
|
||||
有关 GNU time 程序的详细说明可以使用 `man` 命令来查看。
|
||||
|
||||
```
|
||||
$ man time
|
||||
```
|
||||
|
||||
想要了解有关 Bash 内建 `time` 关键字的更多信息,请运行:
|
||||
|
||||
```
|
||||
$ help time
|
||||
```
|
||||
|
||||
就到这里吧。 希望对你有所帮助。
|
||||
|
||||
会有更多好东西分享哦。 请关注我们!
|
||||
|
||||
加油哦!
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-find-the-execution-time-of-a-command-or-process-in-linux/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[caixiangyue](https://github.com/caixiangyue)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.ostechnix.com/find-long-process-running-linux/
|
||||
[2]: https://www.ostechnix.com/the-type-command-tutorial-with-examples-for-beginners/
|
||||
79
published/20181108 Choosing a printer for Linux.md
Normal file
79
published/20181108 Choosing a printer for Linux.md
Normal file
@@ -0,0 +1,79 @@
|
||||
为 Linux 选择打印机
|
||||
======
|
||||
|
||||
> Linux 为打印机提供了广泛的支持。学习如何利用它。
|
||||
|
||||

|
||||
|
||||
我们在传闻已久的无纸化社会方面取得了重大进展,但我们仍需要不时打印文件。如果你是 Linux 用户,并有一台没有 Linux 安装盘的打印机,或者你正准备在市场上购买新设备,那么你很幸运。因为大多数 Linux 发行版(以及 MacOS)都使用通用 Unix 打印系统([CUPS][1]),它包含了当今大多数打印机的驱动程序。这意味着 Linux 为打印机提供了比 Windows 更广泛的支持。
|
||||
|
||||
### 选择打印机
|
||||
|
||||
如果你需要购买新打印机,了解它是否支持 Linux 的最佳方法是查看包装盒或制造商网站上的文档。你也可以搜索 [Open Printing][2] 数据库。它是检查各种打印机与 Linux 兼容性的绝佳资源。
|
||||
|
||||
以下是与 Linux 兼容的佳能打印机的一些 Open Printing 结果。
|
||||
|
||||

|
||||
|
||||
下面的截图是 Open Printing 的 Hewlett-Packard LaserJet 4050 的结果 —— 根据数据库,它应该可以“完美”工作。这里列出了建议驱动以及通用说明,让我了解它适用于 CUPS、行式打印守护程序(LPD)、LPRng 等。
|
||||
|
||||

|
||||
|
||||
在任何情况下,最好在购买打印机之前检查制造商的网站并询问其他 Linux 用户。
|
||||
|
||||
### 检查你的连接
|
||||
|
||||
有几种方法可以将打印机连接到计算机。如果你的打印机是通过 USB 连接的,那么可以在 Bash 提示符下输入 `lsusb` 来轻松检查连接。
|
||||
|
||||
```
|
||||
$ lsusb
|
||||
```
|
||||
|
||||
该命令返回 “Bus 002 Device 004: ID 03f0:ad2a Hewlett-Packard” —— 这没有太多价值,但可以得知打印机已连接。我可以通过输入以下命令获得有关打印机的更多信息:
|
||||
|
||||
```
|
||||
$ dmesg | grep -i usb
|
||||
```
|
||||
|
||||
结果更加详细。
|
||||
|
||||

|
||||
|
||||
如果你尝试将打印机连接到并口(假设你的计算机有并口 —— 如今很少见),你可以使用此命令检查连接:
|
||||
|
||||
```
|
||||
$ dmesg | grep -i parport
|
||||
```
|
||||
|
||||
返回的信息可以帮助我为我的打印机选择正确的驱动程序。我发现,如果我坚持使用流行的名牌打印机,大部分时间我都能获得良好的效果。
|
||||
|
||||
### 设置你的打印机软件
|
||||
|
||||
Fedora Linux 和 Ubuntu Linux 都包含简单的打印机设置工具。[Fedora][3] 为打印问题的答案维护了一个出色的 wiki。可以在 GUI 中的设置轻松启动这些工具,也可以在命令行上调用 `system-config-printer`。
|
||||
|
||||

|
||||
|
||||
HP 支持 Linux 打印的 [HP Linux 成像和打印][4] (HPLIP) 软件可能已安装在你的 Linux 系统上。如果没有,你可以为你的发行版[下载][5]最新版本。打印机制造商 [Epson][6] 和 [Brother][7] 也有带有 Linux 打印机驱动程序和信息的网页。
|
||||
|
||||
你最喜欢的 Linux 打印机是什么?请在评论中分享你的意见。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/choosing-printer-linux
|
||||
|
||||
作者:[Don Watkins][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/don-watkins
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cups.org/
|
||||
[2]: http://www.openprinting.org/printers
|
||||
[3]: https://fedoraproject.org/wiki/Printing
|
||||
[4]: https://developers.hp.com/hp-linux-imaging-and-printing
|
||||
[5]: https://developers.hp.com/hp-linux-imaging-and-printing/gethplip
|
||||
[6]: https://epson.com/Support/wa00821
|
||||
[7]: https://support.brother.com/g/s/id/linux/en/index.html?c=us_ot&lang=en&comple=on&redirect=on
|
||||
@@ -0,0 +1,221 @@
|
||||
more、less 和 most 的区别
|
||||
======
|
||||

|
||||
|
||||
如果你是一个 Linux 方面的新手,你可能会在 `more`、`less`、`most` 这三个命令行工具之间产生疑惑。在本文当中,我会对这三个命令行工具进行对比,以及展示它们各自在 Linux 中的一些使用例子。总的来说,这几个命令行工具之间都有相通和差异,而且它们在大部分 Linux 发行版上都有自带。
|
||||
|
||||
我们首先来看看 `more` 命令。
|
||||
|
||||
### more 命令
|
||||
|
||||
`more` 是一个老式的、基础的终端分页阅读器,它可以用于打开指定的文件并进行交互式阅读。如果文件的内容太长,在一屏以内无法完整显示,就会逐页显示文件内容。使用回车键或者空格键可以滚动浏览文件的内容,但有一个限制,就是只能够单向滚动。也就是说只能按顺序往下翻页,而不能进行回看。
|
||||
|
||||

|
||||
|
||||
**更正**
|
||||
|
||||
有的 Linux 用户向我指出,在 `more` 当中是可以向上翻页的。不过,最原始版本的 `more` 确实只允许向下翻页,在后续出现的较新的版本中也允许了有限次数的向上翻页,只需要在浏览过程中按 `b` 键即可向上翻页。唯一的限制是 `more` 不能搭配管道使用(如 `ls | more`)。(LCTT 译注:此处原作者疑似有误,译者使用 `more` 是可以搭配管道使用的,或许与不同 `more` 版本有关)
|
||||
|
||||
按 `q` 即可退出 `more`。
|
||||
|
||||
**更多示例**
|
||||
|
||||
打开 `ostechnix.txt` 文件进行交互式阅读,可以执行以下命令:
|
||||
|
||||
```
|
||||
$ more ostechnix.txt
|
||||
```
|
||||
|
||||
在阅读过程中,如果需要查找某个字符串,只需要像下面这样输入斜杠(`/`)之后接着输入需要查找的内容:
|
||||
|
||||
```
|
||||
/linux
|
||||
```
|
||||
|
||||
按 `n` 键可以跳转到下一个匹配的字符串。
|
||||
|
||||
如果需要在文件的第 `10` 行开始阅读,只需要执行:
|
||||
|
||||
```
|
||||
$ more +10 file
|
||||
```
|
||||
|
||||
就可以从文件的第 `10` 行开始显示文件的内容了。
|
||||
|
||||
如果你需要让 `more` 提示你按空格键来翻页,可以加上 `-d` 参数:
|
||||
|
||||
```
|
||||
$ more -d ostechnix.txt
|
||||
```
|
||||
|
||||
![][2]
|
||||
|
||||
如上图所示,`more` 会提示你可以按空格键翻页。
|
||||
|
||||
如果需要查看所有选项以及对应的按键,可以按 `h` 键。
|
||||
|
||||
要查看 `more` 的更多详细信息,可以参考手册:
|
||||
|
||||
```
|
||||
$ man more
|
||||
```
|
||||
|
||||
### less 命令
|
||||
|
||||
`less` 命令也是用于打开指定的文件并进行交互式阅读,它也支持翻页和搜索。如果文件的内容太长,也会对输出进行分页,因此也可以翻页阅读。比 `more` 命令更好的一点是,`less` 支持向上翻页和向下翻页,也就是可以在整个文件中任意阅读。
|
||||
|
||||
![][4]
|
||||
|
||||
在使用功能方面,`less` 比 `more` 命令具有更多优点,以下列出其中几个:
|
||||
|
||||
* 支持向上翻页和向下翻页
|
||||
* 支持向上搜索和向下搜索
|
||||
* 可以跳转到文件的末尾并立即从文件的开头开始阅读
|
||||
* 在编辑器中打开指定的文件
|
||||
|
||||
**更多示例**
|
||||
|
||||
打开文件:
|
||||
|
||||
```
|
||||
$ less ostechnix.txt
|
||||
```
|
||||
|
||||
按空格键或回车键可以向下翻页,按 `b` 键可以向上翻页。
|
||||
|
||||
如果需要向下搜索,在输入斜杠(`/`)之后接着输入需要搜索的内容:
|
||||
|
||||
```
|
||||
/linux
|
||||
```
|
||||
|
||||
按 `n` 键可以跳转到下一个匹配的字符串,如果需要跳转到上一个匹配的字符串,可以按 `N` 键。
|
||||
|
||||
如果需要向上搜索,在输入问号(`?`)之后接着输入需要搜索的内容:
|
||||
|
||||
```
|
||||
?linux
|
||||
```
|
||||
|
||||
同样是按 `n` 键或 `N` 键跳转到下一个或上一个匹配的字符串。
|
||||
|
||||
只需要按 `v` 键,就会将正在阅读的文件在默认编辑器中打开,然后就可以对文件进行各种编辑操作了。
|
||||
|
||||
按 `h` 键可以查看 `less` 工具的选项和对应的按键。
|
||||
|
||||
按 `q` 键可以退出阅读。
|
||||
|
||||
要查看 `less` 的更多详细信息,可以参考手册:
|
||||
|
||||
```
|
||||
$ man less
|
||||
```
|
||||
|
||||
### most 命令
|
||||
|
||||
`most` 同样是一个终端阅读工具,而且比 `more` 和 `less` 的功能更为丰富。`most` 支持同时打开多个文件。你可以在打开的文件之间切换、编辑当前打开的文件、迅速跳转到文件中的某一行、分屏阅读、同时锁定或滚动多个屏幕等等功能。在默认情况下,对于较长的行,`most` 不会将其截断成多行显示,而是提供了左右滚动功能以在同一行内显示。
|
||||
|
||||
**更多示例**
|
||||
|
||||
打开文件:
|
||||
|
||||
```
|
||||
$ most ostechnix1.txt
|
||||
```
|
||||
|
||||

|
||||
|
||||
按 `e` 键可以编辑当前文件。
|
||||
|
||||
如果需要向下搜索,在斜杠(`/`)或 `S` 或 `f` 之后输入需要搜索的内容,按 `n` 键就可以跳转到下一个匹配的字符串。
|
||||
|
||||
![][3]
|
||||
|
||||
如果需要向上搜索,在问号(`?`)之后输入需要搜索的内容,也是通过按 `n` 键跳转到下一个匹配的字符串。
|
||||
|
||||
同时打开多个文件:
|
||||
|
||||
```
|
||||
$ most ostechnix1.txt ostechnix2.txt ostechnix3.txt
|
||||
```
|
||||
|
||||
在打开了多个文件的状态下,可以输入 `:n` 切换到下一个文件,使用 `↑` 或 `↓` 键选择需要切换到的文件,按回车键就可以查看对应的文件。
|
||||
|
||||

|
||||
|
||||
要打开文件并跳转到某个字符串首次出现的位置(例如 linux),可以执行以下命令:
|
||||
|
||||
```
|
||||
$ most file +/linux
|
||||
```
|
||||
|
||||
按 `h` 键可以查看帮助。
|
||||
|
||||
**按键操作列表**
|
||||
|
||||
移动:
|
||||
|
||||
* 空格键或 `D` 键 – 向下滚动一屏
|
||||
* `DELETE` 键或 `U` 键 – 向上滚动一屏
|
||||
* `↓` 键 – 向下移动一行
|
||||
* `↑` 键 – 向上移动一行
|
||||
* `T` 键 – 移动到文件开头
|
||||
* `B` 键 – 移动到文件末尾
|
||||
* `>` 键或 `TAB` 键 – 向右滚动屏幕
|
||||
* `<` 键 – 向左滚动屏幕
|
||||
* `→` 键 – 向右移动一列
|
||||
* `←` 键 – 向左移动一列
|
||||
* `J` 键或 `G` 键 – 移动到某一行,例如 `10j` 可以移动到第 10 行
|
||||
* `%` 键 – 移动到文件长度某个百分比的位置
|
||||
|
||||
窗口命令:
|
||||
|
||||
* `Ctrl-X 2`、`Ctrl-W 2` – 分屏
|
||||
* `Ctrl-X 1`、`Ctrl-W 1` – 只显示一个窗口
|
||||
* `O` 键、`Ctrl-X O` – 切换到另一个窗口
|
||||
* `Ctrl-X 0` – 删除窗口
|
||||
|
||||
文件内搜索:
|
||||
|
||||
* `S` 键或 `f` 键或 `/` 键 – 向下搜索
|
||||
* `?` 键 – 向上搜索
|
||||
* `n` 键 – 跳转到下一个匹配的字符串
|
||||
|
||||
退出:
|
||||
|
||||
* `q` 键 – 退出 `most` ,且所有打开的文件都会被关闭
|
||||
* `:N`、`:n` – 退出当前文件并查看下一个文件(使用 `↑` 键、`↓` 键选择下一个文件)
|
||||
|
||||
要查看 `most` 的更多详细信息,可以参考手册:
|
||||
|
||||
```
|
||||
$ man most
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
`more` – 传统且基础的分页阅读工具,仅支持向下翻页和有限次数的向上翻页。
|
||||
|
||||
`less` – 比 `more` 功能丰富,支持向下翻页和向上翻页,也支持文本搜索。在打开大文件的时候,比 `vi` 这类文本编辑器启动得更快。
|
||||
|
||||
`most` – 在上述两个工具功能的基础上,还加入了同时打开多个文件、同时锁定或滚动多个屏幕、分屏等等大量功能。
|
||||
|
||||
以上就是我的介绍,希望能让你通过我的文章对这三个工具有一定的认识。如果想了解这篇文章以外的关于这几个工具的详细功能,请参阅它们的 `man` 手册。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/the-difference-between-more-less-and-most-commands/
|
||||
|
||||
作者:[SK][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://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[2]: http://www.ostechnix.com/wp-content/uploads/2018/11/more-1.png
|
||||
[3]: http://www.ostechnix.com/wp-content/uploads/2018/11/most-1-1.gif
|
||||
[4]: https://www.ostechnix.com/wp-content/uploads/2018/11/less-command-demo.gif
|
||||
41
published/20181109 7 reasons I love open source.md
Normal file
41
published/20181109 7 reasons I love open source.md
Normal file
@@ -0,0 +1,41 @@
|
||||
我爱开源的 7 个理由
|
||||
======
|
||||
|
||||
> 成为开源社区的一员绝对是一个明智之举,原因有很多。
|
||||
|
||||

|
||||
|
||||
这就是我为什么包括晚上和周末在内花费非常多的时间待在 [GitHub][1] 上,成为开源社区的一个活跃成员。
|
||||
|
||||
我参加过各种规模的项目,从个人项目到几个人的协作项目,乃至有数百位贡献者的项目,每一个项目都让我有新的受益。
|
||||
|
||||

|
||||
|
||||
也就是说,这里有七个原因让我为开源做出贡献:
|
||||
|
||||
* **它让我的技能与时俱进。** 在咨询公司的管理职位工作,有时我觉得自己与创建软件的实际过程越来越远。参与开源项目使我可以重新回到我最热爱的编程之中。也使我能够体验新技术,学习新技术和语言,并且使我不被酷酷的孩子们落下。
|
||||
* **它教我如何与人打交道。** 与一群素未谋面的人合作开源项目在与人交往方面能够教会你很多。你很快会发现每个人有他们自己的压力,他们自己的义务,以及不同的时间表。学习如何与一群陌生人合作是一种很好的生活技能。
|
||||
* **它使我成为一个更好的沟通者。** 开源项目的维护者的时间有限。你很快就知道,要成功地贡献,你必须能够清楚、简明地表达你所做的改变、添加或修复,最重要的是,你为什么要这么做。
|
||||
* **它使我成为一个更好的开发者。** 没有什么能像成百上千的其他开发者依赖你的代码一样 —— 它敦促你更加专注软件设计、测试和文档。
|
||||
* **它使我的造物变得更好。** 可能开源背后最强大的观念是它允许你驾驭一个由有创造力、有智慧、有知识的个人组成的全球网络。我知道我自己一个人的能力是有限的,我不可能什么都知道,但与开源社区的合作有助于我改进我的创作。
|
||||
* **它告诉我小事物的价值。** 如果一个项目的文档不清楚或不完整,我会毫不犹豫地把它做得更好。一个小小的更新或修复可能只节省开发人员几分钟的时间,但是随着用户数量的增加,您一个小小的更改可能产生巨大的价值。
|
||||
* **它使我更好的营销。** 好的,这是一个奇怪的例子。有这么多伟大的开源项目在那里,感觉像一场争夺关注的拼搏。从事于开源让我学到了很多营销的价值。这不是关于讲述或创建一个华丽的网站。而是关于如何清楚地传达你所创造的,它是如何使用的,以及它带来的好处。
|
||||
|
||||
我可以继续讨论开源是如何帮助你发展伙伴、关系和朋友的,不过你应该都知道了。有许多原因让我乐于成为开源社区的一员。
|
||||
|
||||
你可能想知道这些如何用于大型金融服务机构的 IT 战略。简单来说:谁不想要一个擅长与人交流和工作,具有尖端的技能,并能够推销他们的成果的开发团队呢?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/reasons-love-open-source
|
||||
|
||||
作者:[Colin Eberhardt][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[ChiZelin](https://github.com/ChiZelin)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/colineberhardt
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/ColinEberhardt/
|
||||
80
published/20181113 4 tips for learning Golang.md
Normal file
80
published/20181113 4 tips for learning Golang.md
Normal file
@@ -0,0 +1,80 @@
|
||||
学习 Golang 的 4 个技巧
|
||||
======
|
||||
|
||||
> 到达 Golang 大陆:一位资深开发者之旅。
|
||||
|
||||

|
||||
|
||||
2014 年夏天……
|
||||
|
||||
> IBM:“我们需要你弄清楚这个 Docker。”
|
||||
|
||||
> 我:“没问题。”
|
||||
|
||||
> IBM:“那就开始吧。”
|
||||
|
||||
> 我:“好的。”(内心声音):”Docker 是用 Go 编写的。是吗?“(Google 一下)“哦,一门编程语言。我在我的岗位上已经学习了很多了。这不会太难。”
|
||||
|
||||
我的大学新生编程课是使用 VAX 汇编程序教授的。在数据结构课上,我们使用 Pascal —— 在图书馆计算机中心的旧电脑上使用软盘加载。在一门更高一级的课程中,我的教授教授喜欢用 ADA 去展示所有的例子。在我们的 Sun 工作站上,我通过各种 UNIX 的实用源代码学到了一点 C。在 IBM,OS/2 源代码中我们使用了 C 和一些 x86 汇编程序;在一个与 Apple 合作的项目中我们大量使用 C++ 的面向对象功能。不久后我学到了 shell 脚本,开始是 csh,但是在 90 年代中期发现 Linux 后就转到了 Bash。在 90 年代后期,我在将 IBM 的定制的 JVM 代码中的即时(JIT)编译器移植到 Linux 时,我不得不开始学习 m4(与其说是编程语言,不如说是一种宏处理器)。
|
||||
|
||||
一晃 20 年……我从未因为学习一门新的编程语言而焦灼。但是 [Go][1] 让我感觉有些不同。我打算公开贡献,上传到 GitHub,让任何有兴趣的人都可以看到!作为一个 40 多岁的资深开发者的 Go 新手,我不想成为一个笑话。我们都知道程序员的骄傲,不想丢人,不论你的经验水平如何。
|
||||
|
||||
我早期的调研显示,Go 似乎比某些语言更 “地道”。它不仅仅是让代码可以编译;也需要让代码可以 “Go Go Go”。
|
||||
|
||||
现在,我的个人的 Go 之旅四年间有了几百个拉取请求(PR),我不是致力于成为一个专家,但是现在我觉得贡献和编写代码比我在 2014 年的时候更舒服了。所以,你该怎么教一个老人新的技能或者一门编程语言呢?以下是我自己在前往 Golang 大陆之旅的四个步骤。
|
||||
|
||||
### 1、不要跳过基础
|
||||
|
||||
虽然你可以通过复制代码来进行你早期的学习(谁还有时间阅读手册!?),Go 有一个非常易读的 [语言规范][2],它写的很易于理解,即便你在语言或者编译理论方面没有取得硕士学位。鉴于 Go 的 **参数:类型** 顺序的特有习惯,以及一些有趣的语言功能,例如通道和 go 协程,搞定这些新概念是非常重要的是事情。阅读这个附属的文档 [高效 Go 编程][3],这是 Golang 创造者提供的另一个重要资源,它将为你提供有效和正确使用语言的准备。
|
||||
|
||||
### 2、从最好的中学习
|
||||
|
||||
有许多宝贵的资源可供挖掘,可以将你的 Go 知识提升到下一个等级。最近在 [GopherCon][4] 上的所有讲演都可以在网上找到,如这个 [GopherCon US 2018][5] 的详尽列表。这些讲演的专业知识和技术水平各不相同,但是你可以通过它们轻松地找到一些你所不了解的事情。[Francesc Campoy][6] 创建了一个名叫 [JustForFunc][7] 的 Go 编程视频系列,其不断增多的剧集可以用来拓宽你的 Go 知识和理解。直接搜索 “Golang" 可以为那些想要了解更多信息的人们展示许多其它视频和在线资源。
|
||||
|
||||
想要看代码?在 GitHub 上许多受欢迎的云原生项目都是用 Go 写的:[Docker/Moby][8]、[Kubernetes][9]、[Istio][10]、[containerd][11]、[CoreDNS][12],以及许多其它的。语言纯粹主义者可能会认为一些项目比另外一些更地道,但这些都是很好的起点,可以看到在高度活跃的项目的大型代码库中使用 Go 的程度。
|
||||
|
||||
### 3、使用优秀的语言工具
|
||||
|
||||
你会很快了解到 [gofmt][13] 的宝贵之处。Go 最漂亮的一个地方就在于没有关于每个项目代码格式的争论 —— **gofmt** 内置在语言的运行环境中,并且根据一系列可靠的、易于理解的语言规则对 Go 代码进行格式化。我不知道有哪个基于 Golang 的项目会在持续集成中不坚持使用 **gofmt** 检查拉取请求。
|
||||
|
||||
除了直接构建于运行环境和 SDK 中的一系列有价值的工具之外,我强烈建议使用一个对 Golang 的特性有良好支持的编辑器或者 IDE。由于我经常在命令行中进行工作,我依赖于 Vim 加上强大的 [vim-go][14] 插件。我也喜欢微软提供的 [VS Code][15],特别是它的 [Go 语言][16] 插件。
|
||||
|
||||
想要一个调试器?[Delve][17] 项目在不断的改进和成熟,它是在 Go 二进制文件上进行 [gdb][18] 式调试的强有力的竞争者。
|
||||
|
||||
### 4、写一些代码
|
||||
|
||||
你要是不开始尝试使用 Go 写代码,你永远不知道它有什么好的地方。找一个有 “需要帮助” 问题标签的项目,然后开始贡献代码。如果你已经使用了一个用 Go 编写的开源项目,找出它是否有一些可以用初学者方式解决的 Bug,然后开始你的第一个拉取请求。与生活中的大多数事情一样,实践出真知,所以开始吧。
|
||||
|
||||
事实证明,你可以教会一个资深的老开发者一门新的技能甚至编程语言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/learning-golang
|
||||
|
||||
作者:[Phill Estes][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[dianbanjiu](https://github.com/dianbanjiu)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/estesp
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://golang.org/
|
||||
[2]: https://golang.org/ref/spec
|
||||
[3]: https://golang.org/doc/effective_go.html
|
||||
[4]: https://www.gophercon.com/
|
||||
[5]: https://tqdev.com/2018-gophercon-2018-videos-online
|
||||
[6]: https://twitter.com/francesc
|
||||
[7]: https://www.youtube.com/channel/UC_BzFbxG2za3bp5NRRRXJSw
|
||||
[8]: https://github.com/moby/moby
|
||||
[9]: https://github.com/kubernetes/kubernetes
|
||||
[10]: https://github.com/istio/istio
|
||||
[11]: https://github.com/containerd/containerd
|
||||
[12]: https://github.com/coredns/coredns
|
||||
[13]: https://blog.golang.org/go-fmt-your-code
|
||||
[14]: https://github.com/fatih/vim-go
|
||||
[15]: https://code.visualstudio.com/
|
||||
[16]: https://code.visualstudio.com/docs/languages/go
|
||||
[17]: https://github.com/derekparker/delve
|
||||
[18]: https://www.gnu.org/software/gdb/
|
||||
@@ -0,0 +1,156 @@
|
||||
举例说明 alias 和 unalias 命令
|
||||
======
|
||||
|
||||

|
||||
|
||||
如果不是一个命令行重度用户的话,过了一段时间之后,你就可能已经忘记了这些复杂且冗长的 Linux 命令了。当然,有很多方法可以让你 [回想起遗忘的命令][1]。你可以简单的 [保存常用的命令][2] 然后按需使用。也可以在终端里 [标记重要的命令][3],然后在任何时候你想要的时间使用它们。而且,Linux 有一个内建命令 `history` 可以帮助你记忆这些命令。另外一个记住这些如此长的命令的简便方式就是为这些命令创建一个别名。你可以为任何经常重复调用的常用命令创建别名,而不仅仅是长命令。通过这种方法,你不必再过多地记忆这些命令。这篇文章中,我们将会在 Linux 环境下举例说明 `alias` 和 `unalias` 命令。
|
||||
|
||||
### alias 命令
|
||||
|
||||
`alias` 使用一个用户自定义的字符串来代替一个或者一串命令(包括多个选项、参数)。这个字符串可以是一个简单的名字或者缩写,不管这个命令原来多么复杂。`alias` 命令已经预装在 shell(包括 BASH、Csh、Ksh 和 Zsh 等) 当中。
|
||||
|
||||
`alias` 的通用语法是:
|
||||
|
||||
```
|
||||
alias [alias-name[=string]...]
|
||||
```
|
||||
|
||||
接下来看几个例子。
|
||||
|
||||
#### 列出别名
|
||||
|
||||
可能在你的系统中已经设置了一些别名。有些应用在你安装它们的时候可能已经自动创建了别名。要查看已经存在的别名,运行:
|
||||
|
||||
```
|
||||
$ alias
|
||||
```
|
||||
|
||||
或者,
|
||||
|
||||
```
|
||||
$ alias -p
|
||||
```
|
||||
|
||||
在我的 Arch Linux 系统中已经设置了下面这些别名。
|
||||
|
||||
```
|
||||
alias betty='/home/sk/betty/main.rb'
|
||||
alias ls='ls --color=auto'
|
||||
alias pbcopy='xclip -selection clipboard'
|
||||
alias pbpaste='xclip -selection clipboard -o'
|
||||
alias update='newsbeuter -r && sudo pacman -Syu'
|
||||
```
|
||||
|
||||
#### 创建一个新的别名
|
||||
|
||||
像我之前说的,你不必去记忆这些又臭又长的命令。你甚至不必一遍一遍的运行长命令。只需要为这些命令创建一个简单易懂的别名,然后在任何你想使用的时候运行这些别名就可以了。这种方式会让你爱上命令行。
|
||||
|
||||
```
|
||||
$ du -h --max-depth=1 | sort -hr
|
||||
```
|
||||
|
||||
这个命令将会查找当前工作目录下的各个子目录占用的磁盘大小,并按照从大到小的顺序进行排序。这个命令有点长。我们可以像下面这样轻易地为其创建一个 别名:
|
||||
|
||||
```
|
||||
$ alias du='du -h --max-depth=1 | sort -hr'
|
||||
```
|
||||
|
||||
这里的 `du` 就是这条命令的别名。这个别名可以被设置为任何名字,主要便于记忆和区别。
|
||||
|
||||
在创建一个别名的时候,使用单引号或者双引号都是可以的。这两种方法最后的结果没有任何区别。
|
||||
|
||||
现在你可以运行这个别名(例如我们这个例子中的 `du` )。它和上面的原命令将会产生相同的结果。
|
||||
|
||||
这个别名仅限于当前 shell 会话中。一旦你退出了当前 shell 会话,别名也就失效了。为了让这些别名长久有效,你需要把它们添加到你 shell 的配置文件当中。
|
||||
|
||||
BASH,编辑 `~/.bashrc` 文件:
|
||||
|
||||
```
|
||||
$ nano ~/.bashrc
|
||||
```
|
||||
|
||||
一行添加一个别名:
|
||||
|
||||

|
||||
|
||||
保存并退出这个文件。然后运行以下命令更新修改:
|
||||
|
||||
```
|
||||
$ source ~/.bashrc
|
||||
```
|
||||
|
||||
现在,这些别名在所有会话中都可以永久使用了。
|
||||
|
||||
ZSH,你需要添加这些别名到 `~/.zshrc`文件中。Fish,跟上面的类似,添加这些别名到 `~/.config/fish/config.fish` 文件中。
|
||||
|
||||
#### 查看某个特定的命令别名
|
||||
|
||||
像我上面提到的,你可以使用 `alias` 命令列出你系统中所有的别名。如果你想查看跟给定的别名有关的命令,例如 `du`,只需要运行:
|
||||
|
||||
```
|
||||
$ alias du
|
||||
alias du='du -h --max-depth=1 | sort -hr'
|
||||
```
|
||||
|
||||
像你看到的那样,上面的命令可以显示与单词 `du` 有关的命令。
|
||||
|
||||
关于 `alias` 命令更多的细节,参阅 man 手册页:
|
||||
|
||||
```
|
||||
$ man alias
|
||||
```
|
||||
|
||||
### unalias 命令
|
||||
|
||||
跟它的名字说的一样,`unalias` 命令可以很轻松地从你的系统当中移除别名。`unalias` 命令的通用语法是:
|
||||
|
||||
```
|
||||
unalias <alias-name>
|
||||
```
|
||||
|
||||
要移除命令的别名,像我们之前创建的 `du`,只需要运行:
|
||||
|
||||
```
|
||||
$ unalias du
|
||||
```
|
||||
|
||||
`unalias` 命令不仅会从当前会话中移除别名,也会从你的 shell 配置文件中永久地移除别名。
|
||||
|
||||
还有一种移除别名的方法,是创建具有相同名称的新别名。
|
||||
|
||||
要从当前会话中移除所有的别名,使用 `-a` 选项:
|
||||
|
||||
```
|
||||
$ unalias -a
|
||||
```
|
||||
|
||||
更多细节,参阅 man 手册页。
|
||||
|
||||
```
|
||||
$ man unalias
|
||||
```
|
||||
|
||||
如果你经常一遍又一遍的运行这些繁杂又冗长的命令,给它们创建别名可以节省你的时间。现在是你为常用命令创建别名的时候了。
|
||||
|
||||
这就是所有的内容了。希望可以帮到你。还有更多的干货即将到来,敬请期待!
|
||||
|
||||
祝近祺!
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/the-alias-and-unalias-commands-explained-with-examples/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[dianbanjiu](https://github.com/dianbanjiu)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.ostechnix.com/easily-recall-forgotten-linux-commands/
|
||||
[2]: https://www.ostechnix.com/save-commands-terminal-use-demand/
|
||||
[3]: https://www.ostechnix.com/bookmark-linux-commands-easier-repeated-invocation/
|
||||
@@ -0,0 +1,55 @@
|
||||
GPL 合作承诺的发展历程
|
||||
======
|
||||
|
||||
> <ruby>GPL 合作承诺<rt>GPL Cooperation Commitment</rt></ruby>消除了开发者对许可证失效的顾虑,从而达到促进技术创新的目的。
|
||||
|
||||

|
||||
|
||||
假如能免于顾虑,技术创新和发展将会让世界发生天翻地覆的改变。<ruby>[GPL 合作承诺][1]<rt>GPL Cooperation Commitment</rt></ruby>就这样应运而生,只为通过公平、一致、可预测的许可证来让科技创新无后顾之忧。
|
||||
|
||||
去年,我曾经写过一篇文章,讨论了许可证对开源软件下游用户的影响。在进行研究的时候,我就发现许可证的约束力并不强,而且很多情况下是不可预测的。因此,我在文章中提出了一个能使开源许可证具有一致性和可预测性的潜在解决方案。但我只考虑到了诸如通过法律系统立法的“传统”方法。
|
||||
|
||||
2017 年 11 月,RedHat、IBM、Google 和 Facebook 提出了这种我从未考虑过的非传统的解决方案:GPL 合作承诺。GPL 合作承诺规定了 GPL 公平一致执行的方式。我认为,GPL 合作承诺之所以有这么深刻的意义,有以下两个原因:一是许可证的公平性和一致性对于开源社区的发展来说至关重要,二是法律对不可预测性并不容忍。
|
||||
|
||||
### 了解 GPL
|
||||
|
||||
要了解 GPL 合作承诺,首先要了解什么是 GPL。GPL 是 <ruby>[GNU 通用许可证][2]<rt>GNU General Public License</rt></ruby>的缩写,它是一个公共版权的开源许可证,这就意味着开源软件的分发者必须向下游用户公开源代码。GPL 还禁止对下游的使用作出限制,要求个人用户不得拒绝他人对开源软件的使用自由、研究自由、共享自由和改进自由。GPL 规定,只要下游用户满足了许可证的要求和条件,就可以使用该许可证。如果被许可人出现了不符合许可证的情况,则视为违规。
|
||||
|
||||
按照第二版 GPL(GPLv2)的描述,许可证会在任何违规的情况下自动终止,这就导致了部分开发者对 GPL 有所抗拒。而在第三版 GPL(GPLv3)中则引入了“<ruby>[治愈条款][3]<rt>cure provision</rt></ruby>”,这一条款规定,被许可人可以在 30 天内对违反 GPL 的行为进行改正,如果在这个缓冲期内改正完成,许可证就不会被终止。
|
||||
|
||||
这一规定消除了许可证被无故终止的顾虑,从而让软件的开发者和用户专注于开发和创新。
|
||||
|
||||
### GPL 合作承诺做了什么
|
||||
|
||||
GPL 合作承诺将 GPLv3 的治愈条款应用于使用 GPLv2 的软件上,让使用 GPLv2 许可证的开发者避免许可证无故终止的窘境,并与 GPLv3 许可证保持一致。
|
||||
|
||||
很多软件开发者都希望正确合规地做好一件事情,但有时候却不了解具体的实施细节。因此,GPL 合作承诺的重要性就在于能够对软件开发者们做出一些引导,让他们避免因一些简单的错误导致许可证违规终止。
|
||||
|
||||
Linux 基金会技术顾问委员会在 2017 年宣布,Linux 内核项目将会[采用 GPLv3 的治愈条款][4]。在 GPL 合作承诺的推动下,很多大型科技公司和个人开发者都做出了相同的承诺,会将该条款扩展应用于他们采用 GPLv2(或 LGPLv2.1)许可证的所有软件,而不仅仅是对 Linux 内核的贡献。
|
||||
|
||||
GPL 合作承诺的广泛采用将会对开源社区产生非常积极的影响。如果更多的公司和个人开始采用 GPL 合作承诺,就能让大量正在使用 GPLv2 或 LGPLv2.1 许可证的软件以更公平和更可预测的形式履行许可证中的条款。
|
||||
|
||||
截至 2018 年 11 月,包括 IBM、Google、亚马逊、微软、腾讯、英特尔、RedHat 在内的 40 余家行业巨头公司都已经[签署了 GPL 合作承诺][5],以期为开源社区创立公平的标准以及提供可预测的执行力。GPL 合作承诺是开源社区齐心协力引领开源未来发展方向的一个成功例子。
|
||||
|
||||
GPL 合作承诺能够让下游用户了解到开发者对他们的尊重,同时也表示了开发者使用了 GPLv2 许可证的代码是安全的。如果你想查阅更多信息,包括如何将自己的名字添加到 GPL 合作承诺中,可以访问 [GPL 合作承诺的网站][6]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/gpl-cooperation-commitment
|
||||
|
||||
作者:[Brooke Driver][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/bdriver
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://gplcc.github.io/gplcc/
|
||||
[2]: https://www.gnu.org/licenses/licenses.en.html
|
||||
[3]: https://opensource.com/article/18/6/gplv3-anniversary
|
||||
[4]: https://www.kernel.org/doc/html/v4.16/process/kernel-enforcement-statement.html
|
||||
[5]: https://gplcc.github.io/gplcc/Company/Company-List.html
|
||||
[6]: http://gplcc.github.io/gplcc
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
ProtectedText:一个免费的在线加密笔记
|
||||
======
|
||||
|
||||

|
||||
|
||||
记录笔记是我们每个人必备的重要技能,它可以帮助我们把自己听到、读到、学到的内容长期地保留下来,也有很多的应用和工具都能让我们更好地记录笔记。下面我要介绍一个叫做 **ProtectedText** 的应用,这是一个可以将你的笔记在线上保存起来的免费的加密笔记。它是一个免费的 web 服务,在上面记录文本以后,它将会对文本进行加密,只需要一台支持连接到互联网并且拥有 web 浏览器的设备,就可以访问到记录的内容。
|
||||
|
||||
ProtectedText 不会向你询问任何个人信息,也不会保存任何密码,没有广告,没有 Cookies,更没有用户跟踪和注册流程。除了拥有密码能够解密文本的人,任何人都无法查看到笔记的内容。而且,使用前不需要在网站上注册账号,写完笔记之后,直接关闭浏览器,你的笔记也就保存好了。
|
||||
|
||||
### 在加密笔记本上记录笔记
|
||||
|
||||
访问 <https://www.protectedtext.com/> 这个链接,就可以打开 ProtectedText 页面了(LCTT 译注:如果访问不了,你知道的)。这个时候你将进入网站主页,接下来需要在页面上的输入框输入一个你想用的名称,或者在地址栏后面直接加上想用的名称。这个名称是一个自定义的名称(例如 <https://www.protectedtext.com/mysite>),是你查看自己保存的笔记的专有入口。
|
||||
|
||||

|
||||
|
||||
如果你选用的名称还没有被占用,你就会看到下图中的提示信息。点击 “Create” 键就可以创建你的个人笔记页了。
|
||||
|
||||

|
||||
|
||||
至此你已经创建好了你自己的笔记页面,可以开始记录笔记了。目前每个笔记页的最大容量是每页 750000+ 个字符。
|
||||
|
||||
ProtectedText 使用 AES 算法对你的笔记内容进行加密和解密,而计算散列则使用了 SHA512 算法。
|
||||
|
||||
笔记记录完毕以后,点击顶部的 “Save” 键保存。
|
||||
|
||||

|
||||
|
||||
按下保存键之后,ProtectedText 会提示你输入密码以加密你的笔记内容。按照它的要求输入两次密码,然后点击 “Save” 键。
|
||||
|
||||

|
||||
|
||||
尽管 ProtectedText 对你使用的密码没有太多要求,但毕竟密码总是一寸长一寸强,所以还是最好使用长且复杂的密码(用到数字和特殊字符)以避免暴力破解。由于 ProtectedText 不会保存你的密码,一旦密码丢失,密码和笔记内容就都找不回来了。因此,请牢记你的密码,或者使用诸如 [Buttercup][3]、[KeeWeb][4] 这样的密码管理器来存储你的密码。
|
||||
|
||||
在使用其它设备时,可以通过访问之前创建的 URL 就可以访问你的笔记了。届时会出现如下的提示信息,只需要输入正确的密码,就可以查看和编辑你的笔记。
|
||||
|
||||

|
||||
|
||||
一般情况下,只有知道密码的人才能正常访问笔记的内容。如果你希望将自己的笔记公开,只需要以 <https://www.protectedtext.com/yourSite?yourPassword> 的形式访问就可以了,ProtectedText 将会自动使用 `yourPassword` 字符串解密你的笔记。
|
||||
|
||||
ProtectedText 还有配套的 [Android 应用][6] 可以让你在移动设备上进行同步笔记、离线工作、备份笔记、锁定/解锁笔记等等操作。
|
||||
|
||||
**优点**
|
||||
|
||||
* 简单、易用、快速、免费
|
||||
* ProtectedText.com 的客户端代码可以在[这里][7]免费获取,如果你想了解它的底层实现,可以自行学习它的源代码
|
||||
* 存储的内容没有到期时间,只要你愿意,笔记内容可以一直保存在服务器上
|
||||
* 可以让你的数据限制为私有或公开开放
|
||||
|
||||
**缺点**
|
||||
|
||||
* 尽管客户端代码是公开的,但服务端代码并没有公开,因此你无法自行搭建一个类似的服务。如果你不信任这个网站,请不要使用。
|
||||
* 由于网站不存储你的任何个人信息,包括你的密码,因此如果你丢失了密码,数据将永远无法恢复。网站方还声称他们并不清楚谁拥有了哪些数据,所以一定要牢记密码。
|
||||
|
||||
|
||||
如果你想通过一种简单的方式将笔记保存到线上,并且需要在不需要安装任何工具的情况下访问,那么 ProtectedText 会是一个好的选择。如果你还知道其它类似的应用程序,欢迎在评论区留言!
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/protectedtext-a-free-encrypted-notepad-to-save-your-notes-online/
|
||||
|
||||
作者:[SK][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://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[2]: http://www.ostechnix.com/wp-content/uploads/2018/11/Protected-Text-4.png
|
||||
[3]: https://www.ostechnix.com/buttercup-a-free-secure-and-cross-platform-password-manager/
|
||||
[4]: https://www.ostechnix.com/keeweb-an-open-source-cross-platform-password-manager/
|
||||
[5]: http://www.ostechnix.com/wp-content/uploads/2018/11/Protected-Text-5.png
|
||||
[6]: https://play.google.com/store/apps/details?id=com.protectedtext.android
|
||||
[7]: https://www.protectedtext.com/js/main.js
|
||||
|
||||
144
published/20181115 How to install a device driver on Linux.md
Normal file
144
published/20181115 How to install a device driver on Linux.md
Normal file
@@ -0,0 +1,144 @@
|
||||
如何在 Linux 上安装设备驱动程序
|
||||
======
|
||||
|
||||
> 学习 Linux 设备驱动如何工作,并知道如何使用它们。
|
||||
|
||||

|
||||
|
||||
对于一个熟悉 Windows 或者 MacOS 的人,想要切换到 Linux,它们都会面临一个艰巨的问题就是怎么安装和配置设备驱动。这是可以理解的,因为 Windows 和 MacOS 都有一套机制把这个过程做得非常的友好。比如说,当你插入一个新的硬件设备, Windows 能够自动检测并会弹出一个窗口询问你是否要继续驱动程序的安装。你也可以从网络上下载驱动程序,仅仅需要双击解压或者是通过设备管理器导入驱动程序即可。
|
||||
|
||||
而这在 Linux 操作系统上并非这么简单。第一个原因是, Linux 是一个开源的操作系统,所以有 [数百种 Linux 发行版的变体][1]。也就是说不可能做一个指南来适应所有的 Linux 发行版。因为每种 Linux 安装驱动程序的过程都有差异。
|
||||
|
||||
第二,大多数默认的 Linux 驱动程序也都是开源的,并被集成到了系统中,这使得安装一些并未包含的驱动程序变得非常复杂,即使已经可以检测大多数的硬件设备。第三,不同发行版的许可也有差异。例如,[Fedora 禁止事项][2] 禁止包含专有的、受法律保护,或者是违反美国法律的驱动程序。而 Ubuntu 则让用户[避免使用受法律保护或闭源的硬件设备][3]。
|
||||
|
||||
为了更好的学习 Linux 驱动程序是如何工作的,我建议阅读 《Linux 设备驱动程序》一书中的 [设备驱动程序简介][4]。
|
||||
|
||||
### 两种方式来寻找驱动程序
|
||||
|
||||
#### 1、 用户界面
|
||||
|
||||
如果是一个刚从 Windows 或 MacOS 转过来的 Linux 新手,那你会很高兴知道 Linux 也提供了一个通过向导式的程序来查看驱动程序是否可用的方法。 Ubuntu 提供了一个 [附加驱动程序][5] 选项。其它的 Linux 发行版也提供了帮助程序,像 [GNOME 的包管理器][6],你可以使用它来检查驱动程序是否可用。
|
||||
|
||||
#### 2、 命令行
|
||||
|
||||
如果你通过漂亮的用户界面没有找到驱动程序,那又该怎么办呢?或许你只能通过没有任何图形界面的 shell?甚至你可以使用控制台来展现你的技能。你有两个选择:
|
||||
|
||||
1. **通过一个仓库**
|
||||
|
||||
这和 MacOS 中的 [homebrew][7] 命令行很像。通过使用 `yum`、 `dnf`、`apt-get` 等等。你基本可以通过添加仓库,并更新包缓存。
|
||||
2. **下载、编译,然后自己构建**
|
||||
|
||||
这通常包括直接从网络,或通过 `wget` 命令下载源码包,然后运行配置和编译、安装。这超出了本文的范围,但是你可以在网络上找到很多在线指南,如果你选择的是这条路的话。
|
||||
|
||||
### 检查是否已经安装了这个驱动程序
|
||||
|
||||
在进一步学习安装 Linux 驱动程序之前,让我们来学习几条命令,用来检测驱动程序是否已经在你的系统上可用。
|
||||
|
||||
[lspci][8] 命令显示了系统上所有 PCI 总线和设备驱动程序的详细信息。
|
||||
|
||||
```
|
||||
$ lscpci
|
||||
```
|
||||
|
||||
或者使用 `grep`:
|
||||
|
||||
```
|
||||
$ lscpci | grep SOME_DRIVER_KEYWORD
|
||||
```
|
||||
|
||||
例如,你可以使用 `lspci | grep SAMSUNG` 命令,如果你想知道是否安装过三星的驱动。
|
||||
|
||||
[dmesg][9] 命令显示了所有内核识别的驱动程序。
|
||||
|
||||
```
|
||||
$ dmesg
|
||||
```
|
||||
|
||||
或配合 `grep` 使用:
|
||||
|
||||
```
|
||||
$ dmesg | grep SOME_DRIVER_KEYWORD
|
||||
```
|
||||
|
||||
任何识别到的驱动程序都会显示在结果中。
|
||||
|
||||
如果通过 `dmesg` 或者 `lscpi` 命令没有识别到任何驱动程序,尝试下这两个命令,看看驱动程序至少是否加载到硬盘。
|
||||
|
||||
```
|
||||
$ /sbin/lsmod
|
||||
```
|
||||
|
||||
和
|
||||
|
||||
```
|
||||
$ find /lib/modules
|
||||
```
|
||||
|
||||
技巧:和 `lspci` 或 `dmesg` 一样,通过在上面的命令后面加上 `| grep` 来过滤结果。
|
||||
|
||||
如果一个驱动程序已经被识别到了,但是通过 `lscpi` 或 `dmesg` 并没有找到,这意味着驱动程序已经存在于硬盘上,但是并没有加载到内核中,这种情况,你可以通过 `modprobe` 命令来加载这个模块。
|
||||
|
||||
```
|
||||
$ sudo modprobe MODULE_NAME
|
||||
```
|
||||
|
||||
使用 `sudo` 来运行这个命令,因为这个模块要使用 root 权限来安装。
|
||||
|
||||
### 添加仓库并安装
|
||||
|
||||
可以通过 `yum`、`dnf` 和 `apt-get` 几种不同的方式来添加一个仓库;一个个介绍完它们并不在本文的范围。简单一点来说,这个示例将会使用 `apt-get` ,但是这个命令和其它的几个都是很类似的。
|
||||
|
||||
#### 1、删除存在的仓库,如果它存在
|
||||
|
||||
```
|
||||
$ sudo apt-get purge NAME_OF_DRIVER*
|
||||
```
|
||||
|
||||
其中 `NAME_OF_DRIVER` 是你的驱动程序的可能的名称。你还可以将模式匹配加到正则表达式中来进一步过滤。
|
||||
|
||||
#### 2、将仓库加入到仓库表中,这应该在驱动程序指南中有指定
|
||||
|
||||
```
|
||||
$ sudo add-apt-repository REPOLIST_OF_DRIVER
|
||||
```
|
||||
|
||||
其中 `REPOLIST_OF_DRIVER` 应该从驱动文档中有指定(例如:`epel-list`)。
|
||||
|
||||
#### 3、更新仓库列表
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
```
|
||||
|
||||
#### 4、安装驱动程序
|
||||
|
||||
```
|
||||
$ sudo apt-get install NAME_OF_DRIVER
|
||||
```
|
||||
|
||||
#### 5、检查安装状态
|
||||
|
||||
像上面说的一样,通过 `lscpi` 命令来检查驱动程序是否已经安装成功。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/how-install-device-driver-linux
|
||||
|
||||
作者:[Bryant Son][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Jamskr](https://github.com/Jamskr)
|
||||
校对:[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://en.wikipedia.org/wiki/List_of_Linux_distributions
|
||||
[2]: https://fedoraproject.org/wiki/Forbidden_items?rd=ForbiddenItems
|
||||
[3]: https://www.ubuntu.com/licensing
|
||||
[4]: https://www.xml.com/ldd/chapter/book/ch01.html
|
||||
[5]: https://askubuntu.com/questions/47506/how-do-i-install-additional-drivers
|
||||
[6]: https://help.gnome.org/users/gnome-packagekit/stable/add-remove.html.en
|
||||
[7]: https://brew.sh/
|
||||
[8]: https://en.wikipedia.org/wiki/Lspci
|
||||
[9]: https://en.wikipedia.org/wiki/Dmesg
|
||||
313
published/20181119 How To Customize Bash Prompt In Linux.md
Normal file
313
published/20181119 How To Customize Bash Prompt In Linux.md
Normal file
@@ -0,0 +1,313 @@
|
||||
在 Linux 上自定义 bash 命令提示符
|
||||
======
|
||||
|
||||

|
||||
|
||||
众所周知,**bash**(the **B**ourne-**A**gain **Sh**ell)是目前绝大多数 Linux 发行版使用的默认 shell。本文将会介绍如何通过添加颜色和样式来自定义 bash 命令提示符的显示。尽管很多插件或工具都可以很轻易地满足这一需求,但我们也可以不使用插件和工具,自己手动自定义一些基本的显示方式,例如添加或者修改某些元素、更改前景色、更改背景色等等。
|
||||
|
||||
### 在 Linux 中自定义 bash 命令提示符
|
||||
|
||||
在 bash 中,我们可以通过更改 `$PS1` 环境变量的值来自定义 bash 命令提示符。
|
||||
|
||||
一般情况下,bash 命令提示符会是以下这样的形式:
|
||||
|
||||

|
||||
|
||||
在上图这种默认显示形式当中,“sk” 是我的用户名,而 “ubuntuserver” 是我的主机名。
|
||||
|
||||
只要插入一些以反斜杠开头的特殊转义字符串,就可以按照你的喜好修改命令提示符了。下面我来举几个例子。
|
||||
|
||||
在开始之前,我强烈建议你预先备份 `~/.bashrc` 文件。
|
||||
|
||||
```
|
||||
$ cp ~/.bashrc ~/.bashrc.bak
|
||||
```
|
||||
|
||||
#### 更改 bash 命令提示符中的 username@hostname 部分
|
||||
|
||||
如上所示,bash 命令提示符一般都带有 “username@hostname” 部分,这个部分是可以修改的。
|
||||
|
||||
只需要编辑 `~/.bashrc` 文件:
|
||||
|
||||
```
|
||||
$ vi ~/.bashrc
|
||||
```
|
||||
|
||||
在文件的最后添加一行:
|
||||
|
||||
```
|
||||
PS1="ostechnix> "
|
||||
```
|
||||
|
||||
将上面的 “ostechnix” 替换为任意一个你想使用的单词,然后按 `ESC` 并输入 `:wq` 保存、退出文件。
|
||||
|
||||
执行以下命令使刚才的修改生效:
|
||||
|
||||
```
|
||||
$ source ~/.bashrc
|
||||
```
|
||||
|
||||
你就可以看见 bash 命令提示符中出现刚才添加的 “ostechnix” 了。
|
||||
|
||||
![][3]
|
||||
|
||||
再来看看另一个例子,比如将 “username@hostname” 替换为 “Hello@welcome>”。
|
||||
|
||||
同样是像刚才那样修改 `~/.bashrc` 文件。
|
||||
|
||||
```
|
||||
export PS1="Hello@welcome> "
|
||||
```
|
||||
|
||||
然后执行 `source ~/.bashrc` 让修改结果立即生效。
|
||||
|
||||
以下是我在 Ubuntu 18.04 LTS 上修改后的效果。
|
||||
|
||||

|
||||
|
||||
#### 仅显示用户名
|
||||
|
||||
如果需要仅显示用户名,只需要在 `~/.bashrc` 文件中加入以下这一行。
|
||||
|
||||
```
|
||||
export PS1="\u "
|
||||
```
|
||||
|
||||
这里的 `\u` 就是一个转义字符串。
|
||||
|
||||
下面提供了一些可以添加到 `$PS1` 环境变量中的用以改变 bash 命令提示符样式的转义字符串。每次修改之后,都需要执行 `source ~/.bashrc` 命令才能立即生效。
|
||||
|
||||
#### 显示用户名和主机名
|
||||
|
||||
```
|
||||
export PS1="\u\h "
|
||||
```
|
||||
|
||||
命令提示符会这样显示:
|
||||
|
||||
```
|
||||
skubuntuserver
|
||||
```
|
||||
|
||||
#### 显示用户名和完全限定域名
|
||||
|
||||
```
|
||||
export PS1="\u\H "
|
||||
```
|
||||
|
||||
#### 在用户名和主机名之间显示其它字符
|
||||
|
||||
如果你还需要在用户名和主机名之间显示其它字符(例如 `@`),可以使用以下格式:
|
||||
|
||||
```
|
||||
export PS1="\u@\h "
|
||||
```
|
||||
|
||||
命令提示符会这样显示:
|
||||
|
||||
```
|
||||
sk@ubuntuserver
|
||||
```
|
||||
|
||||
#### 显示用户名、主机名,并在末尾添加 $ 符号
|
||||
|
||||
```
|
||||
export PS1="\u@\h\\$ "
|
||||
```
|
||||
|
||||
#### 综合以上两种显示方式
|
||||
|
||||
```
|
||||
export PS1="\u@\h> "
|
||||
```
|
||||
|
||||
命令提示符最终会这样显示:
|
||||
|
||||
```
|
||||
sk@ubuntuserver>
|
||||
```
|
||||
|
||||
相似地,还可以添加其它特殊字符,例如冒号、分号、星号、下划线、空格等等。
|
||||
|
||||
#### 显示用户名、主机名、shell 名称
|
||||
|
||||
```
|
||||
export PS1="\u@\h>\s "
|
||||
```
|
||||
|
||||
#### 显示用户名、主机名、shell 名称以及 shell 版本
|
||||
|
||||
```
|
||||
export PS1="\u@\h>\s\v "
|
||||
```
|
||||
|
||||
bash 命令提示符显示样式:
|
||||
|
||||
![][4]
|
||||
|
||||
#### 显示用户名、主机名、当前目录
|
||||
|
||||
```
|
||||
export PS1="\u@\h\w "
|
||||
```
|
||||
|
||||
如果当前目录是 `$HOME` ,会以一个波浪线(`~`)显示。
|
||||
|
||||
#### 在 bash 命令提示符中显示日期
|
||||
|
||||
除了用户名和主机名,如果还想在 bash 命令提示符中显示日期,可以在 `~/.bashrc` 文件中添加以下内容:
|
||||
|
||||
```
|
||||
export PS1="\u@\h>\d "
|
||||
```
|
||||
|
||||
![][5]
|
||||
|
||||
#### 在 bash 命令提示符中显示日期及 12 小时制时间
|
||||
|
||||
```
|
||||
export PS1="\u@\h>\d\@ "
|
||||
```
|
||||
|
||||
#### 显示日期及 hh:mm:ss 格式时间
|
||||
|
||||
```
|
||||
export PS1="\u@\h>\d\T "
|
||||
```
|
||||
|
||||
#### 显示日期及 24 小时制时间
|
||||
|
||||
```
|
||||
export PS1="\u@\h>\d\A "
|
||||
```
|
||||
|
||||
#### 显示日期及 24 小时制 hh:mm:ss 格式时间
|
||||
|
||||
```
|
||||
export PS1="\u@\h>\d\t "
|
||||
```
|
||||
|
||||
以上是一些常见的可以改变 bash 命令提示符的转义字符串。除此以外的其它转义字符串,可以在 bash 的 man 手册 PROMPTING 章节中查阅。
|
||||
|
||||
你也可以随时执行以下命令查看当前的命令提示符样式。
|
||||
|
||||
```
|
||||
$ echo $PS1
|
||||
```
|
||||
|
||||
#### 在 bash 命令提示符中去掉 username@hostname 部分
|
||||
|
||||
如果我不想做任何调整,直接把 username@hostname 部分整个去掉可以吗?答案是肯定的。
|
||||
|
||||
如果你是一个技术方面的博主,你有可能会需要在网站或者博客中上传自己的 Linux 终端截图。或许你的用户名和主机名太拉风、太另类,不想让别人看到,在这种情况下,你就需要隐藏命令提示符中的 “username@hostname” 部分。
|
||||
|
||||
如果你不想暴露自己的用户名和主机名,只需要按照以下步骤操作。
|
||||
|
||||
编辑 `~/.bashrc` 文件:
|
||||
|
||||
```
|
||||
$ vi ~/.bashrc
|
||||
```
|
||||
|
||||
在文件末尾添加这一行:
|
||||
|
||||
```
|
||||
PS1="\W> "
|
||||
```
|
||||
|
||||
输入 `:wq` 保存并关闭文件。
|
||||
|
||||
执行以下命令让修改立即生效。
|
||||
|
||||
```
|
||||
$ source ~/.bashrc
|
||||
```
|
||||
|
||||
现在看一下你的终端,“username@hostname” 部分已经消失了,只保留了一个 `~>` 标记。
|
||||
|
||||
![][6]
|
||||
|
||||
如果你想要尽可能简单的操作,又不想弄乱你的 `~/.bashrc` 文件,最好的办法就是在系统中创建另一个用户(例如 “user@example”、“admin@demo”)。用带有这样的命令提示符的用户去截图或者录屏,就不需要顾虑自己的用户名或主机名被别人看见了。
|
||||
|
||||
**警告:**在某些情况下,这种做法并不推荐。例如像 zsh 这种 shell 会继承当前 shell 的设置,这个时候可能会出现一些意想不到的问题。这个技巧只用于隐藏命令提示符中的 “username@hostname” 部分,仅此而已,如果把这个技巧挪作他用,也可能会出现异常。
|
||||
|
||||
### 为 bash 命令提示符着色
|
||||
|
||||
目前我们也只是变更了 bash 命令提示符中的内容,下面介绍一下如何对命令提示符进行着色。
|
||||
|
||||
通过向 `~/.bashrc` 文件写入一些配置,可以修改 bash 命令提示符的前景色(也就是文本的颜色)和背景色。
|
||||
|
||||
例如,下面这一行配置可以令某些文本的颜色变成红色:
|
||||
|
||||
```
|
||||
export PS1="\u@\[\e[31m\]\h\[\e[m\] "
|
||||
```
|
||||
|
||||
添加配置后,执行 `source ~/.bashrc` 立即生效。
|
||||
|
||||
你的 bash 命令提示符就会变成这样:
|
||||
|
||||
![][7]
|
||||
|
||||
类似地,可以用这样的配置来改变背景色:
|
||||
|
||||
```
|
||||
export PS1="\u@\[\e[31;46m\]\h\[\e[m\] "
|
||||
```
|
||||
|
||||
![][8]
|
||||
|
||||
### 添加 emoji
|
||||
|
||||
大家都喜欢 emoji。还可以按照以下配置把 emoji 插入到命令提示符中。
|
||||
|
||||
```
|
||||
PS1="\W 🔥 >"
|
||||
```
|
||||
|
||||
需要注意的是,emoji 的显示取决于使用的字体,因此某些终端可能会无法正常显示 emoji,取而代之的是一些乱码或者单色表情符号。
|
||||
|
||||
### 自定义 bash 命令提示符有点难,有更简单的方法吗?
|
||||
|
||||
如果你是一个新手,编辑 `$PS1` 环境变量的过程可能会有些困难,因为命令提示符中的大量转义字符串可能会让你有点晕头转向。但不要担心,有一个在线的 bash `$PS1` 生成器可以帮助你轻松生成各种 `$PS1` 环境变量值。
|
||||
|
||||
就是这个[网站][9]:
|
||||
|
||||
[][9]
|
||||
|
||||
只需要直接选择你想要的 bash 命令提示符样式,添加颜色、设计排序,然后就完成了。你可以预览输出,并将配置代码复制粘贴到 `~/.bashrc` 文件中。就这么简单。顺便一提,本文中大部分的示例都是通过这个网站制作的。
|
||||
|
||||
### 我把我的 ~/.bashrc 文件弄乱了,该如何恢复?
|
||||
|
||||
正如我在上面提到的,强烈建议在更改 `~/.bashrc` 文件前做好备份(在更改其它重要的配置文件之前也一定要记得备份)。这样一旦出现任何问题,你都可以很方便地恢复到更改之前的配置状态。当然,如果你忘记了备份,还可以按照下面这篇文章中介绍的方法恢复为默认配置。
|
||||
|
||||
- [如何将 `~/.bashrc` 文件恢复到默认配置][10]
|
||||
|
||||
这篇文章是基于 ubuntu 的,但也适用于其它的 Linux 发行版。不过事先声明,这篇文章的方法会将 `~/.bashrc` 文件恢复到系统最初时的状态,你对这个文件做过的任何修改都将丢失。
|
||||
|
||||
感谢阅读!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/hide-modify-usernamelocalhost-part-terminal/
|
||||
|
||||
作者:[SK][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://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.ostechnix.com/cdn-cgi/l/email-protection
|
||||
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[3]: http://www.ostechnix.com/wp-content/uploads/2017/10/Linux-Terminal-2.png
|
||||
[4]: http://www.ostechnix.com/wp-content/uploads/2017/10/bash-prompt-2.png
|
||||
[5]: http://www.ostechnix.com/wp-content/uploads/2017/10/bash-prompt-3.png
|
||||
[6]: http://www.ostechnix.com/wp-content/uploads/2017/10/Linux-Terminal-1.png
|
||||
[7]: http://www.ostechnix.com/hide-modify-usernamelocalhost-part-terminal/bash-prompt-4/
|
||||
[8]: http://www.ostechnix.com/hide-modify-usernamelocalhost-part-terminal/bash-prompt-5/
|
||||
[9]: http://ezprompt.net/
|
||||
[10]: https://www.ostechnix.com/restore-bashrc-file-default-settings-ubuntu/
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
如何更换 Ubuntu 系统的 GDM 登录界面背景
|
||||
======
|
||||
|
||||

|
||||
|
||||
Ubuntu 18.04 LTS 桌面系统在登录、锁屏和解锁状态下,我们会看到一个纯紫色的背景。它是 GDM(<ruby>GNOME 显示管理器<rt>GNOME Display Manager</rt></ruby>)从 ubuntu 17.04 版本开始使用的默认背景。有一些人可能会不喜欢这个纯色的背景,想换一个酷一点、更吸睛的!如果是这样,你找对地方了。这篇短文将会告诉你如何更换 Ubuntu 18.04 LTS 的 GDM 登录界面的背景。
|
||||
|
||||
### 更换 Ubuntu 的登录界面背景
|
||||
|
||||
这是 Ubuntu 18.04 LTS 桌面系统默认的登录界面。
|
||||
|
||||

|
||||
|
||||
不管你喜欢与否,你总是会不经意在登录、解屏/锁屏的时面对它。别担心!你可以随便更换一个你喜欢的图片。
|
||||
|
||||
在 Ubuntu 上更换桌面壁纸和用户的资料图像不难。我们可以点击鼠标就搞定了。但更换解屏/锁屏的背景则需要修改文件 `ubuntu.css`,它位于 `/usr/share/gnome-shell/theme`。
|
||||
|
||||
修改这个文件之前,最好备份一下它。这样我们可以避免出现问题时可以恢复它。
|
||||
|
||||
```
|
||||
$ sudo cp /usr/share/gnome-shell/theme/ubuntu.css /usr/share/gnome-shell/theme/ubuntu.css.bak
|
||||
```
|
||||
|
||||
修改文件 `ubuntu.css`:
|
||||
|
||||
```
|
||||
$ sudo nano /usr/share/gnome-shell/theme/ubuntu.css
|
||||
```
|
||||
|
||||
在文件中找到关键字 `lockDialogGroup`,如下行:
|
||||
|
||||
```
|
||||
#lockDialogGroup {
|
||||
background: #2c001e url(resource:///org/gnome/shell/theme/noise-texture.png);
|
||||
background-repeat: repeat;
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
可以看到,GDM 默认登录的背景图片是 `noise-texture.png`。
|
||||
|
||||
现在修改为你自己的图片路径。也可以选择 .jpg 或 .png 格式的文件,两种格式的图片文件都是支持的。修改完成后的文件内容如下:
|
||||
|
||||
```
|
||||
#lockDialogGroup {
|
||||
background: #2c001e url(file:///home/sk/image.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
```
|
||||
|
||||
请注意 `ubuntu.css` 文件里这个关键字的修改,我把修改点加粗了。
|
||||
|
||||
你可能注意到,我把原来的 `... url(resource:///org/gnome/shell/theme/noise-texture.png);` 修改为 `... url(file:///home/sk/image.png);`。也就是说,你可以把 `... url(resource ...` 修改为 `.. url(file ...`。
|
||||
|
||||
同时,你可以把参数 `background-repeat:` 的值 `repeat` 修改为 `no-repeat`,并增加另外两行。你可以直接复制上面几行的修改到你的 `ubuntu.css` 文件,对应的修改为你的图片路径。
|
||||
|
||||
修改完成后,保存和关闭此文件。然后系统重启生效。
|
||||
|
||||
下面是 GDM 登录界面的最新背景图片:
|
||||
|
||||

|
||||
|
||||
是不是很酷,你都看到了,更换 GDM 登录的默认背景很简单。你只需要修改 `ubuntu.css` 文件中图片的路径然后重启系统。是不是很简单也很有意思.
|
||||
|
||||
你可以修改 `/usr/share/gnome-shell/theme` 目录下的文件 `gdm3.css` ,具体修改内容和修改结果和上面一样。同时记得修改前备份要修改的文件。
|
||||
|
||||
就这些了。如果有好的东东再分享了,请大家关注!
|
||||
|
||||
后会有期。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-change-gdm-login-screen-background-in-ubuntu/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Guevaraya](https://github.com/guevaraya)
|
||||
校对:[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
|
||||
@@ -0,0 +1,71 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (heguangzhi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: subject: (How to use multiple programming languages without losing your mind)
|
||||
[#]: via: (https://opensource.com/article/18/11/multiple-programming-languages)
|
||||
[#]: author: (Bart Copeland https://opensource.com/users/bartcopeland)
|
||||
[#]: url: (https://linux.cn/article-10291-1.html)
|
||||
|
||||
如何使用多种编程语言而又不失理智
|
||||
======
|
||||
|
||||
> 多语言编程环境是一把双刃剑,既带来好处,也带来可能威胁组织的复杂性。
|
||||
|
||||

|
||||
|
||||
如今,随着各种不同的编程语言的出现,许多组织已经变成了<ruby>数字多语种组织<rt>digital polyglots</rt></ruby>。开源打开了一个语言和技术堆栈的世界,开发人员可以使用这些语言和技术堆栈来完成他们的任务,包括开发、支持过时的和现代的软件应用。
|
||||
|
||||
与那些只说母语的人相比,通晓多种语言的人可以与数百万人交谈。在软件环境中,开发人员不会引入新的语言来达到特定的目的,也不会更好地交流。一些语言对于一项任务来说很棒,但是对于另一项任务来说却不行,因此使用多种编程语言可以让开发人员使用合适的工具来完成这项任务。这样,所有的开发都是多语种的;这只是野兽的本性。
|
||||
|
||||
多语种环境的创建通常是渐进的和情景化的。例如,当一家企业收购一家公司时,它就承担了该公司的技术堆栈 —— 包括其编程语言。或者,随着技术领导的改变,新的领导者可能会将不同的技术纳入其中。技术也有过时的时候,随着时间的推移,增加了组织必须维护的编程语言和技术的数量。
|
||||
|
||||
多语言环境对企业来说是一把双刃剑,既带来好处,也带来复杂性和挑战。最终,如果这种情况得不到控制,多语言将会扼杀你的企业。
|
||||
|
||||
### 棘手的技术绕口令
|
||||
|
||||
如果有多种不同的技术 —— 编程语言、过时的工具和新兴的技术堆栈 —— 就有复杂性。工程师团队花更多的时间努力改进编程语言,包括许可证、安全性和依赖性。与此同时,管理层缺乏对代码合规性的监督,无法衡量风险。
|
||||
|
||||
发生的情况是,企业具有不同程度的编程语言质量和工具支持的高度可变性。当你需要和十几个人一起工作时,很难成为一种语言的专家。一个能流利地说法语和意大利语的人和一个能用八种语言串成几个句子的人在技能水平上有很大差异。开发人员和编程语言也是如此。
|
||||
|
||||
随着更多编程语言的加入,困难只会增加,导致数字巴别塔的出现。
|
||||
|
||||
答案是不要拿走开发人员工作所需的工具。添加新的编程语言可以建立他们的技能基础,并为他们提供合适的设备来完成他们的工作。所以,你想对你的开发者说“是”,但是随着越来越多的编程语言被添加到企业中,它们会拖累你的软件开发生命周期(SDLC)。在规模上,所有这些语言和工具都可能扼杀企业。
|
||||
|
||||
企业应注意三个主要问题:
|
||||
|
||||
1. **可见性:** 团队聚在一起执行项目,然后解散。应用程序已经发布,但从未更新 —— 为什么要修复那些没有被破坏的东西?因此,当发现一个关键漏洞时,企业可能无法了解哪些应用程序受到影响,这些应用程序包含哪些库,甚至无法了解它们是用什么语言构建的。这可能导致成本高昂的“勘探项目”,以确保漏洞得到适当解决。
|
||||
|
||||
2. **更新或编码:** 一些企业将更新和修复功能集中在一个团队中。其他人要求每个“比萨团队”管理自己的开发工具。无论是哪种情况,工程团队和管理层都要付出机会成本:这些团队没有编码新特性,而是不断更新和修复开源工具中的库,因为它们移动得如此之快。
|
||||
|
||||
3. **重新发明轮子:** 由于代码依赖性和库版本不断更新,当发现漏洞时,与应用程序原始版本相关联的工件可能不再可用。因此,许多开发周期都被浪费在试图重新创建一个可以修复漏洞的环境上。
|
||||
|
||||
将你组织中的每种编程语言乘以这三个问题,开始时被认为是分子一样小的东西突然看起来像珠穆朗玛峰。就像登山者一样,没有合适的设备和工具,你将无法生存。
|
||||
|
||||
### 找到你的罗塞塔石碑
|
||||
|
||||
一个全面的解决方案可以满足 SDLC 中企业及其个人利益相关者的需求。企业可以使用以下最佳实践创建解决方案:
|
||||
|
||||
1. 监控生产中运行的代码,并根据应用程序中使用的标记组件(例如,常见漏洞和暴露组件)的风险做出响应。
|
||||
2. 定期接收更新以保持代码的最新和无错误。
|
||||
3. 使用商业开源支持来获得编程语言版本和平台的帮助,这些版本和平台已经接近尾声,并且不受社区支持。
|
||||
4. 标准化整个企业中的特定编程语言构建,以实现跨团队的一致环境,并最大限度地减少依赖性。
|
||||
5. 根据相关性设置何时触发更新、警报或其他类型事件的阈值。
|
||||
6. 为您的包管理创建一个单一的可信来源;这可能需要知识渊博的技术提供商的帮助。
|
||||
7. 根据您的特定标准,只使用您需要的软件包获得较小的构建版本。
|
||||
|
||||
使用这些最佳实践,开发人员可以最大限度地利用他们的时间为企业创造更多价值,而不是执行基本的工具或构建工程任务。这将在软件开发生命周期(SDLC)的所有环境中创建代码一致性。由于维护编程语言和软件包分发所需的资源更少,这也将提高效率和节约成本。这种新的操作方式将使技术人员和管理人员的生活更加轻松。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/multiple-programming-languages
|
||||
|
||||
作者:[Bart Copeland][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[heguangzhi](https://github.com/heguangzhi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/bartcopeland
|
||||
[b]: https://github.com/lujun9972
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# PR 检查脚本
|
||||
set -e
|
||||
|
||||
|
||||
@@ -22,7 +22,12 @@ do_analyze() {
|
||||
# 统计每个类别的每个操作
|
||||
REGEX="$(get_operation_regex "$STAT" "$TYPE")"
|
||||
OTHER_REGEX="${OTHER_REGEX}|${REGEX}"
|
||||
eval "${TYPE}_${STAT}=\"\$(grep -Ec '$REGEX' /tmp/changes)\"" || true
|
||||
CHANGES_FILE="/tmp/changes_${TYPE}_${STAT}"
|
||||
eval "grep -E '$REGEX' /tmp/changes" \
|
||||
| sed 's/^[^\/]*\///g' \
|
||||
| sort > "$CHANGES_FILE" || true
|
||||
sed 's/^.*\///g' "$CHANGES_FILE" > "${CHANGES_FILE}_basename"
|
||||
eval "${TYPE}_${STAT}=$(wc -l < "$CHANGES_FILE")"
|
||||
eval echo "${TYPE}_${STAT}=\$${TYPE}_${STAT}"
|
||||
done
|
||||
done
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# 检查脚本状态
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# PR 文件变更收集
|
||||
set -e
|
||||
|
||||
@@ -31,7 +31,16 @@ git --no-pager show --summary "${MERGE_BASE}..HEAD"
|
||||
|
||||
echo "[收集] 写出文件变更列表……"
|
||||
|
||||
git diff "$MERGE_BASE" HEAD --no-renames --name-status > /tmp/changes
|
||||
RAW_CHANGES="$(git diff "$MERGE_BASE" HEAD --no-renames --name-status -z \
|
||||
| tr '\0' '\n')"
|
||||
[ -z "$RAW_CHANGES" ] && {
|
||||
echo "[收集] 无变更,退出……"
|
||||
exit 1
|
||||
}
|
||||
echo "$RAW_CHANGES" | while read -r STAT; do
|
||||
read -r NAME
|
||||
echo "${STAT} ${NAME}"
|
||||
done > /tmp/changes
|
||||
echo "[收集] 已写出文件变更列表:"
|
||||
cat /tmp/changes
|
||||
{ [ -z "$(cat /tmp/changes)" ] && echo "(无变更)"; } || true
|
||||
|
||||
@@ -10,9 +10,10 @@ export TSL_DIR='translated' # 已翻译
|
||||
export PUB_DIR='published' # 已发布
|
||||
|
||||
# 定义匹配规则
|
||||
export CATE_PATTERN='(news|talk|tech)' # 类别
|
||||
export CATE_PATTERN='(talk|tech)' # 类别
|
||||
export FILE_PATTERN='[0-9]{8} [a-zA-Z0-9_.,() -]*\.md' # 文件名
|
||||
|
||||
# 获取用于匹配操作的正则表达式
|
||||
# 用法:get_operation_regex 状态 类型
|
||||
#
|
||||
# 状态为:
|
||||
@@ -26,5 +27,50 @@ export FILE_PATTERN='[0-9]{8} [a-zA-Z0-9_.,() -]*\.md' # 文件名
|
||||
get_operation_regex() {
|
||||
STAT="$1"
|
||||
TYPE="$2"
|
||||
|
||||
echo "^${STAT}\\s+\"?$(eval echo "\$${TYPE}_DIR")/"
|
||||
}
|
||||
|
||||
# 确保两个变更文件一致
|
||||
# 用法:ensure_identical X类型 X状态 Y类型 Y状态 是否仅比较文件名
|
||||
#
|
||||
# 状态为:
|
||||
# - A:添加
|
||||
# - M:修改
|
||||
# - D:删除
|
||||
# 类型为:
|
||||
# - SRC:未翻译
|
||||
# - TSL:已翻译
|
||||
# - PUB:已发布
|
||||
ensure_identical() {
|
||||
TYPE_X="$1"
|
||||
STAT_X="$2"
|
||||
TYPE_Y="$3"
|
||||
STAT_Y="$4"
|
||||
NAME_ONLY="$5"
|
||||
SUFFIX=
|
||||
[ -n "$NAME_ONLY" ] && SUFFIX="_basename"
|
||||
|
||||
X_FILE="/tmp/changes_${TYPE_X}_${STAT_X}${SUFFIX}"
|
||||
Y_FILE="/tmp/changes_${TYPE_Y}_${STAT_Y}${SUFFIX}"
|
||||
|
||||
cmp "$X_FILE" "$Y_FILE" 2> /dev/null
|
||||
}
|
||||
|
||||
# 检查文章分类
|
||||
# 用法:check_category 类型 状态
|
||||
#
|
||||
# 状态为:
|
||||
# - A:添加
|
||||
# - M:修改
|
||||
# - D:删除
|
||||
# 类型为:
|
||||
# - SRC:未翻译
|
||||
# - TSL:已翻译
|
||||
check_category() {
|
||||
TYPE="$1"
|
||||
STAT="$2"
|
||||
|
||||
CHANGES="/tmp/changes_${TYPE}_${STAT}"
|
||||
! grep -Eqv "^${CATE_PATTERN}/" "$CHANGES"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# 匹配 PR 规则
|
||||
set -e
|
||||
|
||||
@@ -27,31 +27,39 @@ rule_bypass_check() {
|
||||
# 添加原文:添加至少一篇原文
|
||||
rule_source_added() {
|
||||
[ "$SRC_A" -ge 1 ] \
|
||||
&& check_category SRC A \
|
||||
&& [ "$TOTAL" -eq "$SRC_A" ] && echo "匹配规则:添加原文 ${SRC_A} 篇"
|
||||
}
|
||||
|
||||
# 申领翻译:只能申领一篇原文
|
||||
rule_translation_requested() {
|
||||
[ "$SRC_M" -eq 1 ] \
|
||||
&& check_category SRC M \
|
||||
&& [ "$TOTAL" -eq 1 ] && echo "匹配规则:申领翻译"
|
||||
}
|
||||
|
||||
# 提交译文:只能提交一篇译文
|
||||
rule_translation_completed() {
|
||||
[ "$SRC_D" -eq 1 ] && [ "$TSL_A" -eq 1 ] \
|
||||
&& ensure_identical SRC D TSL A \
|
||||
&& check_category SRC D \
|
||||
&& check_category TSL A \
|
||||
&& [ "$TOTAL" -eq 2 ] && echo "匹配规则:提交译文"
|
||||
}
|
||||
|
||||
# 校对译文:只能校对一篇
|
||||
rule_translation_revised() {
|
||||
[ "$TSL_M" -eq 1 ] \
|
||||
&& check_category TSL M \
|
||||
&& [ "$TOTAL" -eq 1 ] && echo "匹配规则:校对译文"
|
||||
}
|
||||
|
||||
# 发布译文:发布多篇译文
|
||||
rule_translation_published() {
|
||||
[ "$TSL_D" -ge 1 ] && [ "$PUB_A" -ge 1 ] && [ "$TSL_D" -eq "$PUB_A" ] \
|
||||
&& [ "$TOTAL" -eq $(($TSL_D + $PUB_A)) ] \
|
||||
&& ensure_identical SRC D TSL A 1 \
|
||||
&& check_category TSL D \
|
||||
&& [ "$TOTAL" -eq $((TSL_D + PUB_A)) ] \
|
||||
&& echo "匹配规则:发布译文 ${PUB_A} 篇"
|
||||
}
|
||||
|
||||
|
||||
8
scripts/status.sh
Executable file
8
scripts/status.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
# 重新生成status data
|
||||
set -o errexit
|
||||
|
||||
SCRIPTS_DIR=$(cd $(dirname "$0") && pwd)
|
||||
BUILD_DIR=$(cd $SCRIPTS_DIR/.. && pwd)/build
|
||||
mkdir -p ${BUILD_DIR}/status
|
||||
${SCRIPTS_DIR}/status/status.sh > ${BUILD_DIR}/status/status.json
|
||||
32
scripts/status/status.sh
Executable file
32
scripts/status/status.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
cd "$(dirname "$0")/../.." # 进入TP root
|
||||
|
||||
function file-translating-p ()
|
||||
{
|
||||
local file="$*"
|
||||
if head -n 1 "${file}" |grep '\[^#\]:'>/dev/null 2>&1 ;then
|
||||
# 新模板
|
||||
head -n 12 "$file" |grep -v '\[^#\]:' |grep -E -i "translat|fanyi|翻译" >/dev/null 2>&1
|
||||
else
|
||||
# 旧模板
|
||||
head -n 3 "$file" |grep -E -i "translat|fanyi|翻译" >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
function get_status_of()
|
||||
{
|
||||
local file="$*"
|
||||
git log --date=short --pretty=format:"{\"file\":\"${file}\",\"time\":\"%ad\",\"user\":\"%an\"}" -n 1 "${file}"
|
||||
}
|
||||
|
||||
while read -r file;do
|
||||
if file-translating-p "${file}";then
|
||||
translating="${translating} $(get_status_of "${file}")"
|
||||
else
|
||||
unselected="${unselected} $(get_status_of "${file}")"
|
||||
fi
|
||||
done< <(find sources -name "2*.md")
|
||||
(
|
||||
echo "${translating}"|jq -s "."
|
||||
echo "${unselected}"|jq -s "."
|
||||
)|jq -s '{"translating":.[0],"unselected":.[1]}'
|
||||
@@ -1,3 +1,5 @@
|
||||
zs19940317翻译中
|
||||
|
||||
The Most Important Database You've Never Heard of
|
||||
======
|
||||
In 1962, JFK challenged Americans to send a man to the moon by the end of the decade, inspiring a heroic engineering effort that culminated in Neil Armstrong’s first steps on the lunar surface. Many of the fruits of this engineering effort were highly visible and sexy—there were new spacecraft, new spacesuits, and moon buggies. But the Apollo Program was so staggeringly complex that new technologies had to be invented even to do the mundane things. One of these technologies was IBM’s Information Management System (IMS).
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user