Merge pull request #1 from LCTT/master

更新2018.11.1
This commit is contained in:
way-ww 2018-11-01 21:33:26 +08:00 committed by GitHub
commit b312fddd11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
151 changed files with 4056 additions and 1871 deletions

View File

@ -0,0 +1,69 @@
模拟 Altair 8800 计算机
======
[Altair 8800][1] 是 1975 年发布的自建家用电脑套件。Altair 基本上是第一台个人电脑PC虽然 PC 这个名词好几年前就出现了。对 Dell、HP 或者 Macbook 而言它是亚当(或者夏娃)。
有些人认为为 Z80与 Altair 的 Intel 8080 密切相关的处理器)编写仿真器真是太棒了,并认为它需要一个模拟 Altair 的控制面板。所以如果你想知道 1975 年使用电脑是什么感觉,你可以在你的 Macbook 上运行 Altair
![Altair 8800][2]
### 安装它
你可以从[这里][3]的 FTP 服务器下载 Z80 包。你要查找最新的 Z80 包版本,例如 `z80pack-1.26.tgz`
首先解压文件:
```
$ tar -xvf z80pack-1.26.tgz
```
进入解压目录:
```
$ cd z80pack-1.26
```
控制面板模拟基于名为 `frontpanel` 的库。你必须先编译该库。如果你进入 `frontpanel` 目录,你会发现 `README` 文件列出了这个库自己的依赖项。你在这里的体会几乎肯定会与我的不同,但也许我的痛苦可以作为例子。我安装了依赖项,但是是通过 [Homebrew][4] 安装的。为了让库能够编译,我必须确保在 `Makefile.osx` 中将 `/usr/local/include `添加到 Clang 的 include 路径中。
如果你觉得依赖没有问题,那么你应该就能编译这个库(我们现在位于 `z80pack-1.26/frontpanel`
```
$ make -f Makefile.osx ...
$ make -f Makefile.osx clean
```
你应该会得到 `libfrontpanel.so`。我把它拷贝到 `libfrontpanel.so`
Altair 模拟器位于 `z80pack-1.26/altairsim` 下。你现在需要编译模拟器本身。进入 `z80pack-1.26/altairsim/srcsim` 并再次运行 `make`
```
$ make -f Makefile.osx ...
$ make -f Makefile.osx clean
```
该过程将在 `z80pack-1.26/altairsim` 中创建一个名为 `altairsim` 的可执行文件。运行该可执行文件,你应该会看到标志性的 Altair 控制面板!
如果你想要探究,请阅读原始的 [Altair 手册][5]
如果你喜欢这篇文章,我们每两周更新一次!在 Twitter 上关注 [@TwoBitHistory][6] 或订阅 [RSS 源][7]了解什么时候有新文章。
--------------------------------------------------------------------------------
via: https://twobithistory.org/2017/12/02/simulating-the-altair.html
作者:[Two-Bit History][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://twobithistory.org
[b]: https://github.com/lujun9972
[1]: https://en.wikipedia.org/wiki/Altair_8800
[2]: https://www.autometer.de/unix4fun/z80pack/altair.png
[3]: http://www.autometer.de/unix4fun/z80pack/ftp/
[4]: http://brew.sh/
[5]: http://www.classiccmp.org/dunfield/altair/d/88opman.pdf
[6]: https://twitter.com/TwoBitHistory
[7]: https://twobithistory.org/feed.xml

View File

@ -1,4 +1,4 @@
Flameshot 一个简洁但功能丰富的截图工具 Flameshot一个简洁但功能丰富的截图工具
====== ======
![](https://www.ostechnix.com/wp-content/uploads/2018/09/Flameshot-720x340.png) ![](https://www.ostechnix.com/wp-content/uploads/2018/09/Flameshot-720x340.png)
@ -10,11 +10,13 @@ Flameshot 一个简洁但功能丰富的截图工具
**在 Arch Linux 上:** **在 Arch Linux 上:**
Flameshot 可以从 Arch LInux 的 [community] 仓库中获取。确保你已经启用了 community 仓库,然后就可以像下面展示的那样使用 pacman 来安装 Flameshot Flameshot 可以从 Arch LInux 的 [community] 仓库中获取。确保你已经启用了 community 仓库,然后就可以像下面展示的那样使用 pacman 来安装 Flameshot
``` ```
$ sudo pacman -S flameshot $ sudo pacman -S flameshot
``` ```
它也可以从 [**AUR**][1] 中获取,所以你还可以使用任意一个 AUR 帮助程序(例如 [**Yay**][2])来在基于 Arch 的系统中安装它: 它也可以从 [**AUR**][1] 中获取,所以你还可以使用任意一个 AUR 帮助程序(例如 [**Yay**][2])来在基于 Arch 的系统中安装它:
``` ```
$ yay -S flameshot-git $ yay -S flameshot-git
``` ```
@ -26,6 +28,7 @@ $ sudo dnf install flameshot
``` ```
**Debian 10+****Ubuntu 18.04+** 中,可以使用 APT 包管理器来安装它: **Debian 10+****Ubuntu 18.04+** 中,可以使用 APT 包管理器来安装它:
``` ```
$ sudo apt install flameshot $ sudo apt install flameshot
``` ```
@ -35,97 +38,105 @@ $ sudo apt install flameshot
``` ```
$ sudo zypper install flameshot $ sudo zypper install flameshot
``` ```
在其他的 Linux 发行版中,可以从源代码编译并安装它。编译过程中需要 **Qt version 5.3** 以及 **GCC 4.9.2** 或者它们的更高版本。 在其他的 Linux 发行版中,可以从源代码编译并安装它。编译过程中需要 **Qt version 5.3** 以及 **GCC 4.9.2** 或者它们的更高版本。
### 使用 ### 使用
可以从菜单或者应用启动器中启动 Flameshot。在 MATE 桌面环境,它通常可以在 **Applications - > Graphics** 下找到。 可以从菜单或者应用启动器中启动 Flameshot。在 MATE 桌面环境,它通常可以在 “Applications -> Graphics” 下找到。
一旦打开了它,你就可以在系统面板中看到 Flameshot 的托盘图标。 一旦打开了它,你就可以在系统面板中看到 Flameshot 的托盘图标。
**注意:** **注意:**
假如你使用 Gnome 桌面环境,为了能够看到系统托盘图标,你需要安装 [TopIcons][3] 扩展。 假如你使用 Gnome 桌面环境,为了能够看到系统托盘图标,你需要安装 [TopIcons][3] 扩展。
在 Flameshot 托盘图标上右击,你便会看到几个菜单项,例如打开配置窗口、信息窗口以及退出该应用。 在 Flameshot 托盘图标上右击,你便会看到几个菜单项,例如打开配置窗口、信息窗口以及退出该应用。
要进行截图,只需要点击托盘图标就可以了。接着你将看到如何使用 Flameshot 的帮助窗口。选择一个截图区域,然后敲 **ENTER** 键便可以截屏了,点击右键便可以看到颜色拾取器,再敲空格键便可以查看屏幕侧边的面板。你可以使用鼠标的滚轮来增加或者减少指针的宽度。 要进行截图,只需要点击托盘图标就可以了。接着你将看到如何使用 Flameshot 的帮助窗口。选择一个截图区域,然后敲回车键便可以截屏了,点击右键便可以看到颜色拾取器,再敲空格键便可以查看屏幕侧边的面板。你可以使用鼠标的滚轮来增加或者减少指针的宽度。
Flameshot 自带一系列非常好的功能,例如: Flameshot 自带一系列非常好的功能,例如:
* 可以进行手写 * 可以进行手写
* 可以划直线 * 可以划直线
* 可以画长方形或者圆形框 * 可以画长方形或者圆形框
* 可以进行长方形区域选择 * 可以进行长方形区域选择
* 可以画箭头 * 可以画箭头
* 可以对要点进行标注 * 可以对要点进行标注
* 可以添加文本 * 可以添加文本
* 可以对图片或者文字进行模糊处理 * 可以对图片或者文字进行模糊处理
* 可以展示图片的尺寸大小 * 可以展示图片的尺寸大小
* 在编辑图片是可以进行撤销和重做操作 * 在编辑图片是可以进行撤销和重做操作
* 可以将选择的东西复制到剪贴板 * 可以将选择的东西复制到剪贴板
* 可以保存选择 * 可以保存选区
* 可以离开截屏 * 可以离开截屏
* 可以选择另一个 app 来打开图片 * 可以选择另一个 app 来打开图片
* 可以上传图片到 imgur 网站 * 可以上传图片到 imgur 网站
* 可以将图片固定到桌面上 * 可以将图片固定到桌面上
下面是一个示例的视频: 下面是一个示例的视频:
<http://www.ostechnix.com/wp-content/uploads/2018/09/Flameshot-demo.mp4> <http://www.ostechnix.com/wp-content/uploads/2018/09/Flameshot-demo.mp4>
**快捷键** ### 快捷键
Frameshot 也支持快捷键。在 Flameshot 的托盘图标上右击并点击 **Information** 窗口便可以看到在 GUI 模式下所有可用的快捷键。下面是在 GUI 模式下可用的快捷键清单: Frameshot 也支持快捷键。在 Flameshot 的托盘图标上右击并点击 “Information” 窗口便可以看到在 GUI 模式下所有可用的快捷键。下面是在 GUI 模式下可用的快捷键清单:
| 快捷键 | 描述 | | 快捷键 | 描述 |
|------------------------|------------------------------| |------------------------|------------------------------|
| ←, ↓, ↑, → | 移动选择区域 1px | | `←`、`↓`、`↑`、`→` | 移动选择区域 1px |
| Shift + ←, ↓, ↑, → | 将选择区域大小更改 1px | | `Shift` + `←`、`↓`、`↑`、`→` | 将选择区域大小更改 1px |
| Esc | 退出截图 | | `Esc` | 退出截图 |
| Ctrl + C | 复制到粘贴板 | | `Ctrl` + `C` | 复制到粘贴板 |
| Ctrl + S | 将选择区域保存为文件 | | `Ctrl` + `S` | 将选择区域保存为文件 |
| Ctrl + Z | 撤销最近的一次操作 | | `Ctrl` + `Z` | 撤销最近的一次操作 |
| Right Click | 展示颜色拾取器 | | 鼠标右键 | 展示颜色拾取器 |
| Mouse Wheel | 改变工具的宽度 | | 鼠标滚轮 | 改变工具的宽度 |
边按住 Shift 键并拖动选择区域的其中一个控制点将会对它相反方向的控制点做类似的拖放操作。 边按住 `Shift` 键并拖动选择区域的其中一个控制点将会对它相反方向的控制点做类似的拖放操作。
**命令行选项** ### 命令行选项
Flameshot 也支持一系列的命令行选项来延时截图和保存图片到自定义的路径。 Flameshot 也支持一系列的命令行选项来延时截图和保存图片到自定义的路径。
要使用 Flameshot GUI 模式,运行: 要使用 Flameshot GUI 模式,运行:
``` ```
$ flameshot gui $ flameshot gui
``` ```
要使用 GUI 模式截屏并将你选取的区域保存到一个自定义的路径,运行: 要使用 GUI 模式截屏并将你选取的区域保存到一个自定义的路径,运行:
``` ```
$ flameshot gui -p ~/myStuff/captures $ flameshot gui -p ~/myStuff/captures
``` ```
要延时 2 秒后打开 GUI 模式可以使用: 要延时 2 秒后打开 GUI 模式可以使用:
``` ```
$ flameshot gui -d 2000 $ flameshot gui -d 2000
``` ```
要延时 2 秒并将截图保存到一个自定义的路径(无 GUI可以使用 要延时 2 秒并将截图保存到一个自定义的路径(无 GUI可以使用
``` ```
$ flameshot full -p ~/myStuff/captures -d 2000 $ flameshot full -p ~/myStuff/captures -d 2000
``` ```
要截图全屏并保存到自定义的路径和粘贴板中使用: 要截图全屏并保存到自定义的路径和粘贴板中使用:
``` ```
$ flameshot full -c -p ~/myStuff/captures $ flameshot full -c -p ~/myStuff/captures
``` ```
要在截屏中包含鼠标并将图片保存为 **PNG** 格式可以使用: 要在截屏中包含鼠标并将图片保存为 PNG 格式可以使用:
``` ```
$ flameshot screen -r $ flameshot screen -r
``` ```
要对屏幕 1 进行截屏并将截屏复制到粘贴板中可以运行: 要对屏幕 1 进行截屏并将截屏复制到粘贴板中可以运行:
``` ```
$ flameshot screen -n 1 -c $ flameshot screen -n 1 -c
``` ```
@ -143,7 +154,7 @@ via: https://www.ostechnix.com/flameshot-a-simple-yet-powerful-feature-rich-scre
作者:[SK][a] 作者:[SK][a]
选题:[lujun9972](https://github.com/lujun9972) 选题:[lujun9972](https://github.com/lujun9972)
译者:[FSSlc](https://github.com/FSSlc) 译者:[FSSlc](https://github.com/FSSlc)
校对:[校对者ID](https://github.com/校对者ID) 校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,28 +1,23 @@
# 用 350 行代码从零开始,将 Lisp 编译成 JavaScript 用 350 行代码从零开始,将 Lisp 编译成 JavaScript
======
我们将会在本篇文章中看到从零开始实现的编译器,将简单的类 LISP 计算语言编译成 JavaScript。完整的源代码在 [这里][7]. 我们将会在本篇文章中看到从零开始实现的编译器,将简单的类 LISP 计算语言编译成 JavaScript。完整的源代码在 [这里][7]
我们将会: 我们将会:
1. 自定义语言,并用它编写一个简单的程序 1. 自定义语言,并用它编写一个简单的程序
2. 实现一个简单的解析器组合器 2. 实现一个简单的解析器组合器
3. 为该语言实现一个解析器 3. 为该语言实现一个解析器
4. 为该语言实现一个美观的打印器 4. 为该语言实现一个美观的打印器
5. 为我们的用途定义 JavaScript 的一个子集
5. 为我们的需求定义 JavaScript 的一个子集
6. 实现代码转译器,将代码转译成我们定义的 JavaScript 子集 6. 实现代码转译器,将代码转译成我们定义的 JavaScript 子集
7. 把所有东西整合在一起 7. 把所有东西整合在一起
开始吧! 开始吧!
### 1. 定义语言 ### 1定义语言
lisps 最迷人的地方在于它们的语法就是树状表示的这就是这门语言很容易解析的原因。我们很快就能接触到它。但首先让我们把自己的语言定义好。关于我们语言的语法的范式BNF描述如下 Lisp 族语言最迷人的地方在于它们的语法就是树状表示的这就是这门语言很容易解析的原因。我们很快就能接触到它。但首先让我们把自己的语言定义好。关于我们语言的语法的范式BNF描述如下
``` ```
program ::= expr program ::= expr
@ -35,17 +30,17 @@ expr ::= <integer> | <name> | ([<expr>])
该语言中,我们保留一些内建的特殊形式,这样我们就能做一些更有意思的事情: 该语言中,我们保留一些内建的特殊形式,这样我们就能做一些更有意思的事情:
* let 表达式使我们可以在它的 body 环境中引入新的变量。语法如下: * `let` 表达式使我们可以在它的 `body` 环境中引入新的变量。语法如下:
``` ```
let ::= (let ([<letarg>]) <body>) let ::= (let ([<letarg>]) <body>)
letargs ::= (<name> <expr>) letargs ::= (<name> <expr>)
body ::= <expr> body ::= <expr>
``` ```
* lambda 表达式:也就是匿名函数定义。语法如下: * `lambda` 表达式:也就是匿名函数定义。语法如下:
``` ```
lambda ::= (lambda ([<name>]) <body>) lambda ::= (lambda ([<name>]) <body>)
``` ```
@ -94,12 +89,11 @@ data Atom
另一件你想做的事情可能是在语法中添加一些注释信息。比如定位:`Expr` 是来自哪个文件的,具体到这个文件的哪一行哪一列。你可以在后面的阶段中使用这一特性,打印出错误定位,即使它们不是处于解析阶段。 另一件你想做的事情可能是在语法中添加一些注释信息。比如定位:`Expr` 是来自哪个文件的,具体到这个文件的哪一行哪一列。你可以在后面的阶段中使用这一特性,打印出错误定位,即使它们不是处于解析阶段。
* _练习 1_:添加一个 `Program` 数据类型,可以按顺序包含多个 `Expr` * _练习 1_:添加一个 `Program` 数据类型,可以按顺序包含多个 `Expr`
* _练习 2_:向语法树中添加一个定位注解。 * _练习 2_:向语法树中添加一个定位注解。
### 2. 实现一个简单的解析器组合库 ### 2实现一个简单的解析器组合库
我们要做的第一件事情是定义一个嵌入式领域专用语言Embedded Domain Specific Language 或者 EDSL我们会用它来定义我们的语言解析器。这常常被称为解析器组合库。我们做这件事完全是出于学习的目的Haskell 里有很好的解析库,在实际构建软件或者进行实验时,你应该使用它们。[megaparsec][8] 就是这样的一个库。 我们要做的第一件事情是定义一个<ruby>嵌入式领域专用语言<rt>Embedded Domain Specific Language</rt></ruby>EDSL我们会用它来定义我们的语言解析器。这常常被称为解析器组合库。我们做这件事完全是出于学习的目的Haskell 里有很好的解析库,在实际构建软件或者进行实验时,你应该使用它们。[megaparsec][8] 就是这样的一个库。
首先我们来谈谈解析库的实现的思路。本质上,我们的解析器就是一个函数,接受一些输入,可能会读取输入的一些或全部内容,然后返回解析出来的值和无法解析的输入部分,或者在解析失败时抛出异常。我们把它写出来。 首先我们来谈谈解析库的实现的思路。本质上,我们的解析器就是一个函数,接受一些输入,可能会读取输入的一些或全部内容,然后返回解析出来的值和无法解析的输入部分,或者在解析失败时抛出异常。我们把它写出来。
@ -114,7 +108,6 @@ data ParseError
= ParseError ParseString Error = ParseError ParseString Error
type Error = String type Error = String
``` ```
这里我们定义了三个主要的新类型。 这里我们定义了三个主要的新类型。
@ -124,9 +117,7 @@ type Error = String
第二个,`ParseString` 是我们的输入或携带的状态。它有三个重要的部分: 第二个,`ParseString` 是我们的输入或携带的状态。它有三个重要的部分:
* `Name`: 这是源的名字 * `Name`: 这是源的名字
* `(Int, Int)`: 这是源的当前位置 * `(Int, Int)`: 这是源的当前位置
* `String`: 这是等待解析的字符串 * `String`: 这是等待解析的字符串
第三个,`ParseError` 包含了解析器的当前状态和一个错误信息。 第三个,`ParseError` 包含了解析器的当前状态和一个错误信息。
@ -180,13 +171,11 @@ instance Monad Parser where
Right (rs, rest) -> Right (rs, rest) ->
case f rs of case f rs of
Parser parser -> parser rest Parser parser -> parser rest
``` ```
接下来,让我们定义一种的方式,用于运行解析器和防止失败的助手函数: 接下来,让我们定义一种的方式,用于运行解析器和防止失败的助手函数:
``` ```
runParser :: String -> String -> Parser a -> Either ParseError (a, ParseString) runParser :: String -> String -> Parser a -> Either ParseError (a, ParseString)
runParser name str (Parser parser) = parser $ ParseString name (0,0) str runParser name str (Parser parser) = parser $ ParseString name (0,0) str
@ -237,7 +226,6 @@ many parser = go []
many1 :: Parser a -> Parser [a] many1 :: Parser a -> Parser [a]
many1 parser = many1 parser =
(:) <$> parser <*> many parser (:) <$> parser <*> many parser
``` ```
下面的这些解析器通过我们定义的组合器来实现一些特殊的解析器: 下面的这些解析器通过我们定义的组合器来实现一些特殊的解析器:
@ -273,14 +261,13 @@ sepBy sep parser = do
frst <- optional parser frst <- optional parser
rest <- many (sep *> parser) rest <- many (sep *> parser)
pure $ maybe rest (:rest) frst pure $ maybe rest (:rest) frst
``` ```
现在为该门语言定义解析器所需要的所有东西都有了。 现在为该门语言定义解析器所需要的所有东西都有了。
* _练习_ :实现一个 EOFend of file/input即文件或输入终止符解析器组合器。 * _练习_ :实现一个 EOFend of file/input即文件或输入终止符解析器组合器。
### 3. 为我们的语言实现解析器 ### 3为我们的语言实现解析器
我们会用自顶而下的方法定义解析器。 我们会用自顶而下的方法定义解析器。
@ -296,7 +283,6 @@ parseAtom = parseSymbol <|> parseInt
parseSymbol :: Parser Atom parseSymbol :: Parser Atom
parseSymbol = fmap Symbol parseName parseSymbol = fmap Symbol parseName
``` ```
注意到这四个函数是在我们这门语言中属于高阶描述。这解释了为什么 Haskell 执行解析工作这么棒。在定义完高级部分后,我们还需要定义低级别的 `parseName``parseInt` 注意到这四个函数是在我们这门语言中属于高阶描述。这解释了为什么 Haskell 执行解析工作这么棒。在定义完高级部分后,我们还需要定义低级别的 `parseName``parseInt`
@ -311,7 +297,7 @@ parseName = do
pure (c:cs) pure (c:cs)
``` ```
整数是一系列数字,数字前面可能有负号 - 整数是一系列数字,数字前面可能有负号 `-`
``` ```
parseInt :: Parser Atom parseInt :: Parser Atom
@ -333,12 +319,10 @@ runExprParser name str =
``` ```
* _练习 1_ :为第一节中定义的 `Program` 类型编写一个解析器 * _练习 1_ :为第一节中定义的 `Program` 类型编写一个解析器
* _练习 2_ :用 Applicative 的形式重写 `parseName` * _练习 2_ :用 Applicative 的形式重写 `parseName`
* _练习 3_ `parseInt` 可能出现溢出情况,找到处理它的方法,不要用 `read` * _练习 3_ `parseInt` 可能出现溢出情况,找到处理它的方法,不要用 `read`
### 4. 为这门语言实现一个更好看的输出器 ### 4为这门语言实现一个更好看的输出器
我们还想做一件事,将我们的程序以源代码的形式打印出来。这对完善错误信息很有用。 我们还想做一件事,将我们的程序以源代码的形式打印出来。这对完善错误信息很有用。
@ -372,7 +356,7 @@ indent tabs e = concat (replicate tabs " ") ++ e
好,目前为止我们写了近 200 行代码,这些代码一般叫做编译器的前端。我们还要写大概 150 行代码,用来执行三个额外的任务:我们需要根据需求定义一个 JS 的子集,定义一个将我们的语言转译成这个子集的转译器,最后把所有东西整合在一起。开始吧。 好,目前为止我们写了近 200 行代码,这些代码一般叫做编译器的前端。我们还要写大概 150 行代码,用来执行三个额外的任务:我们需要根据需求定义一个 JS 的子集,定义一个将我们的语言转译成这个子集的转译器,最后把所有东西整合在一起。开始吧。
### 5. 根据需求定义 JavaScript 的子集 ### 5根据需求定义 JavaScript 的子集
首先,我们要定义将要使用的 JavaScript 的子集: 首先,我们要定义将要使用的 JavaScript 的子集:
@ -411,10 +395,9 @@ printJSExpr doindent tabs = \case
``` ```
* _练习 1_ :添加 `JSProgram` 类型,它可以包含多个 `JSExpr` ,然后创建一个叫做 `printJSExprProgram` 的函数来生成代码。 * _练习 1_ :添加 `JSProgram` 类型,它可以包含多个 `JSExpr` ,然后创建一个叫做 `printJSExprProgram` 的函数来生成代码。
* _练习 2_ :添加 `JSExpr` 的新类型:`JSIf`,并为其生成代码。 * _练习 2_ :添加 `JSExpr` 的新类型:`JSIf`,并为其生成代码。
### 6. 实现到我们定义的 JavaScript 子集的代码转译器 ### 6实现到我们定义的 JavaScript 子集的代码转译器
我们快做完了。这一节将会创建函数,将 `Expr` 转译成 `JSExpr` 我们快做完了。这一节将会创建函数,将 `Expr` 转译成 `JSExpr`
@ -437,7 +420,6 @@ translateList = \case
f xs f xs
f:xs -> f:xs ->
JSFunCall <$> translateToJS f <*> traverse translateToJS xs JSFunCall <$> translateToJS f <*> traverse translateToJS xs
``` ```
`builtins` 是一系列要转译的特例,就像 `lambada``let`。每一种情况都可以获得一系列参数,验证它是否合乎语法规范,然后将其转译成等效的 `JSExpr` `builtins` 是一系列要转译的特例,就像 `lambada``let`。每一种情况都可以获得一系列参数,验证它是否合乎语法规范,然后将其转译成等效的 `JSExpr`
@ -456,7 +438,6 @@ builtins =
,("div", transBinOp "div" "/") ,("div", transBinOp "div" "/")
,("print", transPrint) ,("print", transPrint)
] ]
``` ```
我们这种情况,会将内建的特殊形式当作特殊的、非第一类的进行对待,因此不可能将它们当作第一类函数。 我们这种情况,会将内建的特殊形式当作特殊的、非第一类的进行对待,因此不可能将它们当作第一类函数。
@ -480,10 +461,9 @@ transLambda = \case
fromSymbol :: Expr -> Either String Name fromSymbol :: Expr -> Either String Name
fromSymbol (ATOM (Symbol s)) = Right s fromSymbol (ATOM (Symbol s)) = Right s
fromSymbol e = Left $ "cannot bind value to non symbol type: " ++ show e fromSymbol e = Left $ "cannot bind value to non symbol type: " ++ show e
``` ```
我们会将 let 转译成带有相关名字参数的函数定义,然后带上参数调用函数,因此会在这一作用域中引入变量: 我们会将 `let` 转译成带有相关名字参数的函数定义,然后带上参数调用函数,因此会在这一作用域中引入变量:
``` ```
transLet :: [Expr] -> Either TransError JSExpr transLet :: [Expr] -> Either TransError JSExpr
@ -522,35 +502,27 @@ transBinOp _ f list = foldl1 (JSBinOp f) <$> traverse translateToJS list
transPrint :: [Expr] -> Either TransError JSExpr transPrint :: [Expr] -> Either TransError JSExpr
transPrint [expr] = JSFunCall (JSSymbol "console.log") . (:[]) <$> translateToJS expr transPrint [expr] = JSFunCall (JSSymbol "console.log") . (:[]) <$> translateToJS expr
transPrint xs = Left $ "Syntax error. print expected 1 arguments, got: " ++ show (length xs) transPrint xs = Left $ "Syntax error. print expected 1 arguments, got: " ++ show (length xs)
``` ```
注意,如果我们将这些代码当作 `Expr` 的特例进行解析,那我们就可能会跳过语法验证。 注意,如果我们将这些代码当作 `Expr` 的特例进行解析,那我们就可能会跳过语法验证。
* _练习 1_ :将 `Program` 转译成 `JSProgram` * _练习 1_ :将 `Program` 转译成 `JSProgram`
* _练习 2_ :为 `if Expr Expr Expr` 添加一个特例,并将它转译成你在上一次练习中实现的 `JSIf` 条件语句。 * _练习 2_ :为 `if Expr Expr Expr` 添加一个特例,并将它转译成你在上一次练习中实现的 `JSIf` 条件语句。
### 7. 把所有东西整合到一起 ### 7把所有东西整合到一起
最终,我们将会把所有东西整合到一起。我们会: 最终,我们将会把所有东西整合到一起。我们会:
1. 读取文件 1. 读取文件
2. 将文件解析成 `Expr` 2. 将文件解析成 `Expr`
3. 将文件转译成 `JSExpr` 3. 将文件转译成 `JSExpr`
4. 将 JavaScript 代码发送到标准输出流 4. 将 JavaScript 代码发送到标准输出流
我们还会启用一些用于测试的标志位: 我们还会启用一些用于测试的标志位:
* `--e` 将进行解析并打印出表达式的抽象表示(`Expr` * `--e` 将进行解析并打印出表达式的抽象表示(`Expr`
* `--pp` 将进行解析,美化输出 * `--pp` 将进行解析,美化输出
* `--jse` 将进行解析、转译、并打印出生成的 JS 表达式(`JSExpr`)的抽象表示 * `--jse` 将进行解析、转译、并打印出生成的 JS 表达式(`JSExpr`)的抽象表示
* `--ppc` 将进行解析,美化输出并进行编译 * `--ppc` 将进行解析,美化输出并进行编译
``` ```
@ -616,10 +588,10 @@ undefined
via: https://gilmi.me/blog/post/2016/10/14/lisp-to-js via: https://gilmi.me/blog/post/2016/10/14/lisp-to-js
作者:[ Gil Mizrahi ][a] 作者:[Gil Mizrahi][a]
选题:[oska874][b] 选题:[oska874][b]
译者:[BriFuture](https://github.com/BriFuture) 译者:[BriFuture](https://github.com/BriFuture)
校对:[校对者ID](https://github.com/校对者ID) 校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -3,11 +3,11 @@
![](https://www.ostechnix.com/wp-content/uploads/2018/06/Rename-Multiple-Files-720x340.png) ![](https://www.ostechnix.com/wp-content/uploads/2018/06/Rename-Multiple-Files-720x340.png)
你可能已经知道,我们使用 mv 命令在类 Unix 操作系统中重命名或者移动文件和目录。 但是mv 命令不支持一次重命名多个文件。 不用担心。 在本教程中,我们将学习使用 Linux 中的 “mmv” 命令一次重命名多个文件。 此命令用于在类 Unix 操作系统中使用标准通配符批量移动,复制,追加和重命名文件。 你可能已经知道,我们使用 `mv` 命令在类 Unix 操作系统中重命名或者移动文件和目录。 但是,`mv` 命令不支持一次重命名多个文件。 不用担心。 在本教程中,我们将学习使用 Linux 中的 `mmv` 命令一次重命名多个文件。 此命令用于在类 Unix 操作系统中使用标准通配符批量移动、复制、追加和重命名文件。
### 在 Linux 中一次重命名多个文件 ### 在 Linux 中一次重命名多个文件
mmv 程序可在基于 Debian 的系统的默认仓库中使用。 要想在 DebianUbuntuLinux Mint 上安装它,请运行以下命令: `mmv` 程序可在基于 Debian 的系统的默认仓库中使用。 要想在 Debian、Ubuntu、Linux Mint 上安装它,请运行以下命令:
``` ```
$ sudo apt-get install mmv $ sudo apt-get install mmv
@ -20,7 +20,7 @@ $ ls
a1.txt a2.txt a3.txt a1.txt a2.txt a3.txt
``` ```
现在,你想要将所有以字母 “a” 开头的文件重命名为以 “b” 开头的。 当然,你可以在几秒钟内手动执行此操作。 但是想想你是否有数百个文件想要重命名? 这是一个非常耗时的过程。 这时候 **mmv** 命令就很有帮助了。 现在,你想要将所有以字母 “a” 开头的文件重命名为以 “b” 开头的。 当然,你可以在几秒钟内手动执行此操作。 但是想想你是否有数百个文件想要重命名? 这是一个非常耗时的过程。 这时候 `mmv` 命令就很有帮助了。
要将所有以字母 “a” 开头的文件重命名为以字母 “b” 开头的,只需要运行: 要将所有以字母 “a” 开头的文件重命名为以字母 “b” 开头的,只需要运行:
@ -33,22 +33,20 @@ $ mmv a\* b\#1
``` ```
$ ls $ ls
b1.txt b2.txt b3.txt b1.txt b2.txt b3.txt
``` ```
如你所见,所有以字母 “a” 开头的文件(即 a1.txta2.txta3.txt都重命名为 b1.txtb2.txtb3.txt 如你所见,所有以字母 “a” 开头的文件(即 `a1.txt`、`a2.txt`、`a3.txt`)都重命名为 `b1.txt`、`b2.txt`、`b3.txt`
**解释** **解释**
在上面的例子中,第一个参数(a\\*)是 'from' 模式,第二个参数是 'to' 模式b\\#1。根据上面的例子mmv 将查找任何以字母 'a' 开头的文件名,并根据第二个参数重命名匹配的文件,即 'to' 模式。我们使用通配符,例如用 '*''?' 和 '[]' 来匹配一个或多个任意字符。请注意,你必须避免使用通配符,否则它们将被 shell 扩展mmv 将无法理解。 在上面的例子中,第一个参数(`a\*`)是 “from” 模式,第二个参数是 “to” 模式(`b\#1`)。根据上面的例子,`mmv` 将查找任何以字母 “a” 开头的文件名,并根据第二个参数重命名匹配的文件,即 “to” 模式。我们可以使用通配符,例如用 `*`、`?` 和 `[]` 来匹配一个或多个任意字符。请注意,你必须转义使用通配符,否则它们将被 shell 扩展,`mmv` 将无法理解。
'to' 模式中的 '#1' 是通配符索引。它匹配 'from' 模式中的第一个通配符。 'to' 模式中的 '#2' 将匹配第二个通配符,依此类推。在我们的例子中,我们只有一个通配符(星号),所以我们写了一个 #1。并且,哈希标志也应该被转义。此外,你也可以用引号括起模式。 “to” 模式中的 `#1` 是通配符索引。它匹配 “from” 模式中的第一个通配符。 “to” 模式中的 `#2` 将匹配第二个通配符(如果有的话),依此类推。在我们的例子中,我们只有一个通配符(星号),所以我们写了一个 `#1`。并且,`#` 符号也应该被转义。此外,你也可以用引号括起模式。
你甚至可以将具有特定扩展名的所有文件重命名为其他扩展名。例如,要将当前目录中的所有 **.txt** 文件重命名为 **.doc** 文件格式,只需运行: 你甚至可以将具有特定扩展名的所有文件重命名为其他扩展名。例如,要将当前目录中的所有 `.txt` 文件重命名为 `.doc` 文件格式,只需运行:
``` ```
$ mmv \*.txt \#1.doc $ mmv \*.txt \#1.doc
``` ```
这是另一个例子。 我们假设你有以下文件。 这是另一个例子。 我们假设你有以下文件。
@ -56,16 +54,14 @@ $ mmv \*.txt \#1.doc
``` ```
$ ls $ ls
abcd1.txt abcd2.txt abcd3.txt abcd1.txt abcd2.txt abcd3.txt
``` ```
你希望在当前目录下的所有文件中将第一次出现的 **abc** 替换为 **xyz**。 你会怎么做呢? 你希望在当前目录下的所有文件中将第一次出现的 “abc” 替换为 “xyz”。 你会怎么做呢?
很简单。 很简单。
``` ```
$ mmv '*abc*' '#1xyz#2' $ mmv '*abc*' '#1xyz#2'
``` ```
请注意,在上面的示例中,模式被单引号括起来了。 请注意,在上面的示例中,模式被单引号括起来了。
@ -75,77 +71,74 @@ $ mmv '*abc*' '#1xyz#2'
``` ```
$ ls $ ls
xyzd1.txt xyzd2.txt xyzd3.txt xyzd1.txt xyzd2.txt xyzd3.txt
``` ```
看到没? 文件 **abcd1.txt****abcd2.txt** 和 **abcd3.txt** 已经重命名为 **xyzd1.txt****xyzd2.txt** 和 **xyzd3.txt** 看到没? 文件 `abcd1.txt`、`abcd2.txt` 和 `abcd3.txt` 已经重命名为 `xyzd1.txt`、`xyzd2.txt` 和 `xyzd3.txt`
mmv 命令的另一个值得注意的功能是你可以使用 **-n** 选项打印输出而不是重命名文件,如下所示。 `mmv` 命令的另一个值得注意的功能是你可以使用 `-n` 选项打印输出而不是重命名文件,如下所示。
``` ```
$ mmv -n a\* b\#1 $ mmv -n a\* b\#1
a1.txt -> b1.txt a1.txt -> b1.txt
a2.txt -> b2.txt a2.txt -> b2.txt
a3.txt -> b3.txt a3.txt -> b3.txt
``` ```
这样,你可以在重命名文件之前简单地验证 mmv 命令实际执行的操作。 这样,你可以在重命名文件之前简单地验证 `mmv` 命令实际执行的操作。
有关更多详细信息,请参阅 man 页面。 有关更多详细信息,请参阅 man 页面。
``` ```
$ man mmv $ man mmv
``` ```
**更新:** ### 更新Thunar 文件管理器
**Thunar 文件管理器**默认具有内置**批量重命名**选项。 如果你正在使用thunar那么重命名文件要比使用mmv命令容易得多。 **Thunar 文件管理器**默认具有内置**批量重命名**选项。 如果你正在使用 Thunar那么重命名文件要比使用 `mmv` 命令容易得多。
Thunar在大多数Linux发行版的默认仓库库中都可用。 Thunar 在大多数 Linux 发行版的默认仓库库中都可用。
要在基于Arch的系统上安装它请运行 要在基于 Arch 的系统上安装它,请运行:
``` ```
$ sudo pacman -S thunar $ sudo pacman -S thunar
``` ```
在 RHELCentOS 上: 在 RHEL、CentOS 上:
``` ```
$ sudo yum install thunar $ sudo yum install thunar
``` ```
在 Fedora 上: 在 Fedora 上:
``` ```
$ sudo dnf install thunar $ sudo dnf install thunar
``` ```
在 openSUSE 上: 在 openSUSE 上:
``` ```
$ sudo zypper install thunar $ sudo zypper install thunar
``` ```
在 DebianUbuntuLinux Mint 上: 在 Debian、Ubuntu、Linux Mint 上:
``` ```
$ sudo apt-get install thunar $ sudo apt-get install thunar
``` ```
安装后,你可以从菜单或应用程序启动器中启动批量重命名程序。 要从终端启动它,请使用以下命令: 安装后,你可以从菜单或应用程序启动器中启动批量重命名程序。 要从终端启动它,请使用以下命令:
``` ```
$ thunar -B $ thunar -B
``` ```
批量重命名就是这么回事 批量重命名方式如下
![][1] ![][1]
单击加号,然后选择要重命名的文件列表。 批量重命名可以重命名文件的名称,文件的后缀或者同事重命名文件的名称和后缀。 Thunar 目前支持以下批量重命名: 单击“+”,然后选择要重命名的文件列表。 批量重命名可以重命名文件的名称、文件的后缀或者同时重命名文件的名称和后缀。 Thunar 目前支持以下批量重命名:
- 插入日期或时间 - 插入日期或时间
- 插入或覆盖 - 插入或覆盖
@ -158,9 +151,9 @@ $ thunar -B
![][2] ![][2]
选择条件后,单击**重命名文件**选项来重命名文件。 选择条件后,单击“重命名文件”选项来重命名文件。
你还可以通过选择两个或更多文件从 Thunar 中打开批量重命名器。 选择文件后,按F2或右键单击并选择**重命名** 你还可以通过选择两个或更多文件从 Thunar 中打开批量重命名器。 选择文件后,按 F2 或右键单击并选择“重命名”
嗯,这就是本次的所有内容了。希望有所帮助。更多干货即将到来。敬请关注! 嗯,这就是本次的所有内容了。希望有所帮助。更多干货即将到来。敬请关注!
@ -173,7 +166,7 @@ via: https://www.ostechnix.com/how-to-rename-multiple-files-at-once-in-linux/
作者:[SK][a] 作者:[SK][a]
选题:[lujun9972](https://github.com/lujun9972) 选题:[lujun9972](https://github.com/lujun9972)
译者:[Flowsnow](https://github.com/Flowsnow) 译者:[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/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,164 @@
Flameshot一个简洁但功能丰富的截图工具
======
![](https://www.ostechnix.com/wp-content/uploads/2018/09/Flameshot-720x340.png)
截图是我工作的一部分,我先前使用深度截图工具来截图,深度截图是一个简单、轻量级且非常简洁的截图工具。它自带许多功能例如窗口识别、快捷键支持、图片编辑、延时截图、社交分享、智能存储以及图片清晰度调整等功能。今天我碰巧发现了另一个具备多种功能的截图工具,它就是 **Flameshot** ,一个简单但功能丰富的针对类 Unix 系统的截图工具。它简单易用,可定制并且有选项可以支持上传截图到在线图片分享网站 **imgur** 上。同时 Flameshot 有一个 CLI 版本所以你也可以从命令行来进行截图。Flameshot 是一个完全免费且开源的工具。在本教程中,我们将看到如何安装 Flameshot 以及如何使用它来截图。
### 安装 Flameshot
**在 Arch Linux 上:**
Flameshot 可以从 Arch LInux 的 [community] 仓库中获取。确保你已经启用了 community 仓库,然后就可以像下面展示的那样使用 pacman 来安装 Flameshot
```
$ sudo pacman -S flameshot
```
它也可以从 [**AUR**][1] 中获取,所以你还可以使用任意一个 AUR 帮助程序(例如 [**Yay**][2])来在基于 Arch 的系统中安装它:
```
$ yay -S flameshot-git
```
**在 Fedora 中:**
```
$ sudo dnf install flameshot
```
**Debian 10+****Ubuntu 18.04+** 中,可以使用 APT 包管理器来安装它:
```
$ sudo apt install flameshot
```
**在 openSUSE 上:**
```
$ sudo zypper install flameshot
```
在其他的 Linux 发行版中,可以从源代码编译并安装它。编译过程中需要 **Qt version 5.3** 以及 **GCC 4.9.2** 或者它们的更高版本。
### 使用
可以从菜单或者应用启动器中启动 Flameshot。在 MATE 桌面环境,它通常可以在 “Applications -> Graphics” 下找到。
一旦打开了它,你就可以在系统面板中看到 Flameshot 的托盘图标。
**注意:**
假如你使用 Gnome 桌面环境,为了能够看到系统托盘图标,你需要安装 [TopIcons][3] 扩展。
在 Flameshot 托盘图标上右击,你便会看到几个菜单项,例如打开配置窗口、信息窗口以及退出该应用。
要进行截图,只需要点击托盘图标就可以了。接着你将看到如何使用 Flameshot 的帮助窗口。选择一个截图区域,然后敲回车键便可以截屏了,点击右键便可以看到颜色拾取器,再敲空格键便可以查看屏幕侧边的面板。你可以使用鼠标的滚轮来增加或者减少指针的宽度。
Flameshot 自带一系列非常好的功能,例如:
* 可以进行手写
* 可以划直线
* 可以画长方形或者圆形框
* 可以进行长方形区域选择
* 可以画箭头
* 可以对要点进行标注
* 可以添加文本
* 可以对图片或者文字进行模糊处理
* 可以展示图片的尺寸大小
* 在编辑图片是可以进行撤销和重做操作
* 可以将选择的东西复制到剪贴板
* 可以保存选区
* 可以离开截屏
* 可以选择另一个 app 来打开图片
* 可以上传图片到 imgur 网站
* 可以将图片固定到桌面上
下面是一个示例的视频:
<http://www.ostechnix.com/wp-content/uploads/2018/09/Flameshot-demo.mp4>
### 快捷键
Frameshot 也支持快捷键。在 Flameshot 的托盘图标上右击并点击 “Information” 窗口便可以看到在 GUI 模式下所有可用的快捷键。下面是在 GUI 模式下可用的快捷键清单:
| 快捷键 | 描述 |
|------------------------|------------------------------|
| `←`、`↓`、`↑`、`→` | 移动选择区域 1px |
| `Shift` + `←`、`↓`、`↑`、`→` | 将选择区域大小更改 1px |
| `Esc` | 退出截图 |
| `Ctrl` + `C` | 复制到粘贴板 |
| `Ctrl` + `S` | 将选择区域保存为文件 |
| `Ctrl` + `Z` | 撤销最近的一次操作 |
| 鼠标右键 | 展示颜色拾取器 |
| 鼠标滚轮 | 改变工具的宽度 |
边按住 `Shift` 键并拖动选择区域的其中一个控制点将会对它相反方向的控制点做类似的拖放操作。
### 命令行选项
Flameshot 也支持一系列的命令行选项来延时截图和保存图片到自定义的路径。
要使用 Flameshot GUI 模式,运行:
```
$ flameshot gui
```
要使用 GUI 模式截屏并将你选取的区域保存到一个自定义的路径,运行:
```
$ flameshot gui -p ~/myStuff/captures
```
要延时 2 秒后打开 GUI 模式可以使用:
```
$ flameshot gui -d 2000
```
要延时 2 秒并将截图保存到一个自定义的路径(无 GUI可以使用
```
$ flameshot full -p ~/myStuff/captures -d 2000
```
要截图全屏并保存到自定义的路径和粘贴板中使用:
```
$ flameshot full -c -p ~/myStuff/captures
```
要在截屏中包含鼠标并将图片保存为 PNG 格式可以使用:
```
$ flameshot screen -r
```
要对屏幕 1 进行截屏并将截屏复制到粘贴板中可以运行:
```
$ flameshot screen -n 1 -c
```
你还需要什么功能呢Flameshot 拥有几乎截屏的所有功能:添加注释、编辑图片、模糊处理或者对要点做高亮等等功能。我想:在我找到它的最佳替代品之前,我将一直使用 Flameshot 来作为我当前的截图工具。请尝试一下它,你不会失望的。
好了,这就是今天的全部内容了。后续将有更多精彩内容,请保持关注!
Cheers!
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/flameshot-a-simple-yet-powerful-feature-rich-screenshot-tool/
作者:[SK][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[FSSlc](https://github.com/FSSlc)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.ostechnix.com/author/sk/
[1]: https://aur.archlinux.org/packages/flameshot-git
[2]: https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
[3]: https://extensions.gnome.org/extension/1031/topicons/

View File

@ -0,0 +1,277 @@
重启和关闭 Linux 系统的 6 个终端命令
======
在 Linux 管理员的日程当中,有很多需要执行的任务,其中就有系统的重启和关闭。
对于 Linux 管理员来说,重启和关闭系统是其诸多风险操作中的一例,有时候,由于某些原因,这些操作可能无法挽回,他们需要更多的时间来排查问题。
在 Linux 命令行模式下我们可以执行这些任务。很多时候由于熟悉命令行Linux 管理员更倾向于在命令行下完成这些任务。
重启和关闭系统的 Linux 命令并不多,用户需要根据需要,选择合适的命令来完成任务。
以下所有命令都有其自身特点,并允许被 Linux 管理员使用.
**建议阅读:**
- [查看系统/服务器正常运行时间的 11 个方法][1]
- [Tuptime 一款为 Linux 系统保存历史记录、统计运行时间工具][2]
系统重启和关闭之始,会通知所有已登录的用户和进程。当然,如果使用了时间参数,系统将拒绝新的用户登入。
执行此类操作之前,我建议您坚持复查,因为您只能得到很少的提示来确保这一切顺利。
下面陈列了一些步骤:
* 确保您拥有一个可以处理故障的控制台,以防之后可能会发生的问题。 VMWare 可以访问虚拟机,而 IPMI、iLO 和 iDRAC 可以访问物理服务器。
* 您需要通过公司的流程,申请修改或故障的执行权直到得到许可。
* 为安全着想,备份重要的配置文件,并保存到其他服务器上.
* 验证日志文件(提前检查)
* 和相关团队交流,比如数据库管理团队,应用团队等。
* 通知数据库和应用服务人员关闭服务,并得到确定答复。
* 使用适当的命令复盘操作,验证工作。
* 最后,重启系统。
* 验证日志文件,如果一切顺利,执行下一步操作,如果发现任何问题,对症排查。
* 无论是回退版本还是运行程序,通知相关团队提出申请。
* 对操作做适当守候,并将预期的一切正常的反馈给团队
使用下列命令执行这项任务。
* `shutdown`、`halt`、`poweroff`、`reboot` 命令:用来停机、重启或切断电源
* `init` 命令:是 “initialization” 的简称,是系统启动的第一个进程。
* `systemctl` 命令systemd 是 Linux 系统和服务器的管理程序。
### 方案 1如何使用 shutdown 命令关闭和重启 Linux 系统
`shutdown` 命令用于断电或重启本地和远程的 Linux 机器。它为高效完成作业提供多个选项。如果使用了时间参数,系统关闭的 5 分钟之前,会创建 `/run/nologin` 文件,以确保后续的登录会被拒绝。
通用语法如下:
```
# shutdown [OPTION] [TIME] [MESSAGE]
```
运行下面的命令来立即关闭 Linux 机器。它会立刻杀死所有进程,并关闭系统。
```
# shutdown -h now
```
* `-h`:如果不特指 `-halt` 选项,这等价于 `-poweroff` 选项。
另外我们可以使用带有 `-halt` 选项的 `shutdown` 命令来立即关闭设备。
```
# shutdown --halt now
或者
# shutdown -H now
```
* `-H, --halt`:停止设备运行
另外我们可以使用带有 `poweroff` 选项的 `shutdown` 命令来立即关闭设备。
```
# shutdown --poweroff now
或者
# shutdown -P now
```
* `-P, --poweroff`:切断电源(默认)。
如果您没有使用时间选项运行下面的命令,它将会在一分钟后执行给出的命令。
```
# shutdown -h
Shutdown scheduled for Mon 2018-10-08 06:42:31 EDT, use 'shutdown -c' to cancel.
root@2daygeek.com#
Broadcast message from root@vps.2daygeek.com (Mon 2018-10-08 06:41:31 EDT):
The system is going down for power-off at Mon 2018-10-08 06:42:31 EDT!
```
其他的登录用户都能在中断中看到如下的广播消息:
```
[daygeek@2daygeek.com ~]$
Broadcast message from root@2daygeek.com (Mon 2018-10-08 06:41:31 EDT):
The system is going down for power-off at Mon 2018-10-08 06:42:31 EDT!
```
对于使用了 `-halt` 选项:
```
# shutdown -H
Shutdown scheduled for Mon 2018-10-08 06:37:53 EDT, use 'shutdown -c' to cancel.
root@2daygeek.com#
Broadcast message from root@vps.2daygeek.com (Mon 2018-10-08 06:36:53 EDT):
The system is going down for system halt at Mon 2018-10-08 06:37:53 EDT!
```
对于使用了 `-poweroff` 选项:
```
# shutdown -P
Shutdown scheduled for Mon 2018-10-08 06:40:07 EDT, use 'shutdown -c' to cancel.
root@2daygeek.com#
Broadcast message from root@vps.2daygeek.com (Mon 2018-10-08 06:39:07 EDT):
The system is going down for power-off at Mon 2018-10-08 06:40:07 EDT!
```
可以在您的终端上敲击 `shutdown -c` 选项取消操作。
```
# shutdown -c
Broadcast message from root@vps.2daygeek.com (Mon 2018-10-08 06:39:09 EDT):
The system shutdown has been cancelled at Mon 2018-10-08 06:40:09 EDT!
```
其他的登录用户都能在中断中看到如下的广播消息:
```
[daygeek@2daygeek.com ~]$
Broadcast message from root@vps.2daygeek.com (Mon 2018-10-08 06:41:35 EDT):
The system shutdown has been cancelled at Mon 2018-10-08 06:42:35 EDT!
```
添加时间参数,如果你想在 `N` 秒之后执行关闭或重启操作。这里,您可以为所有登录用户添加自定义广播消息。例如,我们将在五分钟后重启设备。
```
# shutdown -r +5 "To activate the latest Kernel"
Shutdown scheduled for Mon 2018-10-08 07:13:16 EDT, use 'shutdown -c' to cancel.
[root@vps138235 ~]#
Broadcast message from root@vps.2daygeek.com (Mon 2018-10-08 07:08:16 EDT):
To activate the latest Kernel
The system is going down for reboot at Mon 2018-10-08 07:13:16 EDT!
```
运行下面的命令立即重启 Linux 机器。它会立即杀死所有进程并且重新启动系统。
```
# shutdown -r now
```
* `-r, --reboot` 重启设备。
### 方案 2如何通过 reboot 命令关闭和重启 Linux 系统
`reboot` 命令用于关闭和重启本地或远程设备。`reboot` 命令拥有两个实用的选项。
它能够优雅的关闭和重启设备(就好像在系统菜单中惦记重启选项一样简单)。
执行不带任何参数的 `reboot` 命令来重启 Linux 机器。
```
# reboot
```
执行带 `-p` 参数的 `reboot` 命令来关闭 Linux 机器电源。
```
# reboot -p
```
* `-p, --poweroff`:调用 `halt``poweroff` 命令,切断设备电源。
执行带 `-f` 参数的 `reboot` 命令来强制重启 Linux 设备(这类似按压机器上的电源键)。
```
# reboot -f
```
* `-f, --force`:立刻强制中断,切断电源或重启。
### 方案 3如何通过 init 命令关闭和重启 Linux 系统
`init`“initialization” 的简写)是系统启动的第一个进程。
它将会检查 `/etc/inittab` 文件并决定 linux 运行级别。同时,允许用户在 Linux 设备上执行关机或重启操作. 这里存在从 `0``6` 的七个运行等级。
**建议阅读:**
- [如何检查 Linux 上所有运行的服务][3]
执行以下 `init` 命令关闭系统。
```
# init 0
```
* `0` 停机 关闭系统。
运行下面的 `init` 命令重启设备:
```
# init 6
```
* `6`:重启 重启设备。
### 方案 4如何通过 halt 命令关闭和重启 Linux 系统
`halt` 命令用来切断电源或关闭远程 Linux 机器或本地主机。
中断所有进程并关闭 cpu。
```
# halt
```
### 方案 5如何通过 poweroff 命令关闭和重启 Linux 系统
`poweroff` 命令用来切断电源或关闭远程 Linux 机器或本地主机。 `poweroff` 很像 `halt`,但是它可以关闭设备硬件(灯和其他 PC 上的其它东西)。它会给主板发送 ACPI 指令,然后信号发送到电源,切断电源。
```
# poweroff
```
### 方案 6如何通过 systemctl 命令关闭和重启 Linux 系统
systemd 是一款适用于所有主流 Linux 发型版的全新 init 系统和系统管理器,而不是传统的 SysV init 系统。
systemd 兼容与 SysV 和 LSB 初始化脚本。它能够替代 SysV init 系统。systemd 是内核启动的第一个进程,并持有序号为 1 的进程 PID。
**建议阅读:**
- [chkservice 一款终端下系统单元管理工具][4]
它是一切进程的父进程Fedora 15 是第一个适配安装 systemd (替代了 upstart的发行版。
`systemctl` 是命令行下管理 systemd 守护进程和服务的主要工具(如 `start`、`restart`、`stop`、`enable`、`disable`、`reload` & `status`)。
systemd 使用 .service 文件而不是 SysV init 使用的 bash 脚本。 systemd 将所有守护进程归与自身的 Linux cgroups 用户组下,您可以浏览 `/cgroup/systemd` 文件查看该系统层次等级。
```
# systemctl halt
# systemctl poweroff
# systemctl reboot
# systemctl suspend
# systemctl hibernate
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/6-commands-to-shutdown-halt-poweroff-reboot-the-linux-system/
作者:[Prakash Subramanian][a]
选题:[lujun9972][b]
译者:[cyleft](https://github.com/cyleft)
校对:[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/11-methods-to-find-check-system-server-uptime-in-linux/
[2]: https://www.2daygeek.com/tuptime-a-tool-to-report-the-historical-and-statistical-running-time-of-linux-system/
[3]: https://www.2daygeek.com/how-to-check-all-running-services-in-linux/
[4]: https://www.2daygeek.com/chkservice-a-tool-for-managing-systemd-units-from-linux-terminal/

Some files were not shown because too many files have changed in this diff Show More