mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-10 22:21:11 +08:00
commit
d7905f3df5
84
Dict.md
84
Dict.md
@ -14,55 +14,55 @@
|
||||
### 2.
|
||||
#### B ####
|
||||
### 1. Backbone:骨干
|
||||
>是一个网络的一部分,其作为所有网络运输的一个基本通道,其需要非常高的带宽。一个骨干网络的服务提供者连接许多企业子网和较小服务提供者的网络。一个企业骨干网络连接许多局域网和数据中心。
|
||||
> 是一个网络的一部分,其作为所有网络运输的一个基本通道,其需要非常高的带宽。一个骨干网络的服务提供者连接许多企业子网和较小服务提供者的网络。一个企业骨干网络连接许多局域网和数据中心。
|
||||
|
||||
### 2. B channel(Bearer channel):承载信道
|
||||
>承载信道(Bearer Channel),也叫做B channel,是一个全双工DS0时间槽(64-kbps),其携带模拟语音或数字资料通过综合服务数字网(ISDN)。
|
||||
> 承载信道(Bearer Channel),也叫做B channel,是一个全双工DS0时间槽(64-kbps),其携带模拟语音或数字资料通过综合服务数字网(ISDN)。
|
||||
|
||||
### 3. Backchannel:反向通道
|
||||
>是指当其他实时在线会话在进行中时,习惯使用网络化的计算机来维持一个实时的在线会话。
|
||||
> 是指当其他实时在线会话在进行中时,习惯使用网络化的计算机来维持一个实时的在线会话。
|
||||
|
||||
### 4. Back End:后台
|
||||
>在一个计算机系统中,是指为一个前台作业提供服务的一个节点或软件程序。前台直接影响用户,后台可能与其他系统相连接,如数据库和其它系统。
|
||||
> 在一个计算机系统中,是指为一个前台作业提供服务的一个节点或软件程序。前台直接影响用户,后台可能与其他系统相连接,如数据库和其它系统。
|
||||
|
||||
### 5. Back-haul:回程线路
|
||||
>是一个通信信道,它使携带信息流到远于最终目的地的地方,然后将它送回。这样做是因为传输到更远的远程区域的代价要远比直接发送的代价低地多。
|
||||
> 是一个通信信道,它使携带信息流到远于最终目的地的地方,然后将它送回。这样做是因为传输到更远的远程区域的代价要远比直接发送的代价低地多。
|
||||
|
||||
### 6. Backoff:退避
|
||||
>是指当一个主机已经在有MAC 协议的网络中经历了一个冲突之后试图去重发之前的等待时期。这个退避时间通常是任意的来最小化相同节点再次冲突的可能性。在每次冲突后增加退避时期也能帮助预防重复碰撞,特别当这个网络负担很重时。
|
||||
> 是指当一个主机已经在有MAC 协议的网络中经历了一个冲突之后试图去重发之前的等待时期。这个退避时间通常是任意的来最小化相同节点再次冲突的可能性。在每次冲突后增加退避时期也能帮助预防重复碰撞,特别当这个网络负担很重时。
|
||||
|
||||
### 7. Backplane:附加卡
|
||||
>在许多网络中是一个物理接口模块,例如,连接在一个界面处理器或卡和在一个总线机箱内数据总线和功率分配总线之间的一个路由器或转换器。
|
||||
> 在许多网络中是一个物理接口模块,例如,连接在一个界面处理器或卡和在一个总线机箱内数据总线和功率分配总线之间的一个路由器或转换器。
|
||||
|
||||
### 8. Back Pressure:背压
|
||||
>在计算机系统中,是指网络拥塞信息逆流通过一个Internet网络。
|
||||
> 在计算机系统中,是指网络拥塞信息逆流通过一个Internet网络。
|
||||
|
||||
### 9. Balun(balanced-unbalanced):不平衡变压器
|
||||
>意味着平衡-非平衡。不平衡变压器是一个设计用来转换平衡和不平衡之间的电信号的设备。
|
||||
> 意味着平衡-非平衡。不平衡变压器是一个设计用来转换平衡和不平衡之间的电信号的设备。
|
||||
|
||||
### 10. Baseband:基带
|
||||
>是一种类型的网络技术,在那里仅仅一种载波频率被使用。在一个基带网中,信息在传送介质中以数字的形式被携带在一个单一的多元信号通道中。
|
||||
> 是一种类型的网络技术,在那里仅仅一种载波频率被使用。在一个基带网中,信息在传送介质中以数字的形式被携带在一个单一的多元信号通道中。
|
||||
|
||||
### 11. Bastion Host:防御主机
|
||||
>是在内部网络和外部网络之间的一个网关,它被设计来防御针对内部网络的攻击。这个系统在非武装区(DMZ)的公共一边,不被防火墙或过滤路由器保护,它对攻击是完全暴露的。
|
||||
> 是在内部网络和外部网络之间的一个网关,它被设计来防御针对内部网络的攻击。这个系统在非武装区(DMZ)的公共一边,不被防火墙或过滤路由器保护,它对攻击是完全暴露的。
|
||||
|
||||
### 12: Bc(Committed Burst):约定资讯讯务
|
||||
>是一个用在帧中继系统的术语,是一个帧中继交互网约定接受和传输和通过一个帧中继网络数据链路控制(DLC)和一个特殊的时帧的最大数据量(用比特表示)。
|
||||
> 是一个用在帧中继系统的术语,是一个帧中继交互网约定接受和传输和通过一个帧中继网络数据链路控制(DLC)和一个特殊的时帧的最大数据量(用比特表示)。
|
||||
|
||||
### 13. BCP(Best Current Practices):最优现行方法
|
||||
>是副系列的IETF RFCs,其被用于描述在Internet上的最优配置技术。
|
||||
> 是副系列的IETF RFCs,其被用于描述在Internet上的最优配置技术。
|
||||
|
||||
### 14. BCU(Balanced Configuration Unit):平衡配置单元
|
||||
>是一个综合的IBM解决方法,它由软件和硬件组成。BCUs是综合的和测试作为数据仓库系统的预配置功能块。
|
||||
> 是一个综合的IBM解决方法,它由软件和硬件组成。BCUs是综合的和测试作为数据仓库系统的预配置功能块。
|
||||
|
||||
### 15. BECN(Backward Explicit Congestion Notification):显式拥塞通知
|
||||
>是在帧中继报头的一个1比特域,其发信号到任何接收帧的事物(转换器和数据终端设备),拥塞就发生在帧的反面(后面)。帧中继转换器和数据终端设备可能遵照显式拥塞通知位来减慢那个方向的数据传输率。
|
||||
> 是在帧中继报头的一个1比特域,其发信号到任何接收帧的事物(转换器和数据终端设备),拥塞就发生在帧的反面(后面)。帧中继转换器和数据终端设备可能遵照显式拥塞通知位来减慢那个方向的数据传输率。
|
||||
|
||||
### 16. BER(Bit Error Rate):误码率
|
||||
>是接收到的位包含错误的比率。BER通常被表示成十足的负面力量。
|
||||
> 是接收到的位包含错误的比率。BER通常被表示成十足的负面力量。
|
||||
|
||||
### 17. BIP(Bit Interleaved Parity):位交叉奇偶校验
|
||||
>一个用在ATM中的术语,是一个通常用来检测链接错误的一种方法。一个检测位或字被嵌入到以前发生阻塞或帧的链接中。位错误在有效载荷中能够作为维护信息被删除和报告。
|
||||
> 一个用在ATM中的术语,是一个通常用来检测链接错误的一种方法。一个检测位或字被嵌入到以前发生阻塞或帧的链接中。位错误在有效载荷中能够作为维护信息被删除和报告。
|
||||
|
||||
#### C ####
|
||||
|
||||
@ -76,76 +76,88 @@
|
||||
#### H ####
|
||||
### 1. Home Directory:家目录
|
||||
#### I ####
|
||||
### 1. issue:工单
|
||||
> 有翻译做“问题”的,但是应该译作“工单”,尤其是用于 GitHub 中。
|
||||
|
||||
#### J ####
|
||||
|
||||
#### K ####
|
||||
|
||||
#### L ####
|
||||
### 1. LTS(Long Term Support):长期支持
|
||||
>该缩写词多见于操作系统发行版或者软件发行版名称中,表明该版本属于长期支持版。
|
||||
### 1. live CD:现场版 CD
|
||||
> 通常不翻译,但是如果翻译,可以译作“现场版”。
|
||||
### 2. live patch: 实时补丁/热补丁
|
||||
> 指 Linux 内核的 live patch 支持。
|
||||
|
||||
### 2. LTS(Long Term Support):长期支持
|
||||
> 该缩写词多见于操作系统发行版或者软件发行版名称中,表明该版本属于长期支持版。
|
||||
|
||||
#### M ####
|
||||
|
||||
#### N ####
|
||||
|
||||
#### O ####
|
||||
### 1. Orchestration:编排
|
||||
> 描述复杂计算机系统、中间件(middleware)和业务的自动化的安排、协调和管理(来自维基百科)。
|
||||
|
||||
#### P ####
|
||||
### 1.P-code(Pseudo-code):伪代码语言
|
||||
>一种解释型语言,执行方式介于编译型语言和解释型语言之间。和解释型语言一样,伪代码编程语言无需编译,在执行时自动转换成二进制形式。然而,和编译型语言不同的是,这种可执行的二进制文件是以伪代码的形式而不是机器语言的形式存储的。伪代码语言的例子有 Java、Python 和 REXX/Object REXX。
|
||||
### 1. P-code(Pseudo-code):伪代码语言
|
||||
> 一种解释型语言,执行方式介于编译型语言和解释型语言之间。和解释型语言一样,伪代码编程语言无需编译,在执行时自动转换成二进制形式。然而,和编译型语言不同的是,这种可执行的二进制文件是以伪代码的形式而不是机器语言的形式存储的。伪代码语言的例子有 Java、Python 和 REXX/Object REXX。
|
||||
|
||||
### 2. PAM(Pluggable Authentication Modules):可插拔认证模块
|
||||
>用于系统安全性的可替换的用户认证模块,它允许在不知道将使用何种认证方案的情况下进行编程。这允许将来用其它模块来替换某个模块,却无需重写软件。
|
||||
> 用于系统安全性的可替换的用户认证模块,它允许在不知道将使用何种认证方案的情况下进行编程。这允许将来用其它模块来替换某个模块,却无需重写软件。
|
||||
|
||||
### 3. Port/Ported/Porting:移植
|
||||
>一个过程,即获取为某个操作系统平台编写的程序,并对其进行修改使之能在另一 OS 上运行,并且具有类似的功能。
|
||||
> 一个过程,即获取为某个操作系统平台编写的程序,并对其进行修改使之能在另一 OS 上运行,并且具有类似的功能。
|
||||
|
||||
### 4. POSIX(Portable Operating System Interface for uniX):UNIX 可移植操作系统接口
|
||||
>一组编程接口标准,它们规定如何编写应用程序源代码以便应用程序可在操作系统之间移植。POSIX 基于 UNIX,它是 The Open Group 的 X/Open 规范的基础。
|
||||
> 一组编程接口标准,它们规定如何编写应用程序源代码以便应用程序可在操作系统之间移植。POSIX 基于 UNIX,它是 The Open Group 的 X/Open 规范的基础。
|
||||
|
||||
#### Q ####
|
||||
|
||||
#### R ####
|
||||
### 1. RCS(Revision Control System):修订控制系统
|
||||
>一组程序,它们控制组环境下文件的共享访问并跟踪文本文件的变化。常用于维护源代码模块的编码工作。
|
||||
> 一组程序,它们控制组环境下文件的共享访问并跟踪文本文件的变化。常用于维护源代码模块的编码工作。
|
||||
|
||||
### 2. RFS(Remote File Sharing):远程文件共享
|
||||
>一个程序,它让用户访问其它计算机上的文件,就好象文件在用户的系统上一样。
|
||||
> 一个程序,它让用户访问其它计算机上的文件,就好象文件在用户的系统上一样。
|
||||
|
||||
#### S ####
|
||||
### 1. shebang [ʃɪ'bæŋ]:释伴
|
||||
>Shebang(也称为Hashbang)是一个由井号和叹号构成的字符序列(#!),出现在文本文件的第一行的前两个字符,后跟解释器路径,如:#!/bin/sh,这通常是Linux中shell脚本的标准起始行。
|
||||
>长期以来,shebang都没有正式的中文名称。Linux中国翻译组将其翻译为:释伴,即解释伴随行的简称,同时又是shebang的音译。
|
||||
> Shebang(也称为Hashbang)是一个由井号和叹号构成的字符序列(#!),出现在文本文件的第一行的前两个字符,后跟解释器路径,如:#!/bin/sh,这通常是Linux中shell脚本的标准起始行。
|
||||
> 长期以来,shebang都没有正式的中文名称。Linux中国翻译组将其翻译为:释伴,即解释伴随行的简称,同时又是shebang的音译。
|
||||
|
||||
### 2. Spool(Simultaneous Peripheral Operation On-Line):假脱机
|
||||
>将数据发送给一个程序,该程序将该数据信息放入队列以备将来使用(例如,打印假脱机程序)
|
||||
> 将数据发送给一个程序,该程序将该数据信息放入队列以备将来使用(例如,打印假脱机程序)
|
||||
|
||||
### 2. Steganography:隐写术
|
||||
>将一段信息隐藏在另一段信息中的做法。一个示例是在数字化照片中放置不可见的数字水印。
|
||||
> 将一段信息隐藏在另一段信息中的做法。一个示例是在数字化照片中放置不可见的数字水印。
|
||||
|
||||
### 3. Swap:交换
|
||||
>暂时将数据(程序和/或数据文件)从随机存取存储器移到磁盘存储器(换出),或反方向移动(换入),以允许处理比物理内存所能容纳的更多的程序和数据。
|
||||
> 暂时将数据(程序和/或数据文件)从随机存取存储器移到磁盘存储器(换出),或反方向移动(换入),以允许处理比物理内存所能容纳的更多的程序和数据。
|
||||
|
||||
### 4. Scheduling:调度
|
||||
> 将任务分配至资源的过程,在计算机或生产处理中尤为重要(来自维基百科)。
|
||||
|
||||
#### T ####
|
||||
### 1. Time-sharing:分时
|
||||
>一种允许多个用户分享处理器的方法,它以时间为基础给每个用户分配一部分处理器资源,按照这些时间段轮流运行每个用户的进程。
|
||||
> 一种允许多个用户分享处理器的方法,它以时间为基础给每个用户分配一部分处理器资源,按照这些时间段轮流运行每个用户的进程。
|
||||
|
||||
### 2. TL;DR:长篇摘要
|
||||
>Too Long;Didn't Read的缩写词,即太长,未阅的意思。该词多见于互联网社区论坛中,用于指出该文太长,没有阅读,或者标示出一篇长文章的摘要。在论坛回复中,该缩写词也多作为灌水用。因此,Linux中国翻译组将其翻译为:长篇摘要。
|
||||
> Too Long;Didn't Read的缩写词,即太长,未阅的意思。该词多见于互联网社区论坛中,用于指出该文太长,没有阅读,或者标示出一篇长文章的摘要。在论坛回复中,该缩写词也多作为灌水用。因此,Linux中国翻译组将其翻译为:长篇摘要。
|
||||
|
||||
#### U ####
|
||||
|
||||
#### V ####
|
||||
### 1. VRML(Virtual Reality Modeling Language):虚拟现实建模语言
|
||||
>一种主要基于 Web 的语言,用于 3D 效果(如构建遍历)。
|
||||
> 一种主要基于 Web 的语言,用于 3D 效果(如构建遍历)。
|
||||
|
||||
#### W ####
|
||||
### 1. Wrapper:封装器
|
||||
>用于启动另一个程序的程序。
|
||||
> 用于启动另一个程序的程序。
|
||||
|
||||
#### X ####
|
||||
|
||||
#### Y ####
|
||||
|
||||
#### Z ####
|
||||
#### Z ####
|
||||
|
@ -0,0 +1,126 @@
|
||||
Adobe 软件的最佳 Linux 替代品
|
||||
============================================================
|
||||
|
||||
![](https://www.maketecheasier.com/assets/uploads/2016/09/adobe-alternative-linux-featured.jpg "Best Linux Adobe Alternatives You Need to Knows")
|
||||
|
||||
你是一名正在寻找 Adobe 的替代品的 Linux 用户吗?那你不是一个人。如果你是一个狂热的平面设计师,那么你可能很擅长避开昂贵的 Adobe 产品。不过,对于 Adobe 来说,Linux 用户通常是其支持最不利的。因此,Adobe 的替代品是必须的 —— 但是最好的选择是什么?
|
||||
|
||||
这最终要看具体的 Adobe 程序和你希望完成的事情。幸运的是,由于需求是所有发明之母,有人响应了这些号召。其结果是出现了一系列高效的 Adobe 替代品。
|
||||
|
||||
### Evince (Adobe Acrobat Reader)
|
||||
|
||||
![Evince_AdobeReaderSubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Evince_AdobeReaderSubstitute.jpg "Evince_AdobeReaderSubstitute")
|
||||
|
||||
就像 Adobe Acrobat Reader 一样,[Evince][6] 是一个“支持多种文档格式的文档查看器”。例如,用户可以使用 Evince 作为 PDF 查看器。它还支持各种漫画书格式(cbr、cbz、cb7 和 cbt)。你可以在 Evince 网站上找到[支持格式的完整列表][7]。
|
||||
|
||||
对于 Evince ,Linux 用户不用高估,也不用贬低,它就是个标准的查看器。你可以在需要时前往官方网站进行更新。
|
||||
|
||||
### Pixlr (Adobe Photoshop)
|
||||
|
||||
![Pixlr_Photoshopsubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Pixlr_Photoshopsubstitute.jpg "Pixlr_Photoshopsubstitute")
|
||||
|
||||
关于 [Pixlr][8] 的很棒的一点是这个 Adobe 替代品的各种工具可以在线获得。如果你有一个互联网连接,那么你就有一个强大的图像编辑工作区。
|
||||
|
||||
[Pixlr Editor][9] 是 Photoshop 的一个功能强大的替代品,你可以使用图层和相关效果。它还有一些漂亮的绘图和颜色编辑工具。[Pixlr Express][10] 没有这么多功能,因为它主要用于图像增强、调整颜色和清晰度,并增加一些 Instagram 适用的效果!
|
||||
|
||||
你可以通过 Pixlr 完成的任务简直不可置信,而且完全免费的。
|
||||
|
||||
### Inkscape (Adobe Illustrator)
|
||||
|
||||
![Inkscape_Illustratorsubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Inkscape_Illustratorsubstitute.jpg "Inkscape_Illustratorsubstitute")
|
||||
|
||||
[Inkscape][11]是另一个值得推荐的免费 Adobe 替代品。它主要作为一个“专业的矢量图形编辑器”。除了 Illustrator,Inkscape 也与 Corel Draw、Freehand 和 Xara X 的功能差不多。
|
||||
|
||||
它的矢量设计工具可用于制作 logo 和“高可伸缩性”艺术品。Inkscape 包含绘图、形状和文本工具。图层工具允许你锁定、分组或隐藏单个图层。
|
||||
|
||||
### Pinegrow Web Editor (Adobe Dreamweaver)
|
||||
|
||||
![Pinegrow_Dreamweaversubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Pinegrow_Dreamweaversubstitute-400x204.jpg "Pinegrow_Dreamweaversubstitute")
|
||||
|
||||
[Pinegrow Web Editor][12] 是 Dreamweaver 在 Linux 上的绝佳替代品。该程序可让你在桌面上直接制作 HTML 网站。
|
||||
|
||||
不仅是使用代码创建(而且需要稍后预览),Pinegrow 可以提供详细的可视化编辑体验。你可以直接查看和测试你的 HTML 项目,实时了解链接是否正常工作,或者图片是否在它该在的地方。Pinegrow 还附带了 WordPress 主题构建器。
|
||||
|
||||
免费试用 30 天。如果你喜欢,你可以一次性支付 $49 购买。
|
||||
|
||||
### Scribus (Adobe InDesign)
|
||||
|
||||
![Scribus_InDesignsubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Scribus_InDesignsubstitute.jpg "Scribus_InDesignsubstitute")
|
||||
|
||||
[Scribus][13] 可能是最接近 Adobe InDesign 的替代品。根据开发者的说法,你应该[认真考虑使用][14] Scribus,因为它是可靠和免费的。
|
||||
|
||||
实际上,Scribus 不仅仅是一个出色的桌面出版工具,也是一个很好的自出版工具。当你可以自己做高质量的杂志和书籍时,为什么要依靠昂贵的商业软件来创建?Scribus 目前允许设计师使用一个 200 色的调色板,下一个稳定版中[承诺将会加倍颜色数][15]。
|
||||
|
||||
### digiKam (Adobe Lightroom)
|
||||
|
||||
![digiKam_Lightroomsubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/digiKam_Lightroomsubstitute-400x213.jpg "digiKam_Lightroomsubstitute")
|
||||
|
||||
[digiKam][16] 也许是目前 Linux 用户最好的 Lightroom 替代品。功能包括导入照片、整理图片集、图像增强、创建幻灯片等功能。
|
||||
|
||||
它的时尚设计和先进的功能是真正用心之作。实际上,digiKam 背后的人是摄影师们。不仅如此,他们希望在 Linux 中完成在 Lightroom 能做的任何工作。
|
||||
|
||||
### Webflow (Adobe Muse)
|
||||
|
||||
![Webflow_Museubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Webflow_Museubstitute-400x158.jpg "Webflow_Museubstitute")
|
||||
|
||||
[Webflow][17] 是另一个可以证明你无需下载软件而可以完成很多事的网站。这是一个非常方便的 Adobe Muse 替代品,Webflow 是创建高响应式网站设计的理想选择。
|
||||
|
||||
Webflow 的最好的一方面是你不需要自己编写代码。你只需拖放图像并写入文本。Webflow 为你做了所有杂事。你可以从头开始构建网站,也可以使用各种模板。虽然是免费的,但是其高级版本还提供了额外的功能,如能够轻松地导出 HTML 和 CSS 以在其他地方使用。
|
||||
|
||||
### Tupi (Adobe Animate)
|
||||
|
||||
![Tupi_Animatesubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Tupi_Animatesubstitute.jpg "Tupi_Animatesubstitute")
|
||||
|
||||
[Tupi][18] 是 Adobe Animate 的替代品,或者也可以用于那些[不太热衷于 Flash 的人][19]。当然,Tupi 的作者说这并不是与 Flash 竞争。然而,其使用 HTML5 的能力使其成为了理想的替代品。
|
||||
|
||||
在 PC 或平板电脑上绘制 2D 动画。不确定如何开始?使用网站的 [YouTube 教程][20]了解如何制作剪贴画动画以及更多。
|
||||
|
||||
### Black Magic Fusion (Adobe After Effects)
|
||||
|
||||
![Fusion_AFterEffectssubstitute](https://www.maketecheasier.com/assets/uploads/2016/08/Fusion_AFterEffectssubstitute.jpg "Fusion_AFterEffectssubstitute")
|
||||
|
||||
[Black Magic Fusion][21] 注定是 Adobe After Effects 的替代者。这个视觉效果软件历经了大约 25 年的开发!Fusion 通常用于在好莱坞电影和电视节目中制造令人印象深刻的效果 —— 这靠的是其丰富而时尚的功能。
|
||||
|
||||
Fusion 通过使用节点,即那些“代表效果、过滤器和其他处理的小图标”工作。将这些节点连接在一起,创建一系列复杂的视觉效果。该程序包括许多功能,如图片修饰、对象跟踪和令人兴奋的 3D 效果。
|
||||
|
||||
你可以选择免费版或者 $995 的 Fusion Studio。为了帮助你决定,[你可以比较][22]免费和高级版的 Fusion 功能。
|
||||
|
||||
### 总结
|
||||
|
||||
如你所见,这些远不止于是 Adobe 替代品。由于开源的缘故,显著提升的替代品的不断地发布。我们很快就会看到一个仅为 Linux 用户创建的完整套件。在此之前,你可以随意选择这些替代品。
|
||||
|
||||
知道这里没有提到的其它有用的 Adobe 替代品吗?在下面的评论区分享软件建议。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.maketecheasier.com/adobe-alternatives-for-linux/
|
||||
|
||||
作者:[Toni Matthews-El][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.maketecheasier.com/author/ttmatthe/
|
||||
[1]:https://www.maketecheasier.com/author/ttmatthe/
|
||||
[2]:https://www.maketecheasier.com/adobe-alternatives-for-linux/#comments
|
||||
[3]:https://www.maketecheasier.com/category/linux-tips/
|
||||
[4]:https://support.google.com/adsense/troubleshooter/1631343
|
||||
[5]:https://support.google.com/adsense/troubleshooter/1631343
|
||||
[6]:https://wiki.gnome.org/Apps/Evince
|
||||
[7]:https://wiki.gnome.org/Apps/Evince/SupportedDocumentFormats
|
||||
[8]:https://pixlr.com/
|
||||
[9]:https://pixlr.com/editor/
|
||||
[10]:https://pixlr.com/express/
|
||||
[11]:https://inkscape.org/en/
|
||||
[12]:http://pinegrow.com/
|
||||
[13]:https://www.scribus.net/
|
||||
[14]:https://www.scribus.net/why-on-earth-should-i-use-scribus-2/
|
||||
[15]:https://www.scribus.net/because-color-matters/
|
||||
[16]:http://digikam.org/
|
||||
[17]:https://webflow.com/
|
||||
[18]:http://www.maefloresta.com/portal/
|
||||
[19]:https://www.maketecheasier.com/sites-moving-away-flash/
|
||||
[20]:https://www.youtube.com/user/maefloresta
|
||||
[21]:https://www.blackmagicdesign.com/
|
||||
[22]:https://www.blackmagicdesign.com/products/fusion/compare
|
@ -0,0 +1,777 @@
|
||||
详解 Ubuntu snap 包的制作过程
|
||||
============================================================
|
||||
|
||||
> 如果你看过译者以前翻译的 snappy 文章,不知有没有感觉相关主题都是浅尝辄止,讲得不够透彻,看得也不太过瘾?如果有的话,相信这篇详细讲解如何从零开始制作一个 snap 包的文章应该不会让你失望。
|
||||
|
||||
在这篇文章中,我们将看到如何为名为 [timg][1] 的实用程序制作对应的 snap 包。如果这是你第一次听说 snap 安装包,你可以先看看 [如何创建你的第一个 snap 包][2]。
|
||||
|
||||
今天我们将学习以下有关使用 snapcraft 制作 snap 包的内容:
|
||||
|
||||
* [timg][3] 源码中的 Makefile 文件是手工编写,我们需要修改一些 [make 插件参数][4]。
|
||||
* 这个程序是用 C++ 语言写的,依赖几个额外的库文件。我们需要把相关的代码添加到 snap 包中。
|
||||
* [严格限制还是传统限制][38]?我们将会讨论如何在它们之间进行选择。
|
||||
|
||||
首先,我们了解下 [timg][5] 有什么用?
|
||||
|
||||
### 背景
|
||||
|
||||
Linux 终端模拟器已经变得非常炫酷,并且还能显示颜色!
|
||||
|
||||
![1.png-19.9kB][6]
|
||||
|
||||
除了标准的颜色,大多数终端模拟器(如上图显示的 GNOME 终端)都支持真彩色(1600 万种颜色)。
|
||||
|
||||
![图片.png-61.9kB][7]
|
||||
|
||||
是的!终端模拟器已经支持真彩色了!从这个页面“ [多个终端和终端应用程序已经支持真彩色(1600 万种颜色)][8]” 可以获取 AWK 代码自己进行测试。你可以看到在代码中使用了一些 [转义序列][9] 来指定 RGB 的值(256 * 256 * 256 ~= 1600 万种颜色)。
|
||||
|
||||
### timg 是什么?
|
||||
|
||||
好了,言归正传,[timg][10] 有什么用?它能将输入的图片重新调整为终端窗口字符所能显示范围的大小(比如:80 x 25),然后在任何分辨率的终端窗口用彩色字符显示图像。
|
||||
|
||||
![图片.png-37.3kB][11]
|
||||
|
||||
这幅图用彩色块字符显示了 [Ubuntu 的 logo][12],原图是一个 PNG 格式的文件。
|
||||
|
||||
![图片.png-165kB][13]
|
||||
|
||||
这是 [@Doug8888 拍摄的花][14]。
|
||||
|
||||
如果你通过远程连接服务器来管理自己的业务,并想要查看图像文件,那么 [timg][15] 将会特别有用。
|
||||
|
||||
除了静态图片,[timg][16] 同样也可以显示 gif 动图。
|
||||
|
||||
那么让我们开始 snap 之旅吧!
|
||||
|
||||
### 熟悉 timg 的源码
|
||||
|
||||
[timg][17] 的源码可以在 [https://github.com/hzeller/timg][18] 找到。让我们试着手动编译它,以了解它有什么需求。
|
||||
|
||||
![图片.png-128.4kB][19]
|
||||
|
||||
`Makefile` 在 `src/` 子文件夹中而不是项目的根文件夹中。在 github 页面上,他们说需要安装两个开发包(GraphicsMagic++ 和 WebP),然后使用 `make` 就能生成可执行文件。在截图中可以看到我已经将它们安装好了(在我读完相关的 Readme.md 文件后)。
|
||||
|
||||
因此,在编写 `snapcraft.yaml` 文件时已经有了四条腹稿:
|
||||
|
||||
1. `Makefile` 在 `src/` 子文件夹中而不是项目的根文件夹中。
|
||||
2. 这个程序编译时需要两个开发库。
|
||||
3. 为了让 timg 以 snap 包形式运行,我们需要将这两个库捆绑在 snap 包中(或者静态链接它们)。
|
||||
4. [timg][20] 是用 C++ 编写的,所以需要安装 g++。在编译之前,让我们通过 `snapcraft.yaml` 文件来检查 `build-essential` 元包是否已经安装。
|
||||
|
||||
### 从 snapcraft 开始
|
||||
|
||||
让我们新建一个名为 `timg-snap/` 的文件夹,并在其中运行 `snapcraft init` 这条命令来创建 `snapcraft.yaml` 工作的框架。
|
||||
|
||||
```
|
||||
ubuntu@snaps:~$ mkdir timg-snap
|
||||
ubuntu@snaps:~$ cd timg-snap/
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft init
|
||||
Created snap/snapcraft.yaml.
|
||||
Edit the file to your liking or run `snapcraft` to get started
|
||||
ubuntu@snaps:~/timg-snap$ cat snap/snapcraft.yaml
|
||||
name: my-snap-name # you probably want to 'snapcraft register <name>'
|
||||
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
|
||||
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
|
||||
description: |
|
||||
This is my-snap's description. You have a paragraph or two to tell the most important story about your snap. Keep it under 100 words though, we live in tweetspace and your description wants to look good in the snap store.
|
||||
|
||||
grade: devel # must be 'stable' to release into candidate/stable channels
|
||||
confinement: devmode # use 'strict' once you have the right plugs and slots
|
||||
|
||||
parts:
|
||||
my-part:
|
||||
# See 'snapcraft plugins'
|
||||
plugin: nil
|
||||
```
|
||||
|
||||
### 填充元数据
|
||||
|
||||
`snapcraft.yaml` 配置文件的上半部分是元数据。我们需要一个一个把它们填满,这算是比较容易的部分。元数据由以下字段组成:
|
||||
|
||||
1. `name` (名字)—— snap 包的名字,它将公开在 Ubuntu 商店中。
|
||||
2. `version` (版本)—— snap 包的版本号。可以是源代码存储库中一个适当的分支或者标记,如果没有分支或标记的话,也可以是当前日期。
|
||||
3. `summary` (摘要)—— 不超过 80 个字符的简短描述。
|
||||
4. `description` (描述)—— 长一点的描述, 100 个字以下。
|
||||
5. `grade` (等级)—— `stable` (稳定)或者 `devel` (开发)。因为我们想要在 Ubuntu 商店的稳定通道中发布这个 snap 包,所以在 snap 包能正常工作后,就把它设置成 `stable`。
|
||||
6. `confinement` (限制)—— 我们首先设置为 `devmode` (开发模式),这样系统将不会以任何方式限制 snap 包。一旦它在 `devmode`下能正常工作,我们再考虑选择 `strict` (严格)还是 `classic` (传统)限制。
|
||||
|
||||
我们将使用 `timg` 这个名字:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft register timg
|
||||
Registering timg.
|
||||
You already own the name 'timg'.
|
||||
```
|
||||
|
||||
是的,这个名字我已经注册了 :-)。
|
||||
|
||||
接下来,我们应该选择哪个版本的 timg?
|
||||
|
||||
![图片.png-72.7kB][21]
|
||||
|
||||
当在仓库中寻找分支或标记时,我们会发现有一个 v0.9.5 标签,其中有 2016 年 6 月 27 日最新提交的代码。
|
||||
|
||||
![图片.png-71.4kB][22]
|
||||
|
||||
然而主分支(`master`)中有两个看起来很重要的提交。因此我们使用主分支而不用 `v0.9.5` 标签的那个。我们使用今天的日期—— `20170226` 做为版本号。
|
||||
|
||||
我们从仓库中搜集了摘要和描述。其中摘要的内容为 `A terminal image viewer`,描述的内容为 `A viewer that uses 24-Bit color capabilities and unicode character blocks to display images in the terminal`。
|
||||
|
||||
最后,将 `grade` (等级)设置为 `stable` (稳定),将 `confinement` 限制设置为 `devmode` (开发模式)(一直到 snap 包真正起作用)。
|
||||
|
||||
这是更新后的 `snapcraft.yaml`,带有所有的元数据:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ cat snap/snapcraft.yaml
|
||||
name: timg
|
||||
version: '20170226'
|
||||
summary: A terminal image viewer
|
||||
description: |
|
||||
A viewer that uses 24-Bit color capabilities and unicode character blocks to display images in the terminal.
|
||||
|
||||
grade: stable
|
||||
confinement: devmode
|
||||
|
||||
parts:
|
||||
my-part:
|
||||
# See 'snapcraft plugins'
|
||||
plugin: nil
|
||||
```
|
||||
|
||||
### 弄清楚 `parts:` 是什么
|
||||
|
||||
现在我们需要将上面已经存在的 `parts:` 部分替换成真实的 `parts:`。
|
||||
|
||||
![timg-git-url.png-8kB][23]
|
||||
|
||||
*Git 仓库的 URL。*
|
||||
|
||||
![图片.png-28.7kB][24]
|
||||
|
||||
*存在 Makefile,因此我们需要 make 插件。*
|
||||
|
||||
我们已经知道 git 仓库的 URL 链接,并且 timg 源码中已有了 `Makefile` 文件。至于 [snapcraft make 插件][25] 的 Makefile 命令,正如文档所言,这个插件总是会运行 `make` 后再运行 `make install`。为了确认 `make` 插件的用法,我查看了 [snapcraft 可用插件列表][26]。
|
||||
|
||||
因此,我们将最初的配置:
|
||||
|
||||
```
|
||||
parts:
|
||||
my-part:
|
||||
# See 'snapcraft plugins'
|
||||
plugin: nil
|
||||
```
|
||||
|
||||
修改为:
|
||||
|
||||
```
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
plugin: make
|
||||
```
|
||||
|
||||
这是当前 `snapcraft.yaml` 文件的内容:
|
||||
|
||||
```
|
||||
name: timg
|
||||
version: '20170226'
|
||||
summary: A terminal image viewer
|
||||
description: |
|
||||
A viewer that uses 24-Bit color capabilities and unicode character blocks
|
||||
to display images in the terminal.
|
||||
|
||||
grade: stable
|
||||
confinement: devmode
|
||||
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
plugin: make
|
||||
```
|
||||
|
||||
让我们运行下 `snapcraft prime` 命令看看会发生什么:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft prime
|
||||
Preparing to pull timg
|
||||
Pulling timg
|
||||
Cloning into '/home/ubuntu/timg-snap/parts/timg/src'...
|
||||
remote: Counting objects: 144, done.
|
||||
remote: Total 144 (delta 0), reused 0 (delta 0), pack-reused 144
|
||||
Receiving objects: 100% (144/144), 116.00 KiB | 0 bytes/s, done.
|
||||
Resolving deltas: 100% (89/89), done.
|
||||
Checking connectivity... done.
|
||||
Preparing to build timg
|
||||
Building timg
|
||||
make -j4
|
||||
make: *** No targets specified and no makefile found. Stop.
|
||||
Command '['/bin/sh', '/tmp/tmpem97fh9d', 'make', '-j4']' returned non-zero exit status 2
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
我们可以看到 `snapcraft` 无法在源代码中找到 `Makefile` 文件,正如我们之前所暗示的,`Makefile` 位于 `src/` 子文件夹中。那么,我们可以让 `snapcraft` 使用 `src/` 文件夹中的 `Makefile` 文件吗?
|
||||
|
||||
每个 snapcraft 插件都有自己的选项,并且有一些通用选项是所有插件共享的。在本例中,我们希望研究那些[与源代码相关的 snapcraft 选项][27]。我们开始吧:
|
||||
|
||||
**source-subdir:path**
|
||||
|
||||
snapcraft 会<ruby>检出<rt>checkout</rt></ruby> `source` 关键字所引用的仓库或者解压归档文件到 `parts/<part-name>/src/` 中,但是它只会将特定的子目录复制到 `parts/<part-name>/build/` 中。
|
||||
|
||||
我们已经有了适当的选项,下面更新下 `parts`:
|
||||
|
||||
```
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
```
|
||||
|
||||
然后再次运行 `snapcraft prime`:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft prime
|
||||
The 'pull' step of 'timg' is out of date:
|
||||
|
||||
The 'source-subdir' part property appears to have changed.
|
||||
|
||||
Please clean that part's 'pull' step in order to continue
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft clean
|
||||
Cleaning up priming area
|
||||
Cleaning up staging area
|
||||
Cleaning up parts directory
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft prime
|
||||
Skipping pull timg (already ran)
|
||||
Preparing to build timg
|
||||
Building timg
|
||||
make -j4
|
||||
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
|
||||
g++ -Wall -O3 -fPIC -c -o terminal-canvas.o terminal-canvas.cc
|
||||
/bin/sh: 1: GraphicsMagick++-config: not found
|
||||
timg.cc:33:22: fatal error: Magick++.h: No such file or directory
|
||||
compilation terminated.
|
||||
Makefile:10: recipe for target 'timg.o' failed
|
||||
make: *** [timg.o] Error 1
|
||||
make: *** Waiting for unfinished jobs....
|
||||
Command '['/bin/sh', '/tmp/tmpeeyxj5kw', 'make', '-j4']' returned non-zero exit status 2
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
从错误信息我们可以得知 snapcraft 找不到 GraphicsMagick++ 这个开发库文件。根据 [snapcraft 常见关键字][29] 可知,我们需要在 `snapcraft.yaml` 中指定这个库文件,这样 snapcraft 才能安装它。
|
||||
|
||||
**build-packages:[deb, deb, deb…]**
|
||||
|
||||
列出构建 part 前需要在主机中安装的 Ubuntu 包。这些包通常不会进入最终的 snap 包中,除非它们含有 snap 包中二进制文件直接依赖的库文件(在这种情况下,可以通过 `ldd` 发现它们),或者在 `stage-package` 中显式地指定了它们。
|
||||
|
||||
让我们寻找下这个开发包的名字:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ apt-cache search graphicsmagick++ | grep dev
|
||||
graphicsmagick-libmagick-dev-compat/xenial 1.3.23-1build1 all
|
||||
libgraphicsmagick++1-dev/xenial 1.3.23-1build1 amd64
|
||||
format-independent image processing - C++ development files
|
||||
libgraphicsmagick1-dev/xenial 1.3.23-1build1 amd64
|
||||
format-independent image processing - C development files
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
可以看到包名为 `libgraphicsmagick++1-dev`,下面是更新后的 `parts`:
|
||||
|
||||
```
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
build-packages:
|
||||
- libgraphicsmagick++1-dev
|
||||
```
|
||||
|
||||
再次运行 `snapcraft`:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft
|
||||
Installing build dependencies: libgraphicsmagick++1-dev
|
||||
[...]
|
||||
The following NEW packages will be installed:
|
||||
libgraphicsmagick++-q16-12 libgraphicsmagick++1-dev libgraphicsmagick-q16-3
|
||||
libgraphicsmagick1-dev libwebp5
|
||||
[...]
|
||||
Building timg
|
||||
make -j4
|
||||
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
|
||||
g++ -Wall -O3 -fPIC -c -o terminal-canvas.o terminal-canvas.cc
|
||||
g++ -o timg timg.o terminal-canvas.o `GraphicsMagick++-config --ldflags --libs`
|
||||
/usr/bin/ld: cannot find -lwebp
|
||||
collect2: error: ld returned 1 exit status
|
||||
Makefile:7: recipe for target 'timg' failed
|
||||
make: *** [timg] Error 1
|
||||
Command '['/bin/sh', '/tmp/tmptma45jzl', 'make', '-j4']' returned non-zero exit status 2
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
虽然只指定了开发库 `libgraphicsmagick+1-dev`,但 Ubuntu 还安装了一些代码库,包括 `libgraphicsmagick ++-q16-12`,以及动态代码库 `libwebp`。
|
||||
|
||||
这里仍然有一个错误,这个是因为缺少开发版本的 `webp` 库(一个静态库)。我们可以通过下面的命令找到它:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ apt-cache search libwebp | grep dev
|
||||
libwebp-dev - Lossy compression of digital photographic images.
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
上面安装的 `libwebp5` 包只提供了一个动态库(.so)。通过 `libwebp-dev` 包,我们可以得到相应的静态库(.a)。好了,让我们更新下 `parts:` 部分:
|
||||
|
||||
```
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
build-packages:
|
||||
- libgraphicsmagick++1-dev
|
||||
- libwebp-dev
|
||||
```
|
||||
|
||||
下面是更新后的 `snapcraft.yaml` 文件的内容:
|
||||
|
||||
```
|
||||
name: timg
|
||||
version: '20170226'
|
||||
summary: A terminal image viewer
|
||||
description: |
|
||||
A viewer that uses 24-Bit color capabilities and unicode character blocks
|
||||
to display images in the terminal.
|
||||
|
||||
grade: stable
|
||||
confinement: devmode
|
||||
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
build-packages:
|
||||
- libgraphicsmagick++1-dev
|
||||
- libwebp-dev
|
||||
```
|
||||
|
||||
让我们运行下 `snapcraft prime`:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft prime
|
||||
Skipping pull timg (already ran)
|
||||
Preparing to build timg
|
||||
Building timg
|
||||
make -j4
|
||||
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
|
||||
g++ -Wall -O3 -fPIC -c -o terminal-canvas.o terminal-canvas.cc
|
||||
g++ -o timg timg.o terminal-canvas.o `GraphicsMagick++-config --ldflags --libs`
|
||||
make install DESTDIR=/home/ubuntu/timg-snap/parts/timg/install
|
||||
install timg /usr/local/bin
|
||||
install: cannot create regular file '/usr/local/bin/timg': Permission denied
|
||||
Makefile:13: recipe for target 'install' failed
|
||||
make: *** [install] Error 1
|
||||
Command '['/bin/sh', '/tmp/tmptq_s1itc', 'make', 'install', 'DESTDIR=/home/ubuntu/timg-snap/parts/timg/install']' returned non-zero exit status 2
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
我们遇到了一个新问题。由于 `Makefile` 文件是手工编写的,不符合 [snapcraft make 插件][30] 的参数设置,所以不能正确安装到 `prime/` 文件夹中。`Makefile` 会尝试安装到 `usr/local/bin` 中。
|
||||
|
||||
我们需要告诉 [snapcraft make 插件][31] 不要运行 `make install`,而是找到 `timg` 可执行文件然后把它放到 `prime/` 文件夹中。根据文档的描述:
|
||||
|
||||
```
|
||||
- artifacts:
|
||||
(列表)
|
||||
将 make 生成的指定文件复制或者链接到 snap 包安装目录。如果使用,则 `make install` 这步操作将被忽略。
|
||||
```
|
||||
|
||||
所以,我们需要将一些东西放到 `artifacts:` 中。但是具体是哪些东西?
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap/parts/timg$ ls build/src/
|
||||
Makefile terminal-canvas.h timg* timg.o
|
||||
terminal-canvas.cc terminal-canvas.o timg.cc
|
||||
ubuntu@snaps:~/timg-snap/parts/timg$
|
||||
```
|
||||
|
||||
在 `build/` 子目录中,我们可以找到 `make` 的输出结果。由于我们设置了 `source-subdir:` 为 `src`,所以 `artifacts:` 的基目录为 `build/src`。在这里我们可以找到可执行文件 `timg`,我们需要将它设置为 `artifacts:` 的一个参数。通过 `artifacts:`,我们可以把 `make` 输出的某些文件复制到 snap 包的安装目录(在 `prime/` 中)。
|
||||
|
||||
下面是更新后 `snapcraft.yaml` 文件 `parts:` 部分的内容:
|
||||
|
||||
```
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
build-packages:
|
||||
- libgraphicsmagick++1-dev
|
||||
- libwebp-dev
|
||||
artifacts: [timg]
|
||||
```
|
||||
|
||||
让我们运行 `snapcraft prime`:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft prime
|
||||
Preparing to pull timg
|
||||
Pulling timg
|
||||
Cloning into '/home/ubuntu/timg-snap/parts/timg/src'...
|
||||
remote: Counting objects: 144, done.
|
||||
remote: Total 144 (delta 0), reused 0 (delta 0), pack-reused 144
|
||||
Receiving objects: 100% (144/144), 116.00 KiB | 207.00 KiB/s, done.
|
||||
Resolving deltas: 100% (89/89), done.
|
||||
Checking connectivity... done.
|
||||
Preparing to build timg
|
||||
Building timg
|
||||
make -j4
|
||||
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
|
||||
g++ -Wall -O3 -fPIC -c -o terminal-canvas.o terminal-canvas.cc
|
||||
g++ -o timg timg.o terminal-canvas.o `GraphicsMagick++-config --ldflags --libs`
|
||||
Staging timg
|
||||
Priming timg
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
我们还将继续迭代。
|
||||
|
||||
### 导出命令
|
||||
|
||||
到目前为止,snapcraft 生成了可执行文件,但没有导出给用户使用的命令。接下来我们需要通过 `apps:` 导出一个命令。
|
||||
|
||||
首先我们需要知道命令在 `prime/` 的哪个子文件夹中:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ ls prime/
|
||||
meta/ snap/ timg* usr/
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
它在 `prime/` 子文件夹的根目录中。现在,我们已经准备好要在 `snapcaft.yaml` 中增加 `apps:` 的内容:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ cat snap/snapcraft.yaml
|
||||
name: timg
|
||||
version: '20170226'
|
||||
summary: A terminal image viewer
|
||||
description: |
|
||||
A viewer that uses 24-Bit color capabilities and unicode character blocks
|
||||
to display images in the terminal.
|
||||
|
||||
grade: stable
|
||||
confinement: devmode
|
||||
|
||||
apps:
|
||||
timg:
|
||||
command: timg
|
||||
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
build-packages:
|
||||
- libgraphicsmagick++1-dev
|
||||
- libwebp-dev
|
||||
artifacts: [timg]
|
||||
```
|
||||
|
||||
让我们再次运行 `snapcraft prime`,然后测试下生成的 snap 包:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft prime
|
||||
Skipping pull timg (already ran)
|
||||
Skipping build timg (already ran)
|
||||
Skipping stage timg (already ran)
|
||||
Skipping prime timg (already ran)
|
||||
ubuntu@snaps:~/timg-snap$ snap try --devmode prime/
|
||||
timg 20170226 mounted from /home/ubuntu/timg-snap/prime
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
![图片.png-42.3kB][32]
|
||||
|
||||
*图片来源: https://www.flickr.com/photos/mustangjoe/6091603784/*
|
||||
|
||||
我们可以通过 `snap try --devmode prime/ ` 启用该 snap 包然后测试 `timg` 命令。这是一种高效的测试方法,可以避免生成 .snap 文件,并且无需安装和卸载它们,因为 `snap try prime/` 直接使用了 `prime/` 文件夹中的内容。
|
||||
|
||||
### 限制 snap
|
||||
|
||||
到目前为止,snap 包一直是在不受限制的开发模式下运行的。让我们看看如何限制它的运行:
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snap list
|
||||
Name Version Rev Developer Notes
|
||||
core 16-2 1337 canonical -
|
||||
timg 20170226 x1 devmode,try
|
||||
ubuntu@snaps:~/timg-snap$ snap try --jailmode prime
|
||||
timg 20170226 mounted from /home/ubuntu/timg-snap/prime
|
||||
ubuntu@snaps:~/timg-snap$ snap list
|
||||
Name Version Rev Developer Notes
|
||||
core 16-2 1337 canonical -
|
||||
timg 20170226 x2 jailmode,try
|
||||
ubuntu@snaps:~/timg-snap$ timg pexels-photo-149813.jpeg
|
||||
Trouble loading pexels-photo-149813.jpeg (Magick: Unable to open file (pexels-photo-149813.jpeg) reported by magick/blob.c:2828 (OpenBlob))
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
通过这种方式,我们可以无需修改 `snapcraft.yaml` 文件就从开发模式(`devmode`)切换到限制模式(`jailmode`)(`confinement: strict`)。正如预期的那样,`timg` 无法读取图像,因为我们没有开放访问文件系统的权限。
|
||||
|
||||
现在,我们需要作出决定。使用限制模式,我们可以很容易授予某个命令访问用户 `$HOME` 目录中文件的权限,但是只能访问那里。如果图像文件位于其它地方,我们总是需要复制到 `$HOME` 目录并在 `$HOME` 的副本上运行 timg。如果我们觉得可行,那我们可以设置 `snapcraf.yaml` 为:
|
||||
|
||||
```
|
||||
name: timg
|
||||
version: '20170226'
|
||||
summary: A terminal image viewer
|
||||
description: |
|
||||
A viewer that uses 24-Bit color capabilities and unicode character blocks
|
||||
to display images in the terminal.
|
||||
|
||||
grade: stable
|
||||
confinement: strict
|
||||
|
||||
apps:
|
||||
timg:
|
||||
command: timg
|
||||
plugs: [home]
|
||||
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
build-packages:
|
||||
- libgraphicsmagick++1-dev
|
||||
- libwebp-dev
|
||||
artifacts: [timg]
|
||||
```
|
||||
|
||||
另一方面,如果希望 timg snap 包能访问整个文件系统,我们可以设置传统限制来实现。对应的 `snapcraft.yaml` 内容如下:
|
||||
|
||||
```
|
||||
name: timg
|
||||
version: '20170226'
|
||||
summary: A terminal image viewer
|
||||
description: |
|
||||
A viewer that uses 24-Bit color capabilities and unicode character blocks
|
||||
to display images in the terminal.
|
||||
|
||||
grade: stable
|
||||
confinement: classic
|
||||
|
||||
apps:
|
||||
timg:
|
||||
command: timg
|
||||
|
||||
parts:
|
||||
timg:
|
||||
source: https://github.com/hzeller/timg.git
|
||||
source-subdir: src
|
||||
plugin: make
|
||||
build-packages:
|
||||
- libgraphicsmagick++1-dev
|
||||
- libwebp-dev
|
||||
artifacts: [timg]
|
||||
```
|
||||
|
||||
接下来我们将选择严格(`strict`)约束选项。因此,图像应该只能放在 $HOME 中。
|
||||
|
||||
### 打包和测试
|
||||
|
||||
让我们打包这个 snap,也就是制作 .snap 文件,然后在新安装的 Ubuntu 系统上对它进行测试。
|
||||
|
||||
```
|
||||
ubuntu@snaps:~/timg-snap$ snapcraft
|
||||
Skipping pull timg (already ran)
|
||||
Skipping build timg (already ran)
|
||||
Skipping stage timg (already ran)
|
||||
Skipping prime timg (already ran)
|
||||
Snapping 'timg' \
|
||||
Snapped timg_20170226_amd64.snap
|
||||
ubuntu@snaps:~/timg-snap$
|
||||
```
|
||||
|
||||
我们如何在几秒钟内得到一个全新安装的 Ubuntu 系统来对 snap 包进行测试?
|
||||
|
||||
请查看 [尝试在 Ubuntu 上使用 LXD 容器][33],并在你的系统上设置 LXD。然后回到这里,尝试运行下面的命令:
|
||||
|
||||
```
|
||||
$ lxc launch ubuntu:x snaptesting
|
||||
Creating snaptesting
|
||||
Starting snaptesting
|
||||
$ lxc file push timg_20170226_amd64.snap snaptesting/home/ubuntu/
|
||||
$ lxc exec snaptesting -- sudo su - ubuntu
|
||||
To run a command as administrator (user "root"), use "sudo <command>".
|
||||
See "man sudo_root" for details.
|
||||
|
||||
ubuntu@snaptesting:~$ ls
|
||||
timg_20170226_amd64.snap
|
||||
ubuntu@snaptesting:~$ snap install timg_20170226_amd64.snap
|
||||
error: access denied (try with sudo)
|
||||
ubuntu@snaptesting:~$ sudo snap install timg_20170226_amd64.snap
|
||||
error: cannot find signatures with metadata for snap "timg_20170226_amd64.snap"
|
||||
ubuntu@snaptesting:~$ sudo snap install timg_20170226_amd64.snap --dangerous
|
||||
error: cannot perform the following tasks:
|
||||
- Mount snap "core" (1337) ([start snap-core-1337.mount] failed with exit status 1: Job for snap-core-1337.mount failed. See "systemctl status snap-core-1337.mount" and "journalctl -xe" for details.
|
||||
)
|
||||
ubuntu@snaptesting:~$ sudo apt install squashfuse
|
||||
[...]
|
||||
Setting up squashfuse (0.1.100-0ubuntu1~ubuntu16.04.1) ...
|
||||
ubuntu@snaptesting:~$ sudo snap install timg_20170226_amd64.snap --dangerous
|
||||
timg 20170226 installed
|
||||
ubuntu@snaptesting:~$ wget https://farm7.staticflickr.com/6187/6091603784_d6960c8be2_z_d.jpg
|
||||
[...]
|
||||
2017-02-26 22:12:18 (636 KB/s) - ‘6091603784_d6960c8be2_z_d.jpg’ saved [240886/240886]
|
||||
ubuntu@snaptesting:~$ timg 6091603784_d6960c8be2_z_d.jpg
|
||||
[it worked!]
|
||||
ubuntu@snaptesting:~$
|
||||
```
|
||||
|
||||
我们启动了一个名为 `snaptesting` 的 LXD 容器,并将 .snap 文件复制进去。然后,通过普通用户连接到容器,并尝试安装 snap 包。最初,我们安装失败了,因为在无特权的 LXD 容器中安装 snap 包需要使用 `sudo` 。接着又失败了,因为 .snap 没有经过签名(我们需要使用 `--dangerous` 参数)。然而还是失败了,这次是因为我们需要安装 `squashfuse` 包(Ubuntu 16.04 镜像中没有预装)。最后,我们成功安装了snap,并设法查看了图像。
|
||||
|
||||
在一个全新安装的 Linux 系统中测试 snap 包是很重要的,因为这样才能确保 snap 包中包含所有必须的代码库。在这个例子中,我们使用了静态库并运行良好。
|
||||
|
||||
### 发布到 Ubuntu 商店
|
||||
|
||||
这是 [发布 snap 包到 Ubuntu 商店的说明][34]。 在之前的教程中,我们已经发布了一些 snap 包。对于 `timg` 来说,我们设置了严格限制和稳定等级。因此,我们会将它发布到稳定通道。
|
||||
|
||||
```
|
||||
$ snapcraft push timg_20170226_amd64.snap
|
||||
Pushing 'timg_20170226_amd64.snap' to the store.
|
||||
Uploading timg_20170226_amd64.snap [ ] 0%
|
||||
Uploading timg_20170226_amd64.snap [=======================================] 100%
|
||||
Ready to release!|
|
||||
Revision 6 of 'timg' created.
|
||||
$ snapcraft release timg 6 stable
|
||||
Track Arch Series Channel Version Revision
|
||||
latest amd64 16 stable 20170226 6
|
||||
candidate ^ ^
|
||||
beta 0.9.5 5
|
||||
edge 0.9.5 5
|
||||
The 'stable' channel is now open.
|
||||
```
|
||||
|
||||
我们把 .snap 包推送到 Ubuntu 商店后,得到了一个 `Revision 6`。然后,我们将 timg `Revision 6` 发布到了 Ubuntu 商店的稳定通道。
|
||||
|
||||
在候选通道中没有已发布的 snap 包,它继承的是稳定通道的包,所以显示 `^` 字符。
|
||||
|
||||
在之前的测试中,我将一些较老版本的 snap 包上传到了测试和边缘通道。这些旧版本使用了 timg 标签为 `0.9.5` 的源代码。
|
||||
|
||||
我们可以通过将稳定版本发布到测试和边缘通道来移除旧的 0.9.5 版本的包。
|
||||
|
||||
```
|
||||
$ snapcraft release timg 6 beta
|
||||
Track Arch Series Channel Version Revision
|
||||
latest amd64 16 stable 20170226 6
|
||||
candidate ^ ^
|
||||
beta 20170226 6
|
||||
edge 0.9.5 5
|
||||
$ snapcraft release timg 6 edge
|
||||
Track Arch Series Channel Version Revision
|
||||
latest amd64 16 stable 20170226 6
|
||||
candidate ^ ^
|
||||
beta 20170226 6
|
||||
edge 20170226 6
|
||||
```
|
||||
|
||||
### 使用 timg
|
||||
|
||||
让我们不带参数运行 `timg`:
|
||||
|
||||
```
|
||||
ubuntu@snaptesting:~$ timg
|
||||
Expected image filename.
|
||||
usage: /snap/timg/x1/timg [options] <image> [<image>...]
|
||||
Options:
|
||||
-g<w>x<h> : Output pixel geometry. Default from terminal 80x48
|
||||
-s[<ms>] : Scroll horizontally (optionally: delay ms (60)).
|
||||
-d<dx:dy> : delta x and delta y when scrolling (default: 1:0).
|
||||
-w<seconds>: If multiple images given: Wait time between (default: 0.0).
|
||||
-t<seconds>: Only animation or scrolling: stop after this time.
|
||||
-c<num> : Only Animation or scrolling: number of runs through a full cycle.
|
||||
-C : Clear screen before showing image.
|
||||
-F : Print filename before showing picture.
|
||||
-v : Print version and exit.
|
||||
If both -c and -t are given, whatever comes first stops.
|
||||
If both -w and -t are given for some animation/scroll, -t takes precedence
|
||||
ubuntu@snaptesting:~$
|
||||
```
|
||||
|
||||
这里提到当前我们终端模拟器的缩放级别,即分辨率为:80 × 48。
|
||||
|
||||
让我们缩小一点,并最大化 GNOME 终端窗口。
|
||||
|
||||
```
|
||||
-g<w>x<h> : Output pixel geometry. Default from terminal 635x428
|
||||
```
|
||||
|
||||
这是一个更好的解决方案,但我几乎看不到字符,因为他们太小了。让我们调用前面的命令再次显示这辆车。
|
||||
|
||||
![图片.png-904.9kB][35]
|
||||
|
||||
你所看到的是调整后的图像(1080p)。虽然它是用彩色文本字符显示的,但看起来依旧很棒。
|
||||
|
||||
接下来呢?`timg` 其实也可以播放 gif 动画哦!
|
||||
|
||||
```
|
||||
$ wget https://m.popkey.co/9b7141/QbAV_f-maxage-0.gif -O JonahHillAmazed.gif$ timg JonahHillAmazed.gif
|
||||
```
|
||||
|
||||
你可以试着安装 `timg` 来体验 gif 动画。要是不想自己动手,可以在 [asciinema][36] 上查看相关记录 (如果视频看上去起伏不定的,请重新运行它)。
|
||||
|
||||
谢谢阅读!
|
||||
|
||||
-----
|
||||
译者简介:
|
||||
|
||||
经常混迹于 snapcraft.io,对 Ubuntu Core、Snaps 和 Snapcraft 有着浓厚的兴趣,并致力于将这些还在快速发展的新技术通过翻译或原创的方式介绍到中文世界。有兴趣的小伙伴也可以关注译者个人公众号: `Snapcraft`
|
||||
|
||||
-----
|
||||
via:https://blog.simos.info/how-to-create-a-snap-for-timg-with-snapcraft-on-ubuntu/
|
||||
|
||||
作者:[Mi blog lah!][37]
|
||||
译者:[Snapcrafter](https://github.com/Snapcrafter)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
|
||||
[1]: https://github.com/hzeller/timg
|
||||
[2]: https://tutorials.ubuntu.com/tutorial/create-your-first-snap
|
||||
[3]: https://github.com/hzeller/timg
|
||||
[4]: https://snapcraft.io/docs/reference/plugins/make
|
||||
[5]:https://github.com/hzeller/timg
|
||||
[6]: http://static.zybuluo.com/apollomoon/ynm5k5urc7idb037ahca2s93/%E5%9B%BE%E7%89%87.png
|
||||
[7]: http://static.zybuluo.com/apollomoon/h2ynj68axdqiy7dwszgw5z1f/%E5%9B%BE%E7%89%87.png
|
||||
[8]:https://gist.github.com/XVilka/8346728
|
||||
[9]:https://en.wikipedia.org/wiki/Escape_sequence
|
||||
[10]:https://github.com/hzeller/timg
|
||||
[11]: http://static.zybuluo.com/apollomoon/nzlqpq3xn4rs72h4r96k4xlw/%E5%9B%BE%E7%89%87.png
|
||||
[12]:http://design.ubuntu.com/wp-content/uploads/ubuntu-logo112.png
|
||||
[13]: http://static.zybuluo.com/apollomoon/vo1nxnu4xfaghyib03fnkvq4/%E5%9B%BE%E7%89%87.png
|
||||
[14]:https://www.flickr.com/photos/doug88888/5776072628/in/photolist-9WCiNQ-7U3Trc-7YUZBL-5DwkEQ-6e1iT8-a372aS-5F75aL-a1gbow-6eNayj-8gWK2H-5CtH7P-6jVqZv-86RpwN-a2nEnB-aiRmsc-6aKvwK-8hmXrN-5CWDNP-62hWM8-a9smn1-ahQqHw-a22p3w-a36csK-ahN4Pv-7VEmnt-ahMSiT-9NpTa7-5A3Pon-ai7DL7-9TKCqV-ahr7gN-a1boqP-83ZzpH-9Sqjmq-5xujdi-7UmDVb-6J2zQR-5wAGNR-5eERar-5KVDym-5dL8SZ-5S2Uut-7RVyHg-9Z6MAt-aiRiT4-5tLesw-aGLSv6-5ftp6j-5wAVBq-5T2KAP
|
||||
[15]: https://github.com/hzeller/timg
|
||||
[16]: https://github.com/hzeller/timg
|
||||
[17]:https://github.com/hzeller/timg
|
||||
[18]: https://github.com/hzeller/timg
|
||||
[19]: http://static.zybuluo.com/apollomoon/hovu73yqx08pdhm8qmdg6f6a/%E5%9B%BE%E7%89%87.png
|
||||
[20]:https://github.com/hzeller/timg
|
||||
[21]: http://static.zybuluo.com/apollomoon/o64i7jm65u3o12wg3fqqcn7x/%E5%9B%BE%E7%89%87.png
|
||||
[22]: http://static.zybuluo.com/apollomoon/t4w1uak9j4h6rfn4ghc8q15k/%E5%9B%BE%E7%89%87.png
|
||||
[23]: http://static.zybuluo.com/apollomoon/cvuetj2rzd5nee7pgfcp7wr3/timg-git-url.png
|
||||
[24]: http://static.zybuluo.com/apollomoon/dxtl628r1qavphhzu70jiw1n/%E5%9B%BE%E7%89%87.png
|
||||
[25]: https://snapcraft.io/docs/reference/plugins/make
|
||||
[26]:https://snapcraft.io/docs/reference/plugins/
|
||||
[27]: https://snapcraft.io/docs/reference/plugins/source
|
||||
[28]: https://snapcraft.io/docs/reference/plugins/source
|
||||
[29]:https://snapcraft.io/docs/reference/plugins/common
|
||||
[30]:https://snapcraft.io/docs/reference/plugins/make
|
||||
[31]:https://snapcraft.io/docs/reference/plugins/make
|
||||
[32]: http://static.zybuluo.com/apollomoon/v9y3vutt8li4wwaxeigwr4yz/%E5%9B%BE%E7%89%87.png
|
||||
[33]:https://blog.simos.info/trying-out-lxd-containers-on-our-ubuntu/
|
||||
[34]:https://snapcraft.io/docs/build-snaps/publish
|
||||
[35]: http://static.zybuluo.com/apollomoon/clnv44g3bwhaqog7o1jpvpcd/%E5%9B%BE%E7%89%87.png
|
||||
[36]: https://asciinema.org/a/dezbe2gpye84e0pjndp8t0pvh
|
||||
[37]: https://blog.simos.info/
|
||||
[38]:https://snapcraft.io/docs/reference/confinement
|
568
published/20170312 OpenGL Go Tutorial Part 1.md
Normal file
568
published/20170312 OpenGL Go Tutorial Part 1.md
Normal file
@ -0,0 +1,568 @@
|
||||
OpenGL 与 Go 教程(一)Hello, OpenGL
|
||||
============================================================
|
||||
|
||||
- [第一节: Hello, OpenGL][6]
|
||||
- [第二节: 绘制游戏面板][7]
|
||||
- [第三节: 实现游戏功能][8]
|
||||
|
||||
这篇教程的所有源代码都可以在 [GitHub][9] 上找到。
|
||||
|
||||
### 介绍
|
||||
|
||||
[OpenGL][19] 是一门相当好的技术,适用于从桌面的 GUI 到游戏,到移动应用甚至 web 应用的多种类型的绘图工作。我敢保证,你今天看到的图形有些就是用 OpenGL 渲染的。可是,不管 OpenGL 多受欢迎、有多好用,与学习其它高级绘图库相比,学习 OpenGL 是要相当足够的决心的。
|
||||
|
||||
这个教程的目的是给你一个切入点,让你对 OpenGL 有个基本的了解,然后教你怎么用 [Go][20] 操作它。几乎每种编程语言都有绑定 OpenGL 的库,Go 也不例外,它有 [go-gl][21] 这个包。这是一个完整的套件,可以绑定 OpenGL ,适用于多种版本的 OpenGL。
|
||||
|
||||
这篇教程会按照下面列出的几个阶段进行介绍,我们最终的目标是用 OpenGL 在桌面窗口绘制游戏面板,进而实现[康威生命游戏][22]。完整的源代码可以在 GitHub [github.com/KyleBanks/conways-gol][23] 上获得,当你有疑惑的时候可以随时查看源代码,或者你要按照自己的方式学习也可以参考这个代码。
|
||||
|
||||
在我们开始之前,我们要先弄明白<ruby>康威生命游戏<rt>Conway's Game of Life</rt></ruby> 到底是什么。这里是 [Wikipedia][24] 上面的总结:
|
||||
|
||||
> 《生命游戏》,也可以简称为 Life,是一个细胞自动变化的过程,由英国数学家 John Horton Conway 于 1970 年提出。
|
||||
>
|
||||
> 这个“游戏”没有玩家,也就是说它的发展依靠的是它的初始状态,不需要输入。用户通过创建初始配置文件、观察它如何演变,或者对于高级“玩家”可以创建特殊属性的模式,进而与《生命游戏》进行交互。
|
||||
>
|
||||
> `规则`
|
||||
>
|
||||
> 《生命游戏》的世界是一个无穷多的二维正交的正方形细胞的格子世界,每一个格子都有两种可能的状态,“存活”或者“死亡”,也可以说是“填充态”或“未填充态”(区别可能很小,可以把它看作一个模拟人类/哺乳动物行为的早期模型,这要看一个人是如何看待方格里的空白)。每一个细胞与它周围的八个细胞相关联,这八个细胞分别是水平、垂直、斜对角相接的。在游戏中的每一步,下列事情中的一件将会发生:
|
||||
>
|
||||
> 1. 当任何一个存活的细胞的附近少于 2 个存活的细胞时,该细胞将会消亡,就像人口过少所导致的结果一样
|
||||
> 2. 当任何一个存活的细胞的附近有 2 至 3 个存活的细胞时,该细胞在下一代中仍然存活。
|
||||
> 3. 当任何一个存活的细胞的附近多于 3 个存活的细胞时,该细胞将会消亡,就像人口过多所导致的结果一样
|
||||
> 4. 任何一个消亡的细胞附近刚好有 3 个存活的细胞,该细胞会变为存活的状态,就像重生一样。
|
||||
|
||||
不需要其他工具,这里有一个我们将会制作的演示程序:
|
||||
|
||||
![Conway's Game of Life - 示例游戏](https://kylewbanks.com/images/post/golang-opengl-conway-1.gif)
|
||||
|
||||
在我们的运行过程中,白色的细胞表示它是存活着的,黑色的细胞表示它已经死亡。
|
||||
|
||||
### 概述
|
||||
|
||||
本教程将会涉及到很多基础内容,从最基本的开始,但是你还是要对 Go 由一些最基本的了解 —— 至少你应该知道变量、切片、函数和结构体,并且装了一个 Go 的运行环境。我写这篇教程用的 Go 版本是 1.8,但它应该与之前的版本兼容。这里用 Go 语言实现没有什么特别新奇的东西,因此只要你有过类似的编程经历就行。
|
||||
|
||||
这里是我们在这个教程里将会讲到的东西:
|
||||
|
||||
* [第一节: Hello, OpenGL][10]: 安装 OpenGL 和 [GLFW][11],在窗口上绘制一个三角形。
|
||||
* [第二节: 绘制游戏面板][12]: 用三角形拼成方形,在窗口上用方形绘成格子。
|
||||
* [第三节: 实现游戏功能][13]: 实现 Conway 游戏
|
||||
|
||||
最后的源代码可以在 [GitHub][25] 上获得,每一节的末尾有个_回顾_,包含该节相关的代码。如果有什么不清楚的地方或者是你感到疑惑的,看看每一节末尾的完整代码。
|
||||
|
||||
现在就开始吧!
|
||||
|
||||
### 安装 OpenGL 和 GLFW
|
||||
|
||||
我们介绍过 OpenGL,但是为了使用它,我们要有个窗口可以绘制东西。 [GLFW][26] 是一款用于 OpenGL 的跨平台 API,允许我们创建并使用窗口,而且它也是 [go-gl][27] 套件中提供的。
|
||||
|
||||
我们要做的第一件事就是确定 OpenGL 的版本。为了方便本教程,我们将会使用 `OpenGL v4.1`,但要是你的操作系统不支持最新的 OpenGL,你也可以用 `v2.1`。要安装 OpenGL,我们需要做这些事:
|
||||
|
||||
```
|
||||
# 对于 OpenGL 4.1
|
||||
$ go get github.com/go-gl/gl/v4.1-core/gl
|
||||
|
||||
# 或者 2.1
|
||||
$ go get github.com/go-gl/gl/v2.1/gl
|
||||
```
|
||||
|
||||
然后是安装 GLFW:
|
||||
|
||||
```
|
||||
$ go get github.com/go-gl/glfw/v3.2/glfw
|
||||
```
|
||||
|
||||
安装好这两个包之后,我们就可以开始了!先创建 `main.go` 文件,导入相应的包(我们待会儿会用到的其它东西)。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
|
||||
"github.com/go-gl/gl/v4.1-core/gl" // OR: github.com/go-gl/gl/v2.1/gl
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
)
|
||||
```
|
||||
|
||||
接下来定义一个叫做 `main` 的函数,这是用来初始化 OpenGL 以及 GLFW,并显示窗口的:
|
||||
|
||||
```
|
||||
const (
|
||||
width = 500
|
||||
height = 500
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.LockOSThread()
|
||||
|
||||
window := initGlfw()
|
||||
defer glfw.Terminate()
|
||||
|
||||
for !window.ShouldClose() {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
// initGlfw 初始化 glfw 并且返回一个可用的窗口。
|
||||
func initGlfw() *glfw.Window {
|
||||
if err := glfw.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
glfw.WindowHint(glfw.Resizable, glfw.False)
|
||||
glfw.WindowHint(glfw.ContextVersionMajor, 4) // OR 2
|
||||
glfw.WindowHint(glfw.ContextVersionMinor, 1)
|
||||
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
|
||||
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
|
||||
|
||||
window, err := glfw.CreateWindow(width, height, "Conway's Game of Life", nil, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
window.MakeContextCurrent()
|
||||
|
||||
return window
|
||||
}
|
||||
```
|
||||
|
||||
好了,让我们花一分钟来运行一下这个程序,看看会发生什么。首先定义了一些常量, `width` 和 `height` —— 它们决定窗口的像素大小。
|
||||
|
||||
然后就是 `main` 函数。这里我们使用了 `runtime` 包的 `LockOSThread()`,这能确保我们总是在操作系统的同一个线程中运行代码,这对 GLFW 来说很重要,GLFW 需要在其被初始化之后的线程里被调用。讲完这个,接下来我们调用 `initGlfw` 来获得一个窗口的引用,并且推迟(`defer`)其终止。窗口的引用会被用在一个 `for` 循环中,只要窗口处于打开的状态,就执行某些事情。我们待会儿会讲要做的事情是什么。
|
||||
|
||||
`initGlfw` 是另一个函数,这里我们调用 `glfw.Init()` 来初始化 GLFW 包。然后我们定义了 GLFW 的一些全局属性,包括禁用调整窗口大小和改变 OpenGL 的属性。然后创建了 `glfw.Window`,这会在稍后的绘图中用到。我们仅仅告诉它我们想要的宽度和高度,以及标题,然后调用 `window.MakeContextCurrent`,将窗口绑定到当前的线程中。最后就是返回窗口的引用了。
|
||||
|
||||
如果你现在就构建、运行这个程序,你看不到任何东西。很合理,因为我们还没有用这个窗口做什么实质性的事。
|
||||
|
||||
定义一个新函数,初始化 OpenGL,就可以解决这个问题:
|
||||
|
||||
```
|
||||
// initOpenGL 初始化 OpenGL 并且返回一个初始化了的程序。
|
||||
func initOpenGL() uint32 {
|
||||
if err := gl.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
version := gl.GoStr(gl.GetString(gl.VERSION))
|
||||
log.Println("OpenGL version", version)
|
||||
|
||||
prog := gl.CreateProgram()
|
||||
gl.LinkProgram(prog)
|
||||
return prog
|
||||
}
|
||||
```
|
||||
|
||||
`initOpenGL` 就像之前的 `initGlfw` 函数一样,初始化 OpenGL 库,创建一个<ruby>程序<rt>program</rt></ruby>。“程序”是一个包含了<ruby>着色器<rt>shader</rt></ruby>的引用,稍后会用<ruby>着色器<rt>shader</rt></ruby>绘图。待会儿会讲这一点,现在只用知道 OpenGL 已经初始化完成了,我们有一个程序的引用。我们还打印了 OpenGL 的版本,可以用于之后的调试。
|
||||
|
||||
回到 `main` 函数里,调用这个新函数:
|
||||
|
||||
```
|
||||
func main() {
|
||||
runtime.LockOSThread()
|
||||
|
||||
window := initGlfw()
|
||||
defer glfw.Terminate()
|
||||
|
||||
program := initOpenGL()
|
||||
|
||||
for !window.ShouldClose() {
|
||||
draw(window, program)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你应该注意到了现在我们有 `program` 的引用,在我们的窗口循环中,调用新的 `draw` 函数。最终这个函数会绘制出所有细胞,让游戏状态变得可视化,但是现在它做的仅仅是清除窗口,所以我们只能看到一个全黑的屏幕:
|
||||
|
||||
```
|
||||
func draw(window *glfw.Window, program uint32) {
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
gl.UseProgram(prog)
|
||||
|
||||
glfw.PollEvents()
|
||||
window.SwapBuffers()
|
||||
}
|
||||
```
|
||||
|
||||
我们首先做的是调用 `gl.clear` 函数来清除上一帧在窗口中绘制的东西,给我们一个干净的面板。然后我们告诉 OpenGL 去使用我们的程序引用,这个引用还没有做什么事。最终我们告诉 GLFW 用 `PollEvents` 去检查是否有鼠标或者键盘事件(这一节里还不会对这些事件进行处理),告诉窗口去交换缓冲区 `SwapBuffers`。 [交换缓冲区][28] 很重要,因为 GLFW(像其他图形库一样)使用双缓冲,也就是说你绘制的所有东西实际上是绘制到一个不可见的画布上,当你准备好进行展示的时候就把绘制的这些东西放到可见的画布中 —— 这种情况下,就需要调用 `SwapBuffers` 函数。
|
||||
|
||||
好了,到这里我们已经讲了很多东西,花一点时间看看我们的实验成果。运行这个程序,你应该可以看到你所绘制的第一个东西:
|
||||
|
||||
![Conway's Game of Life - 第一个窗口](https://kylewbanks.com/images/post/golang-opengl-conway-2.png)
|
||||
|
||||
完美!
|
||||
|
||||
### 在窗口里绘制三角形
|
||||
|
||||
我们已经完成了一些复杂的步骤,即使看起来不多,但我们仍然需要绘制一些东西。我们会以三角形绘制开始,可能这第一眼看上去要比我们最终要绘制的方形更难,但你会知道这样的想法是错的。你可能不知道的是三角形或许是绘制的图形中最简单的,实际上我们最终会用某种方式把三角形拼成方形。
|
||||
|
||||
好吧,那么我们想要绘制一个三角形,怎么做呢?我们通过定义图形的顶点来绘制图形,把它们交给 OpenGL 来进行绘制。先在 `main.go` 的顶部里定义我们的三角形:
|
||||
|
||||
```
|
||||
var (
|
||||
triangle = []float32{
|
||||
0, 0.5, 0, // top
|
||||
-0.5, -0.5, 0, // left
|
||||
0.5, -0.5, 0, // right
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
这看上去很奇怪,让我们分开来看。首先我们用了一个 `float32` <ruby>切片<rt>slice</rt></ruby>,这是一种我们总会在向 OpenGL 传递顶点时用到的数据类型。这个切片包含 9 个值,每三个值构成三角形的一个点。第一行, `0, 0.5, 0` 表示的是 X、Y、Z 坐标,是最上方的顶点,第二行是左边的顶点,第三行是右边的顶点。每一组的三个点都表示相对于窗口中心点的 X、Y、Z 坐标,大小在 `-1` 和 `1` 之间。因此最上面的顶点 X 坐标是 `0`,因为它在 X 方向上位于窗口中央,Y 坐标是 `0.5` 意味着它会相对窗口中央上移 1/4 个单位(因为窗口的范围是 `-1` 到 `1`),Z 坐标是 0。因为我们只需要在二维空间中绘图,所以 Z 值永远是 `0`。现在看一看左右两边的顶点,看看你能不能理解为什么它们是这样定义的 —— 如果不能立刻就弄清楚也没关系,我们将会在屏幕上去观察它,因此我们需要一个完美的图形来进行观察。
|
||||
|
||||
好了,我们定义了一个三角形,但是现在我们得把它画出来。要画出这个三角形,我们需要一个叫做<ruby>顶点数组对象<rt>Vertex Array Object</rt></ruby>或者叫 vao 的东西,这是由一系列的点(也就是我们定义的三角形)创造的,这个东西可以提供给 OpenGL 来进行绘制。创建一个叫做 `makeVao` 的函数,然后我们可以提供一个点的切片,让它返回一个指向 OpenGL 顶点数组对象的指针:
|
||||
|
||||
```
|
||||
// makeVao 执行初始化并从提供的点里面返回一个顶点数组
|
||||
func makeVao(points []float32) uint32 {
|
||||
var vbo uint32
|
||||
gl.GenBuffers(1, &vbo)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
|
||||
gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), gl.STATIC_DRAW)
|
||||
|
||||
var vao uint32
|
||||
gl.GenVertexArrays(1, &vao)
|
||||
gl.BindVertexArray(vao)
|
||||
gl.EnableVertexAttribArray(0)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
|
||||
gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil)
|
||||
|
||||
return vao
|
||||
}
|
||||
```
|
||||
|
||||
首先我们创造了<ruby>顶点缓冲区对象<rt>Vertex Buffer Object</rt></ruby> 或者说 vbo 绑定到我们的 `vao` 上,`vbo` 是通过所占空间(也就是 4 倍 `len(points)` 大小的空间)和一个指向顶点的指针(`gl.Ptr(points)`)来创建的。你也许会好奇为什么它是 4 倍 —— 而不是 6 或者 3 或者 1078 呢?原因在于我们用的是 `float32` 切片,32 个位的浮点型变量是 4 个字节,因此我们说这个缓冲区以字节为单位的大小是点个数的 4 倍。
|
||||
|
||||
现在我们有缓冲区了,可以创建 `vao` 并用 `gl.BindBuffer` 把它绑定到缓冲区上,最后返回 `vao`。这个 `vao` 将会被用于绘制三角形!
|
||||
|
||||
回到 `main` 函数:
|
||||
|
||||
```
|
||||
func main() {
|
||||
...
|
||||
|
||||
vao := makeVao(triangle)
|
||||
for !window.ShouldClose() {
|
||||
draw(vao, window, program)
|
||||
}
|
||||
}
|
||||
|
||||
这里我们调用了 `makeVao` ,从我们之前定义的 `triangle` 顶点中获得 `vao` 引用,将它作为一个新的参数传递给 `draw` 函数:
|
||||
|
||||
func draw(vao uint32, window *glfw.Window, program uint32) {
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
gl.UseProgram(program)
|
||||
|
||||
gl.BindVertexArray(vao)
|
||||
gl.DrawArrays(gl.TRIANGLES, 0, int32(len(triangle) / 3))
|
||||
|
||||
glfw.PollEvents()
|
||||
window.SwapBuffers()
|
||||
}
|
||||
```
|
||||
|
||||
然后我们把 OpenGL 绑定到 `vao` 上,这样当我们告诉 OpenGL 三角形切片的顶点数(除以 3,是因为每一个点有 X、Y、Z 坐标),让它去 `DrawArrays` ,它就知道要画多少个顶点了。
|
||||
|
||||
如果你这时候运行程序,你可能希望在窗口中央看到一个美丽的三角形,但是不幸的是你还看不到。还有一件事情没做,我们告诉 OpenGL 我们要画一个三角形,但是我们还要告诉它_怎么_画出来。
|
||||
|
||||
要让它画出来,我们需要叫做<ruby>片元着色器<rt>fragment shader</rt></ruby>和<ruby>顶点着色器<rt>vertex shader</rt></ruby>的东西,这些已经超出本教程的范围了(老实说,也超出了我对 OpenGL 的了解),但 [Harold Serrano 在 Quora][29] 上对对它们是什么给出了完美的介绍。我们只需要理解,对于这个应用来说,着色器是它内部的小程序(用 [OpenGL Shader Language 或 GLSL][30] 编写的),它操作顶点进行绘制,也可用于确定图形的颜色。
|
||||
|
||||
添加两个 `import` 和一个叫做 `compileShader` 的函数:
|
||||
|
||||
```
|
||||
import (
|
||||
"strings"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func compileShader(source string, shaderType uint32) (uint32, error) {
|
||||
shader := gl.CreateShader(shaderType)
|
||||
|
||||
csources, free := gl.Strs(source)
|
||||
gl.ShaderSource(shader, 1, csources, nil)
|
||||
free()
|
||||
gl.CompileShader(shader)
|
||||
|
||||
var status int32
|
||||
gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
|
||||
if status == gl.FALSE {
|
||||
var logLength int32
|
||||
gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength)
|
||||
|
||||
log := strings.Repeat("\x00", int(logLength+1))
|
||||
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))
|
||||
|
||||
return 0, fmt.Errorf("failed to compile %v: %v", source, log)
|
||||
}
|
||||
|
||||
return shader, nil
|
||||
}
|
||||
```
|
||||
|
||||
这个函数的目的是以字符串的形式接受着色器源代码和它的类型,然后返回一个指向这个编译好的着色器的指针。如果编译失败,我们就会获得出错的详细信息。
|
||||
|
||||
现在定义着色器,在 `makeProgram` 里编译。回到我们的 `const` 块中,我们在这里定义了 `width` 和 `hegiht`。
|
||||
|
||||
```
|
||||
vertexShaderSource = `
|
||||
#version 410
|
||||
in vec3 vp;
|
||||
void main() {
|
||||
gl_Position = vec4(vp, 1.0);
|
||||
}
|
||||
` + "\x00"
|
||||
|
||||
fragmentShaderSource = `
|
||||
#version 410
|
||||
out vec4 frag_colour;
|
||||
void main() {
|
||||
frag_colour = vec4(1, 1, 1, 1);
|
||||
}
|
||||
` + "\x00"
|
||||
```
|
||||
|
||||
如你所见,这是两个包含了 GLSL 源代码字符串的着色器,一个是<ruby>顶点着色器<rt>vertex shader</rt></ruby>,另一个是<ruby>片元着色器<rt>fragment shader</rt></ruby>。唯一比较特殊的地方是它们都要在末尾加上一个空终止字符,`\x00` —— OpenGL 需要它才能编译着色器。注意 `fragmentShaderSource`,这是我们用 RGBA 形式的值通过 `vec4` 来定义我们图形的颜色。你可以修改这里的值来改变这个三角形的颜色,现在的值是 `RGBA(1, 1, 1, 1)` 或者说是白色。
|
||||
|
||||
同样需要注意的是这两个程序都是运行在 `#version 410` 版本下,如果你用的是 OpenGL 2.1,那你也可以改成 `#version 120`。这里 `120` 不是打错的,如果你用的是 OpenGL 2.1,要用 `120` 而不是 `210`!
|
||||
|
||||
接下来在 `initOpenGL` 中我们会编译着色器,把它们附加到我们的 `program` 中。
|
||||
|
||||
```
|
||||
func initOpenGL() uint32 {
|
||||
if err := gl.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
version := gl.GoStr(gl.GetString(gl.VERSION))
|
||||
log.Println("OpenGL version", version)
|
||||
|
||||
vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
prog := gl.CreateProgram()
|
||||
gl.AttachShader(prog, vertexShader)
|
||||
gl.AttachShader(prog, fragmentShader)
|
||||
gl.LinkProgram(prog)
|
||||
return prog
|
||||
}
|
||||
```
|
||||
|
||||
这里我们用顶点着色器(`vertexShader`)调用了 `compileShader` 函数,指定它的类型是 `gl.VERTEX_SHADER`,对片元着色器(`fragmentShader`)做了同样的事情,但是指定的类型是 `gl.FRAGMENT_SHADER`。编译完成后,我们把它们附加到程序中,调用 `gl.AttachShader`,传递程序(`prog`)以及编译好的着色器作为参数。
|
||||
|
||||
现在我们终于可以看到我们漂亮的三角形了!运行程序,如果一切顺利的话你会看到这些:
|
||||
|
||||
![Conway's Game of Life - Hello, Triangle!](https://kylewbanks.com/images/post/golang-opengl-conway-3.png)
|
||||
|
||||
### 总结
|
||||
|
||||
是不是很惊喜!这些代码画出了一个三角形,但我保证我们已经完成了大部分的 OpenGL 代码,在接下来的章节中我们还会用到这些代码。我十分推荐你花几分钟修改一下代码,看看你能不能移动三角形,改变三角形的大小和颜色。OpenGL 可以令人心生畏惧,有时想要理解发生了什么很困难,但是要记住,这不是魔法 - 它只不过看上去像魔法。
|
||||
|
||||
下一节里我们讲会用两个锐角三角形拼出一个方形 - 看看你能不能在进入下一节前试着修改这一节的代码。不能也没有关系,因为我们在 [第二节][31] 还会编写代码, 接着创建一个有许多方形的格子,我们把它当做游戏面板。
|
||||
|
||||
最后,在[第三节][32] 里我们会用格子来实现 _Conway’s Game of Life_!
|
||||
|
||||
|
||||
### 回顾
|
||||
|
||||
本教程 `main.go` 文件的内容如下:
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/go-gl/gl/v4.1-core/gl" // OR: github.com/go-gl/gl/v2.1/gl
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
)
|
||||
|
||||
const (
|
||||
width = 500
|
||||
height = 500
|
||||
|
||||
vertexShaderSource = `
|
||||
#version 410
|
||||
in vec3 vp;
|
||||
void main() {
|
||||
gl_Position = vec4(vp, 1.0);
|
||||
}
|
||||
` + "\x00"
|
||||
|
||||
fragmentShaderSource = `
|
||||
#version 410
|
||||
out vec4 frag_colour;
|
||||
void main() {
|
||||
frag_colour = vec4(1, 1, 1, 1.0);
|
||||
}
|
||||
` + "\x00"
|
||||
)
|
||||
|
||||
var (
|
||||
triangle = []float32{
|
||||
0, 0.5, 0,
|
||||
-0.5, -0.5, 0,
|
||||
0.5, -0.5, 0,
|
||||
}
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.LockOSThread()
|
||||
|
||||
window := initGlfw()
|
||||
defer glfw.Terminate()
|
||||
program := initOpenGL()
|
||||
|
||||
vao := makeVao(triangle)
|
||||
for !window.ShouldClose() {
|
||||
draw(vao, window, program)
|
||||
}
|
||||
}
|
||||
|
||||
func draw(vao uint32, window *glfw.Window, program uint32) {
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
gl.UseProgram(program)
|
||||
|
||||
gl.BindVertexArray(vao)
|
||||
gl.DrawArrays(gl.TRIANGLES, 0, int32(len(triangle)/3))
|
||||
|
||||
glfw.PollEvents()
|
||||
window.SwapBuffers()
|
||||
}
|
||||
|
||||
// initGlfw 初始化 glfw 并返回一个窗口供使用。
|
||||
func initGlfw() *glfw.Window {
|
||||
if err := glfw.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
glfw.WindowHint(glfw.Resizable, glfw.False)
|
||||
glfw.WindowHint(glfw.ContextVersionMajor, 4)
|
||||
glfw.WindowHint(glfw.ContextVersionMinor, 1)
|
||||
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
|
||||
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
|
||||
|
||||
window, err := glfw.CreateWindow(width, height, "Conway's Game of Life", nil, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
window.MakeContextCurrent()
|
||||
|
||||
return window
|
||||
}
|
||||
|
||||
// initOpenGL 初始化 OpenGL 并返回一个已经编译好的着色器程序
|
||||
func initOpenGL() uint32 {
|
||||
if err := gl.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
version := gl.GoStr(gl.GetString(gl.VERSION))
|
||||
log.Println("OpenGL version", version)
|
||||
|
||||
vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
prog := gl.CreateProgram()
|
||||
gl.AttachShader(prog, vertexShader)
|
||||
gl.AttachShader(prog, fragmentShader)
|
||||
gl.LinkProgram(prog)
|
||||
return prog
|
||||
}
|
||||
|
||||
// makeVao 执行初始化并从提供的点里面返回一个顶点数组
|
||||
func makeVao(points []float32) uint32 {
|
||||
var vbo uint32
|
||||
gl.GenBuffers(1, &vbo)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
|
||||
gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), gl.STATIC_DRAW)
|
||||
|
||||
var vao uint32
|
||||
gl.GenVertexArrays(1, &vao)
|
||||
gl.BindVertexArray(vao)
|
||||
gl.EnableVertexAttribArray(0)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
|
||||
gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil)
|
||||
|
||||
return vao
|
||||
}
|
||||
|
||||
func compileShader(source string, shaderType uint32) (uint32, error) {
|
||||
shader := gl.CreateShader(shaderType)
|
||||
|
||||
csources, free := gl.Strs(source)
|
||||
gl.ShaderSource(shader, 1, csources, nil)
|
||||
free()
|
||||
gl.CompileShader(shader)
|
||||
|
||||
var status int32
|
||||
gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
|
||||
if status == gl.FALSE {
|
||||
var logLength int32
|
||||
gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength)
|
||||
|
||||
log := strings.Repeat("\x00", int(logLength+1))
|
||||
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))
|
||||
|
||||
return 0, fmt.Errorf("failed to compile %v: %v", source, log)
|
||||
}
|
||||
|
||||
return shader, nil
|
||||
}
|
||||
```
|
||||
|
||||
请在 Twitter [@kylewbanks][33] 上告诉我这篇文章对你是否有帮助,或者点击下方的关注,以便及时获取最新文章!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||||
|
||||
作者:[kylewbanks][a]
|
||||
译者:[GitFuture](https://github.com/GitFuture)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://twitter.com/kylewbanks
|
||||
[1]:https://kylewbanks.com/category/golang
|
||||
[2]:https://kylewbanks.com/category/opengl
|
||||
[3]:https://twitter.com/intent/tweet?text=OpenGL%20%26%20Go%20Tutorial%20Part%201%3A%20Hello%2C%20OpenGL%20https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-1-hello-opengl%20by%20%40kylewbanks
|
||||
[4]:mailto:?subject=Check%20Out%20%22OpenGL%20%26%20Go%20Tutorial%20Part%201%3A%20Hello%2C%20OpenGL%22&body=https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[5]:https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[6]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[7]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[8]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game
|
||||
[9]:https://github.com/KyleBanks/conways-gol
|
||||
[10]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[11]:http://www.glfw.org/
|
||||
[12]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[13]:https://kylewbanks.com/blog/blog/tutorial-opengl-with-golang-part-3-implementing-the-game
|
||||
[14]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[15]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[16]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game
|
||||
[17]:https://github.com/KyleBanks/conways-gol
|
||||
[18]:https://twitter.com/kylewbanks
|
||||
[19]:https://www.opengl.org/
|
||||
[20]:https://golang.org/
|
||||
[21]:https://github.com/go-gl/gl
|
||||
[22]:https://en.wikipedia.org/wiki/Conway's_Game_of_Life
|
||||
[23]:https://github.com/KyleBanks/conways-gol
|
||||
[24]:https://en.wikipedia.org/wiki/Conway's_Game_of_Life
|
||||
[25]:https://github.com/KyleBanks/conways-gol
|
||||
[26]:http://www.glfw.org/
|
||||
[27]:https://github.com/go-gl/glfw
|
||||
[28]:http://www.glfw.org/docs/latest/window_guide.html#buffer_swap
|
||||
[29]:https://www.quora.com/What-is-a-vertex-shader-and-what-is-a-fragment-shader/answer/Harold-Serrano?srid=aVb
|
||||
[30]:https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/glsl_overview.php
|
||||
[31]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[32]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game
|
||||
[33]:https://twitter.com/kylewbanks
|
@ -1,19 +1,21 @@
|
||||
OpenGL & Go Tutorial Part 2: Drawing the Game Board
|
||||
OpenGL 与 Go 教程(二)绘制游戏面板
|
||||
============================================================
|
||||
|
||||
_[Part 1: Hello, OpenGL][6]_ | _[Part 2: Drawing the Game Board][7]_ | _[Part 3: Implementing the Game][8]_
|
||||
- [第一节: Hello, OpenGL][6]
|
||||
- [第二节: 绘制游戏面板][7]
|
||||
- [第三节:实现游戏功能][8]
|
||||
|
||||
_The full source code of the tutorial is available on [GitHub][9]._
|
||||
这篇教程的所有源代码都可以在 [GitHub][9] 上找到。
|
||||
|
||||
Welcome back to the _OpenGL & Go Tutorial!_ If you haven’t gone through [Part 1][15] you’ll definitely want to take a step back and check it out.
|
||||
欢迎回到《OpenGL 与 Go 教程》。如果你还没有看过[第一节][15],那就要回过头去看看那一节。
|
||||
|
||||
At this point you should be the proud creator of a magnificent white triangle, but we’re not in the business of using triangles as our game unit so it’s time to turn the triangle into a square, and then we’ll make an entire grid of them.
|
||||
你现在应该能够创造一个漂亮的白色三角形,但我们不会把三角形当成我们游戏的基本单元,是时候把三角形变成正方形了,然后我们会做出一个完整的方格。
|
||||
|
||||
Let’s get started!
|
||||
让我们现在开始做吧!
|
||||
|
||||
### Make a Square out of Triangles
|
||||
### 利用三角形绘制方形
|
||||
|
||||
Before we can make a square, let’s turn our triangle into a right-angle. Open up **main.go** and change the **triangle** definition to look like so:
|
||||
在我们绘制方形之前,先把三角形变成直角三角形。打开 `main.go` 文件,把 `triangle` 的定义改成像这个样子:
|
||||
|
||||
```
|
||||
triangle = []float32{
|
||||
@ -23,11 +25,11 @@ triangle = []float32{
|
||||
}
|
||||
```
|
||||
|
||||
What we’ve done is move the X-coordinate of the top vertex to the left (**-0.5**), giving us a triangle like so:
|
||||
我们做的事情是,把最上面的顶点 X 坐标移动到左边(也就是变为 `-0.5`),这就变成了像这样的三角形:
|
||||
|
||||
![Conway's Game of Life in OpenGL and Golang Tutorial - Right-Angle Triangle](https://kylewbanks.com/images/post/golang-opengl-conway-4.png)
|
||||
![Conway's Game of Life - 右弦三角形](https://kylewbanks.com/images/post/golang-opengl-conway-4.png)
|
||||
|
||||
Easy enough, right? Now let’s make a square out of two of these. Let’s rename **triangle** to **square** and add a second, inverted right-angle triangle to the slice:
|
||||
很简单,对吧?现在让我们用两个这样的三角形顶点做成正方形。把 `triangle` 重命名为 `square`,然后添加第二个倒置的三角形的顶点数据,把直角三角形变成这样的:
|
||||
|
||||
```
|
||||
square = []float32{
|
||||
@ -41,17 +43,17 @@ square = []float32{
|
||||
}
|
||||
```
|
||||
|
||||
Note: You’ll also need to rename the two references to **triangle** to be **square**, namely in **main** and **draw**.
|
||||
注意:你也要把在 `main` 和 `draw` 里面命名的 `triangle` 改为 `square`。
|
||||
|
||||
Here we’ve doubled the number of points by adding a second set of three vertices to be our upper top-right triangle to complete the square. Run it for glory:
|
||||
我们通过添加三个顶点,把顶点数增加了一倍,这三个顶点就是右上角的三角形,用来拼成方形。运行它看看效果:
|
||||
|
||||
![Conway's Game of Life in OpenGL and Golang Tutorial - Two Triangles Make a Square](https://kylewbanks.com/images/post/golang-opengl-conway-5.png)
|
||||
![Conway's Game of Life - 两个三角形构成方形](https://kylewbanks.com/images/post/golang-opengl-conway-5.png)
|
||||
|
||||
Great, now we have the ability to draw a square! OpenGL isn’t so tough after all, is it?
|
||||
很好,现在我们能够绘制正方形了!OpenGL 一点都不难,对吧?
|
||||
|
||||
### Draw a Grid of Squares covering the Window
|
||||
### 在窗口中绘制方形格子
|
||||
|
||||
Now that we can draw one square, how about 100 of them? Let’s create a **cell** struct to represent each unit of our grid so that we can be flexible in the number of squares we draw:
|
||||
现在我们能画一个方形,怎么画 100 个吗?我们来创建一个 `cell` 结构体,用来表示格子的每一个单元,因此我们能够很灵活的选择绘制的数量:
|
||||
|
||||
```
|
||||
type cell struct {
|
||||
@ -62,9 +64,9 @@ type cell struct {
|
||||
}
|
||||
```
|
||||
|
||||
The **cell** contains a **drawable** which is a square **Vertex Array Object** just like the one we created above, and an X and Y coordinate to dictate where on the grid this cell resides.
|
||||
`cell` 结构体包含一个 `drawable` 属性,这是一个顶点数组对象,就像我们在之前创建的一样,这个结构体还包含 X 和 Y 坐标,用来表示这个格子的位置。
|
||||
|
||||
We’re also going to want two more constants that define the size and shape of our grid:
|
||||
我们还需要两个常量,用来设定格子的大小和形状:
|
||||
|
||||
```
|
||||
const (
|
||||
@ -75,7 +77,7 @@ const (
|
||||
)
|
||||
```
|
||||
|
||||
Now let’s add a function to create the grid:
|
||||
现在我们添加一个创建格子的函数:
|
||||
|
||||
```
|
||||
func makeCells() [][]*cell {
|
||||
@ -91,9 +93,9 @@ func makeCells() [][]*cell {
|
||||
}
|
||||
```
|
||||
|
||||
Here we create a multi-dimensional slice to represent our game’s board, and populate each element of the matrix with a **cell** using a new function called **newCell** which we’ll write in just a moment.
|
||||
这里我们创建多维的<ruby>切片<rt>slice</rt></ruby>,代表我们的游戏面板,用名为 `newCell` 的新函数创建的 `cell` 来填充矩阵的每个元素,我们待会就来实现 `newCell` 这个函数。
|
||||
|
||||
Before moving on, let’s take a moment to visualize what **makeCells** is creating. We’re creating a slice that is equal in length to the number of rows on the grid, and each of these slices contains a slice of cells, equal in length to the number of columns. If we were to define **rows** and **columns** each equal to two, we’d create the following matrix:
|
||||
在接着往下阅读前,我们先花一点时间来看看 `makeCells` 函数做了些什么。我们创造了一个切片,这个切片的长度和格子的行数相等,每一个切片里面都有一个<ruby>细胞<rt>cell</rt></ruby>的切片,这些细胞的数量与列数相等。如果我们把 `rows` 和 `columns` 都设定成 2,那么就会创建如下的矩阵:
|
||||
|
||||
```
|
||||
[
|
||||
@ -102,7 +104,7 @@ Before moving on, let’s take a moment to visualize what **makeCells** is cre
|
||||
]
|
||||
```
|
||||
|
||||
We’re creating a much larger matrix that’s **10x10** cells:
|
||||
还可以创建一个更大的矩阵,包含 `10x10` 个细胞:
|
||||
|
||||
```
|
||||
[
|
||||
@ -119,7 +121,7 @@ We’re creating a much larger matrix that’s **10x10** cells:
|
||||
]
|
||||
```
|
||||
|
||||
Now that the we understand the shape and representation of the matrix we’re creating, let’s have a look at **newCell** which we use to actually populate the matrix:
|
||||
现在应该理解了我们创造的矩阵的形状和表示方法。让我们看看 `newCell` 函数到底是怎么填充矩阵的:
|
||||
|
||||
```
|
||||
func newCell(x, y int) *cell {
|
||||
@ -156,15 +158,15 @@ func newCell(x, y int) *cell {
|
||||
}
|
||||
```
|
||||
|
||||
There’s quite a lot going on in this function so let’s break it down. The first thing we do is create a copy of our **square** definition. This allows us to change its contents to customize the current cell’s position, without impacting any other cells that are also using the **square** slice. Next we iterate over the **points** copy and act based on the current index. We use a modulo operation to determine if we’re at an X (**i % 3 == 0**) or Y (**i % 3 == 1**) coordinate **of the shape** (skipping Z since we’re operating in two dimensions) and determine the size (as a percentage of the entire game board) of the cell accordingly, as well as it’s position based on the X and Y coordinate of the cell **on the game board**.
|
||||
这个函数里有很多内容,我们把它分成几个部分。我们做的第一件事是复制了 `square` 的定义。这让我们能够修改该定义,定制当前的细胞位置,而不会影响其它使用 `square` 切片定义的细胞。然后我们基于当前索引迭代 `points` 副本。我们用求余数的方法来判断我们是在操作 X 坐标(`i % 3 == 0`),还是在操作 Y 坐标(`i % 3 == 1`)(跳过 Z 坐标是因为我们仅在二维层面上进行操作),跟着确定细胞的大小(也就是占据整个游戏面板的比例),当然它的位置是基于细胞在 `相对游戏面板的` X 和 Y 坐标。
|
||||
|
||||
Next, we modify the points which currently contain a combination of **0.5**, **0** and **-0.5** as we defined them in the **square** slice. If the point is less than zero, we set it equal to the position times 2 (because OpenGL coordinates have a range of 2, between **-1** and **1**), minus 1 to normalize to OpenGL coordinates. If the position is greater than or equal to zero, we do the same thing but add the size we calculated.
|
||||
接着,我们改变那些包含在 `square` 切片中定义的 `0.5`,`0`, `-0.5` 这样的点。如果点小于 0,我们就把它设置成原来的 2 倍(因为 OpenGL 坐标的范围在 `-1` 到 `1` 之间,范围大小是 2),减 1 是为了归一化 OpenGL 坐标。如果点大于等于 0,我们的做法还是一样的,不过要加上我们计算出的尺寸。
|
||||
|
||||
The purpose of this is to set the scale of each cell so that it fills only its percentage of the game board. Since we have 10 rows and 10 columns, each cell will be given 10% of the width and 10% of the height of the game board.
|
||||
这样做是为了设置每个细胞的大小,这样它就能只填充它在面板中的部分。因为我们有 10 行 10 列,每一个格子能分到游戏面板的 10% 宽度和高度。
|
||||
|
||||
Finally, after all the points have been scaled and positioned, we create a **cell** with the X and Y coordinate provided, and set the **drawable**field equal to a **Vertex Array Object** created from the **points** slice we just manipulated.
|
||||
最后,确定了所有点的位置和大小,我们用提供的 X 和 Y 坐标创建一个 `cell`,并设置 `drawable` 字段与我们刚刚操作 `points` 得到的顶点数组对象(vao)一致。
|
||||
|
||||
Alright, now in **main** we can remove our call to **makeVao** and replace it with a call to **makeCells**. We’ll also change **draw** to take the matrix of cells instead of a single **vao**:
|
||||
好了,现在我们在 `main` 函数里可以移去对 `makeVao` 的调用了,用 `makeCells` 代替。我们还修改了 `draw`,让它绘制一系列的细胞而不是一个 `vao`。
|
||||
|
||||
```
|
||||
func main() {
|
||||
@ -189,7 +191,7 @@ func draw(cells [][]*cell, window *glfw.Window, program uint32) {
|
||||
}
|
||||
```
|
||||
|
||||
Now we’ll need each cell to know how to draw itself. Let’s add a **draw** function to the **cell**:
|
||||
现在我们要让每个细胞知道怎么绘制出自己。在 `cell` 里面添加一个 `draw` 函数:
|
||||
|
||||
```
|
||||
func (c *cell) draw() {
|
||||
@ -198,9 +200,9 @@ func (c *cell) draw() {
|
||||
}
|
||||
```
|
||||
|
||||
This should look familiar, its nearly identical to how we were drawing the square **vao** in **draw** previously, the only difference being we **BindVertexArray** using **c.drawable**, which is the cell’s **vao** we created in **newCell**.
|
||||
这看上去很熟悉,它很像我们之前在 `vao` 里写的 `draw`,唯一的区别是我们的 `BindVertexArray` 函数用的是 `c.drawable`,这是我们在 `newCell` 中创造的细胞的 `vao`。
|
||||
|
||||
Back in the main **draw** function, we can loop over each cell and have it draw itself:
|
||||
回到 main 中的 `draw` 函数上,我们可以循环每个细胞,让它们自己绘制自己:
|
||||
|
||||
```
|
||||
func draw(cells [][]*cell, window *glfw.Window, program uint32) {
|
||||
@ -218,13 +220,13 @@ func draw(cells [][]*cell, window *glfw.Window, program uint32) {
|
||||
}
|
||||
```
|
||||
|
||||
As you can see we loop over each of the cells and call its **draw** function. If you run the application you should see the following:
|
||||
如你所见,我们循环每一个细胞,调用它的 `draw` 函数。如果运行这段代码,你能看到像下面这样的东西:
|
||||
|
||||
![Conway's Game of Life in OpenGL and Golang Tutorial - Full Grid](https://kylewbanks.com/images/post/golang-opengl-conway-6.png)
|
||||
![Conway's Game of Life - 全部格子](https://kylewbanks.com/images/post/golang-opengl-conway-6.png)
|
||||
|
||||
Is this what you expected? What we’ve done is create a square for each row and column on the grid, and colored it in, effectively filling the entire game board!
|
||||
这是你想看到的吗?我们做的是在格子里为每一行每一列创建了一个方块,然后给它上色,这就填满了整个面板!
|
||||
|
||||
We can see an visualize individual cells by commenting out the for-loop for a moment and doing the following:
|
||||
注释掉 for 循环,我们就可以看到一个明显独立的细胞,像这样:
|
||||
|
||||
```
|
||||
// for x := range cells {
|
||||
@ -236,25 +238,21 @@ We can see an visualize individual cells by commenting out the for-loop for a mo
|
||||
cells[2][3].draw()
|
||||
```
|
||||
|
||||
![Conway's Game of Life in OpenGL and Golang Tutorial - A Single Cell](https://kylewbanks.com/images/post/golang-opengl-conway-7.png)
|
||||
![Conway's Game of Life - 一个单独的细胞](https://kylewbanks.com/images/post/golang-opengl-conway-7.png)
|
||||
|
||||
This draws only the cell located at coordinate **(X=2, Y=3)**. As you can see, each individual cell takes up a small portion of the game board, and is responsible for drawing its own space. We can also see that our game board has its origin, that is the **(X=0, Y=0)** coordinate, in the bottom-left corner of the window. This is simply a result of the way our **newCell** function calculates the position, and could be made to use the top-right, bottom-right, top-left, center, or any other position as its origin.
|
||||
这只绘制坐标在 `(X=2, Y=3)` 的格子。你可以看到,每一个独立的细胞占据着面板的一小块部分,并且负责绘制自己那部分空间。我们也能看到游戏面板有自己的原点,也就是坐标为 `(X=0, Y=0)` 的点,在窗口的左下方。这仅仅是我们的 `newCell` 函数计算位置的方式,也可以用右上角,右下角,左上角,中央,或者其它任何位置当作原点。
|
||||
|
||||
Let’s go ahead and remove the **cells[2][3].draw()** line and uncomment the for-loop, leaving us with the fully drawn grid we had above.
|
||||
接着往下做,移除 `cells[2][3].draw()` 这一行,取消 for 循环的那部分注释,变成之前那样全部绘制的样子。
|
||||
|
||||
### Summary
|
||||
### 总结
|
||||
|
||||
Alright - we can now use two triangles to draw a square, and we have ourselves a game board! We should be proud, we’ve covered a lot of ground up to this point and to be completely honest, the hardest part is behind us now!
|
||||
好了,我们现在能用两个三角形画出一个正方形了,我们还有一个游戏的面板了!我们该为此自豪,目前为止我们已经接触到了很多零碎的内容,老实说,最难的部分还在前面等着我们!
|
||||
|
||||
Next up in [Part 3][16] we’ll implement the core game logic and see some cool simulations!
|
||||
在接下来的第三节,我们会实现游戏核心逻辑,看到很酷的东西!
|
||||
|
||||
_[Part 1: Hello, OpenGL][10]_ | _[Part 2: Drawing the Game Board][11]_ | _[Part 3: Implementing the Game][12]_
|
||||
### 回顾
|
||||
|
||||
_The full source code of the tutorial is available on [GitHub][13]._
|
||||
|
||||
### Checkpoint
|
||||
|
||||
Here’s the contents of **main.go** at this point of the tutorial:
|
||||
这是这一部分教程中 `main.go` 文件的内容:
|
||||
|
||||
```
|
||||
package main
|
||||
@ -389,7 +387,7 @@ func (c *cell) draw() {
|
||||
gl.DrawArrays(gl.TRIANGLES, 0, int32(len(square)/3))
|
||||
}
|
||||
|
||||
// initGlfw initializes glfw and returns a Window to use.
|
||||
// 初始化 glfw,返回一个可用的 Window
|
||||
func initGlfw() *glfw.Window {
|
||||
if err := glfw.Init(); err != nil {
|
||||
panic(err)
|
||||
@ -409,7 +407,7 @@ func initGlfw() *glfw.Window {
|
||||
return window
|
||||
}
|
||||
|
||||
// initOpenGL initializes OpenGL and returns an intiialized program.
|
||||
// 初始化 OpenGL 并返回一个可用的着色器程序
|
||||
func initOpenGL() uint32 {
|
||||
if err := gl.Init(); err != nil {
|
||||
panic(err)
|
||||
@ -434,7 +432,7 @@ func initOpenGL() uint32 {
|
||||
return prog
|
||||
}
|
||||
|
||||
// makeVao initializes and returns a vertex array from the points provided.
|
||||
// 初始化并返回由 points 提供的顶点数组
|
||||
func makeVao(points []float32) uint32 {
|
||||
var vbo uint32
|
||||
gl.GenBuffers(1, &vbo)
|
||||
@ -474,17 +472,17 @@ func compileShader(source string, shaderType uint32) (uint32, error) {
|
||||
return shader, nil
|
||||
}
|
||||
```
|
||||
Let me know if this post was helpful on Twitter [@kylewbanks][20] or down below, and follow me to keep up with future posts!
|
||||
|
||||
让我知道这篇文章对你有没有帮助,在 Twitter [@kylewbanks][20] 或者下方的连接,关注我以便获取最新的文章!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
|
||||
作者:[kylewbanks ][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
作者:[kylewbanks][a]
|
||||
译者:[GitFtuture](https://github.com/GitFuture)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -494,16 +492,16 @@ via: https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-
|
||||
[3]:https://twitter.com/intent/tweet?text=OpenGL%20%26%20Go%20Tutorial%20Part%202%3A%20Drawing%20the%20Game%20Board%20https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-2-drawing-the-game-board%20by%20%40kylewbanks
|
||||
[4]:mailto:?subject=Check%20Out%20%22OpenGL%20%26%20Go%20Tutorial%20Part%202%3A%20Drawing%20the%20Game%20Board%22&body=https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[5]:https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[6]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[6]:https://linux.cn/article-8933-1.html
|
||||
[7]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[8]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game
|
||||
[9]:https://github.com/KyleBanks/conways-gol
|
||||
[10]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[10]:https://linux.cn/article-8933-1.html
|
||||
[11]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
|
||||
[12]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game
|
||||
[13]:https://github.com/KyleBanks/conways-gol
|
||||
[14]:https://twitter.com/kylewbanks
|
||||
[15]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||||
[15]:https://linux.cn/article-8933-1.html
|
||||
[16]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game
|
||||
[17]:https://twitter.com/intent/tweet?text=OpenGL%20%26%20Go%20Tutorial%20Part%202%3A%20Drawing%20the%20Game%20Board%20https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-2-drawing-the-game-board%20by%20%40kylewbanks
|
||||
[18]:mailto:?subject=Check%20Out%20%22OpenGL%20%26%20Go%20Tutorial%20Part%202%3A%20Drawing%20the%20Game%20Board%22&body=https%3A%2F%2Fkylewbanks.com%2Fblog%2Ftutorial-opengl-with-golang-part-2-drawing-the-game-board
|
Binary file not shown.
Before Width: | Height: | Size: 247 KiB |
@ -0,0 +1,453 @@
|
||||
调试器工作原理(二):断点
|
||||
============================================================
|
||||
|
||||
这是调试器工作原理系列文章的第二部分,阅读本文前,请确保你已经读过[第一部分][27]。
|
||||
|
||||
### 关于本文
|
||||
|
||||
我将会演示如何在调试器中实现断点。断点是调试的两大利器之一,另一个是可以在被调试进程的内存中检查变量值。我们在系列的第一部分已经了解过值检查,但是断点对我们来说依然神秘。不过本文过后,它们就不再如此了。
|
||||
|
||||
### 软件中断
|
||||
|
||||
为了在 x86 架构机器上实现断点,软件中断(也被称作“陷阱”)被会派上用场。在我们深入细节之前,我想先大致解释一下中断和陷阱的概念。
|
||||
|
||||
CPU 有一条单独的执行流,一条指令接一条的执行(在更高的层面看是这样的,但是在底层的细节上来说,现在的许多 CPU 都会并行执行多个指令,这其中的一些指令就不是按照原本的顺序执行的)。为了能够处理异步的事件,如 IO 和 硬件定时器,CPU 使用了中断。硬件中断通常是一个特定的电子信号,并附加了一个特别的”响应电路”。该电路通知中断激活,并让 CPU 停止当前执行,保存状态,然后跳转到一个预定义的地址,也就是中断处理程序的位置。当处理程序完成其工作后,CPU 又从之前停止的地方重新恢复运行。
|
||||
|
||||
软件中断在规则上与硬件相似,但实际操作中有些不同。CPU 支持一些特殊的指令,来允许软件模拟出一个中断。当这样的一个指令被执行时,CPU 像对待一个硬件中断那样 —— 停止正常的执行流,保存状态,然后跳转到一个处理程序。这种“中断”使得许多现代 OS 的惊叹设计得以高效地实现(如任务调度,虚拟内存,内存保护,调试)。
|
||||
|
||||
许多编程错误(如被 0 除)也被 CPU 当做中断对待,常常也叫做“异常”, 这时候硬件和软件中断之间的界限就模糊了,很难说这种异常到底是硬件中断还是软件中断。但我已经偏离今天主题太远了,所以现在让我们回到断点上来。
|
||||
|
||||
### int 3 理论
|
||||
|
||||
前面说了很多,现在简单来说断点就是一个部署在 CPU 上的特殊中断,叫 `int 3`。`int` 是一个 “中断指令”的 x86 术语,该指令是对一个预定义中断处理的调用。x86 支持 8 位的 int 指令操作数,这决定了中断的数量,所以理论上可以支持 256 个中断。前 32 个中断为 CPU 自己保留,而 int 3 就是本文关注的 —— 它被叫做 “调试器专用中断”。
|
||||
|
||||
避免更深的解释,我将引用“圣经”里一段话(这里说的“圣经”,当然指的是英特尔的体系结构软件开发者手册, 卷 2A)。
|
||||
|
||||
> INT 3 指令生成一个以字节操作码(CC),用于调用该调试异常处理程序。(这个一字节格式是非常有用的,因为它可以用于使用断点来替换任意指令的第一个字节 ,包括哪些一字节指令,而不会覆写其它代码)
|
||||
|
||||
上述引用非常重要,但是目前去解释它还是为时过早。本文后面我们会回过头再看。
|
||||
|
||||
### int 3 实践
|
||||
|
||||
没错,知道事物背后的理论非常不错,不过,这些理论到底意思是啥?我们怎样使用 `int 3` 部署断点?或者怎么翻译成通用的编程术语 —— _请给我看代码!_
|
||||
|
||||
实际上,实现非常简单。一旦你的程序执行了 `int 3` 指令, OS 就会停止程序( OS 是怎么做到像这样停止进程的? OS 注册其 int 3 的控制程序到 CPU 即可,就这么简单)。在 Linux(这也是本文比较关心的地方) 上, OS 会发送给进程一个信号 —— `SIGTRAP`。
|
||||
|
||||
就是这样,真的。现在回想一下本系列的第一部分, 追踪进程(调试程序) 会得到其子进程(或它所连接的被调试进程)所得到的所有信号的通知,接下来你就知道了。
|
||||
|
||||
就这样, 没有更多的电脑架构基础术语了。该是例子和代码的时候了。
|
||||
|
||||
### 手动设置断点
|
||||
|
||||
现在我要演示在程序里设置断点的代码。我要使用的程序如下:
|
||||
|
||||
```
|
||||
section .text
|
||||
; The _start symbol must be declared for the linker (ld)
|
||||
global _start
|
||||
|
||||
_start:
|
||||
|
||||
; Prepare arguments for the sys_write system call:
|
||||
; - eax: system call number (sys_write)
|
||||
; - ebx: file descriptor (stdout)
|
||||
; - ecx: pointer to string
|
||||
; - edx: string length
|
||||
mov edx, len1
|
||||
mov ecx, msg1
|
||||
mov ebx, 1
|
||||
mov eax, 4
|
||||
|
||||
; Execute the sys_write system call
|
||||
int 0x80
|
||||
|
||||
; Now print the other message
|
||||
mov edx, len2
|
||||
mov ecx, msg2
|
||||
mov ebx, 1
|
||||
mov eax, 4
|
||||
int 0x80
|
||||
|
||||
; Execute sys_exit
|
||||
mov eax, 1
|
||||
int 0x80
|
||||
|
||||
section .data
|
||||
|
||||
msg1 db 'Hello,', 0xa
|
||||
len1 equ $ - msg1
|
||||
msg2 db 'world!', 0xa
|
||||
len2 equ $ - msg2
|
||||
```
|
||||
|
||||
我现在在使用汇编语言,是为了当我们面对 C 代码的时候,能清楚一些编译细节。上面代码做的事情非常简单,就是在一行打印出 “hello,”,然后在下一行打印出 “world!”。这与之前文章中的程序非常类似。
|
||||
|
||||
现在我想在第一次打印和第二次打印之间设置一个断点。我们看到在第一条 `int 0x80` ,其后指令是 `mov edx, len2`。(等等,再次 int?是的,Linux 使用 `int 0x80` 来实现用户进程到系统内核的系统调用。用户将系统调用的号码及其参数放到寄存器,并执行 `int 0x80`。然后 CPU 会跳到相应的中断处理程序,其中, OS 注册了一个过程,该过程查看寄存器并决定要执行的系统调用。)首先,我们需要知道该指令所映射的地址。运行 `objdump -d`:
|
||||
|
||||
```
|
||||
traced_printer2: file format elf32-i386
|
||||
|
||||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn
|
||||
0 .text 00000033 08048080 08048080 00000080 2**4
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
1 .data 0000000e 080490b4 080490b4 000000b4 2**2
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
08048080 <.text>:
|
||||
8048080: ba 07 00 00 00 mov $0x7,%edx
|
||||
8048085: b9 b4 90 04 08 mov $0x80490b4,%ecx
|
||||
804808a: bb 01 00 00 00 mov $0x1,%ebx
|
||||
804808f: b8 04 00 00 00 mov $0x4,%eax
|
||||
8048094: cd 80 int $0x80
|
||||
8048096: ba 07 00 00 00 mov $0x7,%edx
|
||||
804809b: b9 bb 90 04 08 mov $0x80490bb,%ecx
|
||||
80480a0: bb 01 00 00 00 mov $0x1,%ebx
|
||||
80480a5: b8 04 00 00 00 mov $0x4,%eax
|
||||
80480aa: cd 80 int $0x80
|
||||
80480ac: b8 01 00 00 00 mov $0x1,%eax
|
||||
80480b1: cd 80 int $0x80
|
||||
```
|
||||
|
||||
所以,我们要设置断点的地址是 `0x8048096`。等等,这不是调试器工作的真实姿势,对吧?真正的调试器是在代码行和函数上设置断点,而不是赤裸裸的内存地址?完全正确,但是目前我们仍然还没到那一步,为了更像_真正的_调试器一样设置断点,我们仍不得不首先理解一些符号和调试信息。所以现在,我们就得面对内存地址。
|
||||
|
||||
在这点上,我真想又偏离一下主题。所以现在你有两个选择,如果你真的感兴趣想知道_为什么_那个地址应该是 `0x8048096`,它代表着什么,那就看下面的部分。否则你只是想了解断点,你可以跳过这部分。
|
||||
|
||||
### 题外话 —— 程序地址和入口
|
||||
|
||||
坦白说,`0x8048096` 本身没多大意义,仅仅是可执行程序的 text 部分开端偏移的一些字节。如果你看上面导出来的列表,你会看到 text 部分从地址 `0x08048080` 开始。这告诉 OS 在分配给进程的虚拟地址空间里,将该地址映射到 text 部分开始的地方。在 Linux 上面,这些地址可以是绝对地址(例如,当可执行程序加载到内存中时它不做重定位),因为通过虚拟地址系统,每个进程获得自己的一块内存,并且将整个 32 位地址空间看做自己的(称为 “线性” 地址)。
|
||||
|
||||
如果我们使用 `readelf` 命令检查 ELF 文件头部(ELF,可执行和可链接格式,是 Linux 上用于对象文件、共享库和可执行程序的文件格式),我们会看到:
|
||||
|
||||
```
|
||||
$ readelf -h traced_printer2
|
||||
ELF Header:
|
||||
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
|
||||
Class: ELF32
|
||||
Data: 2's complement, little endian
|
||||
Version: 1 (current)
|
||||
OS/ABI: UNIX - System V
|
||||
ABI Version: 0
|
||||
Type: EXEC (Executable file)
|
||||
Machine: Intel 80386
|
||||
Version: 0x1
|
||||
Entry point address: 0x8048080
|
||||
Start of program headers: 52 (bytes into file)
|
||||
Start of section headers: 220 (bytes into file)
|
||||
Flags: 0x0
|
||||
Size of this header: 52 (bytes)
|
||||
Size of program headers: 32 (bytes)
|
||||
Number of program headers: 2
|
||||
Size of section headers: 40 (bytes)
|
||||
Number of section headers: 4
|
||||
Section header string table index: 3
|
||||
```
|
||||
|
||||
注意头部里的 `Entry point address`,它同样指向 `0x8048080`。所以我们在系统层面解释该 elf 文件的编码信息,它意思是:
|
||||
|
||||
1. 映射 text 部分(包含所给的内容)到地址 `0x8048080`
|
||||
2. 从入口 —— 地址 `0x8048080` 处开始执行
|
||||
|
||||
但是,为什么是 `0x8048080` 呢?事实证明是一些历史原因。一些 Google 的结果把我引向源头,宣传每个进程的地址空间的前 128M 是保留在栈里的。128M 对应为 `0x8000000`,该地址是可执行程序其他部分可以开始的地方。而 `0x8048080`,比较特别,是 Linux `ld` 链接器使用的默认入口地址。该入口可以通过给 `ld` 传递 `-Ttext` 参数改变。
|
||||
|
||||
总结一下,这地址没啥特别的,我们可以随意修改它。只要 ELF 可执行文件被合理的组织,并且头部里的入口地址与真正的程序代码(text 部分)开始的地址匹配,一切都没问题。
|
||||
|
||||
### 用 int 3 在调试器中设置断点
|
||||
|
||||
为了在被追踪进程的某些目标地址设置一个断点,调试器会做如下工作:
|
||||
|
||||
1. 记住存储在目标地址的数据
|
||||
2. 用 int 指令替换掉目标地址的第一个字节
|
||||
|
||||
然后,当调试器要求 OS 运行该进程的时候(通过上一篇文章中提过的 `PTRACE_CONT`),进程就会运行起来直到遇到 `int 3`,此处进程会停止运行,并且 OS 会发送一个信号给调试器。调试器会收到一个信号表明其子进程(或者说被追踪进程)停止了。调试器可以做以下工作:
|
||||
|
||||
1. 在目标地址,用原来的正常执行指令替换掉 int 3 指令
|
||||
2. 将被追踪进程的指令指针回退一步。这是因为现在指令指针位于刚刚执行过的 int 3 之后。
|
||||
3. 允许用户以某些方式与进程交互,因为该进程仍然停止在特定的目标地址。这里你的调试器可以让你取得变量值,调用栈等等。
|
||||
4. 当用户想继续运行,调试器会小心地把断点放回目标地址去(因为它在第 1 步时被移走了),除非用户要求取消该断点。
|
||||
|
||||
让我们来看看,这些步骤是如何翻译成具体代码的。我们会用到第一篇里的调试器 “模板”(fork 一个子进程并追踪它)。无论如何,文末会有一个完整样例源代码的链接
|
||||
|
||||
```
|
||||
/* Obtain and show child's instruction pointer */
|
||||
ptrace(PTRACE_GETREGS, child_pid, 0, ®s);
|
||||
procmsg("Child started. EIP = 0x%08x\n", regs.eip);
|
||||
|
||||
/* Look at the word at the address we're interested in */
|
||||
unsigned addr = 0x8048096;
|
||||
unsigned data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
|
||||
procmsg("Original data at 0x%08x: 0x%08x\n", addr, data);
|
||||
```
|
||||
|
||||
这里调试器从被追踪的进程中取回了指令指针,也检查了在 `0x8048096` 的字。当开始追踪运行文章开头的汇编代码,将会打印出:
|
||||
|
||||
```
|
||||
[13028] Child started. EIP = 0x08048080
|
||||
[13028] Original data at 0x08048096: 0x000007ba
|
||||
```
|
||||
|
||||
目前为止都看起来不错。接下来:
|
||||
|
||||
```
|
||||
/* Write the trap instruction 'int 3' into the address */
|
||||
unsigned data_with_trap = (data & 0xFFFFFF00) | 0xCC;
|
||||
ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data_with_trap);
|
||||
|
||||
/* See what's there again... */
|
||||
unsigned readback_data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
|
||||
procmsg("After trap, data at 0x%08x: 0x%08x\n", addr, readback_data);
|
||||
```
|
||||
|
||||
注意到 `int 3` 是如何被插入到目标地址的。此处打印:
|
||||
|
||||
```
|
||||
[13028] After trap, data at 0x08048096: 0x000007cc
|
||||
```
|
||||
|
||||
正如预料的那样 —— `0xba` 被 `0xcc` 替换掉了。现在调试器运行子进程并等待它在断点处停止:
|
||||
|
||||
```
|
||||
/* Let the child run to the breakpoint and wait for it to
|
||||
** reach it
|
||||
*/
|
||||
ptrace(PTRACE_CONT, child_pid, 0, 0);
|
||||
|
||||
wait(&wait_status);
|
||||
if (WIFSTOPPED(wait_status)) {
|
||||
procmsg("Child got a signal: %s\n", strsignal(WSTOPSIG(wait_status)));
|
||||
}
|
||||
else {
|
||||
perror("wait");
|
||||
return;
|
||||
}
|
||||
|
||||
/* See where the child is now */
|
||||
ptrace(PTRACE_GETREGS, child_pid, 0, ®s);
|
||||
procmsg("Child stopped at EIP = 0x%08x\n", regs.eip);
|
||||
```
|
||||
|
||||
这里打印出:
|
||||
|
||||
```
|
||||
Hello,
|
||||
[13028] Child got a signal: Trace/breakpoint trap
|
||||
[13028] Child stopped at EIP = 0x08048097
|
||||
```
|
||||
|
||||
注意到 “Hello,” 在断点前打印出来了 —— 完全如我们计划的那样。同时注意到子进程停止的地方 —— 刚好就是单字节中断指令后面。
|
||||
|
||||
最后,如早先诠释的那样,为了让子进程继续运行,我们得做一些工作。我们用原来的指令替换掉中断指令,并且让进程从这里继续之前的运行。
|
||||
|
||||
```
|
||||
/* Remove the breakpoint by restoring the previous data
|
||||
** at the target address, and unwind the EIP back by 1 to
|
||||
** let the CPU execute the original instruction that was
|
||||
** there.
|
||||
*/
|
||||
ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data);
|
||||
regs.eip -= 1;
|
||||
ptrace(PTRACE_SETREGS, child_pid, 0, ®s);
|
||||
|
||||
/* The child can continue running now */
|
||||
ptrace(PTRACE_CONT, child_pid, 0, 0);
|
||||
```
|
||||
|
||||
这会使子进程继续打印出 “world!”,然后退出。
|
||||
|
||||
注意,我们在这里没有恢复断点。通过在单步调试模式下,运行原来的指令,然后将中断放回去,并且只在运行 PTRACE_CONT 时做到恢复断点。文章稍后会展示 debuglib 如何做到这点。
|
||||
|
||||
### 更多关于 int 3
|
||||
|
||||
现在可以回过头去看看 `int 3` 和因特尔手册里那个神秘的说明,原文如下:
|
||||
|
||||
|
||||
> 这个一字节格式是非常有用的,因为它可以用于使用断点来替换任意指令的第一个字节 ,包括哪些一字节指令,而不会覆写其它代码
|
||||
|
||||
int 指令在 x86 机器上占两个字节 —— `0xcd` 紧跟着中断数(细心的读者可以在上面列出的转储中发现 `int 0x80` 翻译成了 `cd 80`)。`int 3` 被编码为 `cd 03`,但是为其还保留了一个单字节指令 —— `0xcc`。
|
||||
|
||||
为什么这样呢?因为这可以允许我们插入一个断点,而不需要重写多余的指令。这非常重要,考虑下面的代码:
|
||||
|
||||
```
|
||||
.. some code ..
|
||||
jz foo
|
||||
dec eax
|
||||
foo:
|
||||
call bar
|
||||
.. some code ..
|
||||
```
|
||||
|
||||
假设你想在 `dec eax` 这里放置一个断点。这对应一个单字节指令(操作码为 `0x48`)。由于替换断点的指令长于一个字节,我们不得不强制覆盖掉下个指令(`call`)的一部分,这就会篡改 `call` 指令,并很可能导致一些完全不合理的事情发生。这样一来跳转到 `foo` 分支的 `jz foo` 指令会导致什么?就会不在 dec eax 这里停止,CPU 径直去执行后面一些无效的指令了。
|
||||
|
||||
而有了单字节的 `int 3` 指令,这个问题就解决了。 1 字节是在 x86 上面所能找到的最短指令,这样我们可以保证仅改变我们想中断的指令。
|
||||
|
||||
### 封装一些晦涩的细节
|
||||
|
||||
很多上述章节样例代码的底层细节,都可以很容易封装在方便使用的 API 里。我已经做了很多封装的工作,将它们都放在一个叫做 debuglib 的通用库里 —— 文末可以去下载。这里我仅仅是想展示它的用法示例,但是绕了一圈。下面我们将追踪一个用 C 写的程序。
|
||||
|
||||
### 追踪一个 C 程序地址和入口
|
||||
|
||||
目前为止,为了简单,我把注意力放在了目标汇编代码。现在是时候往上一个层次,去看看我们如何追踪一个 C 程序。
|
||||
|
||||
事实证明并不是非常难 —— 找到放置断点位置有一点难罢了。考虑下面样例程序:
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
void do_stuff()
|
||||
{
|
||||
printf("Hello, ");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
do_stuff();
|
||||
printf("world!\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
假设我想在 `do_stuff` 入口处放置一个断点。我会先使用 `objdump` 反汇编一下可执行文件,但是打印出的东西太多。尤其看到很多无用,也不感兴趣的 C 程序运行时的初始化代码。所以我们仅看一下 `do_stuff` 部分:
|
||||
|
||||
```
|
||||
080483e4 <do_stuff>:
|
||||
80483e4: 55 push %ebp
|
||||
80483e5: 89 e5 mov %esp,%ebp
|
||||
80483e7: 83 ec 18 sub $0x18,%esp
|
||||
80483ea: c7 04 24 f0 84 04 08 movl $0x80484f0,(%esp)
|
||||
80483f1: e8 22 ff ff ff call 8048318 <puts@plt>
|
||||
80483f6: c9 leave
|
||||
80483f7: c3 ret
|
||||
```
|
||||
|
||||
那么,我们将会把断点放在 `0x080483e4`,这是 `do_stuff` 第一条指令执行的地方。而且,该函数是在循环里面调用的,我们想要在断点处一直停止执行直到循环结束。我们将会使用 debuglib 来简化该流程,下面是完整的调试函数:
|
||||
|
||||
```
|
||||
void run_debugger(pid_t child_pid)
|
||||
{
|
||||
procmsg("debugger started\n");
|
||||
|
||||
/* Wait for child to stop on its first instruction */
|
||||
wait(0);
|
||||
procmsg("child now at EIP = 0x%08x\n", get_child_eip(child_pid));
|
||||
|
||||
/* Create breakpoint and run to it*/
|
||||
debug_breakpoint* bp = create_breakpoint(child_pid, (void*)0x080483e4);
|
||||
procmsg("breakpoint created\n");
|
||||
ptrace(PTRACE_CONT, child_pid, 0, 0);
|
||||
wait(0);
|
||||
|
||||
/* Loop as long as the child didn't exit */
|
||||
while (1) {
|
||||
/* The child is stopped at a breakpoint here. Resume its
|
||||
** execution until it either exits or hits the
|
||||
** breakpoint again.
|
||||
*/
|
||||
procmsg("child stopped at breakpoint. EIP = 0x%08X\n", get_child_eip(child_pid));
|
||||
procmsg("resuming\n");
|
||||
int rc = resume_from_breakpoint(child_pid, bp);
|
||||
|
||||
if (rc == 0) {
|
||||
procmsg("child exited\n");
|
||||
break;
|
||||
}
|
||||
else if (rc == 1) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
procmsg("unexpected: %d\n", rc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup_breakpoint(bp);
|
||||
}
|
||||
```
|
||||
|
||||
为了避免修改 EIP 标志位和目的进程的内存空间的麻烦,我们仅需要调用 `create_breakpoint`,`resume_from_breakpoint` 和 `cleanup_breakpoint`。让我们来看看追踪上面的 C 代码样例会输出什么:
|
||||
|
||||
```
|
||||
$ bp_use_lib traced_c_loop
|
||||
[13363] debugger started
|
||||
[13364] target started. will run 'traced_c_loop'
|
||||
[13363] child now at EIP = 0x00a37850
|
||||
[13363] breakpoint created
|
||||
[13363] child stopped at breakpoint. EIP = 0x080483E5
|
||||
[13363] resuming
|
||||
Hello,
|
||||
[13363] child stopped at breakpoint. EIP = 0x080483E5
|
||||
[13363] resuming
|
||||
Hello,
|
||||
[13363] child stopped at breakpoint. EIP = 0x080483E5
|
||||
[13363] resuming
|
||||
Hello,
|
||||
[13363] child stopped at breakpoint. EIP = 0x080483E5
|
||||
[13363] resuming
|
||||
Hello,
|
||||
world!
|
||||
[13363] child exited
|
||||
```
|
||||
|
||||
如预期一样!
|
||||
|
||||
### 样例代码
|
||||
|
||||
[这里是][25]本文用到的完整源代码文件。在归档中你可以找到:
|
||||
|
||||
* debuglib.h 和 debuglib.c - 封装了调试器的一些内部工作的示例库
|
||||
* bp_manual.c - 这篇文章开始部分介绍的“手动”设置断点的方法。一些样板代码使用了 debuglib 库。
|
||||
* bp_use_lib.c - 大部分代码使用了 debuglib 库,用于在第二个代码范例中演示在 C 程序的循环中追踪。
|
||||
|
||||
### 引文
|
||||
|
||||
在准备本文的时候,我搜集了如下的资源和文章:
|
||||
|
||||
* [How debugger works][12]
|
||||
* [Understanding ELF using readelf and objdump][13]
|
||||
* [Implementing breakpoints on x86 Linux][14]
|
||||
* [NASM manual][15]
|
||||
* [SO discussion of the ELF entry point][16]
|
||||
* [This Hacker News discussion][17] of the first part of the series
|
||||
* [GDB Internals][18]
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints
|
||||
|
||||
作者:[Eli Bendersky][a]
|
||||
译者:[wi-cuckoo](https://github.com/wi-cuckoo)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://eli.thegreenplace.net/
|
||||
[1]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id1
|
||||
[2]:http://en.wikipedia.org/wiki/Out-of-order_execution
|
||||
[3]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id2
|
||||
[4]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id3
|
||||
[5]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id4
|
||||
[6]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id5
|
||||
[7]:http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
[8]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id6
|
||||
[9]:http://eli.thegreenplace.net/tag/articles
|
||||
[10]:http://eli.thegreenplace.net/tag/debuggers
|
||||
[11]:http://eli.thegreenplace.net/tag/programming
|
||||
[12]:http://www.alexonlinux.com/how-debugger-works
|
||||
[13]:http://www.linuxforums.org/articles/understanding-elf-using-readelf-and-objdump_125.html
|
||||
[14]:http://mainisusuallyafunction.blogspot.com/2011/01/implementing-breakpoints-on-x86-linux.html
|
||||
[15]:http://www.nasm.us/xdoc/2.09.04/html/nasmdoc0.html
|
||||
[16]:http://stackoverflow.com/questions/2187484/elf-binary-entry-point
|
||||
[17]:http://news.ycombinator.net/item?id=2131894
|
||||
[18]:http://www.deansys.com/doc/gdbInternals/gdbint_toc.html
|
||||
[19]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id7
|
||||
[20]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id8
|
||||
[21]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id9
|
||||
[22]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id10
|
||||
[23]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id11
|
||||
[24]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints#id12
|
||||
[25]:https://github.com/eliben/code-for-blog/tree/master/2011/debuggers_part2_code
|
||||
[26]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints
|
||||
[27]:https://linux.cn/article-8418-1.html
|
@ -0,0 +1,218 @@
|
||||
详解 UEFI 模式下安装 Linux
|
||||
============================================================
|
||||
|
||||
> 此页面是免费浏览的,没有烦人的外部广告;然而,我的确花了时间准备,网站托管也花了钱。如果您发现此页面帮到了您,请考虑进行小额[捐款](http://www.rodsbooks.com/linux-uefi/),以帮助保持网站的运行。谢谢!
|
||||
> 原著于 2013/10/19;最后修改于 2015/3/16
|
||||
|
||||
### 引言
|
||||
|
||||
几年来,一种新的固件技术悄然出现,而大多数普通用户对此并无所知。该技术被称为 [ <ruby>可扩展固件接口<rt>Extensible Firmware Interface</rt></ruby>][29](EFI), 或更新一些的统一可扩展固件接口(Unified EFI,UEFI,本质上是 EFI 2.x),它已经开始替代古老的[<ruby>基本输入/输出系统<rt>Basic Input/Output System</rt></ruby>][30](BIOS)固件技术,有经验的计算机用户或多或少都有些熟悉 BIOS。
|
||||
|
||||
本页面是给 Linux 用户使用 EFI 技术的一个快速介绍,其中包括有关开始将 Linux 安装到此类计算机上的建议。不幸的是,EFI 是一个庞杂的话题;EFI 软件本身是复杂的,许多实现有系统特定的怪异行为甚至是缺陷。因此,我无法在一个页面上描述在 EFI 计算机上安装和使用 Linux 的一切知识。我希望你能将本页面作为一个有用的起点,不管怎么说,每个部分以及末尾[参考文献][31]部分的链接可以指引你找到更多的文档。
|
||||
|
||||
### 你的计算机是否使用 EFI 技术?
|
||||
|
||||
EFI 是一种_固件_,意味着它是内置于计算机中处理低级任务的软件。最重要的是,固件控制着计算机的引导过程,反过来说这代表着基于 EFI 的计算机与基于 BIOS 的计算机的引导过程不同。(有关此规律的例外之处稍后再说。)这种差异可能使操作系统安装介质的设计超级复杂化,但是一旦安装好并运行之后,它对计算机的日常操作几乎没有影响。请注意,大多数制造商使用术语 “BIOS” 来表示他们的 EFI。我认为这种用法很混乱,所以我避免了;在我看来,EFI 和 BIOS 是两种不同类型的固件。
|
||||
|
||||
> **注意:**苹果公司的 Mac 使用的 EFI 在许多方面是不同寻常的。尽管本页面的大部分内容同样适用于 Mac,但有些细节上的出入,特别是在设置 EFI 引导加载程序的时候。这个任务最好在 OS X 上进行,使用 Mac 的 [bless utility][49]工具,我不在此做过多描述。
|
||||
|
||||
自从 2006 年第一次推出以来,EFI 已被用于基于英特尔的 Mac 上。从 2012 年底开始,大多数安装 Windows 8 或更高版本系统的计算机就已经默认使用 UEFI 启动,实际上大多数 PC 从 2011 年中期就开始使用 UEFI,虽然默认情况下它们可能无法以 EFI 模式启动。2011 年前销出的 PC 也有一些支持 EFI,尽管它们大都默认使用 BIOS 模式启动。
|
||||
|
||||
如果你不确定你的计算机是否支持 EFI,则应查看固件设置实用程序和参考用户手册关于 _EFI_、_UEFI_ 以及 _legacy booting_ 的部分。(可以通过搜索用户手册的 PDF 文件来快速了解。)如果你没有找到类似的参考,你的计算机可能使用老式的(“legacy”) BIOS 引导;但如果你找到了这些术语的参考,几乎可以肯定它使用了 EFI 技术。你还可以尝试_只_有 EFI 模式的引导加载器的安装介质。使用 [rEFInd][50] 制作的 USB 闪存驱动器或 CD-R 镜像是用来测试不错的选择。
|
||||
|
||||
在继续之前,你应当了解大多数 x86 和 x86-64 架构的计算机上的 EFI 都包含一个叫做<ruby>兼容支持模块<rt>Compatibility Support Module</rt></ruby>(CSM)的组件,这使得 EFI 能够使用旧的 BIOS 风格的引导机制来引导操作系统。这会非常方便,因为它向后兼容;但是这样也导致一些意外情况的发生,因为计算机不论以 EFI 模式引导还是以 BIOS (也称为 CSM 或 legacy)模式引导,在控制时没有标准的使用规范和用户界面。特别地,你的 Linux 安装介质非常容易意外的以 BIOS/CSM/legacy 模式启动,这会导致 Linux 以 BIOS/CSM/legacy 模式安装。如果 Linux 是唯一的操作系统,也可以正常工作,但是如果与在 EFI 模式下的 Windows 组成双启动的话,就会非常复杂。(反过来问题也可能发生。)以下部分将帮助你以正确模式引导安装程序。如果你在阅读这篇文章之前就已经以 BIOS 模式安装了 Linux,并且希望切换引导模式,请阅读后续章节,[哎呀:将传统模式下安装的引导转为 EFI 模式下的引导][51]。
|
||||
|
||||
UEFI 的一个附加功能值得一提:<ruby>安全启动<rt>Secure Boot</rt></ruby>。此特性旨在最大限度的降低计算机受到 _boot kit_ 病毒感染的风险,这是一种感染计算机引导加载程序的恶意软件。Boot kits 很难检测和删除,阻止它们的运行刻不容缓。微软公司要求所有带有支持 Windows 8 标志的台式机和笔记本电脑启用 安全启动。这一配置使 Linux 的安装变得复杂,尽管有些发行版可以较好的处理这个问题。不要将安全启动和 EFI 或 UEFI 混淆;支持 EFI 的计算机不一定支持 安全启动,而且支持 EFI 的 x86-64 的计算机也可以禁用 安全启动。微软同意用户在 Windows 8 认证的 x86 和 x86-64 计算机上禁用安全启动功能;然而对装有 Windows 8 的 ARM 计算机而言却相反,它们必须**不允许**用户禁用 安全启动。幸运的是,基于 ARM 的 Windows 8 计算机目前很少见。我建议避免使用它们。
|
||||
|
||||
### 你的发行版是否支持 EFI 技术?
|
||||
|
||||
大多数 Linux 发行版已经支持 EFI 好多年了。然而,不同的发行版对 EFI 的支持程度不同。大多数主流发行版(Fedora,OpenSUSE,Ubuntu 等)都能很好的支持 EFI,包括对安全启动的支持。另外一些“自行打造”的发行版,比如 Gentoo,对 EFI 的支持较弱,但它们的性质使其很容易添加 EFI 支持。事实上,可以向_任意_ Linux 发行版添加 EFI 支持:你需要安装 Linux(即使在 BIOS 模式下),然后在计算机上安装 EFI 引导加载程序。有关如何执行此操作的信息,请参阅[哎呀:将传统模式下安装的引导转为 EFI 模式下的引导][52]部分。
|
||||
|
||||
你应当查看发行版的功能列表,来确定它是否支持 EFI。你还应当注意你的发行版对安全启动的支持情况,特别是如果你打算和 Windows 8 组成双启动。请注意,即使正式支持安全启动的发行版也可能要求禁用此功能,因为 Linux 对安全启动的支持通常很差劲,或者导致意外情况的发生。
|
||||
|
||||
### 准备安装 Linux
|
||||
|
||||
下面几个准备步骤有助于在 EFI 计算机上 Linux 的安装,使其更加顺利:
|
||||
|
||||
#### 1、 升级固件
|
||||
|
||||
有些 EFI 是有问题的,不过硬件制造商偶尔会发布其固件的更新。因此我建议你将固件升级到最新可用的版本。如果你从论坛的帖子知道自己计算机的 EFI 有问题,你应当在安装 Linux 之前更新它,因为如果安装 Linux 之后更新固件,会有些问题需要额外的操作才能解决。另一方面,升级固件是有一定风险的,所以如果制造商提供了 EFI 支持,最好的办法就是按它们提供的方式进行升级。
|
||||
|
||||
#### 2、 了解如何使用固件
|
||||
|
||||
通常你可以通过在引导过程之初按 Del 键或功能键进入固件设置实用程序。按下开机键后尽快查看相关的提示信息,或者尝试每个功能键。类似的,ESC 键或功能键通常可以进入固件的内置引导管理器,可以选择要进入的操作系统或外部设备。一些制造商把这些设置隐藏的很深。在某些情况下,如[此页面][32]所述,你可以在 Windows 8 内做到这些。
|
||||
|
||||
#### 3、调整以下固件设置
|
||||
|
||||
* **快速启动** — 此功能可以通过在硬件初始化时使用快捷方式来加快引导过程。这很好用,但有时候会使 USB 设备不能初始化,导致计算机无法从 USB 闪存驱动器或类似的设备启动。因此禁用快速启动_可能_有一定的帮助,甚至是必须的;你可以让它保持激活,而只在 Linux 安装程序启动遇到问题时将其停用。请注意,此功能有时可能会以其它名字出现。在某些情况下,你必须_启用_ USB 支持,而不是_禁用_快速启动功能。
|
||||
* **安全启动** — Fedora,OpenSUSE,Ubuntu 以及其它的发行版官方就支持安全启动;但是如果在启动引导加载程序或内核时遇到问题,可能需要禁用此功能。不幸的是,没办法具体描述怎么禁用,因为不同计算机的设置方法也不同。请参阅[我的安全启动页面][1]获取更多关于此话题的信息。
|
||||
|
||||
> **注意:** 一些教程说安装 Linux 时需要启用 BIOS/CSM/legacy 支持。通常情况下,这样做是错的。启用这些支持可以解决启动安装程序涉及的问题,但也会带来新的问题。以这种方式安装的教程通常可以通过“引导修复”来解决这些问题,但最好从一开始就做对。本页面提供了帮助你以 EFI 模式启动 Linux 安装程序的提示,从而避免以后的问题。
|
||||
* **CSM/legacy 选项** — 如果你想以 EFI 模式安装,请_关闭_这些选项。一些教程推荐启用这些选项,有时这是必须的 —— 比如,有些附加视频卡需要在固件中启用 BIOS 模式。尽管如此,大多数情况下启用 CSM/legacy 支持只会无意中增加以 BIOS 模式启动 Linux 的风险,但你并_不想_这样。请注意,安全启动和 CSM/legacy 选项有时会交织在一起,因此更改任一选项之后务必检查另一个。
|
||||
|
||||
#### 4、 禁用 Windows 的快速启动功能
|
||||
|
||||
[这个页面][33]描述了如何禁用此功能,不禁用的话会导致文件系统损坏。请注意此功能与固件的快速启动不同。
|
||||
|
||||
#### 5、 检查分区表
|
||||
|
||||
使用 [GPT fdisk][34]、parted 或其它任意分区工具检查磁盘分区。理想情况下,你应该创建一个包含每个分区确切起点和终点(以扇区为单位)的纸面记录。这会是很有用的参考,特别是在安装时进行手动分区的时候。如果已经安装了 Windows,确定可以识别你的 [EFI 系统分区(ESP)][35],它是一个 FAT 分区,设置了“启动标记”(在 parted 或 Gparted 中)或在 gdisk 中的类型码为 EF00。
|
||||
|
||||
### 安装 Linux
|
||||
|
||||
大部分 Linux 发行版都提供了足够的安装说明;然而我注意到了在 EFI 模式安装中的几个常见的绊脚石:
|
||||
|
||||
* **确保使用正确位深的发行版** — EFI 启动加载器和 EFI 自身的位深相同。现代计算机通常是 64 位,尽管最初几代基于 Intel 的 Mac、一些现代的平板电脑和变形本、以及一些鲜为人知的电脑使用 32 位 EFI。虽然可以将 32 位 EFI 引导加载程序添加至 32 位发行版,但我还没有遇到过正式支持 32 位 EFI 的 Linux 发行版。(我的 《[在 Linux 上管理 EFI 引导加载程序][36]》 一文概述了引导加载程序,而且理解了这些原则你就可以修改 32 位发行版的安装程序,尽管这不是一个初学者该做的。)在 64 位 EFI 的计算机上安装 32 位发行版最让人头疼,我不准备在这里描述这一过程;在具有 64 位 EFI 的计算机上,你应当使用 64 位的发行版。
|
||||
* **正确准备引导介质** — 将 .iso 镜像传输到 USB 闪存驱动器的第三方工具,比如 unetbootin,在创建正确的 EFI 模式引导项时经常失败。我建议按照发行版维护者的建议来创建 USB 闪存驱动器。如果没有类似的建议,使用 Linux 的 dd 工具,通过执行 `dd if=image.iso of=/dev/sdc` 在识别为 `/dev/sdc` 的 USB 闪存驱动器上创建一个镜像。至于 Windows,有 [WinDD][37] 和 [dd for windows][38],但我从没测试过它们。请注意,使用不兼容 EFI 的工具创建安装介质是错误的,这会导致人们进入在 BIOS 模式下安装然后再纠正它们的误区,所以不要忽视这一点!
|
||||
* **备份 ESP 分区** — 如果计算机已经存在 Windows 或者其它的操作系统,我建议在安装 Linux 之前备份你的 ESP 分区。尽管 Linux _不应该_ 损坏 ESP 分区已有的文件,但似乎这时不时发生。发生这种事情时备份会有很大用处。只需简单的文件级的备份(使用 cp,tar,或者 zip 类似的工具)就足够了。
|
||||
* **以 EFI 模式启动** — 以 BIOS/CSM/legacy 模式引导 Linux 安装程序的意外非常容易发生,特别是当固件启用 CSM/legacy 选项时。下面一些提示可以帮助你避免此问题:
|
||||
* 进入 Linux shell 环境执行 `ls /sys/firmware/efi` 验证当前是否处于 EFI 引导模式。如果你看到一系列文件和目录,表明你已经以 EFI 模式启动,而且可以忽略以下多余的提示;如果没有,表明你是以 BIOS 模式启动的,应当重新检查你的设置。
|
||||
* 使用固件内置的引导管理器(你应该已经知道在哪;请参阅[了解如何使用固件][26])使之以 EFI 模式启动。一般你会看到 CD-R 或 USB 闪存驱动器两个选项,其中一个选项包括 _EFI_ 或 _UEFI_ 字样的描述,另一个不包括。使用 EFI/UEFI 选项来启动介质。
|
||||
* 禁用安全启动 - 即使你使用的发行版官方支持安全启动,有时它们也不能生效。在这种情况下,计算机会静默的转到下一个引导加载程序,它可能是启动介质的 BIOS 模式的引导加载程序,导致你以 BIOS 模式启动。请参阅我的[安全启动的相关文章][27]以得到禁用安全启动的相关提示。
|
||||
* 如果 Linux 安装程序总是无法以 EFI 模式启动,试试用我的 [rEFInd 引导管理器][28] 制作的 USB 闪存驱动器或 CD-R。如果 rEFInd 启动成功,那它保证是以 EFI 模式运行的,而且在基于 UEFI 的 PC 上,它只显示 EFI 模式的引导项,因此若您启动到 Linux 安装程序,则应处于 EFI 模式。(但是在 Mac 上,除了 EFI 模式选项之外,rEFInd 还显示 BIOS 模式的引导项。)
|
||||
* **准备 ESP 分区** — 除了 Mac,EFI 使用 ESP 分区来保存引导加载程序。如果你的计算机已经预装了 Windows,那么 ESP 分区就已存在,可以在 Linux 上直接使用。如果不是这样,那么我建议创建一个大小为 550 MB 的 ESP 分区。(如果你已有的 ESP 分区比这小,别担心,直接用就行。)在此分区上创建一个 FAT32 文件系统。如果你使用 Gparted 或者 parted 准备 ESP 分区,记得给它一个“启动标记”。如果你使用 GPT fdisk(gdisk,cgdisk 或 sgdisk)准备 ESP 分区,记得给它一个名为 EF00 的类型码。有些安装程序会创建一个较小的 ESP 分区,并且设置为 FAT16 文件系统。尽管这样能正常工作,但如果你之后需要重装 Windows,安装程序会无法识别 FAT16 文件系统的 ESP 分区,所以你需要将其备份后转为 FAT32 文件系统。
|
||||
* **使用 ESP 分区** — 不同发行版的安装程序以不同的方式辨识 ESP 分区。比如,Debian 和 Ubuntu 的某些版本把 ESP 分区称为“EFI boot partition”,而且不会明确显示它的挂载点(尽管它会在后台挂载);但是有些发行版,像 Arch 或 Gentoo,需要你去手动挂载。尽管将 ESP 分区挂载到 /boot 进行相应配置后可以正常工作,特别是当你想使用 gummiboot 或 ELILO(译者注:gummiboot 和 ELILO 都是 EFI 引导工具)时,但是在 Linux 中最标准的 ESP 分区挂载点是 /boot/efi。某些发行版的 /boot 不能用 FAT 分区。因此,当你设置 ESP 分区挂载点时,请将其设置为 /boot/efi。除非 ESP 分区没有,否则_不要_为其新建文件系统 — 如果已经安装 Windows 或其它操作系统,它们的引导文件都在 ESP 分区里,新建文件系统会销毁这些文件。
|
||||
* **设置引导程序的位置** — 某些发行版会询问将引导程序(GRUB)装到何处。如果 ESP 分区按上述内容正确标记,不必理会此问题,但有些发行版仍会询问。请尝试使用 ESP 分区。
|
||||
* **其它分区** — 除了 ESP 分区,不再需要其它的特殊分区;你可以设置 根(/)分区,swap 分区,/home 分区,或者其它分区,就像你在 BIOS 模式下安装时一样。请注意 EFI 模式下_不需要设置_[BIOS 启动分区][39],所以如果安装程序提示你需要它,意味着你可能意外的进入了 BIOS 模式。另一方面,如果你创建了 BIOS 启动分区,会更灵活,因为你可以安装 BIOS 模式下的 GRUB,然后以任意模式(EFI 模式 或 BIOS 模式)引导。
|
||||
* **解决无显示问题** — 2013 年,许多人在 EFI 模式下经常遇到(之后出现的频率逐渐降低)无显示的问题。有时可以在命令行下通过给内核添加 `nomodeset` 参数解决这一问题。在 GRUB 界面按 `e` 键会打开一个简易文本编辑器。大多数情况下你需要搜索有关此问题的更多信息,因为此问题更多是由特定硬件引起的。
|
||||
|
||||
在某些情况下,你可能不得不以 BIOS 模式安装 Linux。但你可以手动安装 EFI 引导程序让 Linux 以 EFI 模式启动。请参阅《 [在 Linux 上管理 EFI 引导加载程序][53]》 页面获取更多有关它们以及如何安装的可用信息。
|
||||
|
||||
### 解决安装后的问题
|
||||
|
||||
如果 Linux 无法在 EFI 模式下工作,但在 BIOS 模式下成功了,那么你可以完全放弃 EFI 模式。在只有 Linux 的计算机上这非常简单;安装 BIOS 引导程序即可(如果你是在 BIOS 模式下安装的,引导程序也应随之装好)。如果是和 EFI 下的 Windows 组成双系统,最简单的方法是安装我的 [rEFInd 引导管理器][54]。在 Windows 上安装它,然后编辑 `refind.conf` 文件:取消注释 `scanfor` 一行,并确保拥有 `hdbios` 选项。这样 rEFInd 在引导时会重定向到 BIOS 模式的引导项。
|
||||
|
||||
如果重启后计算机直接进入了 Windows,很可能是 Linux 的引导程序或管理器安装不正确。(但是应当首先尝试禁用安全启动;之前提到过,它经常引发各种问题。)下面是关于此问题的几种可能的解决方案:
|
||||
|
||||
* **使用 efibootmgr** — 你可以以 _EFI 模式_引导一个 Linux 急救盘,使用 efibootmgr 实用工具尝试重新注册你的 Linux 引导程序,如[这里][40]所述。
|
||||
* **使用 Windows 上的 bcdedit** — 在 Windows 管理员命令提示符窗口中,输入 `bcdedit /set {bootmgr}path \EFI\fedora\grubx64.efi` 会用 ESP 分区的 `EFI/fedora/grubx64.efi` 文件作为默认的引导加载程序。根据需要更改此路径,指向你想设置的引导文件。如果你启用了安全启动,需要设置 `shim.efi`,`shimx64.efi` 或者 `PreLoader.efi`(不管有哪个)为引导而不是 `grubx64.efi`。
|
||||
* **安装 rEFInd** — 有时候 rEFInd 可以解决这个问题。我推荐使用 [CD-R 或者 USB 闪存驱动器][41]进行测试。如果 Linux 可以启动,就安装 Debian 软件包、RPM 程序,或者 .zip 文件包。(请注意,你需要在一个高亮的 Linux vmlinuz* 选项按两次 `F2` 或 `Insert` 修改启动选项。如果你的启动分区是单独的,这就更有必要了,因为这种情况下,rEFInd 无法找到根(/)分区,也就无法传递参数给内核。)
|
||||
* **使用修复引导程序** — Ubuntu 的[引导修复实用工具][42]可以自动修复一些问题;然而,我建议只在 Ubuntu 和 密切相关的发行版上使用,比如 Mint。有时候,有必要通过高级选项备份并替换 Windows 的引导。
|
||||
* **劫持 Windows 引导程序** — 有些不完整的 EFI 引导只能引导 Windows,就是 ESP 分区上的 `EFI/Microsoft/Boot/bootmgfw.efi` 文件。因此,你可能需要将引导程序改名(我建议将其移动到上级目录 `EFI/Microsoft/bootmgfw.efi`),然后将首选引导程序复制到这里。(大多数发行版会在 EFI 的子目录放置 GRUB 的副本,例如 Ubuntu 的 EFI/ubuntu,Fedora 的 EFI/fedora。)请注意此方法是个丑陋的解决方法,有用户反映 Windows 会替换引导程序,所以这个办法不是 100% 有效。然而,这是在不完整的 EFI 上生效的唯一办法。在尝试之前,我建议你升级固件并重新注册自己的引导程序,Linux 上用 efibootmgr,Windows 上用 bcdedit。
|
||||
|
||||
有关引导程序的其它类型的问题 - 如果 GRUB(或者你的发行版默认的其它引导程序或引导管理器)没有引导操作系统,你必须修复这个问题。因为 GRUB 2 引导 Windows 时非常挑剔,所以 Windows 经常启动失败。在某些情况下,安全启动会加剧这个问题。请参阅[我的关于 GRUB 2 的页面][55]获取一个引导 Windows 的 GRUB 2 示例。还会有很多原因导致 Linux 引导出现问题,类似于 BIOS 模式下的情况,所以我没有全部写出来。
|
||||
|
||||
尽管 GRUB 2 使用很普遍,但我对它的评价却不高 - 它很复杂,而且难以配置和使用。因此,如果你在使用 GRUB 的时候遇到了问题,我的第一反应就是用别的东西代替。[我的用于 Linux 的 EFI 引导程序页面][56]有其它的选择。其中包括我的 [rEFInd 引导管理器][57],它除了能够让许多发行版上的 GRUB 2 工作,也更容易安装和维护 - 但是它还不能完全代替 GRUB 2。
|
||||
|
||||
除此之外,EFI 引导的问题可能很奇怪,所以你需要去论坛发帖求助。尽量将问题描述完整。[Boot Info Script][58] 可帮助你提供有用的信息 - 运行此脚本,将生成的名为 RESULTS.txt 的文件粘贴到论坛的帖子上。一定要将文本粘贴到 `[code]` 和 `[/code]` 之间;不然会遭人埋怨。或者将 RESULTS.txt 文件上传到 pastebin 网站上,比如 [pastebin.com][59],然后将网站给你的 URL 地址发布到论坛。
|
||||
|
||||
### 哎呀:将传统模式下安装的系统转为 EFI 模式下引导
|
||||
|
||||
**警告:**这些指南主要用于基于 UEFI 的 PC。如果你的 Mac 已经安装了 BIOS 模式下的 Linux,但想以 EFI 模式启动 Linux,可以_在 OS X_ 中安装引导程序。rEFInd(或者旧式的 rEFIt)是 Mac 上的常用选择,但 GRUB 可以做的更多。
|
||||
|
||||
论坛上有很多人看了错误的教程,在已经存在 EFI 模式的 Windows 的情况下,安装了 BIOS 引导的 Linux,这一问题在 2015 年初很普遍。这样配置效果很不好,因为大多数 EFI 很难在两种模式之间切换,而且 GRUB 也无法胜任这项工作。你可能会遇到不完善的 EFI 无法启动外部介质的情况,也可能遇到 EFI 模式下的显示问题,或者其它问题。
|
||||
|
||||
如前所述,在[解决安装后的问题][60]部分,解决办法之一就是_在 Windows_ 上安装 rEFInd,将其配置为支持 BIOS 模式引导。然后可以引导 rEFInd 并链式引导到你的 BIOS 模式的 GRUB。在 Linux 上遇到 EFI 特定的问题时,例如无法使用显卡,我建议你使用这个办法修复。如果你没有这样的 EFI 特定的问题,在 Windows 中安装 rEFInd 和合适的 EFI 文件系统驱动可以让 Linux 直接以 EFI 模式启动。这个解决方案很完美,它和我下面描述的内容等同。
|
||||
|
||||
大多数情况下,最好将 Linux 配置为以 EFI 模式启动。有很多办法可以做到,但最好的是使用 Linux 的 EFI 引导模式(或者,可以想到,Windows,或者一个 EFI shell)注册到你首选的引导管理器。实现这一目标的方法如下:
|
||||
|
||||
1. 下载适用于 USB 闪存驱动器或 CD-R 的 [rEFInd 引导管理器][43]。
|
||||
2. 从下载的镜像文件生成安装介质。可以在任何计算机上准备,不管是 EFI 还是 BIOS 的计算机都可以(或者在其它平台上使用其它方法)。
|
||||
3. 如果你还没有这样做,[请禁用安全启动][44]。因为 rEFInd CD-R 和 USB 镜像不支持安全启动,所以这很必要,你可以在以后重新启用它。
|
||||
4. 在目标计算机上启动 rEFInd。如前所述,你可能需要调整固件设置,并使用内置引导管理器选择要引导的介质。你选择的那一项也许在其描述中包含 _UEFI_ 这样的字符串。
|
||||
5. 在 rEFInd 上测试引导项。你应该至少看到一个启动 Linux 内核的选项(名字含有 vmlinuz 这样的字符串)。有两种方法可以启动它:
|
||||
* 如果你_没有_独立的 `/boot` 分区,只需简单的选择内核并按回车键。Linux 就会启动。
|
||||
* 如果你_确定有_一个独立的 `/boot` 分区,按两次 `Insert` 或 `F2` 键。这样会打开一个行编辑器,你可以用它来编辑内核选项。增加一个 `root=` 格式以标识根(/)文件系统,如果根(/)分区在 `/dev/sda5` 上,就添加 `root=/dev/sda5`。如果不知道根文件系统在哪里,那你需要重启并尽可能想到办法。
|
||||
|
||||
在一些罕见的情况下,你可能需要添加其它内核选项来代替或补充 `root=` 选项。比如配置了 LVM(LCTT 译注:Logical Volume Manager,逻辑卷管理)的 Gentoo 就需要 `dolvm` 选项。
|
||||
6. Linux 一旦启动,安装你想要的引导程序。rEFInd 的安装很简单,可以通过 RPM、Debian 软件包、PPA,或从[rEFInd 下载页面][45]下载的二进制 .zip 文件进行安装。在 Ubuntu 和相关的发行版上,引导修改程序可以相对简单地修复你的 GRUB 设置,但你要对它有信心可以正常工作。(它通常工作良好,但有时候会把事情搞得一团糟。)另外一些选项都在我的 《[在 Linux 上管理 EFI 引导加载程序][46]》 页面上。
|
||||
7. 如果你想在安全启动激活的情况下引导,只需重启并启用它。但是,请注意,可能需要额外的安装步骤才能将引导程序设置为使用安全启动。有关详细信息,请参阅[我关于这个主题的页面][47]或你的引导程序有关安全启动的文档资料。
|
||||
|
||||
重启时,你可以看到刚才安装的引导程序。如果计算机进入了 BIOS 模式下的 GRUB,你应当进入固件禁用 BIOS/CSM/legacy 支持,或调整引导顺序。如果计算机直接进入了 Windows,那么你应当阅读前一部分,[解决安装后的问题][61]。
|
||||
|
||||
你可能想或需要调整你的配置。通常是为了看到额外的引导选项,或者隐藏某些选项。请参阅引导程序的文档资料,以了解如何进行这些更改。
|
||||
|
||||
### 参考和附加信息
|
||||
|
||||
* **信息网页**
|
||||
* 我的 《[在 Linux 上管理 EFI 引导加载程序][2]》 页面含有可用的 EFI 引导程序和引导管理器。
|
||||
* [OS X's bless tool 的手册页][3] 页面在设置 OS X 平台上的引导程序或引导管理器时可能会很有用。
|
||||
* [EFI 启动过程][4] 描述了 EFI 启动时的大致框架。
|
||||
* [Arch Linux UEFI wiki page][5] 有大量关于 UEFI 和 Linux 的详细信息。
|
||||
* 亚当·威廉姆森写的一篇不错的 《[什么是 EFI,它是怎么工作的][6]》。
|
||||
* [这个页面][7] 描述了如何从 Windows 8 调整 EFI 的固件设置。
|
||||
* 马修·J·加勒特是 Shim 引导程序的开发者,此程序支持安全启动,他维护的[博客][8]经常更新有关 EFI 的问题。
|
||||
* 如果你对 EFI 软件的开发感兴趣,我的 《[EFI 编程][9]》 页面可以为你起步助力。
|
||||
* **附加程序**
|
||||
* [rEFInd 官网][10]
|
||||
* [gummiboot 官网][11]
|
||||
* [ELILO 官网][12]
|
||||
* [GRUB 官网][13]
|
||||
* [GPT fdisk 分区软件官网][14]
|
||||
* Ubuntu 的 [引导修复实用工具][15]可帮助解决一些引启动问题
|
||||
* **交流**
|
||||
* [Sourceforge 上的 rEFInd 交流论坛][16]是 rEFInd 用户互相交流或与我联系的一种方法。
|
||||
* Pastebin 网站,比如 [http://pastebin.com][17], 是在 Web 论坛上与其他用户交换大量文本的一种便捷的方法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.rodsbooks.com/linux-uefi/
|
||||
|
||||
作者:[Roderick W. Smith][a]
|
||||
译者:[fuowang](https://github.com/fuowang)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:rodsmith@rodsbooks.com
|
||||
[1]:http://www.rodsbooks.com/efi-bootloaders/secureboot.html#disable
|
||||
[2]:http://www.rodsbooks.com/efi-bootloaders/
|
||||
[3]:http://ss64.com/osx/bless.html
|
||||
[4]:http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
|
||||
[5]:https://wiki.archlinux.org/index.php/Unified_Extensible_Firmware_Interface
|
||||
[6]:https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/
|
||||
[7]:http://www.eightforums.com/tutorials/20256-uefi-firmware-settings-boot-inside-windows-8-a.html
|
||||
[8]:http://mjg59.dreamwidth.org/
|
||||
[9]:http://www.rodsbooks.com/efi-programming/
|
||||
[10]:http://www.rodsbooks.com/refind/
|
||||
[11]:http://freedesktop.org/wiki/Software/gummiboot
|
||||
[12]:http://elilo.sourceforge.net/
|
||||
[13]:http://www.gnu.org/software/grub/
|
||||
[14]:http://www.rodsbooks.com/gdisk/
|
||||
[15]:https://help.ubuntu.com/community/Boot-Repair
|
||||
[16]:https://sourceforge.net/p/refind/discussion/
|
||||
[17]:http://pastebin.com/
|
||||
[18]:http://www.rodsbooks.com/linux-uefi/#intro
|
||||
[19]:http://www.rodsbooks.com/linux-uefi/#isitefi
|
||||
[20]:http://www.rodsbooks.com/linux-uefi/#distributions
|
||||
[21]:http://www.rodsbooks.com/linux-uefi/#preparing
|
||||
[22]:http://www.rodsbooks.com/linux-uefi/#installing
|
||||
[23]:http://www.rodsbooks.com/linux-uefi/#troubleshooting
|
||||
[24]:http://www.rodsbooks.com/linux-uefi/#oops
|
||||
[25]:http://www.rodsbooks.com/linux-uefi/#references
|
||||
[26]:http://www.rodsbooks.com/linux-uefi/#using_firmware
|
||||
[27]:http://www.rodsbooks.com/efi-bootloaders/secureboot.html#disable
|
||||
[28]:http://www.rodsbooks.com/refind/getting.html
|
||||
[29]:https://en.wikipedia.org/wiki/Uefi
|
||||
[30]:https://en.wikipedia.org/wiki/BIOS
|
||||
[31]:http://www.rodsbooks.com/linux-uefi/#references
|
||||
[32]:http://www.eightforums.com/tutorials/20256-uefi-firmware-settings-boot-inside-windows-8-a.html
|
||||
[33]:http://www.eightforums.com/tutorials/6320-fast-startup-turn-off-windows-8-a.html
|
||||
[34]:http://www.rodsbooks.com/gdisk/
|
||||
[35]:http://en.wikipedia.org/wiki/EFI_System_partition
|
||||
[36]:http://www.rodsbooks.com/efi-bootloaders
|
||||
[37]:https://sourceforge.net/projects/windd/
|
||||
[38]:http://www.chrysocome.net/dd
|
||||
[39]:https://en.wikipedia.org/wiki/BIOS_Boot_partition
|
||||
[40]:http://www.rodsbooks.com/efi-bootloaders/installation.html
|
||||
[41]:http://www.rodsbooks.com/refind/getting.html
|
||||
[42]:https://help.ubuntu.com/community/Boot-Repair
|
||||
[43]:http://www.rodsbooks.com/refind/getting.html
|
||||
[44]:http://www.rodsbooks.com/efi-bootloaders/secureboot.html#disable
|
||||
[45]:http://www.rodsbooks.com/refind/getting.html
|
||||
[46]:http://www.rodsbooks.com/efi-bootloaders/
|
||||
[47]:http://www.rodsbooks.com/efi-bootloaders/secureboot.html
|
||||
[48]:mailto:rodsmith@rodsbooks.com
|
||||
[49]:http://ss64.com/osx/bless.html
|
||||
[50]:http://www.rodsbooks.com/refind/getting.html
|
||||
[51]:http://www.rodsbooks.com/linux-uefi/#oops
|
||||
[52]:http://www.rodsbooks.com/linux-uefi/#oops
|
||||
[53]:http://www.rodsbooks.com/efi-bootloaders/
|
||||
[54]:http://www.rodsbooks.com/refind/
|
||||
[55]:http://www.rodsbooks.com/efi-bootloaders/grub2.html
|
||||
[56]:http://www.rodsbooks.com/efi-bootloaders
|
||||
[57]:http://www.rodsbooks.com/refind/
|
||||
[58]:http://sourceforge.net/projects/bootinfoscript/
|
||||
[59]:http://pastebin.com/
|
||||
[60]:http://www.rodsbooks.com/linux-uefi/#troubleshooting
|
||||
[61]:http://www.rodsbooks.com/linux-uefi/#troubleshooting
|
@ -1,46 +1,44 @@
|
||||
|
||||
微流冷却技术可能让摩尔定律起死回生
|
||||
============================================================
|
||||
|
||||
![](http://tr1.cbsistatic.com/hub/i/r/2015/12/09/a7cb82d1-96e8-43b5-bfbd-d4593869b230/resize/620x/9607388a284e3a61a39f4399a9202bd7/networkingistock000042544852agsandrew.jpg)
|
||||
>Image: iStock/agsandrew
|
||||
|
||||
*Image: iStock/agsandrew*
|
||||
|
||||
现有的技术无法对微芯片进行有效的冷却,这正快速成为摩尔定律消亡的第一原因。
|
||||
|
||||
随着对数字计算速度的需求,科学家和工程师正努力地将更多的晶体管和支撑电路放在已经很拥挤的硅片上。的确,它非常地复杂,然而,和复杂性相比,热量聚积引起的问题更严重。
|
||||
|
||||
洛克希德马丁公司首席研究员John Ditri在新闻稿中说到:当前,我们可以放入微芯片的功能是有限的,最主要的原因之一是发热的管理。如果你能管理好发热,你可以用较少的芯片,较少的材料,那样就可以节约成本,并能减少系统的大小和重量。如果你能管理好发热,用相同数量的芯片将能获得更好的系统性能。
|
||||
洛克希德马丁公司首席研究员 John Ditri 在新闻稿中说到:当前,我们可以放入微芯片的功能是有限的,最主要的原因之一是发热的管理。如果你能管理好发热,你可以用较少的芯片,也就是说较少的材料,那样就可以节约成本,并能减少系统的大小和重量。如果你能管理好发热,用相同数量的芯片将能获得更好的系统性能。
|
||||
|
||||
硅对电子流动的阻力产生了热量,在如此小的空间封装如此多的晶体管累积了足以毁坏元器件的热量。一种消除热累积的方法是在芯片层用光子学技术减少电子的流动,然而光子学技术有它的一系列问题。
|
||||
|
||||
SEE:2015年硅光子将引起数据中心的革命 [Silicon photonics will revolutionize data centers in 2015][5]
|
||||
参见: [2015 年硅光子将引起数据中心的革命][5]
|
||||
|
||||
### 微流冷却技术可能是问题的解决之道
|
||||
|
||||
为了寻找其他解决办法,国防高级研究计划局DARPA发起了一个关于ICECool应用[ICECool Applications][6] (片内/片间增强冷却技术)的项目。GSA网站 [GSA website FedBizOpps.gov][7] 报道:ICECool正在探索革命性的热技术,其将减轻热耗对军用电子系统的限制,同时能显著减小军用电子系统的尺寸,重量和功耗。
|
||||
为了寻找其他解决办法,美国国防高级研究计划局 DARPA 发起了一个关于 [ICECool 应用][6] (片内/片间增强冷却技术)的项目。 [GSA 的网站 FedBizOpps.gov][7] 报道:ICECool 正在探索革命性的热技术,其将减轻热耗对军用电子系统的限制,同时能显著减小军用电子系统的尺寸,重量和功耗。
|
||||
|
||||
微流冷却方法的独特之处在于组合使用片内和(或)片间微流冷却技术和片上热互连技术。
|
||||
|
||||
![](http://tr4.cbsistatic.com/hub/i/r/2016/05/25/fd3d0d17-bd86-4d25-a89a-a7050c4d59c4/resize/300x/e9c18034bde66526310c667aac92fbf5/microcooling-1.png)
|
||||
>MicroCooling 1 Image: DARPA
|
||||
|
||||
DARPA ICECool应用项目 [DARPA ICECool Application announcement][8] 指出, 这种微型片内和(或)片间通道可采用轴向微通道,径向通道和(或)横流通道,采用微孔和歧管结构及局部液体喷射形式来疏散和重新引导微流,从而以最有利的方式来满足指定的散热指标。
|
||||
*MicroCooling 1 Image: DARPA*
|
||||
|
||||
通过上面的技术,洛克希德马丁的工程师已经实验性地证明了片上冷却是如何得到显著改善的。洛克希德马丁新闻报道:ICECool项目的第一阶段发现,当冷却具有多个局部30kW/cm2热点,发热为1kw/cm2的芯片时热阻减少了4倍,进而验证了洛克希德的嵌入式微流冷却方法的有效性。
|
||||
[DARPA ICECool 应用发布的公告][8] 指出,这种微型片内和(或)片间通道可采用轴向微通道、径向通道和(或)横流通道,采用微孔和歧管结构及局部液体喷射形式来疏散和重新引导微流,从而以最有利的方式来满足指定的散热指标。
|
||||
|
||||
第二阶段,洛克希德马丁的工程师聚焦于RF放大器。通过ICECool的技术,团队演示了RF的输出功率可以得到6倍的增长,而放大器仍然比其常规冷却的更凉。
|
||||
通过上面的技术,洛克希德马丁的工程师已经实验性地证明了片上冷却是如何得到显著改善的。洛克希德马丁新闻报道:ICECool 项目的第一阶段发现,当冷却具有多个局部 30kW/cm2 热点,发热为 1kw/cm2 的芯片时热阻减少了 4 倍,进而验证了洛克希德的嵌入式微流冷却方法的有效性。
|
||||
|
||||
第二阶段,洛克希德马丁的工程师聚焦于 RF 放大器。通过 ICECool 的技术,团队演示了 RF 的输出功率可以得到 6 倍的增长,而放大器仍然比其常规冷却的更凉。
|
||||
|
||||
### 投产
|
||||
|
||||
出于对技术的信心,洛克希德马丁已经在设计和制造实用的微流冷却发射天线。 Lockheed Martin还与Qorvo合作,将其热解决方案与Qorvo的高性能GaN工艺 [GaN process][9] 集成.
|
||||
出于对技术的信心,洛克希德马丁已经在设计和制造实用的微流冷却发射天线。 洛克希德马丁还与 Qorvo 合作,将其热解决方案与 Qorvo 的高性能 [ GaN 工艺][9] 相集成。
|
||||
|
||||
研究论文 [DARPA's Intra/Interchip Enhanced Cooling (ICECool) Program][10] 的作者认为ICECool将使电子系统的热管理模式发生改变。ICECool应用的执行者将根据应用来定制片内和片间的热管理方法,这个方法需要兼顾应用的材料,制造工艺和工作环境。
|
||||
研究论文 [DARPA 的片间/片内增强冷却技术(ICECool)流程][10] 的作者认为 ICECool 将使电子系统的热管理模式发生改变。ICECool 应用的执行者将根据应用来定制片内和片间的热管理方法,这个方法需要兼顾应用的材料,制造工艺和工作环境。
|
||||
|
||||
如果微流冷却能像科学家和工程师所说的成功的话,似乎摩尔定律会起死回生。
|
||||
|
||||
更多的关于网络的信息,请订阅Data Centers newsletter。
|
||||
|
||||
[SUBSCRIBE](https://secure.techrepublic.com/user/login/?regSource=newsletter-button&position=newsletter-button&appId=true&redirectUrl=http%3A%2F%2Fwww.techrepublic.com%2Farticle%2Fmicrofluidic-cooling-may-prevent-the-demise-of-moores-law%2F&)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -48,7 +46,7 @@ via: http://www.techrepublic.com/article/microfluidic-cooling-may-prevent-the-de
|
||||
|
||||
作者:[Michael Kassner][a]
|
||||
译者:[messon007](https://github.com/messon007)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,384 @@
|
||||
大数据初步:在树莓派上通过 Apache Spark on YARN 搭建 Hadoop 集群
|
||||
===
|
||||
|
||||
有些时候我们想从 DQYDJ 网站的数据中分析点有用的东西出来,在过去,我们要[用 R 语言提取固定宽度的数据](https://dqydj.com/how-to-import-fixed-width-data-into-a-spreadsheet-via-r-playing-with-ipums-cps-data/),然后通过数学建模来分析[美国的最低收入补贴](http://dqydj.com/negative-income-tax-cost-calculator-united-states/),当然也包括其他优秀的方法。
|
||||
|
||||
今天我将向你展示对大数据的一点探索,不过有点变化,使用的是全世界最流行的微型电脑————[树莓派](https://www.raspberrypi.org/),如果手头没有,那就看下一篇吧(可能是已经处理好的数据),对于其他用户,请继续阅读吧,今天我们要建立一个树莓派 Hadoop集群!
|
||||
|
||||
### I. 为什么要建立一个树莓派的 Hadoop 集群?
|
||||
|
||||
![](https://dqydj.com/wp-content/uploads/2016/08/IMG_9132-245x300.png)
|
||||
|
||||
*由三个树莓派节点组成的 Hadoop 集群*
|
||||
|
||||
我们对 DQYDJ 的数据做了[大量的处理工作](https://dqydj.com/finance-calculators-investment-calculators-and-visualizations/),但这些还不能称得上是大数据。
|
||||
|
||||
和许许多多有争议的话题一样,数据的大小之别被解释成这样一个笑话:
|
||||
|
||||
> 如果能被内存所存储,那么它就不是大数据。 ————佚名
|
||||
|
||||
似乎这儿有两种解决问题的方法:
|
||||
|
||||
1. 我们可以找到一个足够大的数据集合,任何家用电脑的物理或虚拟内存都存不下。
|
||||
2. 我们可以买一些不用特别定制,我们现有数据就能淹没它的电脑:
|
||||
|
||||
—— 上手树莓派 2B
|
||||
|
||||
这个由设计师和工程师制作出来的精致小玩意儿拥有 1GB 的内存, MicroSD 卡充当它的硬盘,此外,每一台的价格都低于 50 美元,这意味着你可以花不到 250 美元的价格搭建一个 Hadoop 集群。
|
||||
|
||||
或许天下没有比这更便宜的入场券来带你进入大数据的大门。
|
||||
|
||||
### II. 制作一个树莓派集群
|
||||
|
||||
我最喜欢制作的原材料。
|
||||
|
||||
这里我将给出我原来为了制作树莓派集群购买原材料的链接,如果以后要在亚马逊购买的话你可先这些链接收藏起来,也是对本站的一点支持。(谢谢)
|
||||
|
||||
- [树莓派 2B 3 块](http://amzn.to/2bEFTVh)
|
||||
- [4 层亚克力支架](http://amzn.to/2bTo1br)
|
||||
- [6 口 USB 转接器](http://amzn.to/2bEGO8g),我选了白色 RAVPower 50W 10A 6 口 USB 转接器
|
||||
- [MicroSD 卡](http://amzn.to/2cguV9I),这个五件套 32GB 卡非常棒
|
||||
- [短的 MicroUSB 数据线](http://amzn.to/2bX2mwm),用于给树莓派供电
|
||||
- [短网线](http://amzn.to/2bDACQJ)
|
||||
- 双面胶,我有一些 3M 的,很好用
|
||||
|
||||
#### 开始制作
|
||||
|
||||
1. 首先,装好三个树莓派,每一个用螺丝钉固定在亚克力面板上。(看下图)
|
||||
2. 接下来,安装以太网交换机,用双面胶贴在其中一个在亚克力面板上。
|
||||
3. 用双面胶贴将 USB 转接器贴在一个在亚克力面板使之成为最顶层。
|
||||
4. 接着就是一层一层都拼好——这里我选择将树莓派放在交换机和USB转接器的底下(可以看看完整安装好的两张截图)
|
||||
|
||||
想办法把线路放在需要的地方——如果你和我一样购买力 USB 线和网线,我可以将它们卷起来放在亚克力板子的每一层
|
||||
|
||||
现在不要急着上电,需要将系统烧录到 SD 卡上才能继续。
|
||||
|
||||
#### 烧录 Raspbian
|
||||
|
||||
按照[这个教程](https://www.raspberrypi.org/downloads/raspbian/)将 Raspbian 烧录到三张 SD 卡上,我使用的是 Win7 下的 [Win32DiskImager][2]。
|
||||
|
||||
将其中一张烧录好的 SD 卡插在你想作为主节点的树莓派上,连接 USB 线并启动它。
|
||||
|
||||
#### 启动主节点
|
||||
|
||||
这里有[一篇非常棒的“Because We Can Geek”的教程](http://www.becausewecangeek.com/building-a-raspberry-pi-hadoop-cluster-part-1/),讲如何安装 Hadoop 2.7.1,此处就不再熬述。
|
||||
|
||||
在启动过程中有一些要注意的地方,我将带着你一起设置直到最后一步,记住我现在使用的 IP 段为 192.168.1.50 – 192.168.1.52,主节点是 .50,从节点是 .51 和 .52,你的网络可能会有所不同,如果你想设置静态 IP 的话可以在评论区看看或讨论。
|
||||
|
||||
一旦你完成了这些步骤,接下来要做的就是启用交换文件,Spark on YARN 将分割出一块非常接近内存大小的交换文件,当你内存快用完时便会使用这个交换分区。
|
||||
|
||||
(如果你以前没有做过有关交换分区的操作的话,可以看看[这篇教程](https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04),让 `swappiness` 保持较低水准,因为 MicroSD 卡的性能扛不住)
|
||||
|
||||
现在我准备介绍有关我的和“Because We Can Geek”关于启动设置一些微妙的区别。
|
||||
|
||||
对于初学者,确保你给你的树莓派起了一个正式的名字——在 `/etc/hostname` 设置,我的主节点设置为 ‘RaspberryPiHadoopMaster’ ,从节点设置为 ‘RaspberryPiHadoopSlave#’
|
||||
|
||||
主节点的 `/etc/hosts` 配置如下:
|
||||
|
||||
```
|
||||
#/etc/hosts
|
||||
127.0.0.1 localhost
|
||||
::1 localhost ip6-localhost ip6-loopback
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
|
||||
192.168.1.50 RaspberryPiHadoopMaster
|
||||
192.168.1.51 RaspberryPiHadoopSlave1
|
||||
192.168.1.52 RaspberryPiHadoopSlave2
|
||||
```
|
||||
|
||||
如果你想让 Hadoop、YARN 和 Spark 运行正常的话,你也需要修改这些配置文件(不妨现在就编辑)。
|
||||
|
||||
这是 `hdfs-site.xml`:
|
||||
|
||||
```
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
|
||||
<configuration>
|
||||
<property>
|
||||
<name>fs.default.name</name>
|
||||
<value>hdfs://RaspberryPiHadoopMaster:54310</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>hadoop.tmp.dir</name>
|
||||
<value>/hdfs/tmp</value>
|
||||
</property>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
这是 `yarn-site.xml` (注意内存方面的改变):
|
||||
|
||||
```
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
|
||||
<!-- Site specific YARN configuration properties -->
|
||||
<property>
|
||||
<name>yarn.nodemanager.aux-services</name>
|
||||
<value>mapreduce_shuffle</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.nodemanager.resource.cpu-vcores</name>
|
||||
<value>4</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.nodemanager.resource.memory-mb</name>
|
||||
<value>1024</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.scheduler.minimum-allocation-mb</name>
|
||||
<value>128</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.scheduler.maximum-allocation-mb</name>
|
||||
<value>1024</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.scheduler.minimum-allocation-vcores</name>
|
||||
<value>1</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.scheduler.maximum-allocation-vcores</name>
|
||||
<value>4</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.nodemanager.vmem-check-enabled</name>
|
||||
<value>false</value>
|
||||
<description>Whether virtual memory limits will be enforced for containers</description>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.nodemanager.vmem-pmem-ratio</name>
|
||||
<value>4</value>
|
||||
<description>Ratio between virtual memory to physical memory when setting memory limits for containers</description>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.resourcemanager.resource-tracker.address</name>
|
||||
<value>RaspberryPiHadoopMaster:8025</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.resourcemanager.scheduler.address</name>
|
||||
<value>RaspberryPiHadoopMaster:8030</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yarn.resourcemanager.address</name>
|
||||
<value>RaspberryPiHadoopMaster:8040</value>
|
||||
</property>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
`slaves`:
|
||||
|
||||
```
|
||||
RaspberryPiHadoopMaster
|
||||
RaspberryPiHadoopSlave1
|
||||
RaspberryPiHadoopSlave2
|
||||
```
|
||||
|
||||
`core-site.xml`:
|
||||
|
||||
```
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
|
||||
<configuration>
|
||||
<property>
|
||||
<name>fs.default.name</name>
|
||||
<value>hdfs://RaspberryPiHadoopMaster:54310</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>hadoop.tmp.dir</name>
|
||||
<value>/hdfs/tmp</value>
|
||||
</property>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
#### 设置两个从节点:
|
||||
|
||||
接下来[按照 “Because We Can Geek”上的教程](http://www.becausewecangeek.com/building-a-raspberry-pi-hadoop-cluster-part-2/),你需要对上面的文件作出小小的改动。 在 `yarn-site.xml` 中主节点没有改变,所以从节点中不必含有这个 `slaves` 文件。
|
||||
|
||||
### III. 在我们的树莓派集群中测试 YARN
|
||||
|
||||
如果所有设备都正常工作,在主节点上你应该执行如下命令:
|
||||
|
||||
```
|
||||
start-dfs.sh
|
||||
start-yarn.sh
|
||||
```
|
||||
|
||||
当设备启动后,以 Hadoop 用户执行,如果你遵循教程,用户应该是 `hduser`。
|
||||
|
||||
接下来执行 `hdfs dfsadmin -report` 查看三个节点是否都正确启动,确认你看到一行粗体文字 ‘Live datanodes (3)’:
|
||||
|
||||
```
|
||||
Configured Capacity: 93855559680 (87.41 GB)
|
||||
Raspberry Pi Hadoop Cluster picture Straight On
|
||||
Present Capacity: 65321992192 (60.84 GB)
|
||||
DFS Remaining: 62206627840 (57.93 GB)
|
||||
DFS Used: 3115364352 (2.90 GB)
|
||||
DFS Used%: 4.77%
|
||||
Under replicated blocks: 0
|
||||
Blocks with corrupt replicas: 0
|
||||
Missing blocks: 0
|
||||
Missing blocks (with replication factor 1): 0
|
||||
————————————————-
|
||||
Live datanodes (3):
|
||||
Name: 192.168.1.51:50010 (RaspberryPiHadoopSlave1)
|
||||
Hostname: RaspberryPiHadoopSlave1
|
||||
Decommission Status : Normal
|
||||
```
|
||||
|
||||
你现在可以做一些简单的诸如 ‘Hello, World!’ 的测试,或者直接进行下一步。
|
||||
|
||||
### IV. 安装 SPARK ON YARN
|
||||
|
||||
YARN 的意思是另一种非常好用的资源调度器(Yet Another Resource Negotiator),已经作为一个易用的资源管理器集成在 Hadoop 基础安装包中。
|
||||
|
||||
[Apache Spark](https://spark.apache.org/) 是 Hadoop 生态圈中的另一款软件包,它是一个毁誉参半的执行引擎和[捆绑的 MapReduce](https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html)。在一般情况下,相对于基于磁盘存储的 MapReduce,Spark 更适合基于内存的存储,某些运行任务能够得到 10-100 倍提升——安装完成集群后你可以试试 Spark 和 MapReduce 有什么不同。
|
||||
|
||||
我个人对 Spark 还是留下非常深刻的印象,因为它提供了两种数据工程师和科学家都比较擅长的语言—— Python 和 R。
|
||||
|
||||
安装 Apache Spark 非常简单,在你家目录下,`wget "为 Hadoop 2.7 构建的 Apache Spark”`([来自这个页面](https://spark.apache.org/downloads.html)),然后运行 `tar -xzf “tgz 文件”`,最后把解压出来的文件移动至 `/opt`,并清除刚才下载的文件,以上这些就是安装步骤。
|
||||
|
||||
我又创建了只有两行的文件 `spark-env.sh`,其中包含 Spark 的配置文件目录。
|
||||
|
||||
```
|
||||
SPARK_MASTER_IP=192.168.1.50
|
||||
SPARK_WORKER_MEMORY=512m
|
||||
```
|
||||
|
||||
(在 YARN 跑起来之前我不确定这些是否有必要。)
|
||||
|
||||
### V. 你好,世界! 为 Apache Spark 寻找有趣的数据集!
|
||||
|
||||
在 Hadoop 世界里面的 ‘Hello, World!’ 就是做单词计数。
|
||||
|
||||
我决定让我们的作品做一些内省式……为什么不统计本站最常用的单词呢?也许统计一些关于本站的大数据会更有用。
|
||||
|
||||
如果你有一个正在运行的 WordPress 博客,可以通过简单的两步来导出和净化。
|
||||
|
||||
1. 我使用 [Export to Text](https://wordpress.org/support/plugin/export-to-text) 插件导出文章的内容到纯文本文件中
|
||||
2. 我使用一些[压缩库](https://pypi.python.org/pypi/bleach)编写了一个 Python 脚本来剔除 HTML
|
||||
|
||||
```
|
||||
import bleach
|
||||
|
||||
# Change this next line to your 'import' filename, whatever you would like to strip
|
||||
# HTML tags from.
|
||||
ascii_string = open('dqydj_with_tags.txt', 'r').read()
|
||||
|
||||
|
||||
new_string = bleach.clean(ascii_string, tags=[], attributes={}, styles=[], strip=True)
|
||||
new_string = new_string.encode('utf-8').strip()
|
||||
|
||||
# Change this next line to your 'export' filename
|
||||
f = open('dqydj_stripped.txt', 'w')
|
||||
f.write(new_string)
|
||||
f.close()
|
||||
```
|
||||
|
||||
现在我们有了一个更小的、适合复制到树莓派所搭建的 HDFS 集群上的文件。
|
||||
|
||||
如果你不能树莓派主节点上完成上面的操作,找个办法将它传输上去(scp、 rsync 等等),然后用下列命令行复制到 HDFS 上。
|
||||
|
||||
```
|
||||
hdfs dfs -copyFromLocal dqydj_stripped.txt /dqydj_stripped.txt
|
||||
```
|
||||
|
||||
现在准备进行最后一步 - 向 Apache Spark 写入一些代码。
|
||||
|
||||
### VI. 点亮 Apache Spark
|
||||
|
||||
Cloudera 有个极棒的程序可以作为我们的超级单词计数程序的基础,[你可以在这里找到](https://www.cloudera.com/documentation/enterprise/5-6-x/topics/spark_develop_run.html)。我们接下来为我们的内省式单词计数程序修改它。
|
||||
|
||||
在主节点上[安装‘stop-words’](https://pypi.python.org/pypi/stop-words)这个 python 第三方包,虽然有趣(我在 DQYDJ 上使用了 23,295 次 the 这个单词),你可能不想看到这些语法单词占据着单词计数的前列,另外,在下列代码用你自己的数据集替换所有有关指向 dqydj 文件的地方。
|
||||
|
||||
```
|
||||
import sys
|
||||
|
||||
from stop_words import get_stop_words
|
||||
from pyspark import SparkContext, SparkConf
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# create Spark context with Spark configuration
|
||||
conf = SparkConf().setAppName("Spark Count")
|
||||
sc = SparkContext(conf=conf)
|
||||
|
||||
# get threshold
|
||||
try:
|
||||
threshold = int(sys.argv[2])
|
||||
except:
|
||||
threshold = 5
|
||||
|
||||
# read in text file and split each document into words
|
||||
tokenized = sc.textFile(sys.argv[1]).flatMap(lambda line: line.split(" "))
|
||||
|
||||
# count the occurrence of each word
|
||||
wordCounts = tokenized.map(lambda word: (word.lower().strip(), 1)).reduceByKey(lambda v1,v2:v1 +v2)
|
||||
|
||||
# filter out words with fewer than threshold occurrences
|
||||
filtered = wordCounts.filter(lambda pair:pair[1] >= threshold)
|
||||
|
||||
print "*" * 80
|
||||
print "Printing top words used"
|
||||
print "-" * 80
|
||||
filtered_sorted = sorted(filtered.collect(), key=lambda x: x[1], reverse = True)
|
||||
for (word, count) in filtered_sorted: print "%s : %d" % (word.encode('utf-8').strip(), count)
|
||||
|
||||
|
||||
# Remove stop words
|
||||
print "\n\n"
|
||||
print "*" * 80
|
||||
print "Printing top non-stop words used"
|
||||
print "-" * 80
|
||||
# Change this to your language code (see the stop-words documentation)
|
||||
stop_words = set(get_stop_words('en'))
|
||||
no_stop_words = filter(lambda x: x[0] not in stop_words, filtered_sorted)
|
||||
for (word, count) in no_stop_words: print "%s : %d" % (word.encode('utf-8').strip(), count)
|
||||
```
|
||||
|
||||
保存好 wordCount.py,确保上面的路径都是正确无误的。
|
||||
|
||||
现在,准备念出咒语,让运行在 YARN 上的 Spark 跑起来,你可以看到我在 DQYDJ 使用最多的单词是哪一个。
|
||||
|
||||
```
|
||||
/opt/spark-2.0.0-bin-hadoop2.7/bin/spark-submit –master yarn –executor-memory 512m –name wordcount –executor-cores 8 wordCount.py /dqydj_stripped.txt
|
||||
```
|
||||
|
||||
### VII. 我在 DQYDJ 使用最多的单词
|
||||
|
||||
可能入列的单词有哪一些呢?“can, will, it’s, one, even, like, people, money, don’t, also“.
|
||||
|
||||
嘿,不错,“money”悄悄挤进了前十。在一个致力于金融、投资和经济的网站上谈论这似乎是件好事,对吧?
|
||||
|
||||
下面是的前 50 个最常用的词汇,请用它们刻画出有关我的文章的水平的结论。
|
||||
|
||||
![](https://dqydj.com/wp-content/uploads/2016/08/dqydj_pk_most_used_words.png)
|
||||
|
||||
我希望你能喜欢这篇关于 Hadoop、YARN 和 Apache Spark 的教程,现在你可以在 Spark 运行和编写其他的应用了。
|
||||
|
||||
你的下一步是任务是开始[阅读 pyspark 文档](https://spark.apache.org/docs/2.0.0/api/python/index.html)(以及用于其他语言的该库),去学习一些可用的功能。根据你的兴趣和你实际存储的数据,你将会深入学习到更多——有流数据、SQL,甚至机器学习的软件包!
|
||||
|
||||
你怎么看?你要建立一个树莓派 Hadoop 集群吗?想要在其中挖掘一些什么吗?你在上面看到最令你惊奇的单词是什么?为什么 'S&P' 也能上榜?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://dqydj.com/raspberry-pi-hadoop-cluster-apache-spark-yarn/
|
||||
|
||||
作者:[PK][a]
|
||||
译者:[popy32](https://github.com/sfantree)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://dqydj.com/about/#contact_us
|
||||
[1]: https://www.raspberrypi.org/downloads/raspbian/
|
||||
[2]: https://sourceforge.net/projects/win32diskimager/
|
||||
[3]: http://www.becausewecangeek.com/building-a-raspberry-pi-hadoop-cluster-part-1/
|
||||
[4]: https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04
|
||||
[5]: http://www.becausewecangeek.com/building-a-raspberry-pi-hadoop-cluster-part-2/
|
||||
[6]: https://spark.apache.org/
|
||||
[7]: https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html
|
||||
[8]: https://spark.apache.org/downloads.html
|
||||
[9]: https://wordpress.org/support/plugin/export-to-text
|
||||
[10]: https://pypi.python.org/pypi/bleach
|
||||
|
@ -0,0 +1,69 @@
|
||||
Rowhammer:针对物理内存的攻击可以取得 Android 设备的 root 权限
|
||||
===
|
||||
|
||||
> 攻击者确实可以在物理存储单元中实现位翻转来达到侵入移动设备与计算机的目的
|
||||
|
||||
![](http://images.techhive.com/images/idgnsImport/2015/08/id-2969037-security1-100606370-large.jpg)
|
||||
|
||||
|
||||
研究者们发现了一种新的在不利用任何软件漏洞情况下,利用内存芯片物理设计上的弱点来侵入 Android 设备的方式。这种攻击技术同样可以影响到其它如 ARM 和 X86 架构的设备与计算机。
|
||||
|
||||
这种称之为“Rowhammer”的攻击起源于过去十多年中将更多的 DRAM(动态随机存取存储器)容量封装进越来越小的芯片中,这将导致在特定情况下存储单元电子可以从相邻两<ruby>行<rt>row</rt></ruby>的一边泄漏到另一边。(LCTT 译注:参见 https://en.wikipedia.org/wiki/Row_hammer)
|
||||
|
||||
例如,反复且快速的访问相同的物理储存位置,这种被称为 “<ruby>锤击<rt>hammering</rt></ruby>” 的行为可以导致相邻位置的位值从 0 反转成 1,或者相反。
|
||||
|
||||
虽然这样的电子干扰已经被生产商知晓并且从可靠性角度研究了一段时间了,因为内存错误能够导致系统崩溃。而研究者们现在展示了在可控方式的触发下它所存在的严重安全隐患。
|
||||
|
||||
在 2015 年 4 月,来自谷歌 Project Zero 项目的研究者公布了两份基于内存 “Rowhammer”漏洞对于 x86-64 CPU 架构的 [提权利用][7]。其中一份利用可以使代码从谷歌的 Chrome 浏览器沙盒里逃逸并且直接在系统上执行,另一份可以在 Linux 机器上获取内核级权限。
|
||||
|
||||
此后,其他的研究者进行了更深入的调查并且展示了[通过网站中 JaveScript 脚本进行利用的方式][6]甚至能够影响运行在云环境下的[虚拟服务器][5]。然而,对于这项技术是否可以应用在智能手机和移动设备大量使用的 ARM 架构中还是有疑问的。
|
||||
|
||||
现在,一队成员来自荷兰阿姆斯特丹自由大学、奥地利格拉茨技术大学和加州大学圣塔芭芭拉分校的 VUSec 小组,已经证明了 Rowhammer 不仅仅可以应用在 ARM 架构上并且甚至比在 x86 架构上更容易。
|
||||
|
||||
研究者们将他们的新攻击命名为 Drammer,代表了 Rowhammer 确实存在,并且计划于周三在维也纳举办的第 23 届 ACM 计算机与通信安全大会上展示。这种攻击建立在之前就被发现与实现的 Rowhammer 技术之上。
|
||||
|
||||
VUSec 小组的研究者已经制造了一个适用于 Android 设备的恶意应用,当它被执行的时候利用不易察觉的内存位反转在不需要任何权限的情况下就可以获取设备根权限。
|
||||
|
||||
研究者们测试了来自不同制造商的 27 款 Android 设备,21 款使用 ARMv7(32-bit)指令集架构,其它 6 款使用 ARMv8(64-bit)指令集架构。他们成功的在 17 款 ARMv7 设备和 1 款 ARMv8 设备上实现了为反转,表明了这些设备是易受攻击的。
|
||||
|
||||
此外,Drammer 能够与其它的 Android 漏洞组合使用,例如 [Stagefright][4] 或者 [BAndroid][3] 来实现无需用户手动下载恶意应用的远程攻击。
|
||||
|
||||
谷歌已经注意到了这一类型的攻击。“在研究者向谷歌漏洞奖励计划报告了这个问题之后,我们与他们进行了密切的沟通来深入理解这个问题以便我们更好的保护用户,”一位谷歌的代表在一份邮件申明中这样说到。“我们已经开发了一个缓解方案,将会包含在十一月的安全更新中。”(LCTT 译注:缓解方案,参见 https://en.wikipedia.org/wiki/Vulnerability_management)
|
||||
|
||||
VUSec 的研究者认为,谷歌的缓解方案将会使得攻击过程更为复杂,但是它不能修复潜在的问题。
|
||||
|
||||
事实上,从软件上去修复一个由硬件导致的问题是不现实的。硬件供应商正在研究相关问题并且有可能在将来的内存芯片中被修复,但是在现有设备的芯片中风险依然存在。
|
||||
|
||||
更糟的是,研究者们说,由于有许多因素会影响到攻击的成功与否并且这些因素尚未被研究透彻,因此很难去说有哪些设备会被影响到。例如,内存控制器可能会在不同的电量的情况下展现不同的行为,因此一个设备可能在满电的情况下没有风险,当它处于低电量的情况下就是有风险的。
|
||||
|
||||
同样的,在网络安全中有这样一句俗语:<ruby>攻击将变本加厉,如火如荼<rt>Attacks always get getter, they never get worse</rt></ruby>。Rowhammer 攻击已经从理论变成了现实可能,同样的,它也可能会从现在的现实可能变成确确实实的存在。这意味着今天某个设备是不被影响的,在明天就有可能被改进后的 Rowhammer 技术证明它是存在风险的。
|
||||
|
||||
Drammer 在 Android 上实现是因为研究者期望研究基于 ARM 设备的影响,但是潜在的技术可以被使用在所有的架构与操作系统上。新的攻击相较于之前建立在运气与特殊特性与特定平台之上并且十分容易失效的技术已经是一个巨大的进步了。
|
||||
|
||||
Drammer 攻击的实现依靠于被包括图形、网络、声音等大量硬件子系统所使用的 DMA(直接存储访问)缓存。Drammer 的实现采用了所有操作系统上都有的 Android 的 ION 内存分配器、接口与方法,这给我们带来的警示是该论文的主要贡献之一。
|
||||
|
||||
“破天荒的,我们成功地展示了我们可以做到,在不依赖任何特定的特性情况下完全可靠的证明了 Rowhammer”, VUSec 小组中的其中一位研究者 Cristiano Giuffrida 这样说道。“攻击所利用的内存位置并非是 Android 独有的。攻击在任何的 Linux 平台上都能工作 -- 我们甚至怀疑其它操作系统也可以 -- 因为它利用的是操作系统内核内存管理中固有的特性。”
|
||||
|
||||
“我期待我们可以看到更多针对其它平台的攻击的变种,”阿姆斯特丹自由大学的教授兼 VUSec 系统安全研究小组的领导者 Herbert Bos 补充道。
|
||||
|
||||
在他们的[论文][2]之外,研究者们也释出了一个 Android 应用来测试 Android 设备在当前所知的技术条件下受到 Rowhammer 攻击时是否会有风险。应用还没有传上谷歌应用商店,可以从 [VUSec Drammer 网站][1] 下载来手动安装。一个开源的 Rowhammer 模拟器同样能够帮助其他的研究者来更深入的研究这个问题。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via:http://www.csoonline.com/article/3134726/security/physical-ram-attack-can-root-android-and-possibly-other-devices.html
|
||||
|
||||
作者:[Lucian Constantin][a]
|
||||
译者:[wcnnbdk1](https://github.com/wcnnbdk1)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.csoonline.com/author/Lucian-Constantin/
|
||||
[1]:https://www.vusec.net/projects/drammer/
|
||||
[2]:https://vvdveen.com/publications/drammer.pdf
|
||||
[3]:https://www.vusec.net/projects/bandroid/
|
||||
[4]:http://www.csoonline.com/article/3045836/security/new-stagefright-exploit-puts-millions-of-android-devices-at-risk.html
|
||||
[5]:http://www.infoworld.com/article/3105889/security/flip-feng-shui-attack-on-cloud-vms-exploits-hardware-weaknesses.html
|
||||
[6]:http://www.computerworld.com/article/2954582/security/researchers-develop-astonishing-webbased-attack-on-a-computers-dram.html
|
||||
[7]:http://www.computerworld.com/article/2895898/google-researchers-hack-computers-using-dram-electrical-leaks.html
|
||||
[8]:http://csoonline.com/newsletters/signup.html
|
466
published/201705/20161025 GitLab Workflow An Overview.md
Normal file
466
published/201705/20161025 GitLab Workflow An Overview.md
Normal file
@ -0,0 +1,466 @@
|
||||
GitLab 工作流概览
|
||||
======
|
||||
|
||||
GitLab 是一个基于 git 的仓库管理程序,也是一个方便软件开发的强大完整应用。
|
||||
|
||||
GitLab 拥有一个“用户新人友好”的界面,通过图形界面和命令行界面,使你的工作更加具有效率。GitLab 不仅仅对开发者是一个有用的工具,它甚至可以被集成到你的整个团队中,使得每一个人获得一个独自唯一的平台。
|
||||
|
||||
GitLab 工作流逻辑符合使用者思维,使得整个平台变得更加易用。相信我,使用一次,你就离不开它了!
|
||||
|
||||
### GitLab 工作流
|
||||
|
||||
**GitLab 工作流** 是在软件开发过程中,在使用 GitLab 作为代码托管平台时,可以采取的动作的一个逻辑序列。
|
||||
|
||||
GitLab 工作流遵循了 [GitLab Flow][97] 策略,这是由一系列由**基于 Git** 的方法和策略组成的,这些方法为版本的管理,例如**分支策略**、**Git最佳实践**等等提供了保障。
|
||||
|
||||
通过 GitLab 工作流,可以很方便的[提升](https://about.gitlab.com/2016/09/13/gitlab-master-plan/)团队的工作效率以及凝聚力。这种提升,从引入一个新的项目开始,一直到发布这个项目,成为一个产品都有所体现。这就是我们所说的“如何通过最快的速度把一个点子在 10 步之内变成一个产品”。
|
||||
|
||||
![FROM IDEA TO PRODUCTION IN 10 STEPS](https://about.gitlab.com/images/blogimages/idea-to-production-10-steps.png)
|
||||
|
||||
#### 软件开发阶段
|
||||
|
||||
一般情况下,软件开发经过 10 个主要阶段;GitLab 为这 10 个阶段依次提供了解决方案:
|
||||
|
||||
1. **IDEA**: 每一个从点子开始的项目,通常来源于一次闲聊。在这个阶段,GitLab 集成了 [Mattermost][44]。
|
||||
2. **ISSUE**: 最有效的讨论一个点子的方法,就是为这个点子建立一个工单讨论。你的团队和你的合作伙伴可以在 <ruby>工单追踪器<rt>issue tracker</rt></ruby> 中帮助你去提升这个点子
|
||||
3. **PLAN**: 一旦讨论得到一致的同意,就是开始编码的时候了。但是等等!首先,我们需要优先考虑组织我们的工作流。对于此,我们可以使用 <ruby>工单看板<rt>Issue Board</rt></ruby>。
|
||||
4. **CODE**: 现在,当一切准备就绪,我们可以开始写代码了。
|
||||
5. **COMMIT**: 当我们为我们的初步成果欢呼的时候,我们就可以在版本控制下,提交代码到功能分支了。
|
||||
6. **TEST**: 通过 [GitLab CI][41],我们可以运行脚本来构建和测试我们的应用。
|
||||
7. **REVIEW**: 一旦脚本成功运行,我们测试和构建成功,我们就可以进行 <ruby>代码复审<rt>code review</rt></ruby> 以及批准。
|
||||
8. **STAGING:**: 现在是时候[将我们的代码部署到演示环境][39]来检查一下,看看是否一切就像我们预估的那样顺畅——或者我们可能仍然需要修改。
|
||||
9. **PRODUCTION**: 当一切都如预期,就是[部署到生产环境][38]的时候了!
|
||||
10. **FEEDBACK**: 现在是时候返回去看我们项目中需要提升的部分了。我们使用[<ruby>周期分析<rt> Cycle Analytics</rt></ruby>][37]来对当前项目中关键的部分进行的反馈。
|
||||
|
||||
简单浏览这些步骤,我们可以发现,提供强大的工具来支持这些步骤是十分重要的。在接下来的部分,我们为 GitLab 的可用工具提供一个简单的概览。
|
||||
|
||||
### GitLab 工单追踪器
|
||||
|
||||
GitLab 有一个强大的工单追溯系统,在使用过程中,允许你和你的团队,以及你的合作者分享和讨论建议。
|
||||
|
||||
![issue tracker - view list](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/issue-tracker-list-view.png)
|
||||
|
||||
工单是 GitLab 工作流的第一个重要重要特性。[以工单的讨论为开始][95]; 跟踪新点子的改变是一个最好的方式。
|
||||
|
||||
这十分有利于:
|
||||
|
||||
* 讨论点子
|
||||
* 提交功能建议
|
||||
* 提问题
|
||||
* 提交错误和故障
|
||||
* 获取支持
|
||||
* 精细化新代码的引入
|
||||
|
||||
每一个在 GitLab 上部署的项目都有一个工单追踪器。找到你的项目中的 **Issues** > **New issue** 来创建一个新的工单。建立一个标题来总结要被讨论的主题,并且使用 [Markdown][94] 来形容它。看看下面的“专业技巧”来加强你的工单描述。
|
||||
|
||||
GitLab 工单追踪器提供了一个额外的实用功能,使得步骤变得更佳易于管理和考虑。下面的部分仔细描述了它。
|
||||
|
||||
![new issue - additional settings](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/issue-features-view.png)
|
||||
|
||||
#### 秘密工单
|
||||
|
||||
无论何时,如果你仅仅想要在团队中讨论这个工单,你可以使[该工单成为秘密的][92]。即使你的项目是公开的,你的工单也会被保密起来。当一个不是本项目成员的人,就算是 [报告人级别][01],想要访问工单的地址时,浏览器也会返回一个 404 错误。
|
||||
|
||||
#### 截止日期
|
||||
|
||||
每一个工单允许你填写一个[截止日期][90]。有些团队工作时间表安排紧凑,以某种方式去设置一个截止日期来解决问题,是有必要的。这些都可以通过截止日期这一功能实现。
|
||||
|
||||
当你对一个多任务项目有截止日期的时候——比如说,一个新的发布活动、项目的启动,或者按阶段追踪任务——你可以使用[里程碑][89]。
|
||||
|
||||
#### 受托者
|
||||
|
||||
要让某人处理某个工单,可以将其分配给他。你可以任意修改被分配者,直到满足你的需求。这个功能的想法是,一个受托者本身对这个工单负责,直到其将这个工单重新赋予其他人。
|
||||
|
||||
这也可以用于按受托者筛选工单。
|
||||
|
||||
#### 标签
|
||||
|
||||
GitLab 标签也是 GitLab 流的一个重要组成部分。你可以使用它们来分类你的工单,在工作流中定位,以及通过[优先级标签][88]来安装优先级组织它们。
|
||||
|
||||
标签使得你与[GitLab 工单看板][87]协同工作,加快工程进度以及组织你的工作流。
|
||||
|
||||
**新功能:** 你可以创建[组标签][86]。它可以使得在每一个项目组中使用相同的标签。
|
||||
|
||||
#### 工单权重
|
||||
|
||||
你可以添加个[工单权重][85]使得一个工单重要性表现的更为清晰。01 - 03 表示工单不是特别重要,07 - 09 表示十分重要,04 - 06 表示程度适中。此外,你可以与你的团队自行定义工单重要性的指标。
|
||||
|
||||
注:该功能仅可用于 GitLab 企业版和 GitLab.com 上。
|
||||
|
||||
#### GitLab 工单看板
|
||||
|
||||
在项目中,[GitLab 工单看板][84]是一个用于计划以及组织你的工单,使之符合你的项目工作流的工具。
|
||||
|
||||
看板包含了与其相关的相应标签,每一个列表包含了相关的被标记的工单,并且以卡片的形式展示出来。
|
||||
|
||||
这些卡片可以在列表之间移动,被移动的卡片,其标签将会依据你移动的位置相应更新到列表上。
|
||||
|
||||
![GitLab Issue Board](https://about.gitlab.com/images/blogimages/designing-issue-boards/issue-board.gif)
|
||||
|
||||
**新功能:** 你也可以通过点击列表上方的“+”按钮在看板右边创建工单。当你这么做的时候,这个工单将会自动添加与列表相关的标签。
|
||||
|
||||
**新功能:** 我们[最近推出了][83] 每一个 GitLab 项目拥有**多个工单看板**的功能(仅存在于 [GitLab 企业版][82]);这是为不同的工作流组织你的工单的好方法。
|
||||
|
||||
![Multiple Issue Boards](https://about.gitlab.com/images/8_13/m_ib.gif)
|
||||
|
||||
### 通过 GitLab 进行代码复审
|
||||
|
||||
在工单追踪器中,讨论了新的提议之后,就是在代码上做工作的时候了。你在本地书写代码,一旦你完成了你的第一个版本,提交你的代码并且推送到你的 GitLab 仓库。你基于 Git 的管理策略可以在 [GitLab 流][81]中被提升。
|
||||
|
||||
#### 第一次提交
|
||||
|
||||
在你的第一次提交信息中,你可以添加涉及到工单号在其中。通过这样做你可以将两个阶段的开发工作流链接起来:工单本身以及关于这个工单的第一次提交。
|
||||
|
||||
这样做,如果你提交的代码和工单属于同一个项目,你可以简单的添加 `#xxx` 到提交信息中(LCTT 译注:`git commit message`),`xxx`是一个工单号。如果它们不在一个项目中,你可以添加整个工单的整个URL(`https://gitlab.com/<username>/<projectname>/issues/<xxx>`)。
|
||||
|
||||
```
|
||||
git commit -m "this is my commit message. Ref #xxx"
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
git commit -m "this is my commit message. Related to https://gitlab.com/<username>/<projectname>/issues/<xxx>"
|
||||
```
|
||||
|
||||
当然,你也可以替换 `gitlab.com`,以你自己的 GitLab 实例来替换这个 URL。
|
||||
|
||||
**注:** 链接工单和你的第一次提交是为了通过 [GitLab 周期分析][80]追踪你的进展。这将会衡量计划执行该工单所采取的时间,即创建工单与第一次提交的间隔时间。
|
||||
|
||||
#### 合并请求
|
||||
|
||||
一旦将你的改动提交到功能分支,GitLab 将识别该修改,并且建议你提交一次<ruby>合并请求<rt>Merge Request</rt></ruby>(MR)。
|
||||
|
||||
每一次 MR 都会有一个标题(这个标题总结了这次的改动)并且一个用 [Markdown][79] 书写的描述。在描述中,你可以简单的描述该 MR 做了什么,提及任何工单以及 MR(在它们之间创建联系),并且,你也可以添加个[关闭工单模式][78],当该 MR 被**合并**的时候,相关联的工单就会被关闭。
|
||||
|
||||
例如:
|
||||
|
||||
```
|
||||
## 增加一个新页面
|
||||
|
||||
这个 MR 将会为这个项目创建一个包含该 app 概览的 `readme.md`。
|
||||
|
||||
Closes #xxx and https://gitlab.com/<username>/<projectname>/issues/<xxx>
|
||||
|
||||
预览:
|
||||
|
||||
![预览新页面](#image-url)
|
||||
|
||||
cc/ @Mary @Jane @John
|
||||
```
|
||||
|
||||
当你创建一个如上的带有描述的 MR,它将会:
|
||||
|
||||
* 当合并时,关闭包括工单 `#xxx` 以及 `https://gitlab.com/<username>/<projectname>/issues/<xxx>`
|
||||
* 展示一张图片
|
||||
* 通过邮件提醒用户 `@Mary`、`@Jane`,以及给 `@John`
|
||||
|
||||
你可以分配这个 MR 给你自己,直到你完成你的工作,然后把它分配给其他人来做一次代码复审。如果有必要的话,这个 MR 可以被重新分配多次,直到你覆盖你所需要的所有复审。
|
||||
|
||||
它也可以被标记,并且添加一个[里程碑][77]来促进管理。
|
||||
|
||||
当你从图形界面而不是命令行添加或者修改一个文件并且提交一个新的分支时,也很容易创建一个新的 MR,仅仅需要标记一下复选框,“以这些改变开始一个新的合并请求”,然后,一旦你提交你的改动,GitLab 将会自动创建一个新的 MR。
|
||||
|
||||
![commit to a feature branch and add a new MR from the UI](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/start-new-mr-edit-from-ui.png)
|
||||
|
||||
**注:** 添加[关闭工单样式][76]到你的 MR 以便可以使用 [GitLab 周期分析][75]追踪你的项目进展,是十分重要的。它将会追踪“CODE”阶段,衡量第一次提交及创建一个相关的合并请求所间隔的时间。
|
||||
|
||||
**新功能:** 我们已经开发了[审查应用][74],这是一个可以让你部署你的应用到一个动态的环境中的新功能,在此你可以按分支名字、每个合并请求来预览改变。参看这里的[可用示例][73]。
|
||||
|
||||
#### WIP MR
|
||||
|
||||
WIP MR 含义是 **在工作过程中的合并请求**,是一个我们在 GitLab 中避免 MR 在准备就绪前被合并的技术。只需要添加 `WIP:` 在 MR 的标题开头,它将不会被合并,除非你把 `WIP:` 删除。
|
||||
|
||||
当你改动已经准备好被合并,编辑工单来手动删除 `WIP:` ,或者使用就像如下 MR 描述下方的快捷方式。
|
||||
|
||||
![WIP MR click to remove WIP from the title](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/gitlab-wip-mr.png)
|
||||
|
||||
**新功能:** `WIP` 模式可以通过[斜线命令][71] `/wip` [快速添加到合并请求中][72]。只需要在评论或者 MR 描述中输入它并提交即可。
|
||||
|
||||
#### 复审
|
||||
|
||||
一旦你创建一个合并请求,就是你开始从你的团队以及合作方收取反馈的时候了。使用图形界面中的差异比较功能,你可以简单的添加行内注释,以及回复或者解决它们。
|
||||
|
||||
你也可以通过点击行号获取每一行代码的链接。
|
||||
|
||||
在图形界面中可以看到提交历史,通过提交历史,你可以追踪文件的每一次改变。你可以以行内差异或左右对比的方式浏览它们。
|
||||
|
||||
![code review in MRs at GitLab](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/gitlab-code-review.png)
|
||||
|
||||
**新功能:** 如果你遇到合并冲突,可以快速地[通过图形界面来解决][70],或者依据你的需要修改文件来修复冲突。
|
||||
|
||||
![mr conflict resolution](https://about.gitlab.com/images/8_13/inlinemergeconflictresolution.gif)
|
||||
|
||||
### 构建、测试以及发布
|
||||
|
||||
[GitLab CI][69] 是一个强大的内建工具,其作用是[持续集成、持续发布以及持续分发][58],它可以按照你希望的运行一些脚本。它的可能性是无止尽的:你可以把它看做是自己运行的命令行。
|
||||
|
||||
它完全是通过一个名为 `.gitlab-ci.yml` 的 YAML 文件设置的,其放置在你的项目仓库中。使用 Web 界面简单的添加一个文件,命名为 `.gitlab-ci.yml` 来触发一个下拉菜单,为不同的应用选择各种 CI 模版。
|
||||
|
||||
![GitLab CI templates - dropdown menu](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/gitlab-ci-template.png)
|
||||
|
||||
#### Koding
|
||||
|
||||
Use GitLab's [Koding integration][67] to run your entire development environment in the cloud. This means that you can check out a project or just a merge request in a full-fledged IDE with the press of a button.
|
||||
|
||||
可以使用 GitLab 的 [Koding 集成][67]功能在云端运行你的整个云端开发环境。这意味着你可以轻轻一键即可在一个完整的 IDE 中检出以个项目,或者合并一个请求。
|
||||
|
||||
#### 使用案例
|
||||
|
||||
GitLab CI 的使用案例:
|
||||
|
||||
* 用它来[构建][36]任何[静态网站生成器][35],并且通过 [GitLab Pages][34] 发布你的网站。
|
||||
* 用它来[发布你的网站][33] 到 `staging` 以及 `production` [环境][32]。
|
||||
* 用它来[构建一个 iOS 应用][31]。
|
||||
* 用它来[构建和发布你的 Docker 镜像][30]到 [GitLab 容器注册库][29]。
|
||||
|
||||
我们已经准备一大堆 [GitLab CI 样例工程][66]作为您的指南。看看它们吧!
|
||||
|
||||
### 反馈:周期分析
|
||||
|
||||
当你遵循 GitLab 工作流进行工作,你的团队从点子到产品,在每一个[过程的关键部分][64],你将会在下列时间获得一个 [GitLab 周期分析][65]的反馈:
|
||||
|
||||
* **Issue**: 从创建一个工单,到分配这个工单给一个里程碑或者添加工单到你的工单看板的时间。
|
||||
* **Plan**: 从给工单分配一个里程碑或者把它添加到工单看板,到推送第一次提交的时间。
|
||||
* **Code**: 从第一次提交到提出该合并请求的时间。
|
||||
* **Test**: CI 为了相关合并请求而运行整个过程的时间。
|
||||
* **Review**: 从创建一个合并请求到合并它的时间。
|
||||
* **Staging**: 从合并到发布成为产品的时间。
|
||||
* **Production(Total)**: 从创建工单到把代码发布成[产品][28]的时间。
|
||||
|
||||
### 加强
|
||||
|
||||
#### 工单以及合并请求模版
|
||||
|
||||
[工单以及合并请求模版][63]允许你为你的项目去定义一个特定内容的工单模版和合并请求的描述字段。
|
||||
|
||||
你可以以 [Markdown][62] 形式书写它们,并且把它们加入仓库的默认分支。当创建工单或者合并请求时,可以通过下拉菜单访问它们。
|
||||
|
||||
它们节省了您在描述工单和合并请求的时间,并标准化了需要持续跟踪的重要信息。它确保了你需要的一切都在你的掌控之中。
|
||||
|
||||
你可以创建许多模版,用于不同的用途。例如,你可以有一个提供功能建议的工单模版,或者一个 bug 汇报的工单模版。在 [GitLab CE project][61] 中寻找真实的例子吧!
|
||||
|
||||
![issues and MR templates - dropdown menu screenshot](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/issues-choose-template.png)
|
||||
|
||||
#### 里程碑
|
||||
|
||||
[里程碑][60] 是 GitLab 中基于共同的目标、详细的日期追踪你队伍工作的最好工具。
|
||||
|
||||
不同情况下的目的是不同的,但是大致是相同的:你有为了达到特定的目标的工单的集合以及正在编码的合并请求。
|
||||
|
||||
这个目标基本上可以是任何东西——用来结合团队的工作,在一个截止日期前完成一些事情。例如,发布一个新的版本,启动一个新的产品,在某个日期前完成,或者按季度收尾一些项目。
|
||||
|
||||
![milestone dashboard](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/gitlab-milestone.png)
|
||||
|
||||
### 专业技巧
|
||||
|
||||
#### 工单和 MR
|
||||
|
||||
* 在工单和 MR 的描述中:
|
||||
* 输入 `#` 来触发一个已有工单的下拉列表
|
||||
* 输入 `!` 来触发一个已有 MR 的下拉列表
|
||||
* 输入 `/` 来触发[斜线命令][4]
|
||||
* 输入 `:` 来出发 emoji 表情 (也支持行中评论)
|
||||
* 通过按钮“附加文件”来添加图片(jpg、png、gif) 和视频到行内评论
|
||||
* 通过 [GitLab Webhooks][26] [自动应用标签][27]
|
||||
* [构成引用][24]: 使用语法 `>>>` 来开始或者结束一个引用
|
||||
|
||||
```
|
||||
>>>
|
||||
Quoted text
|
||||
|
||||
Another paragraph
|
||||
>>>
|
||||
```
|
||||
* 创建[任务列表][23]:
|
||||
|
||||
```
|
||||
- [ ] Task 1
|
||||
- [ ] Task 2
|
||||
- [ ] Task 3
|
||||
```
|
||||
|
||||
##### 订阅
|
||||
|
||||
你是否发现你有一个工单或者 MR 想要追踪?展开你的右边的导航,点击[订阅][59],你就可以在随时收到一个评论的提醒。要是你想要一次订阅多个工单和 MR?使用[批量订阅][58]。
|
||||
|
||||
##### 添加代办
|
||||
|
||||
除了一直留意工单和 MR,如果你想要对它预先做点什么,或者不管什么时候你想要在 GitLab 代办列表中添加点什么,点击你右边的导航,并且[点击**添加代办**][57]。
|
||||
|
||||
##### 寻找你的工单和 MR
|
||||
|
||||
当你寻找一个在很久以前由你开启的工单或 MR——它们可能数以十计、百计、甚至千计——所以你很难找到它们。打开你左边的导航,并且点击**工单**或者**合并请求**,你就会看到那些分配给你的。同时,在那里或者任何工单追踪器里,你可以通过作者、分配者、里程碑、标签以及重要性来过滤工单,也可以通过搜索所有不同状态的工单,例如开启的、合并的,关闭的等等。
|
||||
|
||||
#### 移动工单
|
||||
|
||||
一个工单在一个错误的项目中结束了?不用担心,点击**Edit**,然后[移动工单][56]到正确的项目。
|
||||
|
||||
#### 代码片段
|
||||
|
||||
你经常在不同的项目以及文件中使用一些相同的代码段和模版吗?创建一个代码段并且使它在你需要的时候可用。打开左边导航栏,点击**[Snipptes][25]**。所有你的片段都会在那里。你可以把它们设置成公开的,内部的(仅为 GitLab 注册用户提供),或者私有的。
|
||||
|
||||
![Snippets - screenshot](https://about.gitlab.com/images/blogimages/gitlab-workflow-an-overview/gitlab-code-snippet.png)
|
||||
|
||||
### GitLab 工作流用户案例概要
|
||||
|
||||
作为总结,让我们把所有东西聚在一起理顺一下。不必担心,这十分简单。
|
||||
|
||||
让我们假设:你工作于一个专注于软件开发的公司。你创建了一个新的工单,这个工单是为了开发一个新功能,实施于你的一个应用中。
|
||||
|
||||
**标签策略**
|
||||
|
||||
为了这个应用,你已经创建了几个标签,“讨论”、“后端”、“前端”、“正在进行”、“展示”、“就绪”、“文档”、“营销”以及“产品”。所有都已经在工单看板有它们自己的列表。你的当前的工单已经有了标签“讨论”。
|
||||
|
||||
在工单追踪器中的讨论达成一致之后,你的后端团队开始在工单上工作,所以他们把这个工单的标签从“讨论”移动到“后端”。第一个开发者开始写代码,并且把这个工单分配给自己,增加标签“正在进行”。
|
||||
|
||||
**编码 & 提交**
|
||||
|
||||
在他的第一次提交的信息中,他提及了他的工单编号。在工作后,他把他的提交推送到一个功能分支,并且创建一个新的合并请求,在 MR 描述中,包含工单关闭模式。他的团队复审了他的代码并且保证所有的测试和建立都已经通过。
|
||||
|
||||
**使用工单看板**
|
||||
|
||||
一旦后端团队完成了他们的工作,他们就删除“正在进行”标签,并且把工单从“后端”移动到“前端”看板。所以,前端团队接到通知,这个工单已经为他们准备好了。
|
||||
|
||||
**发布到演示**
|
||||
|
||||
当一个前端开发者开始在该工单上工作,他(她)增加一个标签“正在进行”,并且把这个工单重新分配给自己。当工作完成,该实现将会被发布到一个**演示**环境。标签“正在进行”就会被删除,然后在工单看板里,工单卡被移动到“演示”列表中。
|
||||
|
||||
**团队合作**
|
||||
|
||||
最后,当新功能成功实现,你的团队把它移动到“就绪”列表。
|
||||
|
||||
然后,就是你的技术文档编写团队的时间了,他们为新功能书写文档。一旦某个人完成书写,他添加标签“文档”。同时,你的市场团队开始启动并推荐该功能,所以某个人添加“市场”。当技术文档书写完毕,书写者删除标签“文档”。一旦市场团队完成他们的工作,他们将工单从“市场”移动到“生产”。
|
||||
|
||||
**部署到生产环境**
|
||||
|
||||
最后,你将会成为那个为新版本负责的人,合并“合并请求”并且将新功能部署到**生产**环境,然后工单的状态转变为**关闭**。
|
||||
|
||||
**反馈**
|
||||
|
||||
通过[周期分析][55],你和你的团队节省了如何从点子到产品的时间,并且开启另一个工单,来讨论如何将这个过程进一步提升。
|
||||
|
||||
### 总结
|
||||
|
||||
GitLab 工作流通过一个单一平台帮助你的团队加速从点子到生产的改变:
|
||||
|
||||
* 它是**有效的**:因为你可以获取你想要的结果
|
||||
* 它是**高效的**:因为你可以用最小的努力和成本达到最大的生产力
|
||||
* 它是**高产的**:因为你可以非常有效的计划和行动
|
||||
* 它是**简单的**:因为你不需要安装不同的工具去完成你的目的,仅仅需要 GitLab
|
||||
* 它是**快速的**:因为你不需要在多个平台间跳转来完成你的工作
|
||||
|
||||
每一个月的 22 号都会有一个新的 GitLab 版本释出,让它在集成软件开发解决方案上变得越来越好,让团队可以在一个单一的、唯一的界面下一起工作。
|
||||
|
||||
在 GitLab,每个人都可以奉献!多亏了我们强大的社区,我们获得了我们想要的。并且多亏了他们,我们才能一直为你提供更好的产品。
|
||||
|
||||
还有什么问题和反馈吗?请留言,或者在推特上@我们[@GitLab][54]!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/
|
||||
|
||||
作者:[Marcia Ramos][a]
|
||||
译者:[svtter](https://github.com/svtter)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://twitter.com/XMDRamos
|
||||
[1]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#search-for-your-issues-and-mrs
|
||||
[2]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#add-to-do
|
||||
[3]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#subscribe
|
||||
[4]:https://docs.gitlab.com/ce/user/project/slash_commands.html
|
||||
[5]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#code-snippets
|
||||
[6]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#moving-issues
|
||||
[7]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#for-both-issues-and-mrs
|
||||
[8]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#milestones
|
||||
[9]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#issue-and-mr-templates
|
||||
[10]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#use-cases
|
||||
[11]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#koding
|
||||
[12]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#review
|
||||
[13]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#wip-mr
|
||||
[14]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#merge-request
|
||||
[15]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#first-commit
|
||||
[16]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-issue-board
|
||||
[17]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#issue-weight
|
||||
[18]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#labels
|
||||
[19]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#assignee
|
||||
[20]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#due-dates
|
||||
[21]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#confidential-issues
|
||||
[22]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#stages-of-software-development
|
||||
[23]:https://docs.gitlab.com/ee/user/markdown.html#task-lists
|
||||
[24]:https://about.gitlab.com/2016/07/22/gitlab-8-10-released/#blockquote-fence-syntax
|
||||
[25]:https://gitlab.com/dashboard/snippets
|
||||
[26]:https://docs.gitlab.com/ce/web_hooks/web_hooks.html
|
||||
[27]:https://about.gitlab.com/2016/08/19/applying-gitlab-labels-automatically/
|
||||
[28]:https://docs.gitlab.com/ce/ci/yaml/README.html#environment
|
||||
[29]:https://about.gitlab.com/2016/05/23/gitlab-container-registry/
|
||||
[30]:https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/
|
||||
[31]:https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/
|
||||
[32]:https://docs.gitlab.com/ce/ci/yaml/README.html#environment
|
||||
[33]:https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/
|
||||
[34]:https://pages.gitlab.io/
|
||||
[35]:https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/
|
||||
[36]:https://about.gitlab.com/2016/04/07/gitlab-pages-setup/
|
||||
[37]:https://about.gitlab.com/solutions/cycle-analytics/
|
||||
[38]:https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/
|
||||
[39]:https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/
|
||||
[40]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-code-review
|
||||
[41]:https://about.gitlab.com/gitlab-ci/
|
||||
[42]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-issue-board
|
||||
[43]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-issue-tracker
|
||||
[44]:https://about.gitlab.com/2015/08/18/gitlab-loves-mattermost/
|
||||
[45]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#conclusions
|
||||
[46]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario
|
||||
[47]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#pro-tips
|
||||
[48]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#enhance
|
||||
[49]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#feedback
|
||||
[50]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#build-test-and-deploy
|
||||
[51]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#code-review-with-gitlab
|
||||
[52]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-issue-tracker
|
||||
[53]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow
|
||||
[54]:https://twitter.com/gitlab
|
||||
[55]:https://about.gitlab.com/solutions/cycle-analytics/
|
||||
[56]:https://about.gitlab.com/2016/03/22/gitlab-8-6-released/#move-issues-to-other-projects
|
||||
[57]:https://about.gitlab.com/2016/06/22/gitlab-8-9-released/#manually-add-todos
|
||||
[58]:https://about.gitlab.com/2016/07/22/gitlab-8-10-released/#bulk-subscribe-to-issues
|
||||
[59]:https://about.gitlab.com/2016/03/22/gitlab-8-6-released/#subscribe-to-a-label
|
||||
[60]:https://about.gitlab.com/2016/08/05/feature-highlight-set-dates-for-issues/#milestones
|
||||
[61]:https://gitlab.com/gitlab-org/gitlab-ce/issues/new
|
||||
[62]:https://docs.gitlab.com/ee/user/markdown.html
|
||||
[63]:https://docs.gitlab.com/ce/user/project/description_templates.html
|
||||
[64]:https://about.gitlab.com/2016/09/21/cycle-analytics-feature-highlight/
|
||||
[65]:https://about.gitlab.com/solutions/cycle-analytics/
|
||||
[66]:https://docs.gitlab.com/ee/ci/examples/README.html
|
||||
[67]:https://about.gitlab.com/2016/08/22/gitlab-8-11-released/#koding-integration
|
||||
[68]:https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/
|
||||
[69]:https://about.gitlab.com/gitlab-ci/
|
||||
[70]:https://about.gitlab.com/2016/08/22/gitlab-8-11-released/#merge-conflict-resolution
|
||||
[71]:https://docs.gitlab.com/ce/user/project/slash_commands.html
|
||||
[72]:https://about.gitlab.com/2016/10/22/gitlab-8-13-released/#wip-slash-command
|
||||
[73]:https://gitlab.com/gitlab-examples/review-apps-nginx/
|
||||
[74]:https://about.gitlab.com/2016/10/22/gitlab-8-13-released/#ability-to-stop-review-apps
|
||||
[75]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#feedback
|
||||
[76]:https://docs.gitlab.com/ce/administration/issue_closing_pattern.html
|
||||
[77]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#milestones
|
||||
[78]:https://docs.gitlab.com/ce/administration/issue_closing_pattern.html
|
||||
[79]:https://docs.gitlab.com/ee/user/markdown.html
|
||||
[80]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#feedback
|
||||
[81]:https://about.gitlab.com/2014/09/29/gitlab-flow/
|
||||
[82]:https://about.gitlab.com/free-trial/
|
||||
[83]:https://about.gitlab.com/2016/10/22/gitlab-8-13-released/#multiple-issue-boards-ee
|
||||
[84]:https://about.gitlab.com/solutions/issueboard
|
||||
[85]:https://docs.gitlab.com/ee/workflow/issue_weight.html
|
||||
[86]:https://about.gitlab.com/2016/10/22/gitlab-8-13-released/#group-labels
|
||||
[87]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-issue-board
|
||||
[88]:https://docs.gitlab.com/ee/user/project/labels.html#prioritize-labels
|
||||
[89]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#milestones
|
||||
[90]:https://about.gitlab.com/2016/08/05/feature-highlight-set-dates-for-issues/#due-dates-for-issues
|
||||
[91]:https://docs.gitlab.com/ce/user/permissions.html
|
||||
[92]:https://about.gitlab.com/2016/03/31/feature-highlihght-confidential-issues/
|
||||
[93]:https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#pro-tips
|
||||
[94]:https://docs.gitlab.com/ee/user/markdown.html
|
||||
[95]:https://about.gitlab.com/2016/03/03/start-with-an-issue/
|
||||
[96]:https://about.gitlab.com/2016/09/13/gitlab-master-plan/
|
||||
[97]:https://about.gitlab.com/2014/09/29/gitlab-flow/
|
@ -0,0 +1,138 @@
|
||||
向 Linus Torvalds 学习让编出的代码具有 “good taste”
|
||||
========
|
||||
|
||||
在[最近关于 Linus Torvalds 的一个采访中][1],这位 Linux 的创始人,在采访过程中大约 14:20 的时候,提及了关于代码的 “good taste”。good taste?采访者请他展示更多的细节,于是,Linus Torvalds 展示了一张提前准备好的插图。
|
||||
|
||||
他展示的是一个代码片段。但这段代码并没有 “good taste”。这是一个具有 “poor taste” 的代码片段,把它作为例子,以提供一些初步的比较。
|
||||
|
||||
![Poor Taste Code Example](https://d262ilb51hltx0.cloudfront.net/max/1200/1*X2VgEA_IkLvsCS-X4iPY7g.png)
|
||||
|
||||
这是一个用 C 写的函数,作用是删除链表中的一个对象,它包含有 10 行代码。
|
||||
|
||||
他把注意力集中在底部的 `if` 语句。正是这个 `if` 语句受到他的批判。
|
||||
|
||||
我暂停了这段视频,开始研究幻灯片。我发现我最近有写过和这很像的代码。Linus 不就是在说我的代码品味很差吗?我放下自傲,继续观看视频。
|
||||
|
||||
随后, Linus 向观众解释,正如我们所知道的,当从链表中删除一个对象时,需要考虑两种可能的情况。当所需删除的对象位于链表的表头时,删除过程和位于链表中间的情况不同。这就是这个 `if` 语句具有 “poor taste” 的原因。
|
||||
|
||||
但既然他承认考虑这两种不同的情况是必要的,那为什么像上面那样写如此糟糕呢?
|
||||
|
||||
接下来,他又向观众展示了第二张幻灯片。这个幻灯片展示的是实现同样功能的一个函数,但这段代码具有 “goog taste” 。
|
||||
|
||||
![Good Taste Code Example](https://d262ilb51hltx0.cloudfront.net/max/1200/1*GHFLYFB3vDQeakMyUGPglw.png)
|
||||
|
||||
原先的 10 行代码现在减少为 4 行。
|
||||
|
||||
但代码的行数并不重要,关键是 `if` 语句,它不见了,因为不再需要了。代码已经被重构,所以,不用管对象在列表中的位置,都可以运用同样的操作把它删除。
|
||||
|
||||
Linus 解释了一下新的代码,它消除了边缘情况,就是这样。然后采访转入了下一个话题。
|
||||
|
||||
我琢磨了一会这段代码。 Linus 是对的,的确,第二个函数更好。如果这是一个确定代码具有 “good taste” 还是 “bad taste” 的测试,那么很遗憾,我失败了。我从未想到过有可能能够去除条件语句。我写过不止一次这样的 `if` 语句,因为我经常使用链表。
|
||||
|
||||
这个例子的意义,不仅仅是教给了我们一个从链表中删除对象的更好方法,而是启发了我们去思考自己写的代码。你通过程序实现的一个简单算法,可能还有改进的空间,只是你从来没有考虑过。
|
||||
|
||||
以这种方式,我回去审查最近正在做的项目的代码。也许是一个巧合,刚好也是用 C 写的。
|
||||
|
||||
我尽最大的能力去审查代码,“good taste” 的一个基本要求是关于边缘情况的消除方法,通常我们会使用条件语句来消除边缘情况。你的测试使用的条件语句越少,你的代码就会有更好的 “taste” 。
|
||||
|
||||
下面,我将分享一个通过审查代码进行了改进的一个特殊例子。
|
||||
|
||||
这是一个关于初始化网格边缘的算法。
|
||||
|
||||
下面所写的是一个用来初始化网格边缘的算法,网格 grid 以一个二维数组表示:grid[行][列] 。
|
||||
|
||||
再次说明,这段代码的目的只是用来初始化位于 grid 边缘的点的值,所以,只需要给最上方一行、最下方一行、最左边一列以及最右边一列赋值即可。
|
||||
|
||||
为了完成这件事,我通过循环遍历 grid 中的每一个点,然后使用条件语句来测试该点是否位于边缘。代码看起来就是下面这样:
|
||||
|
||||
```Tr
|
||||
for (r = 0; r < GRID_SIZE; ++r) {
|
||||
for (c = 0; c < GRID_SIZE; ++c) {
|
||||
// Top Edge
|
||||
if (r == 0)
|
||||
grid[r][c] = 0;
|
||||
// Left Edge
|
||||
if (c == 0)
|
||||
grid[r][c] = 0;
|
||||
// Right Edge
|
||||
if (c == GRID_SIZE - 1)
|
||||
grid[r][c] = 0;
|
||||
// Bottom Edge
|
||||
if (r == GRID_SIZE - 1)
|
||||
grid[r][c] = 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
虽然这样做是对的,但回过头来看,这个结构存在一些问题。
|
||||
|
||||
1. 复杂性 — 在双层循环里面使用 4 个条件语句似乎过于复杂。
|
||||
2. 高效性 — 假设 `GRID_SIZE` 的值为 64,那么这个循环需要执行 4096 次,但需要进行赋值的只有位于边缘的 256 个点。
|
||||
|
||||
用 Linus 的眼光来看,将会认为这段代码没有 “good taste” 。
|
||||
|
||||
所以,我对上面的问题进行了一下思考。经过一番思考,我把复杂度减少为包含四个条件语句的单层 `for` 循环。虽然只是稍微改进了一下复杂性,但在性能上也有了极大的提高,因为它只是沿着边缘的点进行了 256 次循环。
|
||||
|
||||
```
|
||||
for (i = 0; i < GRID_SIZE * 4; ++i) {
|
||||
// Top Edge
|
||||
if (i < GRID_SIZE)
|
||||
grid[0][i] = 0;
|
||||
// Right Edge
|
||||
else if (i < GRID_SIZE * 2)
|
||||
grid[i - GRID_SIZE][GRID_SIZE - 1] = 0;
|
||||
// Left Edge
|
||||
else if (i < GRID_SIZE * 3)
|
||||
grid[i - (GRID_SIZE * 2)][0] = 0;
|
||||
// Bottom Edge
|
||||
else
|
||||
grid[GRID_SIZE - 1][i - (GRID_SIZE * 3)] = 0;
|
||||
}
|
||||
```
|
||||
|
||||
的确是一个很大的提高。但是它看起来很丑,并不是易于阅读理解的代码。基于这一点,我并不满意。
|
||||
|
||||
我继续思考,是否可以进一步改进呢?事实上,答案是 YES!最后,我想出了一个非常简单且优雅的算法,老实说,我不敢相信我会花了那么长时间才发现这个算法。
|
||||
|
||||
下面是这段代码的最后版本。它只有一层 `for` 循环并且没有条件语句。另外。循环只执行了 64 次迭代,极大的改善了复杂性和高效性。
|
||||
|
||||
```
|
||||
for (i = 0; i < GRID_SIZE; ++i) {
|
||||
// Top Edge
|
||||
grid[0][i] = 0;
|
||||
|
||||
// Bottom Edge
|
||||
grid[GRID_SIZE - 1][i] = 0;
|
||||
// Left Edge
|
||||
grid[i][0] = 0;
|
||||
// Right Edge
|
||||
grid[i][GRID_SIZE - 1] = 0;
|
||||
}
|
||||
```
|
||||
|
||||
这段代码通过每次循环迭代来初始化四条边缘上的点。它并不复杂,而且非常高效,易于阅读。和原始的版本,甚至是第二个版本相比,都有天壤之别。
|
||||
|
||||
至此,我已经非常满意了。
|
||||
|
||||
那么,我是一个有 “good taste” 的开发者么?
|
||||
|
||||
我觉得我是,但是这并不是因为我上面提供的这个例子,也不是因为我在这篇文章中没有提到的其它代码……而是因为具有 “good taste” 的编码工作远非一段代码所能代表。Linus 自己也说他所提供的这段代码不足以表达他的观点。
|
||||
|
||||
我明白 Linus 的意思,也明白那些具有 “good taste” 的程序员虽各有不同,但是他们都是会将他们之前开发的代码花费时间重构的人。他们明确界定了所开发的组件的边界,以及是如何与其它组件之间的交互。他们试着确保每一样工作都完美、优雅。
|
||||
|
||||
其结果就是类似于 Linus 的 “good taste” 的例子,或者像我的例子一样,不过是千千万万个 “good taste”。
|
||||
|
||||
你会让你的下个项目也具有这种 “good taste” 吗?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://medium.com/@bartobri/applying-the-linus-tarvolds-good-taste-coding-requirement-99749f37684a
|
||||
|
||||
作者:[Brian Barto][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://medium.com/@bartobri?source=post_header_lockup
|
||||
[1]:https://www.ted.com/talks/linus_torvalds_the_mind_behind_linux
|
@ -0,0 +1,165 @@
|
||||
Linux 容器能否弥补 IoT 的安全短板?
|
||||
========
|
||||
|
||||
![](http://hackerboards.com/files/internet_of_things_wikimedia1-thm.jpg)
|
||||
|
||||
> 在这个最后的物联网系列文章中,Canonical 和 Resin.io 向以 Linux 容器技术作为解决方案向物联网安全性和互操作性发起挑战。
|
||||
|
||||
![](http://hackerboards.com/files/samsung_artik710-thm.jpg)
|
||||
|
||||
*Artik 7*
|
||||
|
||||
尽管受到日益增长的安全威胁,但对物联网(IoT)的炒作没有显示减弱的迹象。为了刷存在感,公司们正忙于重新规划它们的物联网方面的路线图。物联网大潮迅猛异常,比移动互联网革命渗透的更加深入和广泛。IoT 像黑洞一样,吞噬一切,包括智能手机,它通常是我们通向物联网世界的窗口,有时也作为我们的汇聚点或终端。
|
||||
|
||||
新的针对物联网的处理器和嵌入式主板继续重塑其技术版图。自从 9 月份推出 [面向物联网的 Linux 和开源硬件][5] 系列文章之后,我们看到了面向物联网网关的 “Apollo Lake]” SoC 芯片 [Intel Atom E3900][6] 以及[三星 新的 Artik 模块][7],包括用于网关并由 Linux 驱动的 64 位 Artik 7 COM 及自带 RTOS 的 Cortex-M4 Artik。 ARM 为具有 ARMv8-M 和 TrustZone 安全性的 IoT 终端发布了 [Cortex-M23 和 Cortex-M33][8] 芯片。
|
||||
|
||||
讲道理,安全是这些产品的卖点。最近攻击 Dyn 服务并在一天内摧毁了美国大部分互联网的 Mirai 僵尸网络将基于 Linux 的物联网推到台前 - 当然这种方式似乎不太体面。就像 IoT 设备可以成为 DDoS 的帮凶一样,设备及其所有者同样可能直接遭受恶意攻击。
|
||||
|
||||
![](http://hackerboards.com/files/arm_cortexm33m23-thm.jpg)
|
||||
|
||||
*Cortex-M33 和 -M23*
|
||||
|
||||
Dyn 攻击更加证明了这种观点,即物联网将更加蓬勃地在受控制和受保护的工业环境发展,而不是家用环境中。这不是因为没有消费级[物联网安全技术][9],但除非产品设计之初就以安全为目标,否则如我们的[智能家居集线器系列][10]中的许多解决方案一样,后期再考虑安全就会增加成本和复杂性。
|
||||
|
||||
在物联网系列的最后这个未来展望的部分,我们将探讨两种基于 Linux 的面向 Docker 的容器技术,这些技术被提出作为物联网安全解决方案。容器还可以帮助解决我们在[物联网框架][11]中探讨的开发复杂性和互操作性障碍的问题。
|
||||
|
||||
我们与 Canonical 的 Ubuntu 客户平台工程副总裁 Oliver Ries 讨论了 Ubuntu Core 和适用于 Docker 的容器式 Snaps 包管理技术。我们还就新的基于 Docker 的物联网方案 ResinOS 采访了 Resin.io 首席执行官和联合创始人 Alexandros Marinos。
|
||||
|
||||
### Ubuntu Core Snaps
|
||||
|
||||
Canonical 面向物联网的 [Snappy Ubuntu Core][12] 版本的 Ubuntu 是围绕一个类似容器的快照包管理机制而构建的,并提供应用商店支持。 snaps 技术最近[自行发布了][13]用于其他 Linux 发行版的版本。去年 11 月 3 日,Canonical 发布了 [Ubuntu Core 16] [14],该版本改进了白标应用商店和更新控制服务。
|
||||
|
||||
|
||||
|
||||
![](http://hackerboards.com/files/canonical_ubuntucore16_diagram.jpg)
|
||||
|
||||
|
||||
*传统 Ubuntu(左)架构 与 Ubuntu Core 16*
|
||||
|
||||
快照机制提供自动更新,并有助于阻止未经授权的更新。 使用事务系统管理,快照可确保更新按预期部署或根本不部署。 在 Ubuntu Core 中,使用 AppArmor 进一步加强了安全性,并且所有应用程序文件都是只读的且保存在隔离的孤岛中。
|
||||
|
||||
![](http://hackerboards.com/files/limesdr-thm.jpg)
|
||||
|
||||
*LimeSDR*
|
||||
|
||||
Ubuntu Core 是我们最近展开的[开源物联网操作系统调查][16]的一部分,现在运行于 Gumstix 主板、Erle 机器人无人机、Dell Edge 网关、[Nextcloud Box][17]、LimeSDR、Mycroft 家庭集线器、英特尔的 Joule 和符合 Linaro 的 96Boards 规范的 SBC(单板计算机) 上。 Canonical 公司还与 Linaro 物联网和嵌入式(LITE)部门集团在其 [96Boards 物联网版(IE)][18] 上达成合作。最初,96Boards IE 专注于 Zephyr 驱动的 Cortex-M4 板卡,如 Seeed 的 [BLE Carbon] [19],不过它将扩展到可以运行 Ubuntu Core 的网关板卡上。
|
||||
|
||||
“Ubuntu Core 和 snaps 具有从边缘到网关到云的相关性,”Canonical 的 Ries 说。 “能够在任何主要发行版(包括 Ubuntu Server 和 Ubuntu for Cloud)上运行快照包,使我们能够提供一致的体验。 snaps 可以使用事务更新以免故障方式升级,可用于安全性更新、错误修复或新功能的持续更新,这在物联网环境中非常重要。”
|
||||
|
||||
![](http://hackerboards.com/files/nextcloud_box3-thm.jpg)
|
||||
|
||||
*Nextcloud盒子*
|
||||
|
||||
安全性和可靠性是关注的重点,Ries 说。 “snaps 应用可以完全独立于彼此和操作系统而运行,使得两个应用程序可以安全地在单个网关上运行,”他说。 “snaps 是只读的和经过认证的,可以保证代码的完整性。
|
||||
|
||||
Ries 还说这种技术减少开发时间。 “snap 软件包允许开发人员向支持它的任何平台提供相同的二进制包,从而降低开发和测试成本,减少部署时间和提高更新速度。 “使用 snap 软件包,开发人员完可以全控制开发生命周期,并可以立即更新。 snap 包提供了所有必需的依赖项,因此开发人员可以选择定制他们使用的组件。”
|
||||
|
||||
### ResinOS: 为 IoT 而生的 Docker
|
||||
|
||||
Resin.io 公司,与其商用的 IoT 框架同名,最近剥离了该框架的基于 Yocto Linux 的 [ResinOS 2.0][20],ResinOS 2.0 将作为一个独立的开源项目运营。 Ubuntu Core 在 snap 包中运行 Docker 容器引擎,ResinOS 在主机上运行 Docker。 极致简约的 ResinOS 抽离了使用 Yocto 代码的复杂性,使开发人员能够快速部署 Docker 容器。
|
||||
|
||||
|
||||
|
||||
![](http://hackerboards.com/files/resinio_resinos_arch.jpg)
|
||||
|
||||
|
||||
*ResinOS 2.0 架构*
|
||||
|
||||
与基于 Linux 的 CoreOS 一样,ResinOS 集成了 systemd 控制服务和网络协议栈,可通过异构网络安全地部署更新的应用程序。 但是,它是为在资源受限的设备(如 ARM 黑客板)上运行而设计的,与之相反,CoreOS 和其他基于 Docker 的操作系统(例如基于 Red Hat 的 Project Atomic)目前仅能运行在 x86 上,并且更喜欢资源丰富的服务器平台。 ResinOS 可以在 20 中 Linux 设备上运行,并不断增长,包括 Raspberry Pi,BeagleBone 和Odroid-C1 等。
|
||||
|
||||
“我们认为 Linux 容器对嵌入式系统比对于云更重要,”Resin.io 的 Marinos 说。 “在云中,容器代表了对之前的进程的优化,但在嵌入式中,它们代表了姗姗来迟的通用虚拟化“
|
||||
|
||||
![](http://hackerboards.com/files/beaglebone-hand-thm.jpg)
|
||||
|
||||
*BeagleBone Black*
|
||||
|
||||
当应用于物联网时,完整的企业级虚拟机有直接访问硬件的限制的性能缺陷,Marinos 说。像 OSGi 和 Android 的Dalvik 这样的移动设备虚拟机可以用于 IoT,但是它们依赖 Java 并有其他限制。
|
||||
|
||||
对于企业开发人员来说,使用 Docker 似乎很自然,但是你如何说服嵌入式黑客转向全新的范式呢? “Marinos 解释说,”ResinOS 不是把云技术的实践经验照单全收,而是针对嵌入式进行了优化。”此外,他说,容器比典型的物联网技术更好地包容故障。 “如果有软件缺陷,主机操作系统可以继续正常工作,甚至保持连接。要恢复,您可以重新启动容器或推送更新。更新设备而不重新启动它的能力进一步消除了故障引发问题的机率。”
|
||||
|
||||
据 Marinos 所说,其他好处源自与云技术的一致性,例如拥有更广泛的开发人员。容器提供了“跨数据中心和边缘的统一范式,以及一种方便地将技术、工作流、基础设施,甚至应用程序转移到边缘(终端)的方式。”
|
||||
|
||||
Marinos 说,容器中的固有安全性优势正在被其他技术增强。 “随着 Docker 社区推动实现镜像签名和鉴证,这些自然会转移并应用到 ResinOS,”他说。 “当 Linux 内核被强化以提高容器安全性时,或者获得更好地管理容器所消耗的资源的能力时,会产生类似的好处。
|
||||
|
||||
容器也适合开源 IoT 框架,Marinos 说。 “Linux 容器很容易与几乎各种协议、应用程序、语言和库结合使用,”Marinos 说。 “Resin.io 参加了 AllSeen 联盟,我们与使用 IoTivity 和 Thread的 伙伴一起合作。”
|
||||
|
||||
### IoT的未来:智能网关与智能终端
|
||||
|
||||
Marinos 和 Canonical 的 Ries 对未来物联网的几个发展趋势具有一致的看法。 首先,物联网的最初概念(其中基于 MCU 的端点直接与云进行通信以进行处理)正在迅速被雾化计算架构所取代。 这需要更智能的网关,也需要比仅仅在 ZigBee 和 WiFi 之间聚合和转换数据更多的功能。
|
||||
|
||||
其次,网关和智能边缘设备越来越多地运行多个应用程序。 第三,许多这些设备将提供板载分析,这些在最新的[智能家居集线器][22]上都有体现。 最后,富媒体将很快成为物联网组合的一部分。
|
||||
|
||||
|
||||
![](http://hackerboards.com/files/eurotech_reliagate2026.jpg)
|
||||
|
||||
|
||||
*最新设备网关: Eurotech 的 [ReliaGate 20-26][1]*
|
||||
|
||||
![](http://hackerboards.com/files/advantech_ubc221.jpg)
|
||||
|
||||
|
||||
*最新设备网关: Advantech 的 [UBC-221][2]*
|
||||
|
||||
“智能网关正在接管最初为云服务设计的许多处理和控制功能,”Marinos 说。 “因此,我们看到对容器化的推动力在增加,可以在 IoT 设备中使用类似云工作流程来部署与功能和安全相关的优化。去中心化是由移动数据紧缩、不断发展的法律框架和各种物理限制等因素驱动的。”
|
||||
|
||||
Ubuntu Core 等平台正在使“可用于网关的软件爆炸式增长”,Canonical 的 Ries 说。 “在单个设备上运行多个应用程序的能力吸引了众多单一功能设备的用户,以及现在可以产生持续的软件收入的设备所有者。”
|
||||
|
||||
![](http://hackerboards.com/files/myomega_mynxg-sm.jpg)
|
||||
|
||||
*两种 IoT 网关: [MyOmega MYNXG IC2 Controller][3]*
|
||||
|
||||
![](http://hackerboards.com/files/technexion_ls1021aiot_front-sm.jpg)
|
||||
|
||||
*两种 IoT 网关: TechNexion 的 [LS1021A-IoT Gateway][4]*
|
||||
|
||||
不仅是网关 - 终端也变得更聪明。 “阅读大量的物联网新闻报道,你得到的印象是所有终端都运行在微控制器上,”Marinos 说。 “但是我们对大量的 Linux 终端,如数字标牌,无人机和工业机械等直接执行任务,而不是作为操作中介(数据转发)感到惊讶。我们称之为影子 IoT。”
|
||||
|
||||
Canonical 的 Ries 同意,对简约技术的专注使他们忽视了新兴物联网领域。 “轻量化的概念在一个发展速度与物联网一样快的行业中初现端倪,”Ries 说。 “今天的高级消费硬件可以持续为终端供电数月。”
|
||||
|
||||
虽然大多数物联网设备将保持轻量和“无头”(一种配置方式,比如物联网设备缺少显示器,键盘等),它们装备有如加速度计和温度传感器这样的传感器并通过低速率的数据流通信,但是许多较新的物联网应用已经使用富媒体。 “媒体输入/输出只是另一种类型的外设,”Marinos 说。 “总是存在多个容器竞争有限资源的问题,但它与传感器或蓝牙竞争天线资源没有太大区别。”
|
||||
|
||||
Ries 看到了工业和家庭网关中“提高边缘智能”的趋势。 “我们看到人工智能、机器学习、计算机视觉和上下文意识的大幅上升,”Ries 说。 “为什么要在云中运行面部检测软件,如果相同的软件可以在边缘设备运行而又没有网络延迟和带宽及计算成本呢?“
|
||||
|
||||
当我们在这个物联网系列的[开篇故事][27]中探索时,我们发现存在与安全相关的物联网问题,例如隐私丧失和生活在监视文化中的权衡。还有一些问题如把个人决策交给可能由他人操控的 AI 裁定。这些不会被容器,快照或任何其他技术完全解决。
|
||||
|
||||
如果 AWS Alexa 可以处理生活琐事,而我们专注在要事上,也许我们会更快乐。或许有一个方法来平衡隐私和效用,现在,我们仍在探索,如此甚好。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://hackerboards.com/can-linux-containers-save-iot-from-a-security-meltdown/
|
||||
|
||||
作者:[Eric Brown][a]
|
||||
译者:[firstadream](https://github.com/firstadream)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://hackerboards.com/can-linux-containers-save-iot-from-a-security-meltdown/
|
||||
[1]:http://hackerboards.com/atom-based-gateway-taps-new-open-source-iot-cloud-platform/
|
||||
[2]:http://hackerboards.com/compact-iot-gateway-runs-yocto-linux-on-quark/
|
||||
[3]:http://hackerboards.com/wireless-crazed-customizable-iot-gateway-uses-arm-or-x86-coms/
|
||||
[4]:http://hackerboards.com/iot-gateway-runs-linux-on-qoriq-accepts-arduino-shields/
|
||||
[5]:http://hackerboards.com/linux-and-open-source-hardware-for-building-iot-devices/
|
||||
[6]:http://hackerboards.com/intel-launches-14nm-atom-e3900-and-spins-an-automotive-version/
|
||||
[7]:http://hackerboards.com/samsung-adds-first-64-bit-and-cortex-m4-based-artik-modules/
|
||||
[8]:http://hackerboards.com/new-cortex-m-chips-add-armv8-and-trustzone/
|
||||
[9]:http://hackerboards.com/exploring-security-challenges-in-linux-based-iot-devices/
|
||||
[10]:http://hackerboards.com/linux-based-smart-home-hubs-advance-into-ai/
|
||||
[11]:http://hackerboards.com/open-source-projects-for-the-internet-of-things-from-a-to-z/
|
||||
[12]:http://hackerboards.com/lightweight-snappy-ubuntu-core-os-targets-iot/
|
||||
[13]:http://hackerboards.com/canonical-pushes-snap-as-a-universal-linux-package-format/
|
||||
[14]:http://hackerboards.com/ubuntu-core-16-gets-smaller-goes-all-snaps/
|
||||
[15]:http://hackerboards.com/files/canonical_ubuntucore16_diagram.jpg
|
||||
[16]:http://hackerboards.com/open-source-oses-for-the-internet-of-things/
|
||||
[17]:http://hackerboards.com/private-cloud-server-and-iot-gateway-runs-ubuntu-snappy-on-rpi/
|
||||
[18]:http://hackerboards.com/linaro-beams-lite-at-internet-of-things-devices/
|
||||
[19]:http://hackerboards.com/96boards-goes-cortex-m4-with-iot-edition-and-carbon-sbc/
|
||||
[20]:http://hackerboards.com/can-linux-containers-save-iot-from-a-security-meltdown/%3Ca%20href=
|
||||
[21]:http://hackerboards.com/files/resinio_resinos_arch.jpg
|
||||
[22]:http://hackerboards.com/linux-based-smart-home-hubs-advance-into-ai/
|
||||
[23]:http://hackerboards.com/files/eurotech_reliagate2026.jpg
|
||||
[24]:http://hackerboards.com/files/advantech_ubc221.jpg
|
||||
[25]:http://hackerboards.com/files/myomega_mynxg.jpg
|
||||
[26]:http://hackerboards.com/files/technexion_ls1021aiot_front.jpg
|
||||
[27]:http://hackerboards.com/an-open-source-perspective-on-the-internet-of-things-part-1/
|
||||
[28]:http://hackerboards.com/can-linux-containers-save-iot-from-a-security-meltdown/
|
@ -1,8 +1,7 @@
|
||||
如何在 Ubuntu16.04 中用 Apache 部署 Jenkins 自动化服务器
|
||||
============================================================
|
||||
|
||||
|
||||
Jenkins 是从 Hudson 项目衍生出来的自动化服务器。Jenkins 是一个基于服务器的应用程序,运行在 Java servlet 容器中,它支持包括 Git、SVN 以及 Mercurial 在内的多种 SCM(Source Control Management,源码控制工具)。Jenkins 提供了上百种插件帮助你的项目实现自动化。Jenkins 由 Kohsuke Kawaguchi 开发,在 2011 年使用 MIT 协议发布了第一个发行版,它是个免费软件。
|
||||
Jenkins 是从 Hudson 项目衍生出来的自动化服务器。Jenkins 是一个基于服务器的应用程序,运行在 Java servlet 容器中,它支持包括 Git、SVN 以及 Mercurial 在内的多种 SCM(Source Control Management,源码控制工具)。Jenkins 提供了上百种插件帮助你的项目实现自动化。Jenkins 由 Kohsuke Kawaguchi 开发,在 2011 年使用 MIT 协议发布了第一个发行版,它是个自由软件。
|
||||
|
||||
在这篇指南中,我会向你介绍如何在 Ubuntu 16.04 中安装最新版本的 Jenkins。我们会用自己的域名运行 Jenkins,在 apache web 服务器中安装和配置 Jenkins,而且支持反向代理。
|
||||
|
||||
@ -17,22 +16,28 @@ Jenkins 基于 Java,因此我们需要在服务器上安装 Java OpenJDK 7。
|
||||
|
||||
默认情况下,Ubuntu 16.04 没有安装用于管理 PPA 仓库的 python-software-properties 软件包,因此我们首先需要安装这个软件。使用 apt 命令安装 python-software-properties。
|
||||
|
||||
`apt-get install python-software-properties`
|
||||
```
|
||||
apt-get install python-software-properties
|
||||
```
|
||||
|
||||
下一步,添加 Java PPA 仓库到服务器中。
|
||||
|
||||
`add-apt-repository ppa:openjdk-r/ppa`
|
||||
```
|
||||
add-apt-repository ppa:openjdk-r/ppa
|
||||
```
|
||||
|
||||
输入回车键
|
||||
用 apt 命令更新 Ubuntu 仓库并安装 Java OpenJDK。
|
||||
|
||||
用 apt 命令更新 Ubuntu 仓库并安装 Java OpenJDK。`
|
||||
|
||||
`apt-get update`
|
||||
`apt-get install openjdk-7-jdk`
|
||||
```
|
||||
apt-get update
|
||||
apt-get install openjdk-7-jdk
|
||||
```
|
||||
|
||||
输入下面的命令验证安装:
|
||||
|
||||
`java -version`
|
||||
```
|
||||
java -version
|
||||
```
|
||||
|
||||
你会看到安装到服务器上的 Java 版本。
|
||||
|
||||
@ -46,21 +51,29 @@ Jenkins 给软件安装包提供了一个 Ubuntu 仓库,我们会从这个仓
|
||||
|
||||
用下面的命令添加 Jenkins 密钥和仓库到系统中。
|
||||
|
||||
`wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -`
|
||||
`echo 'deb https://pkg.jenkins.io/debian-stable binary/' | tee -a /etc/apt/sources.list`
|
||||
```
|
||||
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
|
||||
echo 'deb https://pkg.jenkins.io/debian-stable binary/' | tee -a /etc/apt/sources.list
|
||||
```
|
||||
|
||||
更新仓库并安装 Jenkins。
|
||||
|
||||
`apt-get update`
|
||||
`apt-get install jenkins`
|
||||
```
|
||||
apt-get update
|
||||
apt-get install jenkins
|
||||
```
|
||||
|
||||
安装完成后,用下面的命令启动 Jenkins。
|
||||
|
||||
`systemctl start jenkins`
|
||||
```
|
||||
systemctl start jenkins
|
||||
```
|
||||
|
||||
通过检查 Jenkins 默认使用的端口(端口 8080)验证 Jenkins 正在运行。我会像下面这样用 netstat 命令检测:
|
||||
通过检查 Jenkins 默认使用的端口(端口 8080)验证 Jenkins 正在运行。我会像下面这样用 `netstat` 命令检测:
|
||||
|
||||
`netstat -plntu`
|
||||
```
|
||||
netstat -plntu
|
||||
```
|
||||
|
||||
Jenkins 已经安装好了并运行在 8080 端口。
|
||||
|
||||
@ -70,23 +83,29 @@ Jenkins 已经安装好了并运行在 8080 端口。
|
||||
|
||||
### 第三步 - 为 Jenkins 安装和配置 Apache 作为反向代理
|
||||
|
||||
在这篇指南中,我们会在一个 apache web 服务器中运行 Jenkins,我们会为 Jenkins 配置 apache 作为反向代理。首先我会安装 apache 并启用一些需要的模块,然后我会为 Jenkins 用域名 my.jenkins.id 创建虚拟 host 文件。请在这里使用你自己的域名并在所有配置文件中出现的地方替换。
|
||||
在这篇指南中,我们会在一个 Apache web 服务器中运行 Jenkins,我们会为 Jenkins 配置 apache 作为反向代理。首先我会安装 apache 并启用一些需要的模块,然后我会为 Jenkins 用域名 my.jenkins.id 创建虚拟主机文件。请在这里使用你自己的域名并在所有配置文件中出现的地方替换。
|
||||
|
||||
从 Ubuntu 仓库安装 apache2 web 服务器。
|
||||
|
||||
`apt-get install apache2`
|
||||
```
|
||||
apt-get install apache2
|
||||
```
|
||||
|
||||
安装完成后,启用 proxy 和 proxy_http 模块以便将 apache 配置为 Jenkins 的前端服务器/反向代理。
|
||||
|
||||
`a2enmod proxy`
|
||||
`a2enmod proxy_http`
|
||||
```
|
||||
a2enmod proxy
|
||||
a2enmod proxy_http
|
||||
```
|
||||
|
||||
下一步,在 sites-available 目录创建新的虚拟 host 文件。
|
||||
下一步,在 `sites-available` 目录创建新的虚拟主机文件。
|
||||
|
||||
`cd /etc/apache2/sites-available/`
|
||||
`vim jenkins.conf`
|
||||
```
|
||||
cd /etc/apache2/sites-available/
|
||||
vim jenkins.conf
|
||||
```
|
||||
|
||||
粘贴下面的虚拟 host 配置。
|
||||
粘贴下面的虚拟主机配置。
|
||||
|
||||
```
|
||||
<Virtualhost *:80>
|
||||
@ -106,18 +125,24 @@ Jenkins 已经安装好了并运行在 8080 端口。
|
||||
</Virtualhost>
|
||||
```
|
||||
|
||||
保存文件。然后用 a2ensite 命令激活 Jenkins 虚拟 host。
|
||||
保存文件。然后用 `a2ensite` 命令激活 Jenkins 虚拟主机。
|
||||
|
||||
`a2ensite jenkins`
|
||||
```
|
||||
a2ensite jenkins
|
||||
```
|
||||
|
||||
重启 Apache 和 Jenkins。
|
||||
|
||||
`systemctl restart apache2`
|
||||
`systemctl restart jenkins`
|
||||
```
|
||||
systemctl restart apache2
|
||||
systemctl restart jenkins
|
||||
```
|
||||
|
||||
检查 Jenkins 和 Apache 正在使用 80 和 8080 端口。
|
||||
|
||||
`netstat -plntu`
|
||||
```
|
||||
netstat -plntu
|
||||
```
|
||||
|
||||
[
|
||||
![检查 Apache 和 Jenkins 是否在运行](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/3.png)
|
||||
@ -127,29 +152,30 @@ Jenkins 已经安装好了并运行在 8080 端口。
|
||||
|
||||
Jenkins 用域名 'my.jenkins.id' 运行。打开你的 web 浏览器然后输入 URL。你会看到要求你输入初始管理员密码的页面。Jenkins 已经生成了一个密码,因此我们只需要显示并把结果复制到密码框。
|
||||
|
||||
用 cat 命令显示 Jenkins 初始管理员密码。
|
||||
|
||||
`cat /var/lib/jenkins/secrets/initialAdminPassword`
|
||||
用 `cat` 命令显示 Jenkins 初始管理员密码。
|
||||
|
||||
```
|
||||
cat /var/lib/jenkins/secrets/initialAdminPassword
|
||||
a1789d1561bf413c938122c599cf65c9
|
||||
```
|
||||
|
||||
[
|
||||
![获取 Jenkins 管理员密码](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/4.png)
|
||||
][12]
|
||||
|
||||
将结果粘贴到密码框然后点击 ‘**Continue**’。
|
||||
将结果粘贴到密码框然后点击 Continue。
|
||||
|
||||
[
|
||||
![安装和配置 Jenkins](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/5.png)
|
||||
][13]
|
||||
|
||||
现在为了后面能比较好的使用,我们需要在 Jenkins 中安装一些插件。选择 ‘**Install Suggested Plugin**’,点击它。
|
||||
现在为了后面能比较好的使用,我们需要在 Jenkins 中安装一些插件。选择 Install Suggested Plugin,点击它。
|
||||
|
||||
[
|
||||
![安装 Jenkins 插件](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/6.png)
|
||||
][14]
|
||||
|
||||
Jenkins 插件安装过程
|
||||
Jenkins 插件安装过程:
|
||||
|
||||
[
|
||||
![Jenkins 安装完插件](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/7.png)
|
||||
@ -199,27 +225,29 @@ Jenkins 在 ‘**Access Control**’ 部分提供了多种认证方法。为了
|
||||
![在 Jenkins 中创建新的任务](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/13.png)
|
||||
][21]
|
||||
|
||||
输入任务的名称,在这里我用 ‘Checking System’,选择 ‘**Freestyle Project**’ 然后点击 ‘**OK**’。
|
||||
输入任务的名称,在这里我输入 ‘Checking System’,选择 Freestyle Project 然后点击 OK。
|
||||
|
||||
[
|
||||
![配置 Jenkins 任务](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/14.png)
|
||||
][22]
|
||||
|
||||
进入 ‘**Build**’ 标签页。在 ‘**Add build step**’,选择选项 ‘**Execute shell**’。
|
||||
进入 Build 标签页。在 Add build step,选择选项 Execute shell。
|
||||
|
||||
在输入框输入下面的命令。
|
||||
|
||||
`top -b -n 1 | head -n 5`
|
||||
```
|
||||
top -b -n 1 | head -n 5
|
||||
```
|
||||
|
||||
点击 ‘**Save**’。
|
||||
点击 Save。
|
||||
|
||||
[
|
||||
![启动 Jenkins 任务](https://www.howtoforge.com/images/how-to-install-jenkins-with-apache-on-ubuntu-16-04/15.png)
|
||||
][23]
|
||||
|
||||
现在你是在任务 ‘Project checking system’的任务页。点击 ‘**Build Now**’ 执行任务 ‘checking system’。
|
||||
现在你是在任务 ‘Project checking system’ 的任务页。点击 Build Now 执行任务 ‘checking system’。
|
||||
|
||||
任务执行完成后,你会看到 ‘**Build History**’,点击第一个任务查看结果。
|
||||
任务执行完成后,你会看到 Build History,点击第一个任务查看结果。
|
||||
|
||||
下面是 Jenkins 任务执行的结果。
|
||||
|
||||
@ -233,9 +261,9 @@ Jenkins 在 ‘**Access Control**’ 部分提供了多种认证方法。为了
|
||||
|
||||
via: https://www.howtoforge.com/tutorial/how-to-install-jenkins-with-apache-on-ubuntu-16-04/
|
||||
|
||||
作者:[Muhammad Arul ][a]
|
||||
作者:[Muhammad Arul][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,68 +1,67 @@
|
||||
该死,原生移动应用的开发成本太高了!
|
||||
============================================================
|
||||
|
||||
### 一个有价值的命题
|
||||
> 一个有价值的命题
|
||||
|
||||
我们遇到了一个临界点。除去几个比较好的用例之外,使用原生框架和原生应用开发团队构建、维护移动应用再也没有意义了。
|
||||
我们遇到了一个临界点。除去少数几个特别的的用例之外,使用原生框架和原生应用开发团队构建、维护移动应用再也没有意义了。
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/1000/1*4nyeufIIgw9B7nMSr5Sybg.jpeg)
|
||||
|
||||
在美国,雇佣 iOS,Android,JavaScript 开发人员的平均花费([http://www.indeed.com/salary][1],[http://www.payscale.com/research/US/Skill=JavaScript/Salary][2])
|
||||
*在美国,雇佣 [iOS,Android][1],[JavaScript][2] 开发人员的平均花费*
|
||||
|
||||
在过去的几年,原生移动应用开发的费用螺旋式上升,无法控制。对没有大量资金的新创业者来说,创建原生应用、MVP 设计架构和原型的难度大大增加。现有的公司需要抓住人才,以便在现有应用上进行迭代开发或者构建一个新的应用。要尽一切努力留住最好的人才,与 [世界各地的公司][9] 拼尽全力 [争][6] 个 [高][7] [下][8]。
|
||||
在过去的几年,原生移动应用开发的费用螺旋式上升,无法控制。对没有大量资金的新创业者来说,创建原生应用、MVP 设计架构和原型的难度大大增加。现有的公司需要抓住人才,以便在现有应用上进行迭代开发或者构建一个新的应用。要尽一切努力才能留住最好的人才,与 [世界各地的公司][9] 拼尽全力[争个][6][高][7][下][8]。
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*imThyh2e45RW1np0xXIE4Q.png)
|
||||
|
||||
2015年初,原生方式和混合方式开发 MVP 设计架构的费用对比([Comomentum.com][3])
|
||||
*2015 年初,原生方式和混合方式开发 MVP 设计架构的费用[对比][3]*
|
||||
|
||||
### 这一切对于我们意味着什么?
|
||||
|
||||
如果你的公司很大或者有足够多的现金,旧思维是只要你在原生应用开发方面投入足够多的资金,就高枕无忧。但事实不再如此。
|
||||
|
||||
Facebook 是你最不会想到的在人才战中失败的公司(因为他们没有失败),它也遇到了原生应用方面金钱无法解决的问题。他们的移动应用庞大而又复杂,[可以看到编译它竟然需要15分钟][10]。这意味着哪怕是极小的用户界面改动,比如移动几个点,测试起来都要花费几个小时(甚至几天)。
|
||||
Facebook 是你最不会想到的在人才战中失败的公司(因为他们没有失败),它也遇到了原生应用方面金钱无法解决的问题。他们的移动应用庞大而又复杂,[他们发现编译它竟然需要 15 分钟][10]。这意味着哪怕是极小的用户界面改动,比如移动几个点,测试起来都要花费几个小时(甚至几天)。
|
||||
|
||||
除了冗长的编译时间,应用的每一个小改动在测试时都需要在两个完全不同的环境(IOS 和 Android)实施,开发团队需要使用两种语言和框架工作,这趟水更浑了。
|
||||
|
||||
Facebook 对这个问题的解决方案是 [React Native][11]。
|
||||
|
||||
### 能不能抛弃移动应用,仅面向Web呢?
|
||||
### 能不能抛弃移动应用,仅面向 Web 呢?
|
||||
|
||||
[一些人认为移动应用的末日已到。][12] 尽管我很欣赏、尊重 [Eric Elliott][13] 和他的工作,但我们还是通过考察一些近期的数据,进而讨论一下某些相反的观点:
|
||||
[一些人认为移动应用的末日已到][12]。尽管我很欣赏、尊重 [Eric Elliott][13] 和他的工作,但我们还是通过考察一些近期的数据,进而讨论一下某些相反的观点:
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*s0O7X2PgIqP5_zselxQdqQ.png)
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*s0O7X2PgIqP5_zselxQdqQ.png)
|
||||
|
||||
人们在移动应用上花费的时间(2016年4月,[smartinsights.com][4])
|
||||
*人们在移动应用上花费的[时间][4](2016年4月)*
|
||||
|
||||
> 人们使用 APP 的时间占使用手机总时长的 90%
|
||||
|
||||
目前世界上有 25 亿人在使用移动手机。[这个数字增长到 50 亿的速度会比我们想象的还要快。][14] 在正常情况下,丢掉 45 亿人的生意,或者抛弃有 45 亿人使用的应用程序是绝对荒唐且行不通的。
|
||||
|
||||
老问题是原生移动应用的开发成本对大多数公司来说太高了。尽管这个问题确实存在,但面向 web 的开发成本也在增加。[在美国,JavaScript 开发者的平均工资已达到 $97,000.00。][15]
|
||||
老问题是原生移动应用的开发成本对大多数公司来说太高了。然而,面向 web 的开发成本也在增加。[在美国,JavaScript 开发者的平均工资已达到 $97,000.00][15]。
|
||||
|
||||
伴随着复杂性的增加以及暴涨的高质量 web 开发需求,雇佣一个JavaScript 开发者的平均价格直逼原生应用开发者。论证 web 开发更便宜已经没用了。
|
||||
伴随着复杂性的增加以及对高质量 web 开发的需求暴涨,雇佣一个 JavaScript 开发者的平均价格直逼原生应用开发者。论证 web 开发更便宜已经没用了。
|
||||
|
||||
### 那混合开发呢?
|
||||
|
||||
混合应用是将 HTML5 应用内嵌在原生应用的容器里,并且提供实现原生平台特性所需的权限。Cordova 和 PhoneGap 就是典型的例子。
|
||||
|
||||
如果你想构建一个 MVP 设计架构、一个产品原型,或者不担心模仿原生应用的用户体验,那么混合应用会很适合你。谨记如果你最后想把它转为原生应用,整个项目都得重写。
|
||||
如果你想构建一个 MVP 设计架构、一个产品原型,或者不担心对原生应用的模仿的用户体验,那么混合应用会很适合你。但谨记如果你最后想把它转为原生应用,整个项目都得重写。
|
||||
|
||||
此领域有很多创新的东西,我最喜欢的当属 [Ionic Framework][16]。混合开发正变得越来越好,但还不如原生开发那么流畅自然。
|
||||
|
||||
有很多公司,包括最严峻的初创公司,也包括大中规模的公司,混合应用在质量上的表现似乎没有满足客户的要求,给人的感觉是活糙、不够专业。
|
||||
|
||||
[听说应用商店里的前 100 名都不是混合应用,][17]我没有证据支持这一观点。如果说有百分之零到百分之五是混合应用,我就不怀疑了。
|
||||
[听说应用商店里的前 100 名都不是混合应用][17],我没有证据支持这一观点。如果说有百分之零到百分之五是混合应用,我就不怀疑了。
|
||||
|
||||
> [我们最大的错误是在 HTML5 身上下了太多的赌注][18] — 马克 扎克伯格
|
||||
> [我们最大的错误是在 HTML5 身上下了太多的赌注][18] — 马克·扎克伯格
|
||||
|
||||
### 解决方案
|
||||
|
||||
如果你紧跟移动开发动向,那么你绝对听说过像 [NativeScript][19] 和 [React Native][20] 这样的项目。
|
||||
|
||||
通过这些项目,使用用 JavaScript 写成的基本 UI 组成块,像常规 iOS 和 Android 应用那样,就可以构建出高质量的原生移动应用。
|
||||
通过这些项目,使用由 JavaScript 写成的基本 UI 组成块,像常规 iOS 和 Android 应用那样,就可以构建出高质量的原生移动应用。
|
||||
|
||||
你可以仅用一位工程师,也可以用一个专业的工程师团队,通过 React Native 使用 [现有代码库][22] 或者 [底层技术][23] 进行跨平台移动应用开发,[原生桌面开发][21], 甚至还有 web 开发。把你的应用发布到 APP Store上, Play Store上,还有 Web 上。如此可以在保证不丧失原生应用性能和质量的同时,使成本仅占传统开发的一小部分。
|
||||
你可以仅用一位工程师,也可以用一个专业的工程师团队,通过 React Native 使用 [现有代码库][22] 或者 [底层技术][23] 进行跨平台移动应用开发、[原生桌面开发][21],甚至还有 web 开发。把你的应用发布到 APP Store 上、 Play Store 上,还有 Web 上。如此可以在保证不丧失原生应用性能和质量的同时,使成本仅占传统开发的一小部分。
|
||||
|
||||
通过 React Native 进行跨平台开发时重复使用其中 90% 的代码也不是没有的事,这个范围通常是 80% 到 90%。
|
||||
|
||||
@ -72,7 +71,7 @@ Facebook 对这个问题的解决方案是 [React Native][11]。
|
||||
|
||||
React Native 还可以使用 [Code Push][24] 和 [AppHub][25] 这样的工具来远程更新你的 JavaScript 代码。这意味着你可以向用户实时推送更新、新特性,快速修复 bug,绕过打包、发布这些工作,绕过 App Store、Google Play Store 的审核,省去了耗时 2 到 7 天的过程(App Store 一直是整个过程的痛点)。混合应用的这些优势原生应用不可能比得上。
|
||||
|
||||
如果这个领域的创新力能像刚发行时那样保持,将来你甚至可以为 [Apple Watch ][26],[Apple TV][27],和 [Tizen][28] 这样的平台开发应用。
|
||||
如果这个领域的创新力能像刚发行时那样保持,将来你甚至可以为 [Apple Watch][26]、[Apple TV][27],和 [Tizen][28] 这样的平台开发应用。
|
||||
|
||||
> NativeScript 依然是个相当年轻的框架驱动,Angular 版本 2,[上个月刚刚发布测试版][29]。但只要它保持良好的市场份额,未来就很有前途。
|
||||
|
||||
@ -84,49 +83,57 @@ React Native 还可以使用 [Code Push][24] 和 [AppHub][25] 这样的工具
|
||||
|
||||
看下面的例子,[这是一个使用 React Native 技术的著名应用列表][31]。
|
||||
|
||||
### Facebook
|
||||
#### Facebook
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*36atCP-kVNoYrit2RMR-8g.jpeg)
|
||||
|
||||
Facebook 公司的 React Native 应用
|
||||
*Facebook 公司的 React Native 应用*
|
||||
|
||||
Facebook 的两款应用 [Ads Manager][32] 和 [Facebook Groups][33]都在使用 React Native 技术,并且[将会应用到实现动态消息的框架上][34]。
|
||||
Facebook 的两款应用 [Ads Manager][32] 和 [Facebook Groups][33] 都在使用 React Native 技术,并且[将会应用到实现动态消息的框架上][34]。
|
||||
|
||||
Facebook 也会投入大量的资金创立和维护像 React Native 这样的开源项目,而且开源项目的开发者最近已经创建很多了不起的项目,这是很了不起的工作,像我以及全世界的业务每天都从中享受诸多好处。
|
||||
|
||||
### Instagram
|
||||
#### Instagram
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*MQ0ezjRsUW3A5I0ahryHPg.jpeg)
|
||||
|
||||
Instagram
|
||||
*Instagram*
|
||||
|
||||
Instagram 应用的一部分已经使用了 React Native 技术。
|
||||
|
||||
### Airbnb
|
||||
#### Airbnb
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*JS3R_cfLsDFCmAZJmtVEvg.jpeg)
|
||||
|
||||
Airbnb
|
||||
*Airbnb*
|
||||
|
||||
Airbnb 的很多东西正用 React Native 重写。(来自 [Leland Richardson][36])
|
||||
|
||||
超过 90% 的 Airbnb 旅行平台都是用 React Native 写的。(来自 [spikebrehm][37])
|
||||
|
||||
### Vogue
|
||||
#### Vogue
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*V9JMA2L3lXcO1nczCN3gcA.jpeg)
|
||||
|
||||
Vogue 是 2016 年度十佳应用之一
|
||||
*Vogue 是 2016 年度十佳应用之一*
|
||||
|
||||
Vogue 这么突出不仅仅因为它也用 React Native 写成,而是[因为它被苹果公司评为年度十佳应用之一][38]。
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*vPDVV-vwvjfL3MsHpOO8rQ.jpeg)
|
||||
|
||||
微软
|
||||
#### 沃尔玛
|
||||
|
||||
微软在 React Native 身上下的赌注很大
|
||||
![](https://cdn-images-1.medium.com/max/800/1*ZlUk9AGwfOAPKdEBpa8avg.jpeg)
|
||||
|
||||
它早已发布多个开源工具,包括 [Code Push][39],[React Native VS Code][40],以及 [React Native Windows][41],旨在帮助开发者向 React Native 领域转移。
|
||||
*Walmart Labs*
|
||||
|
||||
查看这篇 [Keerti](https://medium.com/@Keerti) 的[文章](https://medium.com/walmartlabs/react-native-at-walmartlabs-cdd140589560#.azpn97g8t)来了解沃尔玛是怎样看待 React Native 的优势的。
|
||||
|
||||
#### 微软
|
||||
|
||||
微软在 React Native 身上下的赌注很大。
|
||||
|
||||
它早已发布多个开源工具,包括 [Code Push][39]、[React Native VS Code][40],以及 [React Native Windows][41],旨在帮助开发者向 React Native 领域转移。
|
||||
|
||||
微软考虑的是那些已经使用 React Native 为 iOS 和 Android 开发应用的开发者,他们可以重用高达 90% 的代码,不用花费太多额外的时间和成本就可将应用发布到 Windows 上。
|
||||
|
||||
@ -136,11 +143,11 @@ Vogue 这么突出不仅仅因为它也用 React Native 写成,而是[因为
|
||||
|
||||
移动应用界面设计和移动应用开发要进行范式转变,下一步就是 React Native 以及与其相似的技术。
|
||||
|
||||
公司
|
||||
#### 公司
|
||||
|
||||
如果你的公司正想着削减成本、加快开发速度,而又不想在应用质量和性能上妥协,这是最适合使用 React Native 的时候,它能提高你的净利润。
|
||||
|
||||
开发者
|
||||
#### 开发者
|
||||
|
||||
如果你是一个开发者,想进入一个将来会快速发展的领域,我强烈推荐你把 React Native 列入你的学习清单。
|
||||
|
||||
@ -166,7 +173,7 @@ via: https://hackernoon.com/the-cost-of-native-mobile-app-development-is-too-dam
|
||||
|
||||
作者:[Nader Dabit][a]
|
||||
译者:[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/) 荣誉推出
|
||||
|
237
published/201705/20161221 Living Android without Kotlin.md
Normal file
237
published/201705/20161221 Living Android without Kotlin.md
Normal file
@ -0,0 +1,237 @@
|
||||
在没有 Kotlin 的世界与 Android 共舞
|
||||
============================================================
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/2000/1*Fd349rzh3XWwSbCP2IV7zA.jpeg)
|
||||
|
||||
> 开始投入一件事比远离它更容易。 — Donald Rumsfeld
|
||||
|
||||
没有 Kotlin 的生活就像在触摸板上玩魔兽争霸 3。购买鼠标很简单,但如果你的新雇主不想让你在生产中使用 Kotlin,你该怎么办?
|
||||
|
||||
下面有一些选择。
|
||||
* 与你的产品负责人争取获得使用 Kotlin 的权利。
|
||||
* 使用 Kotlin 并且不告诉其他人因为你知道最好的东西是只适合你的。
|
||||
* 擦掉你的眼泪,自豪地使用 Java。
|
||||
|
||||
想象一下,你在和产品负责人的斗争中失败,作为一个专业的工程师,你不能在没有同意的情况下私自去使用那些时髦的技术。我知道这听起来非常恐怖,特别当你已经品尝到 Kotlin 的好处时,不过不要失去生活的信念。
|
||||
|
||||
在文章接下来的部分,我想简短地描述一些 Kotlin 的特征,使你通过一些知名的工具和库,可以应用到你的 Android 里的 Java 代码中去。对于 Kotlin 和 Java 的基本认识是需要的。
|
||||
|
||||
### 数据类
|
||||
|
||||
我想你肯定已经喜欢上 Kotlin 的数据类。对于你来说,得到 `equals()`、 `hashCode()`、 `toString()` 和 `copy()` 这些是很容易的。具体来说,`data` 关键字还可以按照声明顺序生成对应于属性的 `componentN()` 函数。 它们用于解构声明。
|
||||
|
||||
```
|
||||
data class Person(val name: String)
|
||||
val (riddle) = Person("Peter")
|
||||
println(riddle)
|
||||
```
|
||||
|
||||
你知道什么会被打印出来吗?确实,它不会是从 `Person` 类的 `toString()` 返回的值。这是解构声明的作用,它赋值从 `name` 到 `riddle`。使用园括号 `(riddle)` 编译器知道它必须使用解构声明机制。
|
||||
|
||||
```
|
||||
val (riddle): String = Person("Peter").component1()
|
||||
println(riddle) // prints Peter)
|
||||
```
|
||||
|
||||
> 这个代码没编译。它就是展示了构造声明怎么工作的。
|
||||
|
||||
正如你可以看到 `data` 关键字是一个超级有用的语言特性,所以你能做什么把它带到你的 Java 世界? 使用注释处理器并修改抽象语法树(Abstract Syntax Tree)。 如果你想更深入,请阅读文章末尾列出的文章(Project Lombok— Trick Explained)。
|
||||
|
||||
使用项目 Lombok 你可以实现 `data`关键字所提供的几乎相同的功能。 不幸的是,没有办法进行解构声明。
|
||||
|
||||
```
|
||||
import lombok.Data;
|
||||
|
||||
@Data class Person {
|
||||
final String name;
|
||||
}
|
||||
```
|
||||
|
||||
`@Data` 注解生成 `equals()`、`hashCode()` 和 `toString()`。 此外,它为所有字段创建 getter,为所有非最终字段创建setter,并为所有必填字段(final)创建构造函数。 值得注意的是,Lombok 仅用于编译,因此库代码不会添加到您的最终的 .apk。
|
||||
|
||||
### Lambda 表达式
|
||||
|
||||
Android 工程师有一个非常艰难的生活,因为 Android 中缺乏 Java 8 的特性,而且其中之一是 lambda 表达式。 Lambda 是很棒的,因为它们为你减少了成吨的样板。 你可以在回调和流中使用它们。 在 Kotlin 中,lambda 表达式是内置的,它们看起来比它们在 Java 中看起来好多了。 此外,lambda 的字节码可以直接插入到调用方法的字节码中,因此方法计数不会增加。 它可以使用内联函数。
|
||||
|
||||
```
|
||||
button.setOnClickListener { println("Hello World") }
|
||||
```
|
||||
|
||||
最近 Google 宣布在 Android 中支持 Java 8 的特性,由于 Jack 编译器,你可以在你的代码中使用 lambda。还要提及的是,它们在 API 23 或者更低的级别都可用。
|
||||
|
||||
```
|
||||
button.setOnClickListener(view -> System.out.println("Hello World!"));
|
||||
```
|
||||
|
||||
怎样使用它们?就只用添加下面几行到你的 `build.gradle` 文件中。
|
||||
|
||||
```
|
||||
defaultConfig {
|
||||
jackOptions {
|
||||
enabled true
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
```
|
||||
|
||||
如果你不喜欢用 Jack 编译器,或者你由于一些原因不能使用它,这里有一个不同的解决方案提供给你。Retrolambda 项目允许你在 Java 7,6 或者 5 上运行带有 lambda 表达式的 Java 8 代码,下面是设置过程。
|
||||
|
||||
```
|
||||
dependencies {
|
||||
classpath 'me.tatarka:gradle-retrolambda:3.4.0'
|
||||
}
|
||||
|
||||
apply plugin: 'me.tatarka.retrolambda'
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
```
|
||||
|
||||
正如我前面提到的,在 Kotlin 下的 lambda 内联函数不增加方法计数,但是如何在 Jack 或者 Retrolambda 下使用它们呢? 显然,它们不是没成本的,隐藏的成本如下。
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*H7h2MB2auMslMkdaDtqAfg.png)
|
||||
|
||||
*该表展示了使用不同版本的 Retrolambda 和 Jack 编译器生成的方法数量。该比较结果来自 Jake Wharton 的“[探索 Java 的隐藏成本](http://jakewharton.com/exploring-java-hidden-costs/)” 技术讨论之中。*
|
||||
|
||||
### 数据操作
|
||||
|
||||
Kotlin 引入了高阶函数作为流的替代。 当您必须将一组数据转换为另一组数据或过滤集合时,它们非常有用。
|
||||
|
||||
```
|
||||
fun foo(persons: MutableList<Person>) {
|
||||
persons.filter { it.age >= 21 }
|
||||
.filter { it.name.startsWith("P") }
|
||||
.map { it.name }
|
||||
.sorted()
|
||||
.forEach(::println)
|
||||
}
|
||||
|
||||
data class Person(val name: String, val age: Int)
|
||||
```
|
||||
|
||||
流也由 Google 通过 Jack 编译器提供。 不幸的是,Jack 不使用 Lombok,因为它在编译代码时跳过生成中间的 `.class` 文件,而 Lombok 却依赖于这些文件。
|
||||
|
||||
```
|
||||
void foo(List<Person> persons) {
|
||||
persons.stream()
|
||||
.filter(it -> it.getAge() >= 21)
|
||||
.filter(it -> it.getName().startsWith("P"))
|
||||
.map(Person::getName)
|
||||
.sorted()
|
||||
.forEach(System.out::println);
|
||||
}
|
||||
|
||||
class Person {
|
||||
final private String name;
|
||||
final private int age;
|
||||
|
||||
public Person(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
String getName() { return name; }
|
||||
int getAge() { return age; }
|
||||
}
|
||||
```
|
||||
|
||||
这简直太好了,所以 catch 在哪里? 令人悲伤的是,流从 API 24 才可用。谷歌做了好事,但哪个应用程序有用 `minSdkVersion = 24`?
|
||||
|
||||
幸运的是,Android 平台有一个很好的提供许多很棒的库的开源社区。Lightweight-Stream-API 就是其中的一个,它包含了 Java 7 及以下版本的基于迭代器的流实现。
|
||||
|
||||
```
|
||||
import lombok.Data;
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
void foo(List<Person> persons) {
|
||||
Stream.of(persons)
|
||||
.filter(it -> it.getAge() >= 21)
|
||||
.filter(it -> it.getName().startsWith("P"))
|
||||
.map(Person::getName)
|
||||
.sorted()
|
||||
.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Data class Person {
|
||||
final String name;
|
||||
final int age;
|
||||
}
|
||||
```
|
||||
|
||||
上面的例子结合了 Lombok、Retrolambda 和 Lightweight-Stream-API,它看起来几乎和 Kotlin 一样棒。使用静态工厂方法允许您将任何 Iterable 转换为流,并对其应用 lambda,就像 Java 8 流一样。 将静态调用 `Stream.of(persons)` 包装为 Iterable 类型的扩展函数是完美的,但是 Java 不支持它。
|
||||
|
||||
### 扩展函数
|
||||
|
||||
扩展机制提供了向类添加功能而无需继承它的能力。 这个众所周知的概念非常适合 Android 世界,这就是 Kotlin 在该社区很受欢迎的原因。
|
||||
|
||||
有没有技术或魔术将扩展功能添加到你的 Java 工具箱? 因 Lombok,你可以使用它们作为一个实验功能。 根据 Lombok 文档的说明,他们想把它从实验状态移出,基本上没有什么变化的话很快。 让我们重构最后一个例子,并将 `Stream.of(persons)` 包装成扩展函数。
|
||||
|
||||
```
|
||||
import lombok.Data;
|
||||
import lombok.experimental.ExtensionMethod;
|
||||
|
||||
@ExtensionMethod(Streams.class)
|
||||
public class Foo {
|
||||
void foo(List<Person> persons) {
|
||||
persons.toStream()
|
||||
.filter(it -> it.getAge() >= 21)
|
||||
.filter(it -> it.getName().startsWith("P"))
|
||||
.map(Person::getName)
|
||||
.sorted()
|
||||
.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
|
||||
@Data class Person {
|
||||
final String name;
|
||||
final int age;
|
||||
}
|
||||
|
||||
class Streams {
|
||||
static <T> Stream<T> toStream(List<T> list) {
|
||||
return Stream.of(list);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
所有的方法是 `public`、`static` 的,并且至少有一个参数的类型不是原始的,因而是扩展方法。 `@ExtensionMethod` 注解允许你指定一个包含你的扩展函数的类。 你也可以传递数组,而不是使用一个 `.class` 对象。
|
||||
|
||||
* * *
|
||||
|
||||
我完全知道我的一些想法是非常有争议的,特别是 Lombok,我也知道,有很多的库,可以使你的生活更轻松。请不要犹豫在评论里分享你的经验。干杯!
|
||||
|
||||
![](https://cdn-images-1.medium.com/max/800/1*peB9mmElOn6xwR3eH0HXXA.png)
|
||||
|
||||
---------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
![](https://cdn-images-1.medium.com/fit/c/60/60/1*l7_L6VCKzkOm0gq4Kplnkw.jpeg)
|
||||
|
||||
Coder and professional dreamer @ Grid Dynamics
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://medium.com/proandroiddev/living-android-without-kotlin-db7391a2b170
|
||||
|
||||
作者:[Piotr Ślesarew][a]
|
||||
译者:[DockerChen](https://github.com/DockerChen)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://hackernoon.com/@piotr.slesarew?source=post_header_lockup
|
||||
[1]:http://jakewharton.com/exploring-java-hidden-costs/
|
||||
[2]:https://medium.com/u/8ddd94878165
|
||||
[3]:https://projectlombok.org/index.html
|
||||
[4]:https://github.com/aNNiMON/Lightweight-Stream-API
|
||||
[5]:https://github.com/orfjackal/retrolambda
|
||||
[6]:http://notatube.blogspot.com/2010/11/project-lombok-trick-explained.html
|
||||
[7]:http://notatube.blogspot.com/2010/11/project-lombok-trick-explained.html
|
||||
[8]:https://twitter.com/SliskiCode
|
@ -0,0 +1,405 @@
|
||||
GraphQL 用例:使用 Golang 和 PostgreSQL 构建一个博客引擎 API
|
||||
============================================================
|
||||
|
||||
### 摘要
|
||||
|
||||
GraphQL 在生产环境中似乎难以使用:虽然对于建模功能来说图接口非常灵活,但是并不适用于关系型存储,不管是在实现还是性能方面。
|
||||
|
||||
在这篇博客中,我们会设计并实现一个简单的博客引擎 API,它支持以下功能:
|
||||
|
||||
* 三种类型的资源(用户、博文以及评论)支持多种功能(创建用户、创建博文、给博文添加评论、关注其它用户的博文和评论,等等。)
|
||||
* 使用 PostgreSQL 作为后端数据存储(选择它因为它是一个流行的关系型数据库)。
|
||||
* 使用 Golang(开发 API 的一个流行语言)实现 API。
|
||||
|
||||
我们会比较简单的 GraphQL 实现和纯 REST 替代方案,在一种普通场景(呈现博客文章页面)下对比它们的实现复杂性和效率。
|
||||
|
||||
### 介绍
|
||||
|
||||
GraphQL 是一种 IDL(Interface Definition Language,接口定义语言),设计者定义数据类型和并把数据建模为一个图(graph)。每个顶点都是一种数据类型的一个实例,边代表了节点之间的关系。这种方式非常灵活,能适应任何业务领域。然而,问题是设计过程更加复杂,而且传统的数据存储不能很好地映射到图模型。阅读_附录1_了解更多关于这个问题的详细信息。
|
||||
|
||||
GraphQL 在 2014 年由 Facebook 的工程师团队首次提出。尽管它的优点和功能非常有趣而且引人注目,但它并没有得到大规模应用。开发者需要权衡 REST 的设计简单性、熟悉性、丰富的工具和 GraphQL 不会受限于 CRUD(LCTT 译注:Create、Read、Update、Delete) 以及网络性能(它优化了往返服务器的网络)的灵活性。
|
||||
|
||||
大部分关于 GraphQL 的教程和指南都跳过了从数据存储获取数据以便解决查询的问题。也就是,如何使用通用目的、流行存储方案(例如关系型数据库)为 GraphQL API 设计一个支持高效数据提取的数据库。
|
||||
|
||||
这篇博客介绍构建一个博客引擎 GraphQL API 的流程。它的功能相当复杂。为了和基于 REST 的方法进行比较,它的范围被限制为一个熟悉的业务领域。
|
||||
|
||||
这篇博客的文章结构如下:
|
||||
|
||||
* 第一部分我们会设计一个 GraphQL 模式并介绍所使用语言的一些功能。
|
||||
* 第二部分是 PostgreSQL 数据库的设计。
|
||||
* 第三部分介绍了使用 Golang 实现第一部分设计的 GraphQL 模式。
|
||||
* 第四部分我们以从后端获取所需数据的角度来比较呈现博客文章页面的任务。
|
||||
|
||||
### 相关阅读
|
||||
|
||||
* 很棒的 [GraphQL 介绍文档][1]。
|
||||
* 该项目的完整实现代码在 [github.com/topliceanu/graphql-go-example][2]。
|
||||
|
||||
### 在 GraphQL 中建模一个博客引擎
|
||||
|
||||
下述_列表1_包括了博客引擎 API 的全部模式。它显示了组成图的顶点的数据类型。顶点之间的关系,也就是边,被建模为指定类型的属性。
|
||||
|
||||
```
|
||||
type User {
|
||||
id: ID
|
||||
email: String!
|
||||
post(id: ID!): Post
|
||||
posts: [Post!]!
|
||||
follower(id: ID!): User
|
||||
followers: [User!]!
|
||||
followee(id: ID!): User
|
||||
followees: [User!]!
|
||||
}
|
||||
|
||||
type Post {
|
||||
id: ID
|
||||
user: User!
|
||||
title: String!
|
||||
body: String!
|
||||
comment(id: ID!): Comment
|
||||
comments: [Comment!]!
|
||||
}
|
||||
|
||||
type Comment {
|
||||
id: ID
|
||||
user: User!
|
||||
post: Post!
|
||||
title: String
|
||||
body: String!
|
||||
}
|
||||
|
||||
type Query {
|
||||
user(id: ID!): User
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createUser(email: String!): User
|
||||
removeUser(id: ID!): Boolean
|
||||
follow(follower: ID!, followee: ID!): Boolean
|
||||
unfollow(follower: ID!, followee: ID!): Boolean
|
||||
createPost(user: ID!, title: String!, body: String!): Post
|
||||
removePost(id: ID!): Boolean
|
||||
createComment(user: ID!, post: ID!, title: String!, body: String!): Comment
|
||||
removeComment(id: ID!): Boolean
|
||||
}
|
||||
```
|
||||
|
||||
_列表1_
|
||||
|
||||
模式使用 GraphQL DSL 编写,它用于定义自定义数据类型,例如 `User`、`Post` 和 `Comment`。该语言也提供了一系列原始数据类型,例如 `String`、`Boolean` 和 `ID`(它是`String` 的别名,但是有顶点唯一标识符的额外语义)。
|
||||
|
||||
`Query` 和 `Mutation` 是语法解析器能识别并用于查询图的可选类型。从 GraphQL API 读取数据等同于遍历图。需要提供这样一个起始顶点;该角色通过 `Query` 类型来实现。在这种情况中,所有图的查询都要从一个由 id `user(id:ID!)` 指定的用户开始。对于写数据,定义了 `Mutation` 顶点。它提供了一系列操作,建模为能遍历(并返回)新创建顶点类型的参数化属性。_列表2_是这些查询的一些例子。
|
||||
|
||||
顶点属性能被参数化,也就是能接受参数。在图遍历场景中,如果一个博文顶点有多个评论顶点,你可以通过指定 `comment(id: ID)` 只遍历其中的一个。所有这些都取决于设计,设计者可以选择不提供到每个独立顶点的直接路径。
|
||||
|
||||
`!` 字符是一个类型后缀,适用于原始类型和用户定义类型,它有两种语义:
|
||||
|
||||
* 当被用于参数化属性的参数类型时,表示这个参数是必须的。
|
||||
* 当被用于一个属性的返回类型时,表示当顶点被获取时该属性不会为空。
|
||||
* 也可以把它们组合起来,例如 `[Comment!]!` 表示一个非空 Comment 顶点链表,其中 `[]`、`[Comment]` 是有效的,但 `null, [null], [Comment, null]` 就不是。
|
||||
|
||||
|
||||
_列表2_ 包括一系列用于博客 API 的 `curl` 命令,它们会使用 mutation 填充图然后查询图以便获取数据。要运行它们,按照 [topliceanu/graphql-go-example][3] 仓库中的指令编译并运行服务。
|
||||
|
||||
```
|
||||
# 创建用户 1、2 和 3 的更改。更改和查询类似,在该情景中我们检索新创建用户的 id 和 email。
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user1@x.co"){id, email}}'
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user2@x.co"){id, email}}'
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user3@x.co"){id, email}}'
|
||||
# 为用户添加博文的更改。为了和模式匹配我们需要检索他们的 id,否则会出现错误。
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:1,title:"post1",body:"body1"){id}}'
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:1,title:"post2",body:"body2"){id}}'
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:2,title:"post3",body:"body3"){id}}'
|
||||
# 博文所有评论的更改。`createComment` 需要用户 id,标题和正文。看列表 1 的模式。
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:2,post:1,title:"comment1",body:"comment1"){id}}'
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:1,post:3,title:"comment2",body:"comment2"){id}}'
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:3,post:3,title:"comment3",body:"comment3"){id}}'
|
||||
# 让用户 3 关注用户 1 和用户 2 的更改。注意 `follow` 更改只返回一个布尔值而不需要指定。
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {follow(follower:3, followee:1)}'
|
||||
curl -XPOST http://vm:8080/graphql -d 'mutation {follow(follower:3, followee:2)}'
|
||||
|
||||
# 用户获取用户 1 所有数据的查询。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:1)}'
|
||||
# 用户获取用户 2 和用户 1 的关注者的查询。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:2){followers{id, email}}}'
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:1){followers{id, email}}}'
|
||||
# 检测用户 2 是否被用户 1 关注的查询。如果是,检索用户 1 的 email,否则返回空。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:2){follower(id:1){email}}}'
|
||||
# 返回用户 3 关注的所有用户 id 和 email 的查询。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:3){followees{id, email}}}'
|
||||
# 如果用户 3 被用户 1 关注,就获取用户 3 email 的查询。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:1){followee(id:3){email}}}'
|
||||
# 获取用户 1 的第二篇博文的查询,检索它的标题和正文。如果博文 2 不是由用户 1 创建的,就会返回空。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:1){post(id:2){title,body}}}'
|
||||
# 获取用户 1 的所有博文的所有数据的查询。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:1){posts{id,title,body}}}'
|
||||
# 获取写博文 2 用户的查询,如果博文 2 是由 用户 1 撰写;一个现实语言灵活性的例证。
|
||||
curl -XPOST http://vm:8080/graphql -d '{user(id:1){post(id:2){user{id,email}}}}'
|
||||
```
|
||||
|
||||
_列表2_
|
||||
|
||||
通过仔细设计 mutation 和类型属性,可以实现强大而富有表达力的查询。
|
||||
|
||||
### 设计 PostgreSQL 数据库
|
||||
|
||||
关系型数据库的设计,一如以往,由避免数据冗余的需求驱动。选择该方式有两个原因:
|
||||
|
||||
1. 表明实现 GraphQL API 不需要定制化的数据库技术或者学习和使用新的设计技巧。
|
||||
2. 表明 GraphQL API 能在现有的数据库之上创建,更具体地说,最初设计用于 REST 后端甚至传统的呈现 HTML 站点的服务器端数据库。
|
||||
|
||||
阅读 _附录1_ 了解关于关系型和图数据库在构建 GraphQL API 方面的区别。_列表3_ 显示了用于创建新数据库的 SQL 命令。数据库模式和 GraphQL 模式相对应。为了支持 `follow/unfollow` 更改,需要添加 `followers` 关系。
|
||||
|
||||
```
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
email VARCHAR(100) NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS posts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
body TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS comments (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
body TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS followers (
|
||||
follower_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
followee_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY(follower_id, followee_id)
|
||||
);
|
||||
```
|
||||
|
||||
_列表3_
|
||||
|
||||
### Golang API 实现
|
||||
|
||||
本项目使用的用 Go 实现的 GraphQL 语法解析器是 `github.com/graphql-go/graphql`。它包括一个查询解析器,但不包括模式解析器。这要求开发者利用库提供的结构使用 Go 构建 GraphQL 模式。这和 [nodejs 实现][3] 不同,后者提供了一个模式解析器并为数据获取暴露了钩子。因此 _列表1_ 中的模式只是作为指导使用,需要转化为 Golang 代码。然而,这个_“限制”_提供了与抽象级别对等的机会,并且了解模式如何和用于检索数据的图遍历模型相关。_列表4_ 显示了 `Comment` 顶点类型的实现:
|
||||
|
||||
```
|
||||
var CommentType = graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "Comment",
|
||||
Fields: graphql.Fields{
|
||||
"id": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if comment, ok := p.Source.(*Comment); ok == true {
|
||||
return comment.ID, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"title": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if comment, ok := p.Source.(*Comment); ok == true {
|
||||
return comment.Title, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"body": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if comment, ok := p.Source.(*Comment); ok == true {
|
||||
return comment.Body, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
func init() {
|
||||
CommentType.AddFieldConfig("user", &graphql.Field{
|
||||
Type: UserType,
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if comment, ok := p.Source.(*Comment); ok == true {
|
||||
return GetUserByID(comment.UserID)
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
})
|
||||
CommentType.AddFieldConfig("post", &graphql.Field{
|
||||
Type: PostType,
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"id": &graphql.ArgumentConfig{
|
||||
Description: "Post ID",
|
||||
Type: graphql.NewNonNull(graphql.ID),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
i := p.Args["id"].(string)
|
||||
id, err := strconv.Atoi(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return GetPostByID(id)
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
_列表4_
|
||||
|
||||
正如 _列表1_ 中的模式,`Comment` 类型是静态定义的一个有三个属性的结构体:`id`、`title` 和 `body`。为了避免循环依赖,动态定义了 `user` 和 `post` 两个其它属性。
|
||||
|
||||
Go 并不适用于这种动态建模,它只支持一些类型检查,代码中大部分变量都是 `interface{}` 类型,在使用之前都需要进行类型断言。`CommentType` 是一个 `graphql.Object` 类型的变量,它的属性是 `graphql.Field` 类型。因此,GraphQL DSL 和 Go 中使用的数据结构并没有直接的转换。
|
||||
|
||||
每个字段的 `resolve` 函数暴露了 `Source` 参数,它是表示遍历时前一个节点的数据类型顶点。`Comment` 的所有属性都有作为 source 的当前 `CommentType` 顶点。检索`id`、`title` 和 `body` 是一个直接属性访问,而检索 `user` 和 `post` 要求图遍历,也需要数据库查询。由于它们非常简单,这篇文章并没有介绍这些 SQL 查询,但在_参考文献_部分列出的 github 仓库中有。
|
||||
|
||||
### 普通场景下和 REST 的对比
|
||||
|
||||
在这一部分,我们会展示一个普通的博客文章呈现场景,并比较 REST 和 GraphQL 的实现。关注重点会放在入站/出站请求数量,因为这些是造成页面呈现延迟的最主要原因。
|
||||
|
||||
场景:呈现一个博客文章页面。它应该包含关于作者(email)、博客文章(标题、正文)、所有评论(标题、正文)以及评论人是否关注博客文章作者的信息。_图1_ 和 _图2_ 显示了客户端 SPA、API 服务器以及数据库之间的交互,一个是 REST API、另一个对应是 GraphQL API。
|
||||
|
||||
```
|
||||
+------+ +------+ +--------+
|
||||
|client| |server| |database|
|
||||
+--+---+ +--+---+ +----+---+
|
||||
| GET /blogs/:id | |
|
||||
1\. +-------------------------> SELECT * FROM blogs... |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
<-------------------------+ |
|
||||
| | |
|
||||
| GET /users/:id | |
|
||||
2\. +-------------------------> SELECT * FROM users... |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
<-------------------------+ |
|
||||
| | |
|
||||
| GET /blogs/:id/comments | |
|
||||
3\. +-------------------------> SELECT * FROM comments... |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
<-------------------------+ |
|
||||
| | |
|
||||
| GET /users/:id/followers| |
|
||||
4\. +-------------------------> SELECT * FROM followers.. |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
<-------------------------+ |
|
||||
| | |
|
||||
+ + +
|
||||
```
|
||||
|
||||
_图1_
|
||||
|
||||
```
|
||||
+------+ +------+ +--------+
|
||||
|client| |server| |database|
|
||||
+--+---+ +--+---+ +----+---+
|
||||
| GET /graphql | |
|
||||
1\. +-------------------------> SELECT * FROM blogs... |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
2\. | | SELECT * FROM users... |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
3\. | | SELECT * FROM comments... |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
4\. | | SELECT * FROM followers.. |
|
||||
| +--------------------------->
|
||||
| <---------------------------+
|
||||
<-------------------------+ |
|
||||
| | |
|
||||
+ + +
|
||||
```
|
||||
|
||||
_图2_
|
||||
|
||||
_列表5_ 是一条用于获取所有呈现博文所需数据的简单 GraphQL 查询。
|
||||
|
||||
```
|
||||
{
|
||||
user(id: 1) {
|
||||
email
|
||||
followers
|
||||
post(id: 1) {
|
||||
title
|
||||
body
|
||||
comments {
|
||||
id
|
||||
title
|
||||
user {
|
||||
id
|
||||
email
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_列表5_
|
||||
|
||||
对于这种情况,对数据库的查询次数是故意相同的,但是到 API 服务器的 HTTP 请求已经减少到只有一个。我们认为在这种类型的应用程序中通过互联网的 HTTP 请求是最昂贵的。
|
||||
|
||||
为了利用 GraphQL 的优势,后端并不需要进行特别设计,从 REST 到 GraphQL 的转换可以逐步完成。这使得可以测量性能提升和优化。从这一点,API 设计者可以开始优化(潜在的合并) SQL 查询从而提高性能。缓存的机会在数据库和 API 级别都大大增加。
|
||||
|
||||
SQL 之上的抽象(例如 ORM 层)通常会和 `n+1` 问题相抵触。在 REST 示例的步骤 4 中,客户端可能不得不在单独的请求中为每个评论的作者请求关注状态。这是因为在 REST 中没有标准的方式来表达两个以上资源之间的关系,而 GraphQL 旨在通过使用嵌套查询来防止这类问题。这里我们通过获取用户的所有关注者来作弊。我们向客户提出了如何确定评论并关注了作者的用户的逻辑。
|
||||
|
||||
另一个区别是获取比客户端所需更多的数据,以免破坏 REST 资源抽象。这对于用于解析和存储不需要数据的带宽消耗和电池寿命非常重要。
|
||||
|
||||
### 总结
|
||||
|
||||
GraphQL 是 REST 的一个可用替代方案,因为:
|
||||
|
||||
* 尽管设计 API 更加困难,但该过程可以逐步完成。也是由于这个原因,从 REST 转换到 GraphQL 非常容易,两个流程可以没有任何问题地共存。
|
||||
* 在网络请求方面更加高效,即使是类似本博客中的简单实现。它还提供了更多查询优化和结果缓存的机会。
|
||||
* 在用于解析结果的带宽消耗和 CPU 周期方面它更加高效,因为它只返回呈现页面所需的数据。
|
||||
|
||||
REST 仍然非常有用,如果:
|
||||
|
||||
* 你的 API 非常简单,只有少量的资源或者资源之间关系简单。
|
||||
* 在你的组织中已经在使用 REST API,而且你已经配置好了所有工具,或者你的客户希望获取 REST API。
|
||||
* 你有复杂的 ACL(LCTT 译注:Access Control List) 策略。在博客例子中,可能的功能是允许用户良好地控制谁能查看他们的电子邮箱、博客、特定博客的评论、他们关注了谁,等等。优化数据获取同时检查复杂的业务规则可能会更加困难。
|
||||
|
||||
### 附录1:图数据库和高效数据存储
|
||||
|
||||
尽管将其应用领域数据想象为一个图非常直观,正如这篇博文介绍的那样,但是支持这种接口的高效数据存储问题仍然没有解决。
|
||||
|
||||
近年来图数据库变得越来越流行。通过将 GraphQL 查询转换为特定的图数据库查询语言从而延迟解决请求的复杂性似乎是一种可行的方案。
|
||||
|
||||
问题是和关系型数据库相比,图并不是一种高效的数据结构。图中一个顶点可能有到任何其它顶点的连接,访问模式比较难以预测因此提供了较少的优化机会。
|
||||
|
||||
例如缓存的问题,为了快速访问需要将哪些顶点保存在内存中?通用缓存算法在图遍历场景中可能没那么高效。
|
||||
|
||||
数据库分片问题:把数据库切分为更小、没有交叉的数据库并保存到独立的硬件。在学术上,最小切割的图划分问题已经得到了很好的理解,但可能是次优的,而且由于病态的最坏情况可能导致高度不平衡切割。
|
||||
|
||||
在关系型数据库中,数据被建模为记录(行或者元组)和列,表和数据库名称都只是简单的命名空间。大部分数据库都是面向行的,意味着每个记录都是一个连续的内存块,一个表中的所有记录在磁盘上一个接一个地整齐地打包(通常按照某个关键列排序)。这非常高效,因为这是物理存储最优的工作方式。HDD 最昂贵的操作是将磁头移动到磁盘上的另一个扇区,因此最小化此类访问非常重要。
|
||||
|
||||
很有可能如果应用程序对一条特定记录感兴趣,它需要获取整条记录,而不仅仅是记录中的其中一列。也很有可能如果应用程序对一条记录感兴趣,它也会对该记录周围的记录感兴趣,例如全表扫描。这两点使得关系型数据库相当高效。然而,也是因为这个原因,关系型数据库的最差使用场景就是总是随机访问所有数据。图数据库正是如此。
|
||||
|
||||
随着支持更快随机访问的 SSD 驱动器的出现,更便宜的内存使得缓存大部分图数据库成为可能,更好的优化图缓存和分区的技术,图数据库开始成为可选的存储解决方案。大部分大公司也使用它:Facebook 有 Social Graph,Google 有 Knowledge Graph。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://alexandrutopliceanu.ro/post/graphql-with-go-and-postgresql
|
||||
|
||||
作者:[Alexandru Topliceanu][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://github.com/topliceanu
|
||||
[1]:http://graphql.org/learn/
|
||||
[2]:https://github.com/topliceanu/graphql-go-example
|
||||
[3]:https://github.com/graphql/graphql-js
|
@ -1,43 +1,41 @@
|
||||
为何我们需要一个开放模型来设计评估公共政策
|
||||
============================================================
|
||||
|
||||
### 想象一个 app 可以让市民测试驱动提出的政策。
|
||||
> 想象一个 app 可以让市民来试车提出的政策。
|
||||
|
||||
[up][3]
|
||||
![Why we need an open model to design and evaluate public policy](https://opensource.com/sites/default/files/styles/image-full-size/public/images/government/GOV_citizen_participation.jpg?itok=eeLWQgev "Why we need an open model to design and evaluate public policy")
|
||||
图片提供:
|
||||
![Why we need an open model to design and evaluate public policy](https://opensource.com/sites/default/files/styles/image-full-size/public/images/government/GOV_citizen_participation.jpg?itok=eeLWQgev "Why we need an open model to design and evaluate public policy")
|
||||
|
||||
opensource.com
|
||||
图片提供:opensource.com
|
||||
|
||||
在政治选举之前的几个月中,公众辩论会加剧,并且公民面临大量的政策选择信息。在数据驱动的社会中,新的见解一直在为决策提供信息,对这些信息的深入了解从未如此重要,但公众仍然没有意识到公共政策建模的全部潜力。
|
||||
在政治选举之前的几个月中,公众辩论会加剧,并且公民面临大量的各种政策选择的信息。在数据驱动的社会中,新的见解一直在为决策提供信息,对这些信息的深入了解从未如此重要,但公众仍然没有意识到为公共政策建模的全部潜力。
|
||||
|
||||
在“开放政府”的概念不断演变以跟上新技术进步的时代,政府的政策模型和分析可能是新一代的开放知识。
|
||||
在“<ruby>开放政府<rt>open government</rt></ruby>”的概念不断演变以跟上新技术进步的时代,政府的政策模型和分析可能是新一代的开放知识。
|
||||
|
||||
政府开源模型 (GOSM) 是指政府开发的模型,其目的是设计和评估政策,免费提供给所有人使用、分发、不受限制地修改。社区可以提高政策建模的质量、可靠性和准确性,创造有利于公众的新的数据驱动程序。
|
||||
|
||||
今天的这代与技术相互作用,就像它的第二大本质,它默认吸收了大量的信息。如果我们可以在使用 GOSM 的虚拟、沉浸式环境中与不同的公共政策进行互动那会如何?
|
||||
今天的这一代人与技术相互作用,这俨然成为了它的第二种本质,自然而然地吸收了大量的信息。如果我们可以在使用 GOSM 在虚拟、沉浸式环境中与不同的公共政策进行互动那会如何?
|
||||
|
||||
想象一下有一个允许公民测试推动政策来确定他们想要生活的未来的程序。他们会本能地学习关键的驱动因素和所需要的东西。不久之后,公众将更深入地了解公共政策的影响,并更加精明地引导有争议的公众辩论。
|
||||
想象一下如果有一个程序,允许公民试车提出的政策来确定他们想要生活的未来。他们会本能地学习关键的驱动因素和所需要的东西。不久之后,公众将更深入地了解公共政策的影响,并更加精明地引导有争议性的公众辩论。
|
||||
|
||||
为什么我们以前没有更好的使用这些模型?原因在于公共政策建模的神秘面纱。
|
||||
|
||||
在一个如我们所生活的复杂的社会中,量化政策影响是一项艰巨的任务,并被被描述为一种“美好艺术”。此外,大多数政府政策模型都是基于行政和其他私人持有的数据。然而,政策分析师为了指导政策设计而勇于追求,多次以大量武力而获得政治斗争。
|
||||
在一个如我们所生活的复杂的社会中,量化政策影响是一项艰巨的任务,并被被描述为一种“美好艺术”。此外,大多数政府政策模型都是基于行政和其他私人持有的数据。然而,政策分析师为了指导政策设计而勇于追求,多次以大量武力而赢得政治斗争的胜利。
|
||||
|
||||
数字是很有说服力的。它们构建可信度并常常被用作引入新政策的理由。公共政策模型的发展赋予政治家和官僚权力,这些政治家和官僚们可能不愿意破坏现状。给予这一点可能并不容易,但 GOSM 为前所未有的公共政策改革提供了机会。
|
||||
数字是很有说服力的。它们构建可信度,并常常被用作引入新政策的理由。公共政策模型的发展赋予政治家和官僚权力,这些政治家和官僚们可能不愿意破坏现状。给予这一点可能并不容易,但 GOSM 为前所未有的公共政策改革提供了机会。
|
||||
|
||||
GOSM 将所有人的竞争环境均衡化:政治家、媒体、游说团体、利益相关者和公众。通过向社区开放政策评估的大门, 政府可以利用新的和未发现的能力用来创造、创新在公共领域的效率。但在公共政策设计中,利益相关者和政府之间战略互动有哪些实际影响?
|
||||
GOSM 将所有人的竞争环境均衡化:政治家、媒体、游说团体、利益相关者和公众。通过向社区开放政策评估的大门, 政府可以在公共领域为创造、创新和效率引入新的和未发现的能力。但在公共政策设计中,利益相关者和政府之间战略互动有哪些实际影响?
|
||||
|
||||
GOSM 是独一无二的,因为它们主要是设计公共政策的工具,而不一定需要重新分配私人收益。利益相关者和游说团体可能会将 GOSM 与其私人信息一起使用,以获得对经济参与者私人利益的政策环境运作的新见解。
|
||||
|
||||
GOSM 可以成为利益相关者在公共辩论中保持权力平衡的武器,并为战略争取最佳利益么?
|
||||
|
||||
作为一个可变的公共资源,GOSM 在概念上由纳税人资助,并属于国家。私有实体在不向社会带来利益的情况下从 GOSM 中获得资源是合乎道德的吗?与可能用于更有效的服务提供的程序不同,替代政策建议更有可能由咨询机构使用,并有助于公众辩论。
|
||||
作为一个可变的公共资源,GOSM 在概念上由纳税人资助,并属于国家。私有实体在不向社会带来利益的情况下从 GOSM 中获得资源是合乎道德的吗?与可能用于更有效的服务提供的那些程序不同,替代政策建议更有可能由咨询机构使用,并有助于公众辩论。
|
||||
|
||||
开源社区经常使用“ copyleft 许可证” 来确保代码和根据此许可证的任何衍生作品对所有人都开放。当产品价值是代码本身,这需要重新分配才能获得最大利益,它需要重新分发来获得最大的利益。但是,如果代码或 GOSM 重新分发是主要产品附带的,那它会是对现有政策环境的新战略洞察么?
|
||||
开源社区经常使用 “copyleft 许可证” 来确保代码和在此许可证下的任何衍生作品对所有人都开放。当产品价值是代码本身,这需要重新分配才能获得最大利益,它需要重新分发来获得最大的利益。但是,如果代码或 GOSM 重新分发是主要产品附带的,那它会是对现有政策环境的新战略洞察么?
|
||||
|
||||
在私人收集的数据变得越来越多的时候,GOSM 背后的真正价值可能是底层数据,它可以用来改进模型本身。最终,政府是唯一有权实施政策的消费者,利益相关者可以选择在谈判中分享修改后的 GOSM。
|
||||
|
||||
政府在公开发布政策模型时面临的巨大挑战是提高透明度的同时保护隐私。理想情况下,发布 GOSM 将需要以保护建模关键特征的方式保护封闭数据。
|
||||
政府在公开发布政策模型时面临的巨大挑战是提高透明度的同时保护隐私。理想情况下,发布 GOSM 将需要以保护建模关键特征的方式保护封闭的数据。
|
||||
|
||||
公开发布 GOSM 通过促进市民对民主的更多了解和参与,使公民获得权力,从而改善政策成果和提高公众满意度。在开放的政府乌托邦中,开放的公共政策发展将是政府和社区之间的合作性努力,这里知识、数据和分析可供大家免费使用。
|
||||
|
||||
@ -57,9 +55,9 @@ Audrey Lobo-Pulo - Audrey Lobo-Pulo 博士是 Phoensight 的联合创始人,
|
||||
|
||||
via: https://opensource.com/article/17/1/government-open-source-models
|
||||
|
||||
作者:[Audrey Lobo-Pulo ][a]
|
||||
作者:[Audrey Lobo-Pulo][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,59 @@
|
||||
一位老极客的眼中的开发和部署
|
||||
============================================================
|
||||
|
||||
![The difference between development and deployment](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BUS_OpenSourceExperience_520x292_cm.png?itok=APna2N9Y "The difference between development and deployment")
|
||||
|
||||
图片提供 : opensource.com
|
||||
|
||||
多年前,我曾是一名 Smalltalk 程序员,这种经验让我以一种不同的视角来观察编程的世界,例如,需要花时间来适应源代码应该存储在文本文件中的这种做法。
|
||||
|
||||
我们作为程序员通常会区分“开发”和“部署”,特别是我们在开发的地方所使用的工具不同于我们在之后部署软件时的地点和工具时。而在 Smalltalk 世界里,没有这样的区别。
|
||||
|
||||
Smalltalk 构建于虚拟机包含了你的开发环境(IDE、调试器、文本编辑器、版本控制等)的思路之上,如果你需要修改任何一处代码,你得修改内存中运行副本。如果需要的话,你可以为运行中的机器做个快照;如果你想分发你的代码,你可以发送一个运行中的机器的镜像副本(包括 IDE、调试器、文本编辑器、版本控制等)给用户。这就是上世纪 90 年代软件开发的方式(对我们中的一些人来说)。
|
||||
|
||||
如今,部署环境与开发环境有了很大的不同。起初,你不要期望那里(指部署环境)有任何开发工具。一旦部署,就没有版本控制、没有调试、没有开发环境。有的是记录和监视,这些在我们的开发环境中都没有,而有一个“构建管道”,它将我们的软件从开发形式转换为部署形式。作为一个例证,Docker 容器则试图重新找回上世纪 90 年代 Smalltalk 程序员部署体验的那种简单性,而避免同样的开发体验。
|
||||
|
||||
我想如果 Smalltalk 世界是我唯一的编程方面的体验,让我无法区分开发和部署环境,我可能会偶尔回顾一下它。但是在我成为一名 Smalltalk 程序员之前,我还是一位 APL 程序员,这也是一个可修改的虚拟机镜像的世界,其中开发和部署是无法区分的。因此,我相信,在当前的时代,人们编辑单独的源代码文件,然后运行构建管道以创建在编辑代码时尚不存在的部署作品,然后将这些作品部署给用户。我们已经以某种方式将这种反模式的软件开发制度化,而不断发展的软件环境的需求正在迫使我们找回到上世纪 90 年代的更有效的技术方法。因此才会有 Docker 的成功,所以,我需要提出我的建议。
|
||||
|
||||
我有两个建议:我们在运行时系统中实现(并使用)版本控制,以及,我们通过更改运行中的系统来开发软件,而不是用新的运行系统替换它们。这两个想法是相关的。为了安全地更改正在运行的系统,我们需要一些版本控制功能来支持“撤消”功能。也许公平地说,我只提出了一个建议。让我举例来说明。
|
||||
|
||||
让我们开始假设一个静态网站。你要修改一些 HTML 文件。你应该如何工作?如果你像大多数开发者一样,你会有两个,也许三个网站 - 一个用于开发,一个用于 QA(或者预发布),一个用于生产。你将直接编辑开发实例中的文件。准备就绪后,你将把你的修改“部署”到预发布实例。在用户验收测试之后,你将再次部署,这次是生产环境。
|
||||
|
||||
使用 Occam 的 Razor,让我们可以避免不必要地创建实例。我们需要多少台机器?我们可以使用一台电脑。我们需要多少台 web 服务器?我们可以使用具有多个虚拟主机的单台 web 服务器。如果不使用多个虚拟主机的话,我们可以只使用单个虚拟主机吗?那么我们就需要多个目录,并需要使用 URL 的顶级路径来区分不同的版本,而不是虚拟主机名。但是为什么我们需要多个目录?因为 web 服务器将从文件系统中提供静态文件。我们的问题是,目录有三个不同的版本,我们的解决方案是创建目录的三个不同的副本。这不是正是 Subversion 和 Git 这样的版本控制系统解决的问题吗?制作目录的多个副本以存储多个版本的策略回到了版本控制 CVS 之前的日子。为什么不使用比如说一个空的的 Git 仓库来存储文件呢?要这样做,web 服务器将需要能够从 git 仓库读取文件(参见 [mod_git] [3])。
|
||||
|
||||
这将是一个支持版本控制的运行时系统。
|
||||
|
||||
使用这样的 web 服务器,使用的版本可以由 cookie 来标识。这样,任何人都可以推送到仓库,用户将继续看到他们发起会话时所分配的版本。版本控制系统有不可改变的提交; 一旦会话开始,开发人员可以在不影响正在运行的用户的情况下快速推送更改。开发人员可以重置其会话以跟踪他们的新提交,因此开发人员或测试人员就可能如普通用户一样查看在同台服务器上同一个 URL 上正在开发或正在测试的版本。作为偶然的副作用,A/B 测试仅仅是将不同的用户分配给不同的提交的情况。所有用于管理多个版本的 git 设施都可以在运行环境中发挥作用。当然,git reset 为我们提供了前面提到的“撤销”功能。
|
||||
|
||||
为什么不是每个人都这样做?
|
||||
|
||||
一种可能性是,诸如版本控制系统的工具没有被设计为在生产环境中使用。例如,给某人推送到测试分支而不是生产分支的许可是不可能的。对这个方案最常见的反对是,如果发现了一个漏洞,你会想要将某些提交标记为不可访问。这将是另一种更细粒度的权限的情况;开发人员将具有对所有提交的读取权限,但外部用户不会。我们可能需要对现有工具进行一些额外的改造以支持这种模式,但是这些功能很容易理解,并已被设计到其他软件中。例如,Linux (或 PostgreSQL)实现了对不同用户的细粒度权限的想法。
|
||||
|
||||
随着云环境变得越来越普及,这些想法变得更加相关:云总是在运行。例如,我们可以看到,AWS 中等价的 “文件系统”(S3)实现了版本控制,所以你可能有一个不同的想法,使用一台 web 服务器提供来自 S3 的资源文件,并根据会话信息选择不同版本的资源文件。重要的并不是哪个实现是最好的,而是支持这种运行时版本控制的愿景。
|
||||
|
||||
部署的软件环境应该是“版本感知”的原则,应该扩展到除了服务静态文件的 web 服务器之外的其他工具。在将来的文章中,我将介绍版本库,数据库和应用程序服务器的方法。
|
||||
|
||||
_在 linux.conf.au 中了解更多 Robert Lefkowitz 2017 年 ([#lca2017][1])在 Hobart:[保持 Linux 伟大][2]的主题。_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/profile_pictures/public/pictures/robert_lefkowitz.jpg?itok=CFoX-OUI)
|
||||
|
||||
Robert M. Lefkowitz - Robert(即 r0ml)是一个喜欢复杂编程语言的编程语言爱好者。 他是一个提高清晰度、提高可靠性和最大限度地简化的编程技术收藏家。他通过让计算机更加容易获得来使它普及化。他经常演讲中世纪晚期和早期文艺复兴对编程艺术的影响。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/1/difference-between-development-deployment
|
||||
|
||||
作者:[Robert M. Lefkowitz][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[Bestony](https://github.com/Bestony)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/r0ml
|
||||
[1]:https://twitter.com/search?q=%23lca2017&src=typd
|
||||
[2]:https://www.linux.conf.au/schedule/presentation/107/
|
||||
[3]:https://github.com/r0ml/mod_git
|
@ -0,0 +1,67 @@
|
||||
六个开源软件开发的“潜规则”
|
||||
============================================================
|
||||
|
||||
> 你想成为开源项目中得意满满、功成名就的那个人吗,那就要遵守下面的“潜规则”。
|
||||
|
||||
![The 6 unwritten rules of open source development](http://images.techhive.com/images/article/2016/12/09_opensource-100698477-large.jpg)
|
||||
|
||||
正如体育界不成文的规定一样,这些规则基本上不会出现在官方文档和正式记录上。比如说,在棒球运动中,从比分领先时不要盗垒,到跑垒员跑了第一时也不要放弃四坏球保送。对于圈外人来讲,这些东西很难懂,甚至觉得没什么意义。但是对于那些想成为 MVP 的队员来说,这些都是理所当然的。
|
||||
|
||||
软件开发,特别是开源软件开发中,也有一套不成文的规定。和其它的团队运动一样,这些规定很大程度上决定了开源社区如何看待一名开发者,特别是新加入社区的开发者。
|
||||
|
||||
### 运行之前先调试
|
||||
|
||||
在参与社区之前,比如开放源代码或者其它什么的,你需要做一些基本工作。对于有眼界的开源贡献者,这意味这你需要理解社区的目标,并学习应该从哪里起步。人人都想贡献源代码,但是只有少量的人做过准备,并且乐意、同时也有能力完成这项艰苦卓绝的工作:测试补丁、复审代码、撰写文档、修正错误。所有的这些不受待见的任务在一个健康的社区中都是必要的。
|
||||
|
||||
为什么要在优雅地写代码前做这些呢?这是一种信任,更重要的是,不要只关注自己开发的功能,而是要关注整个社区的动向。
|
||||
|
||||
### 填坑而不是挖坑
|
||||
|
||||
当你在某个社区中建立起自己的声望,那么很有必要全面了解该项目和代码。不要停留于任务状态上,而是要去钻研项目本身,理解那些超出你擅长范围之外的知识。不要只把自己的理解局限于开发者,这样会让你着眼于让你的代码有更大的影响,而不只是你那一亩三分地。
|
||||
|
||||
打个比方,你已经完成了一个网络模块的测试版本。你测试了一下,觉得不错。然后你把它开放到社区,想要更多的人测试。结果发现,当它以特定的方式部署时,有可能会破坏安全设置,还可能导致主存储泄露。如果你将代码视为一个整体时问题就可以迎刃而解,而不是孤立地看待问题。这表明,你要对项目各个部分如何与其他人协作交互有比较深入的理解。让你的补丁填坑而不是挖坑。这样你朝成为社区精英的目标上又前进了一大步。
|
||||
|
||||
### 不投放代码炸弹
|
||||
|
||||
代码提交完毕后你的工作还没结束。如果代码被接受,还会有一些关于这些更改的讨论和常见的问答,还要做测试。你要确保你可以准时提交,努力去理解如何在不影响社区其他成员的情况下,改进代码和补丁。
|
||||
|
||||
### 助己之前先助人
|
||||
|
||||
开源社区不是自相残杀的丛林世界,我们更看重项目的价值而非个体的贡献和成功。如果你想给自己加分,让自己成为更重要的社区成员、让社区接纳你的代码,那就努力帮助别人。如果你熟悉网络部分,那就去复审网络部分,用你的专业技能让整个代码更加优雅。道理很简单,顶级的审查者经常和顶级的贡献者打交道。你帮助的人越多,你就越有价值。
|
||||
|
||||
### 打磨抛光才算完
|
||||
|
||||
作为一个开发者,你很可能希望为开源项目解决一个特定的痛点。或许你想要运行在一个目前还不支持的系统上,抑或你很希望改革社区目前使用的安全技术。想要引进新技术,特别是比较有争议的技术,最好的办法就是让人无法拒绝它。你需要透彻地了解底层代码,考虑每个极端情况。在不影响已实现功能的前提下增加新功能。不仅仅是完成就行,还要在特性的完善上下功夫。
|
||||
|
||||
### 不离不弃方始终
|
||||
|
||||
开源社区也有许多玩玩就算的人,但是承诺了就不要轻易失信。不要就因为提交被拒就离开社区。找出原因,修正错误,然后再试一试。当你开发时候,要和整个代码库保持一致,确保即使项目发生变化而你的补丁仍然可用。不要把你的代码留给别人修复,要自己修复。这样可以在社区形成良好的风气,每个人都自己改。
|
||||
|
||||
---
|
||||
|
||||
这些“潜规则”看上去很简单,但是还是有许多开源项目的贡献者并没有遵守。这样做的开发者不仅可以为成功地推动他们自己的项目,而且也有助于开源社区。
|
||||
|
||||
作者简介:
|
||||
|
||||
Matt Hicks 是 Red Hat 软件工程的副主席,也是 Red Hat 开源合作团队的奠基成员之一。他历时十五年,在软件工程中担任多种职务:开发,运行,架构,管理。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.infoworld.com/article/3156776/open-source-tools/the-6-unwritten-rules-of-open-source-development.html
|
||||
|
||||
作者:[Matt Hicks][a]
|
||||
译者:[Taylor1024](https://github.com/Taylor1024)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.infoworld.com/blog/new-tech-forum/
|
||||
[1]:https://twitter.com/intent/tweet?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3156776%2Fopen-source-tools%2Fthe-6-unwritten-rules-of-open-source-development.html&via=infoworld&text=The+6+unwritten+rules+of+open+source+development
|
||||
[2]:https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3156776%2Fopen-source-tools%2Fthe-6-unwritten-rules-of-open-source-development.html
|
||||
[3]:http://www.linkedin.com/shareArticle?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3156776%2Fopen-source-tools%2Fthe-6-unwritten-rules-of-open-source-development.html&title=The+6+unwritten+rules+of+open+source+development
|
||||
[4]:https://plus.google.com/share?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3156776%2Fopen-source-tools%2Fthe-6-unwritten-rules-of-open-source-development.html
|
||||
[5]:http://reddit.com/submit?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3156776%2Fopen-source-tools%2Fthe-6-unwritten-rules-of-open-source-development.html&title=The+6+unwritten+rules+of+open+source+development
|
||||
[6]:http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3156776%2Fopen-source-tools%2Fthe-6-unwritten-rules-of-open-source-development.html
|
||||
[7]:http://www.infoworld.com/article/3156776/open-source-tools/the-6-unwritten-rules-of-open-source-development.html#email
|
||||
[8]:http://www.infoworld.com/article/3152565/linux/5-rock-solid-linux-distros-for-developers.html#tk.ifw-infsb
|
||||
[9]:http://www.infoworld.com/newsletters/signup.html#tk.ifw-infsb
|
@ -0,0 +1,74 @@
|
||||
5 个提升你开源项目贡献者基数的方法
|
||||
============================================================
|
||||
|
||||
![5 ways to expand your project's contributor base](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BUSINESS_cubestalk.png?itok=MxdS-jA_ "5 ways to expand your project's contributor base")
|
||||
|
||||
图片提供:opensource.com
|
||||
|
||||
许多自由和开源软件项目因解决问题而出现,人们开始为它们做贡献,是因为他们也想修复遇到的问题。当项目的最终用户发现它对他们的需求有用,该项目就开始增长。并且出于分享的目的把人们吸引到同一个项目社区。
|
||||
|
||||
就像任何事物都是有寿命的,增长既是项目成功的标志也是来源。那么项目领导者和维护者如何激励贡献者基数的增长?这里有五种方法。
|
||||
|
||||
### 1、 提供好的文档
|
||||
|
||||
人们经常低估项目[文档][2]的重要性。它是项目贡献者的主要信息来源,它会激励他们努力。信息必须是正确和最新的。它应该包括如何构建该软件、如何提交补丁、编码风格指南等步骤。
|
||||
|
||||
查看经验丰富的科技作家、编辑 Bob Reselman 的 [7 个创建世界级文档的规则][3]。
|
||||
|
||||
开发人员文档的一个很好的例子是 [Python 开发人员指南][4]。它包括清晰简洁的步骤,涵盖 Python 开发的各个方面。
|
||||
|
||||
### 2、 降低进入门槛
|
||||
|
||||
如果你的项目有[工单或 bug 追踪工具][5],请确保将初级任务标记为一个“小 bug” 或“起点”。新的贡献者可以很容易地通过解决这些问题进入项目。追踪工具也是标记非编程任务(如平面设计、图稿和文档改进)的地方。有许多项目成员不是每天都编码,但是却通过这种方式成为推动力。
|
||||
|
||||
Fedora 项目维护着一个这样的[易修复和入门级问题的追踪工具][6]。
|
||||
|
||||
### 3、 为补丁提供常规反馈
|
||||
|
||||
确认每个补丁,即使它只有一行代码,并给作者反馈。提供反馈有助于吸引潜在的候选人,并指导他们熟悉项目。所有项目都应有一个邮件列表和[聊天功能][7]进行通信。问答可在这些媒介中发生。大多数项目不会在一夜之间成功,但那些繁荣的列表和沟通渠道为增长创造了环境。
|
||||
|
||||
### 4、 推广你的项目
|
||||
|
||||
始于解决问题的项目实际上可能对其他开发人员也有用。作为项目的主要贡献者,你的责任是为你的的项目建立文档并推广它。写博客文章,并在社交媒体上分享项目的进展。你可以从简要描述如何成为项目的贡献者开始,并在该描述中提供主要开发者文档的参考连接。此外,请务必提供有关路线图和未来版本的信息。
|
||||
|
||||
为了你的听众,看看由 Opensource.com 的社区经理 Rikki Endsley 写的[写作提示][8]。
|
||||
|
||||
### 5、 保持友好
|
||||
|
||||
友好的对话语调和迅速的回复将加强人们对你的项目的兴趣。最初,这些问题只是为了寻求帮助,但在未来,新的贡献者也可能会提出想法或建议。让他们有信心他们可以成为项目的贡献者。
|
||||
|
||||
记住你一直在被人评头论足!人们会观察项目开发者是如何在邮件列表或聊天上交谈。这些意味着对新贡献者的欢迎和开放程度。当使用技术时,我们有时会忘记人文关怀,但这对于任何项目的生态系统都很重要。考虑一个情况,项目是很好的,但项目维护者不是很受欢迎。这样的管理员可能会驱使用户远离项目。对于有大量用户基数的项目而言,不被支持的环境可能导致分裂,一部分用户可能决定复刻项目并启动新项目。在开源世界中有这样的先例。
|
||||
|
||||
另外,拥有不同背景的人对于开源项目的持续增长和源源不断的点子是很重要的。
|
||||
|
||||
最后,项目负责人有责任维持和帮助项目成长。指导新的贡献者是项目的关键,他们将成为项目和社区未来的领导者。
|
||||
|
||||
阅读:由红帽的内容战略家 Nicole Engard 写的 [7 种让新的贡献者感到受欢迎的方式][1]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/profile_pictures/public/pictures/ar1dbnui.jpg?itok=4Xa7f2cM)
|
||||
|
||||
Kushal Das - Kushal Das 是 Python 软件基金会的一名 CPython 核心开发人员和主管。他是一名长期的 FOSS 贡献者和导师,他帮助新人进入贡献世界。他目前在 Red Hat 担任 Fedora 云工程师。他的博客在 https://kushaldas.in 。你也可以在 Twitter @kushaldas 上找到他
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/1/expand-project-contributor-base
|
||||
|
||||
作者:[Kushal Das][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[Bestony](https://github.com/bestony)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/kushaldas
|
||||
[1]:https://opensource.com/life/16/5/sumana-harihareswara-maria-naggaga-oscon
|
||||
[2]:https://opensource.com/tags/documentation
|
||||
[3]:https://opensource.com/business/16/1/scale-14x-interview-bob-reselman
|
||||
[4]:https://docs.python.org/devguide/
|
||||
[5]:https://opensource.com/tags/bugs-and-issues
|
||||
[6]:https://fedoraproject.org/easyfix/
|
||||
[7]:https://opensource.com/alternatives/slack
|
||||
[8]:https://opensource.com/business/15/10/what-stephen-king-can-teach-tech-writers
|
@ -0,0 +1,101 @@
|
||||
如何在 Linux 中捕获并流式传输你的游戏过程
|
||||
============================================================
|
||||
|
||||
也许没有那么多铁杆的游戏玩家使用 Linux,但肯定有很多 Linux 用户喜欢玩游戏。如果你是其中之一,并希望向世界展示 Linux 游戏不再是一个笑话,那么你会喜欢下面这个关于如何捕捉并且/或者以流式播放游戏的快速教程。我在这将用一个名为 “[Open Broadcaster Software Studio][5]” 的软件,这可能是我们所能找到最好的一种。
|
||||
|
||||
### 捕获设置
|
||||
|
||||
在顶层菜单中,我们选择 “File” → “Settings”,然后我们选择 “Output” 来设置要生成的文件的选项。这里我们可以设置想要的音频和视频的比特率、新创建的文件的目标路径和文件格式。这上面还提供了粗略的质量设置。
|
||||
|
||||
[
|
||||
![Select output set in OBS Studio](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_1.png)
|
||||
][6]
|
||||
|
||||
如果我们将顶部的输出模式从 “Simple” 更改为 “Advanced”,我们就能够设置 CPU 负载,以控制 OBS 对系统的影响。根据所选的质量、CPU 能力和捕获的游戏,可以设置一个不会导致丢帧的 CPU 负载设置。你可能需要做一些试验才能找到最佳设置,但如果将质量设置为低,则不用太多设置。
|
||||
|
||||
[
|
||||
![Change OBS output mode](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_2.png)
|
||||
][7]
|
||||
|
||||
接下来,我们转到设置的 “Video” 部分,我们可以设置我们想要的输出视频分辨率。注意缩小过滤(downscaling filtering )方式,因为它使最终的质量有所不同。
|
||||
|
||||
[
|
||||
![Down scaling filter](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_3.png)
|
||||
][8]
|
||||
|
||||
你可能还需要绑定热键以启动、暂停和停止录制。这特别有用,这样你就可以在录制时看到游戏的屏幕。为此,请在设置中选择 “Hotkeys” 部分,并在相应的框中分配所需的按键。当然,你不必每个框都填写,你只需要填写所需的。
|
||||
|
||||
[
|
||||
![Configure Hotkeys in OBS](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_4.png)
|
||||
][9]
|
||||
|
||||
如果你对流式传输感兴趣,而不仅仅是录制,请选择 “Stream” 分类的设置,然后你可以选择支持的 30 种流媒体服务,包括 Twitch、Facebook Live 和 Youtube,然后选择服务器并输入 流密钥。
|
||||
|
||||
[
|
||||
![Streaming settings](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_5.png)
|
||||
][10]
|
||||
|
||||
### 设置源
|
||||
|
||||
在左下方,你会发现一个名为 “Sources” 的框。我们按下加号来添加一个新的源,它本质上就是我们录制的媒体源。在这你可以设置音频和视频源,但是图像甚至文本也是可以的。
|
||||
|
||||
[
|
||||
![OBS Media Source](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_6.png)
|
||||
][11]
|
||||
|
||||
前三个是关于音频源,接下来的两个是图像,JACK 选项用于从乐器捕获的实时音频, Media Source 用于添加文件等。这里我们感兴趣的是 “Screen Capture (XSHM)”、“Video Capture Device (V4L2)” 和 “Window Capture (Xcomposite)” 选项。
|
||||
|
||||
屏幕捕获选项让你选择要捕获的屏幕(包括活动屏幕),以便记录所有内容。如工作区更改、窗口最小化等。对于标准批量录制来说,这是一个适合的选项,它可在发布之前进行编辑。
|
||||
|
||||
我们来探讨另外两个。Window Capture 将让我们选择一个活动窗口并将其放入捕获监视器。为了将我们的脸放在一个角落,视频捕获设备用于人们可以在我们说话时可以看到我们。当然,每个添加的源都提供了一组选项来供我们实现我们最后要的效果。
|
||||
|
||||
[
|
||||
![OBS Window Capture](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_7.png)
|
||||
][12]
|
||||
|
||||
添加的来源是可以调整大小的,也可以沿着录制帧的平面移动,因此你可以添加多个来源,并根据需要进行排列,最后通过右键单击执行基本的编辑任务。
|
||||
|
||||
[
|
||||
![Add Multiple sources](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_8.png)
|
||||
][13]
|
||||
|
||||
### 过渡
|
||||
|
||||
最后,如果你正在流式传输游戏会话时希望能够在游戏视图和自己(或任何其他来源)之间切换。为此,请从右下角切换为“Studio Mode”,并添加一个分配给另一个源的场景。你还可以通过取消选中 “Duplicate scene” 并检查 “Transitions” 旁边的齿轮图标上的 “Duplicate sources” 来切换。 当你想在简短评论中显示你的脸部时,这很有帮助。
|
||||
|
||||
[
|
||||
![Studio mode](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/pic_9.png)
|
||||
][14]
|
||||
|
||||
这个软件有许多过渡效果,你可以按中心的 “Quick Transitions” 旁边的加号图标添加更多。当你添加它们时,还将会提示你进行设置。
|
||||
|
||||
### 总结
|
||||
|
||||
OBS Studio 是一个功能强大的免费软件,它工作稳定,使用起来相当简单直接,并且拥有越来越多的扩展其功能的[附加插件][15]。如果你需要在 Linux 上记录并且/或者流式传输游戏会话,除了使用 OBS 之外,我无法想到其他更好的解决方案。你有其他类似工具的经验么? 请在评论中分享也欢迎包含一个展示你技能的视频链接。:)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/
|
||||
|
||||
作者:[Bill Toulas][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/
|
||||
[1]:https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/#capture-settings
|
||||
[2]:https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/#setting-up-the-sources
|
||||
[3]:https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/#transitioning
|
||||
[4]:https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/#conclusion
|
||||
[5]:https://obsproject.com/download
|
||||
[6]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_1.png
|
||||
[7]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_2.png
|
||||
[8]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_3.png
|
||||
[9]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_4.png
|
||||
[10]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_5.png
|
||||
[11]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_6.png
|
||||
[12]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_7.png
|
||||
[13]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_8.png
|
||||
[14]:https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_9.png
|
||||
[15]:https://obsproject.com/forum/resources/categories/obs-studio-plugins.6/
|
@ -0,0 +1,117 @@
|
||||
如何在 Vim 中使用模式行进行文件特定的设置
|
||||
============================================================
|
||||
|
||||
虽然[插件][4]毫无疑问是 Vim 最大的优势,然而,还有其它一些功能,使得它成为当今 Linux 用户中最强大、功能最丰富的文本编辑器/IDE 之一。其中一个功能就是可以根据文件做特定的设置。我们可以使用该编辑器的模式行(Modeline)特性来实现该功能。
|
||||
|
||||
在这篇文章中,我将讨论如何使用 Vim 的[模式行(Modeline)][5]特性来简单的理解一些例子。
|
||||
|
||||
在开始之前,值得提醒一下,这篇教程中提及的所有例子、命令和指令都已经在 Ubuntu 16.04 中使用 Vim 7.4 版本测试过。
|
||||
|
||||
### VIM 模式行
|
||||
|
||||
#### 用法
|
||||
|
||||
正如上面已经提到的, Vim 的模式行特性让你能够进行特定于文件的更改。比如,假设你想把项目中的一个特定文件中的所有制表符用空格替换,并且确保这个更改不会影响到其它所有文件。这是模式行帮助你完成你想做的事情的一个理想情况。
|
||||
|
||||
因此,你可以考虑将下面这一行加入文件的开头或结尾来完成这件事。
|
||||
|
||||
```
|
||||
# vim: set expandtab:
|
||||
```
|
||||
|
||||
(LCTT 译注:模式行就是一行以注释符,如 `#`、`//`、`/*` 开头,间隔一个空格,以 `vim:` 关键字触发的设置命令。可参看:http://vim.wikia.com/wiki/Modeline_magic )
|
||||
|
||||
如果你是在 Linux 系统上尝试上面的练习来测试用例,很有可能它将不会像你所期望的那样工作。如果是这样,也不必担心,因为某些情况下,模式行特性需要先激活才能起作用(出于安全原因,在一些系统比如 Debian、Ubuntu、GGentoo 和 OSX 上默认情况下禁用)。
|
||||
|
||||
为了启用该特性,打开 `.vimrc` 文件(位于 `home` 目录),然后加入下面一行内容:
|
||||
|
||||
```
|
||||
set modeline
|
||||
```
|
||||
|
||||
现在,无论何时你在该文件输入一个制表符然后保存时(文件中已输入 `expandtab` 模式行命令的前提下),都会被自动转换为空格。
|
||||
|
||||
让我们考虑另一个用例。假设在 Vim 中, 制表符默认设置为 4 个空格,但对于某个特殊的文件,你想把它增加到 8 个。对于这种情况,你需要在文件的开头或末尾加上下面这行内容:
|
||||
|
||||
```
|
||||
// vim: noai:ts=8:
|
||||
```
|
||||
|
||||
现在,输入一个制表符,你会看到,空格的数量为 8 个。
|
||||
|
||||
你可能已经注意到我刚才说的,这些模式行命令需要加在靠近文件的顶部或底部。如果你好奇为什么是这样,那么理由是该特性以这种方式设计的。下面这一行(来自 Vim 官方文件)将会解释清楚:
|
||||
|
||||
> “模式行不能随意放在文件中的任何位置:它需要放在文件中的前几行或最后几行。`modelines` 变量控制 Vim 检查模式行在文件中的确切位置。请查看 `:help modelines` 。默认情况下,设置为 5 行。”
|
||||
|
||||
下面是 `:help modelines` 命令(上面提到的)输出的内容:
|
||||
|
||||
> 如果 `modeline` 已启用并且 `modelines` 给出了行数,那么便在相应位置查找 `set` 命令。如果 `modeline` 禁用或 `modelines` 设置的行数为 0 则不查找。
|
||||
|
||||
尝试把模式行命令置于超出 5 行的范围(距离文件底部和顶部的距离均超过 5 行),你会发现, 制表符将会恢复为 Vim 默认数目的空格 — 在我的情况里是 4 个空格。
|
||||
|
||||
然而,你可以按照自己的意愿改变默认行数,只需在你的 `.vimrc` 文件中加入下面一行命令
|
||||
|
||||
```
|
||||
set modelines=[新值]
|
||||
```
|
||||
|
||||
比如,我把值从 5 增加到了 10 。
|
||||
|
||||
```
|
||||
set modelines=10
|
||||
```
|
||||
|
||||
这意味着,现在我可以把模式行命令置于文件前 10 行或最后 10 行的任意位置。
|
||||
|
||||
继续,无论何时,当你在编辑一个文件的时候,你可以输入下面的命令(在 Vim 编辑器的命令模式下输入)来查看当前与命令行相关的设置以及它们最新的设置。
|
||||
|
||||
```
|
||||
:verbose set modeline? modelines?
|
||||
```
|
||||
|
||||
比如,在我的例子中,上面的命令产生了如下所示的输出:
|
||||
|
||||
```
|
||||
modeline
|
||||
Last set from ~/.vimrc
|
||||
modelines=10
|
||||
Last set from ~/.vimrc
|
||||
```
|
||||
|
||||
关于 Vim 的模式行特性,你还需要知道一些重要的点:
|
||||
|
||||
* 默认情况下,当 Vim 以非兼容(`nocompatible`)模式运行时该特性是启用的,但需要注意的是,在一些发行版中,出于安全考虑,系统的 `vimrc` 文件禁用了该选项。
|
||||
* 默认情况下,当以 root 权限编辑文件时,该特性被禁用(如果你是使用 `sudo` 方式打开该文件,那么该特性依旧能够正常工作)。
|
||||
* 通过 `set` 来设置模式行,其结束于第一个冒号,而非反斜杠。不使用 `set`,则后面的文本都是选项。比如,`/* vim: noai:ts=4:sw=4 */` 是一个无效的模式行。
|
||||
|
||||
(LCTT 译注:关于模式行中的 `set`,上述描述指的是:如果用 `set` 来设置,那么当发现第一个 `:` 时,表明选项结束,后面的 `*/` 之类的为了闭合注释而出现的文本均无关;而如果不用 `set` 来设置,那么以 `vim:` 起头的该行所有内容均视作选项。 )
|
||||
|
||||
#### 安全考虑
|
||||
|
||||
令人沮丧的是, Vim 的模式行特性可能会造成安全性问题。事实上,在过去,已经报道过多个和模式行相关的问题,包括 [shell 命令注入][6],[任意命令执行][7]和[无授权访问][8]等。我知道,这些问题发生在很早的一些时候,现在应该已经修复好了,但是,这提醒了我们,模式行特性有可能会被黑客滥用。
|
||||
|
||||
### 结论
|
||||
|
||||
模式行可能是 Vim 编辑器的一个高级命令,但是它并不难理解。毫无疑问,它的学习曲线会有一些复杂,但是不需多问也知道,该特性是多么的有用。当然,出于安全考虑,在启用并使用该选项前,你需要对自己的选择进行权衡。
|
||||
|
||||
你有使用过模式行特性吗?你的体验是什么样的?记得在下面的评论中分享给我们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.howtoforge.com/tutorial/vim-modeline-settings/
|
||||
|
||||
作者:[Ansh][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.howtoforge.com/tutorial/vim-modeline-settings/
|
||||
[1]:https://www.howtoforge.com/tutorial/vim-modeline-settings/#usage
|
||||
[2]:https://www.howtoforge.com/tutorial/vim-modeline-settings/#vim-modeline
|
||||
[3]:https://www.howtoforge.com/tutorial/vim-modeline-settings/#conclusion
|
||||
[4]:https://linux.cn/article-7901-1.html
|
||||
[5]:http://vim.wikia.com/wiki/Modeline_magic
|
||||
[6]:https://tools.cisco.com/security/center/viewAlert.x?alertId=13223
|
||||
[7]:http://usevim.com/2012/03/28/modelines/
|
||||
[8]:https://tools.cisco.com/security/center/viewAlert.x?alertId=5169
|
@ -1,71 +1,47 @@
|
||||
### 如何在 Linux 终端会话中使用 Asciinema 进行录制和回放
|
||||
如何在 Linux 中使用 Asciinema 进行录制和回放终端会话
|
||||
===========
|
||||
|
||||
![](https://linuxconfig.org/images/asciimena-video-example.jpg?58942057)
|
||||
|
||||
内容
|
||||
|
||||
* * [1、简介][11]
|
||||
* [2、困难][12]
|
||||
* [3、惯例][13]
|
||||
* [4、标准库安装][14]
|
||||
* [4.1、在 Arch Linux 上安装][1]
|
||||
* [4.2、在 Debian 上安装][2]
|
||||
* [4.3、在 Ubuntu 上安装][3]
|
||||
* [4.4、在 Fedora 上安装][4]
|
||||
* [5、从源代码安装][15]
|
||||
* [6、前提条件][16]
|
||||
* [6.1、在 Arch Linux 上安装 ruby][5]
|
||||
* [6.2、在 Debian 上安装 ruby][6]
|
||||
* [6.3、在 Ubuntu 安装 ruby][7]
|
||||
* [6.4、在 Fedora 安装 ruby][8]
|
||||
* [6.5、在 CentOS 安装 ruby][9]
|
||||
* [7、 安装 Linuxbrew][17]
|
||||
* [8、 安装 Asciinema][18]
|
||||
* [9、录制终端会话][19]
|
||||
* [10、回放已录制终端会话][20]
|
||||
* [11、将视频嵌入 HTML][21]
|
||||
* [12、结论][22]
|
||||
* [13、 故障排除][23]
|
||||
* [13.1、在 UTF-8 环境下运行 asciinema][10]
|
||||
|
||||
### 简介
|
||||
|
||||
Asciinema 是一个轻量并且非常高效的脚本终端会话录制器的替代品。使用它可以录制、回放和分享 JSON 格式的终端会话记录。和一些桌面录制器,比如 Recordmydesktop、Simplescreenrecorder、Vokoscreen 或 Kazam 相比,Asciinema 最主要的优点是,它能够以通过 ANSI 转义码编码的 ASCII 文本录制所有的标准终端输入、输出和错误。
|
||||
Asciinema 是一个轻量并且非常高效的终端会话录制器。使用它可以录制、回放和分享 JSON 格式的终端会话记录。与一些桌面录制器,比如 Recordmydesktop、Simplescreenrecorder、Vokoscreen 或 Kazam 相比,Asciinema 最主要的优点是,它能够以通过 ASCII 文本以及 ANSI 转义码编码来录制所有的标准终端输入、输出和错误信息。
|
||||
|
||||
事实上,即使是很长的终端会话,录制出的 JSON 格式文件也非常小。另外,JSON 格式使得用户可以利用简单的文件转化器,将输出的 JSON 格式文件嵌入到 HTML 代码中,然后分享到公共网站或者使用 asciinema 账户分享到 Asciinema.org 。最后,如果你的终端会话中有一些错误,并且你还懂一些 ASCI 转义码语法,那么你可以使用任何编辑器来修改你的已录制终端会话。
|
||||
|
||||
### 困难
|
||||
**难易程度:**
|
||||
|
||||
很简单!
|
||||
|
||||
### 惯例
|
||||
**标准终端:**
|
||||
|
||||
* **#** - 给定命令需要以 root 用户权限运行或者使用 `sudo` 命令
|
||||
* **$** - 给定命令以常规权限用户运行
|
||||
|
||||
### 标准库安装
|
||||
### 从软件库安装
|
||||
|
||||
很有可能, asciinema 可以使用你的版本库进行安装。但是,如果不可以使用系统版本库进行安装或者你想安装最新的版本,那么,你可以像下面的“从源代码安装”部分所描述的那样,使用 Linuxbrew 包管理器来执行 Asciinema 安装。
|
||||
通常, asciinema 可以使用你的发行版的软件库进行安装。但是,如果不可以使用系统的软件库进行安装或者你想安装最新的版本,那么,你可以像下面的“从源代码安装”部分所描述的那样,使用 Linuxbrew 包管理器来执行 Asciinema 安装。
|
||||
|
||||
### 在 Arch Linux 上安装
|
||||
**在 Arch Linux 上安装:**
|
||||
|
||||
```
|
||||
# pacman -S asciinema
|
||||
```
|
||||
|
||||
### 在 Debian 上安装
|
||||
**在 Debian 上安装:**
|
||||
|
||||
```
|
||||
# apt install asciinema
|
||||
```
|
||||
|
||||
### 在 Ubuntu 上安装
|
||||
**在 Ubuntu 上安装:**
|
||||
|
||||
```
|
||||
$ sudo apt install asciinema
|
||||
```
|
||||
|
||||
### 在 Fedora 上安装
|
||||
**在 Fedora 上安装:**
|
||||
|
||||
```
|
||||
$ sudo dnf install asciinema
|
||||
@ -75,7 +51,7 @@ $ sudo dnf install asciinema
|
||||
|
||||
最简单并且值得推荐的方式是使用 Linuxbrew 包管理器,从源代码安装最新版本的 Asciinema 。
|
||||
|
||||
### 前提条件
|
||||
#### 前提条件
|
||||
|
||||
下面列出的前提条件是安装 Linuxbrew 和 Asciinema 需要满足的依赖关系:
|
||||
|
||||
@ -86,61 +62,69 @@ $ sudo dnf install asciinema
|
||||
|
||||
在安装 Linuxbrew 之前,请确保上面的这些包都已经安装在了你的 Linux 系统中。
|
||||
|
||||
### 在 Arch Linux 上安装 ruby
|
||||
**在 Arch Linux 上安装 ruby:**
|
||||
|
||||
```
|
||||
# pacman -S git gcc make ruby
|
||||
```
|
||||
|
||||
### 在 Debian 上安装 ruby
|
||||
**在 Debian 上安装 ruby:**
|
||||
|
||||
```
|
||||
# apt install git gcc make ruby
|
||||
```
|
||||
|
||||
### 在 Ubuntu 上安装 ruby
|
||||
**在 Ubuntu 上安装 ruby:**
|
||||
|
||||
```
|
||||
$ sudo apt install git gcc make ruby
|
||||
```
|
||||
|
||||
### 在 Fedora 上安装 ruby
|
||||
**在 Fedora 上安装 ruby:**
|
||||
|
||||
```
|
||||
$ sudo dnf install git gcc make ruby
|
||||
```
|
||||
|
||||
### 在 CentOS 上安装 ruby
|
||||
**在 CentOS 上安装 ruby:**
|
||||
|
||||
```
|
||||
# yum install git gcc make ruby
|
||||
```
|
||||
|
||||
### 安装 Linuxbrew
|
||||
#### 安装 Linuxbrew
|
||||
|
||||
Linuxbrew 包管理器是苹果的 MacOS 操作系统很受欢迎的 Homebrew 包管理器的一个复刻版本。还没发布多久,Homebrew 就以容易使用而著称。如果你想使用 Linuxbrew 来安装 Asciinema,那么,请运行下面命令在你的 Linux 版本上安装 Linuxbrew:
|
||||
|
||||
```
|
||||
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install)"
|
||||
```
|
||||
|
||||
现在,Linuxbrew 已经安装到了目录 `$HOME/.linuxbrew/` 下。剩下需要做的就是使它成为可执行 `PATH` 环境变量的一部分。
|
||||
|
||||
```
|
||||
$ echo 'export PATH="$HOME/.linuxbrew/bin:$PATH"' >>~/.bash_profile
|
||||
$ . ~/.bash_profile
|
||||
```
|
||||
|
||||
为了确认 Linuxbrew 是否已经安装好,你可以使用 `brew` 命令来查看它的版本:
|
||||
|
||||
```
|
||||
$ brew --version
|
||||
Homebrew 1.1.7
|
||||
Homebrew/homebrew-core (git revision 5229; last commit 2017-02-02)
|
||||
```
|
||||
|
||||
### 安装 Asciinema
|
||||
#### 安装 Asciinema
|
||||
|
||||
安装好 Linuxbrew 以后,安装 Asciinema 就变得无比容易了:
|
||||
|
||||
```
|
||||
$ brew install asciinema
|
||||
```
|
||||
|
||||
检查 Asciinema 是否安装正确:
|
||||
|
||||
```
|
||||
$ asciinema --version
|
||||
asciinema 1.3.0
|
||||
@ -151,10 +135,13 @@ asciinema 1.3.0
|
||||
经过一番辛苦的安装工作以后,是时候来干一些有趣的事情了。Asciinema 是一个非常容易使用的软件。事实上,目前的 1.3 版本只有很少的几个可用命令行选项,其中一个是 `--help` 。
|
||||
|
||||
我们首先使用 `rec` 选项来录制终端会话。下面的命令将会开始录制终端会话,之后,你将会有一个选项来丢弃已录制记录或者把它上传到 asciinema.org 网站以便将来参考。
|
||||
|
||||
```
|
||||
$ asciinema rec
|
||||
```
|
||||
|
||||
运行上面的命令以后,你会注意到, Asciinema 已经开始录制终端会话了,你可以按下 `CTRL+D` 快捷键或执行 `exit` 命令来停止录制。如果你使用的是 Debian/Ubuntu/Mint Linux 系统,你可以像下面这样尝试进行第一次 asciinema 录制:
|
||||
|
||||
```
|
||||
$ su
|
||||
Password:
|
||||
@ -162,7 +149,9 @@ Password:
|
||||
# exit
|
||||
$ sl
|
||||
```
|
||||
|
||||
一旦输入最后一个 `exit` 命令以后,将会询问你:
|
||||
|
||||
```
|
||||
$ exit
|
||||
~ Asciicast recording finished.
|
||||
@ -170,11 +159,15 @@ $ exit
|
||||
|
||||
https://asciinema.org/a/7lw94ys68gsgr1yzdtzwijxm4
|
||||
```
|
||||
|
||||
如果你不想上传你的私密命令行技巧到 asciinema.org 网站,那么有一个选项可以把 Asciinema 记录以 JSON 格式保存为本地文件。比如,下面的 asciinema 记录将被存为 `/tmp/my_rec.json`:
|
||||
|
||||
```
|
||||
$ asciinema rec /tmp/my_rec.json
|
||||
```
|
||||
另一个非常有用的 asciinema 特性是时间微调。如果你的键盘输入速度很慢,或者你在进行多任务,输入命令和执行命令之间的时间可以延长。Asciinema 会记录你的实时按键时间,这意味着每一个停顿都将反映在最终视频的长度上。可以使用 `-w` 选项来缩短按键的时间间隔。比如,下面的命令将按键的时间间隔缩短为 0.2 秒:
|
||||
|
||||
另一个非常有用的 asciinema 特性是时间微调。如果你的键盘输入速度很慢,或者你在进行多任务,输入命令和执行命令之间的时间会比较长。Asciinema 会记录你的实时按键时间,这意味着每一个停顿都将反映在最终视频的长度上。可以使用 `-w` 选项来缩短按键的时间间隔。比如,下面的命令将按键的时间间隔缩短为 0.2 秒:
|
||||
|
||||
```
|
||||
$ asciinema rec -w 0.2
|
||||
```
|
||||
@ -182,15 +175,19 @@ $ asciinema rec -w 0.2
|
||||
### 回放已录制终端会话
|
||||
|
||||
有两种方式可以来回放已录制会话。第一种方式是直接从 asciinema.org 网站上播放终端会话。这意味着,你之前已经把录制会话上传到了 asciinema.org 网站,并且需要提供有效链接:
|
||||
|
||||
```
|
||||
$ asciinema play https://asciinema.org/a/7lw94ys68gsgr1yzdtzwijxm4
|
||||
```
|
||||
Alternatively, use your locally stored JSON file:
|
||||
|
||||
另外,你也可以使用本地存储的 JSON 文件:
|
||||
|
||||
```
|
||||
$ asciinema play /tmp/my_rec.json
|
||||
```
|
||||
|
||||
如果要使用 `wget` 命令来下载之前的上传记录,只需在链接的后面加上 `.json`:
|
||||
|
||||
```
|
||||
$ wget -q -O steam_locomotive.json https://asciinema.org/a/7lw94ys68gsgr1yzdtzwijxm4.json
|
||||
$ asciinema play steam_locomotive.json
|
||||
@ -198,7 +195,8 @@ $ asciinema play steam_locomotive.json
|
||||
|
||||
### 将视频嵌入 HTML
|
||||
|
||||
最后,Asciinema 还带有一个独立的 JavaScript 播放器。这意味者你可以很容易的在你的网站上分享终端会话记录。下面,使用一段简单的 `index.html` 代码来说明这个方法。首先,下载所有必要的东西:
|
||||
最后,asciinema 还带有一个独立的 JavaScript 播放器。这意味者你可以很容易的在你的网站上分享终端会话记录。下面,使用一段简单的 `index.html` 代码来说明这个方法。首先,下载所有必要的东西:
|
||||
|
||||
```
|
||||
$ cd /tmp/
|
||||
$ mkdir steam_locomotive
|
||||
@ -208,6 +206,7 @@ $ wget -q https://github.com/asciinema/asciinema-player/releases/download/v2.4.0
|
||||
$ wget -q https://github.com/asciinema/asciinema-player/releases/download/v2.4.0/asciinema-player.js
|
||||
```
|
||||
之后,创建一个新的包含下面这些内容的 `/tmp/steam_locomotive/index.html` 文件:
|
||||
|
||||
```
|
||||
<html>
|
||||
<head>
|
||||
@ -219,28 +218,34 @@ $ wget -q https://github.com/asciinema/asciinema-player/releases/download/v2.4.0
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
完成以后,打开你的网页浏览器,按下 `CTRL+O` 来打开新创建的 `/tmp/steam_locomotive/index.html` 文件。
|
||||
|
||||
### 结论
|
||||
|
||||
正如前面所说的,使用 Asciinema 录制器来录制终端会话最主要的优点是它的输出文件非常小,这使得你的视频很容易分享出去。上面的例子产生了一个包含 58472 个字符的文件,它是一个只有 58 KB 大的 22 秒终端会话视频。如果我们查看输出的 JSON 文件,会发现甚至这个数字已经非常大了,这主要是因为一个 “蒸汽机车” 已经跑过了终端。这个长度的正常终端会话会产生一个更小的输出文件。
|
||||
正如前面所说的,使用 asciinema 录制器来录制终端会话最主要的优点是它的输出文件非常小,这使得你的视频很容易分享出去。上面的例子产生了一个包含 58472 个字符的文件,它是一个只有 58 KB 大 小的 22 秒终端会话视频。如果我们查看输出的 JSON 文件,会发现甚至这个数字已经非常大了,这主要是因为一个 “蒸汽机车” 已经跑过了终端。这个长度的正常终端会话一般会产生一个更小的输出文件。
|
||||
|
||||
下次,当你想要在一个论坛上询问关于 Linux 配置的问题,并且很难描述你的问题的时候,只需运行下面的命令:
|
||||
|
||||
```
|
||||
$ asciinema rec
|
||||
```
|
||||
|
||||
然后把最后的链接贴到论坛的帖子里。
|
||||
|
||||
### 故障排除
|
||||
|
||||
### 在 UTF-8 环境下运行 asciinema
|
||||
#### 在 UTF-8 环境下运行 asciinema
|
||||
|
||||
错误信息:
|
||||
|
||||
```
|
||||
asciinema 需要在 UTF-8 环境下运行。请检查 `locale` 命令的输出。
|
||||
asciinema needs a UTF-8 native locale to run. Check the output of `locale` command.
|
||||
```
|
||||
|
||||
解决方法:
|
||||
生成并导出UTF-8语言环境。例如:
|
||||
生成并导出 UTF-8 语言环境。例如:
|
||||
|
||||
```
|
||||
$ localedef -c -f UTF-8 -i en_US en_US.UTF-8
|
||||
$ export LC_ALL=en_US.UTF-8
|
||||
@ -252,7 +257,7 @@ via: https://linuxconfig.org/record-and-replay-terminal-session-with-asciinema-o
|
||||
|
||||
作者:[Lubos Rendek][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,49 @@
|
||||
甲骨文的政策更改提高了其在 AWS 上的价格
|
||||
============================================================
|
||||
|
||||
> 这种改变使在 AWS 上实施甲骨文的软件的价格翻了一番,它已经安静地生效了,而几乎没有通知用户。
|
||||
|
||||
![](http://windowsitpro.com/site-files/windowsitpro.com/files/imagecache/large_img/uploads/2017/02/ellison-hero.jpg)
|
||||
|
||||
之前有消息传出,甲骨文使亚马逊云上的产品价格翻了一倍。它在[如何计算 AWS 的虚拟 CPU][6] 上耍了一些花招。它这么做也没有任何宣扬。该公司的新定价政策于 1 月 23 日生效,直到 1 月 28 日都几乎没有被人注意到, 甲骨文的关注者 Tim Hall 偶然发现 Big Red 公司的 [甲骨文软件云计算环境许可][7]文件并披露了出来。
|
||||
|
||||
乍一看,这一举动似乎并不太大,因为它仅将甲骨文的 AWS 定价与 Microsoft Azure 的价格相提并论。但是 Azure 只有市场领先的 AWS 体量的三分之一,所以如果你想在云中销售许可证,AWS 是合适的地方。虽然此举可能或可能不会影响已经在 AWS 上使用甲骨文产品的用户,但是尚不清楚新规则是否适用于已在使用产品的用户 - 它肯定会让一些考虑可能使用甲骨文的用户另寻它处。
|
||||
|
||||
这个举动的主要原因是显而易见的。甲骨文希望使自己的云更具吸引力 - 这让 [The Register 观察][8]到一点:“拉里·埃里森确实承诺过甲骨文的云将会更快更便宜”。更快和更便宜仍然有待看到。如果甲骨文的 SPARC 云计划启动,并且按照广告的形式执行,那么可能会更快,但是更便宜的可能性较小。甲骨文以对其价格的强硬态度而著称。
|
||||
|
||||
随着其招牌数据库和业务栈销售的下滑,并且对 Sun 公司的 74 亿美元的投资并未能按照如期那样,甲骨文将其未来赌在云计算上。但是甲骨文来晚了,迄今为止,它的努力似乎还没有结果, 一些金融预测者并没有看到甲骨文云的光明前景。他们说,云是一个拥挤的市场,而四大公司 - 亚马逊、微软、IBM 和谷歌 - 已经有了领先优势。
|
||||
|
||||
确实如此。但是甲骨文面临的最大的障碍是,好吧,就是甲骨文。它的声誉在它之前。
|
||||
|
||||
保守地说这个公司并不是因为明星客户服务而闻名。事实上,各种新闻报道将甲骨文描绘成一个恶霸和操纵者。
|
||||
|
||||
例如,早在 2015 年,甲骨文就因为它的云并不像预期那样快速增长而越来越沮丧,开始[激活业内人士称之为的“核特权”][9]。它会审核客户的数据中心,如果客户不符合规定,将发出“违规通知” - 它通常只适用于大规模滥用情况,并命令客户在 30 天内退出使用其软件。
|
||||
|
||||
或许你能想到,大量投入在甲骨文软件平台上的大公司们绝对不能在短时间内迁移到另一个解决方案。甲骨文的违规通知将会引发灾难。
|
||||
|
||||
商业内幕人士 Julie Bort 解释到:“为了使违规通知消失 - 或者减少高额的违规罚款 - 甲骨文销售代表通常希望客户向合同中添加云额度”。
|
||||
|
||||
换句话说,甲骨文正在使用审计来扭转客户去购买它的云,而无论他们是否有需要。这种策略与最近 AWS 价格翻倍之间也可能存在联系。Hall 的文章的评论者指出,围绕价格提升的秘密背后的目的可能是触发软件审计。
|
||||
|
||||
使用这些策略的麻烦迟早会出来。消息一旦传播开来,你的客户就开始寻找其他选项。对 Big Red 而言或许是时候参考微软的做法,开始建立一个更好和更温和的甲骨文,将客户的需求放在第一位。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://windowsitpro.com/cloud/oracle-policy-change-raises-prices-aws
|
||||
|
||||
作者:[Christine Hall][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://windowsitpro.com/author/christine-hall
|
||||
[1]:http://windowsitpro.com/penton_ur/nojs/user/register?path=node%2F186491&nid=186491&source=email
|
||||
[2]:http://windowsitpro.com/author/christine-hall
|
||||
[3]:http://windowsitpro.com/author/christine-hall
|
||||
[4]:http://windowsitpro.com/cloud/oracle-policy-change-raises-prices-aws#comments
|
||||
[5]:http://windowsitpro.com/cloud/oracle-policy-change-raises-prices-aws#comments
|
||||
[6]:https://oracle-base.com/blog/2017/01/28/oracles-cloud-licensing-change-be-warned/
|
||||
[7]:http://www.oracle.com/us/corporate/pricing/cloud-licensing-070579.pdf
|
||||
[8]:https://www.theregister.co.uk/2017/01/30/oracle_effectively_doubles_licence_fees_to_run_in_aws/
|
||||
[9]:http://www.businessinsider.com/oracle-is-using-the-nuclear-option-to-sell-its-cloud-software-2015-7
|
@ -1,17 +1,17 @@
|
||||
5 个要了解的开源软件定义网络项目
|
||||
5 个需要知道的开源的软件定义网络(SDN)项目
|
||||
============================================================
|
||||
|
||||
|
||||
![SDN](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/software-defined-networking_0.jpg?itok=FeWzZo8n "SDN")
|
||||
|
||||
SDN 开始重新定义企业网络。这里有五个应该知道的开源项目。
|
||||
[Creative Commons Zero][1] Pixabay
|
||||
> SDN 开始重新定义企业网络。这里有五个应该知道的开源项目。
|
||||
|
||||
|
||||
纵观整个 2016 年,软件定义网络(SDN)持续快速发展并变得成熟。我们现在已经超出了开源网络的概念阶段,两年前评估这些项目潜力的公司已经开始了企业部署。如几年来所预测的,SDN 正在开始重新定义企业网络。
|
||||
|
||||
这与市场研究人员的观点基本上是一致的。IDC 在今年早些时候公布了 SDN 市场的[一份研究][3],它预计从 2014 年到 2020 年 SDN 的年均复合增长率为 53.9%,届时市场价值将达到 125 亿美元。此外,“<ruby>2016 技术趋势<rt>Technology Trends 2016</rt></ruby>” 报告中将 SDN 列为 2016 年最佳技术投资。
|
||||
|
||||
IDC 网络基础设施副总裁,[Rohit Mehra][4] 说:“云计算和第三方平台推动了 SDN 的需求,这将在 2020 年代表一个价值超过 125 亿美元的市场。毫无疑问的是 SDN 的价值将越来越多地渗透到网络虚拟化软件和 SDN 应用中,包括虚拟化网络和安全服务,大型企业在数据中心实现 SDN 的价值,但它们最终会认识到其在分支机构和校园网络中的广泛应用。“
|
||||
IDC 网络基础设施副总裁,[Rohit Mehra][4] 说:“云计算和第三方平台推动了 SDN 的需求,这预示着 2020 年的一个价值超过 125 亿美元的市场。毫无疑问的是 SDN 的价值将越来越多地渗透到网络虚拟化软件和 SDN 应用中,包括虚拟化网络和安全服务。大型企业现在正在数据中心体现 SDN 的价值,但它们最终会认识到其在分支机构和校园网络中的广泛应用。“
|
||||
|
||||
Linux 基金会最近[发布][5]了其 2016 年度报告[“开放云指南:当前趋势和开源项目”][6]。其中第三份年度报告全面介绍了开放云计算的状态,并包含关于 unikernel 的部分。你现在可以[下载报告][7]了,首先要注意的是汇总和分析研究,说明了容器、unikernel 等的趋势是如何重塑云计算的。该报告提供了对当今开放云环境中心的分类项目的描述和链接。
|
||||
|
||||
@ -19,27 +19,37 @@ Linux 基金会最近[发布][5]了其 2016 年度报告[“开放云指南:
|
||||
|
||||
### 软件定义网络
|
||||
|
||||
[ONOS][8]
|
||||
#### [ONOS][8]
|
||||
|
||||
<ruby>开放网络操作系统<rt>Open Network Operating System </rt></ruby>(ONOS)是一个 Linux 基金会项目,它是一个给服务提供商的软件定义网络操作系统,它具有可扩展性、高可用性、高性能和抽象功能来创建应用程序和服务。[ONOS 的 GitHub 地址][9]。
|
||||
<ruby>开放网络操作系统<rt>Open Network Operating System</rt></ruby>(ONOS)是一个 Linux 基金会项目,它是一个面向服务提供商的软件定义网络操作系统,它具有可扩展性、高可用性、高性能和抽象功能来创建应用程序和服务。
|
||||
|
||||
[OpenContrail][10]
|
||||
[ONOS 的 GitHub 地址][9]。
|
||||
|
||||
OpenContrail 是 Juniper Networks 的云开源网络虚拟化平台。它提供网络虚拟化的所有必要组件:SDN 控制器、虚拟路由器、分析引擎和已发布的上层 API。其 REST API 配置并收集来自系统的操作和分析数据。[OpenContrail 的 GitHub 地址][11]。
|
||||
#### [OpenContrail][10]
|
||||
|
||||
[OpenDaylight][12]
|
||||
OpenContrail 是 Juniper Networks 的云开源网络虚拟化平台。它提供网络虚拟化的所有必要组件:SDN 控制器、虚拟路由器、分析引擎和已发布的上层 API。其 REST API 配置并收集来自系统的操作和分析数据。
|
||||
|
||||
OpenDaylight 是 Linux 基金会的一个 OpenDaylight Foundation 项目,它是一个可编程的、提供给服务提供商和企业的软件定义网络平台。它基于微服务架构,可以在多供应商环境中的一系列硬件上实现网络服务。[OpenDaylight 的 GitHub 地址][13]。
|
||||
[OpenContrail 的 GitHub 地址][11]。
|
||||
|
||||
[Open vSwitch][14]
|
||||
#### [OpenDaylight][12]
|
||||
|
||||
Open vSwitch 是一个 Linux 基金会项目,具有生产级别质量的多层虚拟交换机。它通过程序化扩展设计用于大规模网络自动化,同时还支持标准管理接口和协议,包括 NetFlow、sFlow、IPFIX、RSPAN、CLI、LACP 和 802.1ag。它支持类似 VMware 的分布式 vNetwork 或者 Cisco Nexus 1000V 那样跨越多个物理服务器分发。[OVS 在 GitHub 的地址][15]。
|
||||
OpenDaylight 是 Linux 基金会旗下的 OpenDaylight 基金会项目,它是一个可编程的、提供给服务提供商和企业的软件定义网络平台。它基于微服务架构,可以在多供应商环境中的一系列硬件上实现网络服务。
|
||||
|
||||
[OPNFV][16]
|
||||
[OpenDaylight 的 GitHub 地址][13]。
|
||||
|
||||
<ruby>网络功能虚拟化开放平台<rt>Open Platform for Network Functions Virtualization</rt></ruby>(OPNFV) 是 Linux 基金会项目,它用于企业和服务提供商网络的 NFV 平台。它汇集了计算、存储和网络虚拟化方面的上游组件以创建 NFV 程序的端到端平台。[OPNFV 在 Bitergia 上的地址][17]。
|
||||
#### [Open vSwitch][14]
|
||||
|
||||
_要了解更多关于开源云计算趋势和查看顶级开源云计算项目完整列表,[请下载 Linux 基金会的 “开放云指南”。][18]_
|
||||
Open vSwitch 是一个 Linux 基金会项目,是具有生产级品质的多层虚拟交换机。它通过程序化扩展设计用于大规模网络自动化,同时还支持标准管理接口和协议,包括 NetFlow、sFlow、IPFIX、RSPAN、CLI、LACP 和 802.1ag。它支持类似 VMware 的分布式 vNetwork 或者 Cisco Nexus 1000V 那样跨越多个物理服务器分发。
|
||||
|
||||
[OVS 在 GitHub 的地址][15]。
|
||||
|
||||
#### [OPNFV][16]
|
||||
|
||||
<ruby>网络功能虚拟化开放平台<rt>Open Platform for Network Functions Virtualization</rt></ruby>(OPNFV)是 Linux 基金会项目,它用于企业和服务提供商网络的 NFV 平台。它汇集了计算、存储和网络虚拟化方面的上游组件以创建 NFV 程序的端到端平台。
|
||||
|
||||
[OPNFV 在 Bitergia 上的地址][17]。
|
||||
|
||||
_要了解更多关于开源云计算趋势和查看顶级开源云计算项目完整列表,[请下载 Linux 基金会的 “开放云指南”][18]。_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -0,0 +1,108 @@
|
||||
CentOS 上最佳的第三方仓库
|
||||
============================================================
|
||||
|
||||
![CentOS](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/centos.png?itok=YRMQVk7U "CentOS")
|
||||
|
||||
> 从 Software Collections、EPEL 和 Remi 获得可靠的 CentOS 新版软件。
|
||||
|
||||
在 Red Hat 企业 Linux(RHEL) 上,提供那些早已老掉牙的软件已经是企业级软件厂商的传统了。这倒不是因为他们懒,而确实是用户需要。很多公司像看待家具一样看待软件:我买一张桌子,能用一辈子,软件不应该也这样吗?
|
||||
|
||||
CentOS 作为 RHEL 的复制品有着同样的遭遇。虽然 Red Hat 还在为这些被厂商抛弃的过时软件提供支持、修补安全漏洞等,但如果你的应用依赖新版软件,你就得想办法了。 我在这个问题上不止一次碰壁。 LAMP 组合里任一个组件都需要其它所有组件能与其兼容,这有时就显得很麻烦。 比如说去年我就被 RHEL/CentOS 折腾得够呛。REHL/CentOS 第 6 版最高支持 PHP 5.3 ,第 7 版支持到 PHP 5.4 。而 PHP 5.3 早在 2014 年 8 月就到达 EOL(End Of Life) ,不再被厂商支持了, PHP 5.4 的 EOL 在 2015 年 9 月, 5.5 则是 2016 年 7 月。 有太多古老的软件版本,包括 MySQL、Python 等,它们应该像木乃伊一样被展示在博物馆里,但它们却活在你的系统上。
|
||||
|
||||
那么,可怜的管理员们该怎么办呢?如果你跑着 RHEL/CentOS ,那应该先试试 [Software Collections][3],因为这是 Red Hat 唯一支持的新软件包源。 [Software Collections][3] 为 CentOS 设立了专门的仓库,安装和管理都和其它第三方仓库一样。但如果你用的是 RHEL 的,情况就有点不同了,具体请参考 [RHEL 的解决方法][4]。[Software Collections][3] 同样支持 Fedora 和 Scientific Linux 。
|
||||
|
||||
### 安装 Software Collections
|
||||
|
||||
在 CentOS 6/7 上安装 Software Collections 的命令如下:
|
||||
|
||||
```
|
||||
$ sudo yum install centos-release-scl
|
||||
```
|
||||
|
||||
`centos-release-scl-rh` 可能作为依赖包被同时安装。
|
||||
|
||||
然后就可以像平常一样搜索、安装软件包了:
|
||||
|
||||
```
|
||||
$ yum search php7
|
||||
[...]
|
||||
rh-php70.x86_64 : Package that installs PHP 7.0
|
||||
[...]
|
||||
$ sudo yum install rh-php70
|
||||
```
|
||||
|
||||
最后一件事就是启用你的新软件包:
|
||||
|
||||
```
|
||||
$ scl enable rh-php70 bash
|
||||
$ php -v
|
||||
PHP 7.0.10
|
||||
```
|
||||
|
||||
此命令会开启一个新的 bash 并配置好环境变量以便运行新软件包。 如果需要的话,你还得安装对应的扩展包,比如对于 Python 、PHP、MySQL 等软件包,有些配置文件也需要修改以指向新版软件(比如 Apache )。
|
||||
|
||||
这些 SCL 软件包在重启后不会激活。SCL 的设计初衷就是在不影响原有配置的前提下,让新旧软件能一起运行。不过你可以通过 `~/.bashrc` 加载 SCL 提供的 `enable` 脚本来实现自动启用。 SCL 的所有软件包都安装在 `/opt` 下, 以我们的 PHP 7 为例,在 `~/.bashrc` 里加入一行:
|
||||
|
||||
```
|
||||
source /opt/rh/rh-php70/enable
|
||||
```
|
||||
|
||||
以后相应的软件包就能在重启后自动启用了。有新软件保驾护航,你终于可以专注于自己的业务了。
|
||||
|
||||
### 列出可用软件包
|
||||
|
||||
那么,到底 Software Collections 里都是些什么呢? centos-release-scl 里有一些由社区维护的额外的软件包。除了在 [CentOS Wiki][5] 查看软件包列表外,你还可以使用 Yum 。我们先来看看安装了哪些仓库:
|
||||
|
||||
```
|
||||
$ yum repolist
|
||||
[...]
|
||||
repo id repo name
|
||||
base/7/x86_64 CentOS-7 - Base
|
||||
centos-sclo-rh/x86_64 CentOS-7 - SCLo rh
|
||||
centos-sclo-sclo/x86_64 CentOS-7 - SCLo sclo
|
||||
extras/7/x86_64 CentOS-7 - Extras
|
||||
updates/7/x86_64 CentOS-7 - Updates
|
||||
```
|
||||
|
||||
Yum 没有专门用来打印某一个仓库中所有软件包的命令,所以你得这样来: (LCTT 译注:实际上有,`yum repo-pkgs REPO list`,需要 root 权限,dnf 同)
|
||||
|
||||
```
|
||||
$ yum --disablerepo "*" --enablerepo centos-sclo-rh \
|
||||
list available | less
|
||||
```
|
||||
|
||||
`--disablerepo` 与 `--enablerepo` 选项的用法没有详细的文档,这里简单说下。 实际上在这个命令里你并没有禁用或启用什么东西,而只是将你的搜索范围限制在某一个仓库内。 此命令会打印出一个很长的列表,所以我们用管道传递给 `less` 输出。
|
||||
|
||||
### EPEL
|
||||
|
||||
强大的 Fedora 社区为 Feora 及所有 RHEL 系的发行版维护着 [EPEL:Extra Packages for Enterprise Linux][6] 。 里面包含一些最新软件包以及一些未被发行版收纳的软件包。安装 EPEL 里的软件就不用麻烦 `enable` 脚本了,直接像平常一样用。你还可以用 `--disablerepo` 和 `--enablerepo` 选项指定从 EPEL 里安装软件包:
|
||||
|
||||
```
|
||||
$ sudo yum --disablerepo "*" --enablerepo epel install [package]
|
||||
```
|
||||
|
||||
### Remi Collet
|
||||
|
||||
Remi Collet 在 [Remi 的 RPM 仓库][7] 里维护着大量更新的和额外的软件包。需要先安装 EPEL ,因为 Remi 仓库依赖它。
|
||||
|
||||
CentOS wiki 上有较完整的仓库列表:[更多的第三方仓库][8] ,用哪些,不用哪些,里面都有建议。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/learn/intro-to-linux/2017/2/best-third-party-repositories-centos
|
||||
|
||||
作者:[CARLA SCHRODER][a]
|
||||
译者:[Dotcra](https://github.com/Dotcra)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linux.com/users/cschroder
|
||||
[1]:https://www.linux.com/licenses/category/creative-commons-attribution
|
||||
[2]:https://www.linux.com/files/images/centospng
|
||||
[3]:https://www.softwarecollections.org/en/
|
||||
[4]:https://access.redhat.com/solutions/472793
|
||||
[5]:https://wiki.centos.org/SpecialInterestGroup/SCLo/CollectionsList
|
||||
[6]:https://fedoraproject.org/wiki/EPEL
|
||||
[7]:http://rpms.remirepo.net/
|
||||
[8]:https://wiki.centos.org/AdditionalResources/Repositories
|
97
published/201705/20170210 Fedora 25 Wayland vs Xorg.md
Normal file
97
published/201705/20170210 Fedora 25 Wayland vs Xorg.md
Normal file
@ -0,0 +1,97 @@
|
||||
Fedora 25: Wayland 大战 Xorg
|
||||
============
|
||||
|
||||
就像异形大战铁血战士的结果一样,后者略胜一筹。不管怎样,你可能知道,我最近测试了 [Fedora 25][1],体验还可以。总的来说,这个发行版表现的相当不错。它不是最快速的,但随着一系列的改进,变得足够稳定也足够好用。最重要的是,除了一些性能以及响应性的损失,Wayland 并没有造成我的系统瘫痪。但这还仅仅是个开始。
|
||||
|
||||
Wayland 作为一种消费者技术还处在它的襁褓期,或者至少是当人们在处理桌面事物时应就这么认为。因此,我必须继续测试,绝不弃坑。在过去的积极地使用 Fedora 25 的几个星期里,我确实碰到了几个其它的问题,有些不用太担心,有些确实很恼人,有些很奇怪,有些却无意义。让我们来讲述一下吧!
|
||||
|
||||
![Teaser](http://www.dedoimedo.com/images/computers-years/2016-2/fedora-wayland-xorg-teaser.jpg)
|
||||
|
||||
注: 图片来自 [Wikimedia][2] 并做了些修改, [CC BY-SA 3.0][3] 许可
|
||||
|
||||
### Wayland 并不支持所有软件
|
||||
|
||||
没错,这是一个事实。如果你去网站上阅读相关的信息,你会发现各种各样的软件都还没为 Wayland 做好准备。当然,我们都知道 Fedora 是一个激进的高端发行版,它是为了探索新功能而出现的测试床。这没毛病。有一段时间,所有东西都很正常,没有瞎忙活,没有错误。但接下来,我突然需要使用 GParted。我当时很着急,正在排除一个大故障,然而我却让自己置身于一些无意义的额外工作。 GParted 没办法在 Wayland 下直接启动。在探索了更多一些细节之后,我知道了该分区软件目前还没有被 Wayland 支持。
|
||||
|
||||
![GParted 无法运行于 Wayland](http://www.dedoimedo.com/images/computers-years/2016-2/fedora-wayland-xorg-gparted.jpg)
|
||||
|
||||
问题就在于我并不太清楚其它哪些应用不能在 Wayland 下运行,并且我不能在一个正确估计的时间敏锐地发现这一点。通过在线搜索,我还是不能快速找到一个简要的当前不兼容列表。可能只是我在搜索方面不太在行,但显而易见这些东西是和“Wayland + 兼容性” 这样的问题一样零零散散的。
|
||||
|
||||
我找到了一个[自诩][4] Wayland 很棒的文章、一个目前已被这个新玩意儿支持的 [Gnome][5] 应用程序列表、一些 ArchWiki 上难懂的资料,一篇在[英伟达][6]开发论坛上的晦涩得让我后悔点进去的主题,以及一些其他含糊的讨论。
|
||||
|
||||
### 再次提到性能
|
||||
|
||||
在 Fedora 25 上,我把登录会话从 Gnome(Wayland)切换到 Gnome Xorg,观察会对系统产生什么影响。我之前已经提到过在同一个笔记本([联想 G50][8])上的性能跑分和与 [Fedora 24][7] 的比较,但这次会给我们提供更加准确的结果。
|
||||
|
||||
Wayland(截图 1)空闲时的内存占用为 1.4GB, CPU 的平均负载约为 4-5%。Xorg(截图 2)占用了同样大小的内存,处理器消耗了全部性能的 3-4%,单纯从数字上来看少了一小点。但是 Xorg 会话的体验却好得多。虽然只是毫秒级的差距,但你能感受得到。传统的会话方式看起来更加的灵动、快速、清新一点。但 Wayland 落后得并不明显。如果你对你的电脑响应速度很敏感,你可能会对这点延迟不会太满意。当然,这也许只是作为新手缺乏优化的缘故,Wayland 会随时间进步。但这一点也是我们所不能忽视的。
|
||||
|
||||
![Wayland resources](http://www.dedoimedo.com/images/computers-years/2016-2/fedora-wayland-xorg-resources-wayland.jpg)
|
||||
|
||||
![Xorg resources](http://www.dedoimedo.com/images/computers-years/2016-2/fedora-wayland-xorg-resources-xorg.jpg)
|
||||
|
||||
### 批评
|
||||
|
||||
我对此并不高兴。虽然并不是很愤怒,但我不喜欢为了能完全享受我的桌面体验,我却需要登录到传统的 X 会话。因为 X 给了我全部,但 Wayland 则没有。这意味着我不能一天都用着 Wayland。我喜欢探索科技,但我不是一个盲目的狂热追随者。我只是想用我的桌面,有时我可能需要它快速响应。注销然后重新登录在急需使用的时候会成为恼人的麻烦。我们遇到这个问题的原因就是 Wayland 没有让 Linux 桌面用户的生活变得更简单,而恰恰相反。
|
||||
|
||||
引用:
|
||||
|
||||
> Wayland 是为了成为 X 的更加简单的替代品,更加容易开发和维护。建议 GNOME 和 KDE 都使用它。
|
||||
|
||||
你能看到,这就是问题的一方面原因。东西不应该被设计成容易开发或维护。它可以是满足了所有其它消费需求之后提供的有益副产品。但如果没有,那么不管它对于程序员敲代码来说多么困难或简单都将不重要。那是他们的工作。科技的所有目的都是为了达到一种无缝并且流畅的用户体验。
|
||||
|
||||
不幸的是,现在很大数量的产品都被重新设计或者开发,只是为了使软件人员更加轻松,而不是用户。在很大程度上,Gnome 3、PulseAudio、[Systemd][9] 和 Wayland 都没有遵循提高用户体验的宗旨。在这个意义上来说,它们更像是一种打扰,而没有为 Linux 桌面生态的稳定性和易用性作出贡献。
|
||||
|
||||
这也是为什么 Linux 桌面是一个相对不成熟产品的一个主要原因————它被设计成开发人员的自我支持产品,更像一个活生生的生物,而不是依附于用户各种怪念头和想法的奴隶。这也是伟大事物是如何形成的,你满足于主要需求,接下来只是担心细节方面。优秀的用户体验不依赖于(也永远不依赖于)编程语言、编译器的选择,或任何其他无意义的东西。如果依赖了,那么不管谁来设计这个抽象层做的不够好的产品,我们都会得到一个失败的作品,需要把它的存在抹去。
|
||||
|
||||
那么在我的展望中,我不在乎是否要吐血十升去编译一个 Xorg 或其它什么的版本。我是一个用户,我所在乎的只是我的桌面能否像它昨天或者 5 年前一样健壮地工作。没事的情况下,我不会对宏、类、变量、声明、结构体,或其他任何极客的计算机科技感兴趣。那是不着边际的。一个产品宣传自己是被创造出来为人们的开发提供方便的,那是个悖论。如果接下来再也不用去开发它了,这样反而会使事情更简单。
|
||||
|
||||
现在,事实是 Wayland 大体上可用,但它仍然不像 Xorg 那么好,并且它也不应该在任何的桌面上作为就绪的产品被提供。一但它能够无人知晓般无缝地取代那些过时技术,只有在那种时候,它才获得了它所需要的成功,那之后,它可以用 C、D 或者 K 之类的无论什么语言编写,拥有开发者需要的任何东西。而在那之前,它都是一个蚕食资源和人们思想的寄生虫而已。
|
||||
|
||||
不要误会,我们需要进步,需要改变。但它必须为了进化的目而服务。现在 Xorg 能很好地满足用户需求了吗?它能为第三方库提供图形支持吗?它能支持 HD、UHD、DPI 或其他的什么吗?你能用它玩最新的游戏吗?行还是不行?如果不行,那么它就需要被改进。这些就是进化的驱动力,而不是写代码或者编译代码的困难程度。软件开发者是数字工业的矿工,他们需要努力工作而取悦于用户。就像短语“更加易于开发”应该被取缔一样,那些崇尚于此的人也应该用老式收音机的电池处以电刑,然后用没有空调的飞船流放到火星上去。如果你不能写出高明的代码,那是你的问题。用户不能因为开发者认为自己是公主而遭受折磨。
|
||||
|
||||
### 结语
|
||||
|
||||
说到这里。大体上说,Wayland 还可以,并不差。但这说的就像是某人决定修改你工资单上分配比例,导致你从昨天能赚 100% 到今天只能赚 83% 一样。讲道理这是不能接受的,即使 Wayland 工作的相当好。正是那些不能运作的东西导致如此大的不同。忽略所有批评它的一面,Wayland 被认为降低了可用性、性能以及软件的知名度,这正是 Fedora 亟待解决的问题。
|
||||
|
||||
其他的发行版会跟进,然后我们会看到历史重演,就像 Gnome 3 和 Systemd 所发生的一样。没有完全准备好的东西被放到开放环境中,然后我们花费一两年时间修复那些本无需修复的东西,最终我们将拥有的是我们已经拥有的相同功能,只是用不同的编程语言来实现。我并不感兴趣这些。计算机科学曾在 1999 年非常受欢迎,当时 Excel 用户每小时能赚 50 美元。而现在,编程就像是躲在平底船下划桨,人们并不会在乎你在甲板下流下的汗水与磨出的水泡。
|
||||
|
||||
性能可能不太是一个问题了,因为你可以放弃 1-2% 的变化,尤其是它会受随机的来自任何一个因素的影响,如果你已经用 Linux 超过一、两年你就会知道的。但是无法启动应用是个大问题。不过至少, Fedora 也友好地提供了传统的平台。但是,它可能会在 Wayland 100% 成熟前就消失了。我们再来看看,不,不会有灾难。我原本的 Fedora 25 宣称支持这种看法。我们有的就是烦恼,不必要的烦恼。啊,这是 Linux 故事中的第 9000 集。
|
||||
|
||||
那么,在今天结束之际,我们已经讨论了所有事情。从中我们学到:**臣伏于 Xorg!天呐!**真棒,现在我将淡入背景音乐,而笑声会将你的欢乐带给寒冷的夜晚。再见!
|
||||
|
||||
干杯。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
作者简介:
|
||||
|
||||
我是 Igor Ljubuncic。现在大约 38 岁,已婚但还没有孩子。我现在在一个大胆创新的云科技公司做首席工程师。直到大约 2015 年初,我还在一个全世界最大的 IT 公司之一中做系统架构工程师,和一个工程计算团队开发新的基于 Linux 的解决方案,优化内核以及攻克 Linux 的问题。在那之前,我是一个为高性能计算环境设计创新解决方案的团队的技术领导。还有一些其他花哨的头衔,包括系统专家、系统程序员等等。所有这些都曾是我的爱好,但从 2008 年开始成为了我的有偿的工作。还有什么比这更令人满意的呢?
|
||||
|
||||
从 2004 年到 2008 年间,我曾通过作为医学影像行业的物理学家来糊口。我的工作专长集中在解决问题和算法开发。为此,我广泛地使用了 Matlab,主要用于信号和图像处理。另外,我得到了几个主要的工程方法学的认证,包括 MEDIC 六西格玛绿带、试验设计以及统计工程学。
|
||||
|
||||
我也写过书,包括高度魔幻类和 Linux 上的技术工作方面的,彼此交织。
|
||||
|
||||
|
||||
-------------
|
||||
|
||||
|
||||
via: http://www.dedoimedo.com/computers/fedora-25-wayland-vs-xorg.html
|
||||
|
||||
作者:[Igor Ljubuncic][a]
|
||||
译者:[cycoe](https://github.com/cycoe)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.dedoimedo.com/faq.html
|
||||
|
||||
[1]:http://www.dedoimedo.com/computers/fedora-25-gnome.html
|
||||
[2]:https://commons.wikimedia.org/wiki/File:DragonCon-AlienVsPredator.jpg
|
||||
[3]:https://creativecommons.org/licenses/by-sa/3.0/deed.en
|
||||
[4]:https://wayland.freedesktop.org/faq.html
|
||||
[5]:https://wiki.gnome.org/Initiatives/Wayland/Applications
|
||||
[6]:https://devtalk.nvidia.com/default/topic/925605/linux/nvidia-364-12-release-vulkan-glvnd-drm-kms-and-eglstreams/
|
||||
[7]:http://www.dedoimedo.com/computers/fedora-24-gnome.html
|
||||
[8]:http://www.dedoimedo.com/computers/lenovo-g50-distros-second-round.html
|
||||
[9]:http://www.ocsmag.com/2016/10/19/systemd-progress-through-complexity/
|
@ -0,0 +1,216 @@
|
||||
8 个优秀的开源 Markdown 编辑器
|
||||
============================================================
|
||||
|
||||
### Markdown
|
||||
|
||||
首先,对 Markdown 进行一个简单的介绍。Markdown 是由 John Gruber 和 Aaron Swartz 共同创建的一种轻量级纯文本格式语法。Markdown 可以让用户“以易读、易写的纯文本格式来进行写作,然后可以将其转换为有效格式的 XHTML(或 HTML)“。Markdown 语法只包含一些非常容易记住的符号。其学习曲线平缓;你可以在炒蘑菇的同时一点点学习 Markdown 语法(大约 10 分钟)。通过使用尽可能简单的语法,错误率达到了最小化。除了拥有友好的语法,它还具有直接输出干净、有效的(X)HTML 文件的强大功能。如果你看过我的 HTML 文件,你就会知道这个功能是多么的重要。
|
||||
|
||||
Markdown 格式语法的主要目标是实现最大的可读性。用户能够以纯文本的形式发布一份 Markdown 格式的文件。用 Markdown 进行文本写作的一个优点是易于在计算机、智能手机和个人之间共享。几乎所有的内容管理系统都支持 Markdown 。它作为一种网络写作格式流行起来,其产生一些被许多服务采用的变种,比如 GitHub 和 Stack Exchange 。
|
||||
|
||||
你可以使用任何文本编辑器来写 Markdown 文件。但我建议使用一个专门为这种语法设计的编辑器。这篇文章中所讨论的软件允许你使用 Markdown 语法来写各种格式的专业文档,包括博客文章、演示文稿、报告、电子邮件以及幻灯片等。另外,所有的应用都是在开源许可证下发布的,在 Linux、OS X 和 Windows 操作系统下均可用。
|
||||
|
||||
|
||||
### Remarkable
|
||||
|
||||
![Remarkable - cross-platform Markdown editor](https://i2.wp.com/www.ossblog.org/wp-content/uploads/2017/02/Remarkable.png?resize=800%2C319&ssl=1)
|
||||
|
||||
让我们从 Remarkable 开始。Remarkable 是一个 apt 软件包的名字,它是一个相当有特色的 Markdown 编辑器 — 它并不支持 Markdown 的全部功能特性,但该有的功能特性都有。它使用和 GitHub Markdown 类似的语法。
|
||||
|
||||
你可以使用 Remarkable 来写 Markdown 文档,并在实时预览窗口查看更改。你可以把你的文件导出为 PDF 格式(带有目录)和 HTML 格式文件。它有强大的配置选项,从而具有许多样式,因此,你可以把它配置成你最满意的 Markdown 编辑器。
|
||||
|
||||
其他一些特性:
|
||||
|
||||
* 语法高亮
|
||||
* 支持 [GitHub 风味的 Markdown](https://linux.cn/article-8399-1.html)
|
||||
* 支持 MathJax - 通过高级格式呈现丰富文档
|
||||
* 键盘快捷键
|
||||
|
||||
在 Debian、Ubuntu、Fedora、SUSE 和 Arch 系统上均有 Remarkable 的可用的简易安装程序。
|
||||
|
||||
主页: [https://remarkableapp.github.io/][4]
|
||||
许可证: MIT 许可
|
||||
|
||||
### Atom
|
||||
|
||||
![Atom - cross-platform Markdown editor](https://i2.wp.com/www.ossblog.org/wp-content/uploads/2017/02/Atom-Markdown.png?resize=800%2C328&ssl=1)
|
||||
|
||||
毫无疑问, Atom 是一个神话般的文本编辑器。超过 50 个开源包集合在一个微小的内核上,从而构成 Atom 。伴有 Node.js 的支持,以及全套功能特性,Atom 是我最喜欢用来写代码的编辑器。Atom 的特性在[杀手级开源应用][5]的文章中有更详细介绍,它是如此的强大。但是作为一个 Markdown 编辑器,Atom 还有许多不足之处,它的默认包不支持 Markdown 的特性。例如,正如上图所展示的,它不支持等价渲染。
|
||||
|
||||
但是,开源拥有强大的力量,这是我强烈提倡开源的一个重要原因。Atom 上有许多包以及一些复刻,从而添加了缺失的功能特性。比如,Markdown Preview Plus 提供了 Markdown 文件的实时预览,并伴有数学公式渲染和实时重加载。另外,你也可以尝试一下 [Markdown Preview Enhanced][6]。如果你需要自动滚动特性,那么 [markdown-scroll-sync][7] 可以满足你的需求。我是 [Markdown-Writer][8]和 [Markdown-pdf][9]的忠实拥趸,后者支持将 Markdown 快速转换为 PDF、PNG 以及 JPEG 文件。
|
||||
|
||||
这个方式体现了开源的理念:允许用户通过添加扩展来提供所需的特性。这让我想起了 Woolworths 的 n 种杂拌糖果的故事。虽然需要多付出一些努力,但能收获最好的回报。
|
||||
|
||||
主页: [https://atom.io/][10]
|
||||
许可证: MIT 许可
|
||||
|
||||
### Haroopad
|
||||
|
||||
![Haroopad - - cross-platform Markdown editor](https://i2.wp.com/www.ossblog.org/wp-content/uploads/2017/02/Haroopad-1.png?resize=800%2C332&ssl=1)
|
||||
|
||||
Haroopad 是一个优秀的 Markdown 编辑器,是一个用于创建适宜 Web 的文档的处理器。使用 Haroopad 可以创作各种格式的文档,比如博客文章、幻灯片、演示文稿、报告和电子邮件等。Haroopad 在 Windows、Mac OS X 和 Linux 上均可用。它有 Debian/Ubuntu 的软件包,也有 Windows 和 Mac 的二进制文件。该应用程序使用 node-webkit、CodeMirror,marked,以及 Twitter 的 Bootstrap 。
|
||||
|
||||
Haroo 在韩语中的意思是“一天”。
|
||||
|
||||
它的功能列表非常可观。请看下面:
|
||||
|
||||
* 主题、皮肤和 UI 组件
|
||||
* 超过 30 种不同的编辑主题 - tomorrow-night-bright 和 zenburn 是近期刚添加的
|
||||
* 编辑器中的代码块的语法高亮
|
||||
* Ruby、Python、PHP、Javascript、C、HTML 和 CSS 的语法高亮支持
|
||||
* 基于 CodeMirror,这是一个在浏览器中使用 JavaScript 实现的通用文本编辑器
|
||||
* 实时预览主题
|
||||
* 基于 markdown-css 的 7 个主题
|
||||
* 语法高亮
|
||||
* 基于 hightlight.js 的 112 种语言以及 49 种样式
|
||||
* 定制主题
|
||||
* 基于 CSS (层叠样式表)的样式
|
||||
* 演示模式 - 对于现场演示非常有用
|
||||
* 绘图 - 流程图和序列图
|
||||
* 任务列表
|
||||
* 扩展 Markdown 语法,支持 TOC(目录)、 GitHub 风味 Markdown 以及数学表达式、脚注和任务列表等
|
||||
* 字体大小
|
||||
* 使用首选窗口和快捷键来设置编辑器和预览字体大小
|
||||
* 嵌入富媒体内容
|
||||
* 视频、音频、3D、文本、开放图形以及 oEmbed
|
||||
* 支持大约 100 种主要的网络服务(YouTude、SoundCloud、Flickr 等)
|
||||
* 支持拖放
|
||||
* 显示模式
|
||||
* 默认:编辑器|预览器,倒置:预览器|编辑器,仅编辑器,仅预览器(View -> Mode)
|
||||
* 插入当前日期和时间
|
||||
* 多种格式支持(Insert -> Data & Time)
|
||||
* HtML 到 Markdown
|
||||
* 拖放你在 Web 浏览器中选择好的文本
|
||||
* Markdown 解析选项
|
||||
* 大纲预览
|
||||
* 纯粹主义者的 Vim 键位绑定
|
||||
* Markdown 自动补全
|
||||
* 导出为 PDF 和 HTML
|
||||
* 带有样式的 HTML 复制到剪切板可用于所见即所得编辑器
|
||||
* 自动保存和恢复
|
||||
* 文件状态信息
|
||||
* 换行符或空格缩进
|
||||
* (一、二、三)列布局视图
|
||||
* Markdown 语法帮助对话框
|
||||
* 导入和导出设置
|
||||
* 通过 MathJax 支持 LaTex 数学表达式
|
||||
* 导出文件为 HTML 和 PDF
|
||||
* 创建扩展来构建自己的功能
|
||||
* 高效地将文件转换进博客系统:WordPress、Evernote 和 Tumblr 等
|
||||
* 全屏模式-尽管该模式不能隐藏顶部菜单栏和顶部工具栏
|
||||
* 国际化支持:英文、韩文、西班牙文、简体中文、德文、越南文、俄文、希腊文、葡萄牙文、日文、意大利文、印度尼西亚文土耳其文和法文
|
||||
|
||||
主页 [http://pad.haroopress.com/][11]
|
||||
许可证: GNU GPL v3 许可
|
||||
|
||||
### StackEdit
|
||||
|
||||
![StackEdit - a web based Markdown editor](https://i2.wp.com/www.ossblog.org/wp-content/uploads/2017/02/StackEdit.png?resize=800%2C311&ssl=1)
|
||||
|
||||
StackEdit 是一个功能齐全的 Markdown 编辑器,基于 PageDown(该 Markdown 库被 Stack Overflow 和其他一些 Stack 交流网站使用)。不同于在这个列表中的其他编辑器,StackEdit 是一个基于 Web 的编辑器。在 Chrome 浏览器上即可使用 StackEdit 。
|
||||
|
||||
特性包括:
|
||||
|
||||
* 实时预览 HTML,并通过绑定滚动连接特性来将编辑器和预览的滚动条相绑定
|
||||
* 支持 Markdown Extra 和 GitHub 风味 Markdown,Prettify/Highlight.js 语法高亮
|
||||
* 通过 MathJax 支持 LaTex 数学表达式
|
||||
* 所见即所得的控制按键
|
||||
* 布局配置
|
||||
* 不同风格的主题支持
|
||||
* la carte 扩展
|
||||
* 离线编辑
|
||||
* 可以与 Google 云端硬盘(多帐户)和 Dropbox 在线同步
|
||||
* 一键发布到 Blogger、Dropbox、Gist、GitHub、Google Drive、SSH 服务器、Tumblr 和 WordPress
|
||||
|
||||
主页: [https://stackedit.io/][12]
|
||||
许可证: Apache 许可
|
||||
|
||||
### MacDown
|
||||
|
||||
![MacDown - OS X Markdown editor](https://i0.wp.com/www.ossblog.org/wp-content/uploads/2017/02/MacDown.png?resize=800%2C422&ssl=1)
|
||||
|
||||
MacDown 是在这个列表中唯一一个只运行在 macOS 上的全特性编辑器。具体来说,它需要在 OX S 10.8 或更高的版本上才能使用。它在内部使用 Hoedown 将 Markdown 渲染成 HTML,这使得它的特性更加强大。Heodown 是 Sundown 的一个复活复刻。它完全符合标准,无依赖,具有良好的扩展支持和 UTF-8 感知。
|
||||
|
||||
MacDown 基于 Mou,这是专为 Web 开发人员设计的专用解决方案。
|
||||
|
||||
它提供了良好的 Markdown 渲染,通过 Prism 提供的语言识别渲染实现代码块级的语法高亮,MathML 和 LaTex 渲染,GTM 任务列表,Jekyll 前端以及可选的高级自动补全。更重要的是,它占用资源很少。想在 OS X 上写 Markdown?MacDown 是我针对 Web 开发者的开源推荐。
|
||||
|
||||
主页: [https://macdown.uranusjr.com/][13]
|
||||
许可证: MIT 许可
|
||||
|
||||
|
||||
### ghostwriter
|
||||
|
||||
![ghostwriter - cross-platform Markdown editor](https://i0.wp.com/www.ossblog.org/wp-content/uploads/2017/02/ghostwriter.png?resize=800%2C310&ssl=1)
|
||||
|
||||
ghostwriter 是一个跨平台的、具有美感的、无干扰的 Markdown 编辑器。它内建了 Sundown 处理器支持,还可以自动检测 pandoc、MultiMarkdown、Discount 和 cmark 处理器。它试图成为一个朴实的编辑器。
|
||||
|
||||
ghostwriter 有许多很好的功能设置,包括语法高亮、全屏模式、聚焦模式、主题、通过 Hunspell 进行拼写检查、实时字数统计、实时 HTML 预览、HTML 预览自定义 CSS 样式表、图片拖放支持以及国际化支持。Hemingway 模式按钮可以禁用退格键和删除键。一个新的 “Markdown cheat sheet” HUD 窗口是一个有用的新增功能。主题支持很基本,但在 [GitHub 仓库上][14]也有一些可用的试验性主题。
|
||||
|
||||
ghostwriter 的功能有限。我越来越欣赏这个应用的通用性,部分原因是其简洁的界面能够让写作者完全集中在策划内容上。这一应用非常值得推荐。
|
||||
|
||||
ghostwirter 在 Linux 和 Windows 系统上均可用。在 Windows 系统上还有一个便携式的版本可用。
|
||||
|
||||
主页: [https://github.com/wereturtle/ghostwriter][15]
|
||||
许可证: GNU GPL v3 许可
|
||||
|
||||
### Abricotine
|
||||
|
||||
![Abricotine - cross-platform Markdown editor](https://i2.wp.com/www.ossblog.org/wp-content/uploads/2017/02/Abricotine.png?resize=800%2C316&ssl=1)
|
||||
|
||||
Abricotine 是一个为桌面构建的、旨在跨平台且开源的 Markdown 编辑器。它在 Linux、OS X 和 Windows 上均可用。
|
||||
|
||||
该应用支持 Markdown 语法以及一些 GitHub 风味的 Markdown 增强(比如表格)。它允许用户直接在文本编辑器中预览文档,而不是在侧窗栏。
|
||||
|
||||
该应用有一系列有用的特性,包括拼写检查、以 HTML 格式保存文件或把富文本复制粘贴到邮件客户端。你也可以在侧窗中显示文档目录,展示语法高亮代码、以及助手、锚点和隐藏字符等。它目前正处于早期的开发阶段,因此还有一些很基本的 bug 需要修复,但它值得关注。它有两个主题可用,如果有能力,你也可以添加你自己的主题。
|
||||
|
||||
主页: [http://abricotine.brrd.fr/][16]
|
||||
许可证: GNU 通用公共许可证 v3 或更高许可
|
||||
|
||||
### ReText
|
||||
|
||||
![ReText - Linux Markdown editor](https://i1.wp.com/www.ossblog.org/wp-content/uploads/2017/02/ReText.png?resize=800%2C270&ssl=1)
|
||||
|
||||
ReText 是一个简单而强大的 Markdown 和 reStructureText 文本编辑器。用户可以控制所有输出的格式。它编辑的文件是纯文本文件,但可以导出为 PDF、HTML 和其他格式的文件。ReText 官方仅支持 Linux 系统。
|
||||
|
||||
特性包括:
|
||||
|
||||
* 全屏模式
|
||||
* 实时预览
|
||||
* 同步滚动(针对 Markdown)
|
||||
* 支持数学公式
|
||||
* 拼写检查
|
||||
* 分页符
|
||||
* 导出为 HTML、ODT 和 PDF 格式
|
||||
* 使用其他标记语言
|
||||
|
||||
主页: [https://github.com/retext-project/retext][17]
|
||||
许可证: GNU GPL v2 或更高许可
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ossblog.org/markdown-editors/
|
||||
|
||||
作者:[Steve Emms][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.ossblog.org/author/steve/
|
||||
[1]:https://www.ossblog.org/author/steve/
|
||||
[2]:https://www.ossblog.org/markdown-editors/#comments
|
||||
[3]:https://www.ossblog.org/category/utilities/
|
||||
[4]:https://remarkableapp.github.io/
|
||||
[5]:https://www.ossblog.org/top-software/2/
|
||||
[6]:https://atom.io/packages/markdown-preview-enhanced
|
||||
[7]:https://atom.io/packages/markdown-scroll-sync
|
||||
[8]:https://atom.io/packages/markdown-writer
|
||||
[9]:https://atom.io/packages/markdown-pdf
|
||||
[10]:https://atom.io/
|
||||
[11]:http://pad.haroopress.com/
|
||||
[12]:https://stackedit.io/
|
||||
[13]:https://macdown.uranusjr.com/
|
||||
[14]:https://github.com/jggouvea/ghostwriter-themes
|
||||
[15]:https://github.com/wereturtle/ghostwriter
|
||||
[16]:http://abricotine.brrd.fr/
|
||||
[17]:https://github.com/retext-project/retext
|
@ -1,24 +1,25 @@
|
||||
# 从损坏的 Linux EFI 安装中恢复
|
||||
从损坏的 Linux EFI 安装中恢复
|
||||
=========
|
||||
|
||||
在过去的十多年里,Linux 发行版在安装前、安装过程中、以及安装后偶尔会失败,但我总是有办法恢复系统并继续正常工作。然而,[Solus][1] 损坏了我的笔记本。
|
||||
|
||||
GRUB 恢复。不行,重装。还不行!Ubuntu 拒绝安装,报错目标设备不是这个或那个。哇。我之前还没有遇到过想这样的事情。我的测试机已变成无用的砖块。我们该失望吗?不,绝对不。让我来告诉你怎样你可以修复它吧。
|
||||
GRUB 恢复。不行,重装。还不行!Ubuntu 拒绝安装,目标设备的报错一会这样,一会那样。哇。我之前还没有遇到过像这样的事情。我的测试机已变成无用的砖块。难道我该绝望吗?不,绝对不。让我来告诉你怎样你可以修复它吧。
|
||||
|
||||
### 问题详情
|
||||
|
||||
所有事情都从 Solus 尝试安装它自己的启动引导器 - goofiboot 开始。不知道什么原因、它没有成功完成安装,留给我的就是一个无法启动的系统。BIOS 之后,我有一个 GRUB 恢复终端。
|
||||
所有事情都从 Solus 尝试安装它自己的启动引导器 - goofiboot 开始。不知道什么原因、它没有成功完成安装,留给我的就是一个无法启动的系统。经过 BIOS 引导之后,我进入一个 GRUB 恢复终端。
|
||||
|
||||
![安装失败](http://www.dedoimedo.com/images/computers-years/2016-2/solus-installation-failed.png)
|
||||
![安装失败](http://www.dedoimedo.com/images/computers-years/2016-2/solus-installation-failed.png)
|
||||
|
||||
我尝试在终端中手动修复,使用类似和我在我的扩展 [GRUB2 指南][2]中介绍的这个或那个命令。但还是不行。然后我尝试按照我在[GRUB2 和 EFI 指南][3]中的建议从 Live CD(译者注:Live CD 是一个完整的计算机可引导安装媒介,它包括在计算机内存中运行的操作系统,而不是从硬盘驱动器加载; CD 本身是只读的。 它允许用户为任何目的运行操作系统,而无需安装它或对计算机的配置进行任何更改)中恢复。我用 efibootmgr 工具创建了一个条目,确保标记它为有效。正如我们之前在指南中做的那样,之前这些是能正常工作的。哎,现在这个方法也不起作用。
|
||||
我尝试在终端中手动修复,使用类似和我在我详实的 [GRUB2 指南][2]中介绍的各种命令。但还是不行。然后我尝试按照我在 [GRUB2 和 EFI 指南][3]中的建议从 Live CD 中恢复(LCTT 译注:Live CD 是一个完整的计算机可引导安装媒介,它包括在计算机内存中运行的操作系统,而不是从硬盘驱动器加载;CD 本身是只读的。 它允许用户为任何目的运行操作系统,而无需安装它或对计算机的配置进行任何更改)。我用 efibootmgr 工具创建了一个引导入口,确保标记它为有效。正如我们之前在指南中做的那样,之前这些是能正常工作的。哎,现在这个方法也不起作用。
|
||||
|
||||
我尝试一次完整的 Ubuntu 安装,把它安装到 Solus 所在的分区,希望安装程序能给我一些有用的信息。但是 Ubuntu 无法按成安装。它报错:failed to install into /target。又回到开始的地方了。怎么办?
|
||||
我尝试做一个完整的 Ubuntu 安装,把它安装到 Solus 所在的分区,希望安装程序能给我一些有用的信息。但是 Ubuntu 无法完成安装。它报错:failed to install into /target。又回到开始的地方了。怎么办?
|
||||
|
||||
### 手动清除 EFI 分区
|
||||
|
||||
显然,我们的 EFI 分区出现了严重问题。简单回顾以下,如果你使用的是 UEFI,那么你需要一个单独的 FAT-32 格式化分区。该分区用于存储 EFI 引导镜像。例如,当你安装 Fedora 时,Fedora 引导镜像会被拷贝到 EFI 子目录。每个操作系统都会被存储到一个它自己的目录,一般是 /boot/efi/EFI/<操作系统版本>/。
|
||||
显然,我们的 EFI 分区出现了严重问题。简单回顾以下,如果你使用的是 UEFI,那么你需要一个单独的 FAT-32 格式化的分区。该分区用于存储 EFI 引导镜像。例如,当你安装 Fedora 时,Fedora 引导镜像会被拷贝到 EFI 子目录。每个操作系统都会被存储到一个它自己的目录,一般是 `/boot/efi/EFI/<操作系统版本>/`。
|
||||
|
||||
![EFI 分区内容](http://www.dedoimedo.com/images/computers-years/2016-2/grub2-efi-partition-contents.png)
|
||||
![EFI 分区内容](http://www.dedoimedo.com/images/computers-years/2016-2/grub2-efi-partition-contents.png)
|
||||
|
||||
在我的 [G50][4] 机器上,这里有很多各种发行版测试条目,包括:centos、debian、fedora、mx-15、suse、Ubuntu、zorin 以及其它。这里也有一个 goofiboot 目录。但是,efibootmgr 并没有在它的菜单中显示 goofiboot 条目。显然这里出现了一些问题。
|
||||
|
||||
@ -45,7 +46,7 @@ Boot2003* EFI Network
|
||||
P.S. 上面的输出是在 LIVE 会话中运行命令生成的!
|
||||
|
||||
|
||||
我决定清除所有非默认的以及非微软的条目然后重新开始。显然,有些东西被损坏了,妨碍了新的发行版设置它们自己的启动引导程序。因此我删除了 /boot/efi/EFI 分区下面出 Boot 和 Windows 外的所有目录。同时,我也通过删除所有额外的条目更新了启动管理器。
|
||||
我决定清除所有非默认的以及非微软的条目然后重新开始。显然,有些东西被损坏了,妨碍了新的发行版设置它们自己的启动引导程序。因此我删除了 `/boot/efi/EFI` 分区下面除了 Boot 和 Windows 以外的所有目录。同时,我也通过删除所有额外的条目更新了启动管理器。
|
||||
|
||||
```
|
||||
efibootmgr -b <hex> -B <hex>
|
||||
@ -53,23 +54,20 @@ efibootmgr -b <hex> -B <hex>
|
||||
|
||||
最后,我重新安装了 Ubuntu,并仔细监控 GRUB 安装和配置的过程。这次,成功完成啦。正如预期的那样,几个无效条目出现了一些错误,但整个安装过程完成就好了。
|
||||
|
||||
![安装错误](http://www.dedoimedo.com/images/computers-years/2016-2/grub2-install-errors.jpg)
|
||||
![安装的错误消息](http://www.dedoimedo.com/images/computers-years/2016-2/grub2-install-errors.jpg)
|
||||
|
||||
![安装成功](http://www.dedoimedo.com/images/computers-years/2016-2/grub2-install-successful.jpg)
|
||||
![安装的成功消息](http://www.dedoimedo.com/images/computers-years/2016-2/grub2-install-successful.jpg)
|
||||
|
||||
### 额外阅读
|
||||
|
||||
如果你不喜欢这种手动修复,你可以阅读:
|
||||
|
||||
```
|
||||
[Boot-Info][5] 手册,里面有帮助你恢复系统的自动化工具
|
||||
|
||||
[Boot-repair-cd][6] 自动恢复工具下载页面
|
||||
```
|
||||
- [Boot-Info][5] 手册,里面有帮助你恢复系统的自动化工具
|
||||
- [Boot-repair-cd][6] 自动恢复工具下载页面
|
||||
|
||||
### 总结
|
||||
|
||||
如果你遇到由于 EFI 分区破坏而导致系统严重瘫痪的情况,那么你可能需要遵循本指南中的建议。 删除所有非默认条目。 如果你使用 Windows 进行多重引导,请确保不要修改任何和 Microsoft 相关的东西。 然后相应地更新引导菜单,以便删除损坏的条目。 重新运行所需发行版的安装设置,或者尝试用之前介绍的比较不严格的修复方法。
|
||||
如果你遇到由于 EFI 分区破坏而导致系统严重瘫痪的情况,那么你可能需要遵循本指南中的建议。 删除所有非默认条目。 如果你使用 Windows 进行多重引导,请确保不要修改任何和 Microsoft 相关的东西。 然后相应地更新引导菜单,以便删除损坏的条目。 重新运行所需发行版的安装设置,或者尝试用之前介绍的比较不严谨的修复方法。
|
||||
|
||||
我希望这篇小文章能帮你节省一些时间。Solus 对我系统的更改使我很懊恼。这些事情本不应该发生,恢复过程也应该更简单。不管怎样,虽然事情似乎很可怕,修复并不是很难。你只需要删除损害的文件然后重新开始。你的数据应该不会受到影响,你也应该能够顺利进入到运行中的系统并继续工作。开始吧。
|
||||
|
||||
@ -84,12 +82,6 @@ efibootmgr -b <hex> -B <hex>
|
||||
|
||||
从 2004 到 2008 年,我通过在医疗图像行业担任物理专家养活自己。我的工作主要关注解决问题和开发算法。为此,我广泛使用 Matlab,主要用于信号和图像处理。另外,我已通过几个主要工程方法的认证,包括 MEDIC Six Sigma Green Belt、实验设计以及统计工程。
|
||||
|
||||
有时候我也会写书,包括 Linux 创新及技术工作。
|
||||
|
||||
往下滚动你可以查看我开源项目的完整列表、发表文章以及专利。
|
||||
|
||||
有关我奖项、提名以及 IT 相关认证的完整列表,稍后也会有。
|
||||
|
||||
|
||||
-------------
|
||||
|
||||
@ -98,7 +90,7 @@ via: http://www.dedoimedo.com/computers/grub2-efi-corrupt-part-recovery.html
|
||||
|
||||
作者:[Igor Ljubuncic][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,40 +1,46 @@
|
||||
translating by Locez
|
||||
Set Up and Configure a Firewall with FirewallD on CentOS 7
|
||||
============================================================
|
||||
在 CentOS 上使用 FirewallD 配置防火墙
|
||||
================================================
|
||||
|
||||
![](https://www.rosehosting.com/blog/wp-content/uploads/2017/02/set-up-and-configure-a-firewall-with-firewalld-on-centos-7.jpg)
|
||||
![](https://www.rosehosting.com/blog/wp-content/uploads/2017/02/set-up-and-configure-a-firewall-with-firewalld-on-centos-7.jpg)
|
||||
|
||||
FirewallD is a firewall management tool available by default on CentOS 7 servers. Basically, it is a wrapper around iptables and it comes with graphical configuration tool firewall-config and command line tool firewall-cmd. With the iptables service, every change requires flushing of the old rules and reading the new rules from the `/etc/sysconfig/iptables` file, while with firewalld only differences are applied.
|
||||
FirewallD 是 CentOS 7 服务器上默认使用的防火墙管理工具。从根本上来讲,它是在 iptables 基础上的一个包装,它同时拥有图形配置工具 firewall-config 和命令行工具 firewall-cmd。使用 iptables 服务的话,每次更改设置后都要求刷新旧的规则,然后从文件 `/etc/sysconfig/iptables` 中读取新的规则,然而 firewalld 只对差异进行改动。
|
||||
|
||||
### FirewallD zones
|
||||
### FirewallD 区域
|
||||
|
||||
FirewallD uses services and zones instead of iptables rules and chains. By default the following zones are available:
|
||||
FirewallD 使用服务和区域代替 iptables 的规则和链。默认下面的区域都是可用的:
|
||||
|
||||
* drop – Drop all incoming network packets with no reply, only outgoing network connections are available.
|
||||
* block – Reject all incoming network packets with an icmp-host-prohibited message, only outgoing network connections are available.
|
||||
* public – Only selected incoming connections are accepted, for use in public areas
|
||||
* external For external networks with masquerading enabled, only selected incoming connections are accepted.
|
||||
* dmz – DMZ demilitarized zone, publicly-accessible with limited access to the internal network, only selected incoming connections are accepted.
|
||||
* work – For computers in your home area, only selected incoming connections are accepted.
|
||||
* home – For computers in your home area, only selected incoming connections are accepted.
|
||||
* internal -For computers in your internal network, only selected incoming connections are accepted.
|
||||
* trusted – All network connections are accepted.
|
||||
* drop——任何流入网络的包都被丢弃,不作出任何响应,只允许流出的网络连接。
|
||||
|
||||
To list all available zones run:
|
||||
* block——任何进入的网络连接都被拒绝,并返回 IPv4 的 icmp-host-prohibited 报文。只允许流出的网络连接。
|
||||
|
||||
* public——只接受选中的传入网络连接,例如在公共场合。
|
||||
|
||||
* public——用于启用伪装的外部网络,只接受被选中的传入网络连接。
|
||||
|
||||
* dmz——隔离区域(demilitarized zone),有限制地公开访问内部网络,只接受被选中的传入网络连接。
|
||||
|
||||
* work——用于工作区域中的计算机,只接受选中的流入网络连接。
|
||||
|
||||
* home——用于家庭区域中的计算机,只接受选中的流入网络连接。
|
||||
|
||||
* internal——用于内部网络中的计算机,只接受选中的流入网络连接。
|
||||
|
||||
* trusted——所有的网络连接都可以接受。
|
||||
|
||||
要显示所有可用的区域可以运行:
|
||||
|
||||
```
|
||||
# firewall-cmd --get-zones
|
||||
work drop internal external trusted home dmz public block
|
||||
```
|
||||
|
||||
To list the default zone:
|
||||
要显示默认的区域:
|
||||
|
||||
```
|
||||
# firewall-cmd --get-default-zone
|
||||
public
|
||||
```
|
||||
|
||||
To change the default zone:
|
||||
改变默认的区域:
|
||||
|
||||
```
|
||||
# firewall-cmd --set-default-zone=dmz
|
||||
@ -42,44 +48,41 @@ To change the default zone:
|
||||
dmz
|
||||
```
|
||||
|
||||
### FirewallD services
|
||||
### FirewallD 服务
|
||||
|
||||
FirewallD services are xml configuration files, with information of a service entry for firewalld. TO list all available services run:
|
||||
FirewallD服务是 xml 配置文件,每个文件里面记录有防火墙针对某项服务的配置信息。要列出所有可用的服务,运行命令:
|
||||
|
||||
```
|
||||
# firewall-cmd --get-services
|
||||
amanda-client amanda-k5-client bacula bacula-client ceph ceph-mon dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync freeipa-ldap freeipa-ldaps freeipa-replication ftp high-availability http https imap imaps ipp ipp-client ipsec iscsi-target kadmin kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mosh mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster radius rpc-bind rsyncd samba samba-client sane smtp smtps snmp snmptrap squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server
|
||||
```
|
||||
|
||||
xml configuration files are stored in the `/usr/lib/firewalld/services/` and `/etc/firewalld/services/`directories.
|
||||
xml 配置文件存放在 `/usr/lib/firewalld/services/` 和 `/etc/firewalld/services/` 目录内。
|
||||
|
||||
### Configuring your firewall with FirewallD
|
||||
### 使用 FirewallD 配置你的防火墙
|
||||
|
||||
As an example, here is how you can configure your [RoseHosting VPS][6] firewall with FirewallD if you were running a web server, SSH on port 7022 and mail server.
|
||||
作为一个例子,如果你正在运行一个 web 服务器、7022端口上的 SSH 和 mail 服务器,这里会告诉你如何用 FirewallD 配置你的 [RoseHosting VPS](6) 防火墙。
|
||||
|
||||
First we will set the default zone to dmz.
|
||||
我们首先设置默认区域为 dmz:
|
||||
|
||||
```
|
||||
# firewall-cmd --set-default-zone=dmz
|
||||
# firewall-cmd --get-default-zone
|
||||
dmz
|
||||
```
|
||||
|
||||
To add permanent service rules for HTTP and HTTPS to the dmz zone, run:
|
||||
为了将 HTTP 和 HTTPS 的服务规则永久加入 dmz 区域,运行命令:
|
||||
|
||||
```
|
||||
# firewall-cmd --zone=dmz --add-service=http --permanent
|
||||
# firewall-cmd --zone=dmz --add-service=https --permanent
|
||||
```
|
||||
|
||||
Open port 25 (SMTP) and port 465 (SMTPS) :
|
||||
打开 25 端口SMTP)和 465 端口(SMTPS):
|
||||
|
||||
```
|
||||
firewall-cmd --zone=dmz --add-service=smtp --permanent
|
||||
firewall-cmd --zone=dmz --add-service=smtps --permanent
|
||||
```
|
||||
|
||||
Open, IMAP, IMAPS, POP3 and POP3S ports:
|
||||
打开 IMAP、IMAPS、POP3 和 POP3S端口:
|
||||
|
||||
```
|
||||
firewall-cmd --zone=dmz --add-service=imap --permanent
|
||||
@ -88,24 +91,22 @@ firewall-cmd --zone=dmz --add-service=pop3 --permanent
|
||||
firewall-cmd --zone=dmz --add-service=pop3s --permanent
|
||||
```
|
||||
|
||||
Since the SSH port is changed to 7022, we will remove the ssh service (port 22) and open port 7022
|
||||
因为 SSH 端口号已经被改为 7022,所以我们将删除 ssh 服务(端口 22),然后开启端口 7022:
|
||||
|
||||
```
|
||||
firewall-cmd --remove-service=ssh --permanent
|
||||
firewall-cmd --add-port=7022/tcp --permanent
|
||||
```
|
||||
|
||||
To implement the changes we need to reload the firewall with:
|
||||
为了让这些改变生效,我们需要用命令重新加载防火墙:
|
||||
|
||||
```
|
||||
firewall-cmd --reload
|
||||
```
|
||||
最后,你可以使用命令列出规则:
|
||||
|
||||
Finally, you can list the rules with:
|
||||
|
||||
### firewall-cmd –list-all
|
||||
|
||||
```
|
||||
### firewall-cmd –list-all
|
||||
dmz
|
||||
target: default
|
||||
icmp-block-inversion: no
|
||||
@ -119,20 +120,21 @@ forward-ports:
|
||||
sourceports:
|
||||
icmp-blocks:
|
||||
rich rules:
|
||||
|
||||
```
|
||||
|
||||
* * *
|
||||
***
|
||||
|
||||
Of course, you don’t have to do any of this if you use one of our [CentOS VPS hosting][7] services, in which case you can simply ask our expert Linux admins to setup this for you. They are available 24×7 and will take care of your request immediately.
|
||||
当然,如果您使用我们的 [CentOS VPS hosting][7] 服务中任何一种服务,您都不必亲自做上面任何设置,您可以让我们专业的 Linux 管理员来为您设置。他们提供 24x7 的服务,并且会立即处理您的要求。
|
||||
|
||||
PS. If you liked this post please share it with your friends on the social networks using the sharing buttons or simply leave a reply below. Thanks.
|
||||
PS:如果您喜欢这篇文章,请将它分享到社交平台上与您的朋友共享,或者仅仅在下面留言回复。谢谢!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.rosehosting.com/blog/set-up-and-configure-a-firewall-with-firewalld-on-centos-7/
|
||||
|
||||
作者:[rosehosting.com][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
@ -144,4 +146,4 @@ via: https://www.rosehosting.com/blog/set-up-and-configure-a-firewall-with-firew
|
||||
[4]:https://plus.google.com/share?url=https://www.rosehosting.com/blog/set-up-and-configure-a-firewall-with-firewalld-on-centos-7/
|
||||
[5]:http://www.linkedin.com/shareArticle?mini=true&url=https://www.rosehosting.com/blog/set-up-and-configure-a-firewall-with-firewalld-on-centos-7/&title=Set%20Up%20and%20Configure%20a%20Firewall%20with%20FirewallD%20on%20CentOS%207&summary=FirewallD%20is%20a%20firewall%20management%20tool%20available%20by%20default%20on%20CentOS%207%20servers.%20Basically,%20it%20is%20a%20wrapper%20around%20iptables%20and%20it%20comes%20with%20graphical%20configuration%20tool%20firewall-config%20and%20command%20line%20tool%20firewall-cmd.%20With%20the%20iptables%20service,%20every%20change%20requires%20flushing%20of%20the%20old%20rules%20and%20reading%20the%20new%20rules%20...
|
||||
[6]:https://www.rosehosting.com/linux-vps-hosting.html
|
||||
[7]:https://www.rosehosting.com/centos-vps.html
|
||||
[7]:https://www.rosehosting.com/centos-vps.html
|
@ -1,28 +1,28 @@
|
||||
如何在 CentOS 7 中安装、配置 SFTP - [全面指南]
|
||||
完全指南:如何在 CentOS 7 中安装、配置和安全加固 FTP 服务
|
||||
============================================================
|
||||
|
||||
FTP(文件传输协议)是一种用于通过网络[在服务器和客户端之间传输文件][1]的传统并广泛使用的标准工具,特别是在不需要身份验证的情况下(允许匿名用户连接到服务器)。我们必须明白,默认情况下 FTP 是不安全的,因为它不加密传输用户凭据和数据。
|
||||
|
||||
在本指南中,我们将介绍在 CentOS/RHEL7 和 Fedora 发行版中安装、配置和保护 FTP 服务器( VSFTPD 代表 “Very Secure FTP Daemon”)的步骤。
|
||||
|
||||
请注意,本指南中的所有命令将以 root 身份运行,以防你不使用 root 帐户操作服务器,请使用 [sudo命令][2] 获取 root 权限。
|
||||
请注意,本指南中的所有命令将以 root 身份运行,如果你不使用 root 帐户操作服务器,请使用 [sudo命令][2] 获取 root 权限。
|
||||
|
||||
### 步骤 1:安装 FTP 服务器
|
||||
|
||||
1. 安装 vsftpd 服务器很直接,只要在终端运行下面的命令。
|
||||
1、 安装 vsftpd 服务器很直接,只要在终端运行下面的命令。
|
||||
|
||||
```
|
||||
# yum install vsftpd
|
||||
```
|
||||
|
||||
2. 安装完成后,服务会先被禁用,因此我们需要手动启动,并设置在下次启动时自动启用:
|
||||
2、 安装完成后,服务先是被禁用的,因此我们需要手动启动,并设置在下次启动时自动启用:
|
||||
|
||||
```
|
||||
# systemctl start vsftpd
|
||||
# systemctl enable vsftpd
|
||||
```
|
||||
|
||||
3. 接下来,为了允许从外部系统访问 FTP 服务,我们需要打开 FTP 守护进程监听 21 端口:
|
||||
3、 接下来,为了允许从外部系统访问 FTP 服务,我们需要打开 FTP 守护进程监听的 21 端口:
|
||||
|
||||
```
|
||||
# firewall-cmd --zone=public --permanent --add-port=21/tcp
|
||||
@ -32,7 +32,7 @@ FTP(文件传输协议)是一种用于通过网络[在服务器和客户端
|
||||
|
||||
### 步骤 2: 配置 FTP 服务器
|
||||
|
||||
4. 现在,我们会进行一些配置来设置并加密我们的 FTP 服务器,让我们先备份一下原始配置文件 /etc/vsftpd/vsftpd.conf:
|
||||
4、 现在,我们会进行一些配置来设置并加密我们的 FTP 服务器,让我们先备份一下原始配置文件 `/etc/vsftpd/vsftpd.conf`:
|
||||
|
||||
```
|
||||
# cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.orig
|
||||
@ -41,30 +41,30 @@ FTP(文件传输协议)是一种用于通过网络[在服务器和客户端
|
||||
接下来,打开上面的文件,并将下面的选项设置相关的值:
|
||||
|
||||
```
|
||||
anonymous_enable=NO # disable anonymous login
|
||||
local_enable=YES # permit local logins
|
||||
write_enable=YES # enable FTP commands which change the filesystem
|
||||
local_umask=022 # value of umask for file creation for local users
|
||||
dirmessage_enable=YES # enable showing of messages when users first enter a new directory
|
||||
xferlog_enable=YES # a log file will be maintained detailing uploads and downloads
|
||||
connect_from_port_20=YES # use port 20 (ftp-data) on the server machine for PORT style connections
|
||||
xferlog_std_format=YES # keep standard log file format
|
||||
listen=NO # prevent vsftpd from running in standalone mode
|
||||
listen_ipv6=YES # vsftpd will listen on an IPv6 socket instead of an IPv4 one
|
||||
pam_service_name=vsftpd # name of the PAM service vsftpd will use
|
||||
userlist_enable=YES # enable vsftpd to load a list of usernames
|
||||
tcp_wrappers=YES # turn on tcp wrappers
|
||||
anonymous_enable=NO ### 禁用匿名登录
|
||||
local_enable=YES ### 允许本地用户登录
|
||||
write_enable=YES ### 允许对文件系统做改动的 FTP 命令
|
||||
local_umask=022 ### 本地用户创建文件所用的 umask 值
|
||||
dirmessage_enable=YES ### 当用户首次进入一个新目录时显示一个消息
|
||||
xferlog_enable=YES ### 用于记录上传、下载细节的日志文件
|
||||
connect_from_port_20=YES ### 使用端口 20 (ftp-data)用于 PORT 风格的连接
|
||||
xferlog_std_format=YES ### 使用标准的日志格式
|
||||
listen=NO ### 不要让 vsftpd 运行在独立模式
|
||||
listen_ipv6=YES ### vsftpd 将监听 IPv6 而不是 IPv4
|
||||
pam_service_name=vsftpd ### vsftpd 使用的 PAM 服务名
|
||||
userlist_enable=YES ### vsftpd 支持载入用户列表
|
||||
tcp_wrappers=YES ### 使用 tcp wrappers
|
||||
```
|
||||
|
||||
5. 现在基于用户列表文件 `/etc/vsftpd.userlist` 来配置 FTP 允许/拒绝用户访问。
|
||||
5、 现在基于用户列表文件 `/etc/vsftpd.userlist` 来配置 FTP 来允许/拒绝用户的访问。
|
||||
|
||||
默认情况下,如果设置了 userlist_enable=YES,当 userlist_deny 选项设置为 YES 的时候,`userlist_file=/etc/vsftpd.userlist` 中的用户列表被拒绝登录。
|
||||
默认情况下,如果设置了 `userlist_enable=YES`,当 `userlist_deny` 选项设置为 `YES` 的时候,`userlist_file=/etc/vsftpd.userlist` 中列出的用户被拒绝登录。
|
||||
|
||||
然而, userlist_deny=NO 更改了设置,意味着只有在 userlist_file=/etc/vsftpd.userlist 显式指定的用户才允许登录。
|
||||
然而, 更改配置为 `userlist_deny=NO`,意味着只有在 `userlist_file=/etc/vsftpd.userlist` 显式指定的用户才允许登录。
|
||||
|
||||
```
|
||||
userlist_enable=YES # vsftpd will load a list of usernames, from the filename given by userlist_file
|
||||
userlist_file=/etc/vsftpd.userlist # stores usernames.
|
||||
userlist_enable=YES ### vsftpd 将从 userlist_file 给出的文件中载入用户名列表
|
||||
userlist_file=/etc/vsftpd.userlist ### 存储用户名的文件
|
||||
userlist_deny=NO
|
||||
```
|
||||
|
||||
@ -72,30 +72,30 @@ userlist_deny=NO
|
||||
|
||||
接下来,我们将介绍如何将 FTP 用户 chroot 到 FTP 用户的家目录(本地 root)中的两种可能情况,如下所述。
|
||||
|
||||
6. 接下来添加下面的选项来限制 FTP 用户到它们自己的家目录。
|
||||
6、 接下来添加下面的选项来限制 FTP 用户到它们自己的家目录。
|
||||
|
||||
```
|
||||
chroot_local_user=YES
|
||||
allow_writeable_chroot=YES
|
||||
```
|
||||
|
||||
chroot_local_user=YES 意味着用户可以设置 chroot jail,默认是登录后的家目录。
|
||||
`chroot_local_user=YES` 意味着用户可以设置 chroot jail,默认是登录后的家目录。
|
||||
|
||||
同样默认的是,出于安全原因,vsftpd 不会允许 chroot jail 目录可写,然而,我们可以添加 allow_writeable_chroot=YES 来覆盖这个设置。
|
||||
同样默认的是,出于安全原因,vsftpd 不会允许 chroot jail 目录可写,然而,我们可以添加 `allow_writeable_chroot=YES` 来覆盖这个设置。
|
||||
|
||||
保存并关闭文件。
|
||||
|
||||
### 用 SELinux 加密 FTP 服务器
|
||||
### 步骤 3: 用 SELinux 加密 FTP 服务器
|
||||
|
||||
7. 现在,让我们设置下面的 SELinux 布尔值来允许 FTP 能读取用户家目录下的文件。请注意,这最初是使用以下命令完成的:
|
||||
7、现在,让我们设置下面的 SELinux 布尔值来允许 FTP 能读取用户家目录下的文件。请注意,这原本是使用以下命令完成的:
|
||||
|
||||
```
|
||||
# setsebool -P ftp_home_dir on
|
||||
```
|
||||
|
||||
然而,`ftp_home_dir` 指令由于这个 bug 报告:[https://bugzilla.redhat.com/show_bug.cgi?id=1097775][3] 默认是禁用的。
|
||||
然而,由于这个 bug 报告:[https://bugzilla.redhat.com/show_bug.cgi?id=1097775][3],`ftp_home_dir` 指令默认是禁用的。
|
||||
|
||||
现在,我们会使用 semanage 命令来设置 SELinux 规则来允许 FTP 读取/写入用户的家目录。
|
||||
现在,我们会使用 `semanage` 命令来设置 SELinux 规则来允许 FTP 读取/写入用户的家目录。
|
||||
|
||||
```
|
||||
# semanage boolean -m ftpd_full_access --on
|
||||
@ -109,21 +109,21 @@ chroot_local_user=YES 意味着用户可以设置 chroot jail,默认是登录
|
||||
|
||||
### 步骤 4: 测试 FTP 服务器
|
||||
|
||||
8. 现在我们会用[ useradd 命令][4]创建一个 FTP 用户来测试 FTP 服务器。
|
||||
8、 现在我们会用 [useradd 命令][4]创建一个 FTP 用户来测试 FTP 服务器。
|
||||
|
||||
```
|
||||
# useradd -m -c “Ravi Saive, CEO” -s /bin/bash ravi
|
||||
# passwd ravi
|
||||
```
|
||||
|
||||
之后,我们如下使用[ echo 命令][5]添加用户 ravi 到文件 /etc/vsftpd.userlist 中:
|
||||
之后,我们如下使用 [echo 命令][5]添加用户 ravi 到文件 `/etc/vsftpd.userlist` 中:
|
||||
|
||||
```
|
||||
# echo "ravi" | tee -a /etc/vsftpd.userlist
|
||||
# cat /etc/vsftpd.userlist
|
||||
```
|
||||
|
||||
9. 现在是时候测试我们上面的设置是否可以工作了。让我们使用匿名登录测试,我们可以从下面的截图看到匿名登录不被允许。
|
||||
9、 现在是时候测试我们上面的设置是否可以工作了。让我们使用匿名登录测试,我们可以从下面的截图看到匿名登录没有被允许。
|
||||
|
||||
```
|
||||
# ftp 192.168.56.10
|
||||
@ -134,13 +134,14 @@ Name (192.168.56.10:root) : anonymous
|
||||
Login failed.
|
||||
ftp>
|
||||
```
|
||||
|
||||
[
|
||||
![Test Anonymous FTP Login](http://www.tecmint.com/wp-content/uploads/2017/02/Test-Anonymous-FTP-Login.png)
|
||||
][6]
|
||||
|
||||
测试 FTP 匿名登录
|
||||
*测试 FTP 匿名登录*
|
||||
|
||||
10. 让我们也测试一下没有列在 /etc/vsftpd.userlist 中的用户是否有权限登录,这不是下面截图中的例子:
|
||||
10、 让我们也测试一下没有列在 `/etc/vsftpd.userlist` 中的用户是否有权限登录,下面截图是没有列入的情况:
|
||||
|
||||
```
|
||||
# ftp 192.168.56.10
|
||||
@ -155,9 +156,9 @@ ftp>
|
||||
![FTP User Login Failed](http://www.tecmint.com/wp-content/uploads/2017/02/FTP-User-Login-Failed.png)
|
||||
][7]
|
||||
|
||||
FTP 用户登录失败
|
||||
*FTP 用户登录失败*
|
||||
|
||||
11. 现在最后测试一下列在 /etc/vsftpd.userlis 中的用户是否在登录后真的进入了他/她的家目录:
|
||||
11、 现在最后测试一下列在 `/etc/vsftpd.userlist` 中的用户是否在登录后真的进入了他/她的家目录:
|
||||
|
||||
```
|
||||
# ftp 192.168.56.10
|
||||
@ -171,21 +172,22 @@ Remote system type is UNIX.
|
||||
Using binary mode to transfer files.
|
||||
ftp> ls
|
||||
```
|
||||
|
||||
[
|
||||
![FTP User Login Successful[](http://www.tecmint.com/wp-content/uploads/2017/02/FTP-User-Login.png)
|
||||
![FTP User Login Successful](http://www.tecmint.com/wp-content/uploads/2017/02/FTP-User-Login.png)
|
||||
][8]
|
||||
|
||||
用户成功登录
|
||||
*用户成功登录*
|
||||
|
||||
警告:使用 `allow_writeable_chroot=YES' 有一定的安全隐患,特别是用户具有上传权限或 shell 访问权限时。
|
||||
警告:使用 `allow_writeable_chroot=YES` 有一定的安全隐患,特别是用户具有上传权限或 shell 访问权限时。
|
||||
|
||||
只有当你完全知道你正做什么时才激活此选项。重要的是要注意,这些安全性影响并不是 vsftpd 特定的,它们适用于所有 FTP 守护进程,它们也提供将本地用户置于 chroot jail中。
|
||||
只有当你完全知道你正做什么时才激活此选项。重要的是要注意,这些安全性影响并不是 vsftpd 特定的,它们适用于所有提供了将本地用户置于 chroot jail 中的 FTP 守护进程。
|
||||
|
||||
因此,我们将在下一节中看到一种更安全的方法来设置不同的不可写本地根目录。
|
||||
|
||||
### 步骤 5: 配置不同的 FTP 家目录
|
||||
|
||||
12. 再次打开 vsftpd 配置文件,并将下面不安全的选项注释掉:
|
||||
12、 再次打开 vsftpd 配置文件,并将下面不安全的选项注释掉:
|
||||
|
||||
```
|
||||
#allow_writeable_chroot=YES
|
||||
@ -199,7 +201,7 @@ ftp> ls
|
||||
# chmod a-w /home/ravi/ftp
|
||||
```
|
||||
|
||||
13. 接下来,在用户存储他/她的文件的本地根目录下创建一个文件夹:
|
||||
13、 接下来,在用户存储他/她的文件的本地根目录下创建一个文件夹:
|
||||
|
||||
```
|
||||
# mkdir /home/ravi/ftp/files
|
||||
@ -207,11 +209,11 @@ ftp> ls
|
||||
# chmod 0700 /home/ravi/ftp/files/
|
||||
```
|
||||
|
||||
、接着在 vsftpd 配置文件中添加/修改这些选项:
|
||||
接着在 vsftpd 配置文件中添加/修改这些选项:
|
||||
|
||||
```
|
||||
user_sub_token=$USER # 在本地根目录下插入用户名
|
||||
local_root=/home/$USER/ftp # 定义任何用户的本地根目录
|
||||
user_sub_token=$USER ### 在本地根目录下插入用户名
|
||||
local_root=/home/$USER/ftp ### 定义任何用户的本地根目录
|
||||
```
|
||||
|
||||
保存并关闭文件。再说一次,有新的设置后,让我们重启服务:
|
||||
@ -220,7 +222,7 @@ local_root=/home/$USER/ftp # 定义任何用户的本地根目录
|
||||
# systemctl restart vsftpd
|
||||
```
|
||||
|
||||
14. 现在最后在测试一次查看用户本地根目录就是我们在他的家目录创建的 FTP 目录。
|
||||
14、 现在最后在测试一次查看用户本地根目录就是我们在他的家目录创建的 FTP 目录。
|
||||
|
||||
```
|
||||
# ftp 192.168.56.10
|
||||
@ -238,7 +240,7 @@ ftp> ls
|
||||
![FTP User Home Directory Login Successful](http://www.tecmint.com/wp-content/uploads/2017/02/FTP-User-Home-Directory-Login-Successful.png)
|
||||
][9]
|
||||
|
||||
FTP 用户家目录登录成功
|
||||
*FTP 用户家目录登录成功*
|
||||
|
||||
就是这样了!在本文中,我们介绍了如何在 CentOS 7 中安装、配置以及加密的 FTP 服务器,使用下面的评论栏给我们回复,或者分享关于这个主题的任何有用信息。
|
||||
|
||||
@ -258,7 +260,7 @@ via: http://www.tecmint.com/install-ftp-server-in-centos-7/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[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/) 荣誉推出
|
||||
|
||||
@ -273,5 +275,5 @@ via: http://www.tecmint.com/install-ftp-server-in-centos-7/
|
||||
[7]:http://www.tecmint.com/wp-content/uploads/2017/02/FTP-User-Login-Failed.png
|
||||
[8]:http://www.tecmint.com/wp-content/uploads/2017/02/FTP-User-Login.png
|
||||
[9]:http://www.tecmint.com/wp-content/uploads/2017/02/FTP-User-Home-Directory-Login-Successful.png
|
||||
[10]:http://www.tecmint.com/install-proftpd-in-centos-7/
|
||||
[10]:https://linux.cn/article-8504-1.html
|
||||
[11]:http://www.tecmint.com/secure-vsftpd-using-ssl-tls-on-centos/
|
@ -1,33 +1,33 @@
|
||||
如何在 CentOS 7 中使用 SSL/TLS 加固 FTP 服务器进行安全文件传输
|
||||
============================================================
|
||||
|
||||
在一开始的设计中,FTP(文件传输协议)是不安全的,意味着它不会加密两台机器之间传输的数据以及用户的凭据。这使得数据和服务器安全面临很大威胁。
|
||||
在一开始的设计中,FTP(文件传输协议)就是不安全的,意味着它不会加密两台机器之间传输的数据以及用户的凭据。这使得数据和服务器安全面临很大威胁。
|
||||
|
||||
在这篇文章中,我们会介绍在 CentOS/RHEL 7 以及 Fedora 中如何在 FTP 服务器中手动启用数据加密服务;我们会介绍使用 SSL/TLS 证书保护 VSFTPD(Very Secure FTP Daemon)服务的各个步骤。
|
||||
|
||||
#### 前提条件:
|
||||
|
||||
1. 你必须已经[在 CentOS 7 中安装和配置 FTP 服务][1]
|
||||
- 你必须已经[在 CentOS 7 中安装和配置 FTP 服务][1] 。
|
||||
|
||||
在我们开始之前,要注意本文中所有命令都以 root 用户运行,否则,如果现在你不是使用 root 用户控制服务器,你可以使用 [sudo 命令][2] 去获取 root 权限。
|
||||
|
||||
### 第一步:生成 SSL/TLS 证书和密钥
|
||||
|
||||
1. 我们首先要在 `/etc/ssl` 目录下创建用于保存 SSL/TLS 证书和密钥文件的子目录:
|
||||
1、 我们首先要在 `/etc/ssl` 目录下创建用于保存 SSL/TLS 证书和密钥文件的子目录:
|
||||
|
||||
```
|
||||
# mkdir /etc/ssl/private
|
||||
```
|
||||
|
||||
2. 然后运行下面的命令为 vsftpd 创建证书和密钥并保存到一个文件中,下面会解析使用的每个标签。
|
||||
2、 然后运行下面的命令为 vsftpd 创建证书和密钥并保存到一个文件中,下面会解析使用的每个选项。
|
||||
|
||||
1. req - 是 X.509 Certificate Signing Request (CSR,证书签名请求)管理的一个命令。
|
||||
2. x509 - X.509 证书数据管理。
|
||||
3. days - 定义证书的有效日期。
|
||||
4. newkey - 指定证书密钥处理器。
|
||||
5. rsa:2048 - RSA 密钥处理器,会生成一个 2048 位的密钥。
|
||||
6. keyout - 设置密钥存储文件。
|
||||
7. out - 设置证书存储文件,注意证书和密钥都保存在一个相同的文件:/etc/ssl/private/vsftpd.pem。
|
||||
1. `req` - 是 X.509 Certificate Signing Request (CSR,证书签名请求)管理的一个命令。
|
||||
2. `x509` - X.509 证书数据管理。
|
||||
3. `days` - 定义证书的有效日期。
|
||||
4. `newkey` - 指定证书密钥处理器。
|
||||
5. `rsa:2048` - RSA 密钥处理器,会生成一个 2048 位的密钥。
|
||||
6. `keyout` - 设置密钥存储文件。
|
||||
7. `out` - 设置证书存储文件,注意证书和密钥都保存在一个相同的文件:/etc/ssl/private/vsftpd.pem。
|
||||
|
||||
```
|
||||
# openssl req -x509 -nodes -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem -days 365 -newkey rsa:2048
|
||||
@ -47,7 +47,7 @@ Email Address []:admin@tecmint.com
|
||||
|
||||
### 第二步:配置 VSFTPD 使用 SSL/TLS
|
||||
|
||||
3. 在我们进行任何 VSFTPD 配置之前,首先开放 990 和 40000-50000 端口,以便在 VSFTPD 配置文件中分别定义 TLS 连接的端口和被动端口的端口范围:
|
||||
3、 在我们进行任何 VSFTPD 配置之前,首先开放 990 和 40000-50000 端口,以便在 VSFTPD 配置文件中分别定义 TLS 连接的端口和被动端口的端口范围:
|
||||
|
||||
```
|
||||
# firewall-cmd --zone=public --permanent --add-port=990/tcp
|
||||
@ -55,7 +55,7 @@ Email Address []:admin@tecmint.com
|
||||
# firewall-cmd --reload
|
||||
```
|
||||
|
||||
4. 现在,打开 VSFTPD 配置文件并在文件中指定 SSL 的详细信息:
|
||||
4、 现在,打开 VSFTPD 配置文件并在文件中指定 SSL 的详细信息:
|
||||
|
||||
```
|
||||
# vi /etc/vsftpd/vsftpd.conf
|
||||
@ -70,14 +70,14 @@ ssl_sslv2=NO
|
||||
ssl_sslv3=NO
|
||||
```
|
||||
|
||||
5. 然后,添加下面的行定义 SSL 证书和密钥文件的位置:
|
||||
5、 然后,添加下面的行来定义 SSL 证书和密钥文件的位置:
|
||||
|
||||
```
|
||||
rsa_cert_file=/etc/ssl/private/vsftpd.pem
|
||||
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
|
||||
```
|
||||
|
||||
6. 下面,我们要阻止匿名用户使用 SSL,然后强制所有非匿名用户登录使用安全的 SSL 连接进行数据传输和登录过程中的密码发送:
|
||||
6、 下面,我们要阻止匿名用户使用 SSL,然后强制所有非匿名用户登录使用安全的 SSL 连接进行数据传输和登录过程中的密码发送:
|
||||
|
||||
```
|
||||
allow_anon_ssl=NO
|
||||
@ -85,7 +85,7 @@ force_local_data_ssl=YES
|
||||
force_local_logins_ssl=YES
|
||||
```
|
||||
|
||||
7. 另外,我们还可以添加下面的选项增强 FTP 服务器的安全性。当选项 `require_ssl_reuse` 被设置为 `YES` 时,要求所有 SSL 数据连接都显示 SSL 会话重用;表明它们知道与控制频道相同的主机密码。
|
||||
7、 另外,我们还可以添加下面的选项增强 FTP 服务器的安全性。当选项 `require_ssl_reuse` 被设置为 `YES` 时,要求所有 SSL 数据连接都会重用 SSL 会话;这样它们会知道控制通道的主密码。
|
||||
|
||||
因此,我们需要把它关闭。
|
||||
|
||||
@ -93,19 +93,19 @@ force_local_logins_ssl=YES
|
||||
require_ssl_reuse=NO
|
||||
```
|
||||
|
||||
另外,我们还要用 `ssl_ciphers` 选项选择 VSFTPD 允许用于加密 SSL 连接的 SSL 密码。这可以大大限制尝试使用在漏洞中发现的特定密码的攻击者:
|
||||
另外,我们还要用 `ssl_ciphers` 选项选择 VSFTPD 允许用于加密 SSL 连接的 SSL 算法。这可以极大地限制那些尝试发现使用存在缺陷的特定算法的攻击者:
|
||||
|
||||
```
|
||||
ssl_ciphers=HIGH
|
||||
```
|
||||
|
||||
8. 现在,设置被动端口的端口范围(最小和最大端口)。
|
||||
8、 现在,设置被动端口的端口范围(最小和最大端口)。
|
||||
```
|
||||
pasv_min_port=40000
|
||||
pasv_max_port=50000
|
||||
```
|
||||
|
||||
9. 选择性启用 `debug_ssl` 选项以允许 SSL 调试,意味着 OpenSSL 连接诊断会被记录到 VSFTPD 日志文件:
|
||||
9、 选择性启用 `debug_ssl` 选项以允许 SSL 调试,这意味着 OpenSSL 连接诊断会被记录到 VSFTPD 日志文件:
|
||||
|
||||
```
|
||||
debug_ssl=YES
|
||||
@ -119,7 +119,7 @@ debug_ssl=YES
|
||||
|
||||
### 第三步:用 SSL/TLS 连接测试 FTP 服务器
|
||||
|
||||
10. 完成上面的所有配置之后,像下面这样通过在命令行中尝试使用 FTP 测试 VSFTPD 是否使用 SSL/TLS 连接:
|
||||
10、 完成上面的所有配置之后,像下面这样通过在命令行中尝试使用 FTP 测试 VSFTPD 是否使用 SSL/TLS 连接:
|
||||
|
||||
```
|
||||
# ftp 192.168.56.10
|
||||
@ -131,11 +131,12 @@ Login failed.
|
||||
421 Service not available, remote server has closed connection
|
||||
ftp>
|
||||
```
|
||||
|
||||
[
|
||||
![验证 FTP SSL 安全连接](http://www.tecmint.com/wp-content/uploads/2017/02/Verify-FTP-Secure-Connection.png)
|
||||
][3]
|
||||
|
||||
验证 FTP SSL 安全连接
|
||||
*验证 FTP SSL 安全连接*
|
||||
|
||||
从上面的截图中,我们可以看到这里有个错误提示我们 VSFTPD 只允许用户从支持加密服务的客户端登录。
|
||||
|
||||
@ -143,7 +144,7 @@ ftp>
|
||||
|
||||
### 第四步:安装 FileZilla 以便安全地连接到 FTP 服务器
|
||||
|
||||
11. FileZilla 是一个时尚、流行且重要的交叉平台 FTP 客户端,它默认支持 SSL/TLS 连接。
|
||||
11、 FileZilla 是一个现代化、流行且重要的跨平台的 FTP 客户端,它默认支持 SSL/TLS 连接。
|
||||
|
||||
要在 Linux 上安装 FileZilla,可以运行下面的命令:
|
||||
|
||||
@ -154,7 +155,7 @@ ftp>
|
||||
$ sudo apt-get install filezilla
|
||||
```
|
||||
|
||||
12. 当安装完成后(或者你已经安装了该软件),打开它,选择 File=>Sites Manager 或者按 `Ctrl + S` 打开 Site Manager 界面。
|
||||
12、 当安装完成后(或者你已经安装了该软件),打开它,选择 File => Sites Manager 或者按 `Ctrl + S` 打开 Site Manager 界面。
|
||||
|
||||
点击 New Site 按钮添加一个新的站点/主机连接详细信息。
|
||||
|
||||
@ -162,7 +163,7 @@ $ sudo apt-get install filezilla
|
||||
![在 FileZilla 中添加新 FTP 站点](http://www.tecmint.com/wp-content/uploads/2017/02/Add-New-FTP-Site-in-Filezilla.png)
|
||||
][4]
|
||||
|
||||
在 FileZilla 中添加新 FTP 站点
|
||||
*在 FileZilla 中添加新 FTP 站点*
|
||||
|
||||
13. 下一步,像下面这样设置主机/站点名称、添加 IP 地址、定义使用的协议、加密和登录类型(使用你自己情况的值):
|
||||
|
||||
@ -177,15 +178,15 @@ User: username
|
||||
![在 Filezilla 中添加 FTP 服务器详细信息](http://www.tecmint.com/wp-content/uploads/2017/02/Add-FTP-Server-Details-in-Filezilla.png)
|
||||
][5]
|
||||
|
||||
在 Filezilla 中添加 FTP 服务器详细信息
|
||||
*在 Filezilla 中添加 FTP 服务器详细信息*
|
||||
|
||||
14. 然后点击 Connect,再次输入密码,然后验证用于 SSL/TLS 连接的证书,再一次点击 `OK` 连接到 FTP 服务器:
|
||||
14、 然后点击 Connect,再次输入密码,然后验证用于 SSL/TLS 连接的证书,再一次点击 `OK` 连接到 FTP 服务器:
|
||||
|
||||
[
|
||||
![验证 FTP SSL 证书](http://www.tecmint.com/wp-content/uploads/2017/02/Verify-FTP-SSL-Certificate.png)
|
||||
][6]
|
||||
|
||||
验证 FTP SSL 证书
|
||||
*验证 FTP SSL 证书*
|
||||
|
||||
到了这里,我们应该使用 TLS 连接成功地登录到了 FTP 服务器,在下面的界面中检查连接状态部分获取更多信息。
|
||||
|
||||
@ -193,15 +194,15 @@ User: username
|
||||
![通过 TLS/SSL 连接到 FTP 服务器](http://www.tecmint.com/wp-content/uploads/2017/02/connected-to-ftp-server-with-tls.png)
|
||||
][7]
|
||||
|
||||
通过 TLS/SSL 连接到 FTP 服务器
|
||||
*通过 TLS/SSL 连接到 FTP 服务器*
|
||||
|
||||
15. 最后,在文件目录尝试 [从本地传输文件到 FTP 服务器][8],看 FileZilla 界面后面的部分查看文件传输相关的报告。
|
||||
15、 最后,在文件目录尝试 [从本地传输文件到 FTP 服务器][8],看 FileZilla 界面后面的部分查看文件传输相关的报告。
|
||||
|
||||
[
|
||||
![使用 FTP 安全地传输文件](http://www.tecmint.com/wp-content/uploads/2017/02/Transfer-Files-Securely-Using-FTP.png)
|
||||
][9]
|
||||
|
||||
使用 FTP 安全地传输文件
|
||||
*使用 FTP 安全地传输文件*
|
||||
|
||||
就是这些。记住 FTP 默认是不安全的,除非我们像上面介绍的那样配置它使用 SSL/TLS 连接。在下面的评论框中和我们分享你关于这篇文章/主题的想法吧。
|
||||
|
||||
@ -217,7 +218,7 @@ via: http://www.tecmint.com/secure-vsftpd-using-ssl-tls-on-centos/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,195 +1,175 @@
|
||||
如何安装 pandom : 一个针对 linux 的真随机数生成器
|
||||
如何安装 pandom : 一个针对 Linux 的真随机数生成器
|
||||
============================================================
|
||||
|
||||
### 在本文中,你将看到
|
||||
|
||||
1. [简介][40]
|
||||
2. [1 pandom 的安装][41]
|
||||
1. [1.1 获取 root 权限][1]
|
||||
2. [1.2 安装编译所需的依赖][2]
|
||||
3. [基于 Arch 的系统][3]
|
||||
4. [基于 Debian 的系统][4]
|
||||
5. [基于 Red Hat 的系统][5]
|
||||
6. [基于 SUSE 的系统][6]
|
||||
7. [1.3 下载并析出源码][7]
|
||||
8. [1.4 在安装前进行测试 (推荐)][8]
|
||||
9. [1.5 确定初始化系统][9]
|
||||
10. [1.6 安装 pandom][10]
|
||||
11. [基于 init.d 的初始化系统 (例如 upstart、sysvinit)][11]
|
||||
12. [以 systemd 作为初始化程序的系统][12]
|
||||
3. [2 checkme 文件的分析][42]
|
||||
1. [2.1 获取 root 权限][13]
|
||||
2. [2.2 安装编译所需的依赖][14]
|
||||
3. [基于 Arch 的系统][15]
|
||||
4. [基于 Debian 的系统][16]
|
||||
5. [基于 Red Hat 的系统][17]
|
||||
6. [基于 SUSE 的系统][18]
|
||||
7. [2.3 下载并析出源码][19]
|
||||
8. [2.4 安装 entropyarray][20]
|
||||
9. [2.5 分析 checkme 文件][21]
|
||||
10. [2.6 卸载 entropyarray (可选)][22]
|
||||
4. [3 使用 debian 软件仓库安装 pandom][43]
|
||||
1. [3.1 获取 root 权限][23]
|
||||
2. [3.2 安装密钥][24]
|
||||
3. [3.3 安装软件源列表][25]
|
||||
4. [Wheezy][26]
|
||||
5. [Jessie][27]
|
||||
6. [Stretch][28]
|
||||
7. [3.4 更新软件源列表][29]
|
||||
8. [3.5 测试 pandom][30]
|
||||
9. [3.6 安装 pandom][31]
|
||||
5. [4 管理 pandom][44]
|
||||
1. [4.1 性能测试][32]
|
||||
2. [4.2 熵及序列相关性测试][33]
|
||||
3. [4.3 系统服务][34]
|
||||
4. [基于 init.d 的初始化系统 (例如 upstart、sysvinit)][35]
|
||||
5. [以 systemd 作为初始化程序的系统][36]
|
||||
6. [5 增强不可预测性或者性能][45]
|
||||
1. [5.1 编辑源文件][37]
|
||||
2. [5.2 测试不可预测性][38]
|
||||
3. [5.3 安装个人定制的 pandom][39]
|
||||
|
||||
本教程只针对 amd64/x86_64 架构 linux 内核版本大于等于 2.6.9 的系统。本文将解释如何安装 [pandom][46],一个由 ncomputers.org 维护的定时颤动真随机数生成器。
|
||||
本教程只针对 amd64/x86_64 架构 Linux 内核版本大于等于 2.6.9 的系统。本文将解释如何安装 [pandom][46],这是一个由 ncomputers.org 维护的定时抖动真随机数生成器。
|
||||
|
||||
### 简介
|
||||
|
||||
以现代的眼光来看,Linux 内核内置的真随机数发生器提供了一个很低的吞吐量,例如在配置固态硬盘 (SSD) 的个人电脑和虚拟专用服务器 (VPS)的环境中。
|
||||
在现在的计算机状况下,比如说配置了固态硬盘(SSD)的个人电脑和虚拟专用服务器(VPS)的环境中,Linux 内核内置的真随机数发生器提供的吞吐量很低。
|
||||
|
||||
各种不同的加密目的使得对真随机数的需求持续增长,从而使得这个低吞吐量问题在各种 linux 实现中变得越来越普遍。
|
||||
而出于各种不同的加密目的使得对真随机数的需求持续增长,从而使得这个低吞吐量问题在 Linux 实现中变得越来越严重。
|
||||
|
||||
在相同的物理或者虚拟环境下,并假设没有其他进程以 root 身份向 /dev/random 进行写操作的话,64 [ubits][47]/64 bits 的 pandom 可以以 8 KiB/s 的速率生成随机数。
|
||||
在与上述相同的物理或者虚拟环境下,并假设没有其它进程以 root 身份向 `/dev/random` 进行写操作的话,64 [ubits][47]/64 bits 的 pandom 可以以 8 KiB/s 的速率生成随机数。
|
||||
|
||||
### 1 pandom 的安装
|
||||
|
||||
### 1.1 获得 root 权限
|
||||
#### 1.1 获得 root 权限
|
||||
|
||||
Pandom 必须以 root 身份来安装,所以在必要的时候请运行如下命令:
|
||||
|
||||
su -
|
||||
```
|
||||
su -
|
||||
```
|
||||
|
||||
### 1.2 安装编译所需的依赖
|
||||
#### 1.2 安装编译所需的依赖
|
||||
|
||||
为了下载并安装 pandom,你需要 GNU **as** 汇编器、GNU **make**、GNU **tar** 和 GNU **wget** (最后两个工具通常已被安装)。随后你可以按照你的意愿卸载它们。
|
||||
为了下载并安装 pandom,你需要 GNU `as` 汇编器、GNU `make`、GNU `tar` 和 GNU `wget` (最后两个工具通常已被安装)。随后你可以按照你的意愿卸载它们。
|
||||
|
||||
### 基于 Arch 的系统
|
||||
|
||||
pacman -S binutils make
|
||||
|
||||
### 基于 Debian 的系统
|
||||
|
||||
apt-get install binutils make
|
||||
|
||||
### 基于 Red Hat 的系统
|
||||
|
||||
dnf install binutils make
|
||||
|
||||
yum install binutils make
|
||||
|
||||
### 基于 SUSE 的系统
|
||||
|
||||
zypper install binutils make
|
||||
|
||||
### 1.3 下载并析出源码
|
||||
|
||||
下面的命令将使用 **wget** 和 **tar** 从 ncomputers.org 下载 pandom 的源代码并将它们解压出来:
|
||||
|
||||
wget [http://ncomputers.org/pandom.tar.gz][48]
|
||||
tar xf pandom.tar.gz
|
||||
cd pandom/amd64-linux
|
||||
|
||||
### 1.4 在安装前进行测试 (推荐)
|
||||
|
||||
这个被推荐的测试将花费大约 8 分钟的时间,它将检查内核支持情况并生成一个名为 **checkme** 的文件 (在下一节中将被分析)。
|
||||
|
||||
make check
|
||||
|
||||
### 1.5 确定系统的初始化程序
|
||||
|
||||
在安装 pandom 之前,你需要知道你的系统使用的是哪个初始化程序。假如下面命令的输出中包含 **running**,则意味着你的系统使用了 **systemd**,否则你的系统则可能使用了一个 **init.d** 的实现 (例如 upstart、sysvinit)。
|
||||
|
||||
systemctl is-system-running
|
||||
**基于 Arch 的系统:**
|
||||
|
||||
```
|
||||
pacman -S binutils make
|
||||
```
|
||||
|
||||
**基于 Debian 的系统:**
|
||||
|
||||
```
|
||||
apt-get install binutils make
|
||||
```
|
||||
|
||||
基于 Red Hat 的系统:
|
||||
|
||||
```
|
||||
dnf install binutils make
|
||||
yum install binutils make
|
||||
```
|
||||
|
||||
**基于 SUSE 的系统:**
|
||||
|
||||
```
|
||||
zypper install binutils make
|
||||
```
|
||||
|
||||
#### 1.3 下载并析出源码
|
||||
|
||||
下面的命令将使用 `wget` 和 `tar` 从 ncomputers.org 下载 pandom 的源代码并将它们解压出来:
|
||||
|
||||
```
|
||||
wget http://ncomputers.org/pandom.tar.gz
|
||||
tar xf pandom.tar.gz
|
||||
cd pandom/amd64-linux
|
||||
```
|
||||
|
||||
#### 1.4 在安装前进行测试 (推荐)
|
||||
|
||||
这个被推荐的测试将花费大约 8 分钟的时间,它将检查内核支持情况并生成一个名为 `checkme` 的文件(在下一节中将被分析)。
|
||||
|
||||
```
|
||||
make check
|
||||
```
|
||||
#### 1.5 确定系统的初始化程序
|
||||
|
||||
在安装 pandom 之前,你需要知道你的系统使用的是哪个初始化程序。假如下面命令的输出中包含 `running`,则意味着你的系统使用了 `systemd`,否则你的系统则可能使用了一个 `init.d` 的实现(例如 upstart、sysvinit)。
|
||||
|
||||
```
|
||||
systemctl is-system-running
|
||||
running
|
||||
```
|
||||
|
||||
### 1.6 安装 pandom
|
||||
#### 1.6 安装 pandom
|
||||
|
||||
一旦你知道了你的系统使用何种 linux 实现,那么你就可以相应地安装 pandom 了。
|
||||
一旦你知道了你的系统使用何种 Linux 实现,那么你就可以相应地安装 pandom 了。
|
||||
|
||||
### 使用基于 init.d 作为初始化程序(如: upstart、sysvinit) 的系统
|
||||
**使用基于 init.d 作为初始化程序(如: upstart、sysvinit)的系统:**
|
||||
|
||||
假如你的系统使用了一个 **init.d** 的实现(如: upstart、sysvinit),请运行下面的命令来安装 pandom:
|
||||
假如你的系统使用了一个 init.d 的实现(如: upstart、sysvinit),请运行下面的命令来安装 pandom:
|
||||
|
||||
make install-init.d
|
||||
```
|
||||
make install-init.d
|
||||
```
|
||||
|
||||
### 以 systemd 作为初始化程序的系统
|
||||
**以 systemd 作为初始化程序的系统:**
|
||||
|
||||
假如你的系统使用 **systemd**,则请运行以下命令来安装 pandom:
|
||||
假如你的系统使用 `systemd`,则请运行以下命令来安装 pandom:
|
||||
|
||||
make install-systemd
|
||||
```
|
||||
make install-systemd
|
||||
```
|
||||
|
||||
### 2 checkme 文件的分析
|
||||
|
||||
在使用 pandom 进行加密之前,强烈建议分析一下先前在安装过程中生成的 **checkme** 文件。通过分析我们便可以知道用 pandom 生成的数是否真的随机。本节将解释如何使用 ncomputers.org 的 shell 脚本 **entropyarray** 来测试由 pandom 产生的输出的熵及序列相关性。
|
||||
在使用 pandom 进行加密之前,强烈建议分析一下先前在安装过程中生成的 `checkme` 文件。通过分析我们便可以知道用 pandom 生成的数是否真的随机。本节将解释如何使用 ncomputers.org 的 shell 脚本 `entropyarray` 来测试由 pandom 产生的输出的熵及序列相关性。
|
||||
|
||||
**注**:整个分析过程也可以在另一台电脑上完成,例如在一个笔记本电脑或台式机上。举个例子:假如你正在一个资源受到限制的 VPS 上安装 pandom 程序,或许你更倾向于将 **checkme** 复制到自己的个人电脑中,然后再进行分析。
|
||||
**注**:整个分析过程也可以在另一台电脑上完成,例如在一个笔记本电脑或台式机上。举个例子:假如你正在一个资源受到限制的 VPS 上安装 pandom 程序,或许你更倾向于将 `checkme` 复制到自己的个人电脑中,然后再进行分析。
|
||||
|
||||
### 2.1 获取 root 权限
|
||||
#### 2.1 获取 root 权限
|
||||
|
||||
`entropyarray` 程序也必须以 root 身份来安装,所以在必要时请运行如下命令:
|
||||
|
||||
su -
|
||||
```
|
||||
su -
|
||||
```
|
||||
|
||||
### 2.2 安装编译所需的依赖
|
||||
#### 2.2 安装编译所需的依赖
|
||||
|
||||
为了下载并安装 entropyarray, 你需要 GNU **g++** 编译器、GNU **make**、GNU **tar** 和 GNU **wget**。在随后你可以任意卸载这些依赖。
|
||||
为了下载并安装 `entropyarray`, 你需要 GNU g++ 编译器、GNU `make`、GNU `tar` 和 GNU `wget`。在随后你可以任意卸载这些依赖。
|
||||
|
||||
### 基于 Arch 的系统
|
||||
|
||||
pacman -S gcc make
|
||||
|
||||
### 基于 Debian 的系统
|
||||
|
||||
apt-get install g++ make
|
||||
|
||||
### 基于 Red Hat 的系统
|
||||
|
||||
dnf install gcc-c++ make
|
||||
|
||||
yum install gcc-c++ make
|
||||
|
||||
### 基于 SUSE 的系统
|
||||
|
||||
zypper install gcc-c++ make
|
||||
|
||||
### 2.3 下载并析出源码
|
||||
|
||||
以下命令将使用 **wget** 和 **tar** 从 ncomputers.org 下载到 entropyarray 的源码并进行解压:
|
||||
|
||||
wget [http://ncomputers.org/rearray.tar.gz][50]
|
||||
wget [http://ncomputers.org/entropy.tar.gz][51]
|
||||
wget [http://ncomputers.org/entropyarray.tar.gz][52]
|
||||
|
||||
tar xf entropy.tar.gz
|
||||
tar xf rearray.tar.gz
|
||||
tar xf entropyarray.tar.gz
|
||||
|
||||
### 2.4 安装 entropyarray
|
||||
|
||||
**注**:如果在编译过程中报有关 -std=c++11 的错误,则说明当前系统安装的 GNU **g++** 版本不支持 ISO C++ 2011 标准,那么你可能需要在另一个支持该标准的系统中编译 ncomputers.org/**entropy** 和 ncomputers.org/**rearray** (例如在一个你喜爱的较新的 linux 发行版本中来编译)。接着使用 **make install** 来安装编译好的二进制文件,再接着你可能想继续运行 **entropyarray** 程序,或者跳过运行该程序这一步骤,然而我还是建议在使用 pandom 来达到加密目地之前先分析一下 **checkme** 文件。
|
||||
|
||||
cd rearray; make install; cd ..
|
||||
cd entropy; make install; cd ..
|
||||
cd entropyarray; make install; cd ..
|
||||
|
||||
### 2.5 分析 checkme 文件
|
||||
|
||||
**注**:64 [ubits][53] / 64 bits 的 pandom 实现所生成的结果中熵应该高于 **15.977** 且 **max** 字段低于 **70**。假如你的结果与之相差巨大,或许你应该按照下面第 5 节介绍的那样增加你的 pandom 实现的不可预测性。假如你跳过了生成 checkme 文件的那一步,你也可以使用其他的工具来进行测试,例如 [伪随机数序列测试][54]。
|
||||
|
||||
entropyarray checkme
|
||||
**基于 Arch 的系统:**
|
||||
|
||||
```
|
||||
pacman -S gcc make
|
||||
```
|
||||
|
||||
**基于 Debian 的系统:**
|
||||
|
||||
```
|
||||
apt-get install g++ make
|
||||
```
|
||||
|
||||
**基于 Red Hat 的系统:**
|
||||
|
||||
```
|
||||
dnf install gcc-c++ make
|
||||
yum install gcc-c++ make
|
||||
```
|
||||
|
||||
**基于 SUSE 的系统:**
|
||||
|
||||
```
|
||||
zypper install gcc-c++ make
|
||||
```
|
||||
|
||||
#### 2.3 下载并析出源码
|
||||
|
||||
以下命令将使用 `wget` 和 `tar` 从 ncomputers.org 下载到 entropyarray 的源码并进行解压:
|
||||
|
||||
```
|
||||
wget http://ncomputers.org/rearray.tar.gz
|
||||
wget http://ncomputers.org/entropy.tar.gz
|
||||
wget http://ncomputers.org/entropyarray.tar.gz
|
||||
|
||||
tar xf entropy.tar.gz
|
||||
tar xf rearray.tar.gz
|
||||
tar xf entropyarray.tar.gz
|
||||
```
|
||||
|
||||
#### 2.4 安装 entropyarray
|
||||
|
||||
**注**:如果在编译过程中报有关 `-std=c++11` 的错误,则说明当前系统安装的 GNU g++ 版本不支持 ISO C++ 2011 标准,那么你可能需要在另一个支持该标准的系统中编译 ncomputers.org/entropy 和 ncomputers.org/rearray (例如在一个你喜爱的较新的 Linux 发行版本中来编译)。接着使用 `make install` 来安装编译好的二进制文件,再接着你可能想继续运行 `entropyarray` 程序,或者跳过运行该程序这一步骤,然而我还是建议在使用 pandom 来达到加密目地之前先分析一下 `checkme` 文件。
|
||||
|
||||
```
|
||||
cd rearray; make install; cd ..
|
||||
cd entropy; make install; cd ..
|
||||
cd entropyarray; make install; cd ..
|
||||
```
|
||||
|
||||
#### 2.5 分析 checkme 文件
|
||||
|
||||
**注**:64 [ubits][53] / 64 bits 的 pandom 实现所生成的结果中熵应该高于 `15.977` 且 `max` 字段低于 `70`。假如你的结果与之相差巨大,或许你应该按照下面第 5 节介绍的那样增加你的 pandom 实现的不可预测性。假如你跳过了生成 `checkme` 文件的那一步,你也可以使用其他的工具来进行测试,例如 [伪随机数序列测试][54]。
|
||||
|
||||
```
|
||||
entropyarray checkme
|
||||
|
||||
entropyarray in /tmp/tmp.mbCopmzqsg
|
||||
15.977339
|
||||
min:12
|
||||
@ -221,75 +201,90 @@ med:32
|
||||
max:67
|
||||
```
|
||||
|
||||
### 2.6 卸载 entropyarray (可选)
|
||||
#### 2.6 卸载 entropyarray (可选)
|
||||
|
||||
假如你打算不再使用 entropyarray,那么你可以按照你自己的需求卸载它:
|
||||
假如你打算不再使用 `entropyarray`,那么你可以按照你自己的需求卸载它:
|
||||
|
||||
cd entropyarray; make uninstall; cd ..
|
||||
cd entropy; make uninstall; cd ..
|
||||
cd rearray; make uninstall; cd ..
|
||||
|
||||
```
|
||||
cd entropyarray; make uninstall; cd ..
|
||||
cd entropy; make uninstall; cd ..
|
||||
cd rearray; make uninstall; cd ..
|
||||
```
|
||||
|
||||
### 3 使用 debian 的软件仓库来进行安装
|
||||
|
||||
假如你想在你基于 debian 的系统中让 pandom 保持更新,则你可以使用 ncomputers.org 的 debian 软件仓库来安装或者重新安装它。
|
||||
|
||||
### 3.1 获取 root 权限
|
||||
#### 3.1 获取 root 权限
|
||||
|
||||
以下的 debian 软件包必须以 root 身份来安装,所以在必要时请运行下面这个命令:
|
||||
|
||||
su -
|
||||
```
|
||||
su -
|
||||
```
|
||||
|
||||
### 3.2 安装密钥
|
||||
#### 3.2 安装密钥
|
||||
|
||||
下面的 debian 软件包中包含 ncomputers.org debian 软件仓库的公匙密钥:
|
||||
|
||||
wget [http://ncomputers.org/debian/keyring.deb][55]
|
||||
dpkg -i keyring.deb
|
||||
rm keyring.deb
|
||||
```
|
||||
wget http://ncomputers.org/debian/keyring.deb
|
||||
dpkg -i keyring.deb
|
||||
rm keyring.deb
|
||||
```
|
||||
|
||||
### 3.3 安装软件源列表
|
||||
#### 3.3 安装软件源列表
|
||||
|
||||
下面这些 debian 软件包含有 ncomputers.org debian 软件仓库的软件源列表,这些软件源列表对应最新的 debian 发行版本(截至 2017 年)。
|
||||
|
||||
**注**:你也可以将下面的以 `#` 注释的行加入 **/etc/apt/sources.list** 文件中,而不是为你的 debian 发行版本安装对应的 debian 软件包。但假如这些源在将来改变了,你就需要手动更新它们。
|
||||
**注**:你也可以将下面的以 `#` 注释的行加入 `/etc/apt/sources.list` 文件中,而不是为你的 debian 发行版本安装对应的 debian 软件包。但假如这些源在将来改变了,你就需要手动更新它们。
|
||||
|
||||
### Wheezy
|
||||
**Wheezy:**
|
||||
|
||||
#deb [http://ncomputers.org/debian][56] wheezy main
|
||||
wget [http://ncomputers.org/debian/wheezy.deb][57]
|
||||
dpkg -i wheezy.deb
|
||||
rm wheezy.deb
|
||||
```
|
||||
#deb http://ncomputers.org/debian wheezy main
|
||||
wget http://ncomputers.org/debian/wheezy.deb
|
||||
dpkg -i wheezy.deb
|
||||
rm wheezy.deb
|
||||
```
|
||||
|
||||
### Jessie
|
||||
Jessie:
|
||||
|
||||
#deb [http://ncomputers.org/debian][58] jessie main
|
||||
wget [http://ncomputers.org/debian/jessie.deb][59]
|
||||
dpkg -i jessie.deb
|
||||
rm jessie.deb
|
||||
```
|
||||
#deb http://ncomputers.org/debian jessie main
|
||||
wget http://ncomputers.org/debian/jessie.deb
|
||||
dpkg -i jessie.deb
|
||||
rm jessie.deb
|
||||
```
|
||||
|
||||
### Stretch
|
||||
**Stretch:**
|
||||
|
||||
#deb [http://ncomputers.org/debian][60] stretch main
|
||||
wget [http://ncomputers.org/debian/stretch.deb][61]
|
||||
dpkg -i stretch.deb
|
||||
rm stretch.deb
|
||||
```
|
||||
#deb http://ncomputers.org/debian stretch main
|
||||
wget http://ncomputers.org/debian/stretch.deb
|
||||
dpkg -i stretch.deb
|
||||
rm stretch.deb
|
||||
```
|
||||
|
||||
### 3.4 升级软件源列表
|
||||
#### 3.4 升级软件源列表
|
||||
|
||||
一旦密钥和软件源列表安装完成,则可以使用下面的命令来更新:
|
||||
|
||||
apt-get update
|
||||
```
|
||||
apt-get update
|
||||
```
|
||||
|
||||
### 3.5 测试 pandom
|
||||
#### 3.5 测试 pandom
|
||||
|
||||
测试完毕后,你可以随意卸载下面的软件包。
|
||||
|
||||
**注**:假如你已经在你的 linux 中测试了 pandom , 则你可以跳过这一步。
|
||||
|
||||
apt-get install pandom-test
|
||||
pandom-test
|
||||
**注**:假如你已经在你的 Linux 中测试了 pandom , 则你可以跳过这一步。
|
||||
|
||||
```
|
||||
apt-get install pandom-test
|
||||
pandom-test
|
||||
|
||||
generating checkme file, please wait around 8 minutes ...
|
||||
entropyarray in /tmp/tmp.5SkiYsYG3h
|
||||
15.977366
|
||||
@ -322,57 +317,64 @@ med:32
|
||||
max:57
|
||||
```
|
||||
|
||||
### 3.6 安装 pandom
|
||||
#### 3.6 安装 pandom
|
||||
|
||||
apt-get install pandom
|
||||
```
|
||||
apt-get install pandom
|
||||
```
|
||||
|
||||
### 4 管理 pandom
|
||||
|
||||
在 pandom 安装完成后,你可能想对它进行管理。
|
||||
|
||||
### 4.1 性能测试
|
||||
#### 4.1 性能测试
|
||||
|
||||
pandom 提供大约 8 kB/s 的随机数生成速率,但它的性能可能根据环境而有所差异。
|
||||
|
||||
dd if=/dev/random of=/dev/null bs=8 count=512
|
||||
|
||||
```
|
||||
dd if=/dev/random of=/dev/null bs=8 count=512
|
||||
|
||||
512+0 records in
|
||||
512+0 records out
|
||||
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.451253 s, 9.1 kB/s
|
||||
```
|
||||
|
||||
### 4.2 熵和序列相关性检验
|
||||
#### 4.2 熵和序列相关性检验
|
||||
|
||||
除了 ncomputers.org/**entropyarray**,还存在更多的测试,例如 [Ilja Gerhardt 的 NIST 测试套件][62].
|
||||
除了 ncomputers.org/entropyarray,还存在更多的测试,例如 [Ilja Gerhardt 的 NIST 测试套件][62]。
|
||||
|
||||
entropyarray /dev/random 1M
|
||||
```
|
||||
entropyarray /dev/random 1M
|
||||
```
|
||||
|
||||
### 4.3 系统服务
|
||||
#### 4.3 系统服务
|
||||
|
||||
pandom 还可以以系统服务的形式运行。
|
||||
|
||||
### 基于 init.d 的初始化系统(如 upstart、sysvinit)
|
||||
**基于 init.d 的初始化系统(如 upstart、sysvinit):**
|
||||
|
||||
/etc/init.d/random status
|
||||
/etc/init.d/random start
|
||||
/etc/init.d/random stop
|
||||
/etc/init.d/random restart
|
||||
```
|
||||
/etc/init.d/random status
|
||||
/etc/init.d/random start
|
||||
/etc/init.d/random stop
|
||||
/etc/init.d/random restart
|
||||
```
|
||||
**以 systemd 作为初始化程序的系统:**
|
||||
|
||||
### 以 systemd 作为初始化程序的系统
|
||||
|
||||
systemctl status random
|
||||
systemctl start random
|
||||
systemctl stop random
|
||||
systemctl restart random
|
||||
```
|
||||
systemctl status random
|
||||
systemctl start random
|
||||
systemctl stop random
|
||||
systemctl restart random
|
||||
```
|
||||
|
||||
### 5 增强不可预测性或者性能
|
||||
|
||||
假如你想增加你编译的 pandom 程序的不可预测性或者性能,你可以尝试增加或删减 CPU 时间测量选项。
|
||||
|
||||
### 5.1 编辑源文件
|
||||
#### 5.1 编辑源文件
|
||||
|
||||
请按照自己的意愿,在源文件 **test.s** 和 **tRNG.s** 中增加或者移除 measurement blocks 字段。
|
||||
请按照自己的意愿,在源文件 `test.s` 和 `tRNG.s` 中增加或者移除 `measurement blocks` 字段。
|
||||
|
||||
```
|
||||
#measurement block
|
||||
@ -388,17 +390,21 @@ rdtsc
|
||||
[...]
|
||||
```
|
||||
|
||||
### 5.2 测试不可预测性
|
||||
#### 5.2 测试不可预测性
|
||||
|
||||
我们总是建议在使用个人定制的 pandom 实现来用于加密目地之前,先进行一些测试。
|
||||
|
||||
make check
|
||||
```
|
||||
make check
|
||||
```
|
||||
|
||||
### 5.3 安装定制的 pandom
|
||||
#### 5.3 安装定制的 pandom
|
||||
|
||||
假如你对测试的结果很满意,你就可以使用下面的命令来安装你的 pandom 实现。
|
||||
|
||||
make install
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
更多额外信息及更新详见 [http://ncomputers.org/pandom][63]
|
||||
|
||||
@ -408,7 +414,7 @@ via: https://www.howtoforge.com/tutorial/how-to-install-pandom-a-true-random-num
|
||||
|
||||
作者:[Oliver][a]
|
||||
译者:[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/) 荣誉推出
|
||||
|
@ -0,0 +1,88 @@
|
||||
Linux 桌面系统的优势
|
||||
============================================================
|
||||
|
||||
![linux-desktop-advantages](http://www.linuxinsider.com/article_images/story_graphics_xlarge/xl-2017-linux-1.jpg)
|
||||
|
||||
当我放弃 Windows [转而使用 Linux 系统][3] 后,我的信心不断增长。出于安全方面的考虑促使我选用 Linux 系统,但是我很快发现了很多使用 Linux 桌面系统的优势。
|
||||
|
||||
对于那些还对 Linux 系统犹豫不决,或是那些不甚了解 Linux 系统的用户,我将通过这篇文章给大家介绍一些使用 Linux 桌面系统的优势。
|
||||
|
||||
### 免费才是王道
|
||||
|
||||
首先, Linux 系统完全免费。你无须为使用的操作系统或软件花费一分钱。除了免费获取软件产生的经济效益之外,你还可以在 Linux 系统中随意使用一些当前很流行的软件,比如文字处理软件和照片编辑软件——由于费用方面的原因,我们可能不太愿意花钱去购买这些软件。
|
||||
|
||||
微软的 Office 办公软件几乎是处理各种类型文档的一种标准软件了,但是它每年的费用竟高达 70 美元。然而,你却可以免费使用 [LibreOffice][4] 软件来代替,它同样可以处理各种类型的文档,而且使用也很方便。
|
||||
|
||||
免费软件还能让您有机会尝试新的功能,并通过它们寻求商务和休闲的新方式,而且你也不需要支付任何预期的费用。
|
||||
|
||||
与其费尽周折的去衡量 Mac 或 Windows 系统的优点,你可以考虑下在[上百款不同风格的 Linux 发行版][5]中选择一款最适合自己的操作系统。
|
||||
|
||||
Linux 系统甚至在硬件方面也为用户节省了不少钱,比如有些厂商——尤其是戴尔公司——为购买预安装了 Linux 系统的电脑的用户提供打折优惠。这些电脑的价格相对来说比较便宜,因为用户无须再花钱购买微软的 Windows 系统许可证。
|
||||
|
||||
### 随心所欲的系统定制
|
||||
|
||||
其次,在 Linux 系统中,你可以对系统功能进行任意更改。 Linux 生态系统中的核心项目之一就是桌面环境——它是一些由基础的用户程序和可视化元素组成的一个集合,比如状态栏和启动器,这些元素构成了用户与计算机的一个交互界面。
|
||||
|
||||
有些 Linux 发行版还预安装了桌面环境。比如, Ubuntu 系统就预安装了 Unity 桌面。其它系统,比如 Debian 会在系统安装的过程中让用户选择需要的桌面环境。总之,在 Linux 系统中,用户都可以随意更换他们喜欢的桌面环境。
|
||||
|
||||
大多数的 Linux 发行版都支持(也就是兼容)那些非常流行的桌面环境,因此,找到一款适合自己的桌面系统也非常容易。在桌面系统这个万花筒里,你可以找到界面华丽的系统桌面,比如 KDE Plasma 或者 [Gnome][6],以及轻量级的系统桌面,比如 Xfce 和 MATE 桌面。使用任一款系统桌面,你都可以通过更改主题、系统托盘和菜单,以及仿照其它用户的桌面环境来进一步定制自己的桌面环境。
|
||||
|
||||
Linux 系统的可定制特性完全超出你的想象力。如果你更看重系统的稳定性,你可以使用 Mint 这个发行版系统,它对硬件的兼容性非常好,而且也能确保系统顺利更新。
|
||||
|
||||
除此之外,如果你希望及时领略前沿,你可以安装 Arch Linux ,每一款软件只要开发者一发布,你就可以进行得到最新更新。
|
||||
|
||||
如果你介乎于两者之间,既想要稳定的系统,也想运行一些几个崭新的程序,你可以下载程序的源代码(程序员所开发的代码文件),然后自己进行编译。这就需要你使用工具来编译源代码,生成一堆你的电脑可以运行的 0 和 1 组成的二进制文件。
|
||||
|
||||
你可以使用自己喜欢的任何方式去折腾属于自己的 Linux 系统。
|
||||
|
||||
### 无与伦比的安全性
|
||||
|
||||
第三,多才多艺的 Linux 系统还有一个更重要的特性:安全。
|
||||
|
||||
起初,尽管有一些针对 Linux 系统的病毒,但是跟 Mac 系统比起来,已经屈指可数了。更重要的是,实际上 Linux 系统的核心代码是开源的,对用户完全透明,这意味着你的 Linux 系统漏洞更少。
|
||||
|
||||
一些专有(比如,不开源)的操作系统被任务会影响用户安全,因为它们会启动一些实现方式糟糕的、不透明的进程,从而造成了巨大的威胁。
|
||||
|
||||
比如说, Windows 系统在升级的过程中,默认情况下[不会检查加密签名][7]来验证更新文件的可靠性。
|
||||
|
||||
而使用 Linux 系统,你可以在选择更新时通过签名检查进行严格的细粒度控制,大多数的发行版在系统更新时都默认强制安全检查。这种责任感源自于 Linux 系统的开源开发模式所带来的透明度。
|
||||
|
||||
像 Arch Linux 这种滚动发行版则增加了更多的安全性设置,因为一些重要的补丁一旦通过验证, Arch Linux 就会马上可以使用。你可能很难找到那些每天都提供更新的单一主流操作系统,但是这样的 Linux 发行版却有很多。
|
||||
|
||||
### 天生的编程环境
|
||||
|
||||
很多开发者或者任何对编程有兴趣的人都得益于 Linux 桌面系统中集成的强大开发工具。其中包括那些最经典的编程工具,比如 GNU C 编译器,或者 GCC 和 GNU Autoconf 工具都是 Linux 系统中一些非常重要的基础工具。
|
||||
|
||||
Linux 系统的大多数默认软件库都支持数十种编程语言,它包含了发行版中可以使用的预编译软件。
|
||||
|
||||
很多因特网的基础架构和许多联网设备都运行于 Linux 系统上——从服务器到智能设备,比如安防摄像机和恒温器。在 Linux 系统下开发调试这些设备的软件非常容易。如果你有一个跟计算机相关的项目, Linux 系统可以完美地支持你完成这个项目。
|
||||
|
||||
### 社区是 Linux 系统发展的关键
|
||||
|
||||
最后一点, Linux 系统拥有一个团结且友好型的社区。由于 Linux 在桌面系统是一个相对小众的桌面操作系统,仅占有 3% 左右的市场份额,因此, Linux 社区更希望有更多的潜在用户加入进来。
|
||||
|
||||
Linux 系统有很多的用户论坛,尤其是对新手比较友好的 Unbuntu 系统论坛,它包括非常丰富且全面的知识来帮助用户解决一些基本的系统问题。很多高级用户更倾向于使用 Linux 系统,因此那些 Linux 发行版都拥有非常非常详尽维基文档,以指导用户完成高级的系统应用项目。
|
||||
|
||||
甚至还有业余的 Linux 论坛和 [Reddit] [8] 讨论区,所涉及的范围包括从对比 Linux 系统各种应用软件到炫耀桌面主题等。总而言之,这是一个比 Windows 用户群更加友善的社区。
|
||||
|
||||
我沉浸在 Linux 的世界里两年多了,我更加相信 Linux 系统对每一个用户都有所帮助。我希望这篇文章能够让你了解到 Linux 桌面系统的各种优势。但是真正的乐趣是从中发现自己感兴趣的东西!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.linuxinsider.com/story/84326.html
|
||||
|
||||
作者:[Jonathan Terrasi][a]
|
||||
译者:[rusking](https://github.com/rusking)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.linkedin.com/company/ect-news-network
|
||||
[1]:http://www.linuxinsider.com/story/84326.html?rss=1#
|
||||
[2]:http://www.linuxinsider.com/perl/mailit/?id=84326
|
||||
[3]:http://www.linuxinsider.com/story/84286.html
|
||||
[4]:http://www.libreoffice.org/
|
||||
[5]:https://en.wikipedia.org/wiki/Linux_distribution
|
||||
[6]:http://en.wikipedia.org/wiki/GNOME
|
||||
[7]:https://duo.com/blog/out-of-box-exploitation-a-security-analysis-of-oem-updaters
|
||||
[8]:http://www.reddit.com/
|
@ -1,25 +1,20 @@
|
||||
在 Linux 上给用户赋予指定目录的读写权限
|
||||
============================================================
|
||||
|
||||
|
||||
在上篇文章中我们向您展示了如何在 Linux 上[创建一个共享目录][3]。这次,我们会为您介绍如何将 Linux 上指定目录的读写权限赋予用户。
|
||||
|
||||
|
||||
有两种方法可以实现这个目标:第一种是 [使用 ACL (访问控制列表)][4] ,第二种是[创建用户组来管理文件权限][5],下面会一一介绍。
|
||||
|
||||
|
||||
为了完成这个教程,我们将使用以下设置。
|
||||
|
||||
```
|
||||
Operating system: CentOS 7
|
||||
Test directory: /shares/project1/reports
|
||||
Test user: tecmint
|
||||
Filesystem type: Ext4
|
||||
```
|
||||
- 操作系统:CentOS 7
|
||||
- 测试目录:`/shares/project1/reports`
|
||||
- 测试用户:tecmint
|
||||
- 文件系统类型:ext4
|
||||
|
||||
请确认所有的命令都是使用 root 用户执行的,或者使用 [sudo 命令][6] 来享受与之同样的权限。
|
||||
|
||||
让我们开始吧!下面,先使用 mkdir 命令来创建一个名为 `reports` 的目录。
|
||||
让我们开始吧!下面,先使用 `mkdir` 命令来创建一个名为 `reports` 的目录。
|
||||
|
||||
```
|
||||
# mkdir -p /shares/project1/reports
|
||||
@ -27,16 +22,16 @@ Filesystem type: Ext4
|
||||
|
||||
### 使用 ACL 来为用户赋予目录的读写权限
|
||||
|
||||
重要提示:打算使用此方法的话,您需要确认您的 Linux 文件系统类型(如 Ext3 和 Ext4, NTFS, BTRFS)支持 ACL。
|
||||
重要提示:打算使用此方法的话,您需要确认您的 Linux 文件系统类型(如 ext3 和 ext4, NTFS, BTRFS)支持 ACL。
|
||||
|
||||
1. 首先, 依照以下命令在您的系统中[检查当前文件系统类型][7],并且查看内核是否支持 ACL:
|
||||
1、 首先, 依照以下命令在您的系统中[检查当前文件系统类型][7],并且查看内核是否支持 ACL:
|
||||
|
||||
```
|
||||
# df -T | awk '{print $1,$2,$NF}' | grep "^/dev"
|
||||
# grep -i acl /boot/config*
|
||||
```
|
||||
|
||||
从下方的截屏可以看到,文件系统类型是 **Ext4**,并且从 **CONFIG_EXT4_FS_POSIX_ACL=y** 选项可以发现内核是支持 **POSIX ACLs** 的。
|
||||
从下方的截屏可以看到,文件系统类型是 `ext4`,并且从 `CONFIG_EXT4_FS_POSIX_ACL=y` 选项可以发现内核是支持 **POSIX ACLs** 的。
|
||||
|
||||
[
|
||||
![Check Filesystem Type and Kernel ACL Support](http://www.tecmint.com/wp-content/uploads/2017/03/Check-Filesystem-Type-and-Kernel-ACL-Support.png)
|
||||
@ -44,7 +39,7 @@ Filesystem type: Ext4
|
||||
|
||||
*查看文件系统类型和内核的 ACL 支持。*
|
||||
|
||||
2. 接下来,查看文件系统(分区)挂载时是否使用了 ACL 选项。
|
||||
2、 接下来,查看文件系统(分区)挂载时是否使用了 ACL 选项。
|
||||
|
||||
```
|
||||
# tune2fs -l /dev/sda1 | grep acl
|
||||
@ -55,14 +50,14 @@ Filesystem type: Ext4
|
||||
|
||||
*查看分区是否支持 ACL*
|
||||
|
||||
通过上边的输出可以发现,默认的挂载项目中已经对 **ACL** 进行了支持。如果发现结果不如所愿,你可以通过以下命令对指定分区(此例中使用 **/dev/sda3**)开启 ACL 的支持。
|
||||
通过上边的输出可以发现,默认的挂载项目中已经对 **ACL** 进行了支持。如果发现结果不如所愿,你可以通过以下命令对指定分区(此例中使用 `/dev/sda3`)开启 ACL 的支持。
|
||||
|
||||
```
|
||||
# mount -o remount,acl /
|
||||
# tune2fs -o acl /dev/sda3
|
||||
```
|
||||
|
||||
3. 现在是时候指定目录 `reports` 的读写权限分配给名为 `tecmint` 的用户了,依照以下命令执行即可。
|
||||
3、 现在是时候指定目录 `reports` 的读写权限分配给名为 `tecmint` 的用户了,依照以下命令执行即可。
|
||||
|
||||
```
|
||||
# getfacl /shares/project1/reports # Check the default ACL settings for the directory
|
||||
@ -75,9 +70,9 @@ Filesystem type: Ext4
|
||||
|
||||
*通过 ACL 对指定目录赋予读写权限*
|
||||
|
||||
在上方的截屏中,通过输出结果的第二行 **getfacl** 命令可以发现,用户 `tecmint` 已经成功的被赋予了 **/shares/project1/reports** 目录的读写权限。
|
||||
在上方的截屏中,通过输出结果的第二行 `getfacl` 命令可以发现,用户 `tecmint` 已经成功的被赋予了 `/shares/project1/reports` 目录的读写权限。
|
||||
|
||||
如果想要获取ACL列表的更多信息。可以在下方查看我们的其他指南。
|
||||
如果想要获取 ACL 列表的更多信息。可以在下方查看我们的其他指南。
|
||||
|
||||
1. [如何使用访问控制列表(ACL)为用户/组设置磁盘配额][1]
|
||||
2. [如何使用访问控制列表(ACL)挂载网络共享][2]
|
||||
@ -86,7 +81,7 @@ Filesystem type: Ext4
|
||||
|
||||
### 使用用户组来为用户赋予指定目录的读写权限
|
||||
|
||||
1. 如果用户已经拥有了默认的用户组(通常组名与用户名相同),就可以简单的通过变更文件夹的所属用户组来完成。
|
||||
1、 如果用户已经拥有了默认的用户组(通常组名与用户名相同),就可以简单的通过变更文件夹的所属用户组来完成。
|
||||
|
||||
```
|
||||
# chgrp tecmint /shares/project1/reports
|
||||
@ -98,20 +93,20 @@ Filesystem type: Ext4
|
||||
# groupadd projects
|
||||
```
|
||||
|
||||
2. 接下来将用户 `tecmint` 添加到 `projects` 组中:
|
||||
2、 接下来将用户 `tecmint` 添加到 `projects` 组中:
|
||||
|
||||
```
|
||||
# usermod -aG projects tecmint # add user to projects
|
||||
# groups tecmint # check users groups
|
||||
```
|
||||
|
||||
3. 将目录的所属用户组变更为 projects:
|
||||
3、 将目录的所属用户组变更为 projects:
|
||||
|
||||
```
|
||||
# chgrp projects /shares/project1/reports
|
||||
```
|
||||
|
||||
4. 现在,给组成员设置读写权限。
|
||||
4、 现在,给组成员设置读写权限。
|
||||
|
||||
```
|
||||
# chmod -R 0760 /shares/projects/reports
|
||||
@ -141,7 +136,7 @@ via: http://www.tecmint.com/give-read-write-access-to-directory-in-linux/
|
||||
[a]:http://www.tecmint.com/author/aaronkili/
|
||||
[1]:http://www.tecmint.com/set-access-control-lists-acls-and-disk-quotas-for-users-groups/
|
||||
[2]:http://www.tecmint.com/rhcsa-exam-configure-acls-and-mount-nfs-samba-shares/
|
||||
[3]:http://www.tecmint.com/create-a-shared-directory-in-linux/
|
||||
[3]:https://linux.cn/article-8187-1.html
|
||||
[4]:http://www.tecmint.com/secure-files-using-acls-in-linux/
|
||||
[5]:http://www.tecmint.com/manage-users-and-groups-in-linux/
|
||||
[6]:http://www.tecmint.com/sudoers-configurations-for-setting-sudo-in-linux/
|
@ -1,30 +1,30 @@
|
||||
如何用树莓派搭建一个自己的 web 服务器
|
||||
如何用树莓派搭建个人 web 服务器
|
||||
============================================================
|
||||
|
||||
![How to set up a personal web server with a Raspberry Pi](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/lightbulb_computer_person_general_.png?itok=ZY3UuQQa "How to set up a personal web server with a Raspberry Pi")
|
||||
|
||||
>图片来源 : opensource.com
|
||||
|
||||
个人网络服务器即 “云”,只不过是你拥有和控制它,而不是一个大型公司。
|
||||
个人 Web 服务器即 “云”,只不过是你拥有和控制它,而不是一个大型公司。
|
||||
|
||||
拥有一个自己的云有很多好处,包括定制,免费存储,免费的互联网服务,开源软件的路径,高品质的安全性,完全控制您的内容,快速更改的能力,实验代码的地方等等。 这些好处大部分是无法估量的,但在财务上,这些好处可以为您每个月节省超过 100 美元。
|
||||
拥有一个自己的云有很多好处,包括可定制、免费存储、免费的互联网服务、通往开源软件之路、高安全性、完全控制您的内容、快速更改的能力、实验代码的地方等等。 这些好处大部分是无法估量的,但在财务上,这些好处可以为您每个月节省超过 100 美元。
|
||||
|
||||
![Building your own web server with Raspberry Pi](https://opensource.com/sites/default/files/1-image_by_mitchell_mclaughlin_cc_by-sa_4.0.png "Building your own web server with Raspberry Pi")
|
||||
|
||||
图片来自 Mitchell McLaughlin, CC BY-SA 4.0
|
||||
|
||||
我本可以选择 AWS ,但我更喜欢完全自由且安全性可控,并且我可以学一下这些东西是如何搭建的。
|
||||
|
||||
* 私有主机: 不使用 BlueHost 或 DreamHost
|
||||
* 云存储:不使用 Dropbox, Box, Google Drive, Microsoft Azure, iCloud, 或是 AWS
|
||||
* 内部部署安全
|
||||
* 私有 Web 托管:而非 BlueHost 或 DreamHost
|
||||
* 云存储:而非 Dropbox、Box、Google Drive、Microsoft Azure、iCloud 或是 AWS
|
||||
* 自主部署安全
|
||||
* HTTPS:Let’s Encrypt
|
||||
* 分析: Google
|
||||
* OpenVPN:不需要专有互联网连接 (预计每个月花费 $7)
|
||||
* OpenVPN:不需要专有互联网连接(预计每个月花费 $7)
|
||||
|
||||
我所使用的物品清单:
|
||||
|
||||
* 树莓派 3 代 Model B
|
||||
* MicroSD 卡(推荐使用 32 GB, [兼容树莓派的 SD 卡][a1])
|
||||
* MicroSD 卡(推荐使用 32 GB, [兼容树莓派的 SD 卡][a1])
|
||||
* USB microSD 卡读卡器
|
||||
* 以太网络线
|
||||
* 连接上 Wi-Fi 的路由器
|
||||
@ -37,36 +37,38 @@
|
||||
* 显示器 (支持接入 HDMI)
|
||||
* MacBook Pro
|
||||
|
||||
### 步骤 1: 启动树莓派
|
||||
### 步骤 1: 启动树莓派
|
||||
|
||||
下载最新发布的 Raspbian (树莓派的操作系统)。 [Raspbian Jessie][a6] 的 ZIP 包就可以用 [1]。解压缩或提取下载的文件然后把它拷贝到 SD 卡里。使用 [Pi Filler][a7] 可以让这些过程变得更简单。[下载 Pi Filer 1.3][8] 或最新的版本。解压或提取下载文件之后打开它,你应该会看到这样的提示:
|
||||
下载最新发布的 Raspbian (树莓派的操作系统)。 [Raspbian Jessie][a6] 的 ZIP 包就可以用 [脚注 1]。解压缩或提取下载的文件然后把它拷贝到 SD 卡里。使用 [Pi Filler][a7] 可以让这些过程变得更简单。[下载 Pi Filer 1.3][8] 或最新的版本。解压或提取下载文件之后打开它,你应该会看到这样的提示:
|
||||
|
||||
![Pi Filler prompt](https://opensource.com/sites/default/files/2-image_by_mitchell_mclaughlin_cc_by-sa_4.0.png "Pi Filler prompt")
|
||||
|
||||
确保 USB 读卡器这时还没有插上。如果已经插上了那就先推出。点 Continue 继续下一步。你会看到一个让你选择文件的界面,选择你之前解压缩后的树莓派系统文件。然后你会看到另一个提示,如图所示:
|
||||
确保 USB 读卡器这时还没有插上。如果已经插上了那就先弹出。点 “Continue” 继续下一步。你会看到一个让你选择文件的界面,选择你之前解压缩后的树莓派系统文件。然后你会看到另一个提示,如图所示:
|
||||
|
||||
![USB card reader prompt](https://opensource.com/sites/default/files/3-image_by_mitchell_mclaughlin_cc_by-sa_4.0.png "USB card reader")
|
||||
|
||||
把 MicroSD 卡 (推荐 32 GB ,至少 16GB) 插入到 USB MicroSD 卡读卡器里。然后把 USB 读卡器接入到你的电脑里。你可以把你的 SD 卡重命名为 “Raspberry” 以区别其他设备。然后点击 continue。请先确保你的 SD 卡是空的,因为 Pi Filler 会在运行时 _擦除_ 所有事先存在 SD 卡里的内容。如果你要备份卡里的内容,那你最好就马上备份。当你点 continue 的时候,Raspbian OS 就会被写入到 SD 卡里。这个过程大概会花费一到三分钟左右。当写入完成后,推出 USB 读卡器,把 SD 卡拔出来插入到树莓派的 SD 卡槽里。把电源线接上,给树莓派提供电源。这时树莓派就会自己启动。树莓派的默认登录账户信息是:
|
||||
把 MicroSD 卡(推荐 32 GB ,至少 16GB)插入到 USB MicroSD 卡读卡器里。然后把 USB 读卡器接入到你的电脑里。你可以把你的 SD 卡重命名为 “Raspberry” 以区别其他设备。然后点击 “Continue”。请先确保你的 SD 卡是空的,因为 Pi Filler 会在运行时 _擦除_ 所有事先存在 SD 卡里的内容。如果你要备份卡里的内容,那你最好就马上备份。当你点 “Continue” 的时候,Raspbian OS 就会被写入到 SD 卡里。这个过程大概会花费一到三分钟左右。当写入完成后,推出 USB 读卡器,把 SD 卡拔出来插入到树莓派的 SD 卡槽里。把电源线接上,给树莓派供电。这时树莓派就会自己启动。树莓派的默认登录账户信息是:
|
||||
|
||||
**用户名: pi
|
||||
密码: raspberry**
|
||||
- 用户名: pi
|
||||
- 密码:raspberry
|
||||
|
||||
当树莓派首次启动完成时,会跳出一个标题为 <ruby>设置选项<rt>Setup Options</rt></ruby> 的配置界面,就像下面的图片一样 [2]:
|
||||
当树莓派首次启动完成时,会跳出一个标题为 “<ruby>设置选项<rt>Setup Options</rt></ruby>” 的配置界面,就像下面的图片一样 [脚注 2]:
|
||||
|
||||
![Raspberry Pi software configuration setup](https://opensource.com/sites/default/files/4-image_by_mitchell_mclaughlin_cc_by-sa_4.0.png "Raspberry Pi software configuration setup")
|
||||
|
||||
选择 “Expand Filesystem” 这一选项并回车 [3]。 同时,我还推荐选择第二个选项 “Change User Password”。这对保证安全性来说尤为重要。它还能个性化你的树莓派。
|
||||
选择 “<ruby>扩展文件系统<rt>Expand Filesystem</rt></ruby>” 这一选项并回车 [脚注 3]。 同时,我还推荐选择第二个选项 “<ruby>修改密码<rt>Change User Password</rt></ruby>”。这对保证安全性来说尤为重要。它还能个性化你的树莓派。
|
||||
|
||||
在选项列表中选择第三项 “Enable Boot To Desktop/Scratch” 并回车。这时会跳到另一个标题为 “Choose boot option” 的界面,就像下面这张图这样。
|
||||
在选项列表中选择第三项 “<ruby>启用引导到桌面<rt>Enable Boot To Desktop/Scratch</rt></ruby>” 并回车。这时会跳到另一个标题为 “<ruby>选择引导选项<rt>Choose boot option</rt></ruby>” 的界面,就像下面这张图这样:
|
||||
|
||||
![Choose boot option](https://opensource.com/sites/default/files/5-image_by_mitchell_mclaughlin_cc_by-sa_4.0.png "Choose boot option")
|
||||
|
||||
在 “Choose boot option” 这个界面选择第二个选项 “Desktop log in as user 'pi' at the graphical desktop” 并回车 [4]。完成这个操作之后会回到之前的 “Setup Options” 界面。如果没有回到之前的界面的话就选择当前界面底部的 “OK” 按钮并回车。
|
||||
在这个界面选择第二个选项 “<ruby>以用户‘pi’登录图形化桌面<rt>Desktop log in as user 'pi' at the graphical desktop</rt></ruby>” 并回车 [脚注 4]。完成这个操作之后会回到之前的 “<ruby>设置选项<rt>Setup Options</rt></ruby>” 界面。如果没有回到之前的界面的话就选择当前界面底部的 “OK” 按钮并回车。
|
||||
|
||||
当这些操作都完成之后,选择当前界面底部的 “Finish” 按钮并回车,这时它就会自动重启。如果没有自动重启的话,就在终端里使用如下命令来重启。
|
||||
|
||||
**$ sudo reboot**
|
||||
```
|
||||
$ sudo reboot
|
||||
```
|
||||
|
||||
接上一步的重启,如果所有步骤都顺利进行的话,你会进入到类似下面这样桌面环境中。
|
||||
|
||||
@ -76,17 +78,14 @@
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
|
||||
$ sudo apt-get upgrade-y
|
||||
|
||||
$ sudo apt-get dist-upgrade -y
|
||||
|
||||
$ sudo rpi-update
|
||||
```
|
||||
|
||||
这些操作可能会花费几分钟时间。完成之后,现在运行着的树莓派就是最新的了。
|
||||
|
||||
### 步骤 2: 配置树莓派
|
||||
### 步骤 2: 配置树莓派
|
||||
|
||||
SSH 指的是 Secure Shell,是一种加密网络协议,可让你在计算机和树莓派之间安全地传输数据。 你可以从 Mac 的命令行控制你的树莓派,而无需显示器或键盘。
|
||||
|
||||
@ -96,9 +95,9 @@ SSH 指的是 Secure Shell,是一种加密网络协议,可让你在计算机
|
||||
$ sudo ifconfig
|
||||
```
|
||||
|
||||
如果你在使用以太网,看 “eth0” 部分。如果你在使用 Wi-Fi, 看 “wlan0” 部分。
|
||||
如果你在使用以太网,看 `eth0` 部分。如果你在使用 Wi-Fi, 看 `wlan0` 部分。
|
||||
|
||||
查找 “inet addr”,后跟一个 IP 地址,如 192.168.1.115,这是本篇文章中使用的默认 IP。
|
||||
查找 `inet addr`,后跟一个 IP 地址,如 192.168.1.115,这是本篇文章中使用的默认 IP。
|
||||
|
||||
有了这个地址,在终端中输入 :
|
||||
|
||||
@ -106,9 +105,9 @@ $ sudo ifconfig
|
||||
$ ssh pi@192.168.1.115
|
||||
```
|
||||
|
||||
对于 PC 上的 SSH,请参见脚注 [5]。
|
||||
对于 PC 上的 SSH,请参见 [脚注 5]。
|
||||
|
||||
出现提示时输入默认密码 “raspberry”,除非你之前更改过密码。
|
||||
出现提示时输入默认密码 `raspberry`,除非你之前更改过密码。
|
||||
|
||||
现在你已经通过 SSH 登录成功。
|
||||
|
||||
@ -120,22 +119,18 @@ $ ssh pi@192.168.1.115
|
||||
$ sudo apt-get install xrdp
|
||||
```
|
||||
|
||||
Xrdp 支持 Mac 和 PC 的 Microsoft Remote Desktop 客户端。
|
||||
xrdp 支持 Mac 和 PC 的 Microsoft Remote Desktop 客户端。
|
||||
|
||||
在 Mac 上,在 App store 中搜索 “Microsoft Remote Desktop”。 下载它。 (对于 PC,请参见脚注 [6]。)
|
||||
在 Mac 上,在 App store 中搜索 “Microsoft Remote Desktop”。 下载它。 (对于 PC,请参见 [脚注 6]。)
|
||||
|
||||
安装完成之后,在你的 Mac 中搜索一个叫 “Microsoft Remote Desktop” 的应用并打开它,你会看到 :
|
||||
|
||||
![Microsoft Remote Desktop](https://opensource.com/sites/default/files/7-image_by_mitchell_mclaughlin_cc_by-sa_4.0.png "Microsoft Remote Desktop")
|
||||
|
||||
*图片来自 Mitchell McLaughlin, CC BY-SA 4.0*
|
||||
|
||||
点击 “New” 新建一个远程连接,在空白处填写如下配置。
|
||||
|
||||
![Setting up a remote connection](https://opensource.com/sites/default/files/8-image_by_mitchell_mclaughlin_cc_by-sa_4.0.png "Setting up a remote connection")
|
||||
|
||||
*图片来自 Mitchell McLaughlin, CC BY-SA 4.0*
|
||||
|
||||
关闭 “New” 窗口就会自动保存。
|
||||
|
||||
你现在应该看到 “My Desktop” 下列出的远程连接。 双击它。
|
||||
@ -146,7 +141,7 @@ Xrdp 支持 Mac 和 PC 的 Microsoft Remote Desktop 客户端。
|
||||
|
||||
好了,现在你不需要额外的鼠标、键盘或显示器就能控制你的树莓派。这是一个更为轻量级的配置。
|
||||
|
||||
### 静态本地 IP 地址
|
||||
### 静态化本地 IP 地址
|
||||
|
||||
有时候你的本地 IP 地址 192.168.1.115 会发生改变。我们需要让这个 IP 地址静态化。输入:
|
||||
|
||||
@ -154,17 +149,17 @@ Xrdp 支持 Mac 和 PC 的 Microsoft Remote Desktop 客户端。
|
||||
$ sudo ifconfig
|
||||
```
|
||||
|
||||
从 “eth0” 部分或 “wlan0” 部分,“inet addr”(树莓派当前 IP),“bcast”(广播 IP 范围)和 “mask”(子网掩码地址))中写入。 然后输入:
|
||||
从 `eth0` 部分或 `wlan0` 部分,记下 `inet addr`(树莓派当前 IP),`bcast`(广播 IP 范围)和 `mask`(子网掩码地址)。 然后输入:
|
||||
|
||||
```
|
||||
$ netstat -nr
|
||||
```
|
||||
|
||||
记下 “destination” 和 “gateway/network”。
|
||||
记下 `destination` 和 `gateway/network`。
|
||||
|
||||
![Setting up a local IP address](https://opensource.com/sites/default/files/setting_up_local_ip_address.png "Setting up a local IP address")
|
||||
|
||||
应该大概是这样子的:
|
||||
大概应该是这样子的:
|
||||
|
||||
```
|
||||
net address 192.168.1.115
|
||||
@ -181,7 +176,7 @@ destination 192.168.1.0
|
||||
$ sudo nano /etc/dhcpcd.conf
|
||||
```
|
||||
|
||||
不要使用 **/etc/network/interfaces**。
|
||||
不要去动 `/etc/network/interfaces`。
|
||||
|
||||
剩下要做的就是把这些内容追加到这个文件的底部,把 IP 换成你想要的 IP 地址。
|
||||
|
||||
@ -206,25 +201,25 @@ $ sudo ifconfig
|
||||
|
||||
这时你就可以看到你的树莓派上的新的静态配置了。
|
||||
|
||||
### 静态全局 IP address
|
||||
### 静态化全局 IP 地址
|
||||
|
||||
如果您的 ISP(互联网服务提供商)已经给您一个静态外部 IP 地址,您可以跳到端口转发部分。 如果没有,请继续阅读。
|
||||
|
||||
你已经设置了 SSH,远程桌面和静态内部 IP 地址,因此现在本地网络中的计算机将会知道在哪里可以找到你的树莓派。 但是你仍然无法从本地 Wi-Fi 网络外部访问你的树莓派。 你需要树莓派可以从互联网上的任何地方公开访问。这需要静态外部 IP 地址 [7]。
|
||||
你已经设置了 SSH、远程桌面和静态内部 IP 地址,因此现在本地网络中的计算机将会知道在哪里可以找到你的树莓派。 但是你仍然无法在本地 Wi-Fi 网络外部访问你的树莓派。 你需要树莓派可以从互联网上的任何地方公开访问。这需要静态的外部 IP 地址 [脚注 7]。
|
||||
|
||||
调用您的 ISP 并请求静态外部(有时称为静态全局)IP 地址可能会是一个非常敏感的过程。 ISP 拥有决策权,所以我会非常小心处理。 他们可能拒绝你的的静态外部 IP 地址请求。 如果他们拒绝了你的请求,你不要怪罪于他们,因为这种类型的请求有法律和操作风险。 他们特别不希望客户运行中型或大型互联网服务。 他们可能会明确地询问为什么需要一个静态的外部 IP 地址。 最好说实话,告诉他们你打算主办一个低流量的个人网站或类似的小型非营利互联网服务。 如果一切顺利,他们应该会建立一个任务,并在一两个星期内给你打电话。
|
||||
联系您的 ISP 并请求静态的外部(有时称为静态全局)IP 地址可能会是一个非常敏感的过程。 ISP 拥有决策权,所以我会非常小心处理。 他们可能拒绝你的的静态外部 IP 地址请求。 如果他们拒绝了你的请求,你不要怪罪于他们,因为这种类型的请求有法律和操作风险。 他们特别不希望客户运行中型或大型互联网服务。 他们可能会明确地询问为什么需要一个静态的外部 IP 地址。 最好说实话,告诉他们你打算主办一个低流量的个人网站或类似的小型非营利互联网服务。 如果一切顺利,他们应该会建立一个工单,并在一两个星期内给你打电话。
|
||||
|
||||
### 端口转发
|
||||
|
||||
这个新获得的 ISP 分配的静态全局 IP 地址是用于访问路由器。 树莓派现在仍然无法访问。 你需要设置端口转发才能访问树莓派。
|
||||
|
||||
端口是信息在互联网上传播的虚拟途径。 你有时需要转发端口,以使计算机像树莓派一样可以访问 Internet,因为它位于网络路由器后面。 VollmilchTV 专栏在 YouTube 上的一个视频,名字是[什么是 TCP/IP,端口,路由,Intranet,防火墙,互联网][9],帮助我更好地了解端口。
|
||||
端口是信息在互联网上传播的虚拟途径。 你有时需要转发端口,以使计算机像树莓派一样可以访问 Internet,因为它位于网络路由器后面。 VollmilchTV 专栏在 YouTube 上的一个视频,名字是[什么是 TCP/IP,端口,路由,Intranet,防火墙,互联网][9],可以帮助你更好地了解端口。
|
||||
|
||||
端口转发可用于像 树莓派 Web 服务器或 VoIP 或点对点下载的应用程序。 有 [65,000+个端口][10]可供选择,因此你可以为你构建的每个 Internet 应用程序分配一个不同的端口。
|
||||
端口转发可用于像 树莓派 Web 服务器或 VoIP 或点对点下载的应用程序。 有 [65000个以上的端口][10]可供选择,因此你可以为你构建的每个 Internet 应用程序分配一个不同的端口。
|
||||
|
||||
设置端口转发的方式取决于你的路由器。 如果你有 Linksys 的话,Gabriel Ramirez 在 YouTbue 上有一个标题叫 [How to go online with your Apache Ubuntu server][a2] 的视频解释了如何设置。 如果您没有 Linksys,请阅读路由器附带的文档,以便自定义和定义要转发的端口。
|
||||
设置端口转发的方式取决于你的路由器。 如果你有 Linksys 的话,Gabriel Ramirez 在 YouTbue 上有一个标题叫 [如何让你的 Apache Ubuntu 服务器连到互联网][a2] 的视频解释了如何设置。 如果您没有 Linksys,请阅读路由器附带的文档,以便自定义和定义要转发的端口。
|
||||
|
||||
你将需要转发 SSH 以及远程桌面端口。
|
||||
你需要转发 SSH 以及远程桌面端口。
|
||||
|
||||
如果你认为你已经过配置端口转发了,输入下面的命令以查看它是否正在通过 SSH 工作:
|
||||
|
||||
@ -234,17 +229,17 @@ $ ssh pi@your_global_ip_address
|
||||
|
||||
它应该会提示你输入密码。
|
||||
|
||||
检查端口转发是否也适用于远程桌面。 打开 Microsoft Remote Desktop。 你之前的的远程连接设置应该已经保存了,但需要使用静态外部 IP 地址(例如195.198.227.116)来更新 “PC名称” 字段,而不是静态内部地址(例如 192.168.1.115)。
|
||||
检查端口转发是否也适用于远程桌面。 打开 Microsoft Remote Desktop。 你之前的的远程连接设置应该已经保存了,但需要使用静态的外部 IP 地址(例如 195.198.227.116)来更新 “PC 名称” 字段,而不是静态的内部地址(例如 192.168.1.115)。
|
||||
|
||||
现在,尝试通过远程桌面连接。 它应该简单地加载并到达树莓派的桌面。
|
||||
现在,尝试通过远程桌面连接。 它应该简单地加载并显示树莓派的桌面。
|
||||
|
||||
![Raspberry Pi desktop](https://opensource.com/sites/default/files/6-image_by_mitchell_mclaughlin_cc_by-sa_4.0_1.png "Raspberry Pi desktop")
|
||||
|
||||
好了, 树莓派现在可以从互联网上访问了,并且已经准备好进行高级项目了。
|
||||
|
||||
作为一个奖励选项,您可以保持两个远程连接到您的 Pi。 一个通过互联网,另一个通过 LAN(局域网)。很容易设置。在 Microsoft Remote Desktop 中,保留一个称为 “Pi Internet” 的远程连接,另一个称为 “Pi Local”。 将 Pi Internet 的 “PC name” 配置为静态外部 IP 地址,例如 195.198.227.116。 将 Pi Local 的 “PC name” 配置为静态内部 IP 地址,例如192.168.1.115。 现在,您可以选择在全球或本地连接。
|
||||
作为一个奖励选项,您可以保持到您的 Pi 的两个远程连接。 一个通过互联网,另一个通过 LAN(局域网)。很容易设置。在 Microsoft Remote Desktop 中,保留一个称为 “Pi Internet” 的远程连接,另一个称为 “Pi Local”。 将 Pi Internet 的 “PC 名称” 配置为静态外部 IP 地址,例如 195.198.227.116。 将 Pi Local 的 “PC 名称” 配置为静态内部 IP 地址,例如 192.168.1.115。 现在,您可以选择在全局或本地连接。
|
||||
|
||||
如果你还没有看过由 Gabriel Ramirez 发布的 [如何使用您的Apache Ubuntu服务器上线][a3],那么你可以去看一下,作为过渡到第二个项目的教程。 它将向您展示项目背后的技术架构。 在我们的例子中,你使用的是树莓派而不是 Ubuntu 服务器。 动态 DNS 位于域公司和您的路由器之间,这是 Ramirez 省略的部分。 除了这个微妙之处外,视频是在整体上解释系统的工作原理。 您可能会注意到本教程涵盖了树莓派设置和端口转发,这是服务器端或后端。 查看原始来源,涵盖域名,动态 DNS,Jekyll(静态 HTML 生成器)和 Apache(网络托管)的更高级项目,这是客户端或前端。
|
||||
如果你还没有看过由 Gabriel Ramirez 发布的 [如何让你的 Apache Ubuntu 服务器连到互联网][a3],那么你可以去看一下,作为过渡到第二个项目的教程。 它将向您展示项目背后的技术架构。 在我们的例子中,你使用的是树莓派而不是 Ubuntu 服务器。 动态 DNS 位于域名公司和您的路由器之间,这是 Ramirez 省略的部分。 除了这个微妙之处外,视频是在整体上解释系统的工作原理。 您可能会注意到本教程涵盖了树莓派设置和端口转发,这是服务器端或后端。 查看原始来源,涵盖域名,动态 DNS,Jekyll(静态 HTML 生成器)和 Apache(网络托管)的更高级项目,这是客户端或前端。
|
||||
|
||||
### 脚注
|
||||
|
||||
@ -264,7 +259,7 @@ $ sudo-rasps-config
|
||||
|
||||
![PuTTY configuration](https://opensource.com/sites/default/files/putty_configuration.png "PuTTY configuration")
|
||||
|
||||
[下载并运行 PuTTY][11] 或 Windows 的另一个 SSH 客户端。 在该字段中输入你的 IP 地址,如上图所示。 将默认端口保留在 22。 回车,PuTTY 将打开一个终端窗口,提示你输入用户名和密码。 填写然后开始在树莓派上进行你的远程工作。
|
||||
[下载并运行 PuTTY][11] 或 Windows 的其它 SSH 客户端。 在该字段中输入你的 IP 地址,如上图所示。 将默认端口保留为 22。 回车,PuTTY 将打开一个终端窗口,提示你输入用户名和密码。 填写然后开始在树莓派上进行你的远程工作。
|
||||
|
||||
[6] 如果尚未安装,请下载 [Microsoft Remote Desktop][12]。 搜索您的计算机上的的 Microsoft Remote Desktop。 运行。 提示时输入 IP 地址。 接下来,会弹出一个 xrdp 窗口,提示你输入用户名和密码。
|
||||
|
||||
@ -276,12 +271,10 @@ $ sudo-rasps-config
|
||||
|
||||
作者简介:
|
||||
|
||||
Mitchell McLaughlin - 我是一名开放网络的贡献者和开发者。我感兴趣的领域很广泛,但我特别喜欢开源软件/硬件,比特币和编程。 我住在旧金山 我有过一些简短的 GoPro 和 Oracle 工作经验。
|
||||
|
||||
Mitchell McLaughlin - 我是一名开放网络的贡献者和开发者。我感兴趣的领域很广泛,但我特别喜欢开源软件/硬件,比特币和编程。 我住在旧金山,我有过一些简短的 GoPro 和 Oracle 工作经验。
|
||||
|
||||
-------------
|
||||
|
||||
|
||||
via: https://opensource.com/article/17/3/building-personal-web-server-raspberry-pi-3
|
||||
|
||||
作者:[Mitchell McLaughlin ][a]
|
331
published/201705/20170308 Our guide to a Golang logs world.md
Normal file
331
published/201705/20170308 Our guide to a Golang logs world.md
Normal file
@ -0,0 +1,331 @@
|
||||
Go 语言日志指南
|
||||
============================================================
|
||||
|
||||
![golang logo](https://logmatic.io/wp-content/uploads/2017/03/golang-logo.png)
|
||||
|
||||
你是否厌烦了那些使用复杂语言编写的、难以部署的、总是在不停构建的解决方案?Golang 是解决这些问题的好方法,它和 C 语言一样快,又和 Python 一样简单。
|
||||
|
||||
但是你是如何使用 Golang 日志监控你的应用程序的呢?Golang 没有异常,只有错误。因此你的第一印象可能就是开发 Golang 日志策略并不是一件简单的事情。不支持异常事实上并不是什么问题,异常在很多编程语言中已经失去了其异常性:它们过于被滥用以至于它们的作用都被忽视了。
|
||||
|
||||
在进一步深入之前,我们首先会介绍 Golang 日志的基础,并讨论 Golang 日志标准、元数据意义、以及最小化 Golang 日志对性能的影响。通过日志,你可以追踪用户在你应用中的活动,快速识别你项目中失效的组件,并监控总体性能以及用户体验。
|
||||
|
||||
### I. Golang 日志基础
|
||||
|
||||
#### 1) 使用 Golang “log” 库
|
||||
|
||||
Golang 给你提供了一个称为 “log” 的原生[日志库][3] 。它的日志器完美适用于追踪简单的活动,例如通过使用可用的[选项][4]在错误信息之前添加一个时间戳。
|
||||
|
||||
下面是一个 Golang 中如何记录错误日志的简单例子:
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
/* 定义局部变量 */
|
||||
...
|
||||
|
||||
/* 除法函数,除以 0 的时候会返回错误 */
|
||||
ret,err = div(a, b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(ret)
|
||||
}
|
||||
```
|
||||
|
||||
如果你尝试除以 0,你就会得到类似下面的结果:
|
||||
|
||||
![golang 代码](https://logmatic.io/wp-content/uploads/2017/03/golang-code.png)
|
||||
|
||||
为了快速测试一个 Golang 函数,你可以使用 [go playground][5]。
|
||||
|
||||
为了确保你的日志总是能轻易访问,我们建议你把它们写到一个文件:
|
||||
|
||||
```
|
||||
package main
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
func main() {
|
||||
// 按照所需读写权限创建文件
|
||||
f, err := os.OpenFile("filename", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// 完成后延迟关闭,而不是习惯!
|
||||
defer f.Close()
|
||||
//设置日志输出到 f
|
||||
log.SetOutput(f)
|
||||
//测试用例
|
||||
log.Println("check to make sure it works")
|
||||
}
|
||||
```
|
||||
|
||||
你可以在[这里][6]找到 Golang 日志的完整指南,以及 “log” [库][7]内可用函数的完整列表。
|
||||
|
||||
现在你就可以记录它们的错误以及根本原因啦。
|
||||
|
||||
另外,日志也可以帮你将活动流拼接在一起,查找需要修复的错误上下文,或者调查在你的系统中单个请求如何影响其它应用层和 API。
|
||||
|
||||
为了获得更好的日志效果,你首先需要在你的项目中使用尽可能多的上下文丰富你的 Golang 日志,并标准化你使用的格式。这就是 Golang 原生库能达到的极限。使用最广泛的库是 [glog][8] 和 [logrus][9]。必须承认还有很多好的库可以使用。如果你已经在使用支持 JSON 格式的库,你就不需要再换其它库了,后面我们会解释。
|
||||
|
||||
### II. 为你 Golang 日志统一格式
|
||||
|
||||
#### 1) JSON 格式的结构优势
|
||||
|
||||
在一个项目或者多个微服务中结构化你的 Golang 日志可能是最困难的事情,但一旦完成就很轻松了。结构化你的日志能使机器可读(参考我们 [收集日志的最佳实践博文][10])。灵活性和层级是 JSON 格式的核心,因此信息能够轻易被人类和机器解析以及处理。
|
||||
|
||||
下面是一个使用 [Logrus/Logmatic.io][11] 如何用 JSON 格式记录日志的例子:
|
||||
|
||||
```
|
||||
package main
|
||||
import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/logmatic/logmatic-go"
|
||||
)
|
||||
func main() {
|
||||
// 使用 JSONFormatter
|
||||
log.SetFormatter(&logmatic.JSONFormatter{})
|
||||
// 使用 logrus 像往常那样记录事件
|
||||
log.WithFields(log.Fields{"string": "foo", "int": 1, "float": 1.1 }).Info("My first ssl event from golang")
|
||||
}
|
||||
```
|
||||
|
||||
会输出结果:
|
||||
|
||||
```
|
||||
{
|
||||
"date":"2016-05-09T10:56:00+02:00",
|
||||
"float":1.1,
|
||||
"int":1,
|
||||
"level":"info",
|
||||
"message":"My first ssl event from golang",
|
||||
"String":"foo"
|
||||
}
|
||||
```
|
||||
|
||||
#### 2) 标准化 Golang 日志
|
||||
|
||||
同一个错误出现在你代码的不同部分,却以不同形式被记录下来是一件可耻的事情。下面是一个由于一个变量错误导致无法确定 web 页面加载状态的例子。一个开发者日志格式是:
|
||||
|
||||
```
|
||||
message: 'unknown error: cannot determine loading status from unknown error: missing or invalid arg value client'</span>
|
||||
```
|
||||
|
||||
另一个人的格式却是:
|
||||
|
||||
```
|
||||
unknown error: cannot determine loading status - invalid client</span>
|
||||
```
|
||||
|
||||
强制日志标准化的一个好的解决办法是在你的代码和日志库之间创建一个接口。这个标准化接口会包括所有你想添加到你日志中的可能行为的预定义日志消息。这么做可以防止出现不符合你想要的标准格式的自定义日志信息。这么做也便于日志调查。
|
||||
|
||||
![接口函数](https://logmatic.io/wp-content/uploads/2017/03/functions-interface.png)
|
||||
|
||||
由于日志格式都被统一处理,使它们保持更新也变得更加简单。如果出现了一种新的错误类型,它只需要被添加到一个接口,这样每个组员都会使用完全相同的信息。
|
||||
|
||||
最常使用的简单例子就是在 Golang 日志信息前面添加日志器名称和 id。你的代码然后就会发送 “事件” 到你的标准化接口,它会继续讲它们转化为 Golang 日志消息。
|
||||
|
||||
```
|
||||
// 主要部分,我们会在这里定义所有消息。
|
||||
// Event 结构体很简单。为了当所有信息都被记录时能检索它们,
|
||||
// 我们维护了一个 Id
|
||||
var (
|
||||
invalidArgMessage = Event{1, "Invalid arg: %s"}
|
||||
invalidArgValueMessage = Event{2, "Invalid arg value: %s => %v"}
|
||||
missingArgMessage = Event{3, "Missing arg: %s"}
|
||||
)
|
||||
|
||||
// 在我们应用程序中可以使用的所有日志事件
|
||||
func (l *Logger)InvalidArg(name string) {
|
||||
l.entry.Errorf(invalidArgMessage.toString(), name)
|
||||
}
|
||||
func (l *Logger)InvalidArgValue(name string, value interface{}) {
|
||||
l.entry.WithField("arg." + name, value).Errorf(invalidArgValueMessage.toString(), name, value)
|
||||
}
|
||||
func (l *Logger)MissingArg(name string) {
|
||||
l.entry.Errorf(missingArgMessage.toString(), name)
|
||||
}
|
||||
```
|
||||
|
||||
因此如果我们使用前面例子中无效的参数值,我们就会得到相似的日志信息:
|
||||
|
||||
```
|
||||
time="2017-02-24T23:12:31+01:00" level=error msg="LoadPageLogger00003 - Missing arg: client - cannot determine loading status" arg.client=<nil> logger.name=LoadPageLogger
|
||||
```
|
||||
|
||||
JSON 格式如下:
|
||||
|
||||
```
|
||||
{"arg.client":null,"level":"error","logger.name":"LoadPageLogger","msg":"LoadPageLogger00003 - Missing arg: client - cannot determine loading status", "time":"2017-02-24T23:14:28+01:00"}
|
||||
```
|
||||
|
||||
### III. Golang 日志上下文的力量
|
||||
|
||||
现在 Golang 日志已经按照特定结构和标准格式记录,时间会决定需要添加哪些上下文以及相关信息。为了能从你的日志中抽取信息,例如追踪一个用户活动或者工作流,上下文和元数据的顺序非常重要。
|
||||
|
||||
例如在 logrus 库中可以按照下面这样使用 JSON 格式添加 `hostname`、`appname` 和 `session` 参数:
|
||||
|
||||
```
|
||||
// 对于元数据,通常做法是通过复用来重用日志语句中的字段。
|
||||
contextualizedLog := log.WithFields(log.Fields{
|
||||
"hostname": "staging-1",
|
||||
"appname": "foo-app",
|
||||
"session": "1ce3f6v"
|
||||
})
|
||||
contextualizedLog.Info("Simple event with global metadata")
|
||||
```
|
||||
|
||||
元数据可以视为 javascript 片段。为了更好地说明它们有多么重要,让我们看看几个 Golang 微服务中元数据的使用。你会清楚地看到是怎么在你的应用程序中跟踪用户的。这是因为你不仅需要知道一个错误发生了,还要知道是哪个实例以及什么模式导致了错误。假设我们有两个按顺序调用的微服务。上下文信息保存在头部(header)中传输:
|
||||
|
||||
```
|
||||
func helloMicroService1(w http.ResponseWriter, r *http.Request) {
|
||||
client := &http.Client{}
|
||||
// 该服务负责接收所有到来的用户请求
|
||||
// 我们会检查是否是一个新的会话还是已有会话的另一次调用
|
||||
session := r.Header.Get("x-session")
|
||||
if ( session == "") {
|
||||
session = generateSessionId()
|
||||
// 为新会话记录日志
|
||||
}
|
||||
// 每个请求的 Track Id 都是唯一的,因此我们会为每个会话生成一个
|
||||
track := generateTrackId()
|
||||
// 调用你的第二个微服务,添加 session/track
|
||||
reqService2, _ := http.NewRequest("GET", "http://localhost:8082/", nil)
|
||||
reqService2.Header.Add("x-session", session)
|
||||
reqService2.Header.Add("x-track", track)
|
||||
resService2, _ := client.Do(reqService2)
|
||||
….
|
||||
```
|
||||
|
||||
当调用第二个服务时:
|
||||
|
||||
```
|
||||
func helloMicroService2(w http.ResponseWriter, r *http.Request) {
|
||||
// 类似之前的微服务,我们检查会话并生成新的 track
|
||||
session := r.Header.Get("x-session")
|
||||
track := generateTrackId()
|
||||
// 这一次,我们检查请求中是否已经设置了一个 track id,
|
||||
// 如果是,它变为父 track
|
||||
parent := r.Header.Get("x-track")
|
||||
if (session == "") {
|
||||
w.Header().Set("x-parent", parent)
|
||||
}
|
||||
// 为响应添加 meta 信息
|
||||
w.Header().Set("x-session", session)
|
||||
w.Header().Set("x-track", track)
|
||||
if (parent == "") {
|
||||
w.Header().Set("x-parent", track)
|
||||
}
|
||||
// 填充响应
|
||||
w.WriteHeader(http.StatusOK)
|
||||
io.WriteString(w, fmt.Sprintf(aResponseMessage, 2, session, track, parent))
|
||||
}
|
||||
```
|
||||
|
||||
现在第二个微服务中已经有和初始查询相关的上下文和信息,一个 JSON 格式的日志消息看起来类似如下。
|
||||
|
||||
在第一个微服务:
|
||||
|
||||
```
|
||||
{"appname":"go-logging","level":"debug","msg":"hello from ms 1","session":"eUBrVfdw","time":"2017-03-02T15:29:26+01:00","track":"UzWHRihF"}
|
||||
```
|
||||
|
||||
在第二个微服务:
|
||||
|
||||
```
|
||||
{"appname":"go-logging","level":"debug","msg":"hello from ms 2","parent":"UzWHRihF","session":"eUBrVfdw","time":"2017-03-02T15:29:26+01:00","track":"DPRHBMuE"}
|
||||
```
|
||||
|
||||
如果在第二个微服务中出现了错误,多亏了 Golang 日志中保存的上下文信息,现在我们就可以确定它是怎样被调用的以及什么模式导致了这个错误。
|
||||
|
||||
如果你想进一步深挖 Golang 的追踪能力,这里还有一些库提供了追踪功能,例如 [Opentracing][12]。这个库提供了一种简单的方式在或复杂或简单的架构中添加追踪的实现。它通过不同步骤允许你追踪用户的查询,就像下面这样:
|
||||
|
||||
![客户端事务](https://logmatic.io/wp-content/uploads/2017/03/client-transaction.png)
|
||||
|
||||
### IV. Golang 日志对性能的影响
|
||||
|
||||
#### 1) 不要在 Goroutine 中使用日志
|
||||
|
||||
在每个 goroutine 中创建一个新的日志器看起来很诱人。但最好别这么做。Goroutine 是一个轻量级线程管理器,它用于完成一个 “简单的” 任务。因此它不应该负责日志。它可能导致并发问题,因为在每个 goroutine 中使用 `log.New()` 会重复接口,所有日志器会并发尝试访问同一个 io.Writer。
|
||||
|
||||
为了限制对性能的影响以及避免并发调用 io.Writer,库通常使用一个特定的 goroutine 用于日志输出。
|
||||
|
||||
#### 2) 使用异步库
|
||||
|
||||
尽管有很多可用的 Golang 日志库,要注意它们中的大部分都是同步的(事实上是伪异步)。原因很可能是到现在为止它们中没有一个会由于日志严重影响性能。
|
||||
|
||||
但正如 Kjell Hedström 在[他的实验][13]中展示的,使用多个线程创建成千上万日志,即便是在最坏情况下,异步 Golang 日志也会有 40% 的性能提升。因此日志是有开销的,也会对你的应用程序性能产生影响。如果你并不需要处理大量的日志,使用伪异步 Golang 日志库可能就足够了。但如果你需要处理大量的日志,或者很关注性能,Kjell Hedström 的异步解决方案就很有趣(尽管事实上你可能需要进一步开发,因为它只包括了最小的功能需求)。
|
||||
|
||||
#### 3)使用严重等级管理 Golang 日志
|
||||
|
||||
一些日志库允许你启用或停用特定的日志器,这可能会派上用场。例如在生产环境中你可能不需要一些特定等级的日志。下面是一个如何在 glog 库中停用日志器的例子,其中日志器被定义为布尔值:
|
||||
|
||||
```
|
||||
type Log bool
|
||||
func (l Log) Println(args ...interface{}) {
|
||||
fmt.Println(args...)
|
||||
}
|
||||
var debug Log = false
|
||||
if debug {
|
||||
debug.Println("DEBUGGING")
|
||||
}
|
||||
```
|
||||
|
||||
然后你就可以在配置文件中定义这些布尔参数来启用或者停用日志器。
|
||||
|
||||
没有一个好的 Golang 日志策略,Golang 日志可能开销很大。开发人员应该抵制记录几乎所有事情的诱惑 - 尽管它非常有趣!如果日志的目的是为了获取尽可能多的信息,为了避免包含无用元素的日志的白噪音,必须正确使用日志。
|
||||
|
||||
### V. 集中化 Golang 日志
|
||||
|
||||
![集中化 go 日志](https://logmatic.io/wp-content/uploads/2017/03/source-selector-1024x460-1.png)
|
||||
|
||||
如果你的应用程序是部署在多台服务器上的,这样可以避免为了调查一个现象需要连接到每一台服务器的麻烦。日志集中确实有用。
|
||||
|
||||
使用日志装箱工具,例如 windows 中的 Nxlog,linux 中的 Rsyslog(默认安装了的)、Logstash 和 FluentD 是最好的实现方式。日志装箱工具的唯一目的就是发送日志,因此它们能够处理连接失效以及其它你很可能会遇到的问题。
|
||||
|
||||
这里甚至有一个 [Golang syslog 软件包][14] 帮你将 Golang 日志发送到 syslog 守护进程。
|
||||
|
||||
### 希望你享受你的 Golang 日志之旅
|
||||
|
||||
在你项目一开始就考虑你的 Golang 日志策略非常重要。如果在你代码的任意地方都可以获得所有的上下文,追踪用户就会变得很简单。从不同服务中阅读没有标准化的日志是已经很痛苦的事情。一开始就计划在多个微服务中扩展相同用户或请求 id,后面就会允许你比较容易地过滤信息并在你的系统中跟踪活动。
|
||||
|
||||
你是在构架一个很大的 Golang 项目还是几个微服务也会影响你的日志策略。一个大项目的主要组件应该有按照它们功能命名的特定 Golang 日志器。这使你可以立即判断出日志来自你的哪一部分代码。然而对于微服务或者小的 Golang 项目,只有较少的核心组件需要它们自己的日志器。但在每种情形中,日志器的数目都应该保持低于核心功能的数目。
|
||||
|
||||
你现在已经可以使用 Golang 日志量化决定你的性能或者用户满意度啦!
|
||||
|
||||
_如果你有想阅读的特定编程语言,在 Twitter [@logmatic][2] 上告诉我们吧。_
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://logmatic.io/blog/our-guide-to-a-golang-logs-world/
|
||||
|
||||
作者:[Nils][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://logmatic.io/blog/our-guide-to-a-golang-logs-world/
|
||||
[1]:https://twitter.com/logmatic?lang=en
|
||||
[2]:http://twitter.com/logmatic
|
||||
[3]:https://golang.org/pkg/log/
|
||||
[4]:https://golang.org/pkg/log/#pkg-constants
|
||||
[5]:https://play.golang.org/
|
||||
[6]:https://www.goinggo.net/2013/11/using-log-package-in-go.html
|
||||
[7]:https://golang.org/pkg/log/
|
||||
[8]:https://github.com/google/glog
|
||||
[9]:https://github.com/sirupsen/logrus
|
||||
[10]:https://logmatic.io/blog/beyond-application-monitoring-discover-logging-best-practices/
|
||||
[11]:https://github.com/logmatic/logmatic-go
|
||||
[12]:https://github.com/opentracing/opentracing-go
|
||||
[13]:https://sites.google.com/site/kjellhedstrom2/g2log-efficient-background-io-processign-with-c11/g2log-vs-google-s-glog-performance-comparison
|
||||
[14]:https://golang.org/pkg/log/syslog/
|
@ -1,10 +1,9 @@
|
||||
Integrate Ubuntu 16.04 to AD as a Domain Member with Samba and Winbind – Part 8
|
||||
Samba 系列(八):使用 Samba 和 Winbind 将 Ubuntu 16.04 添加到 AD 域
|
||||
============================================================
|
||||
使用 Samba 和 Winbind 将 Ubuntu 16.04 添加到 AD 域 ——(八)
|
||||
|
||||
这篇文章讲述了如何将 Ubuntu 主机加入到 Samba4 AD 域,并实现使用域帐号登录 Ubuntu 系统。
|
||||
|
||||
#### 要求:
|
||||
### 要求:
|
||||
|
||||
1. [在 Ubuntu 系统上使用 Samba4 软件来创建活动目录架构][1]
|
||||
|
||||
@ -12,7 +11,7 @@ Integrate Ubuntu 16.04 to AD as a Domain Member with Samba and Winbind – Part
|
||||
|
||||
1、在将 Ubuntu 主机加入到 AD DC 之前,你得先确保 Ubuntu 系统中的一些服务配置正常。
|
||||
|
||||
主机名是你的机器的一个重要标识。因此,在加入域前,使用 hostnamectl 命令或者通过手动编辑 /etc/hostname 文件来为 Ubuntu 主机设置一个合适的主机名。
|
||||
主机名是你的机器的一个重要标识。因此,在加入域前,使用 `hostnamectl` 命令或者通过手动编辑 `/etc/hostname` 文件来为 Ubuntu 主机设置一个合适的主机名。
|
||||
|
||||
```
|
||||
# hostnamectl set-hostname your_machine_short_name
|
||||
@ -23,32 +22,32 @@ Integrate Ubuntu 16.04 to AD as a Domain Member with Samba and Winbind – Part
|
||||
![Set System Hostname](http://www.tecmint.com/wp-content/uploads/2017/03/Set-Ubuntu-System-Hostname.png)
|
||||
][2]
|
||||
|
||||
设置系统主机名
|
||||
*设置系统主机名*
|
||||
|
||||
2、在这一步中,打开并编辑网卡配置文件,为你的主机设置一个合适的 IP 地址。注意把 DNS 地址设置为你的域控制器的地址。
|
||||
|
||||
编辑 /etc/network/interfaces 文件,添加 dns-nameservers 参数,并设置为 AD 服务器的 IP 地址,添加 dns-search 参数,其值为域控制器的主机名,如下图所示。
|
||||
编辑 `/etc/network/interfaces` 文件,添加 `dns-nameservers` 参数,并设置为 AD 服务器的 IP 地址;添加 `dns-search` 参数,其值为域控制器的主机名,如下图所示。
|
||||
|
||||
并且,把上面设置的 DNS IP 地址和域名添加到 /etc/resolv.conf 配置文件中,如下图所示:
|
||||
并且,把上面设置的 DNS IP 地址和域名添加到 `/etc/resolv.conf` 配置文件中,如下图所示:
|
||||
|
||||
[
|
||||
![Configure Network Settings for AD](http://www.tecmint.com/wp-content/uploads/2017/03/Configure-Network-Settings-for-AD.png)
|
||||
][3]
|
||||
|
||||
为 AD 配置网络设置
|
||||
*为 AD 配置网络设置*
|
||||
|
||||
在上面的截图中, 192.168.1.254 和 192.168.1.253 是 Samba4 AD DC 服务器的 IP 地址, Tecmint.lan 是 AD 域名,已加入到这个域中的所有机器都可以查询到该域名。
|
||||
在上面的截图中, `192.168.1.254` 和 `192.168.1.253` 是 Samba4 AD DC 服务器的 IP 地址, `Tecmint.lan` 是 AD 域名,已加入到这个域中的所有机器都可以查询到该域名。
|
||||
|
||||
3、重启网卡服务或者重启计算机以使网卡配置生效。使用 ping 命令加上域名来检测 DNS 解析是否正常。
|
||||
|
||||
AD DC 应该返回的 FQDN 。如果你的网络中配置了 DHCP 服务器来为局域网中的计算机自动分配 IP 地址,请确保你已经把 AD DC 服务器的 IP 地址添加到 DHCP 服务器的 DNS 配置中。
|
||||
AD DC 应该返回的是 FQDN 。如果你的网络中配置了 DHCP 服务器来为局域网中的计算机自动分配 IP 地址,请确保你已经把 AD DC 服务器的 IP 地址添加到 DHCP 服务器的 DNS 配置中。
|
||||
|
||||
```
|
||||
# systemctl restart networking.service
|
||||
# ping -c2 your_domain_name
|
||||
```
|
||||
|
||||
4、最后一步是配置服务器时间同步。安装 ntpdate 包,使用下面的命令来查询并同步 AD DC 服务器的时间。
|
||||
4、最后一步是配置服务器时间同步。安装 `ntpdate` 包,使用下面的命令来查询并同步 AD DC 服务器的时间。
|
||||
|
||||
```
|
||||
$ sudo apt-get install ntpdate
|
||||
@ -59,7 +58,7 @@ $ sudo ntpdate your_domain_name
|
||||
![Time Synchronization with AD](http://www.tecmint.com/wp-content/uploads/2017/03/Time-Synchronization-with-AD.png)
|
||||
][4]
|
||||
|
||||
AD 服务器时间同步
|
||||
*AD 服务器时间同步*
|
||||
|
||||
5、下一步,在 Ubuntu 机器上执行下面的命令来安装加入域环境所必需软件。
|
||||
|
||||
@ -70,7 +69,7 @@ $ sudo apt-get install samba krb5-config krb5-user winbind libpam-winbind libnss
|
||||
![Install Samba4 in Ubuntu Client](http://www.tecmint.com/wp-content/uploads/2017/03/Install-Samba4-in-Ubuntu-Client.png)
|
||||
][5]
|
||||
|
||||
在 Ubuntu 机器上安装 Samba4 软件
|
||||
*在 Ubuntu 机器上安装 Samba4 软件*
|
||||
|
||||
在 Kerberos 软件包安装的过程中,你会被询问输入默认的域名。输入大写的域名,并按 Enter 键继续安装。
|
||||
|
||||
@ -78,7 +77,7 @@ $ sudo apt-get install samba krb5-config krb5-user winbind libpam-winbind libnss
|
||||
![Add AD Domain Name](http://www.tecmint.com/wp-content/uploads/2017/03/Add-AD-Domain-Name.png)
|
||||
][6]
|
||||
|
||||
添加 AD 域名
|
||||
*添加 AD 域名*
|
||||
|
||||
6、当所有的软件包安装完成之后,使用域管理员帐号来测试 Kerberos 认证,然后执行下面的命令来列出票据信息。
|
||||
|
||||
@ -90,7 +89,7 @@ $ sudo apt-get install samba krb5-config krb5-user winbind libpam-winbind libnss
|
||||
![Check Kerberos Authentication with AD](http://www.tecmint.com/wp-content/uploads/2017/03/Check-Kerberos-Authentication-with-AD.png)
|
||||
][7]
|
||||
|
||||
使用 AD 来检查 Kerberos 认证是否正常
|
||||
*使用 AD 来检查 Kerberos 认证是否正常*
|
||||
|
||||
### 第二步:将 Ubuntu 主机添加到 Samba4 AD DC
|
||||
|
||||
@ -129,11 +128,11 @@ store dos attributes = Yes
|
||||
![Configure Samba for AD](http://www.tecmint.com/wp-content/uploads/2017/03/Configure-Samba.png)
|
||||
][8]
|
||||
|
||||
Samba 服务的 AD 环境配置
|
||||
*Samba 服务的 AD 环境配置*
|
||||
|
||||
根据你本地的实际情况来替换 workgroup , realm , netbios name 和 dns forwarder 的参数值。
|
||||
根据你本地的实际情况来替换 `workgroup` , `realm` , `netbios name` 和 `dns forwarder` 的参数值。
|
||||
|
||||
由于 winbind use default domain 这个参数会让 winbind 服务把任何登录系统的帐号都当作 AD 帐号。因此,如果存在本地帐号名跟域帐号同名的情况下,请不要设置该参数。
|
||||
由于 `winbind use default domain` 这个参数会让 winbind 服务把任何登录系统的帐号都当作 AD 帐号。因此,如果存在本地帐号名跟域帐号同名的情况下,请不要设置该参数。
|
||||
|
||||
8、现在,你应该重启 Samba 后台服务,停止并卸载一些不必要的服务,然后启用 samba 服务的 system-wide 功能,使用下面的命令来完成。
|
||||
|
||||
@ -153,7 +152,7 @@ $ sudo net ads join -U ad_admin_user
|
||||
![Join Ubuntu to Samba4 AD DC](http://www.tecmint.com/wp-content/uploads/2017/03/Join-Ubuntu-to-Samba4-AD-DC.png)
|
||||
][9]
|
||||
|
||||
把 Ubuntu 主机加入到 Samba4 AD DC
|
||||
*把 Ubuntu 主机加入到 Samba4 AD DC*
|
||||
|
||||
10、在 [安装了 RSAT 工具的 Windows 机器上][10] 打开 AD UC ,展开到包含的计算机。你可以看到已加入域的 Ubuntu 计算机。
|
||||
|
||||
@ -161,7 +160,7 @@ $ sudo net ads join -U ad_admin_user
|
||||
![Confirm Ubuntu Client in Windows AD DC](http://www.tecmint.com/wp-content/uploads/2017/03/Confirm-Ubuntu-Client-in-RSAT-.png)
|
||||
][11]
|
||||
|
||||
确认 Ubuntu 计算机已加入到 Windows AD DC
|
||||
*确认 Ubuntu 计算机已加入到 Windows AD DC*
|
||||
|
||||
### 第三步:配置 AD 帐号认证
|
||||
|
||||
@ -173,7 +172,7 @@ $ sudo net ads join -U ad_admin_user
|
||||
$ sudo nano /etc/nsswitch.conf
|
||||
```
|
||||
|
||||
然后在 passwd 和 group 行添加 winbind 值,如下图所示:
|
||||
然后在 `passwd` 和 `group` 行添加 winbind 值,如下图所示:
|
||||
|
||||
```
|
||||
passwd: compat winbind
|
||||
@ -183,9 +182,9 @@ group: compat winbind
|
||||
![Configure AD Accounts Authentication](http://www.tecmint.com/wp-content/uploads/2017/03/Configure-AD-Accounts-Authentication.png)
|
||||
][12]
|
||||
|
||||
配置 AD 帐号认证
|
||||
*配置 AD 帐号认证*
|
||||
|
||||
12、为了测试 Ubuntu 机器是否已加入到域中,你可以使用 wbinfo 命令来列出域帐号和组。
|
||||
12、为了测试 Ubuntu 机器是否已加入到域中,你可以使用 `wbinfo` 命令来列出域帐号和组。
|
||||
|
||||
```
|
||||
$ wbinfo -u
|
||||
@ -195,9 +194,9 @@ $ wbinfo -g
|
||||
![List AD Domain Accounts and Groups](http://www.tecmint.com/wp-content/uploads/2017/03/List-AD-Domain-Accounts-and-Groups.png)
|
||||
][13]
|
||||
|
||||
列出域帐号和组
|
||||
*列出域帐号和组*
|
||||
|
||||
13、同时,使用 getent 命令加上管道符及 grep 参数来过滤指定域用户或组,以测试 Winbind nsswitch 模块是否运行正常。
|
||||
13、同时,使用 `getent` 命令加上管道符及 `grep` 参数来过滤指定域用户或组,以测试 Winbind nsswitch 模块是否运行正常。
|
||||
|
||||
```
|
||||
$ sudo getent passwd| grep your_domain_user
|
||||
@ -207,9 +206,9 @@ $ sudo getent group|grep 'domain admins'
|
||||
![Check AD Domain Users and Groups](http://www.tecmint.com/wp-content/uploads/2017/03/Check-AD-Domain-Users-and-Groups.png)
|
||||
][14]
|
||||
|
||||
检查 AD 域用户和组
|
||||
*检查 AD 域用户和组*
|
||||
|
||||
14、为了让域帐号在 Ubuntu 机器上完成认证登录,你需要使用 root 帐号运行 pam-auth-update 命令,然后勾选 winbind 服务所需的选项,以让每个域帐号首次登录时自动创建 home 目录。
|
||||
14、为了让域帐号在 Ubuntu 机器上完成认证登录,你需要使用 root 帐号运行 `pam-auth-update` 命令,然后勾选 winbind 服务所需的选项,以让每个域帐号首次登录时自动创建 home 目录。
|
||||
|
||||
查看所有的选项,按 ‘[空格]’键选中,单击 OK 以应用更改。
|
||||
|
||||
@ -220,9 +219,9 @@ $ sudo pam-auth-update
|
||||
![Authenticate Ubuntu with Domain Accounts](http://www.tecmint.com/wp-content/uploads/2017/03/Authenticate-Ubuntu-with-Domain-Accounts.png)
|
||||
][15]
|
||||
|
||||
使用域帐号登录 Ubuntu 主机
|
||||
*使用域帐号登录 Ubuntu 主机*
|
||||
|
||||
15、在 Debian 系统中,如果想让系统自动为登录的域帐号创建家目录,你需要手动编辑 /etc/pam.d/common-account 配置文件,并添加下面的内容。
|
||||
15、在 Debian 系统中,如果想让系统自动为登录的域帐号创建家目录,你需要手动编辑 `/etc/pam.d/common-account` 配置文件,并添加下面的内容。
|
||||
|
||||
```
|
||||
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
|
||||
@ -231,9 +230,9 @@ session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
|
||||
![Authenticate Debian with Domain Accounts](http://www.tecmint.com/wp-content/uploads/2017/03/Authenticate-Debian-with-Domain-Accounts.png)
|
||||
][16]
|
||||
|
||||
使用域帐号登录 Debian 系统
|
||||
*使用域帐号登录 Debian 系统*
|
||||
|
||||
16、为了让 AD 用户能够在 Linux 的命令行下修改密码,你需要打开 /etc/pam.d/common-password 配置文件,在 password 那一行删除 use_authtok 参数,如下图所示:
|
||||
16、为了让 AD 用户能够在 Linux 的命令行下修改密码,你需要打开 /etc/pam.d/common-password 配置文件,在 `password` 那一行删除 `use_authtok` 参数,如下图所示:
|
||||
|
||||
```
|
||||
password [success=1 default=ignore] pam_winbind.so try_first_pass
|
||||
@ -242,9 +241,9 @@ password [success=1 default=ignore] pam_winbind.so try_first_pass
|
||||
![Users Allowed to Change Password](http://www.tecmint.com/wp-content/uploads/2017/03/AD-Domain-Users-Change-Password.png)
|
||||
][17]
|
||||
|
||||
允许域帐号在 Linux 命令行下修改密码
|
||||
*允许域帐号在 Linux 命令行下修改密码*
|
||||
|
||||
17、要使用 Samba4 AD 帐号来登录 Ubuntu 主机,在 su - 后面加上域用户名即可。你还可以通过运行 id 命令来查看 AD 帐号的其它信息。
|
||||
17、要使用 Samba4 AD 帐号来登录 Ubuntu 主机,在 `su -` 后面加上域用户名即可。你还可以通过运行 `id` 命令来查看 AD 帐号的其它信息。
|
||||
|
||||
```
|
||||
$ su - your_ad_user
|
||||
@ -253,9 +252,9 @@ $ su - your_ad_user
|
||||
![Find AD User Information](http://www.tecmint.com/wp-content/uploads/2017/03/Find-AD-User-Information.png)
|
||||
][18]
|
||||
|
||||
查看 AD 用户信息
|
||||
*查看 AD 用户信息*
|
||||
|
||||
使用 [pwd 命令][19]来查看域帐号的当前目录,如果你想修改域帐号的密码,你可以使用 passwd 命令来完成。
|
||||
使用 [pwd 命令][19]来查看域帐号的当前目录,如果你想修改域帐号的密码,你可以使用 `passwd` 命令来完成。
|
||||
|
||||
18、如果想让域帐号在 ubuntu 机器上拥有 root 权限,你可以使用下面的命令来把 AD 帐号添加到 sudo 系统组中:
|
||||
|
||||
@ -263,15 +262,15 @@ $ su - your_ad_user
|
||||
$ sudo usermod -aG sudo your_domain_user
|
||||
```
|
||||
|
||||
登录域帐号登录到 Ubuntu 主机,然后运行 apt-get-update 命令来更新系统,以验证域账号是否拥有 root 权限。
|
||||
登录域帐号登录到 Ubuntu 主机,然后运行 `apt-get-update` 命令来更新系统,以验证域账号是否拥有 root 权限。
|
||||
|
||||
[
|
||||
![Add Sudo User Root Group](http://www.tecmint.com/wp-content/uploads/2017/03/Add-Sudo-User-Root-Group.png)
|
||||
][20]
|
||||
|
||||
给域帐号添加 root 权限
|
||||
*给域帐号添加 root 权限*
|
||||
|
||||
19、要为整个域用户组添加 root 权限,使用 vi 命令打开并编辑 /etc/sudoers 配置文件,如下图所示,添加如下内容:
|
||||
19、要为整个域用户组添加 root 权限,使用 `vi` 命令打开并编辑 `/etc/sudoers` 配置文件,如下图所示,添加如下内容:
|
||||
|
||||
```
|
||||
%YOUR_DOMAIN\\your_domain\ group ALL=(ALL:ALL) ALL
|
||||
@ -280,13 +279,13 @@ $ sudo usermod -aG sudo your_domain_user
|
||||
![Add Root Privileges to Domain Group](http://www.tecmint.com/wp-content/uploads/2017/03/Add-Root-Privileges-to-Domain-Group.jpg)
|
||||
][21]
|
||||
|
||||
为域帐号组添加 root 权限
|
||||
*为域帐号组添加 root 权限*
|
||||
|
||||
使用反斜杠来转义域用户组的名称中包含的空格,或者用来转义第一个反斜杠。在上面的例子中, TECMINT 域的域用户组的名字是 “domain admins" 。
|
||||
|
||||
前边的 `(%)` 表明我们指定是的用户组而不是用户名。
|
||||
前边的 `%` 表明我们指定是的用户组而不是用户名。
|
||||
|
||||
20、如果你使用的是图形界面的 Ubuntu 系统,并且你想使用域帐号来登录系统,你需要修改 LightDM 显示管理器,编辑 /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf 配置文件,添加下面的内容,然后重启系统才能生效。
|
||||
20、如果你使用的是图形界面的 Ubuntu 系统,并且你想使用域帐号来登录系统,你需要修改 LightDM 显示管理器,编辑 `/usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf` 配置文件,添加下面的内容,然后重启系统才能生效。
|
||||
|
||||
```
|
||||
greeter-show-manual-login=true
|
||||
@ -307,7 +306,7 @@ via: http://www.tecmint.com/join-ubuntu-to-active-directory-domain-member-samba-
|
||||
|
||||
作者:[Matei Cezar][a]
|
||||
译者:[rusking](https://github.com/rusking)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,68 @@
|
||||
买个 DDoS 服务干掉你的对手
|
||||
========================
|
||||
|
||||
> 随着物联网设备的普及,网络犯罪分子通过利用密码的缺陷而提供拒绝服务攻击。
|
||||
|
||||
![](http://images.techhive.com/images/article/2016/12/7606416730_e659cea89c_o-100698667-large.jpg)
|
||||
|
||||
随着物联网设备飞速发展,分布式拒绝服务(DDoS)攻击正在成为一种危险的趋势。就如 [DNS 服务商 Dyn 上年秋季之遭遇][3] 一样,黑客似乎瞄上了每个人,使用未保护的物联网设备来轰炸网络的做法正在抬头。
|
||||
|
||||
可雇佣的 DDoS 攻击的出现意味着即使是最不精通技术的人都能精准报复某些网站。就像在柜台前面买个东西一样方便,然后就可以彻底搞定一个公司。
|
||||
|
||||
根据 [Neustar][4] 的报告,四分之三的国际品牌、机构和公司都是 DDoS 攻击的受害者。[每天至少会发生 3700 起 DDoS 攻击][5]。
|
||||
|
||||
睿科网络公司(A10 Networks)网络运营总监 Chase Cunningham 说:“想要找个可用的物联网设备,你只需要在地下网站四处打听一下 Mirai 扫描器代码,一旦你找到了,你将能够利用在线的每一台设备来进行攻击”。
|
||||
|
||||
“或者你可以去一些类似 Shodan 的网站,然后简单的搜一下设备特定的请求。当你得到这些信息之后,你就可以将你所雇佣的 DDoS 工具配置正确的流量模拟器类型、指向正确的目标并发动攻击。”
|
||||
|
||||
“几乎所有东西都是可买卖的。”他补充道,“你可以购买一个 ‘stresser’,这就是个随便哪个会点按钮的人都会使用的 DDoS 僵尸网络。”
|
||||
|
||||
网络安全提供商 Imperva 说,用户只需要出几十美金,就可以快速发动攻击。有些公司在它们的网站上说它们的工具包含肉鸡负载和 CnC(命令与控制)文件。使用这些工具,那些有点想法的肉鸡大师(或者被称为 herders)就可以开始传播恶意软件,通过垃圾邮件、漏洞扫描程序、暴力攻击等来感染设备。
|
||||
|
||||
大部分 [stresser 和 booter][6] 都会有一个常见的、基于订阅服务的 SaaS(软件即服务)业务模式。来自 Incapsula 公司的 [Q2 2015 DDoS 报告][7] 显示,在 DDoS 上的月均每小时花费是 38 美元(规模较低的是 19.99 美元)。
|
||||
|
||||
![雇佣ddos服务](http://images.techhive.com/images/article/2017/03/ddos-hire-100713247-large.jpg)
|
||||
|
||||
“stresser 和 booter 只是新世界的一个副产品,这些可以扳倒企业和机构的服务只能运作在灰色领域”,Imperva 写道。
|
||||
|
||||
虽然成本不同,但是企业受到的[各种攻击,每次损失在 1.4 万美元到 235 万美元之间][8]。而且企业受到一次攻击后,[有 82% 的可能性会再次受到攻击][9]。
|
||||
|
||||
物联网洪水攻击(DoT,DDoS of Things)使用物联网设备建立的僵尸网络可造成非常大规模的 DDoS 攻击。物联网洪水攻击会利用成百上千的物联网设备攻击,无论是大型服务提供商还是企业,均无幸免。
|
||||
|
||||
“大部分讲究声誉的 DDoS 卖家都会将他们的工具配置为可修改的,这样你就可以轻松地设置攻击的类型。虽然我还没怎么看到有哪些可以‘付费的’物联网流量模拟器的选项,但我敢肯定就要有了。如果是我来搞这个服务,我是绝对会加入这个选项的。”Cunningham 如是说。
|
||||
|
||||
由 IDG 新闻服务的消息可知,要建造一个 DDoS 服务也是很简单的。通常黑客会租用 6 到 12 个左右的服务器,然后使用它们随意的攻击任何目标。去年十月下旬,HackForums.net [关闭][10]了他们的“服务器压力测试”版块,这个做法就是考虑到黑客可能通过使用他们每月十美元的服务建造可雇佣的 DDoS 服务。
|
||||
|
||||
同样地在十二月时,美国和欧洲的执法机构 [逮捕][11] 34个参与可雇佣的 DDoS 服务的嫌犯。
|
||||
|
||||
但是如果这很简单,怎么还没有经常发生攻击?
|
||||
|
||||
Cunningham 说这其实每时每刻都在发生,实际上每天每秒都在发生。他说:”你不知道它们的原因是因为大部分都是扰乱攻击,而不是大规模的、想要搞倒公司的攻击。“
|
||||
|
||||
他说,大部分的攻击平台只出售那些会让系统宕机一个小时或稍长一点的攻击。通常宕机一小时的攻击大概需要花费 15 到 50 美元。当然这得看平台,有些可能一小时就要花上百美元。
|
||||
|
||||
**减少这些攻击的解决方案是让用户把所有联网设备的出厂预置的密码改掉,然后还要禁用那些你不需要的功能。**
|
||||
|
||||
(题图:[Victor](https://www.flickr.com/photos/v1ctor/7606416730/))
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.csoonline.com/article/3180246/data-protection/hire-a-ddos-service-to-take-down-your-enemies.html
|
||||
|
||||
作者:[Ryan Francis][a]
|
||||
译者:[kenxx](https://github.com/kenxx)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.csoonline.com/author/Ryan-Francis/
|
||||
[1]:http://csoonline.com/article/3103122/security/how-can-you-detect-a-fake-ransom-letter.html#tk.cso-infsb
|
||||
[2]:https://www.incapsula.com/ddos/ddos-attacks/denial-of-service.html
|
||||
[3]:http://csoonline.com/article/3135986/security/ddos-attack-against-overwhelmed-despite-mitigation-efforts.html
|
||||
[4]:https://ns-cdn.neustar.biz/creative_services/biz/neustar/www/resources/whitepapers/it-security/ddos/2016-apr-ddos-report.pdf
|
||||
[5]:https://www.a10networks.com/resources/ddos-trends-report
|
||||
[6]:https://www.incapsula.com/ddos/booters-stressers-ddosers.html
|
||||
[7]:https://www.incapsula.com/blog/ddos-global-threat-landscape-report-q2-2015.html
|
||||
[8]:http://www.datacenterknowledge.com/archives/2016/05/13/number-of-costly-dos-related-data-center-outages-rising/
|
||||
[9]:http://www.networkworld.com/article/3064677/security/hit-by-ddos-you-will-likely-be-struck-again.html
|
||||
[10]:http://www.pcworld.com/article/3136730/hacking/hacking-forum-cuts-section-allegedly-linked-to-ddos-attacks.html
|
||||
[11]:http://www.pcworld.com/article/3149543/security/dozens-arrested-in-international-ddos-for-hire-crackdown.html
|
@ -0,0 +1,123 @@
|
||||
如何通过 OpenELEC 创建你自己的媒体中心
|
||||
======
|
||||
|
||||
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-media-center.jpg "How to Build Your Own Media Center with OpenELECs")
|
||||
|
||||
你是否曾经想要创建你自己的家庭影院系统?如果是的话,这里有一个为你准备的指南!在本篇文章中,我们将会介绍如何设置一个由 OpenELEC 以及 Kodi 驱动的家庭娱乐系统。我们将会介绍如何制作安装介质,哪些设备可以运行该软件,如何安装它,以及其他一切需要知道的事情等等。
|
||||
|
||||
### 选择一个设备
|
||||
|
||||
在开始设定媒体中心的软件前,你需要选择一个设备。OpenELEC 支持一系列设备。从一般的桌面设备到树莓派 2/3 等等。选择好设备以后,考虑一下你怎么访问 OpenELEC 系统中的媒体并让其就绪。
|
||||
|
||||
**注意: **OpenELEC 基于 Kodi,有许多方式加载一个可播放的媒体(比如 Samba 网络分享,外设,等等)。
|
||||
|
||||
### 制作安装磁盘
|
||||
|
||||
OpenELEC 安装磁盘需要一个 USB 存储器,且其至少有 1GB 的容量。这是安装该软件的唯一方式,因为开发者没有发布 ISO 文件。取而代之的是需要创建一个 IMG 原始文件。选择与你设备相关的链接并且[下载][10]原始磁盘镜像。当磁盘镜像下载完毕,打开一个终端,并且使用命令将数据从压缩包中解压出来。
|
||||
|
||||
**在Linux/macOS上**
|
||||
|
||||
```
|
||||
cd ~/Downloads
|
||||
gunzip -d OpenELEC*.img.gz
|
||||
```
|
||||
|
||||
**在Windows上**
|
||||
|
||||
下载 [7zip][11],安装它,然后解压压缩文件。
|
||||
|
||||
当原始的 .IMG 文件被解压后,下载 [Etcher USB creation tool][12],并且依据在界面上的指示来安装它并创建 USB 磁盘。
|
||||
|
||||
**注意:** 对于树莓派用户,Etcher 也支持将文件写入到 SD 卡中。
|
||||
|
||||
### 安装 OpenELEC
|
||||
|
||||
OpenELEC 安装进程可能是安装流程最简单的操作系统之一了。将 USB 设备加入,然后配置设备使其以 USB 方式启动。同样,这个过程也可以通过按 DEL 或者 F2 来替代。然而并不是所有的 BIOS 都是一样的,所以最好的方式就是看看手册什么的。
|
||||
|
||||
![openelec-installer-selection](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-installer-selection.png "openelec-installer-selection")
|
||||
|
||||
一旦进入 BIOS,修改设置使其从 USB 磁盘中直接加载。这将会允许电脑从 USB 磁盘中启动,这将会使你进入到 Syslinux 引导屏幕。在提示符中,键入 `installer`,然后按下回车键。
|
||||
|
||||
![openelec-installation-selection-menu](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-installation-selection-menu.png "openelec-installation-selection-menu")
|
||||
|
||||
默认情况下,快速安装选项已经是选中的。按回车键来开始安装。这将会使安装器跳转到磁盘选择界面。选择 OpenELEC 要被安装到的地方,然后按下回车键来开始安装过程。
|
||||
|
||||
![openelec-installation-in-progress](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-installation-in-progress.png "openelec-installation-in-progress")
|
||||
|
||||
一旦完成安装,重启系统并加载 OpenELEC。
|
||||
|
||||
### 配置 OpenELEC
|
||||
|
||||
![openelec-wireless-network-setup](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-wireless-network-setup.jpg "openelec-wireless-network-setup")
|
||||
|
||||
在第一次启动时,用户必须配置一些东西。如果你的媒体中心拥有一个无线网卡,OpenELEC 将会提示用户将其连接到一个热点上。选择一个列表中的网络并且输入密码。
|
||||
|
||||
![openelec-sharing-setup](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-sharing-setup.jpg "openelec-sharing-setup")
|
||||
|
||||
在下一步“<ruby>欢迎来到 OpenELEC<rt>Welcome to OpenELEC</rt></ruby>”屏上,用户必须配置不同的分享设置(SSH 以及 Samba)。建议你把这些设置开启,因为可以用命令行访问,这将会使得远程传输媒体文件变得很简单。
|
||||
|
||||
### 增加媒体
|
||||
|
||||
在 OpenELEC(Kodi)中增加媒体,首先选择你希望添加的媒体到的部分。以同样的流程,为照片、音乐等添加媒体。在这个指南中,我们将着重讲解添加视频。
|
||||
|
||||
![openelec-add-files-to-kodi](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-add-files-to-kodi.jpg "openelec-add-files-to-kodi")
|
||||
|
||||
点击在主页的“<ruby>视频<rt>Video</rt></ruby>”选项来进入视频页面。选择“<ruby>文件<rt>Files</rt></ruby>”选项,在下一个页面点击“<ruby>添加视频...<rt>Add videos…</rt></ruby>”,这将会使得用户进入Kodi 的添加媒体页面。在这个页面,你可以随意的添加媒体源了(包括内部和外部的)。
|
||||
|
||||
![openelec-add-media-source-kodi](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-add-media-source-kodi.jpg "openelec-add-media-source-kodi")
|
||||
|
||||
OpenELEC 会自动挂载外部的设备(像是 USB,DVD 碟片,等等),并且它可以通过浏览文件挂载点来挂载。一般情况下,这些设备都会被放在“/run”下,或者,返回你点击“<ruby>添加视频...<rt>Add videos…</rt></ruby>”的页面,在那里选择设备。任何外部设备,包括 DVD/CD,将会直接展示在那里,并可以直接访问。这是一个很好的选择——对于那些不懂如何找到挂载点的用户。
|
||||
|
||||
![openelec-name-video-source-folder](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-name-video-source-folder.jpg "openelec-name-video-source-folder")
|
||||
|
||||
现在这个设备在 Kodi 中被选中了,界面将会询问用户去浏览设备上私人文件夹,里面有私人文件——这一切都是在媒体中心文件浏览器工具下执行的。一旦找到了放置文件的文件夹,添加它,给予文件夹一个名字,然后按下 OK 按钮来保存它。
|
||||
|
||||
![openelec-show-added-media-kodi](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-show-added-media-kodi.jpg "openelec-show-added-media-kodi")
|
||||
|
||||
当一个用户浏览“<ruby>视频<rt>Videos</rt></ruby>”,他们将会看到可以点击的文件夹,这个文件夹中带有从外部设备添加的媒体。这些文件夹可以很容易地在系统上播放。
|
||||
|
||||
### 使用 OpenELec
|
||||
|
||||
当用户登录他们将会看见一个“主界面”,这个主界面有许多部分,用户可以点击它们并且进入,包括:图片,视频,音乐,程序等等。当悬停在这些部分的时候,子部分就会出现。例如,当悬停在“图片”上时,子部分”文件“以及”插件”就会出现。
|
||||
|
||||
![openelec-navigation-bar](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-navigation-bar.jpg "openelec-navigation-bar")
|
||||
|
||||
如果一个用户点击了一个部分中的子部分,例如“插件”,Kodi 插件选择就会出现。这个安装器将会允许用户浏览新的插件内容,来安装到这个子部分(像是图片关联插件,等等)或者启动一个已经存在的图片关联插件,当然,这个插件应该已经安装到系统上了。
|
||||
|
||||
此外,点击任何部分的文件子部分(例如视频)将会直接给显示用户该部分可用的文件。
|
||||
|
||||
### 系统设置
|
||||
|
||||
![openelec-system-settings](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2017/03/openelec-system-settings.jpg "openelec-system-settings")
|
||||
|
||||
Kodi 有丰富的设置区域。为了找到这些设置,使鼠标在右方悬停,目录选择器将会滚动右方并且显示”<ruby>系统<rt>System</rt></ruby>“。点击来打开全局系统设定区。
|
||||
|
||||
用户可以修改任何设置,从安装 Kodi 仓库的插件,到激活各种服务,到改变主题,甚至天气。如果想要退出设定区域并且返回主页面,点击右下方角落中的“home”图标。
|
||||
|
||||
### 结论
|
||||
|
||||
通过 OpenELEC 的安装和配置,你现在可以随意体验使用你自己的 Linux 支持的家庭影院系统。在所有的家庭影院系统 Linux 发行版中,这个是最用户友好的。请记住,尽管这个系统是以“OpenELEC”为名,但它运行着的是 Kodi ,并兼容任何 Kodi 的插件,工具以及程序。
|
||||
|
||||
------
|
||||
|
||||
via: https://www.maketecheasier.com/build-media-center-with-openelec/
|
||||
|
||||
作者:[Derrik Diener][a]
|
||||
译者:[svtter](https://github.com/svtter)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.maketecheasier.com/author/derrikdiener/
|
||||
[1]: https://www.maketecheasier.com/author/derrikdiener/
|
||||
[2]: https://www.maketecheasier.com/build-media-center-with-openelec/#comments
|
||||
[3]: https://www.maketecheasier.com/category/linux-tips/
|
||||
[4]: http://www.facebook.com/sharer.php?u=https%3A%2F%2Fwww.maketecheasier.com%2Fbuild-media-center-with-openelec%2F
|
||||
[5]: http://twitter.com/share?url=https%3A%2F%2Fwww.maketecheasier.com%2Fbuild-media-center-with-openelec%2F&text=How+to+Build+Your+Own+Media+Center+with+OpenELEC
|
||||
[6]: mailto:?subject=How%20to%20Build%20Your%20Own%20Media%20Center%20with%20OpenELEC&body=https%3A%2F%2Fwww.maketecheasier.com%2Fbuild-media-center-with-openelec%2F
|
||||
[7]: https://www.maketecheasier.com/permanently-disable-windows-defender-windows-10/
|
||||
[8]: https://www.maketecheasier.com/repair-mac-hard-disk-with-fsck/
|
||||
[9]: https://support.google.com/adsense/troubleshooter/1631343
|
||||
[10]: http://openelec.tv/get-openelec/category/1-openelec-stable-releases
|
||||
[11]: http://www.7-zip.org/
|
||||
[12]: https://etcher.io/
|
@ -1,15 +1,14 @@
|
||||
Join CentOS 7 Desktop to Samba4 AD as a Domain Member – Part 9
|
||||
Samba 系列(九):将 CentOS 7 桌面系统加入到 Samba4 AD 域环境中
|
||||
============================================================
|
||||
将 CentOS 7 桌面系统加入到 Samba4 AD 域环境中——(九)
|
||||
|
||||
这篇文章讲述了如何使用 Authconfig-gtk 工具将 CentOS 7 桌面系统加入到 Samba4 AD 域环境中,并使用域帐号登录到 CentOS 系统。
|
||||
|
||||
#### 要求
|
||||
### 要求
|
||||
|
||||
1、[在 Ubuntu 系统中使用 Samba4 创建活动目录架构][1]
|
||||
2、[CentOS 7.3 安装指南]][2]
|
||||
2、[CentOS 7.3 安装指南][2]
|
||||
|
||||
### 第一步:在 CentOS 系统中配置 Samba4 AD DC Step 1: Configure CentOS Network for Samba4 AD DC
|
||||
### 第一步:在 CentOS 系统中配置 Samba4 AD DC
|
||||
|
||||
1、在将 CentOS 7 加入到 Samba4 域环境之前,你得先配置 CentOS 系统的网络环境,确保在 CentOS 系统中通过 DNS 可以解析到域名。
|
||||
|
||||
@ -21,13 +20,13 @@ Join CentOS 7 Desktop to Samba4 AD as a Domain Member – Part 9
|
||||
![Network Settings](http://www.tecmint.com/wp-content/uploads/2017/03/Network-Settings.jpg)
|
||||
][3]
|
||||
|
||||
网络设置
|
||||
*网络设置*
|
||||
|
||||
[
|
||||
![Configure Network](http://www.tecmint.com/wp-content/uploads/2017/03/Configure-Network.jpg)
|
||||
][4]
|
||||
|
||||
配置网络
|
||||
*配置网络*
|
||||
|
||||
2、下一步,打开网络配置文件,在文件末尾添加一行域名信息。这样能确保当你仅使用主机名来查询域中的 DNS 记录时, DNS 解析器会自动把域名添加进来。
|
||||
|
||||
@ -44,7 +43,7 @@ SEARCH="your_domain_name"
|
||||
![Network Interface Configuration](http://www.tecmint.com/wp-content/uploads/2017/03/Network-Interface-Configuration.jpg)
|
||||
][5]
|
||||
|
||||
网卡配置
|
||||
*网卡配置*
|
||||
|
||||
3、最后,重启网卡服务以应用更改,并验证解析器的配置文件是否正确配置。我们通过使用 ping 命令加上 DC 服务器的主机名或域名以验证 DNS 解析能否正常运行。
|
||||
|
||||
@ -54,12 +53,13 @@ $ cat /etc/resolv.conf
|
||||
$ ping -c1 adc1
|
||||
$ ping -c1 adc2
|
||||
$ ping tecmint.lan
|
||||
```
|
||||
```
|
||||
|
||||
[
|
||||
![Verify Network Configuration](http://www.tecmint.com/wp-content/uploads/2017/03/Verify-Network-Configuration.jpg)
|
||||
][6]
|
||||
|
||||
验证网络配置是否正常
|
||||
*验证网络配置是否正常*
|
||||
|
||||
4、同时,使用下面的命令来配置你的主机名,然后重启计算机以应用更改:
|
||||
|
||||
@ -68,7 +68,7 @@ $ sudo hostnamectl set-hostname your_hostname
|
||||
$ sudo init 6
|
||||
```
|
||||
|
||||
使用下面的命令来验证主机名是否正确配置
|
||||
使用下面的命令来验证主机名是否正确配置:
|
||||
|
||||
```
|
||||
$ cat /etc/hostname
|
||||
@ -106,30 +106,30 @@ $ sudo authconfig-gtk
|
||||
|
||||
打开身份或认证配置页面:
|
||||
|
||||
* 用户帐号数据库 = 选择 Winbind
|
||||
* Winbind 域 = 你的域名
|
||||
* 安全模式 = ADS
|
||||
* Winbind ADS 域 = 你的域名.TLD
|
||||
* 域控制器 = 域控服务器的全域名
|
||||
* 默认Shell = /bin/bash
|
||||
* 用户帐号数据库 : 选择 Winbind
|
||||
* Winbind 域 : 你的域名
|
||||
* 安全模式 : ADS
|
||||
* Winbind ADS 域 : 你的域名.TLD
|
||||
* 域控制器 : 域控服务器的全域名
|
||||
* 默认Shell : /bin/bash
|
||||
* 勾选允许离线登录
|
||||
|
||||
[
|
||||
![Authentication Configuration](http://www.tecmint.com/wp-content/uploads/2017/03/Authentication-Configuration.jpg)
|
||||
][7]
|
||||
|
||||
域认证配置
|
||||
*域认证配置*
|
||||
|
||||
打开高级选项配置页面:
|
||||
|
||||
* 本地认证选项 = 支持指纹识别
|
||||
* 其它认证选项 = 用户首次登录创建家目录
|
||||
* 本地认证选项 : 支持指纹识别
|
||||
* 其它认证选项 : 用户首次登录创建家目录
|
||||
|
||||
[
|
||||
![Authentication Advance Configuration](http://www.tecmint.com/wp-content/uploads/2017/03/Authentication-Advance-Configuration.jpg)
|
||||
][8]
|
||||
|
||||
高级认证配置
|
||||
*高级认证配置*
|
||||
|
||||
9、修改完上面的配置之后,返回到身份或认证配置页面,点击加入域按钮,在弹出的提示框点保存即可。
|
||||
|
||||
@ -137,13 +137,13 @@ $ sudo authconfig-gtk
|
||||
![Identity and Authentication](http://www.tecmint.com/wp-content/uploads/2017/03/Identity-and-Authentication.jpg)
|
||||
][9]
|
||||
|
||||
身份和认证
|
||||
*身份和认证*
|
||||
|
||||
[
|
||||
![Save Authentication Configuration](http://www.tecmint.com/wp-content/uploads/2017/03/Save-Authentication-Configuration.jpg)
|
||||
][10]
|
||||
|
||||
保存认证配置
|
||||
*保存认证配置*
|
||||
|
||||
10、保存配置之后,系统将会提示你提供域管理员信息以将 CentOS 系统加入到域中。输入域管理员帐号及密码后点击 OK 按钮,加入域完成。
|
||||
|
||||
@ -151,15 +151,15 @@ $ sudo authconfig-gtk
|
||||
![Joining Winbind Domain](http://www.tecmint.com/wp-content/uploads/2017/03/Joining-Winbind-Domain.jpg)
|
||||
][11]
|
||||
|
||||
加入 Winbind 域环境
|
||||
*加入 Winbind 域环境*
|
||||
|
||||
11、另入域后,点击应用按钮以让配置生效,选择所有的 windows 并重启机器。
|
||||
11、加入域后,点击应用按钮以让配置生效,选择所有的 windows 并重启机器。
|
||||
|
||||
[
|
||||
![Apply Authentication Configuration](http://www.tecmint.com/wp-content/uploads/2017/03/Apply-Authentication-Configuration.jpg)
|
||||
][12]
|
||||
|
||||
应用认证配置
|
||||
*应用认证配置*
|
||||
|
||||
12、要验证 CentOS 是否已成功加入到 Samba4 AD DC 中,你可以在安装了 [RSAT 工具][13] 的 windows 机器上,打开 AD 用户和计算机工具,点击域中的计算机。
|
||||
|
||||
@ -169,7 +169,7 @@ $ sudo authconfig-gtk
|
||||
![Active Directory Users and Computers](http://www.tecmint.com/wp-content/uploads/2017/03/Active-Directory-Users-and-Computers.jpg)
|
||||
][14]
|
||||
|
||||
活动目录用户和计算机
|
||||
*活动目录用户和计算机*
|
||||
|
||||
### 第四步:使用 Samba4 AD DC 帐号登录 CentOS 桌面系统
|
||||
|
||||
@ -177,20 +177,20 @@ $ sudo authconfig-gtk
|
||||
|
||||
```
|
||||
Domain\domain_account
|
||||
or
|
||||
或
|
||||
Domain_user@domain.tld
|
||||
```
|
||||
[
|
||||
![Not listed Users](http://www.tecmint.com/wp-content/uploads/2017/03/Not-listed-Users.jpg)
|
||||
][15]
|
||||
|
||||
使用其它账户
|
||||
*使用其它账户*
|
||||
|
||||
[
|
||||
![Enter Domain Username](http://www.tecmint.com/wp-content/uploads/2017/03/Enter-Domain-Username.jpg)
|
||||
][16]
|
||||
|
||||
输入域用户名
|
||||
*输入域用户名*
|
||||
|
||||
14、在 CentOS 系统的命令行中,你也可以使用下面的任一方式来切换到域帐号进行登录:
|
||||
|
||||
@ -202,15 +202,15 @@ $ su - domain_user@domain.tld
|
||||
![Authenticate Domain Username](http://www.tecmint.com/wp-content/uploads/2017/03/Authenticate-Domain-User.jpg)
|
||||
][17]
|
||||
|
||||
使用域帐号登录
|
||||
*使用域帐号登录*
|
||||
|
||||
[
|
||||
![Authenticate Domain User Email](http://www.tecmint.com/wp-content/uploads/2017/03/Authenticate-Domain-User-Email.jpg)
|
||||
][18]
|
||||
|
||||
使用域帐号邮箱登录
|
||||
*使用域帐号邮箱登录*
|
||||
|
||||
15、要为域用户或组添加 root 权限,在命令行下使用 root 权限帐号打开 sudoers 配置文件,添加下面一行内容:
|
||||
15、要为域用户或组添加 root 权限,在命令行下使用 root 权限帐号打开 `sudoers` 配置文件,添加下面一行内容:
|
||||
|
||||
```
|
||||
YOUR_DOMAIN\\domain_username ALL=(ALL:ALL) ALL #For domain users
|
||||
@ -220,7 +220,7 @@ YOUR_DOMAIN\\domain_username ALL=(ALL:ALL) ALL #For domain users
|
||||
![Assign Permission to User and Group](http://www.tecmint.com/wp-content/uploads/2017/03/Assign-Permission-to-User-and-Group.jpg)
|
||||
][19]
|
||||
|
||||
指定用户和用户组权限
|
||||
*指定用户和用户组权限*
|
||||
|
||||
16、使用下面的命令来查看域控制器信息:
|
||||
|
||||
@ -231,7 +231,7 @@ $ sudo net ads info
|
||||
![Check Domain Controller Info](http://www.tecmint.com/wp-content/uploads/2017/03/Check-Domain-Controller-Info.jpg)
|
||||
][20]
|
||||
|
||||
查看域控制器信息
|
||||
*查看域控制器信息*
|
||||
|
||||
17、你可以在安装了 Winbind 客户端的机器上使用下面的命令来验证 CentOS 加入到 Samba4 AD DC 后的信任关系是否正常:
|
||||
|
||||
@ -242,17 +242,17 @@ $ sudo yum install samba-winbind-clients
|
||||
然后,执行下面的一些命令来查看 Samba4 AD DC 的相关信息:
|
||||
|
||||
```
|
||||
$ wbinfo -p #Ping 域名
|
||||
$ wbinfo -t #检查信任关系
|
||||
$ wbinfo -u #列出域用户帐号
|
||||
$ wbinfo -g #列出域用户组
|
||||
$ wbinfo -n domain_account #查看域帐号的 SID 信息
|
||||
$ wbinfo -p ### Ping 域名
|
||||
$ wbinfo -t ### 检查信任关系
|
||||
$ wbinfo -u ### 列出域用户帐号
|
||||
$ wbinfo -g ### 列出域用户组
|
||||
$ wbinfo -n domain_account ### 查看域帐号的 SID 信息
|
||||
```
|
||||
[
|
||||
![Get Samba4 AD DC Details](http://www.tecmint.com/wp-content/uploads/2017/03/Get-Samba4-AD-DC-Details.jpg)
|
||||
][21]
|
||||
|
||||
查看 Samba4 AD DC 信息
|
||||
*查看 Samba4 AD DC 信息*
|
||||
|
||||
18、如果你想让 CentOS 系统退出域环境,使用具有管理员权限的帐号执行下面的命令,后面加上域名及域管理员帐号,如下图所示:
|
||||
|
||||
@ -263,7 +263,7 @@ $ sudo net ads leave your_domain -U domain_admin_username
|
||||
![Leave Domain from Samba4 AD](http://www.tecmint.com/wp-content/uploads/2017/03/Leave-Domain-from-Samba4-AD.jpg)
|
||||
][22]
|
||||
|
||||
退出 Samba4 AD 域
|
||||
*退出 Samba4 AD 域*
|
||||
|
||||
这篇文章就写到这里吧!尽管上面的这些操作步骤是将 CentOS 7 系统加入到 Samba4 AD DC 域中,其实这些步骤也同样适用于将 CentOS 7 桌面系统加入到 Microsoft Windows Server 2008 或 2012 的域中。
|
||||
|
||||
@ -279,14 +279,14 @@ via: http://www.tecmint.com/join-centos-7-to-samba4-active-directory/
|
||||
|
||||
作者:[Matei Cezar][a]
|
||||
译者:[rusking](https://github.com/rusking)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.tecmint.com/author/cezarmatei/
|
||||
|
||||
[1]:http://www.tecmint.com/install-samba4-active-directory-ubuntu/
|
||||
[2]:http://www.tecmint.com/centos-7-3-installation-guide/
|
||||
[1]:https://linux.cn/article-8065-1.html
|
||||
[2]:https://linux.cn/article-8048-1.html
|
||||
[3]:http://www.tecmint.com/wp-content/uploads/2017/03/Network-Settings.jpg
|
||||
[4]:http://www.tecmint.com/wp-content/uploads/2017/03/Configure-Network.jpg
|
||||
[5]:http://www.tecmint.com/wp-content/uploads/2017/03/Network-Interface-Configuration.jpg
|
||||
@ -297,7 +297,7 @@ via: http://www.tecmint.com/join-centos-7-to-samba4-active-directory/
|
||||
[10]:http://www.tecmint.com/wp-content/uploads/2017/03/Save-Authentication-Configuration.jpg
|
||||
[11]:http://www.tecmint.com/wp-content/uploads/2017/03/Joining-Winbind-Domain.jpg
|
||||
[12]:http://www.tecmint.com/wp-content/uploads/2017/03/Apply-Authentication-Configuration.jpg
|
||||
[13]:http://www.tecmint.com/manage-samba4-ad-from-windows-via-rsat/
|
||||
[13]:https://linux.cn/article-8097-1.html
|
||||
[14]:http://www.tecmint.com/wp-content/uploads/2017/03/Active-Directory-Users-and-Computers.jpg
|
||||
[15]:http://www.tecmint.com/wp-content/uploads/2017/03/Not-listed-Users.jpg
|
||||
[16]:http://www.tecmint.com/wp-content/uploads/2017/03/Enter-Domain-Username.jpg
|
@ -1,20 +1,11 @@
|
||||
如何在 Ubuntu 上使用 pm2 和 Nginx 部署 Node.js 应用
|
||||
============================================================
|
||||
|
||||
### 导航
|
||||
|
||||
1. [第一步 - 安装 Node.js][1]
|
||||
2. [第二步 - 生成 Express 事例 App][2]
|
||||
3. [第三步- 安装 pm2][3]
|
||||
4. [第四步 - 安装配置 Nginx 作为反向代理][4]
|
||||
5. [第五步 - 测试][5]
|
||||
6. [链接][6]
|
||||
|
||||
pm2 是一个 Node.js 应用的进程管理器,它允许你让你的应用程序保持运行,还有一个内建的负载均衡器。它非常简单而且强大,你可以零间断重启或重新加载你的 node 应用,它也允许你为你的 node 应用创建集群。
|
||||
|
||||
pm2 是一个 Node.js 应用的进程管理器,它可以让你的应用程序保持运行,还有一个内建的负载均衡器。它非常简单而且强大,你可以零间断重启或重新加载你的 node 应用,它也允许你为你的 node 应用创建集群。
|
||||
|
||||
在这篇博文中,我会向你展示如何安装和配置 pm2 用于这个简单的 'Express' 应用,然后配置 Nginx 作为运行在 pm2 下的 node 应用的反向代理。
|
||||
|
||||
**前提**
|
||||
前提:
|
||||
|
||||
* Ubuntu 16.04 - 64bit
|
||||
* Root 权限
|
||||
@ -23,50 +14,64 @@ pm2 是一个 Node.js 应用的进程管理器,它允许你让你的应用程
|
||||
|
||||
在这篇指南中,我们会从零开始我们的实验。首先,我们需要在服务器上安装 Node.js。我会使用 Nodejs LTS 6.x 版本,它能从 nodesource 仓库中安装。
|
||||
|
||||
从 Ubuntu 仓库安装 '**python-software-properties**' 软件包并添加 'nodesource' Nodejs 仓库。
|
||||
从 Ubuntu 仓库安装 `python-software-properties` 软件包并添加 “nodesource” Nodejs 仓库。
|
||||
|
||||
`sudo apt-get install -y python-software-properties`
|
||||
`curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -`
|
||||
```
|
||||
sudo apt-get install -y python-software-properties
|
||||
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
||||
```
|
||||
|
||||
安装最新版本的 Nodejs LTS
|
||||
安装最新版本的 Nodejs LTS:
|
||||
|
||||
`sudo apt-get install -y nodejs`
|
||||
```
|
||||
sudo apt-get install -y nodejs
|
||||
```
|
||||
|
||||
安装完成后,查看 node 和 npm 版本。
|
||||
|
||||
`node -v`
|
||||
`npm -v`
|
||||
```
|
||||
node -v
|
||||
npm -v
|
||||
```
|
||||
|
||||
[
|
||||
![检查 node.js 版本](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/1.png)
|
||||
][10]
|
||||
|
||||
### 第二步 - 生成 Express 事例 App
|
||||
### 第二步 - 生成 Express 示例 App
|
||||
|
||||
我会使用 **express-generator**' 软件包生成的简单 web 应用框架进行事例安装。Express-generator 可以使用 npm 命令安装。
|
||||
我会使用 `express-generator` 软件包生成的简单 web 应用框架进行示例安装。`express-generator` 可以使用 `npm` 命令安装。
|
||||
|
||||
用 npm 安装 '**express-generator**':
|
||||
用 `npm `安装 `express-generator`:
|
||||
|
||||
`npm install express-generator -g`
|
||||
```
|
||||
npm install express-generator -g
|
||||
```
|
||||
|
||||
**-g:** 在系统内部安装软件包
|
||||
- `-g` : 在系统内部安装软件包。
|
||||
|
||||
我会以普通用户运行应用程序,而不是 root 或者超级用户。我们首先需要创建一个新的用户。
|
||||
|
||||
创建一个名为 '**yume**' 的用户:
|
||||
创建一个名为 `yume` 的用户:
|
||||
|
||||
`useradd -m -s /bin/bash yume`
|
||||
`passwd yume`
|
||||
```
|
||||
useradd -m -s /bin/bash yume
|
||||
passwd yume
|
||||
```
|
||||
|
||||
使用 su 命令登录到新用户:
|
||||
使用 `su` 命令登录到新用户:
|
||||
|
||||
`su - yume`
|
||||
```
|
||||
su - yume
|
||||
```
|
||||
|
||||
下一步,用 express 命令生成一个新的简单 web 应用程序:
|
||||
下一步,用 `express` 命令生成一个新的简单 web 应用程序:
|
||||
|
||||
`express hakase-app`
|
||||
```
|
||||
express hakase-app
|
||||
```
|
||||
|
||||
命令会创建新项目目录 '**hakase-app**'。
|
||||
命令会创建新项目目录 `hakase-app`。
|
||||
|
||||
[
|
||||
![用 express-generator 生成应用框架](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/2.png)
|
||||
@ -74,47 +79,59 @@ pm2 是一个 Node.js 应用的进程管理器,它允许你让你的应用程
|
||||
|
||||
进入到项目目录并安装应用需要的所有依赖。
|
||||
|
||||
`cd hakase-app`
|
||||
`npm install`
|
||||
```
|
||||
cd hakase-app
|
||||
npm install
|
||||
```
|
||||
|
||||
然后用下面的命令测试并启动一个新的简单应用程序:
|
||||
|
||||
`DEBUG=myapp:* npm start`
|
||||
```
|
||||
DEBUG=myapp:* npm start
|
||||
```
|
||||
|
||||
默认情况下,我们的 express 应用汇运行在 **3000** 端口。现在访问服务器的 IP 地址:[192.168.33.10:3000][12]
|
||||
默认情况下,我们的 express 应用会运行在 `3000` 端口。现在访问服务器的 IP 地址:192.168.33.10:3000 :
|
||||
|
||||
[
|
||||
![express nodejs 运行在 3000 端口](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/3.png)
|
||||
][13]
|
||||
|
||||
简单 web 应用框架以 'yume' 用户运行在 3000 端口。
|
||||
这个简单 web 应用框架现在以 'yume' 用户运行在 3000 端口。
|
||||
|
||||
### 第三步 - 安装 pm2
|
||||
|
||||
pm2 是一个 node 软件包,可以使用 npm 命令安装。让我们用 npm 命令安装吧(用 root 权限,如果你仍然以 yume 用户登录,那么运行命令 "exit" 再次成为 root 用户):
|
||||
pm2 是一个 node 软件包,可以使用 `npm` 命令安装。(用 root 权限,如果你仍然以 yume 用户登录,那么运行命令 `exit` 再次成为 root 用户):
|
||||
|
||||
`npm install pm2 -g`
|
||||
```
|
||||
npm install pm2 -g
|
||||
```
|
||||
|
||||
现在我们可以为我们的 web 应用使用 pm2 了。
|
||||
|
||||
进入应用目录 '**hakase-app**':
|
||||
进入应用目录 `hakase-app`:
|
||||
|
||||
`su - yume`
|
||||
`cd ~/hakase-app/`
|
||||
```
|
||||
su - yume
|
||||
cd ~/hakase-app/
|
||||
```
|
||||
|
||||
这里你可以看到一个名为 '**package.json**' 的文件,用 cat 命令显示它的内容。
|
||||
这里你可以看到一个名为 `package.json` 的文件,用 `cat` 命令显示它的内容。
|
||||
|
||||
`cat package.json`
|
||||
```
|
||||
cat package.json
|
||||
```
|
||||
|
||||
[
|
||||
![配置 express nodejs 服务](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/4.png)
|
||||
][14]
|
||||
|
||||
你可以看到 '**start**' 行有一个 nodejs 用于启动 express 应用的命令。我们会和 pm2 进程管理器一起使用这个命令。
|
||||
你可以看到 `start` 行有一个 nodejs 用于启动 express 应用的命令。我们会和 pm2 进程管理器一起使用这个命令。
|
||||
|
||||
像下面这样使用 pm2 命令运行 express 应用:
|
||||
像下面这样使用 `pm2` 命令运行 express 应用:
|
||||
|
||||
`pm2 start ./bin/www`
|
||||
```
|
||||
pm2 start ./bin/www
|
||||
```
|
||||
|
||||
现在你可以看到像下面这样的结果:
|
||||
|
||||
@ -122,9 +139,11 @@ pm2 是一个 node 软件包,可以使用 npm 命令安装。让我们用 npm
|
||||
![使用 pm2 运行 nodejs app](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/5.png)
|
||||
][15]
|
||||
|
||||
我们的 express 应用正在 pm2 中运行,名称为 '**www**',id '**0**'。你可以用 show 选项 '**show nodeid|name**' 获取更多 pm2 下运行的应用的信息。
|
||||
我们的 express 应用正在 `pm2` 中运行,名称为 `www`,id 为 `0`。你可以用 show 选项 `show nodeid|name` 获取更多 pm2 下运行的应用的信息。
|
||||
|
||||
`pm2 show www`
|
||||
```
|
||||
pm2 show www
|
||||
```
|
||||
|
||||
[
|
||||
![pm2 服务状态](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/6.png)
|
||||
@ -132,7 +151,9 @@ pm2 是一个 node 软件包,可以使用 npm 命令安装。让我们用 npm
|
||||
|
||||
如果你想看我们应用的日志,你可以使用 logs 选项。它包括访问和错误日志,你还可以看到应用程序的 HTTP 状态。
|
||||
|
||||
`pm2 logs www`
|
||||
```
|
||||
pm2 logs www
|
||||
```
|
||||
|
||||
[
|
||||
![pm2 服务日志](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/7.png)
|
||||
@ -140,14 +161,17 @@ pm2 是一个 node 软件包,可以使用 npm 命令安装。让我们用 npm
|
||||
|
||||
你可以看到我们的程序正在运行。现在,让我们来让它开机自启动。
|
||||
|
||||
`pm2 startup systemd`
|
||||
```
|
||||
pm2 startup systemd
|
||||
```
|
||||
|
||||
**systemd**: Ubuntu 16 使用的是 systemd。
|
||||
- `systemd`: Ubuntu 16 使用的是 systemd。
|
||||
|
||||
你会看到要用 root 用户运行命令的信息。使用 "exit" 命令回到 root 用户然后运行命令。
|
||||
你会看到要用 root 用户运行命令的信息。使用 `exit` 命令回到 root 用户然后运行命令。
|
||||
|
||||
|
||||
`sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u yume --hp /home/yume`
|
||||
```
|
||||
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u yume --hp /home/yume
|
||||
```
|
||||
|
||||
它会为启动应用程序生成 systemd 配置文件。当你重启服务器的时候,应用程序就会自动运行。
|
||||
|
||||
@ -157,66 +181,73 @@ pm2 是一个 node 软件包,可以使用 npm 命令安装。让我们用 npm
|
||||
|
||||
### 第四步 - 安装和配置 Nginx 作为反向代理
|
||||
|
||||
在这篇指南中,我们会使用 Nginx 作为 node 应用的反向代理。Ubuntu 仓库中有 Nginx,用 apt 命令安装它:
|
||||
在这篇指南中,我们会使用 Nginx 作为 node 应用的反向代理。Ubuntu 仓库中有 Nginx,用 `apt` 命令安装它:
|
||||
|
||||
`sudo apt-get install -y nginx`
|
||||
```
|
||||
sudo apt-get install -y nginx
|
||||
```
|
||||
|
||||
下一步,进入到 '**sites-available**' 目录并创建新的虚拟 host 配置文件。
|
||||
下一步,进入到 `sites-available` 目录并创建新的虚拟主机配置文件。
|
||||
|
||||
`cd /etc/nginx/sites-available/`
|
||||
`vim hakase-app`
|
||||
```
|
||||
cd /etc/nginx/sites-available/
|
||||
vim hakase-app
|
||||
```
|
||||
|
||||
粘贴下面的配置:
|
||||
|
||||
upstream hakase-app {
|
||||
# Nodejs app upstream
|
||||
server 127.0.0.1:3000;
|
||||
keepalive 64;
|
||||
}
|
||||
|
||||
# Server on port 80
|
||||
server {
|
||||
listen 80;
|
||||
server_name hakase-node.co;
|
||||
root /home/yume/hakase-app;
|
||||
|
||||
location / {
|
||||
# Proxy_pass configuration
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_max_temp_file_size 0;
|
||||
proxy_pass http://hakase-app/;
|
||||
proxy_redirect off;
|
||||
proxy_read_timeout 240s;
|
||||
}
|
||||
}
|
||||
```
|
||||
upstream hakase-app {
|
||||
# Nodejs app upstream
|
||||
server 127.0.0.1:3000;
|
||||
keepalive 64;
|
||||
}
|
||||
|
||||
# Server on port 80
|
||||
server {
|
||||
listen 80;
|
||||
server_name hakase-node.co;
|
||||
root /home/yume/hakase-app;
|
||||
|
||||
location / {
|
||||
# Proxy_pass configuration
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_max_temp_file_size 0;
|
||||
proxy_pass http://hakase-app/;
|
||||
proxy_redirect off;
|
||||
proxy_read_timeout 240s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
保存文件并退出 vim。
|
||||
|
||||
在配置中:
|
||||
|
||||
* node 应用使用域名 '**hakase-node.co**' 运行。
|
||||
* 所有来自 nginx 的流量都会被转发到运行在 **3000** 端口的 node app。
|
||||
* node 应用使用域名 `hakase-node.co` 运行。
|
||||
* 所有来自 nginx 的流量都会被转发到运行在 `3000` 端口的 node app。
|
||||
|
||||
测试 Nginx 配置确保没有错误。
|
||||
|
||||
`nginx -t`
|
||||
```
|
||||
nginx -t
|
||||
```
|
||||
|
||||
启用 Nginx 并使其开机自启动。
|
||||
|
||||
`systemctl start nginx`
|
||||
`systemctl enable nginx`
|
||||
```
|
||||
systemctl start nginx
|
||||
systemctl enable nginx
|
||||
```
|
||||
|
||||
### 第五步 - 测试
|
||||
|
||||
打开你的 web 浏览器并访问域名(我的是):
|
||||
|
||||
[http://hakase-app.co][19]
|
||||
打开你的 web 浏览器并访问域名(我的是):[http://hakase-app.co][19]
|
||||
|
||||
你可以看到 express 应用正在 Nginx web 服务器中运行。
|
||||
|
||||
@ -226,13 +257,17 @@ pm2 是一个 node 软件包,可以使用 npm 命令安装。让我们用 npm
|
||||
|
||||
下一步,重启你的服务器,确保你的 node app 能开机自启动:
|
||||
|
||||
`pm2 save`
|
||||
`sudo reboot`
|
||||
```
|
||||
pm2 save
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
如果你再次登录到了你的服务器,检查 node app 进程。以 '**yume**' 用户运行下面的命令。
|
||||
如果你再次登录到了你的服务器,检查 node app 进程。以 `yume` 用户运行下面的命令。
|
||||
|
||||
`su - yume`
|
||||
`pm2 status www`
|
||||
```
|
||||
su - yume
|
||||
pm2 status www
|
||||
```
|
||||
|
||||
[
|
||||
![nodejs 在 pm2 下开机自启动](https://www.howtoforge.com/images/how_to_deploy_nodejs_applications_with_pm2_and_nginx_on_ubuntu/10.png)
|
||||
@ -250,9 +285,9 @@ Node 应用在 pm2 中运行并使用 Nginx 作为反向代理。
|
||||
|
||||
via: https://www.howtoforge.com/tutorial/how-to-deploy-nodejs-applications-with-pm2-and-nginx-on-ubuntu/
|
||||
|
||||
作者:[Muhammad Arul ][a]
|
||||
作者:[Muhammad Arul][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -5,40 +5,34 @@
|
||||
|
||||
|
||||
![How to deploy Kubernetes on the Raspberry Pi ](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/raspberrypi_cartoon.png?itok=sntNdheJ "How to deploy Kubernetes on the Raspberry Pi ")
|
||||
>图片提供: opensource.com
|
||||
|
||||
> 图片提供: opensource.com
|
||||
|
||||
当我开始对 [ARM][6]设备,特别是 Raspberry Pi 感兴趣时,我的第一个项目是一个 OpenVPN 服务器。
|
||||
|
||||
通过将 Raspberry Pi 作为家庭网络的安全网关,我可以使用我的手机来控制我的桌面,远程播放 Spotify,打开文档以及一些其他有趣的东西。我在第一个项目中使用了一个现有的教程,因为我害怕自己使用命令行。
|
||||
通过将 Raspberry Pi 作为家庭网络的安全网关,我可以使用我的手机来控制我的桌面,远程播放 Spotify,打开文档以及一些其他有趣的东西。我在第一个项目中使用了一个现有的教程,因为我害怕自己在命令行中拼砌。
|
||||
|
||||
更多关于 Raspberry Pi 的文章:
|
||||
|
||||
* [最新的 Raspberry Pi][1]
|
||||
* [什么是 Raspberry Pi?][2]
|
||||
* [开始使用 Raspberry Pi][3]
|
||||
* [给我们发送你的 Raspberry Pi 项目和教程][4]
|
||||
|
||||
几个月后,这种恐惧消失了。我扩展了我的原始项目,并使用[ Samba 服务器][7]从文件服务器隔离了 OpenVPN 服务器。这是我第一个没有完全按照教程来的项目。不幸的是,在我的 Samba 项目结束后,我意识到我没有记录任何东西,所以我无法复制它。为了重新创建它,我不得不重新参考我曾经用过的那些单独的教程,将项目拼回到一起。
|
||||
几个月后,这种恐惧消失了。我扩展了我的原始项目,并使用 [Samba 服务器][7]从文件服务器分离出了 OpenVPN 服务器。这是我第一个没有完全按照教程来的项目。不幸的是,在我的 Samba 项目结束后,我意识到我没有记录任何东西,所以我无法复制它。为了重新创建它,我不得不重新参考我曾经用过的那些单独的教程,将项目拼回到一起。
|
||||
|
||||
我学到了关于开发人员工作流程的宝贵经验 - 跟踪你所有的更改。我在本地做了一个小的 git 仓库,并记录了我输入的所有命令。
|
||||
|
||||
### 发现 Kubernetes
|
||||
|
||||
2015 年 5 月,我发现了 Linux 容器和 Kubernetes。我觉得 Kubernetes 很有魅力,我可以使用仍在技术上发展的概念 - 并且我实际上可以用它。平台本身及其所呈现的可能性令人兴奋。在此之前,我才刚刚在一块 Raspberry Pi 上运行了一个程序。有了 Kubernetes,我可以做出比以前更高级的配置。
|
||||
2015 年 5 月,我发现了 Linux 容器和 Kubernetes。我觉得 Kubernetes 很有魅力,我可以使用仍然处于技术发展的概念 - 并且我实际上可以用它。平台本身及其所呈现的可能性令人兴奋。在此之前,我才刚刚在一块 Raspberry Pi 上运行了一个程序。而有了 Kubernetes,我可以做出比以前更先进的配置。
|
||||
|
||||
那时候,Docker(v1.6 版本,如果我记得正确的话)在 ARM 上有一个 bug,这意味着在 Raspberry Pi 上运行 Kubernetes 实际上是不可能的。在早期的 0.x 版本中,Kubernetes 的变化很快。每次我在 AMD64 上找到一篇关于如何设置 Kubernetes 的指南时,它针对的还都是一个旧版本,与我当时使用的完全不兼容。
|
||||
|
||||
不管怎样,我用自己的方法在 Raspberry Pi 上创建了一个 Kubernetes 节点,而在 Kubernetes v1.0.1 中,我使用 Docker v1.7.1 [让它工作了][8]。这是第一个将 Kubernetes 全功能部署到 ARM 的方法。
|
||||
|
||||
在 Raspberry Pi 上运行 Kubernetes 的优势在于,由于 ARM 设备非常小巧,因此不会产生大量的功耗。如果程序以正确的方式构建,那么同样可以在 AMD64 上用同样的方法运行程序。有一块小型 IoT 板为教育创造了巨大的机会。用它来做演示也很有用,比如你要出差参加一个会议。携带 Raspberry Pi (通常)比拖着大型英特尔机器要容易得多。
|
||||
在 Raspberry Pi 上运行 Kubernetes 的优势在于,由于 ARM 设备非常小巧,因此不会产生大量的功耗。如果程序以正确的方式构建而成,那么就可以在 AMD64 上用同样的方法运行同一个程序。这样的一块小型 IoT 板为教育创造了巨大的机会。用它来做演示也很有用,比如你要出差参加一个会议。携带 Raspberry Pi (通常)比拖着大型英特尔机器要容易得多。
|
||||
|
||||
现在按照[我建议][9]的 ARM(32 位和 64 位)的支持已被合并到核心中。ARM 的二进制文件会自动与 Kubernetes 一起发布。虽然我们还没有为 ARM 提供自动化的 CI(持续集成)系统,在 PR 合并之前会自动确定它可在 ARM 上工作,它仍然工作得不错。
|
||||
现在按照[我建议][9]的 ARM(32 位和 64 位)的支持已被合并到 Kubernetes 核心中。ARM 的二进制文件会自动与 Kubernetes 一起发布。虽然我们还没有为 ARM 提供自动化的 CI(持续集成)系统,不过在 PR 合并之前会自动确定它可在 ARM 上工作,现在它运转得不错。
|
||||
|
||||
### Raspberry Pi 上的分布式网络
|
||||
|
||||
我通过 [kubeadm][10] 发现了 Weave Net。[Weave Mesh][11]是一个有趣的分布式网络解决方案,因此我开始阅读更多关于它的内容。在 2016 年 12 月,我在 [Weaveworks][12] 收到了第一份合同工作。我是 Weave Net 中 ARM 支持团队的一员。
|
||||
我通过 [kubeadm][10] 发现了 Weave Net。[Weave Mesh][11] 是一个有趣的分布式网络解决方案,因此我开始了解更多关于它的内容。在 2016 年 12 月,我在 [Weaveworks][12] 收到了第一份合同工作,我成为了 Weave Net 中 ARM 支持团队的一员。
|
||||
|
||||
我很高兴可以在 Raspberry Pi 上运行 Weave Net 的工业案例,比如那些需要更加移动化的工厂。目前,将 Weave Scope 或 Weave Cloud 部署到 Raspberry Pi 可能不太现实(尽管可以考虑使用其他 ARM 设备),因为我猜这个软件需要更多的内存才能运行良好。理想情况下,随着 Raspberry Pi 升级到 2GB 内存,我想我可以在它上面运行 Weave Cloud 了。
|
||||
我很高兴可以在 Raspberry Pi 上运行 Weave Net 的工业案例,比如那些需要设备更加移动化的工厂。目前,将 Weave Scope 或 Weave Cloud 部署到 Raspberry Pi 可能不太现实(尽管可以考虑使用其他 ARM 设备),因为我猜这个软件需要更多的内存才能运行良好。理想情况下,随着 Raspberry Pi 升级到 2GB 内存,我想我可以在它上面运行 Weave Cloud 了。
|
||||
|
||||
在 Weave Net 1.9 中,Weave Net 支持了 ARM。Kubeadm(通常是 Kubernetes)在多个平台上工作。你可以使用 Weave 将 Kubernetes 部署到 ARM,就像在任何 AMD64 设备上一样安装 Docker、kubeadm、kubectl 和 kubelet。然后初始化控制面板组件运行的主机:
|
||||
|
||||
@ -52,7 +46,7 @@ kubeadm init
|
||||
kubectl apply -f https://git.io/weave-kube
|
||||
```
|
||||
|
||||
在此之前在 ARM 上,你只可以用 Flannel 安装一个 pod 网络,但是在 Weave Net 1.9 中已经改变了,它官方支持了 ARM。
|
||||
在此之前在 ARM 上,你只能用 Flannel 安装 pod 网络,但是在 Weave Net 1.9 中已经改变了,它官方支持了 ARM。
|
||||
|
||||
最后,加入你的节点:
|
||||
|
||||
@ -84,7 +78,7 @@ Lucas Käldström - 谢谢你发现我!我是一名来自芬兰的说瑞典语
|
||||
|
||||
via: https://opensource.com/article/17/3/kubernetes-raspberry-pi
|
||||
|
||||
作者:[ Lucas Käldström][a]
|
||||
作者:[Lucas Käldström][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
@ -0,0 +1,111 @@
|
||||
AI 正快速入侵我们生活的五个方面
|
||||
============================================================
|
||||
|
||||
> 让我们来看看我们已经被人工智能包围的五个真实存在的方面。
|
||||
|
||||
![5 big ways AI is rapidly invading our lives](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/brain-think-ai-intelligence-ccby.png?itok=-EK6Vpz1 "5 big ways AI is rapidly invading our lives")
|
||||
|
||||
> 图片来源: opensource.com
|
||||
|
||||
开源项目[正在助推][2]人工智能(AI)进步,而且随着技术的成熟,我们将听到更多关于 AI 如何影响我们生活的消息。你有没有考虑过 AI 是如何改变你周围的世界的?让我们来看看我们日益被我们所改变的世界,以及大胆预测一下 AI 对未来影响。
|
||||
|
||||
### 1. AI 影响你的购买决定
|
||||
|
||||
最近 [VentureBeat][3] 上的一篇文章,[“AI 将如何帮助我们解读千禧一代”][4]吸引了我的注意。我承认我对人工智能没有思考太多,也没有费力尝试解读千禧一代,所以我很好奇,希望了解更多。事实证明,文章标题有点误导人,“如何卖东西给千禧一代”或许会是一个更准确的标题。
|
||||
|
||||
根据这篇文章,千禧一代是“一个令人垂涎的年龄阶段的人群,全世界的市场经理都在争抢他们”。通过分析网络行为 —— 无论是购物、社交媒体或其他活动 - 机器学习可以帮助预测行为模式,这将可以变成有针对性的广告。文章接着解释如何对物联网和社交媒体平台进行挖掘形成数据点。“使用机器学习挖掘社交媒体数据,可以让公司了解千禧一代如何谈论其产品,他们对一个产品类别的看法,他们对竞争对手的广告活动如何响应,还可获得很多数据,用于设计有针对性的广告,"这篇文章解释说。AI 和千禧一代成为营销的未来并不是什么很令人吃惊的事,但是 X 一代和婴儿潮一代,你们也逃不掉呢!(LCTT 译注:X 一代指出生于 20 世纪 60 年代中期至 70 年代末的美国人,婴儿潮是指二战结束后,1946 年初至 1964 年底出生的人)
|
||||
|
||||
> 人工智能根据行为变化,将包括城市人在内的整个人群设为目标群体。
|
||||
|
||||
例如, [Raconteur 上][23]的一篇文章 —— “AI 将怎样改变购买者的行为”中解释说,AI 在网上零售行业最大的力量是它能够迅速适应客户行为不断变化的形势。人工智能创业公司 [Fluid AI][25] 首席执行官 Abhinav Aggarwal 表示,他公司的软件被一个客户用来预测顾客行为,有一次系统注意到在暴风雪期间发生了一个变化。“那些通常会忽略在一天中发送的电子邮件或应用内通知的用户现在正在打开它们,因为他们在家里没有太多的事情可做。一个小时之内,AI 系统就适应了新的情况,并在工作时间开始发送更多的促销材料。”他解释说。
|
||||
|
||||
AI 正在改变我们怎样花钱和为什么花钱,但是 AI 是怎样改变我们挣钱的方式的呢?
|
||||
|
||||
### 2. 人工智能正在改变我们如何工作
|
||||
|
||||
[Fast 公司][5]最近的一篇文章“2017 年人工智能将如何改变我们的生活”中说道,求职者将会从人工智能中受益。作者解释说,除更新薪酬趋势之外,人工智能将被用来给求职者发送相关职位空缺信息。当你应该升职的时候,你很可能会得到一个升职的机会。
|
||||
|
||||
人工智能也可以被公司用来帮助新入职的员工。文章解释说:“许多新员工在刚入职的几天内会获得大量信息,其中大部分都留不下来。” 相反,机器人可能会随着时间的推移,当新员工需要相关信息时,再向他一点点“告知信息”。
|
||||
|
||||
[Inc.][7] 有一篇文章[“没有偏见的企业:人工智能将如何重塑招聘机制”][8],观察了人才管理解决方案提供商 [SAP SuccessFactors][9] 是怎样利用人工智能作为一个工作描述“偏见检查器”,以及检查员工赔偿金的偏见。
|
||||
|
||||
[《Deloitte 2017 人力资本趋势报告》][10]显示,AI 正在激励组织进行重组。Fast 公司的文章[“AI 是怎样改变公司组织的方式”][11]审查了这篇报告,该报告是基于全球 10,000 多名人力资源和商业领袖的调查结果。这篇文章解释说:"许多公司现在更注重文化和环境的适应性,而不是聘请最有资格的人来做某个具体任务,因为知道个人角色必须随 AI 的实施而发展。" 为了适应不断变化的技术,组织也从自上而下的结构转向多学科团队,文章说。
|
||||
|
||||
### 3. AI 正在改变教育
|
||||
|
||||
> AI 将使所有教育生态系统的利益相关者受益。
|
||||
|
||||
尽管教育预算正在缩减,但是教室的规模却正在增长。因此利用技术的进步有助于提高教育体系的生产率和效率,并在提高教育质量和负担能力方面发挥作用。根据 VentureBeat 上的一篇文章[“2017 年人工智能将怎样改变教育”][26],今年我们将看到 AI 对学生们的书面答案进行评分,机器人回答学生的问题,虚拟个人助理辅导学生等等。文章解释说:“AI 将惠及教育生态系统的所有利益相关者。学生将能够通过即时的反馈和指导学习地更好,教师将获得丰富的学习分析和对个性化教学的见解,父母将以更低的成本看到他们的孩子的更好的职业前景,学校能够规模化优质的教育,政府能够向所有人提供可负担得起的教育。"
|
||||
|
||||
### 4. 人工智能正在重塑医疗保健
|
||||
|
||||
2017 年 2 月 [CB Insights][12] 的一篇文章挑选了 106 个医疗保健领域的人工智能初创公司,它们中的很多在过去几年中提高了第一次股权融资。这篇文章说:“在 24 家成像和诊断公司中,19 家公司自 2015 年 1 月起就首次公开募股。”这份名单上有那些从事于远程病人监测,药物发现和肿瘤学方面人工智能的公司。”
|
||||
|
||||
3 月 16 日发表在 TechCrunch 上的一篇关于 AI 进步如何重塑医疗保健的文章解释说:“一旦对人类的 DNA 有了更好的理解,就有机会更进一步,并能根据他们特殊的生活习性为他们提供个性化的见解。这种趋势预示着‘个性化遗传学’的新纪元,人们能够通过获得关于自己身体的前所未有的信息来充分控制自己的健康。”
|
||||
|
||||
本文接着解释说,AI 和机器学习降低了研发新药的成本和时间。部分得益于广泛的测试,新药进入市场需要 12 年以上的时间。这篇文章说:“机器学习算法可以让计算机根据先前处理的数据来‘学习’如何做出预测,或者选择(在某些情况下,甚至是产品)需要做什么实验。类似的算法还可用于预测特定化合物对人体的副作用,这样可以加快审批速度。”这篇文章指出,2015 年旧金山的一个创业公司 [Atomwise][15] 一天内完成了可以减少埃博拉感染的两种新药物的分析,而不是花费数年时间。
|
||||
|
||||
> AI 正在帮助发现、诊断和治疗新疾病。
|
||||
|
||||
另外一个位于伦敦的初创公司 [BenevolentAI][27] 正在利用人工智能寻找科学文献中的模式。这篇文章说:“最近,这家公司找到了两种可能对 Alzheimer 起作用的化合物,引起了很多制药公司的关注。"
|
||||
|
||||
除了有助于研发新药,AI 正在帮助发现、诊断和治疗新疾病。TechCrunch 上的文章解释说,过去是根据显示的症状诊断疾病,但是现在 AI 正在被用于检测血液中的疾病特征,并利用对数十亿例临床病例分析进行深度学习获得经验来制定治疗计划。这篇文章说:“IBM 的 Watson 正在与纽约的 Memorial Sloan Kettering 合作,消化理解数十年来关于癌症患者和治疗方面的数据,为了向治疗疑难的癌症病例的医生提供和建议治疗方案。”
|
||||
|
||||
### 5. AI 正在改变我们的爱情生活
|
||||
|
||||
有 195 个国家的超过 5000 万活跃用户通过一个在 2012 年推出的约会应用程序 [Tinder][16] 找到潜在的伴侣。在一个 [Forbes 采访播客][17]中,Tinder 的创始人兼董事长 Sean Rad spoke 与 Steven Bertoni 对人工智能是如何正在改变人们约会进行过讨论。在[关于此次采访的文章][18]中,Bertoni 引用了 Rad 说的话,他说:“可能有这样一个时刻,Tinder 可以很好的推测你会感兴趣的人,在组织约会中还可能会做很多跑腿的工作”,所以,这个 app 会向用户推荐一些附近的同伴,并更进一步,协调彼此的时间安排一次约会,而不只是向用户显示一些有可能的同伴。
|
||||
|
||||
> 我们的后代真的可能会爱上人工智能。
|
||||
|
||||
你爱上了 AI 吗?我们的后代真的可能会爱上人工智能。Raya Bidshahri 发表在 [Singularity Hub][19] 的一篇文章“AI 将如何重新定义爱情”说,几十年的后,我们可能会认为爱情不再受生物学的限制。
|
||||
|
||||
Bidshahri 解释说:“我们的技术符合摩尔定律,正在以惊人的速度增长 —— 智能设备正在越来越多地融入我们的生活。”,他补充道:“到 2029 年,我们将会有和人类同等智慧的 AI,而到 21 世纪 40 年代,AI 将会比人类聪明无数倍。许多人预测,有一天我们会与强大的机器合并,我们自己可能会变成人工智能。”他认为在这样一个世界上那些是不可避免的,人们将会接受与完全的非生物相爱。
|
||||
|
||||
这听起来有点怪异,但是相比较于未来机器人将统治世界,爱上 AI 会是一个更乐观的结果。Bidshahri 说:“对 AI 进行编程,让他们能够感受到爱,这将使我们创造出更富有同情心的 AI,这可能也是避免很多人忧虑的 AI 大灾难的关键。”
|
||||
|
||||
这份 AI 正在入侵我们生活各领域的清单只是涉及到了我们身边的人工智能的表面。哪些 AI 创新是让你最兴奋的,或者是让你最烦恼的?大家可以在文章评论区写下你们的感受。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Rikki Endsley - Rikki Endsley 是开源社区 Opensource.com 的管理员。在过去,她曾做过 Red Hat 开源和标准(OSAS)团队社区传播者;自由技术记者;USENIX 协会的社区管理员;linux 权威杂志 ADMIN 和 Ubuntu User 的合作出版者,还是杂志 Sys Admin 和 UnixReview.com 的主编。在 Twitter 上关注她:@rikkiends。
|
||||
|
||||
----
|
||||
|
||||
via: https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives
|
||||
|
||||
作者:[Rikki Endsley][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/rikki-endsley
|
||||
[1]:https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives?rate=ORfqhKFu9dpA9aFfg-5Za9ZWGcBcx-f0cUlf_VZNeQs
|
||||
[2]:https://www.linux.com/news/open-source-projects-are-transforming-machine-learning-and-ai
|
||||
[3]:https://twitter.com/venturebeat
|
||||
[4]:http://venturebeat.com/2017/03/16/how-ai-will-help-us-decipher-millennials/
|
||||
[5]:https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives
|
||||
[6]:https://www.fastcompany.com/3066620/this-is-how-ai-will-change-your-work-in-2017
|
||||
[7]:https://twitter.com/Inc
|
||||
[8]:http://www.inc.com/bill-carmody/businesses-beyond-bias-how-ai-will-reshape-hiring-practices.html
|
||||
[9]:https://www.successfactors.com/en_us.html
|
||||
[10]:https://dupress.deloitte.com/dup-us-en/focus/human-capital-trends.html?id=us:2el:3pr:dup3575:awa:cons:022817:hct17
|
||||
[11]:https://www.fastcompany.com/3068492/how-ai-is-changing-the-way-companies-are-organized
|
||||
[12]:https://twitter.com/CBinsights
|
||||
[13]:https://www.cbinsights.com/blog/artificial-intelligence-startups-healthcare/
|
||||
[14]:https://techcrunch.com/2017/03/16/advances-in-ai-and-ml-are-reshaping-healthcare/
|
||||
[15]:http://www.atomwise.com/
|
||||
[16]:https://twitter.com/Tinder
|
||||
[17]:https://www.forbes.com/podcasts/the-forbes-interview/#5e962e5624e1
|
||||
[18]:https://www.forbes.com/sites/stevenbertoni/2017/02/14/tinders-sean-rad-on-how-technology-and-artificial-intelligence-will-change-dating/#4180fc2e5b99
|
||||
[19]:https://twitter.com/singularityhub
|
||||
[20]:https://singularityhub.com/2016/08/05/how-ai-will-redefine-love/
|
||||
[21]:https://opensource.com/user/23316/feed
|
||||
[22]:https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives#comments
|
||||
[23]:https://twitter.com/raconteur
|
||||
[24]:https://www.raconteur.net/technology/how-ai-will-change-buyer-behaviour
|
||||
[25]:http://www.fluid.ai/
|
||||
[26]:http://venturebeat.com/2017/02/04/how-ai-will-transform-education-in-2017/
|
||||
[27]:https://twitter.com/benevolent_ai
|
||||
[28]:https://opensource.com/users/rikki-endsley
|
||||
|
@ -1,24 +1,24 @@
|
||||
Remmina - 一个 Linux 下功能丰富的远程桌面共享工具
|
||||
Remmina:一个 Linux 下功能丰富的远程桌面共享工具
|
||||
============================================================
|
||||
|
||||
**Remmina** 是一款在 Linux 和其他类 Unix 系统下的免费开源、功能丰富、强大的远程桌面客户端,它用 GTK+ 3 编写而成。它适用于那些需要远程访问及使用许多计算机的系统管理员和在外出行人员。
|
||||
**Remmina** 是一款在 Linux 和其他类 Unix 系统下的自由开源、功能丰富、强大的远程桌面客户端,它用 GTK+ 3 编写而成。它适用于那些需要远程访问及使用许多计算机的系统管理员和在外出行人员。
|
||||
|
||||
它以简单、统一、同一性、易于使用的用户界面支持多种网络协议。
|
||||
它以简单、统一、同质、易用的用户界面支持多种网络协议。
|
||||
|
||||
#### Remmina 功能
|
||||
### Remmina 功能
|
||||
|
||||
* 支持 RDP、VNC、NX、XDMCP 和 SSH。
|
||||
* 用户能够以组的形式维护一份连接配置列表。
|
||||
* 支持用户直接输入服务器地址的快速连接。
|
||||
* 具有更高分辨率的远程桌面,可以在窗口和全屏模式下滚动/缩放。
|
||||
* 支持窗口全屏模式;当鼠标移动到屏幕边缘时,远程桌面会自动滚动。
|
||||
* 还支持全屏模式浮动工具栏;使你能够在不同模式间切换、触发键盘获取、最小化等。
|
||||
* 提供选项卡式界面,可选择由组管理。
|
||||
* 还支持全屏模式的浮动工具栏;使你能够在不同模式间切换、触发键盘获取、最小化等。
|
||||
* 提供选项卡式界面,可以按组管理。
|
||||
* 还提供托盘图标,允许你快速访问已配置的连接文件。
|
||||
|
||||
在本文中,我们将向你展示如何在 Linux 中安装 Remmina,以及使用它通过支持的不同协议实现桌面共享。
|
||||
|
||||
#### 先决条件
|
||||
### 先决条件
|
||||
|
||||
* 在远程机器上允许桌面共享(让远程机器允许远程连接)。
|
||||
* 在远程机器上设置 SSH 服务。
|
||||
@ -43,7 +43,7 @@ $ sudo dnf copr enable hubbitus/remmina-next
|
||||
$ sudo dnf upgrade --refresh 'remmina*' 'freerdp*'
|
||||
```
|
||||
|
||||
一旦安装完成后,在 Ubuntu 或 Linux Mint 菜单中搜索 **remmina**,接着运行它:
|
||||
一旦安装完成后,在 Ubuntu 或 Linux Mint 菜单中搜索 `remmina`,接着运行它:
|
||||
|
||||
[
|
||||
![Remmina Desktop Sharing Client](http://www.tecmint.com/wp-content/uploads/2017/03/Remmina-Desktop-Sharing-Client.png)
|
||||
@ -53,7 +53,7 @@ $ sudo dnf upgrade --refresh 'remmina*' 'freerdp*'
|
||||
|
||||
你可以通过图形界面或者编辑 `$HOME/.remmina` 或者 `$HOME/.config/remmina` 下的文件来进行配置。
|
||||
|
||||
要设置到一个新的远程服务器的连接,按下 `[Ctrl+N]` 并点击 **Connection -> New**,如下截图中配置远程连接。这是基本的设置界面。
|
||||
要设置到一个新的远程服务器的连接,按下 `Ctrl+N` 并点击 **Connection -> New**,如下截图中配置远程连接。这是基本的设置界面。
|
||||
|
||||
[
|
||||
![Remmina Basic Desktop Preferences](http://www.tecmint.com/wp-content/uploads/2017/03/Remmina-Basic-Desktop-Preferences.png)
|
||||
@ -87,7 +87,7 @@ $ sudo dnf upgrade --refresh 'remmina*' 'freerdp*'
|
||||
|
||||
#### 使用 sFTP 连接到远程机器
|
||||
|
||||
选择连接配置并编辑设置,在 “**Protocols**” 下拉菜单中选择 **sFTP - 安全文件传输**。接着设置启动路径(可选),并指定 SSH 验证细节。最后点击**连接**。
|
||||
选择连接配置并编辑设置,在 “**Protocols**” 下拉菜单中选择 **sFTP - Secure File Transfer**。接着设置启动路径(可选),并指定 SSH 验证细节。最后点击**连接**。
|
||||
|
||||
[
|
||||
![Remmina sftp Connection](http://www.tecmint.com/wp-content/uploads/2017/03/Remmina-sftp-connection.png)
|
||||
@ -103,7 +103,7 @@ $ sudo dnf upgrade --refresh 'remmina*' 'freerdp*'
|
||||
|
||||
*输入 SSH 密码*
|
||||
|
||||
如果你看到下面的界面,那么代表 SFTP 连接成功了,你现在可以[在两台机器键传输文件了][8]。
|
||||
如果你看到下面的界面,那么代表 sFTP 连接成功了,你现在可以[在两台机器键传输文件了][8]。
|
||||
|
||||
[
|
||||
![Remmina Remote sFTP Filesystem](http://www.tecmint.com/wp-content/uploads/2017/03/Remmina-Remote-sFTP-Filesystem.png)
|
||||
@ -131,7 +131,7 @@ $ sudo dnf upgrade --refresh 'remmina*' 'freerdp*'
|
||||
|
||||
#### 使用 VNC 连接到远程机器
|
||||
|
||||
选择连接配置并编辑设置,在 “**Protocols**” 下拉菜单中选择 **VNC - 虚拟网络计算**。为连接配置基础、高级以及 ssh 设置,点击**连接**,接着输入用户 SSH 密码。
|
||||
选择连接配置并编辑设置,在 “**Protocols**” 下拉菜单中选择 **VNC - Virtual Network Computing**。为该连接配置基础、高级以及 ssh 设置,点击**连接**,接着输入用户 SSH 密码。
|
||||
|
||||
[
|
||||
![Remmina VNC Connection](http://www.tecmint.com/wp-content/uploads/2017/03/Remmina-VNC-Connection.png)
|
||||
@ -172,7 +172,7 @@ via: http://www.tecmint.com/remmina-remote-desktop-sharing-and-ssh-client/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[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,255 @@
|
||||
rdiff-backup:一个 Linux 中的远程增量备份工具
|
||||
============================================================
|
||||
|
||||
rdiff-backup 是一个用于本地/远程增量备份的强大而易用的 Python 脚本,它适用于任何 POSIX 操作系统,如Linux、Mac OS X 或 [Cygwin][1]。它集合了镜像和增量备份的显著特性。
|
||||
|
||||
值得注意的是,它保留了子目录、dev 文件、硬链接,以及关键的文件属性,如权限、uid/gid 所有权、修改时间、扩展属性、acl 以及 resource fork。它可以通过管道以高效带宽的模式工作,这与流行的 [rsync 备份工具][2]类似。
|
||||
|
||||
rdiff-backup 通过使用 SSH 将单个目录备份到另一个目录,这意味着数据传输被加密并且是安全的。目标目录(在远程系统上)最终会得到源目录的完整副本,但是此外的反向差异会存储在目标目录的特殊子目录中,从而可以恢复前一段时间丢失的文件。
|
||||
|
||||
### 依赖
|
||||
|
||||
要在 Linux 中使用 rdiff-backup,你需要在系统上安装以下软件包:
|
||||
|
||||
* Python v2.2 或更高版本
|
||||
* librsync v0.9.7 或更高版本
|
||||
* pylibacl 和 pyxattr Python 模块是可选的,但它们分别是 POSIX 访问控制列表(ACL)和扩展属性支持必需的。
|
||||
* rdiff-backup-statistics 需要 Python v2.4 或更高版本。
|
||||
|
||||
### 如何在 Linux 中安装 rdiff-backup
|
||||
|
||||
重要:如果你通过网络运行它,则必须在两个系统中都安装 rdiff-backup,两者最好是相同版本。
|
||||
|
||||
该脚本已经存在于主流 Linux 发行版的官方仓库中,只需运行以下命令来安装 rdiff-backup 及其依赖关系:
|
||||
|
||||
#### 在 Debian/Ubuntu 中
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install librsync-dev rdiff-backup
|
||||
```
|
||||
|
||||
#### 在 CentOS/RHEL 7 中
|
||||
|
||||
```
|
||||
# wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-9.noarch.rpm
|
||||
# rpm -ivh epel-release-7-9.noarch.rpm
|
||||
# yum install librsync rdiff-backup
|
||||
```
|
||||
|
||||
#### 在 CentOS/RHEL 6 中
|
||||
|
||||
```
|
||||
# wget http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
|
||||
# rpm -ivh epel-release-6-8.noarch.rpm
|
||||
# yum install librsync rdiff-backup
|
||||
```
|
||||
|
||||
#### 在 Fedora 中
|
||||
|
||||
```
|
||||
# yum install librsync rdiff-backup
|
||||
# dnf install librsync rdiff-backup [Fedora 22+]
|
||||
```
|
||||
|
||||
### 如何在 Linux 中使用 rdiff-backup
|
||||
|
||||
如前所述,rdiff-backup 使用 SSH 连接到网络上的远程计算机,SSH 的默认身份验证方式是用户名/密码,这通常需要人工交互。
|
||||
|
||||
但是,要自动执行诸如脚本等自动备份之类的任务,那么你需要配置[使用 SSH 密钥无密码登录 SSH][3],因为 SSH 密钥增加了两台 Linux服务器之间的信任来[简化文件同步或传输][4]。
|
||||
|
||||
在你设置了 [SSH 无密码登录][5]后,你可以使用下面的例子开始使用该脚本。
|
||||
|
||||
#### 备份文件到不同分区
|
||||
|
||||
下面的例子会备份 `/etc` 文件夹到另外一个分区的 `Backup` 文件夹内:
|
||||
|
||||
```
|
||||
$ sudo rdiff-backup /etc /media/aaronkilik/Data/Backup/mint_etc.backup
|
||||
```
|
||||
[
|
||||
![Backup Files to Different Partition](http://www.tecmint.com/wp-content/uploads/2017/03/Backup-Files-to-Different-Partition.png)
|
||||
][6]
|
||||
|
||||
*备份文件到不同分区*
|
||||
|
||||
要排除一个特定文件夹和它的子目录,你可以如下使用 `--exclude` 选项:
|
||||
|
||||
```
|
||||
$ sudo rdiff-backup --exclude /etc/cockpit --exclude /etc/bluetooth /media/aaronkilik/Data/Backup/mint_etc.backup
|
||||
```
|
||||
|
||||
我们可以如下使用 `--include-special-files` 包含所有的设备文件、fifo 文件、socket 文件和链接文件:
|
||||
|
||||
```
|
||||
$ sudo rdiff-backup --include-special-files --exclude /etc/cockpit /media/aaronkilik/Data/Backup/mint_etc.backup
|
||||
```
|
||||
|
||||
还有另外两个重要标志来用于选择文件,`--max-file-size` 用来排除大于给定字节大小的文件,`--min-file-size` 用于排除小于给定字节大小的文件:
|
||||
|
||||
```
|
||||
$ sudo rdiff-backup --max-file-size 5M --include-special-files --exclude /etc/cockpit /media/aaronkilik/Data/Backup/mint_etc.backup
|
||||
```
|
||||
|
||||
#### 在本地 Linux 服务器上备份远程文件
|
||||
|
||||
要这么做,我们使用:
|
||||
|
||||
```
|
||||
Remote Server (tecmint) : 192.168.56.102
|
||||
Local Backup Server (backup) : 192.168.56.10
|
||||
```
|
||||
|
||||
如前所述,你必须在两台机器上安装相同版本的 rdiff-backup,如下所示,请尝试在两台机器上检查版本:
|
||||
|
||||
```
|
||||
$ rdiff-backup -V
|
||||
```
|
||||
[
|
||||
![Check rdiff Version on Servers](http://www.tecmint.com/wp-content/uploads/2017/03/check-rdif-versions-on-servers.png)
|
||||
][7]
|
||||
|
||||
*检查服务器中 rdiff 版本*
|
||||
|
||||
在备份服务器中,像这样创建一个存储备份文件的目录:
|
||||
|
||||
```
|
||||
# mkdir -p /backups
|
||||
```
|
||||
|
||||
现在在备份服务器中,运行下面的命令来将远程 Linux 服务器 192.168.56.102 中的 `/var/log/` 和 `/root` 备份到 `/backups` 中:
|
||||
|
||||
```
|
||||
# rdiff-backup root@192.168.56.102::/var/log/ /backups/192.168.56.102_logs.backup
|
||||
# rdiff-backup root@192.168.56.102::/root/ /backups/192.168.56.102_rootfiles.backup
|
||||
```
|
||||
|
||||
下面的截图展示了远程服务器 192.168.56.102 中的 `root` 文件夹以及 192.168.56.10 备份服务器中的已备份文件:
|
||||
|
||||
[
|
||||
![Backup Remote Directory on Local Server](http://www.tecmint.com/wp-content/uploads/2017/03/Backup-Remote-Linux-Directory-on-Local-Server.png)
|
||||
][8]
|
||||
|
||||
*在本地服务器备份远程目录*
|
||||
|
||||
注意截图中 “backup” 目录中创建的 rdiff-backup-data 文件夹,它包含了备份过程和增量文件的重要数据。
|
||||
|
||||
[
|
||||
![rdiff-backup - Backup Process Files](http://www.tecmint.com/wp-content/uploads/2017/03/rdiff-backup-data-directory-contents.png)
|
||||
][9]
|
||||
|
||||
*rdiff-backup – 备份过程文件*
|
||||
|
||||
现在,在 192.168.56.102 服务器中,如下所示 `root` 目录已经添加了额外的文件:
|
||||
|
||||
[
|
||||
![Verify Backup Directory](http://www.tecmint.com/wp-content/uploads/2017/03/additional-files-in-root-directory.png)
|
||||
][10]
|
||||
|
||||
*验证备份目录*
|
||||
|
||||
让我们再次运行备份命令以获取更改的数据,我们可以使用 `-v[0-9]`(其中数字指定详细程度级别,默认值为 3,这是静默模式)选项设置详细功能:
|
||||
|
||||
```
|
||||
# rdiff-backup -v4 root@192.168.56.102::/root/ /backups/192.168.56.102_rootfiles.backup
|
||||
```
|
||||
[
|
||||
![Incremental Backup with Summary](http://www.tecmint.com/wp-content/uploads/2017/03/incremental-backup-of-root-files.png)
|
||||
][11]
|
||||
|
||||
*带有摘要的增量备份*
|
||||
|
||||
要列出 `/backups/192.168.56.102_rootfiles.backup` 目录中包含的部分增量备份的数量和日期,我们可以运行:
|
||||
|
||||
```
|
||||
# rdiff-backup -l /backups/192.168.56.102_rootfiles.backup/
|
||||
```
|
||||
|
||||
#### 使用 cron 自动进行 rdiff-back 备份
|
||||
|
||||
使用 `--print-statistics` 成功备份后,我们可以打印摘要统计信息。但是,如果我们不设置此选项,我们可以仍从会话统计中获得。在手册页的 “STATISTICS” 部分中阅读有关此选项的更多信息。
|
||||
|
||||
`-remote-schema` 选项使我们能够指定使用替代方法连接到远程计算机。
|
||||
|
||||
现在,我们开始在备份服务器 192.168.56.10 上创建一个 `backup.sh` 脚本,如下所示:
|
||||
|
||||
```
|
||||
# cd ~/bin
|
||||
# vi backup.sh
|
||||
```
|
||||
|
||||
添加下面的行到脚本中。
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
#This is a rdiff-backup utility backup script
|
||||
#Backup command
|
||||
rdiff-backup --print-statistics --remote-schema 'ssh -C %s "sudo /usr/bin/rdiff-backup --server --restrict-read-only /"' root@192.168.56.102::/var/logs /backups/192.168.56.102_logs.back
|
||||
#Checking rdiff-backup command success/error
|
||||
status=$?
|
||||
if [ $status != 0 ]; then
|
||||
#append error message in ~/backup.log file
|
||||
echo "rdiff-backup exit Code: $status - Command Unsuccessful" >>~/backup.log;
|
||||
exit 1;
|
||||
fi
|
||||
#Remove incremental backup files older than one month
|
||||
rdiff-backup --force --remove-older-than 1M /backups/192.168.56.102_logs.back
|
||||
```
|
||||
|
||||
保存文件并退出,接着运行下面的命令在服务器 192.168.56.10 上的 crontab 中添加此脚本:
|
||||
|
||||
```
|
||||
# crontab -e
|
||||
```
|
||||
|
||||
添加此行在每天午夜运行你的备份脚本:
|
||||
|
||||
```
|
||||
0 0 * * * /root/bin/backup.sh > /dev/null 2>&1
|
||||
```
|
||||
|
||||
保存 crontab 并退出,现在我们已经成功自动化了备份过程。确保一切如希望那样工作。
|
||||
|
||||
阅读 rdiff-backup 的手册页获取更多信息、详尽的使用选项以及示例:
|
||||
|
||||
```
|
||||
# man rdiff-backup
|
||||
```
|
||||
|
||||
rdiff-backup 主页: [http://www.nongnu.org/rdiff-backup/][12]
|
||||
|
||||
就是这样了!在本教程中,我们向你展示了如何安装并基础地使用 rdiff-backup 这个易于使用的 Python 脚本,用于 Linux 中的本地/远程增量备份。 请通过下面的反馈栏与我们分享你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 和 F.O.S.S 爱好者,将来的 Linux SysAdmin 和 web 开发人员,目前是 TecMint 的内容创建者,他喜欢用电脑工作,并坚信分享知识。
|
||||
|
||||
|
||||
------------
|
||||
|
||||
via: http://www.tecmint.com/rdiff-backup-remote-incremental-backup-for-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.tecmint.com/author/aaronkili/
|
||||
[1]:http://www.tecmint.com/install-cygwin-to-run-linux-commands-on-windows-system/
|
||||
[2]:http://www.tecmint.com/rsync-local-remote-file-synchronization-commands/
|
||||
[3]:https://linux.cn/article-6901-1.html
|
||||
[4]:http://www.tecmint.com/sync-new-changed-modified-files-rsync-linux/
|
||||
[5]:https://linux.cn/article-6901-1.html
|
||||
[6]:http://www.tecmint.com/wp-content/uploads/2017/03/Backup-Files-to-Different-Partition.png
|
||||
[7]:http://www.tecmint.com/wp-content/uploads/2017/03/check-rdif-versions-on-servers.png
|
||||
[8]:http://www.tecmint.com/wp-content/uploads/2017/03/Backup-Remote-Linux-Directory-on-Local-Server.png
|
||||
[9]:http://www.tecmint.com/wp-content/uploads/2017/03/rdiff-backup-data-directory-contents.png
|
||||
[10]:http://www.tecmint.com/wp-content/uploads/2017/03/additional-files-in-root-directory.png
|
||||
[11]:http://www.tecmint.com/wp-content/uploads/2017/03/incremental-backup-of-root-files.png
|
||||
[12]:http://www.nongnu.org/rdiff-backup/
|
||||
[13]:http://www.tecmint.com/author/aaronkili/
|
||||
[14]:http://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[15]:http://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,141 @@
|
||||
bd:快速返回某级父目录而不用冗余地输入 “cd ../../..”
|
||||
============================================================
|
||||
|
||||
在 Linux 系统上通过命令行切换文件夹时,为了回到父目录(长路径),我们通常会重复输入 [cd 命令][1](`cd ../../..`),直到进入感兴趣的目录。
|
||||
|
||||
对于经验丰富的 Linux 用户或需要进行各种不同任务的系统管理员而言,这可能非常乏味,因此希望在操作系统时有一个快捷方式来简化工作。
|
||||
|
||||
**建议阅读:** [Autojump - 一个快速浏览 Linux 文件系统的高级 “cd” 命令][2]
|
||||
|
||||
在本文中,我们将在 bd 工具的帮助下,用这个简单而有用的工具快速回到 Linux 中的父目录。
|
||||
|
||||
bd 是用于切换文件夹的便利工具,它可以使你快速返回到父目录,而不必重复键入 `cd ../../..` 。 你可以可靠地将其与其他 Linux 命令组合以执行几个日常操作。
|
||||
|
||||
### 如何在 Linux 中安装 bd
|
||||
|
||||
运行下面的命令,使用 [wget 命令][3]下载并安装 bd 到 `/usr/bin/` 中,添加执行权限,并在 `~/.bashrc` 中创建需要的别名:
|
||||
|
||||
```
|
||||
$ wget --no-check-certificate -O /usr/bin/bd https://raw.github.com/vigneshwaranr/bd/master/bd
|
||||
$ chmod +rx /usr/bin/bd
|
||||
$ echo 'alias bd=". bd -si" >> ~/.bashrc
|
||||
$ source ~/.bashrc
|
||||
```
|
||||
|
||||
注意:如果要启用大小写敏感的目录名匹配,请在上面创建的别名中,设置 `-s` 标志而不是 `-si` 标志。
|
||||
|
||||
要启用自动补全支持,运行这些命令:
|
||||
|
||||
```
|
||||
$ sudo wget -O /etc/bash_completion.d/bd https://raw.github.com/vigneshwaranr/bd/master/bash_completion.d/bd
|
||||
$ sudo source /etc/bash_completion.d/bd
|
||||
```
|
||||
|
||||
#### 如何在 Linux 中使用 bd
|
||||
|
||||
假设你目前在这个路径的顶层目录:
|
||||
|
||||
```
|
||||
/media/aaronkilik/Data/Computer Science/Documents/Books/LEARN/Linux/Books/server $
|
||||
```
|
||||
|
||||
你想要快速进入 “Documents” 目录,只要输入:
|
||||
|
||||
```
|
||||
$ bd Documents
|
||||
```
|
||||
|
||||
接着直接进入到 Data 目录,你可以输入:
|
||||
|
||||
```
|
||||
$ bd Data
|
||||
```
|
||||
[
|
||||
![Switch Between Directories Quickly](http://www.tecmint.com/wp-content/uploads/2017/03/Switch-Between-Directories-Quickly.png)
|
||||
][4]
|
||||
|
||||
*目录间快速切换*
|
||||
|
||||
实际上,bd 让它变得更加直接,你要做的是输入 “bd <开头几个字母>”,比如:
|
||||
|
||||
```
|
||||
$ bd Doc
|
||||
$ bd Da
|
||||
```
|
||||
[
|
||||
![Quickly Switch Directories](http://www.tecmint.com/wp-content/uploads/2017/03/Quickly-Switch-Directories.png)
|
||||
][5]
|
||||
|
||||
*快速切换目录*
|
||||
|
||||
重要:如果层次结构中有不止一个具有相同名称的目录,bd 将会移动到最接近的目录,而不考虑最近的父目录,如下面的例子那样。
|
||||
|
||||
例如,在上面的路径中,有两个名称相同的目录 Books,如果你想移动到:
|
||||
|
||||
```
|
||||
/media/aaronkilik/Data/ComputerScience/Documents/Books/LEARN/Linux/Books
|
||||
```
|
||||
|
||||
输入 `bd Books` 会进入:
|
||||
|
||||
```
|
||||
/media/aaronkilik/Data/ComputerScience/Documents/Books
|
||||
```
|
||||
[
|
||||
![Move to 'Books' Directory Quickly](http://www.tecmint.com/wp-content/uploads/2017/03/Move-to-Directory-Quickly.png)
|
||||
][6]
|
||||
|
||||
*快速进入 ‘Books’ 目录*
|
||||
|
||||
另外,在引号中使用 bd 如 ``bd <开头几个字母>`` 会打印出路径而不更改当前目录,所以你可以与其他常见的 Linux 命令,如 [ls][7],[echo][8] 等一起使用 ``bd <开头几个字母>`` 。
|
||||
|
||||
在下面的例子中,当前在 `/var/www/html/internship/assets/filetree` 目录中,要打印出绝对路径、详细列出内容、统计目录 html 中所有文件的大小,你不必进入它,只需要键入:
|
||||
|
||||
```
|
||||
$ echo `bd ht`
|
||||
$ ls -l `bd ht`
|
||||
$ du -cs `bd ht`
|
||||
```
|
||||
[
|
||||
![Switch Directory with Listing](http://www.tecmint.com/wp-content/uploads/2017/03/Switch-Directory-with-Listing.png)
|
||||
][9]
|
||||
|
||||
*列出切换的目录*
|
||||
|
||||
要在 Github 上了解更多关于 bd 的信息:[https://github.com/vigneshwaranr/bd][10]
|
||||
|
||||
就是这样了!在本文中,我们展示了使用 bd 程序[在 Linux 中快速切换文件夹][11]的便捷方法。
|
||||
|
||||
通过下面的反馈栏单发表你的看法。此外,你还知道其他类似的工具么,在评论中让我们知道。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili是一名 Linux 和 F.O.S.S 的爱好者,未来的 Linux 系统管理员、网站开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并乐于分享知识。
|
||||
|
||||
---------------
|
||||
|
||||
via: http://www.tecmint.com/bd-quickly-go-back-to-a-linux-parent-directory/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.tecmint.com/author/aaronkili/
|
||||
[1]:http://www.tecmint.com/cd-command-in-linux/
|
||||
[2]:https://linux.cn/article-5983-1.html
|
||||
[3]:http://www.tecmint.com/10-wget-command-examples-in-linux/
|
||||
[4]:http://www.tecmint.com/wp-content/uploads/2017/03/Switch-Between-Directories-Quickly.png
|
||||
[5]:http://www.tecmint.com/wp-content/uploads/2017/03/Quickly-Switch-Directories.png
|
||||
[6]:http://www.tecmint.com/wp-content/uploads/2017/03/Move-to-Directory-Quickly.png
|
||||
[7]:http://www.tecmint.com/tag/linux-ls-command/
|
||||
[8]:http://www.tecmint.com/echo-command-in-linux/
|
||||
[9]:http://www.tecmint.com/wp-content/uploads/2017/03/Switch-Directory-with-Listing.png
|
||||
[10]:https://github.com/vigneshwaranr/bd
|
||||
[11]:https://linux.cn/article-5983-1.html
|
||||
[12]:http://www.tecmint.com/author/aaronkili/
|
||||
[13]:http://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[14]:http://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,134 @@
|
||||
Python-mode:在 Vim 编辑器中开发 Python 应用的 Vim 插件
|
||||
============================================================
|
||||
|
||||
Python-mode 是一个 Vim 插件,它使你能够在 [Vim 编辑器][1]中更快的利用包括 pylint、rope、pydoc、pyflakes、pep8、autopep8、pep257 和 mccable 在内的各种库来写 Python 代码,这些库提供了一些编码功能,比如静态分析、特征重构、折叠、补全和文档等。
|
||||
|
||||
**推荐阅读:** [如何用 Bash-Support 插件将 Vim 编辑器打造成编写 Bash 脚本的 IDE][2]
|
||||
|
||||
这个插件包含了所有你在 Vim 编辑器中可以用来开发 Python 应用的特性。
|
||||
|
||||
### Python-mode 的特性
|
||||
|
||||
它包含下面这些值得一提的特性:
|
||||
|
||||
* 支持 Python 2.6+ 至 Python 3.2 版本
|
||||
* 语法高亮
|
||||
* 提供 virtualenv 支持
|
||||
* 支持 Python 式折叠
|
||||
* 提供增强的 Python 缩进
|
||||
* 能够在 Vim 中运行 Python 代码
|
||||
* 能够添加/删除断点
|
||||
* 支持 Python 的 motion 和运算符
|
||||
* 能够在运行的同时检查代码(pylint、pyflakes、pylama ……)
|
||||
* 支持自动修复 PEP8 错误
|
||||
* 允许在 Python 文档中进行搜索
|
||||
* 支持代码重构
|
||||
* 支持强代码补全
|
||||
* 支持定义跳转
|
||||
|
||||
在这篇教程中,我将阐述如何在 Linux 中为 Vim 安装设置 Python-mode,从而在 Vim 编辑器中开发 Python 应用。
|
||||
|
||||
### 如何在 Linux 系统中为 Vim 安装 Python-mode
|
||||
|
||||
首先安装 [Pathogen][3] (它使得安装插件超级简单,并且运行文件位于私有目录中),从而更加容易的安装 Python-mode
|
||||
|
||||
运行下面的命令来获取 `pathogen.vim` 文件和它需要的目录:
|
||||
|
||||
```
|
||||
# mkdir -p ~/.vim/autoload ~/.vim/bundle && \
|
||||
# curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
|
||||
```
|
||||
|
||||
然后把下面这些内容加入 `~/.vimrc` 文件中:
|
||||
|
||||
```
|
||||
execute pathogen#infect()
|
||||
syntax on
|
||||
filetype plugin indent on
|
||||
```
|
||||
|
||||
安装好 pathogen 以后,你可以像下面这样把 Python-mode 插件放入 `~/.vim/bunble` 目录中:
|
||||
|
||||
```
|
||||
# cd ~/.vim/bundle
|
||||
# git clone https://github.com/klen/python-mode.git
|
||||
```
|
||||
|
||||
然后像下面这样在 Vim 中重建 `helptags` :
|
||||
|
||||
```
|
||||
:helptags
|
||||
```
|
||||
|
||||
你需要启用 `filetype-plugin` (:help filetype-plugin-on)和 `filetype-indent` (:help filetype-indent-on)来使用 Python-mode 。
|
||||
|
||||
### 在 Debian 和 Ubuntu 中安装 Python-mode
|
||||
|
||||
另一种在 Debian 和 Ubuntu 中安装 Python-mode 的方法是使用 PPA,就像下面这样
|
||||
|
||||
```
|
||||
$ sudo add-apt-repository https://klen.github.io/python-mode/deb main
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install vim-python-mode
|
||||
```
|
||||
|
||||
如果你遇到消息:“The following signatures couldn’t be verified because the public key is not available”,请运行下面的命令:
|
||||
|
||||
```
|
||||
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B5DF65307000E266
|
||||
```
|
||||
|
||||
现在,使用 `vim-addon-manager` 启用 Python-mode:
|
||||
|
||||
```
|
||||
$ sudo apt install vim-addon-manager
|
||||
$ vim-addons install python-mode
|
||||
```
|
||||
|
||||
### 在 Linux 中定制 Python-mode
|
||||
|
||||
如果想覆盖默认键位绑定,可以在 `.vimrc` 文件中重定义它们,比如:
|
||||
|
||||
```
|
||||
" Override go-to.definition key shortcut to Ctrl-]
|
||||
let g:pymode_rope_goto_definition_bind = "<C-]>"
|
||||
" Override run current python file key shortcut to Ctrl-Shift-e
|
||||
let g:pymode_run_bind = "<C-S-e>"
|
||||
" Override view python doc key shortcut to Ctrl-Shift-d
|
||||
let g:pymode_doc_bind = "<C-S-d>"
|
||||
```
|
||||
|
||||
注意,默认情况下, Python-mode 使用 Python 2 进行语法检查。你可以在 `.vimrc` 文件中加入下面这行内容从而启动 Python 3 语法检查。
|
||||
|
||||
```
|
||||
let g:pymode_python = 'python3'
|
||||
```
|
||||
|
||||
你可以在 Python-mode 的 GitHub 仓库找到更多的配置选项: [https://github.com/python-mode/python-mode][4]
|
||||
|
||||
这就是全部内容了。在本教程中,我向你们展示了如何在 Linux 中使用 Python-mode 来配置 Vim 。请记得通过下面的反馈表来和我们分享你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一个 Linux 和 F.O.S.S 爱好者、Linux 系统管理员、网络开发人员,现在也是 TecMint 的内容创作者,他喜欢和电脑一起工作,坚信共享知识。
|
||||
|
||||
------------------
|
||||
|
||||
via: https://www.tecmint.com/python-mode-a-vim-editor-plugin/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/vi-editor-usage/
|
||||
[2]:https://linux.cn/article-8467-1.html
|
||||
[3]:https://github.com/tpope/vim-pathogen
|
||||
[4]:https://github.com/python-mode/python-mode
|
||||
[5]:https://www.tecmint.com/author/aaronkili/
|
||||
[6]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[7]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -1,14 +1,13 @@
|
||||
如何在 Ubuntu 中安装 Discord
|
||||
如何在 Ubuntu 中安装语音聊天工具 Discord
|
||||
============================================================
|
||||
|
||||
![](https://www.maketecheasier.com/assets/uploads/2017/04/discord-feat.jpg "How to Install Discord on Ubuntu Linuxs")
|
||||
|
||||
Discord 是一个非常受欢迎的文字和语音聊天程序。虽然开始时主要面向游戏玩家,但它几乎获得了所有人的了广泛青睐。
|
||||
|
||||
Discord 是一个非常受欢迎的文字和语音聊天程序。虽然开始了主要面向游戏玩家,但它几乎获得了所有人的了广泛青睐。
|
||||
Discord 不仅仅是一个很好的聊天客户端。当你安装它时,你还可以获得其强大的服务端功能,强力而自足。游戏玩家和非玩家都可以在几分钟内开启自己的私人聊天服务,这使 Discord 成为团队、公会和各种社区的明显选择。
|
||||
|
||||
Discord 不仅仅是一个很好的聊天客户端。当你安装它时,你还可以获得其强大的服务端功能,包括电池。游戏玩家和非玩家都可以在几分钟内开启自己的私人聊天服务,这使 Discord 成为团队、公会和各种社区的明显选择。
|
||||
|
||||
Linux 用户经常在游戏世界中被遗忘。但 Discord 并不是这样。它的开发人员也在 Linux 下积极构建并维护其流行聊天平台。Ubuntu 用户拥有更好的功能。Discord 捆绑在方便的 Debian/Ubuntu .deb 包中。
|
||||
Linux 用户经常被游戏世界遗忘。但 Discord 并不是这样。它的开发人员也在 Linux 下积极构建并维护其流行聊天平台。Ubuntu 用户甚至拥有更好的待遇,Discord 捆绑在方便的 Debian/Ubuntu .deb 包中。
|
||||
|
||||
### 获取并安装软件包
|
||||
|
||||
@ -46,7 +45,7 @@ sudo apt install libgconf-2-4 libappindicator1
|
||||
|
||||
### 命令行安装
|
||||
|
||||
懒惰的 Linux 熟手并不在意花哨的 GUI 工具。如果你是这个阵营的人,那么你有一个更直接的命令行选项。
|
||||
“懒惰”的 Linux 熟手并不在意花哨的 GUI 工具。如果你是这个阵营的人,那么你有一个更直接的命令行选项。
|
||||
|
||||
首先,打开一个终端并进入你的下载目录。在那里可以使用 `wget` 直接下载 .deb 包。
|
||||
|
||||
@ -55,7 +54,7 @@ cd ~/Downloads
|
||||
wget -O discord-0.0.1.deb https://discordapp.com/api/download?platform=linux&format=deb
|
||||
```
|
||||
|
||||
下载完成后,你可以使用 dpkg 直接安装 .deb 软件包。运行下面的命令:
|
||||
下载完成后,你可以使用 `dpkg` 直接安装 .deb 软件包。运行下面的命令:
|
||||
|
||||
```
|
||||
sudo dpkg -i discord-0.0.1.deb
|
||||
@ -69,19 +68,19 @@ sudo dpkg -i discord-0.0.1.deb
|
||||
|
||||
![Login to Discord on Ubuntu](https://www.maketecheasier.com/assets/uploads/2017/04/discord-login.jpg "Login to Discord on Ubuntu")
|
||||
|
||||
首次启动,你需要创建一个帐户或者登录。做任意一个你需要做的。
|
||||
首次启动,根据你需求,创建一个帐户或者登录。
|
||||
|
||||
![Discord running on Ubuntu Linux](https://www.maketecheasier.com/assets/uploads/2017/04/discord-running.jpg "Discord running on Ubuntu Linux")
|
||||
|
||||
登录后,你就进入 Discord 了。它会提供一些介绍教程和建议。你可以直接略过开始尝试。欢迎进入你新的 Linux 聊天体验!
|
||||
登录后,你就进入 Discord 了。它会提供一些介绍教程和建议。你可以直接略过并开始尝试。欢迎进入你新的 Linux 聊天体验!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.maketecheasier.com/install-discord-ubuntu/
|
||||
|
||||
作者:[ Nick Congleton][a]
|
||||
作者:[Nick Congleton][a]
|
||||
译者:[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/) 荣誉推出
|
||||
|
132
published/201705/20170501 Containers running Containers.md
Normal file
132
published/201705/20170501 Containers running Containers.md
Normal file
@ -0,0 +1,132 @@
|
||||
LinuxKit:在容器中运行容器
|
||||
============================================================
|
||||
|
||||
一些令人振奋的消息引发了我对今年 DockerCon 的兴趣,在这次会议中,无可争议的容器巨头公司 Docker 发布了一个新的操作系统:LinuxKit。
|
||||
|
||||
这家容器巨头宣布的是一个灵活的、可扩展的操作系统,而为了可移植性,系统服务也是运行在容器之中。甚至,令人惊讶的是,就连 Docker 运行时环境也是运行在容器内!
|
||||
|
||||
在本文中,我们将简要介绍一下 LinuxKit 中所承诺的内容,以及如何自己尝试一下这个不断精简、优化的容器。
|
||||
|
||||
### 少即是多
|
||||
|
||||
不可否认的是,用户一直在寻找一个可以运行他们的微服务的精简版本的 Linux 。通过容器化,你会尽可能地最小化每个应用程序,使其成为一个适合于运行在其自身容器内的独立进程。但是,由于你需要对那些驻留容器的宿主机出现的问题进行修补,因此你不断地在宿主机间移动容器。实际上,如果没有像 Kubernetes 或 Docker Swarm 这样的编排系统,容器编排几乎总是会导致停机。
|
||||
|
||||
不用说,这只是让你保持操作系统尽可能小的原因之一。
|
||||
|
||||
我曾多次在不同场合重复过的最喜爱的名言,来自荷兰的天才程序员 Wietse Zweitze,他为我们提供了重要的 Email 软件 Postfix 和 TCP Wrappers 等知名软件。
|
||||
|
||||
在 [Postfix 网站][10] 指出,即使你编码和 Wietse 一样小心,“每 1000 行[你]就会在 Postfix 中引入一个额外的 bug”。从我的专业的 DevSecOps 角度看,这里提到的“bug” 可以将其大致看做安全问题。
|
||||
|
||||
从安全的角度来看,正是由于这个原因,代码世界中“少即是多”。简单地说,使用较少的代码行有很多好处,即安全性、管理时间和性能。对于初学者来说,这意味着安全漏洞较少,更新软件包的时间更短,启动时间更快。
|
||||
|
||||
### 深入观察
|
||||
|
||||
考虑下在容器内部运行你的程序。
|
||||
|
||||
一个好的起点是 [Alpine Linux][1],它是一个苗条、精简的操作系统,通常比那些笨重的系统更受喜欢,如 Ubuntu 或 CentOS 等。Alpine 还提供了一个 miniroot 文件系统(用于容器内),最近我看到的大小是惊人的 1.8M。事实上,这个完整的 Linux 操作系统下载后有 80M。
|
||||
|
||||
如果你决定使用 Alpine Linux 作为 Docker 基础镜像,那么你可以在 Docker Hub 上[找到][2]一个, 它将其描述为:“一个基于 Alpine Linux 的最小 Docker 镜像,具有完整的包索引,大小只有5 MB!”
|
||||
|
||||
据说无处不在的 “Window 开始菜单” 文件也是大致相同的大小!我没有验证过,也不会进一步评论。
|
||||
|
||||
讲真,希望你去了解一下这个创新的类 Unix 操作系统(如 Alpine Linux)的强大功能。
|
||||
|
||||
### 锁定一切
|
||||
|
||||
再说一点,Alpine Linux 是(并不惊人)基于 [BusyBox][3],这是一套著名的打包了 Linux 命令的集合,许多人不会意识到他们的宽带路由器、智能电视,当然还有他们家庭中的物联网设备就有它。
|
||||
|
||||
Alpine Linux 站点的“[关于][4]”页面的评论中指出:
|
||||
|
||||
> “Alpine Linux 的设计考虑到安全性。内核使用 grsecurity/PaX 的非官方移植进行了修补,所有用户态二进制文件都编译为具有堆栈保护的地址无关可执行文件(PIE)。 这些主动安全特性可以防止所有类别的零日漏洞和其它漏洞利用。”
|
||||
|
||||
换句话说,这些捆绑在 Alpine Linux 中的精简二进制文件提供的功能通过了那些行业级安全工具筛选,以缓解缓冲区溢出攻击所带来的危害。
|
||||
|
||||
### 多出一只袜子
|
||||
|
||||
你可能会问,为什么当我们谈及 Docker 的新操作系统时,容器的内部结构很重要?
|
||||
|
||||
那么,你可能已经猜到,当涉及容器时,他们的目标是精简。除非绝对必要,否则不包括任何东西。所以你可以放心地清理橱柜、花园棚子、车库和袜子抽屉了。
|
||||
|
||||
Docker 的确因为它们的先见而获得声望。据报道,2 月初,Docker 聘请了 Alpine Linux 的主要推动者 Nathaniel Copa,他帮助将默认的官方镜像库从 Ubuntu 切换到 Alpine。Docker Hub 从新近精简镜像节省的带宽受到了赞誉。
|
||||
|
||||
并且最新的情况是,这项工作将与最新的基于容器的操作系统相结合:Docker 的 LinuxKit。
|
||||
|
||||
要说清楚的是 LinuxKit 注定不会代替 Alpine,而是位于容器下层,并作为一个完整的操作系统出现,你可以高兴地启动你的运行时守护程序(在这种情况下,是生成你的容器的Docker 守护程序 )。
|
||||
|
||||
### 金发女郎的 Atomic
|
||||
|
||||
经过精心调试的宿主机绝对不是一件新事物(以前提到过嵌入式 Linux 的家用设备)。在过去几十年中一直在优化 Linux 的天才在某个时候意识到底层的操作系统才是快速生产含有大量容器主机的关键。
|
||||
|
||||
例如,强大的红帽长期以来一直在出售已经贡献给 [Project Atomic][6] 的 [红帽 Atomic][5]。后者继续解释:
|
||||
|
||||
> “基于 Red Hat Enterprise Linux 或 CentOS 和 Fedora 项目的成熟技术,Atomic Host 是一个轻量级的、不可变的平台,其设计目的仅在于运行容器化应用程序。”
|
||||
|
||||
将底层的、不可变的 Atomic OS 作为红帽的 OpenShift PaaS(平台即服务)产品推荐有一个很好理由:它最小化、高性能、尖端。
|
||||
|
||||
### 特性
|
||||
|
||||
在 Docker 关于 LinuxKit 的公告中,“少即是多”的口号是显而易见的。实现 LinuxKit 愿景的项目显然是不小的事业,它由 Docker 老将和 [Unikernel][7] 的主管 Justin Cormack 指导,并与 HPE、Intel、ARM、IBM 和 Microsoft LinuxKit 合作,可以运行在从大型机到基于物联网的冰柜之中。
|
||||
|
||||
LinuxKit 的可配置性、可插拔性和可扩展性将吸引许多寻求建立其服务基准的项目。通过开源项目,Docker 明智地邀请每个人全身心地投入其功能开发,随着时间的推移,它会像好的奶酪那样成熟。
|
||||
|
||||
### 布丁作证
|
||||
|
||||
按照该发布消息中所承诺的,那些急于使用新系统的人不用再等待了。如果你准备着手 LinuxKit,你可以从 GitHub 中开始:[LinuxKit][11]。
|
||||
|
||||
在 GitHub 页面上有关于如何启动和运行一些功能的指导。
|
||||
|
||||
时间允许的话我准备更加深入研究 LinuxKit。对有争议的 Kubernetes 与 Docker Swarm 编排功能对比会是有趣的尝试。此外,我还想看到内存占用、启动时间和磁盘空间使用率的基准测试。
|
||||
|
||||
如果该承诺可靠,则作为容器运行的可插拔系统服务是构建操作系统的迷人方式。Docker 在[博客][12])中提到:“因为 LinuxKit 是原生容器,它有一个非常小的尺寸 - 35MB,引导时间非常小。所有系统服务都是容器,这意味着可以删除或替换所有的内容。”
|
||||
|
||||
我不知道你觉得怎么样,但这非常符合我的胃口。
|
||||
|
||||
### 呼叫警察
|
||||
|
||||
除了我站在 DevSecOps 角度看到的功能,我会看看其对安全的承诺。
|
||||
|
||||
Docker 在他们的博客上引用来自 NIST([国家标准与技术研究所] [8])的话:
|
||||
|
||||
> “安全性是最高目标,这与 NIST 在其《应用程序容器安全指南》草案中说明的保持一致:‘使用容器专用操作系统而不是通用操作系统来减少攻击面。当使用专用容器操作系统时,攻击面通常比通用操作系统小得多,因此攻击和危及专用容器操作系统的机会较少。’”
|
||||
|
||||
可能最重要的容器到主机和主机到容器的安全创新是将系统容器(系统服务)完全地沙箱化到自己的非特权空间中,而只给它们需要的外部访问。
|
||||
|
||||
通过<ruby>内核自我保护项目<rt>Kernel Self Protection Project</rt></ruby>([KSPP][9])的协作来实现这一功能,我很满意 Docker 开始专注于一些非常值得的东西上。对于那些不熟悉的 KSPP 的人而言,它存在理由如下:
|
||||
|
||||
> “启动这个项目的的假设是内核 bug 的存在时间很长,内核必须设计成可以防止这些缺陷的危害。”
|
||||
|
||||
KSPP 网站进一步表态:
|
||||
|
||||
> “这些努力非常重要并还在进行,但如果我们要保护我们的十亿 Android 手机、我们的汽车、国际空间站,还有其他运行 Linux 的产品,我们必须在上游的 Linux 内核中建立积极的防御性技术。我们需要内核安全地出错,而不只是安全地运行。”
|
||||
|
||||
而且,如果 Docker 最初只是在 LinuxKit 前进了一小步,那么随着时间的推移,成熟度带来的好处可能会在容器领域中取得长足的进步。
|
||||
|
||||
### 离终点还远
|
||||
|
||||
像 Docker 这样不断发展壮大的巨头无论在哪个方向上取得巨大的飞跃都将会用户和其他软件带来益处。
|
||||
|
||||
我鼓励所有对 Linux 感兴趣的人密切关注这个领域。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.devsecops.cc/devsecops/containers.html
|
||||
|
||||
作者:[Chris Binnie][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.devsecops.cc/
|
||||
[1]:https://alpinelinux.org/downloads/
|
||||
[2]:https://hub.docker.com/_/alpine
|
||||
[3]:https://busybox.net/
|
||||
[4]:https://www.alpinelinux.org/about/
|
||||
[5]:https://www.redhat.com/en/resources/red-hat-enterprise-linux-atomic-host
|
||||
[6]:http://www.projectatomic.io/
|
||||
[7]:https://en.wikipedia.org/wiki/Unikernel
|
||||
[8]:https://www.nist.gov/
|
||||
[9]:https://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project
|
||||
[10]:http://www.postfix.org/TLS_README.html
|
||||
[11]:https://github.com/linuxkit/linuxkit
|
||||
[12]:https://blog.docker.com/2017/04/introducing-linuxkit-container-os-toolkit
|
@ -0,0 +1,159 @@
|
||||
在 Ubuntu 16.04 中安装支持 CPU 和 GPU 的 Google TensorFlow 神经网络软件
|
||||
============================================================
|
||||
|
||||
TensorFlow 是用于机器学习任务的开源软件。它的创建者 Google 希望提供一个强大的工具以帮助开发者探索和建立基于机器学习的应用,所以他们在去年作为开源项目发布了它。TensorFlow 是一个非常强大的工具,专注于一种称为<ruby>深层神经网络<rt>deep neural network</rt></ruby>(DNN)的神经网络。
|
||||
|
||||
深层神经网络被用来执行复杂的机器学习任务,例如图像识别、手写识别、自然语言处理、聊天机器人等等。这些神经网络被训练学习其所要执行的任务。由于训练所需的计算是非常巨大的,在大多数情况下需要 GPU 支持,这时 TensorFlow 就派上用场了。启用了 GPU 并安装了支持 GPU 的软件,那么训练所需的时间就可以大大减少。
|
||||
|
||||
本教程可以帮助你安装只支持 CPU 的和同时支持 GPU 的 TensorFlow。要使用带有 GPU 支持的 TensorFLow,你必须要有一块支持 CUDA 的 Nvidia GPU。CUDA 和 CuDNN(Nvidia 的计算库)的安装有点棘手,本指南会提供在实际安装 TensorFlow 之前一步步安装它们的方法。
|
||||
|
||||
Nvidia CUDA 是一个 GPU 加速库,它已经为标准神经网络中用到的标准例程调优过。CuDNN 是一个用于 GPU 的调优库,它负责 GPU 性能的自动调整。TensorFlow 同时依赖这两者用于训练并运行深层神经网络,因此它们必须在 TensorFlow 之前安装。
|
||||
|
||||
需要指出的是,那些不希望安装支持 GPU 的 TensorFlow 的人,你可以跳过以下所有的步骤并直接跳到:“步骤 5:安装只支持 CPU 的 TensorFlow”。
|
||||
|
||||
关于 TensorFlow 的介绍可以在[这里][10]找到。
|
||||
|
||||
### 1、 安装 CUDA
|
||||
|
||||
首先,在[这里][11]下载用于 Ubuntu 16.04 的 CUDA 库。此文件非常大(2GB),因此也许会花费一些时间下载。
|
||||
|
||||
下载的文件是 “.deb” 包。要安装它,运行下面的命令:
|
||||
|
||||
```
|
||||
sudo dpkg -i cuda-repo-ubuntu1604-8-0-local_8.0.44-1_amd64.deb
|
||||
```
|
||||
|
||||
[
|
||||
![Install CUDA](https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/image1.png)
|
||||
][12]
|
||||
|
||||
下面的的命令会安装所有的依赖,并最后安装 cuda 工具包:
|
||||
|
||||
```
|
||||
sudo apt install -f
|
||||
sudo apt update
|
||||
sudo apt install cuda
|
||||
```
|
||||
|
||||
如果成功安装,你会看到一条消息说:“successfully installed”。如果已经安装了,接着你可以看到类似下面的输出:
|
||||
|
||||
[
|
||||
![Install CUDA with apt](https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/image2.png)
|
||||
][13]
|
||||
|
||||
### 2、安装 CuDNN 库
|
||||
|
||||
CuDNN 下载需要花费一些功夫。Nvidia 没有直接提供下载文件(虽然它是免费的)。通过下面的步骤获取 CuDNN。
|
||||
|
||||
1. 点击[此处][8]进入 Nvidia 的注册页面并创建一个帐户。第一页要求你输入你的个人资料,第二页会要求你回答几个调查问题。如果你不知道所有答案也没问题,你可以随便选择一个选项。
|
||||
2. 通过前面的步骤,Nvidia 会向你的邮箱发送一个激活链接。在你激活之后,直接进入[这里][9]的 CuDNN 下载链接。
|
||||
3. 登录之后,你需要填写另外一份类似的调查。随机勾选复选框,然后点击调查底部的 “proceed to Download”,在下一页我们点击同意使用条款。
|
||||
4. 最后,在下拉中点击 “Download cuDNN v5.1 (Jan 20, 2017), for CUDA 8.0”,最后,你需要下载这两个文件:
|
||||
* [cuDNN v5.1 Runtime Library for Ubuntu14.04 (Deb)][6]
|
||||
* [cuDNN v5.1 Developer Library for Ubuntu14.04 (Deb)][7]
|
||||
|
||||
注意:即使上面说的是用于 Ubuntu 14.04 的库。它也适用于 16.04。
|
||||
|
||||
现在你已经同时有 CuDNN 的两个文件了,是时候安装它们了!在包含这些文件的文件夹内运行下面的命令:
|
||||
|
||||
```
|
||||
sudo dpkg -i libcudnn5_5.1.5-1+cuda8.0_amd64.deb
|
||||
sudo dpkg -i libcudnn5-dev_5.1.5-1+cuda8.0_amd64.deb
|
||||
```
|
||||
|
||||
下面的图片展示了这些命令的输出:
|
||||
|
||||
[
|
||||
![Install the CuDNN library](https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/image3.png)
|
||||
][14]
|
||||
|
||||
### 3、 在 bashrc 中添加安装位置
|
||||
|
||||
安装位置应该被添加到 bashrc 文件中,以便系统下一次知道如何找到这些用于 CUDA 的文件。使用下面的命令打开 bashrc 文件:
|
||||
|
||||
```
|
||||
sudo gedit ~/.bashrc
|
||||
```
|
||||
|
||||
文件打开后,添加下面两行到文件的末尾:
|
||||
|
||||
```
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64"
|
||||
export CUDA_HOME=/usr/local/cuda
|
||||
```
|
||||
|
||||
### 4、 安装带有 GPU 支持的 TensorFlow
|
||||
|
||||
这步我们将安装带有 GPU 支持的 TensorFlow。如果你使用的是 Python 2.7,运行下面的命令:
|
||||
|
||||
```
|
||||
pip install TensorFlow-gpu
|
||||
```
|
||||
|
||||
如果安装了 Python 3.x,使用下面的命令:
|
||||
|
||||
```
|
||||
pip3 install TensorFlow-gpu
|
||||
```
|
||||
|
||||
安装完后,你会看到一条 “successfully installed” 的消息。现在,剩下要测试的是是否已经正确安装。打开终端并输入下面的命令测试:
|
||||
|
||||
```
|
||||
python
|
||||
import TensorFlow as tf
|
||||
```
|
||||
|
||||
你应该会看到类似下面图片的输出。在图片中你可以观察到 CUDA 库已经成功打开了。如果有任何错误,消息会提示说无法打开 CUDA 甚至无法找到模块。为防你或许遗漏了上面的某步,仔细重做教程的每一步就行了。
|
||||
|
||||
[
|
||||
![Install TensorFlow with GPU support](https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/image4.png)
|
||||
][15]
|
||||
|
||||
### 5、 安装只支持 CPU 的 TensorFlow
|
||||
|
||||
注意:这步是对那些没有 GPU 或者没有 Nvidia GPU 的人而言的。其他人请忽略这步!!
|
||||
|
||||
安装只支持 CPU 的 TensorFlow 非常简单。使用下面两个命令:
|
||||
|
||||
```
|
||||
pip install TensorFlow
|
||||
```
|
||||
|
||||
如果你有 python 3.x,使用下面的命令:
|
||||
|
||||
```
|
||||
pip3 install TensorFlow
|
||||
```
|
||||
|
||||
是的,就是这么简单!
|
||||
|
||||
安装指南至此结束,你现在可以开始构建深度学习应用了。如果你刚刚起步,你可以在[这里][16]看下适合初学者的官方教程。如果你正在寻找更多的高级教程,你可以在[这里][17]学习了解如何设置可以高精度识别上千个物体的图片识别系统/工具。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.howtoforge.com/tutorial/installing-tensorflow-neural-network-software-for-cpu-and-gpu-on-ubuntu-16-04/
|
||||
|
||||
作者:[Akshay Pai][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.howtoforge.com/tutorial/installing-tensorflow-neural-network-software-for-cpu-and-gpu-on-ubuntu-16-04/
|
||||
[1]:https://www.howtoforge.com/tutorial/installing-tensorflow-neural-network-software-for-cpu-and-gpu-on-ubuntu-16-04/#-install-cuda
|
||||
[2]:https://www.howtoforge.com/tutorial/installing-tensorflow-neural-network-software-for-cpu-and-gpu-on-ubuntu-16-04/#-install-the-cudnn-library
|
||||
[3]:https://www.howtoforge.com/tutorial/installing-tensorflow-neural-network-software-for-cpu-and-gpu-on-ubuntu-16-04/#-add-the-installation-location-to-bashrc-file
|
||||
[4]:https://www.howtoforge.com/tutorial/installing-tensorflow-neural-network-software-for-cpu-and-gpu-on-ubuntu-16-04/#-install-tensorflow-with-gpu-support
|
||||
[5]:https://www.howtoforge.com/tutorial/installing-tensorflow-neural-network-software-for-cpu-and-gpu-on-ubuntu-16-04/#-install-tensorflow-with-only-cpu-support
|
||||
[6]:https://developer.nvidia.com/compute/machine-learning/cudnn/secure/v5.1/prod_20161129/8.0/libcudnn5_5.1.10-1+cuda8.0_amd64-deb
|
||||
[7]:https://developer.nvidia.com/compute/machine-learning/cudnn/secure/v5.1/prod_20161129/8.0/libcudnn5-dev_5.1.10-1+cuda8.0_amd64-deb
|
||||
[8]:https://developer.nvidia.com/group/node/873374/subscribe/og_user_node
|
||||
[9]:https://developer.nvidia.com/rdp/form/cudnn-download-survey
|
||||
[10]:http://sourcedexter.com/what-is-tensorflow/
|
||||
[11]:https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64-deb
|
||||
[12]:https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/big/image1.png
|
||||
[13]:https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/big/image2.png
|
||||
[14]:https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/big/image3.png
|
||||
[15]:https://www.howtoforge.com/images/installing_tensorflow_machine_learning_software_for_cpu_and_gpu_on_ubuntu_1604/big/image4.png
|
||||
[16]:https://www.tensorflow.org/get_started/mnist/beginners
|
||||
[17]:https://www.tensorflow.org/tutorials/image_recognition
|
@ -0,0 +1,59 @@
|
||||
Linux 系统调用的初学者指南
|
||||
============================================================
|
||||
|
||||
![A beginner's guide to Linux syscalls](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/rh_003499_01_linux11x_cc.png?itok=ZivAkk-L "A beginner's guide to Linux syscalls")
|
||||
|
||||
>图片提供: opensource.com
|
||||
|
||||
在过去的几年中,我一直在做大量容器相关的工作。先前,我看到 [Julien Friedman][7] 的一个很棒的演讲,它用几行 Go 语言写了一个容器框架。这让我突然了解到容器只是一个受限的 Linux 进程中的机器。
|
||||
|
||||
构建这个受限视图涉及到 [Golang 系统调用包][8]中的很多调用。最初,我只是用到了表面的那些,但过了一段时间,我想剥下洋葱的下一层,看看这些系统调用是什么,以及它们的工作原理。我将在 OSCON 的演讲中分享我所学到的东西。
|
||||
|
||||
顾名思义,[syscalls][9] 即系统调用,它们是你从用户空间请求进入 Linux 内核的方式。内核为你做一些工作,例如创建一个进程,然后再回到用户空间。
|
||||
|
||||
有一个常见的机制使所有的系统调用转换到内核,这是由 **libc** 库处理的。 用户空间代码设置一些寄存器,包括其想要的系统调用的 ID 以及需要传递给系统调用的所有参数。它触发一个 “陷阱” 将控制转换到内核。
|
||||
|
||||
这就是用户空间代码如何向内核请求的,而 Linux 也有一个伪文件系统,它允许内核将信息传递给用户空间,其内容看起来像普通的目录和文件。
|
||||
|
||||
`/proc` 目录是一个很好的例子。看看里面,你会发现有关机器上运行的进程的各种有趣的信息。在某些情况,像 **cgroups**(控制组)那样,用户空间可以通过写入这些伪文件系统下的文件来配置参数。
|
||||
|
||||
当你在使用容器时,特别有趣的是,主机的 `/proc` 包含了所有有关容器化的进程的信息。这包括环境变量,它们也保存在 `/proc` 伪文件系统中,这意味着你的主机可以访问所有正在运行的容器的环境。如果你通过环境变量将诸如凭证或数据库密码这类秘密传递到容器中,则可能会产生安全性后果。
|
||||
|
||||
许多编写常规程序的程序员可能不觉得他们经常使用系统调用。但实际上他们会经常调用,因为每天的活动比如制作文件或者更改目录都涉及 Linux 的系统调用。
|
||||
|
||||
你不必是一位系统程序员才能享受系统调用的乐趣!
|
||||
|
||||
|
||||
_如果你想要了解更多_,Liz 会在 Austin,Texas 举办的 OSCON 2017 上演讲 [_Linux 系统调用的初学者指南_][10]。如果你对参加会议感兴趣,_[当你在注册时][11]_,使用这个折扣码:_**PCOS**_。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Liz Rice - Liz Rice 是一位技术传播者,也是 Aqua Security 的容器安全专家。此前,她共同创立了 Microscaling Systems,并开发了其实时伸缩引擎,以及流行的图像元数据网站 MicroBadger.com。她拥有丰富的从网络协议和分布式系统,以及数字技术领域,如 VOD,音乐和 VoIP 软件的开发、团队和产品管理经验。
|
||||
|
||||
----------
|
||||
|
||||
|
||||
via: https://opensource.com/article/17/5/beginners-guide-syscalls
|
||||
|
||||
作者:[Liz Rice][a]
|
||||
译者:[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/lizrice
|
||||
[1]:https://opensource.com/resources/what-is-linux?src=linux_resource_menu
|
||||
[2]:https://opensource.com/resources/what-are-linux-containers?src=linux_resource_menu
|
||||
[3]:https://developers.redhat.com/promotions/linux-cheatsheet/?intcmp=7016000000127cYAAQ
|
||||
[4]:https://developers.redhat.com/cheat-sheet/advanced-linux-commands-cheatsheet?src=linux_resource_menu&intcmp=7016000000127cYAAQ
|
||||
[5]:https://opensource.com/tags/linux?src=linux_resource_menu
|
||||
[6]:https://opensource.com/article/17/5/beginners-guide-syscalls?rate=BT-vq0qMILAvJVxPFqug17N1RfhoAb_vkwNqRZFAqLQ
|
||||
[7]:https://twitter.com/doctor_julz
|
||||
[8]:https://golang.org/pkg/syscall/
|
||||
[9]:http://man7.org/linux/man-pages/man2/syscalls.2.html
|
||||
[10]:https://conferences.oreilly.com/oscon/oscon-tx/public/schedule/detail/56840
|
||||
[11]:http://www.oreilly.com/pub/cpc/44407?sc_cid=701600000012BzSAAU%20target=%22_blank%22
|
||||
[12]:https://opensource.com/user/129431/feed
|
||||
[13]:https://opensource.com/users/lizrice
|
@ -0,0 +1,82 @@
|
||||
T-UI Launcher:将你的 Android 设备变成 Linux 命令行界面
|
||||
============================================================
|
||||
|
||||
不管你是一位命令行大师,还是只是不想让你的朋友和家人使用你的 Android 设备,那就看下 T-UI Launcher 这个程序。Unix/Linux 用户一定会喜欢这个。
|
||||
|
||||
T-UI Launcher 是一个免费的轻量级 Android 程序,具有类似 Linux 的命令行界面,它可将你的普通 Android 设备变成一个完整的命令行界面。对于喜欢使用基于文本的界面的人来说,这是一个简单、快速、智能的启动器。
|
||||
|
||||
#### T-UI Launcher 功能
|
||||
|
||||
下面是一些重要的功能:
|
||||
|
||||
* 第一次启动后展示快速使用指南。
|
||||
* 快速且可完全定制。
|
||||
* 提供自动补全菜单及快速、强大的别名系统。
|
||||
* 此外,提供预测建议,并提供有用的搜索功能。
|
||||
|
||||
它是免费的,你可以从 Google Play 商店[下载并安装它][1],接着在 Android 设备中运行。
|
||||
|
||||
安装完成后,第一次启动时你会看到一个快速指南。阅读完成之后,你可以如下面那样使用简单的命令开始使用了。
|
||||
|
||||
[![T-UI Commandline Help Guide](https://www.tecmint.com/wp-content/uploads/2017/05/T-UI-Commandline-Help.jpg)][2]
|
||||
|
||||
*T-UI 命令行帮助指南*
|
||||
|
||||
要启动一个 app,只要输入几个字母,自动补全功能会在屏幕中展示可用的 app。接着点击你想打开的程序。
|
||||
|
||||
```
|
||||
$ Telegram ### 启动 telegram
|
||||
$ WhatsApp ### 启动 whatsapp
|
||||
$ Chrome ### 启动 chrome
|
||||
```
|
||||
|
||||
[![T-UI Commandline Usage](https://www.tecmint.com/wp-content/uploads/2017/05/T-UI-Commandline-Usage.jpg)][3]
|
||||
|
||||
*T-UI 命令行使用*
|
||||
|
||||
要浏览你的 Android 设备状态(电池电量、wifi、移动数据),输入:
|
||||
|
||||
```
|
||||
$ status
|
||||
```
|
||||
|
||||
[![Android Phone Status](https://www.tecmint.com/wp-content/uploads/2017/05/T-UI-Commandline-Status.jpg)][4]
|
||||
|
||||
*Android 电话状态*
|
||||
|
||||
其它的有用命令。
|
||||
|
||||
```
|
||||
$ uninstall telegram ### 卸载 telegram
|
||||
$ search [google, playstore, youtube, files] ### 搜索在线应用或本地文件
|
||||
$ wifi ### 打开或关闭 WIFI
|
||||
$ cp Downloads/* Music ### 从 Download 文件夹复制所有文件到 Music 文件夹
|
||||
$ mv Downloads/* Music ### 从 Download 文件夹移动所有文件到 Music 文件夹
|
||||
```
|
||||
|
||||
就是这样了!在本篇中,我们展示了一个带有类似 Linux CLI(命令界面)的简单而有用的 Android 程序,它可以将你的常规 Android 设备变成一个完整的命令行界面。尝试一下并在下面的评论栏分享你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 和 F.O.S.S 爱好者,将来的 Linux 系统管理员和网络开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并坚信分享知识。
|
||||
|
||||
------------------
|
||||
|
||||
via: https://www.tecmint.com/t-ui-launcher-turns-android-device-into-linux-cli/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://play.google.com/store/apps/details?id=ohi.andre.consolelauncher
|
||||
[2]:https://www.tecmint.com/wp-content/uploads/2017/05/T-UI-Commandline-Help.jpg
|
||||
[3]:https://www.tecmint.com/wp-content/uploads/2017/05/T-UI-Commandline-Usage.jpg
|
||||
[4]:https://www.tecmint.com/wp-content/uploads/2017/05/T-UI-Commandline-Status.jpg
|
||||
[5]:https://www.tecmint.com/author/aaronkili/
|
||||
[6]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[7]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,89 @@
|
||||
WPSeku:一个找出 WordPress 安全问题的漏洞扫描器
|
||||
============================================================
|
||||
|
||||
WordPress 是一个免费开源、可高度自定义的内容管理系统(CMS),它被全世界数以百万计的人来运行博客和完整的网站。因为它是被用的最多的 CMS,因此有许多潜在的 WordPress 安全问题/漏洞需要考虑。
|
||||
|
||||
然而,如果我们遵循通常的 WordPress 最佳实践,这些安全问题可以避免。在本篇中,我们会向你展示如何使用 WPSeku,一个 Linux 中的 WordPress 漏洞扫描器,它可以被用来找出你安装的 WordPress 的安全漏洞,并阻止潜在的威胁。
|
||||
|
||||
WPSeku 是一个用 Python 写的简单的 WordPress 漏洞扫描器,它可以被用来扫描本地以及远程安装的 WordPress 来找出安全问题。
|
||||
|
||||
### 如何安装 WPSeku - Linux 中的 WordPress 漏洞扫描器
|
||||
|
||||
要在 Linux 中安装 WPSeku,你需要如下从 Github clone 最新版本的 WPSeku。
|
||||
|
||||
```
|
||||
$ cd ~
|
||||
$ git clone https://github.com/m4ll0k/WPSeku
|
||||
```
|
||||
|
||||
完成之后,进入 WPSeku 目录,并如下运行。
|
||||
|
||||
```
|
||||
$ cd WPSeku
|
||||
```
|
||||
|
||||
使用 `-u` 选项指定 WordPress 的安装 URL,如下运行 WPSeku:
|
||||
|
||||
```
|
||||
$ ./wpseku.py -u http://yourdomain.com
|
||||
```
|
||||
|
||||
[![WordPress Vulnerability Scanner](https://www.tecmint.com/wp-content/uploads/2017/05/WordPress-Vulnerability-Scanner.png)][1]
|
||||
|
||||
*WordPress 漏洞扫描器*
|
||||
|
||||
以下命令使用 `-p` 选项搜索 WordPress 插件中的跨站脚本(`x`)、本地文件夹嵌入(`l`)和 SQL 注入(`s`)漏洞,你需要在 URL 中指定插件的位置:
|
||||
|
||||
```
|
||||
$ ./wpseku.py -u http://yourdomain.com/wp-content/plugins/wp/wp.php?id= -p [x,l,s]
|
||||
```
|
||||
|
||||
以下命令将使用 `-b` 选项通过 XML-RPC 执行暴力密码登录。另外,你可以使用 `--user` 和 `--wordlist` 选项分别设置用户名和单词列表,如下所示。
|
||||
|
||||
```
|
||||
$ ./wpseku.py -u http://yourdomian.com --user username --wordlist wordlist.txt -b [l,x]
|
||||
```
|
||||
|
||||
要浏览所有 WPSeku 使用选项,输入:
|
||||
|
||||
```
|
||||
$ ./wpseku.py --help
|
||||
```
|
||||
|
||||
[![WPSeku WordPress Vulnerability Scanner Help](https://www.tecmint.com/wp-content/uploads/2017/05/WPSeku-WordPress-Vulnerability-Scanner-Help.png)][2]
|
||||
|
||||
*WPSeku WordPress 漏洞扫描帮助*
|
||||
|
||||
WPSeku Github 仓库:[https://github.com/m4ll0k/WPSeku][3]
|
||||
|
||||
就是这样了!在本篇中,我们向你展示了如何在 Linux 中获取并使用 WPSeku 用于 WordPress 漏洞扫描。WordPress 是安全的,但需要我们遵循 WordPress 安全最佳实践才行。你有要分享的想法么?如果有,请在评论区留言。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一个 Linux 及 F.O.S.S 热衷者,即将成为 Linux 系统管理员、web 开发者,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并坚信分享知识。
|
||||
|
||||
------------------
|
||||
|
||||
via: https://www.tecmint.com/wpseku-wordpress-vulnerability-security-scanner/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/wp-content/uploads/2017/05/WordPress-Vulnerability-Scanner.png
|
||||
[2]:https://www.tecmint.com/wp-content/uploads/2017/05/WPSeku-WordPress-Vulnerability-Scanner-Help.png
|
||||
[3]:https://github.com/m4ll0k/WPSeku
|
||||
[4]:https://www.tecmint.com/wpseku-wordpress-vulnerability-security-scanner/#
|
||||
[5]:https://www.tecmint.com/wpseku-wordpress-vulnerability-security-scanner/#
|
||||
[6]:https://www.tecmint.com/wpseku-wordpress-vulnerability-security-scanner/#
|
||||
[7]:https://www.tecmint.com/wpseku-wordpress-vulnerability-security-scanner/#
|
||||
[8]:https://www.tecmint.com/wpseku-wordpress-vulnerability-security-scanner/#comments
|
||||
[9]:https://www.tecmint.com/author/aaronkili/
|
||||
[10]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[11]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,107 @@
|
||||
ttyload:在终端中用彩色显示 Linux 的平均负载
|
||||
============================================================
|
||||
|
||||
ttyload 是一个轻量级的实用程序,它为 Linux 和其他类 Unix 系统上提供随着时间变化的彩色平均负载。它实现了在终端中(“tty”)图形化跟踪系统的平均负载。
|
||||
|
||||
它已知可以在诸如 Linux、IRIX、Solaris、FreeBSD、MacOS X (Darwin) 和 Isilon OneFS 等系统上运行。它被设计为可以容易地移植到其他平台,但这也带来了一些艰苦的工作。
|
||||
|
||||
它的一些值得注意功能是:它使用标准的硬编码 ANSI 转义序列进行屏幕显示和着色。如果你想要在一个没有什么负载压力的系统中查看工作的情况,它甚至还自带了一个相对独立(默认不会安装,甚至不会构建)的负载炸弹。
|
||||
|
||||
**建议阅读:**[GoTTY:把你的 Linux 终端放到浏览器里面][1]
|
||||
|
||||
在本篇中,我们会向你展示如何在 Linux 安装及使用 ttyload,以在终端中用彩色图形查看系统的平均负载。
|
||||
|
||||
### 如何在 Linux 中安装 ttyload
|
||||
|
||||
在基于 Debian/Ubuntu 的发行版中,你可以输入下面的 [apt 命令][2]来从默认的系统仓库中安装 ttyload。
|
||||
|
||||
```
|
||||
$ sudo apt-get install ttyload
|
||||
```
|
||||
|
||||
在其他发行版中,你可以如下从 ttyload 的源码安装。
|
||||
|
||||
```
|
||||
$ git clone https://github.com/lindes/ttyload.git
|
||||
$ cd ttyload
|
||||
$ make
|
||||
$ ./ttyload
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
安装完成后,你可以输入下面的命令启动。
|
||||
|
||||
```
|
||||
$ ttyload
|
||||
```
|
||||
|
||||
[![ttyload - Graphical View of Linux Load Average](https://www.tecmint.com/wp-content/uploads/2017/05/ttyload-Graphical-View-of-Linux-Load-Average-.png)][3]
|
||||
|
||||
*ttyload - 图形浏览 Linux 的平均负载*
|
||||
|
||||
注意:要关闭程序,只需按下 `Ctrl+C` 键。
|
||||
|
||||
你也可以定义两次刷新之间间隔的秒数。默认是 4 秒,最小是 1 秒。
|
||||
|
||||
```
|
||||
$ ttyload -i 5
|
||||
$ ttyload -i 1
|
||||
```
|
||||
|
||||
要以单色模式运行,即它会关闭 ANSI 转义,如下使用 `-m`:
|
||||
|
||||
```
|
||||
$ ttyload -m
|
||||
```
|
||||
|
||||
[![ttyload - Monochrome Mode](https://www.tecmint.com/wp-content/uploads/2017/05/ttyload-monochrome-mode.png)][4]
|
||||
|
||||
*ttyload – 单色模式*
|
||||
|
||||
要获取 ttyload 的使用信息以及帮助,输入:
|
||||
|
||||
```
|
||||
$ ttyload -h
|
||||
```
|
||||
|
||||
下面是一些尚不支持的重要功能:
|
||||
|
||||
* 支持任意大小调整。
|
||||
* 使用相同的基本引擎制作 X 前端,“3xload”。
|
||||
* 面向日志的模式。
|
||||
|
||||
要获得更多信息,访问 ttyload 的主页:[http://www.daveltd.com/src/util/ttyload/][5]
|
||||
|
||||
就是这样了!在本文中,我们向你展示了如何在 Linux 中安装及使用 ttyload。通过下面的评论栏给我们回馈。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一个 Linux 和 F.O.S.S 的爱好者,即将推出的 Linux SysAdmin 网络开发人员,目前也是 TecMint 的内容创作者,他喜欢和电脑一起工作,并且坚信共享知识。
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
via: https://www.tecmint.com/ttyload-shows-color-coded-graph-of-linux-load-average/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://linux.cn/article-8445-1.html
|
||||
[2]:https://www.tecmint.com/useful-basic-commands-of-apt-get-and-apt-cache-for-package-management/
|
||||
[3]:https://www.tecmint.com/wp-content/uploads/2017/05/ttyload-Graphical-View-of-Linux-Load-Average-.png
|
||||
[4]:https://www.tecmint.com/wp-content/uploads/2017/05/ttyload-monochrome-mode.png
|
||||
[5]:http://www.daveltd.com/src/util/ttyload/
|
||||
[6]:https://www.tecmint.com/ttyload-shows-color-coded-graph-of-linux-load-average/#
|
||||
[7]:https://www.tecmint.com/ttyload-shows-color-coded-graph-of-linux-load-average/#
|
||||
[8]:https://www.tecmint.com/ttyload-shows-color-coded-graph-of-linux-load-average/#
|
||||
[9]:https://www.tecmint.com/ttyload-shows-color-coded-graph-of-linux-load-average/#
|
||||
[10]:https://www.tecmint.com/ttyload-shows-color-coded-graph-of-linux-load-average/#comments
|
||||
[11]:https://www.tecmint.com/author/aaronkili/
|
||||
[12]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[13]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,125 @@
|
||||
4 个拥有绝佳命令行界面的终端程序
|
||||
============================================================
|
||||
|
||||
> 让我们来看几个精心设计的 CLI 程序,以及如何解决一些可发现性问题。
|
||||
|
||||
![4 awesome command-line tools](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/code_computer_development_programming.png?itok=wMspQJcO "4 awesome command-line tools")
|
||||
|
||||
>图片提供: opensource.com
|
||||
|
||||
在本文中,我会指出命令行界面的<ruby>可发现性<rt>discoverability</rt></ruby>缺点以及克服这些问题的几种方法。
|
||||
|
||||
我喜欢命令行。我第一次接触命令行是在 1997 的 DOS 6.2 上。我学习了各种命令的语法,并展示了如何在目录中列出隐藏的文件(`attrib`)。我会每次仔细检查命令中的每个字符。 当我犯了一个错误,我会从头开始重新输入命令。直到有一天,有人向我展示了如何使用向上和向下箭头按键遍历命令行历史,我被震惊了。
|
||||
|
||||
后来当我接触到 Linux 时,让我感到惊喜的是,上下箭头保留了它们遍历历史记录的能力。我仍然很仔细地打字,但是现在,我了解如何盲打,并且我能打的很快,每分钟可以达到 55 个单词的速度。接着有人向我展示了 tab 补完,再一次改变了我的生活。
|
||||
|
||||
在 GUI 应用程序中,菜单、工具提示和图标用于向用户展示功能。而命令行缺乏这种能力,但是有办法克服这个问题。在深入解决方案之前,我会来看看几个有问题的 CLI 程序:
|
||||
|
||||
**1、 MySQL**
|
||||
|
||||
首先让我们看看我们所钟爱的 MySQL REPL。我经常发现自己在输入 `SELECT * FROM` 然后按 `Tab` 的习惯。MySQL 会询问我是否想看到所有的 871 种可能性。我的数据库中绝对没有 871 张表。如果我选择 `yes`,它会显示一堆 SQL 关键字、表、函数等。(LCTT 译注:REPL —— Read-Eval-Print Loop,交互式开发环境)
|
||||
|
||||
![MySQL gif](https://opensource.com/sites/default/files/mysql.gif)
|
||||
|
||||
**2、 Python**
|
||||
|
||||
我们来看另一个例子,标准的 Python REPL。我开始输入命令,然后习惯按 `Tab` 键。瞧,插入了一个 `Tab` 字符,考虑到 `Tab` 在 Python 源代码中没有特定作用,这是一个问题。
|
||||
|
||||
![Python gif](https://opensource.com/sites/default/files/python.gif "Python gif")
|
||||
|
||||
### 好的用户体验
|
||||
|
||||
让我看下设计良好的 CLI 程序以及它们是如何克服这些可发现性问题的。
|
||||
|
||||
#### 自动补全: bpython
|
||||
|
||||
[Bpython][15] 是对 Python REPL 的一个很好的替代。当我运行 bpython 并开始输入时,建议会立即出现。我没用通过特殊的键盘绑定触发它,甚至没有按下 `Tab` 键。
|
||||
|
||||
![bpython gif](https://opensource.com/sites/default/files/bpython.gif "bpython gif")
|
||||
|
||||
当我出于习惯按下 `Tab` 键时,它会用列表中的第一个建议补全。这是给 CLI 设计带来可发现性性的一个很好的例子。
|
||||
|
||||
bpython 的另一个方面是可以展示模块和函数的文档。当我输入一个函数的名字时,它会显示这个函数附带的签名以及文档字符串。这是一个多么令人难以置信的周到设计啊。
|
||||
|
||||
#### 上下文感知补全:mycli
|
||||
|
||||
[mycli][16] 是默认的 MySQL 客户端的现代替代品。这个工具对 MySQL 来说就像 bpython 之于标准 Python REPL 一样。mycli 将在你输入时自动补全关键字、表名、列和函数。
|
||||
|
||||
补全建议是上下文相关的。例如,在 `SELECT * FROM` 之后,只有来自当前数据库的表才会列出,而不是所有可能的关键字。
|
||||
|
||||
![mycli gif](https://opensource.com/sites/default/files/mycli.gif "mycli gif")
|
||||
|
||||
#### 模糊搜索和在线帮助: pgcli
|
||||
|
||||
如果您正在寻找 PostgreSQL 版本的 mycli,请看看 [pgcli][17]。 与 mycli 一样,它提供了上下文感知的自动补全。菜单中的项目使用模糊搜索缩小范围。模糊搜索允许用户输入整体字符串中的任意子字符串来尝试找到正确的匹配项。
|
||||
|
||||
![pgcli gif](https://opensource.com/sites/default/files/pgcli.gif "pgcli gif")
|
||||
|
||||
pgcli 和 mycli 在其 CLI 中都实现了这个功能。斜杠命令的文档也作为补全菜单的一部分展示。
|
||||
|
||||
#### 可发现性: fish
|
||||
|
||||
在传统的 Unix shell(Bash、zsh 等)中,有一种搜索历史记录的方法。此搜索模式由 `Ctrl-R` 触发。当再次调用你上周运行过的命令时,例如 **ssh**或 **docker**,这是一个令人难以置信的有用的工具。 一旦你知道这个功能,你会发现自己经常会使用它。
|
||||
|
||||
如果这个功能是如此有用,那为什么不每次都搜索呢?这正是 [**fish** shell][18] 所做的。一旦你开始输入命令,**fish** 将开始建议与历史记录类似的命令。然后,你可以按右箭头键接受该建议。
|
||||
|
||||
### 命令行规矩
|
||||
|
||||
我已经回顾了一些解决可发现性的问题的创新方法,但也有一些基本的命令行功能应该作为每个 REPL 所实现基础功能的一部分:
|
||||
|
||||
* 确保 REPL 有可通过箭头键调用的历史记录。确保会话之间的历史持续存在。
|
||||
* 提供在编辑器中编辑命令的方法。不管你的补全是多么棒,有时用户只需要一个编辑器来制作完美的命令来删除生产环境中所有的表。
|
||||
* 使用分页器(`pager`)来管道输出。不要让用户滚动他们的终端。哦,要为分页器设置个合理的默认值。(记得添加选项来处理颜色代码。)
|
||||
* 提供一种通过 `Ctrl-R` 界面或者 fish 式的自动搜索来搜索历史记录的方法。
|
||||
|
||||
### 总结
|
||||
|
||||
在第 2 节中,我将来看看 Python 中使你能够实现这些技术的特定库。同时,请查看其中一些精心设计的命令行应用程序:
|
||||
|
||||
* [bpython][5]或 [ptpython][6]:具有自动补全支持的 Python REPL。
|
||||
* [http-prompt][7]:交互式 HTTP 客户端。
|
||||
* [mycli][8]:MySQL、MariaDB 和 Percona 的命令行界面,具有自动补全和语法高亮。
|
||||
* [pgcli][9]:具有自动补全和语法高亮,是对 [psql][10] 的替代工具。
|
||||
* [wharfee][11]:用于管理 Docker 容器的 shell。
|
||||
|
||||
_了解更多: Amjith Ramanujam 在 5 月 20 日在波特兰俄勒冈州举办的 [PyCon US 2017][12] 上的谈话“[神奇的命令行工具][13]”。_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
作者简介:
|
||||
|
||||
Amjith Ramanujam - Amjith Ramanujam 是 pgcli 和 mycli 的创始人。人们认为它们很酷,他表示笑纳赞誉。他喜欢用 Python、Javascript 和 C 编程。他喜欢编写简单易懂的代码,它们有时甚至会成功。
|
||||
|
||||
-----------------------
|
||||
|
||||
via: https://opensource.com/article/17/5/4-terminal-apps
|
||||
|
||||
作者:[Amjith Ramanujam][a]
|
||||
译者:[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/amjith
|
||||
[1]:https://opensource.com/tags/python?src=programming_resource_menu
|
||||
[2]:https://opensource.com/tags/javascript?src=programming_resource_menu
|
||||
[3]:https://opensource.com/tags/perl?src=programming_resource_menu
|
||||
[4]:https://developers.redhat.com/?intcmp=7016000000127cYAAQ&src=programming_resource_menu
|
||||
[5]:http://bpython-interpreter.org/
|
||||
[6]:http://github.com/jonathanslenders/ptpython/
|
||||
[7]:https://github.com/eliangcs/http-prompt
|
||||
[8]:http://mycli.net/
|
||||
[9]:http://pgcli.com/
|
||||
[10]:https://www.postgresql.org/docs/9.2/static/app-psql.html
|
||||
[11]:http://wharfee.com/
|
||||
[12]:https://us.pycon.org/2017/
|
||||
[13]:https://us.pycon.org/2017/schedule/presentation/518/
|
||||
[14]:https://opensource.com/article/17/5/4-terminal-apps?rate=3HL0zUQ8_dkTrinonNF-V41gZvjlRP40R0RlxTJQ3G4
|
||||
[15]:https://bpython-interpreter.org/
|
||||
[16]:http://mycli.net/
|
||||
[17]:http://pgcli.com/
|
||||
[18]:https://fishshell.com/
|
||||
[19]:https://opensource.com/user/125521/feed
|
||||
[20]:https://opensource.com/article/17/5/4-terminal-apps#comments
|
||||
[21]:https://opensource.com/users/amjith
|
@ -0,0 +1,151 @@
|
||||
怎样在 Linux 中用 Vim 对文件进行密码保护
|
||||
============================================================
|
||||
|
||||
[Vim][5] 是一种流行的、功能丰富的和高度可扩展的 [Linux 文本编辑器][6],它的一个特殊功能便是支持用带密码各种的加密方法来加密文本文件。
|
||||
|
||||
本文中,我们将向你介绍一种简单的 Vim 使用技巧:在 Linux 中使用 Vim 对文件进行密码保护。我们将向你展示如何让一个文件在它创建的时侯以及为了修改目的而被打开了之后获得安全防护。
|
||||
|
||||
**建议阅读:** [你应该在 Linux 中使用 Vim 编辑器的 7 个原因][7]
|
||||
|
||||
要安装 Vim 完整版,只需运行这些命令:
|
||||
|
||||
```
|
||||
$ sudo apt install vim #Debian/Ubuntu 系统
|
||||
$ sudo yum install vim #RHEL/CentOS 系统
|
||||
$ sudo dnf install vim #Fedora 22+
|
||||
```
|
||||
参阅: [十年后 Vim 8.0 发布了][8a] – [在 Linux 上安装][8]
|
||||
|
||||
### 怎样在 Linux 中用 Vim 对文件进行密码保护
|
||||
|
||||
Vim 有个 `-x` 选项,这个选项能让你在创建文件时用它来加密。一旦你运行下面的 [vim 命令][9],你会被提示输入一个密钥:
|
||||
|
||||
```
|
||||
$ vim -x file.txt
|
||||
警告:正在使用弱加密方法;参见 :help 'cm'
|
||||
输入加密密钥:*******
|
||||
再次输入相同密钥:*******
|
||||
```
|
||||
|
||||
如果第二次输入的密钥无误,你就能可以修改此文件了。
|
||||
|
||||
[![Vim File Password Protected](https://www.tecmint.com/wp-content/uploads/2017/05/Vim-File-Password-Protected-File.png)][10]
|
||||
|
||||
*被密码保护的 Vim 文件*
|
||||
|
||||
等你修改好之后,摁 `Esc` 和键入 `:wq` 来保存及关闭文件。下次你想打开它编辑一下,你就必须像这样去输入密钥:
|
||||
|
||||
```
|
||||
$ vim file.txt
|
||||
需要 "file.txt" 的加密密钥
|
||||
警告:正在使用弱加密方法;参见 :help 'cm'
|
||||
输入密钥:*******
|
||||
```
|
||||
|
||||
假设你输了一个错误的密码(或者没输密码),你会看到一些垃圾字符。
|
||||
|
||||
[![Vim Content Encrypted](https://www.tecmint.com/wp-content/uploads/2017/05/Vim-Content-Encrypted.png)][11]
|
||||
|
||||
*Vim 中的加密内容*
|
||||
|
||||
#### 在 Vim 中设置一种强加密方法
|
||||
|
||||
注意:警告信息暗示保护文件的是弱加密方法。那么接下来,我们来看看怎么在 Vim 中设置一种强加密方法。
|
||||
|
||||
[![Weak Encryption on Vim File](https://www.tecmint.com/wp-content/uploads/2017/05/Weak-Encryption-on-Vim-File.png)][12]
|
||||
|
||||
*Vim 中文件弱加密*
|
||||
|
||||
为了查看加密方式(cm)集,键入如下:
|
||||
|
||||
```
|
||||
:help 'cm'
|
||||
```
|
||||
|
||||
输出样例:
|
||||
|
||||
```
|
||||
*'cryptmethod'* *'cm'*
|
||||
'cryptmethod' string (默认 "zip")
|
||||
全局或本地到缓冲区 |global-local|
|
||||
{not in Vi}
|
||||
当缓冲区写进文件中所用的加密方式:
|
||||
*pkzip*
|
||||
zip PkZip 兼容方式。 一种弱加密方法。
|
||||
与 Vim 7.2 及更老版本后向兼容。
|
||||
*blowfish*
|
||||
blowfish 河豚加密方式。 中级强度加密方法但有实现上
|
||||
的瑕疵。需要 Vim 7.3 及以上版本,用它加密的文件不
|
||||
能被 Vim 7.2 及更老版本读取。它会添加一个 “种子”,
|
||||
每次你当你写入文件时,这个加密字节都不同。
|
||||
|
||||
```
|
||||
|
||||
你可以像如下所示的那样给一个 Vim 文件设置个新的加密方法(本例中我们用 `blowfish2` 加密方法)
|
||||
|
||||
```
|
||||
:setlocal cm=blowfish2
|
||||
```
|
||||
|
||||
然后键入回车和 `:wq` 保存文件。
|
||||
|
||||
[![Set Strong Encryption on Vim File](https://www.tecmint.com/wp-content/uploads/2017/05/Set-Strong-Encryption-on-Vim-File.png)][13]
|
||||
|
||||
*对 Vim 文件设置强加密*
|
||||
|
||||
现在你再打开下面的文件时应该就看不到那条警告信息了。
|
||||
|
||||
```
|
||||
$ vim file.txt
|
||||
需要 "file.txt" 的加密密钥
|
||||
输入加密密钥:*******
|
||||
```
|
||||
|
||||
你也可以在打开 Vim 文件之后来设置密码,用 `:X` 命令就能像上面所示的那样去设置一个加密密码。
|
||||
|
||||
可以看看我们其他的关于 Vim 编辑器的有用的文章。
|
||||
|
||||
1. [在 Linux 中学习有用的 Vim 编辑器的技巧][1]
|
||||
2. [给每个 Linux 用户的 8 种有用的 Vim 编辑器技巧][2]
|
||||
3. [spf13-vim – Vim 编辑器的顶级分发版][3]
|
||||
4. [怎样在 Linux 种把 Vim 编辑当作 Bash IDE 来用][4]
|
||||
|
||||
本文到这里就结束了!文章中我们介绍了怎么通过 Linux 下的 Vim 文本编辑器来给一个文件做加密防护。
|
||||
|
||||
永远记住要用强加密方式及密码来适当的保护那些可能包含了诸如用户名及密码、财务账户信息等机密信息的文本文件。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一个 Linux 和 F.O.S.S(Free and Open-Source Software,自由及开放源代码软件)爱好者,未来的 Linux 系统管理员、Web 开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,且崇尚分享知识。
|
||||
|
||||
------------------
|
||||
|
||||
via: https://www.tecmint.com/password-protect-vim-file-in-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ch-cn](https://github.com/ch-cn)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/learn-vi-and-vim-editor-tips-and-tricks-in-linux/
|
||||
[2]:https://www.tecmint.com/how-to-use-vi-and-vim-editor-in-linux/
|
||||
[3]:https://www.tecmint.com/spf13-vim-offers-vim-plugins-vim-editor/
|
||||
[4]:https://linux.cn/article-8467-1.html
|
||||
[5]:https://www.tecmint.com/vi-editor-usage/
|
||||
[6]:https://www.tecmint.com/best-open-source-linux-text-editors/
|
||||
[7]:https://linux.cn/article-7728-1.html
|
||||
[8a]:https://linux.cn/article-7766-1.html
|
||||
[8]:https://linux.cn/article-8094-1.html
|
||||
[9]:https://www.tecmint.com/linux-command-line-editors/
|
||||
[10]:https://www.tecmint.com/wp-content/uploads/2017/05/Vim-File-Password-Protected-File.png
|
||||
[11]:https://www.tecmint.com/wp-content/uploads/2017/05/Vim-Content-Encrypted.png
|
||||
[12]:https://www.tecmint.com/wp-content/uploads/2017/05/Weak-Encryption-on-Vim-File.png
|
||||
[13]:https://www.tecmint.com/wp-content/uploads/2017/05/Set-Strong-Encryption-on-Vim-File.png
|
||||
[14]:https://www.tecmint.com/vi-editor-usage/
|
||||
[15]:https://www.tecmint.com/author/aaronkili/
|
||||
[16]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[17]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,82 @@
|
||||
如何在 Linux 中删除大(100-200GB)文件
|
||||
============================================================
|
||||
|
||||
通常,要[在 Linux 终端删除一个文件][1],我们使用 rm 命令(删除文件)、shred 命令(安全删除文件)、wipe 命令(安全擦除文件)或者 secure-deletion 工具包(一个[安全文件删除工具][2]集合)。
|
||||
|
||||
我们可以使用上面任意的工具来处理相对较小的文件。如果我们想要删除大的文件/文件夹,比如大概 100-200GB。这个方法在删除文件(I/O 调度)所花费的时间以及 RAM 占用量方面看起来可能并不容易。
|
||||
|
||||
在本教程中,我们会解释如何在 Linux 中有效率并可靠地删除大文件/文件夹。
|
||||
|
||||
**建议阅读:** [5 个在 Linux 中清空或者删除大文件内容的方法][3]
|
||||
|
||||
主要的目标是使用一种不会在删除大文件时拖慢系统的技术,并有合理的 I/O 占用。我们可以用 **ionice 命令**实现这个目标。
|
||||
|
||||
### 在 Linux 中使用 ionice 命令删除大(200GB)文件
|
||||
|
||||
ionice 是一个可以为另一个程序设置或获取 I/O 调度级别和优先级的有用程序。如果没有给出参数或者只有 `-p`,那么 ionice 将会查询该进程的当前的 I/O 调度级别以及优先级。
|
||||
|
||||
如果我们给出命令名称,如 rm 命令,它将使用给定的参数运行此命令。要指定要获取或设置调度参数的[进程的进程 ID][4],运行这个:
|
||||
|
||||
```
|
||||
# ionice -p PID
|
||||
```
|
||||
|
||||
要指定名字或者调度的数字,使用(0 表示无、1 表示实时、2 表示尽力、3 表示空闲)下面的命令。
|
||||
|
||||
这意味这 rm 会属于空闲 I/O 级别,并且只在其他进程不使用的时候使用 I/O:
|
||||
|
||||
```
|
||||
---- Deleting Huge Files in Linux -----
|
||||
# ionice -c 3 rm /var/logs/syslog
|
||||
# ionice -c 3 rm -rf /var/log/apache
|
||||
```
|
||||
|
||||
如果系统中没有很多空闲时间,那么我们希望使用尽力调度级别,并且使用低优先级:
|
||||
|
||||
```
|
||||
# ionice -c 2 -n 6 rm /var/logs/syslog
|
||||
# ionice -c 2 -n 6 rm -rf /var/log/apache
|
||||
```
|
||||
|
||||
注意:要使用安全的方法删除大文件,我们可以使用先前提到的 shred、wipe 以及 secure-deletion 工具包中的不同工具,而不是 rm 命令。
|
||||
|
||||
**建议阅读:**[3 个在 Linux 中永久/安全删除文件/文件夹的方法][5]
|
||||
|
||||
要获取更多信息,查阅 ionice 的手册页:
|
||||
|
||||
```
|
||||
# man ionice
|
||||
```
|
||||
|
||||
就是这样了!你脑海里还有其他的方法么?在评论栏中与我们分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 和 F.O.S.S 爱好者,将来的 Linux 系统管理员和网络开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并坚信分享知识。
|
||||
|
||||
------------------
|
||||
|
||||
via: https://www.tecmint.com/delete-huge-files-in-linux/
|
||||
|
||||
作者:[Aaron Kili ][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/permanently-and-securely-delete-files-directories-linux/
|
||||
[2]:https://www.tecmint.com/permanently-and-securely-delete-files-directories-linux/
|
||||
[3]:https://www.tecmint.com/empty-delete-file-content-linux/
|
||||
[4]:https://www.tecmint.com/find-linux-processes-memory-ram-cpu-usage/
|
||||
[5]:https://www.tecmint.com/permanently-and-securely-delete-files-directories-linux/
|
||||
[6]:https://www.tecmint.com/delete-huge-files-in-linux/#
|
||||
[7]:https://www.tecmint.com/delete-huge-files-in-linux/#
|
||||
[8]:https://www.tecmint.com/delete-huge-files-in-linux/#
|
||||
[9]:https://www.tecmint.com/delete-huge-files-in-linux/#
|
||||
[10]:https://www.tecmint.com/delete-huge-files-in-linux/#comments
|
||||
[11]:https://www.tecmint.com/author/aaronkili/
|
||||
[12]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[13]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,77 @@
|
||||
在 Linux 服务器关机前向用户显示一条自定义消息
|
||||
============================================================
|
||||
|
||||
在先前的文章中,我们解释了 Linux 中 [shutdown、poweroff、halt、reboot 命令的不同之处][3],并揭示了在用不同的选项执行这些命令时它们实际做了什么。
|
||||
|
||||
本篇将会向你展示如何在系统关机时向所有的系统用户发送一条自定义的消息。
|
||||
|
||||
**建议阅读:**[tuptime - 显示 Linux 系统的历史和统计运行时间][4]
|
||||
|
||||
作为一名系统管理员,在你关闭服务器之前,你也许想要发送一条消息来警告他们系统将要关闭。默认上,`shutdown` 命令会如下所示给其他系统用户广播这条信息:
|
||||
|
||||
```
|
||||
# shutdown 13:25
|
||||
```
|
||||
Linux 关机操作广播消息:
|
||||
```
|
||||
Shutdown scheduled for Fri 2017-05-12 13:25:00 EAT, use 'shutdown -c' to cancel.
|
||||
Broadcast message for root@tecmint (Fri 2017-05-12 13:23:34 EAT):
|
||||
The system is going down for power-off at Fri 2017-05-12 13:25:00 EAT!
|
||||
```
|
||||
|
||||
要在 shutdown 那行发送一条自定义的消息给其他系统用户,运行下面的命令。在本例中,关闭会在命令执行后的两分钟之后发生。
|
||||
|
||||
```
|
||||
# shutdown 2 The system is going down for required maintenance. Please save any important work you are doing now!
|
||||
```
|
||||
[![Linux System Shutdown Message](https://www.tecmint.com/wp-content/uploads/2017/05/Linux-System-Shutdown-Message.png)][5]
|
||||
|
||||
*Linux 系统关闭消息*
|
||||
|
||||
假设你有一些关键的系统操作,如计划系统备份或更新会在系统关闭的时候进行,如下所示,你可以使用 `-c` 选项取消关机,并在执行玩这些操作后继续执行:
|
||||
|
||||
```
|
||||
# shutdown -c
|
||||
```
|
||||
Linux 关机操作取消消息:
|
||||
```
|
||||
Shutdown scheduled for Fri 2017-05-12 14:10:22 EAT, use 'shutdown -c' to cancel.
|
||||
Broadcast message for root@tecmint (Fri 2017-05-14 :10:27 EAT):
|
||||
The system shutdown has been cancelled at Fri 2017-05-12 14:11:27 EAT!
|
||||
```
|
||||
|
||||
另外,学习如何在 Linux 中使用简单和传统的方法[在重启或者开机时自动执行命令/脚本][6]。
|
||||
|
||||
不要错过:
|
||||
|
||||
1. [管理系统启动进程和服务(SysVinit、Systemd 和 Upstart)][1]
|
||||
2. [11 个 Linux 中 cron 计划任务示例][2]
|
||||
|
||||
现在你知道了如何在系统关闭前向其他系统用户发送自定义消息了。你有其他关于这个主题想要分享的想法么?何不使用下面的评论栏?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一个 Linux 和 F.O.S.S 爱好者、Linux 系统管理员、网络开发人员,现在也是 TecMint 的内容创作者,他喜欢和电脑一起工作,坚信共享知识。
|
||||
|
||||
------------------
|
||||
|
||||
via: https://www.tecmint.com/show-linux-server-shutdown-message/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/linux-boot-process-and-manage-services/
|
||||
[2]:https://www.tecmint.com/11-cron-scheduling-task-examples-in-linux/
|
||||
[3]:https://www.tecmint.com/shutdown-poweroff-halt-and-reboot-commands-in-linux/
|
||||
[4]:https://www.tecmint.com/find-linux-uptime-shutdown-and-reboot-time-with-tuptime/
|
||||
[5]:https://www.tecmint.com/wp-content/uploads/2017/05/Linux-System-Shutdown-Message.png
|
||||
[6]:https://www.tecmint.com/auto-execute-linux-scripts-during-reboot-or-startup/
|
||||
[7]:https://www.tecmint.com/author/aaronkili/
|
||||
[8]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[9]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
@ -0,0 +1,69 @@
|
||||
如何使用 Cream 提高 Vim 的用户友好性
|
||||
============================================================
|
||||
|
||||
> Cream 附加包通过把一个更加熟悉的“面孔”置于 Vim 文本编辑器之上,同时保留 Vim 的功能,使其更加容易使用
|
||||
|
||||
![How to make Vim user-friendly with Cream](https://opensource.com/sites/default/files/styles/image-full-size/public/images/education/osdc_edu_rightmix_520.png?itok=SCsog_qv "How to make Vim user-friendly with Cream")
|
||||
|
||||
图片来自 : opensource.com
|
||||
|
||||
大约 10 年前,我既使用 Emacs 进行文本编辑,也使用 Vim 进行文本编辑。说到底,我的确是一个热衷于 Emacs 的家伙。尽管 Emacs 在我的心里占据了很重要的地位,但我知道, Vim 也不赖。
|
||||
|
||||
一些人,或者像我一样的人,在技术方面有些笨手笨脚。多年来,我和一些 Linux 新手交流,了解到他们想使用 Vim,但是却失望的发现, Vim 编辑器和他们在其它操作系统上使用过的编辑器不一样。
|
||||
|
||||
但是,当我把 Cream 介绍给他们以后,他们的失望就变成了满意。Cream 是 Vim 的一个附加包,它使得 Vim 更加容易使用。Cream 让这些 Linux 新手变成了 Vim 的坚决拥护者和忠心用户。
|
||||
|
||||
让我们来看一看 Cream 是什么以及它是如何让 Vim 变得更加容易使用的。
|
||||
|
||||
### Cream 的安装
|
||||
|
||||
在安装 Cream 之前,你需要先在你的电脑上安装好 Vim 和 GVim 的 GUI 组件。我发现最容易完成这件事的方法是使用 Linux 版本的包管理器。
|
||||
|
||||
安装好 Vim 以后,便可[下载 Cream 的安装程序][2],或者你也可以再次使用 Linux 发行版的包管理器进行安装。
|
||||
|
||||
安装好 Cream 以后,你可以从应用菜单选择它(比如,**Applications**->**Cream**)或者在程序启动器中输入 `Cream`,从而启动 Cream 。
|
||||
|
||||
![Cream’s main window](https://opensource.com/sites/default/files/resize/cream-main-window-520x336.png "Cream’s main window")
|
||||
|
||||
### Cream 的使用
|
||||
|
||||
如果你之前已经使用过 Gvim,那么你会注意到, Cream 几乎没改变该编辑器的外观和感觉。最大的不同是 Cream 的菜单栏和工具栏,它们取代了 Gvim 陈旧的菜单栏和工具栏,新的菜单栏和工具栏的外观和功能分组看起来和其它编辑器的一样。
|
||||
|
||||
Cream 的菜单栏对用户隐藏了更多的技术选项,比如指定一个编译器的能力,以及运行 `make` 命令的能力。当你通过使用 Cream 更加熟悉 Vim 以后,你只需要从 **Setting**->**Preferences**->**Behavior** 选择选项,就可以更容易地访问这些特性。有了这些选项,你可以(如果你想)体验到一个兼有 Cream 和传统 Vim 二者优点的强大编辑器。
|
||||
|
||||
Cream 并不是仅由菜单驱动。尽管编辑器的功能仅有单击或双击两种方式,但是你也可以使用常见的键盘快捷键来执行操作,比如 `CTRL-O`(打开一个文件),`CTRL-C`(复制文本)。你不需要在几种模式之间切换,也不需要记住一些很难记住的命令。
|
||||
|
||||
Cream 开始运行以后,打开一个文件,或者新建一个文件,然后就可以开始输入了。几个我向他们介绍过 Cream 的人说,虽然 Cream 保留了 Vim 的许多典型风格,但是 Cream 使用起来更加舒服。
|
||||
|
||||
![Cream add-on for VIM in action](https://opensource.com/sites/default/files/cream-in-action.png "Cream add-on for VIM in action")
|
||||
|
||||
并不是说 Cream 是 Vim 的简化版,远远不是。事实上, Cream 保留了 Vim 的全部特性,同时,它还有[一系列其他有用的特性][7]。我发现的 Cream 的一些有用的特性包括:
|
||||
|
||||
* 一个标签式界面
|
||||
* 语法高亮(特别是针对 Markdown、LaTeX 和 HTML)
|
||||
* 自动修正拼写错误
|
||||
* 字数统计
|
||||
* 内建文件浏览器
|
||||
|
||||
Cream 本身也有许多附加包,可以给编辑器增加一些新的特性。这些特性包括文本加密、清理电子邮件内容,甚至还有一个使用教程。老实说,我还没有发现哪一个附加包是真正有用的,不过你的感受可能会有所不同。
|
||||
|
||||
我曾听过一些 Vi/Vim 的狂热分子谴责 Cream “降低”(这是他们的原话)了 Vi/Vim 编辑器的水准。的确,Cream 并不是为他们设计的。它是为那些想快速使用 Vim ,同时保留他们曾经使用过的编辑器的外观和感觉的人准备的。在这种情况下, Cream 是值得赞赏的,它使得 Vim 更加容易使用,更加广泛的被人们使用。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/5/stir-bit-cream-make-vim-friendlier
|
||||
|
||||
作者:[Scott Nesbitt][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/scottnesbitt
|
||||
[1]:https://opensource.com/article/17/5/stir-bit-cream-make-vim-friendlier?rate=sPQVOnwWoNwyyQX4wV2SZ_7Ly_KXd_Gu9pBu16LRyhU
|
||||
[2]:http://cream.sourceforge.net/download.html
|
||||
[3]:http://cream.sourceforge.net/featurelist.html
|
||||
[4]:https://opensource.com/user/14925/feed
|
||||
[5]:https://opensource.com/article/17/5/stir-bit-cream-make-vim-friendlier#comments
|
||||
[6]:https://opensource.com/users/scottnesbitt
|
||||
[7]:http://cream.sourceforge.net/featurelist.html
|
@ -0,0 +1,126 @@
|
||||
Linfo:实时显示你的 Linux 服务器运行状况
|
||||
============================================================
|
||||
|
||||
|
||||
Linfo 是一个自由开源的跨平台的服务器统计 UI 或库,它可以显示大量的系统信息。Linfo 是可扩展的,通过 `composer`,很容易使用 PHP5 库以程序化方式获取来自 PHP 应用的丰富的系统统计数据。它有 Web UI 及其Ncurses CLI 视图,在 Linux、Windows、BSD、Darwin/Mac OSX、Solaris 和 Minix 系统上均可用。
|
||||
|
||||
Linfo 显示的系统信息包括 [CPU 类型/速度][2]、服务器的体系结构、挂载点用量、硬盘/光纤/Flash 驱动器、硬件设备、网络设备和统计信息、运行时间/启动日期、主机名、内存使用量(RAM 和 swap)、温度/电压/风扇速度和 RAID 阵列等。
|
||||
|
||||
### 环境要求:
|
||||
|
||||
* PHP 5.3
|
||||
* pcre 扩展
|
||||
* Linux – `/proc` 和 `/sys` 已挂载且可对 `PHP` 可读,已经在 2.6.x/3.x 内核中测试过
|
||||
|
||||
### 如何在 Linux 中安装 Linfo 服务器统计 UI及库
|
||||
|
||||
首先,在 Apache 或 Nginx 的 Web 根目录下创建 Linfo 的目录,然后,使用下面展示的 [rsync 命令][3] 克隆仓库文件并将其移动到目录 `/var/www/html/linfo` 下:
|
||||
|
||||
```
|
||||
$ sudo mkdir -p /var/www/html/linfo
|
||||
$ git clone git://github.com/jrgp/linfo.git
|
||||
$ sudo rsync -av linfo/ /var/www/html/linfo/
|
||||
```
|
||||
|
||||
接下来,将 `sample.config.inc.php` 重命名为 `config.inc.php`。这是 Linfo 的配置文件,你可以在里面定义你想要的值:
|
||||
|
||||
```
|
||||
$ sudo mv sample.config.inc.php config.inc.php
|
||||
```
|
||||
|
||||
现在,在 Web 浏览器中打开链接 `http://SERVER_IP/linfo` 来查看这个 Web UI,正如下面的截图所展示的。
|
||||
|
||||
从截图中可以看到, Linfo 显示了系统内核信息、硬件组成、RAM 统计、网络设备、驱动器以及文件系统挂载点。
|
||||
|
||||
[![Linux Server Health Information](https://www.tecmint.com/wp-content/uploads/2017/05/Linux-Server-Health-Information.png)][4]
|
||||
|
||||
*Linux 服务器运行信息*
|
||||
|
||||
你可以将下面一行内容加入配置文件 `config.inc.php` 中,以便进行故障排查时看到错误信息。
|
||||
|
||||
```
|
||||
$settings['show_errors'] = true;
|
||||
```
|
||||
|
||||
### 以 Ncurses 模式运行 Linfo
|
||||
|
||||
Linfo 有一个基于 `ncurses` 的简单界面,它依赖于 `php` 的 `ncurses` 扩展。
|
||||
|
||||
```
|
||||
# yum install php-pecl-ncurses [在 CentOS/RHEL 上]
|
||||
# dnf install php-pecl-ncurses [在 Fedora 上]
|
||||
$ sudo apt-get install php5-dev libncurses5-dev [在 Debian/Ubuntu 上]
|
||||
```
|
||||
|
||||
现在,像下面这样编译这个 php 扩展:
|
||||
|
||||
```
|
||||
$ wget http://pecl.php.net/get/ncurses-1.0.2.tgz
|
||||
$ tar xzvf ncurses-1.0.2.tgz
|
||||
$ cd ncurses-1.0.2
|
||||
$ phpize # generate configure script
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
接下来,如果编译成功并安装好了该 php 扩展,运行下面的命令:
|
||||
|
||||
```
|
||||
$ sudo echo extension=ncurses.so > /etc/php5/cli/conf.d/ncurses.ini
|
||||
```
|
||||
|
||||
验证 ncurse:
|
||||
|
||||
```
|
||||
$ php -m | grep ncurses
|
||||
```
|
||||
|
||||
现在,运行 Info:
|
||||
|
||||
```
|
||||
$ cd /var/www/html/linfo/
|
||||
$ ./linfo-curses
|
||||
```
|
||||
|
||||
[![Linux Server Information](https://www.tecmint.com/wp-content/uploads/2017/05/Linux-Server-Information.png)][5]
|
||||
|
||||
*Linux 服务器信息*
|
||||
|
||||
Info 中尚欠缺下面这些功能:
|
||||
|
||||
1. 支持更多 Unix 操作系统(比如 Hurd、IRIX、AIX 和 HP UX 等)
|
||||
2. 支持不太出名的操作系统 Haiku/BeOS
|
||||
3. 额外功能/扩展
|
||||
5. 在 ncurses 模式中支持 [htop 类][1] 特性
|
||||
|
||||
如果想了解更多信息,请访问 Linfo 的 GitHub 仓库: [https://github.com/jrgp/linfo][6]
|
||||
|
||||
这就是本文的全部内容了。从现在起,你可以使用 Linfo 在 Web 浏览器中查看 Linux 系统的信息。尝试一下,并在评论中和我们分享你的想法。另外,你是否还知道与之类似的有用工具/库?如果有,请给我们提供一些相关信息。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 和 F.O.S.S 爱好者,将来的 Linux 系统管理员和网络开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并坚信分享知识
|
||||
|
||||
---------------
|
||||
|
||||
via: https://www.tecmint.com/linfo-shows-linux-server-health-status-in-real-time/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/install-htop-linux-process-monitoring-for-rhel-centos-fedora/
|
||||
[2]:https://www.tecmint.com/corefreq-linux-cpu-monitoring-tool/
|
||||
[3]:https://www.tecmint.com/rsync-local-remote-file-synchronization-commands/
|
||||
[4]:https://www.tecmint.com/wp-content/uploads/2017/05/Linux-Server-Health-Information.png
|
||||
[5]:https://www.tecmint.com/wp-content/uploads/2017/05/Linux-Server-Information.png
|
||||
[6]:https://github.com/jrgp/linfo
|
||||
[7]:https://www.tecmint.com/author/aaronkili/
|
||||
[8]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[9]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
200
published/201705/20170518 Maintaining a Git Repository.md
Normal file
200
published/201705/20170518 Maintaining a Git Repository.md
Normal file
@ -0,0 +1,200 @@
|
||||
如何瘦身 Git 仓库
|
||||
============================================================
|
||||
|
||||
对 Git 仓库的维护通常是为了减少仓库的大小。如果你从另外一个版本控制系统导入了一个仓库,你可能需要在导入后清除掉不必要的文件。本文着重于从一个 Git 仓库中删除大文件,并且包含下列主题:
|
||||
|
||||
* 理解从 Git 的历史记录中删除文件
|
||||
* 使用 BFG 重写历史记录
|
||||
* 可选,使用 `git filter-branch` 重写历史记录
|
||||
* 垃圾回收
|
||||
|
||||
> **请格外小心.....**
|
||||
|
||||
> 本文中的步骤和工具使用的高级技术涉及破坏性操作。确保您在开始之前仔细读过并**备份了你的仓库**,创建一个备份最容易的方式是使用 [--mirror][5] 标志对你的仓库克隆,然后对整个克隆的文件进行打包压缩。有了这个备份,如果在维护期间意外损坏了您的仓库的关键元素,那么你可以通过备份的仓库来恢复。
|
||||
|
||||
> 请记住,仓库维护对仓库的用户可能会是毁灭性的。与你的团队或者仓库的关注者进行沟通会是一个不错的主意。确保每个人都已经检查了他们的代码,并且同意在仓库维护期间停止开发。
|
||||
|
||||
### 理解从 Git 的历史记录中删除文件
|
||||
|
||||
回想一下,克隆仓库会克隆整个历史记录——包括每个源代码文件的所有版本。如果一个用户提交了一个较大的文件,比如一个 JAR,则随后的每次克隆都会包含这个文件。即使用户最终在后面的某次提交中删除了这个文件,但是这个文件仍然存在于这个仓库的历史记录中。要想完全的从你的仓库中删除这个文件,你必须:
|
||||
|
||||
* 从你的项目的*当前的*文件树中删除该文件;
|
||||
* 从仓库的历史记录中删除文件——*重写* Git 历史记录,从包含该文件的*所有的*提交中删除这个文件;
|
||||
* 删除指向*旧的*提交历史记录的所有 [reflog][6] 历史记录;
|
||||
* 重新整理仓库,使用 [git gc][7] 对现在没有使用的数据进行垃圾回收。
|
||||
|
||||
Git 的 “gc”(垃圾回收)将通过你的任何一个分支或者标签来删除仓库中所有的实际没用的或者以某种方式引用的数据。为了使其发挥作用,我们需要重写包含不需要的文件的所有 Git 仓库历史记录,仓库将不再引用它—— git gc 将会丢弃所有没用的数据。
|
||||
|
||||
重写存储库历史是一个棘手的事情,因为每个提交都依赖它的父提交,所以任何一个很小的改变都会改变它的每一个随后的提交的提交 ID。有两个自动化的工具可以做到这:
|
||||
|
||||
1. [BFG Repo Cleaner][8] 快速、简单且易于使用,需要 Java 6 或者更高版本的运行环境。
|
||||
2. [git filter-branch][9] 功能强大、配置麻烦,用于大于仓库时速度较慢,是核心 Git 套件的一部分。
|
||||
|
||||
切记,当你重写历史记录后,无论你是使用 BFG 还是使用 filter-branch,你都需要删除指向旧的历史记录的 `reflog` 条目,最后运行垃圾回收器来删除旧的数据。
|
||||
|
||||
### 使用 BFG 重写历史记录
|
||||
|
||||
[BFG][11] 是为将像大文件或者密码这些不想要的数据从 Git 仓库中删除而专门设计的,所以它有一一个简单的标志用来删除那些大的历史文件(不在当前的提交里面):`--strip-blobs-bigger-than`
|
||||
|
||||
```
|
||||
$ java -jar bfg.jar --strip-blobs-than 100M
|
||||
|
||||
```
|
||||
大小超过 100MB 的任何文件(不包含在你*最近的*提交中的文件——因为 BFG [默认会保护你的最新提交的内容][12])将会从你的 Git 仓库的历史记录中删除。如果你想用名字来指明具体的文件,你也可以这样做:
|
||||
|
||||
```
|
||||
$ java -jar bfg.jar --delete-files *.mp4
|
||||
|
||||
```
|
||||
|
||||
BFG 的速度要比 `git filter-branch` 快 [10-1000 倍][13],而且通常更容易使用——查看完整的[使用说明][14]和[示例][15]获取更多细节。
|
||||
|
||||
### 或者,使用 git filter-branch 来重写历史记录
|
||||
|
||||
`filter-branch` 命令可以对 Git 仓库的历史记录重写,就像 BFG 一样,但是过程更慢和更手动化。如果你不知道这些大文件在_哪里_,那么你第一步就需要找到它们:
|
||||
|
||||
#### 手动查看你 Git 仓库中的大文件
|
||||
|
||||
[Antony Stubbs][16] 写了一个可以很好地完成这个功能的 BASH 脚本。该脚本可以检查你的包文件的内容并列出大文件。在你开始删除文件之前,请执行以下操作获取并安装此脚本:
|
||||
|
||||
1、 [下载脚本][10]到你的本地的系统。
|
||||
|
||||
2、 将它放在一个可以访问你的 Git 仓库的易于找到的位置。
|
||||
|
||||
3、 让脚本成为可执行文件:
|
||||
|
||||
```
|
||||
$ chmod 777 git_find_big.sh
|
||||
```
|
||||
|
||||
4、 克隆仓库到你本地系统。
|
||||
|
||||
5、 改变当前目录到你的仓库根目录。
|
||||
|
||||
6、 手动运行 Git 垃圾回收器:
|
||||
|
||||
```
|
||||
git gc --auto
|
||||
```
|
||||
|
||||
7、 找出 .git 文件夹的大小
|
||||
|
||||
```
|
||||
$ du -hs .git/objects
|
||||
45M .git/objects
|
||||
```
|
||||
|
||||
注意文件大小,以便随后参考。
|
||||
|
||||
8、 运行 `git_find_big.sh` 脚本来列出你的仓库中的大文件。
|
||||
|
||||
```
|
||||
$ git_find_big.sh
|
||||
All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file.
|
||||
size pack SHA location
|
||||
592 580 e3117f48bc305dd1f5ae0df3419a0ce2d9617336 media/img/emojis.jar
|
||||
550 169 b594a7f59ba7ba9daebb20447a87ea4357874f43 media/js/aui/aui-dependencies.jar
|
||||
518 514 22f7f9a84905aaec019dae9ea1279a9450277130 media/images/screenshots/issue-tracker-wiki.jar
|
||||
337 92 1fd8ac97c9fecf74ba6246eacef8288e89b4bff5 media/js/lib/bundle.js
|
||||
240 239 e0c26d9959bd583e5ef32b6206fc8abe5fea8624 media/img/featuretour/heroshot.png
|
||||
```
|
||||
|
||||
大文件都是 JAR 文件,包的大小列是最相关的。`aui-dependencies.jar` 被压缩到 169kb,但是 `emojis.jar` 只压缩到 500kb。`emojis.jar` 就是一个待删除的对象。
|
||||
|
||||
#### 运行 filter-branch
|
||||
|
||||
你可以给这个命令传递一个用于重写 Git 索引的过滤器。例如,一个过滤器可以可以将每个检索的提交删除。这个用法如下:
|
||||
|
||||
```
|
||||
git filter-branch --index-filter 'git rm --cached --ignore-unmatch _pathname_ ' commitHASH
|
||||
```
|
||||
|
||||
`--index-filter` 选项可以修改仓库的索引,`--cached ` 选项从索引中而不是磁盘来删除文件。这样会更快,因为你不需要在运行这个过滤器前检查每个修订版本。`git rm` 中的 `ignore-unmatch` 选项可以防止在尝试移走不存在的文件 `pathname` 的时候命令失败。通过指定一个提交 HASH 值,你可以从每个以这个 HASH 值开始的提交中删除`pathname`。要从开始处删除,你可以省略这个参数或者指定为 `HEAD`。
|
||||
|
||||
如果你的大文件在不同的分支,你将需要通过名字来删除每个文件。如果大文件都在一个单独的分支,你可以直接删除这个分支本身。
|
||||
|
||||
#### 选项 1:通过文件名删除文件
|
||||
|
||||
使用下面的步骤来删除大文件:
|
||||
|
||||
1、 使用下面的命令来删除你找到的第一个大文件:
|
||||
|
||||
```
|
||||
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
|
||||
|
||||
```
|
||||
|
||||
2、 重复步骤 1 找到剩下的每个大文件。
|
||||
|
||||
3、 在你的仓库里更新引用。 `filter-branch` 会为你原先的引用创建一个 `refs/original/` 下的备份。一旦你确信已经删除了正确的文件,你可以运行下面的命令来删除备份文件,同时可以让垃圾回收器回收大的对象:
|
||||
|
||||
```
|
||||
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
|
||||
|
||||
```
|
||||
|
||||
#### 选项 2:直接删除分支
|
||||
|
||||
如果你所有的大文件都在一个单独的分支上,你可以直接删除这个分支。删除这个分支会自动删除所有的引用。
|
||||
|
||||
1、 删除分支。
|
||||
|
||||
```
|
||||
$ git branch -D PROJ567bugfix
|
||||
```
|
||||
|
||||
2、 从后面的分支中删除所有的 reflog 引用。
|
||||
|
||||
|
||||
### 对不用的数据垃圾回收
|
||||
|
||||
1、 删除从现在到后面的所有 reflog 引用(除非你明确地只在一个分支上操作)。
|
||||
|
||||
```
|
||||
$ git reflog expire --expire=now --all
|
||||
```
|
||||
|
||||
2、 通过运行垃圾回收器和删除旧的对象重新打包仓库。
|
||||
|
||||
```
|
||||
$ git gc --prune=now
|
||||
```
|
||||
|
||||
3、 把你所有的修改推送回仓库。
|
||||
|
||||
```
|
||||
$ git push --all --force
|
||||
```
|
||||
|
||||
4、 确保你所有的标签也是当前最新的:
|
||||
|
||||
```
|
||||
$ git push --tags --force
|
||||
```
|
||||
|
||||
----------
|
||||
via: https://confluence.atlassian.com/bitbucket/maintaining-a-git-repository-321848291.html
|
||||
|
||||
作者:[atlassian.com][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://confluence.atlassian.com/bitbucket/maintaining-a-git-repository-321848291.html
|
||||
[1]:https://confluence.atlassian.com/bitbucket/maintaining-a-git-repository-321848291.html#MaintainingaGitRepository-UnderstandingfileremovalfromGithistory
|
||||
[2]:https://confluence.atlassian.com/bitbucket/maintaining-a-git-repository-321848291.html#MaintainingaGitRepository-UsingtheBFGtorewritehistory
|
||||
[3]:https://confluence.atlassian.com/bitbucket/maintaining-a-git-repository-321848291.html#MaintainingaGitRepository-Alternatively,usinggitfilter-branchtorewritehistory
|
||||
[4]:https://confluence.atlassian.com/bitbucket/maintaining-a-git-repository-321848291.html#MaintainingaGitRepository-Garbagecollectingdeaddata
|
||||
[5]:http://stackoverflow.com/questions/3959924/whats-the-difference-between-git-clone-mirror-and-git-clone-bare
|
||||
[6]:http://git-scm.com/docs/git-reflog
|
||||
[7]:http://git-scm.com/docs/git-gc
|
||||
[8]:http://rtyley.github.io/bfg-repo-cleaner/
|
||||
[9]:http://git-scm.com/docs/git-filter-branch
|
||||
[10]:https://confluence.atlassian.com/bitbucket/files/321848291/321979854/1/1360604134990/git_find_big.sh
|
||||
[11]:http://rtyley.github.io/bfg-repo-cleaner/
|
||||
[12]:http://rtyley.github.io/bfg-repo-cleaner/#protected-commits
|
||||
[13]:https://www.youtube.com/watch?v=Ir4IHzPhJuI
|
||||
[14]:http://rtyley.github.io/bfg-repo-cleaner/#usage
|
||||
[15]:http://rtyley.github.io/bfg-repo-cleaner/#examples
|
||||
[16]:https://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
|
@ -0,0 +1,123 @@
|
||||
怎样在 Linux 命令行下杀死一个进程
|
||||
============================================================
|
||||
|
||||
> Linux 的命令行里面有用来停止正在运行的进程的所有所需工具。Jack Wallen 将为您讲述细节。
|
||||
|
||||
![stop processes](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/stop-processes.jpg?itok=vfNx8VRz "stop processes")
|
||||
|
||||
想像一下:你打开了一个程序(可能来自于你的桌面菜单或者命令行),然后开始使用这个程序,没想到程序会锁死、停止运行、或者意外死机。你尝试再次运行该程序,但是它反馈说原来的进程没有完全关闭。
|
||||
|
||||
你该怎么办?你要结束进程。但该如何做?不管你信与不信,最好的解决方法大都在命令行里。值得庆幸的是, Linux 有供用户杀死错误的进程的每个必要的工具,然而,你在执行杀死进程的命令之前,你首先需要知道进程是什么。该如何处理这一类的任务。一旦你能够掌握这种工具,它实际是十分简单的……
|
||||
|
||||
让我来介绍给你这些工具。
|
||||
|
||||
我来概述的步骤是每个 Linux 发行版都能用的,不论是桌面版还是服务器版。我将限定只使用命令行,请打开你的终端开始输入命令吧。
|
||||
|
||||
### 定位进程
|
||||
|
||||
杀死一个没有响应的进程的第一个步骤是定位这个进程。我用来定位进程的命令有两个:`top` 和 `ps` 命令。`top` 是每个系统管理员都知道的工具,用 `top` 命令,你能够知道到所有当前正在运行的进程有哪些。在命令行里,输入 `top` 命令能够就看到你正在运行的程序进程(图1)
|
||||
|
||||
![top](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/killa.jpg?itok=95cUI9Lh "top")
|
||||
|
||||
*图 1: top 命令给出你许多的信息。*
|
||||
|
||||
从显示的列表中你能够看到相当重要的信息,举个例子,Chrome 浏览器反映迟钝,依据我们的 `top` 命令显示,我们能够辨别的有四个 Chrome 浏览器的进程在运行,进程的 pid 号分别是 3827、3919、10764 和 11679。这个信息是重要的,可以用一个特殊的方法来结束进程。
|
||||
|
||||
尽管 `top` 命令很是方便,但也不是得到你所要信息最有效的方法。 你知道你要杀死的 Chrome 进程是那个,并且你也不想看 `top` 命令所显示的实时信息。 鉴于此,你能够使用 `ps` 命令然后用 `grep` 命令来过滤出输出结果。这个 `ps` 命令能够显示出当前进程列表的快照,然后用 `grep` 命令输出匹配的样式。我们通过 `grep` 命令过滤 `ps` 命令的输出的理由很简单:如果你只输入 `ps` 命令,你将会得到当前所有进程的列表快照,而我们需要的是列出 Chrome 浏览器进程相关的。所以这个命令是这个样子:
|
||||
|
||||
```
|
||||
ps aux | grep chrome
|
||||
```
|
||||
|
||||
这里 `aux` 选项如下所示:
|
||||
|
||||
* a = 显示所有用户的进程
|
||||
* u = 显示进程的用户和拥有者
|
||||
* x = 也显示不依附于终端的进程
|
||||
|
||||
当你搜索图形化程序的信息时,这个 `x` 参数是很重要的。
|
||||
|
||||
当你输入以上命令的时候,你将会得到比图 2 更多的信息,而且它有时用起来比 `top` 命令更有效。
|
||||
|
||||
![ps command](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/killb.jpg?itok=vyWIuTva "ps command")
|
||||
|
||||
*图 2:用 ps 命令来定位所需的内容信息。*
|
||||
|
||||
### 结束进程
|
||||
|
||||
现在我们开始结束进程的任务。我们有两种可以帮我们杀死错误的进程的信息。
|
||||
|
||||
* 进程的名字
|
||||
* 进程的 ID (PID)
|
||||
|
||||
你用哪一个将会决定终端命令如何使用,通常有两个命令来结束进程:
|
||||
|
||||
* `kill` - 通过进程 ID 来结束进程
|
||||
* `killall` - 通过进程名字来结束进程
|
||||
|
||||
有两个不同的信号能够发送给这两个结束进程的命令。你发送的信号决定着你想要从结束进程命令中得到的结果。举个例子,你可以发送 `HUP`(挂起)信号给结束进程的命令,命令实际上将会重启这个进程。当你需要立即重启一个进程(比如就守护进程来说),这是一个明智的选择。你通过输入 `kill -l` 可以得到所有信号的列表,你将会发现大量的信号。
|
||||
|
||||
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/killc.jpg?itok=9ewRHFW2)
|
||||
|
||||
*图 3: 可用的结束进程信号。*
|
||||
|
||||
最经常使用的结束进程的信号是:
|
||||
|
||||
| Signal Name | Single Value | Effect |
|
||||
|-----------|-----------|----------|
|
||||
| SIGHUP | 1 | 挂起 |
|
||||
| SIGINT | 2 | 键盘的中断信号 |
|
||||
| SIGKILL | 9 | 发出杀死信号 |
|
||||
| SIGTERM | 15 | 发出终止信号 |
|
||||
| SIGSTOP | 17, 19, 23 | 停止进程 |
|
||||
|
||||
好的是,你能用信号值来代替信号名字。所以你没有必要来记住所有各种各样的信号名字。
|
||||
|
||||
所以,让我们现在用 `kill` 命令来杀死 Chrome 浏览器的进程。这个命令的结构是:
|
||||
|
||||
```
|
||||
kill SIGNAL PID
|
||||
```
|
||||
|
||||
这里 SIGNAL 是要发送的信号,PID 是被杀死的进程的 ID。我们已经知道,来自我们的 `ps` 命令显示我们想要结束的进程 ID 号是 3827、3919、10764 和 11679。所以要发送结束进程信号,我们输入以下命令:
|
||||
|
||||
```
|
||||
kill -9 3827
|
||||
kill -9 3919
|
||||
kill -9 10764
|
||||
kill -9 11679
|
||||
```
|
||||
|
||||
一旦我们输入了以上命令,Chrome 浏览器的所有进程将会成功被杀死。
|
||||
|
||||
我们有更简单的方法!如果我们已经知道我们想要杀死的那个进程的名字,我们能够利用 `killall` 命令发送同样的信号,像这样:
|
||||
|
||||
```
|
||||
killall -9 chrome
|
||||
```
|
||||
|
||||
附带说明的是,上边这个命令可能不能捕捉到所有正在运行的 Chrome 进程。如果,运行了上边这个命令之后,你输入 `ps aux | grep chrome` 命令过滤一下,看到剩下正在运行的 Chrome 进程有那些,最好的办法还是回到 `kIll` 命令通过进程 ID 来发送信号值 `9` 来结束这个进程。
|
||||
|
||||
### 结束进程很容易
|
||||
|
||||
正如你看到的,杀死错误的进程并没有你原本想的那样有挑战性。当我让一个顽固的进程结束的时候,我趋向于用 `killall`命令来作为有效的方法来终止,然而,当我让一个真正的活跃的进程结束的时候,`kill`命令是一个好的方法。
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/learn/intro-to-linux/2017/5/how-kill-process-command-line
|
||||
|
||||
作者:[JACK WALLEN][a]
|
||||
译者:[hwlog](https://github.com/hwlog)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linux.com/users/jlwallen
|
||||
[1]:https://www.linux.com/licenses/category/used-permission
|
||||
[2]:https://www.linux.com/licenses/category/used-permission
|
||||
[3]:https://www.linux.com/licenses/category/used-permission
|
||||
[4]:https://www.linux.com/licenses/category/creative-commons-zero
|
||||
[5]:https://www.linux.com/files/images/killajpg
|
||||
[6]:https://www.linux.com/files/images/killbjpg
|
||||
[7]:https://www.linux.com/files/images/killcjpg
|
||||
[8]:https://www.linux.com/files/images/stop-processesjpg
|
@ -0,0 +1,126 @@
|
||||
新的“永恒之石”病毒利用了七个 NSA 黑客工具,“想哭”病毒才两个
|
||||
===========
|
||||
|
||||
![永恒之石](https://www.bleepstatic.com/content/posts/2017/05/19/EternalRocks.png)
|
||||
|
||||
研究人员们发现有一个新的蠕虫病毒正在通过 SMB 文件共享漏洞传播,但是不同于“想哭”(WannaCry)勒索病毒的构成,这个病毒利用了 7 个 NSA 黑客工具,而不是“想哭”(WannaCry)勒索病毒的两个。
|
||||
|
||||
这个蠕虫病毒的存在首次发现是在周三,它感染了 [Miroslav Stampar][15] 的 SMB 文件共享的蜜罐,Miroslav Stampar 是克罗地亚政府计算机应急响应小组成员,也是用来探测和利用 SQL 注入漏洞的 SQLMAP 工具的制造者。
|
||||
|
||||
### 永恒之石利用了七个 NSA 的工具
|
||||
|
||||
Stampar 命名这个在样本中被发现的病毒为“永恒之石”(EternalRocks),其基于蠕虫病毒可执行的特性,它通过 6 个以 SMB 文件共享漏洞为中心的 NSA 工具来感染暴露在外网的一台开启 SMB 端口的计算机。这些被叫做 **永恒之蓝**、**永恒战士**、**永恒浪漫**和 **永恒协同**的 SMB 漏洞被利用危害易受攻击的计算机,而 **SMBTOUCH** 和 **ARCHITOUCH** 这两个 NSA 工具起到了检测 SMB 文件共享漏洞的作用。
|
||||
|
||||
一旦这个蠕虫病毒获得了最初的立足点,那么它会用另一个叫做 **DOUBLEPULSAR** 的 NSA 工具扩散到新的易受攻击的机器上。
|
||||
|
||||
![永恒之石名字的起源](https://www.bleepstatic.com/images/news/u/986406/Malware/EternalRocks-properties.png)
|
||||
|
||||
**“永恒之石”名字的起源**
|
||||
|
||||
[“想哭”勒索病毒爆发][16],用了一个 SMB 蠕虫病毒感染计算机并扩散给新的受害人,这影响了超过 24 万受害者。
|
||||
|
||||
|
||||
不同于“永恒之石”,“想哭”的 SMB 蠕虫病毒只利用了永恒之蓝这一个漏洞做初步感染,然后通过 DOUBLEPULSAR 来扩散到其他的计算机上。
|
||||
|
||||
### “永恒之石”更加复杂,但危险性较低
|
||||
|
||||
作为蠕虫病毒,“永恒之石”没有“想哭”那么危险,这是由于它当前不传递任何恶意的内容,然而,这并不意味着“永恒之石”不复杂,据 Stampar 说,实际恰恰相反。
|
||||
|
||||
首先,“永恒之石”要比“想哭”的 SMB 蠕虫病毒更加隐蔽,一旦病毒感染了一台计算机,它会发起有两个阶段的安装过程,其中另一个是延迟执行的。
|
||||
|
||||
在病毒的第一个安装过程阶段,永恒之石获取一个感染计算机主机的立足点,下载 tor 客户端,然后连接到它的命令控制服务器,其定位在暗网的一个 .onion 的域名上。
|
||||
|
||||
在一个预定的时间内,一般是 24 个小时,命令控制器会响应,这个长延迟执行进程的做法最有可能绕过沙盒安全测试环境和安全研究人员们对病毒的分析,因为没多少人愿意一整天来等命令控制器响应。
|
||||
|
||||
|
||||
> [ Follow][1] [![](https://pbs.twimg.com/profile_images/687638130694995970/Xtras5w3_normal.png) Miroslav Stampar @stamparm][6]
|
||||
>
|
||||
> Update on [#EternalRocks][7]. Original name is actually "MicroBotMassiveNet" while author's nick is "tmc" [https://github.com/stamparm/EternalRocks/#debug-strings …][8]
|
||||
>
|
||||
> [<time class="dt-updated" datetime="2017-05-19T09:10:50+0000" pubdate="" title="Time posted: 19 May 2017, 09:10:50 (UTC)">5:10 PM - 19 May 2017</time>][9]
|
||||
>
|
||||
> * [][2]
|
||||
>
|
||||
> * [ 2525 Retweets][3]
|
||||
>
|
||||
> * [ 1717 likes][4]
|
||||
|
||||
[Twitter Ads info & Privacy][11]</twitterwidget>
|
||||
|
||||
### 没有停止开关的域名
|
||||
|
||||
此外,“永恒之石”病毒也会用和一个与“想哭” SMB 的蠕虫病毒文件相同名字的一个文件,以此愚弄安全研究人员来误判它。
|
||||
|
||||
但是不同于“想哭”病毒,永恒之石不包括停止开关的域名,但这是安全研究人员唯一用来停止“想哭”病毒爆发的方法。
|
||||
|
||||
在病毒隐匿期满且命令控制器有了响应,永恒之石开始进入安装过程的第二阶段,它会下载一个名为 shadowbrokers.zip 的归档形式的第二阶段恶意组件。
|
||||
|
||||
这个文件能够自解压,它包含着 shadow Brokers 黑客组织在 2017 年 4 月泄漏的七个 NSA 的 SMB 漏洞工具。
|
||||
这个蠕虫病毒会开始一个快速的 ip 扫描过程并且尝试连接随机的 ip 地址。
|
||||
|
||||
![shadowbrokers.zip的内容](https://www.bleepstatic.com/images/news/u/986406/Malware/EternalRocks-exploits.png)
|
||||
|
||||
**在 shadowbrokers.zip 压缩包里发现了 NSA 工具的配置文件。**
|
||||
|
||||
### “永恒之石”可以马上成为武器
|
||||
|
||||
由于该病毒集成的漏洞较多且广泛,缺少停止开关的域名,而且有它的隐匿期,如果病毒的作者决定用它来作为勒索、银行木马、远程控制或者其他功能的武器,“永恒之石”可能会对 SMB 端口暴露在互联网的易受攻击的计算机造成严重的威胁。
|
||||
|
||||
就目前来看,蠕虫病毒看起来像是一个试验,或者是恶意软件作者在进行测试或者为未来的威胁而做的微调。
|
||||
|
||||
然而,这并不意味着“永恒之石”是无害的,感染了这个病毒的计算机是通过命令控制服务器来控制,并且蠕虫病毒的制造者能够利用这个隐藏通讯连接,发送新的恶意软件到这台感染了病毒的电脑上。
|
||||
|
||||
此外,DOUBLEPULSAR,这是一个带有后门的植入仍然运行在感染了永恒之石的 PC 上,不幸的是,该病毒的作者没有采取任何措施来保护这个 DOUBLEPULSAR 的植入,这意味这缺省其运行在未被保护的状态下,其他的恶意的用户能使用它作为把感染了永恒之石的计算机的后门,发送他们自己的恶意软件到这些感染病毒的 PC 上。
|
||||
|
||||
关于这个病毒的感染过程的 IOC 和更多信息能够在 Stampar 在几天前设置的 [GitHub] 仓库上获得。
|
||||
|
||||
### SMB 漏洞的混战
|
||||
|
||||
当前,有许多人在扫描旧的和未打补丁的 SMB 服务,系统管理员已经注意到并且开始给易受攻击的计算机打补丁,关闭旧版的 SMBv1 协议,慢慢的来减少被永恒之石感染的计算机数量。
|
||||
|
||||
此外,像 Adylkuzz 这类恶意软件,也会关闭 SMB 端口,来阻止来自其它威胁软件的进一步利用,这同时也导致了“永恒之石”和其它利用 SMB 漏洞的恶意软件潜在目标数量的减少,来自 [Forcepoint][21]、[Cyphort][22] 和 [Secdo][23] 的报告详细介绍了当前针对 SMB 端口的计算机的威胁情况。
|
||||
|
||||
虽然如此,系统管理员补丁打的越快,系统越安全,“蠕虫病毒感染速度正在和系统管理员给机器打补丁速度比赛”,Stampar 在一次私人谈话中告诉 BleepingComputer 记者,“一旦计算机被感染,它能在任何时间将其作为武器,不论你打多时间多近的补丁。”
|
||||
|
||||
(题图:Miroslav Stampar, BleepingComputer & [Ana María Lora Macias][13])
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Catalin 涉及了各方面,像数据泄漏、软件漏洞、漏洞利用、黑客新闻、暗网、编程话题、社交媒体、Web技术、产品研发等领域。
|
||||
|
||||
---------------
|
||||
|
||||
via: https://www.bleepingcomputer.com/news/security/new-smb-worm-uses-seven-nsa-hacking-tools-wannacry-used-just-two/
|
||||
|
||||
作者:[CATALIN CIMPANU][a]
|
||||
译者:[hwlog](https://github.com/hwlog)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.bleepingcomputer.com/author/catalin-cimpanu/
|
||||
[1]:https://twitter.com/stamparm
|
||||
[2]:https://twitter.com/intent/tweet?in_reply_to=865494946974900224
|
||||
[3]:https://twitter.com/intent/retweet?tweet_id=865494946974900224
|
||||
[4]:https://twitter.com/intent/like?tweet_id=865494946974900224
|
||||
[5]:https://twitter.com/stamparm/status/865494946974900224/photo/1
|
||||
[6]:https://twitter.com/stamparm
|
||||
[7]:https://twitter.com/hashtag/EternalRocks?src=hash
|
||||
[8]:https://t.co/xqoxkNYfM7
|
||||
[9]:https://twitter.com/stamparm/status/865494946974900224
|
||||
[10]:https://twitter.com/stamparm/status/865494946974900224/photo/1
|
||||
[11]:https://support.twitter.com/articles/20175256
|
||||
[12]:https://www.bleepingcomputer.com/news/security/new-smb-worm-uses-seven-nsa-hacking-tools-wannacry-used-just-two/#comment_form
|
||||
[13]:https://thenounproject.com/search/?q=worm&i=24323
|
||||
[14]:https://www.bleepingcomputer.com/author/catalin-cimpanu/
|
||||
[15]:https://about.me/stamparm
|
||||
[16]:https://www.bleepingcomputer.com/news/security/wana-decrypt0r-ransomware-using-nsa-exploit-leaked-by-shadow-brokers-is-on-a-rampage/
|
||||
[17]:https://www.bleepingcomputer.com/news/security/shadow-brokers-release-new-files-revealing-windows-exploits-swift-attacks/
|
||||
[18]:https://www.bleepingcomputer.com/news/security/over-36-000-computers-infected-with-nsas-doublepulsar-malware/
|
||||
[19]:https://github.com/stamparm/EternalRocks/
|
||||
[20]:https://www.bleepingcomputer.com/news/security/adylkuzz-cryptocurrency-miner-may-have-saved-you-from-the-wannacry-ransomware/
|
||||
[21]:https://blogs.forcepoint.com/security-labs/wannacry-multiple-malware-families-using-eternalblue-exploit
|
||||
[22]:https://www.cyphort.com/eternalblue-exploit-actively-used-deliver-remote-access-trojans/
|
||||
[23]:http://blog.secdo.com/multiple-groups-exploiting-eternalblue-weeks-before-wannacry
|
@ -0,0 +1,95 @@
|
||||
朝鲜 180 局的网络战部门让西方国家忧虑
|
||||
============================================================
|
||||
|
||||
本文译自澳大利亚广播公司相关文章,不代表本站及译者、编辑的态度。
|
||||
|
||||
[![在夜色的映衬下,部队的军车通过平壤市区](http://www.abc.net.au/news/image/8545124-3x2-700x467.jpg "Military trucks through Pyongyang")][13]
|
||||
|
||||
*[PHOTO:脱北者说, 平壤的网络战攻击目的旨在为一个叫做“180局”的部门来筹集资金。(路透社:Damir Sagolj, file)][14]*
|
||||
|
||||
> 据脱北者、官方和网络安全专家的消息,朝鲜的情报机关有一个叫做 180 局的特殊部门, 这个部门已经发起过多起胆大且成功的网络战。
|
||||
|
||||
近几年,朝鲜被指责在美国、韩国,及其周边的几个国家对金融网络发起多起在线袭击。
|
||||
|
||||
网络安全研究人员称他们找到了这个月全球性感染了 150 多个国家 30 多万台计算机的[“想哭”勒索病毒和朝鲜网络战有关联的技术证据][15]。
|
||||
|
||||
平壤称该指控是“荒谬的”。
|
||||
|
||||
对朝鲜的关键指控是指朝鲜与一个叫做拉撒路(Lazarus)的黑客组织有联系,这个组织是在去年在孟加拉国中央银行网络抢劫了 8100 万美元,并在 2014 年攻击了索尼的好莱坞工作室的网络。
|
||||
|
||||
美国政府指责朝鲜对索尼公司的黑客袭击,同时美国政府对平壤在孟加拉国银行的盗窃行为提起公诉并要求立案。
|
||||
|
||||
由于没有确凿的证据、没有犯罪指控并不能够立案。朝鲜之后也否认了索尼公司和该银行的袭击与其有关。
|
||||
|
||||
朝鲜是世界上最封闭的国家之一,它秘密行动的一些细节很难获得。
|
||||
|
||||
但研究这个封闭国家的专家和流落到韩国和一些西方国家的的脱北者已经给出了或多或少的提示。
|
||||
|
||||
### 黑客们喜欢以雇员身份来作为掩护
|
||||
|
||||
金恒光,一位朝鲜前计算机教授,2004 叛逃到韩国,他仍然有着韩国内部的消息来源,他说平壤的网络战目的在于通过侦察总局(RGB)下属的一个叫做 180 局来筹集资金,这个局主要是负责海外的情报机构。
|
||||
|
||||
金教授称,“180 局负责入侵金融机构通过漏洞从银行账户提取资金”。
|
||||
|
||||
他之前也说过,他以前的一些学生已经加入了朝鲜的网络战略司令部,即朝鲜的网络部队。
|
||||
|
||||
>“黑客们到海外寻找比朝鲜更好的互联网服务的地方,以免留下痕迹,” 金教授补充说。
|
||||
|
||||
他说他们经常用贸易公司、朝鲜的海外分公司和在中国和东南亚合资企业的雇员来作为掩护。
|
||||
|
||||
位于华盛顿的战略与国际研究中心的一位名为 James Lewis 的朝鲜专家称,平壤首先把黑客攻击作为间谍活动的工具,然后对韩国和美国的目的进行政治干扰。
|
||||
|
||||
他说,“索尼公司事件之后,他们改变方法,通过用黑客来支持犯罪活动来形成国内坚挺的货币经济政策。”
|
||||
|
||||
“目前为止,网上毒品,假冒伪劣,走私,都是他们惯用的伎俩”。
|
||||
|
||||
|
||||
[**VIDEO:** 你遇到过勒索病毒吗? (ABC News)][16] : https://dn-linuxcn.qbox.me/static/video/CNb_Ransomware_1505_512k.mp4
|
||||
|
||||
### 韩国声称拥有“大量的证据”
|
||||
|
||||
美国国防部称在去年提交给国会的一个报告中显示,朝鲜将网络视为有成本效益的、不对称的、可否认的工具,它能够应付来自报复性袭击的很小风险,因为它的“网络”大部分是和因特网分离的。
|
||||
|
||||
> 报告中说," 它可能从第三方国家使用互联网基础设施"。
|
||||
|
||||
韩国政府称,他们拥有朝鲜网络战行动的大量证据。
|
||||
|
||||
“朝鲜进行网络战通过第三方国家来掩护网络袭击的来源,并且使用他们的信息和通讯技术设施”,韩国外交部副部长安总基在书面评论中告诉路透社。
|
||||
|
||||
除了孟加拉银行抢劫案,他说怀疑平壤也与菲律宾、越南和波兰的银行袭击有关。
|
||||
|
||||
去年六月,警察称朝鲜袭击了 160 个韩国公司和政府机构,入侵了大约 14 万台计算机,暗中在它的对手的计算机中植入恶意代码,为进行大规模网络攻击的长期计划而准备。
|
||||
|
||||
朝鲜也被怀疑在 2014 年对韩国核反应堆操作系统进行阶段性网络攻击,尽管朝鲜否认与其无关。
|
||||
|
||||
根据在一个韩国首尔的杀毒软件厂商 hauri 的高级安全研究员 Simon Choi 的说法,网络袭击是来自于朝鲜在中国的一个基地。
|
||||
|
||||
Choi 先生,是一位对朝鲜的黑客能力有广泛的研究的人,他称,“他们在那里行动,不管他们究竟在做什么,他们拥有中国的 IP 地址”。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.abc.net.au/news/2017-05-21/north-koreas-unit-180-cyber-warfare-cell-hacking/8545106
|
||||
|
||||
作者:[www.abc.net.au][a]
|
||||
译者:[hwlog](https://github.com/hwlog)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.abc.net.au
|
||||
[1]:http://www.abc.net.au/news/2017-05-16/wannacry-ransomware-showing-up-in-obscure-places/8527060
|
||||
[2]:http://www.abc.net.au/news/2015-08-05/why-we-should-care-about-cyber-crime/6673274
|
||||
[3]:http://www.abc.net.au/news/2017-05-15/what-to-do-if-youve-been-hacked/8526118
|
||||
[4]:http://www.abc.net.au/news/2017-05-16/researchers-link-wannacry-to-north-korea/8531110
|
||||
[5]:http://www.abc.net.au/news/2017-05-18/adylkuzz-cyberattack-could-be-far-worse-than-wannacry:-expert/8537502
|
||||
[6]:http://www.google.com/maps/place/Korea,%20Democratic%20People%20S%20Republic%20Of/@40,127,5z
|
||||
[7]:http://www.abc.net.au/news/2017-05-16/wannacry-ransomware-showing-up-in-obscure-places/8527060
|
||||
[8]:http://www.abc.net.au/news/2017-05-16/wannacry-ransomware-showing-up-in-obscure-places/8527060
|
||||
[9]:http://www.abc.net.au/news/2015-08-05/why-we-should-care-about-cyber-crime/6673274
|
||||
[10]:http://www.abc.net.au/news/2015-08-05/why-we-should-care-about-cyber-crime/6673274
|
||||
[11]:http://www.abc.net.au/news/2017-05-15/what-to-do-if-youve-been-hacked/8526118
|
||||
[12]:http://www.abc.net.au/news/2017-05-15/what-to-do-if-youve-been-hacked/8526118
|
||||
[13]:http://www.abc.net.au/news/2017-05-21/military-trucks-trhough-pyongyang/8545134
|
||||
[14]:http://www.abc.net.au/news/2017-05-21/military-trucks-trhough-pyongyang/8545134
|
||||
[15]:http://www.abc.net.au/news/2017-05-16/researchers-link-wannacry-to-north-korea/8531110
|
||||
[16]:http://www.abc.net.au/news/2017-05-15/have-you-been-hit-by-ransomware/8527854
|
@ -0,0 +1,116 @@
|
||||
在 Linux 中使用 pushd 和 popd 命令来进行高效的目录导航
|
||||
======
|
||||
|
||||
有时候,通过命令来在 Linux 文件系统导航是一件非常痛苦的事情,特别是对于一些新手。通常情况下,我们主要使用 [cd(改变目录)命令][1]在 Linux 文件系统之间移动。
|
||||
|
||||
在之前的文章中,我们回顾了一个非常简单但很有用的 Linux 上的 CLI 工具,文章叫做 [bd:快速返回某级父目录而不用冗余地输入 “cd ../../..”][2]
|
||||
|
||||
在这个教程中,我们将讨论两个相关的命令:`pushd` 和 `popd` ,使用它们可以高效的浏览 Linux 目录结构。这两个命令在大多数 shell ,比如 bash、tcsh 中都存在。
|
||||
|
||||
**推荐阅读:**[Autojump:快速浏览 Linux 文件系统的一个高级 `cd` 命令][3]
|
||||
|
||||
### pushd 和 popd 命令在 Linux 系统中如何工作
|
||||
|
||||
`pushd` 和 `popd` 命令根据 ‘LIFO’(后进先出)原则工作。在这个原则之下,只有两个操作是允许的:把一个目录压入栈,以及把一个目录弹出栈。
|
||||
|
||||
`pushd` 命令会增加一个目录到栈顶,而 `popd` 命令会从栈顶移除一个目录。
|
||||
|
||||
为了显示目录栈中(或历史)的目录,我们可以使用下面展示的 `dirs` 命令:
|
||||
|
||||
```
|
||||
$ dirs
|
||||
或
|
||||
$ dirs -v
|
||||
```
|
||||
|
||||
![Dirs - Display Directories in Directory](https://www.tecmint.com/wp-content/uploads/2017/05/dirs-command.png)
|
||||
|
||||
*`dirs` - 显示位于目录栈中的目录*
|
||||
|
||||
`pushd` 命令:将一个目录路径添加到/放入目录栈(历史)中,之后,你可以浏览位于目录栈(历史)中的任意目录。当把一个新的目录入栈时,会打印出当前位于栈中的所有目录。
|
||||
|
||||
下面这些命令会展示这个命令是如何工作的:
|
||||
|
||||
```
|
||||
$ pushd /var/www/html/
|
||||
$ pushd ~/Documents/
|
||||
$ pushd ~/Desktop/
|
||||
$ pushd /var/log/
|
||||
```
|
||||
|
||||
![pushd - Add Directories to Stack](https://www.tecmint.com/wp-content/uploads/2017/05/pushd-examples.png)
|
||||
|
||||
*`pushd` - 添加新目录入栈*
|
||||
|
||||
根据上面输出的目录栈可知(目录索引按倒序排列):
|
||||
|
||||
* `/var/log` 是目录栈中的第五个目录,索引为 0
|
||||
* `~/Desktop/` 是第四个,索引为 1
|
||||
* `~/Document/` 是第三个,索引为 2
|
||||
* `/var/www/html` 是第二个,索引为 3
|
||||
* `~` 是第一个,索引为 4
|
||||
|
||||
另外,我们也可以使用目录索引的形式 `pushd +#` 或 `pushd -#` 来添加目录入栈。为了进入目录 `~/Documents` ,我们可以输入:
|
||||
|
||||
```
|
||||
$ pushd +2
|
||||
```
|
||||
|
||||
![pushd - Directory Navigation with Number](https://www.tecmint.com/wp-content/uploads/2017/05/pushd-Directory-Navigation-with-Number.png)
|
||||
|
||||
*`pushd` -通过数字浏览目录*
|
||||
|
||||
注意,经过上一步操作以后,栈的内容便发生了改变。所以,要从上面的例子中进入目录 `/var/www/html` ,我们应该使用下面的命令:
|
||||
|
||||
```
|
||||
$ pushd +1
|
||||
```
|
||||
|
||||
![pushd - Navigate Directory with Number](https://www.tecmint.com/wp-content/uploads/2017/05/pushd-Navigate-Directory-with-Number.png)
|
||||
|
||||
*`pushd` -通过数字浏览目录*
|
||||
|
||||
`popd` 命令-从栈顶或历史中移除一个目录。为了列出目录栈中的所有目录,只需输入:
|
||||
|
||||
```
|
||||
$ popd
|
||||
```
|
||||
|
||||
为了从目录栈中移除一个目录,我们可以使用 `popd +#` 或 `popd -#` 命令,在这时,我们需要输入下面的命令来移除目录 `~/Documents` :
|
||||
|
||||
```
|
||||
$ popd +1
|
||||
```
|
||||
|
||||
![popd - Remove Directory from Stack](https://www.tecmint.com/wp-content/uploads/2017/05/popd-exmples.png)
|
||||
|
||||
*`popd`-从栈中以移除目录*
|
||||
|
||||
也可以阅读:[Fasd-一个提供快速访问文件和目录功能的命令行工具][4]
|
||||
|
||||
在这篇文章中,我们阐述了 `pushd` 和 `popd` 命令,使用它们可以高效的访问目录结构。你可以通过下面的反馈表和我们分享你关于这篇文章的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 和 F.O.S.S 爱好者,将来的 Linux 系统管理员和网络开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并坚信分享知识。
|
||||
|
||||
-----
|
||||
|
||||
via: https://www.tecmint.com/pushd-and-popd-linux-filesystem-navigation/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/cd-command-in-linux/
|
||||
[2]:https://linux.cn/article-8491-1.html
|
||||
[3]:https://linux.cn/article-5983-1.html
|
||||
[4]:https://linux.cn/article-5983-1.html
|
||||
[5]:https://www.tecmint.com/author/aaronkili/
|
||||
[6]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[7]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
115
published/20170516 What's the point of DevOps.md
Normal file
115
published/20170516 What's the point of DevOps.md
Normal file
@ -0,0 +1,115 @@
|
||||
DevOps 的意义
|
||||
========================================
|
||||
|
||||
> 真正的组织文化变革有助于弥合你原以为无法跨过的鸿沟
|
||||
|
||||
![What's the point of DevOps?](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUSINESS_creativity.png?itok=zxGNSqJ1 "What's the point of DevOps?")
|
||||
|
||||
回想一下你最近一次尝试改掉一个个人习惯的事情,你可能遇到过这样的情形,你需要改变你思考的方式并且改掉之前的习惯。这很艰难,你只能试着改变_你自己的_思维方式。
|
||||
|
||||
所以你可能会试着让自己置身于新的环境。新的环境实际上可帮助我们养成_新的_习惯,它反过来又会促成新的思维方式。
|
||||
|
||||
那就是能否成功改变的所在:思考的越多,得到的越多。你需要知道你在改变的原因以及你的目的所在(而不仅仅你要怎么做),因为改变本身往往是短暂和短视的。
|
||||
|
||||
现在想想你的 IT 组织需要做出的改变。也许你正在考虑采用像 DevOps 这样的东西。这个我们称之为 “DevOps” 的东西有三个组件:人、流程和工具。人和流程是_任何_团体组织的基础。因此,采用 DevOps 需要对大多数组织的核心进行根本性的改变,而不仅仅是学习新的工具。
|
||||
|
||||
如同其它的改变一样,它也是短视的。如果您将注意力集中在将改变作为单点解决方案 —— 例如,“获得更好的报警工具” —— 你可能只是管中窥豹。这种思维方式或许可以提供一套拥有更多铃声、口哨以及可以更好地处理呼叫轮询的工具,但是它不能解决这样的实际问题:警报不能送达到正确的团队,或者故障得不到解决,因为实际上没有人知道如何修复服务。
|
||||
|
||||
新的工具(或者至少一个新工具的想法)创造了一个讨论潜在问题的机会,可以让你的团队讨论对监控的看法。新工具让你能够做出更大的改变 —— 信仰和做法的改变 —— 它们作为你组织的基础而显得更加重要。
|
||||
|
||||
创造更深层次的变革需要一种可以全新地改变观念的方法。要找到这种方法,我们首先需要更好的理解变革的驱动力。
|
||||
|
||||
### 清除栅栏
|
||||
|
||||
> 就改革而言,它不同于推翻。这是一条直白且简单的原则,这个原则或许被视作悖论。在这种情况下,存在某种制度或法律;这么说吧,为了简单起见,在一条路上架设了一个栅栏或门。当今的改革者们来到这儿,并说:“我看不到它的用处,让我们把它清除掉。”更聪明的改革者会很好地回答:“如果你看不到它的用处,我肯定不会让你清除它,回去想想,然后你可以回来告诉我你知道了它的用处,我也许会允许你摧毁它。” — G.K Chesterton, 1929
|
||||
|
||||
为了了解对 DevOps 的需求 —— 它试图将传统意义上分开的开发部门和运维部门进行重新组合 —— 我们首先必须明白这个分开是如何产生的。一旦我们"知道了它的用处",然后我们就会知道将它们分开是为了什么,并且在必要的时候可以取消分开。
|
||||
|
||||
今天我们没有一个单一的管理理论,但是大多数现代管理理论的起源可以追溯到<ruby>弗雷德里克·温斯洛·泰勒<rt>Frederick Winslow Taylor</rt></ruby>。泰勒是一名机械工程师,他创建了一个衡量钢厂工人效率的系统。泰勒认为,他可以对工厂的劳动者运用科学分析的方法,不仅可以改进个人任务,也证明发现了有一个可以用来执行_任何_任务最佳方法。
|
||||
|
||||
我们可以很容易地画一个以泰勒为起源的历史树。从泰勒早在 18 世纪 80 年代后期的研究出现的时间运动研究和其他质量改进计划,跨越 20 世纪 20 年代一直到今天,我们可以从中看到六西格玛、精益,等等类似方法。自上而下、指导式管理,再加上研究过程的系统方法,主宰了今天主流商业文化。它主要侧重于把效率作为工人成功的测量标准。
|
||||
|
||||
如果泰勒是我们这颗历史树的根,那么我们主干上的下一个主叉将是 20 世纪 20 年代通用汽车公司的<ruby>阿尔弗雷德·斯隆<rt>Alfred P. Sloan</rt></ruby>。通用汽车公司创造的斯隆结构不仅持续强劲到 21 世纪初,而且在未来五十年的大部分时间里,都将成为该公司的主要模式。
|
||||
|
||||
1920 年,通用公司正经历一场管理危机,或者说是缺乏管理的危机。斯隆向董事会写了一份为通用汽车的多个部门提出了一个新的结构《组织研究》。这一新结构的核心概念是“集中管理下放业务”。与雪佛兰,凯迪拉克和别克等品牌相关的各个部门将独立运作,同时为中央管理层提供推动战略和控制财务的手段。
|
||||
|
||||
在斯隆的建议下(以及后来就任 CEO 的指导下),通用汽车在美国汽车工业中占据了主导地位。斯隆的计划把一个处于灾难边缘公司创造成了一个非常成功的公司。从中间来看,自治单位是黑盒子,激励和目标被设置在顶层,而团队在底层推动。
|
||||
|
||||
泰勒思想的“最佳实践” —— 标准、可互换和可重复的行为 —— 仍然在今天的管理理念中占有一席之地,与斯隆公司结构的层次模式相结合,主导了僵化部门的分裂和孤岛化以实现最大的控制。
|
||||
|
||||
我们可以指出几份管理研究来证明这一点,但商业文化不是通过阅读书籍而创造和传播的。组织文化是 *真实的* 人在 *实际的* 情形下执行推动文化规范的 *具体的* 行为的产物。这就是为何类似泰勒和斯隆这样的理论变得固化而不可动摇的原因。
|
||||
|
||||
技术部门投资就是一个例子。以下是这个周期是如何循环的:投资者只投资于他们认为可以实现 *他们的* 特定成功观点的公司。这个成功的模式并不一定源于公司本身(和它的特定的目标);它来自董事会对一家成功的公司 *应该* 如何看待的想法。许多投资者来自从经营企业的尝试和苦难中幸存下来的公司,因此他们对什么会使一个公司成功有 *不同的* 理念。他们为那些能够被教导模仿他们的成功模式的公司提供资金,希望获得资金的公司学会模仿。这样,初创公司孵化器就是一种重现理想的结构和文化的*直接的*方式。
|
||||
|
||||
“开发”和“运维”的分开不是因为人的原因,也不是因为不同的技能,或者放在新员工头上的一顶魔法分院帽;它是泰勒和斯隆的理论的副产品。责任与人员之间的清晰而不可渗透的界线是一个管理功能,同时也注重员工的工作效率。管理上的分开可以很容易的落在产品或者项目界线上,而不是技能上,但是通过今天的业务管理理论的历史告诉我们,基于技能的分组是“最好”的高效方式。
|
||||
|
||||
不幸的是,那些界线造成了紧张局势,这些紧张局势是由不同的管理链出于不同的目标设定的相反目标的直接结果。例如:
|
||||
|
||||
* 敏捷 ⟷ 稳定
|
||||
* 吸引新用户 ⟷ 现有用户的体验
|
||||
* 让应用程序增加新功能 ⟷ 让应用程序保持可用
|
||||
* 打败竞争对手 ⟷ 维持收入
|
||||
* 修复出现的问题 ⟷ 在问题出现之前就进行预防
|
||||
|
||||
今天,我们可以看到组织的高层领导人越来越认识到,现有的商业文化(并扩大了它所产生的紧张局势)是一个严重的问题。在 2016 年的 Gartner 报告中,57% 的受访者表示,文化变革是 2020 年之前企业面临的主要挑战之一。像作为一种影响组织变革的手段的敏捷和 DevOps 这样的新方法的兴起反映了这一认识。“[影子 IT][7]” 的出现更是事物的另一个方面;最近的估计有将近 30% 的 IT 支出在 IT 组织的控制之外。
|
||||
|
||||
这些只是企业正在面临的一些“文化担忧”。改变的必要性是明确的,但前进的道路仍然受到昨天的决定的约束。
|
||||
|
||||
### 抵抗并不是没用的
|
||||
|
||||
> Bert Lance 认为如果他能让政府采纳一条简单的格言“如果东西还没损坏,那就别去修理它”,他就可以为国家节省三十亿。他解释说:“这是政府的问题:‘修复没有损坏的东西,而不是修复已经损坏了的东西。’” — Nation's Business, 1977.5
|
||||
|
||||
通常,改革是组织针对所出现的错误所做的应对。在这个意义上说,如果紧张局势(即使逆境)是变革的正常催化剂,那么对变化的 *抵抗* 就是成功的指标。但是过分强调成功的道路会使组织变得僵硬、衰竭和独断。重视有效结果的政策导向是这种不断增长的僵局的症状。
|
||||
|
||||
传统 IT 部门的成功加剧了 IT 孤岛的壁垒。其他部门现在变成了“顾客”,而不是伙伴。试图将 IT 从成本中心转移出来创建一个新的操作模式,它可以将 IT 与其他业务目标断开。这反过来又会对敏捷性造成限制,增加摩擦,降低反应能力。合作被搁置转而偏向“专家方向”。结果是一个孤立主义的观点,IT 只能带来更多的伤害而不是好处。
|
||||
|
||||
正如“软件吃掉世界”,IT 越来越成为组织整体成功的核心。具有前瞻性的 IT 组织认识到这一点,并且已经对其战略规划进行了有意义的改变,而不是将改变视为恐惧。
|
||||
|
||||
例如,Facebook 与人类学家<ruby>罗宾·邓巴<rt>Robin Dunbar</rt></ruby>就社会团体的方法进行了磋商,而且意识到这一点对公司成长的内部团体(不仅仅是该网站的外部用户)的影响。<ruby>扎波斯<rt>Zappos</rt></ruby>的文化得到了很多的赞誉,该组织创立了一个部门,专注于培养他人对于核心价值观和企业文化的看法。当然,这本书是 《开放式组织》的姊妹篇,那是一本描述被应用于管理的开放原则 —— 透明度、参与度和社区 —— 可以如何为我们快节奏的互联时代重塑组织。
|
||||
|
||||
### 决心改变
|
||||
|
||||
> “如果外界的变化率超过了内部的变化率,那末日就不远了。” — Jack Welch, 2004
|
||||
|
||||
一位同事曾经告诉我他可以只用 “[信息技术基础设施库(ITIL)][9]” 框架里面的词汇向一位项目经理解释 DevOps。
|
||||
|
||||
虽然这些框架 *似乎* 是反面的,但实际上它们都集中在风险和变革管理上。它们简单地介绍了这种管理的不同流程和工具。在 IT 圈子外面谈论 DevOps 时,这一点需要注意。不要强调流程问题和故障,而是显示更小的变化引起的风险 *更小* 等等。这是强调改变团队文化的有益方式:专注于 *新的* 功能而不是老问题,是改变的有效中介,特别是当您采用别人的框架进行参考时。
|
||||
|
||||
改革不仅仅只是 *重构* 组织;它也是跨越历史上不可跨越的鸿沟的新途径 —— 通过拒绝把像“敏捷”和“稳定”这样的东西作为互相排斥的力量来解决我之前提到的那些紧张局势。建立注重 *结果* 胜过 *功能* 的跨部门团队是一个有效的策略。把不同的团队 —— 其中每个人的工作依赖于其他人 —— 聚集起来围绕一个项目或目标是最常见的方法之一。消除这些团队之间的摩擦和改善沟通能够产生巨大的改进 —— 即使在坚持铁仓管理结构时(如果可以掌握,则不需要拆除孤岛)。在这些情况下,对改革的 *抵抗* 不是成功的一个指标;而对改革的拥抱才是。
|
||||
|
||||
这些也不是“最佳实例”,它们只是一种检查你自己的栅栏的方式。每个组织都会有独特的、由他们内部人员创造的栅栏。一旦你“知道了它的用途”,你就可以决定它是需要拆解还是掌握。
|
||||
|
||||
** 本文是 Opensource.com 即将推出的关于开放组织和 IT 文化指南的一部分。[你可以在这注册以便当它发布时收到通知][5]**
|
||||
|
||||
(题图 : opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
作者简介:
|
||||
|
||||
Matt Micene 是 Red Hat 公司的 Linux 和容器传播者。从架构和系统设计到数据中心设计,他在信息技术方面拥有超过 15 年的经验。他对关键技术(如容器,云计算和虚拟化)有深入的了解。他目前的重点是宣传红帽企业版 Linux,以及操作系统如何与计算环境的新时代相关。
|
||||
|
||||
------------------------------------------
|
||||
|
||||
via: https://opensource.com/open-organization/17/5/what-is-the-point-of-DevOps
|
||||
|
||||
作者:[Matt Micene][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[apemost](https://github.com/apemost),[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/matt-micene
|
||||
[1]:https://opensource.com/open-organization/resources/leaders-manual?src=too_resource_menu
|
||||
[2]:https://opensource.com/open-organization/resources/field-guide?src=too_resource_menu
|
||||
[3]:https://opensource.com/open-organization/resources/open-org-definition?src=too_resource_menu
|
||||
[4]:https://opensource.com/open-organization/resources/open-decision-framework?src=too_resource_menu
|
||||
[5]:https://opensource.com/open-organization/resources/book-series
|
||||
[6]:https://opensource.com/open-organization/17/5/what-is-the-point-of-DevOps?rate=gOQvGqsEbNk_RSnoU0wP3PJ71E_XDYiYo7KS2HKFfP0
|
||||
[7]:https://thenewstack.io/parity-check-dont-afraid-shadow-yet/
|
||||
[8]:http://www.npr.org/2017/01/13/509358157/is-there-a-limit-to-how-many-friends-we-can-have
|
||||
[9]:https://en.wikipedia.org/wiki/ITIL
|
||||
[10]:https://opensource.com/user/18066/feed
|
||||
[11]:https://opensource.com/open-organization/17/5/what-is-the-point-of-DevOps#comments
|
||||
[12]:https://opensource.com/users/matt-micene
|
187
published/20170529 LFCS sed Command.md
Normal file
187
published/20170529 LFCS sed Command.md
Normal file
@ -0,0 +1,187 @@
|
||||
LFCS 基础:sed 命令
|
||||
=====================
|
||||
|
||||
Linux 基金会认证系统管理员(LFCS)的另一个有用的命令是 “sed”,最初表示“流式编辑器” (Streaming EDitor)。
|
||||
|
||||
“sed” 命令是一个可以将文件作为流进行编辑的编辑器。流式传输文件的方法是从另一个命令使用管道(`>` 或 `|`)传递,或将其直接加载到 “sed” 中。
|
||||
|
||||
该命令的工作方式与其他编辑器相同,只是文件不显示,也不允许可视化编辑。命令被传递给 “sed” 来操纵流。
|
||||
|
||||
用 “sed” 可以做五件基本的事。当然,“sed” 如此强大,还有其他高级的功能,但你只需要集中精力在五件基本的事上。五种功能类型如下:
|
||||
|
||||
1. 搜索
|
||||
2. 替换
|
||||
3. 删除
|
||||
4. 添加
|
||||
5. 改变/变换
|
||||
|
||||
在深入命令参数之前,我们需要看看基本的语法。
|
||||
|
||||
### 语法
|
||||
|
||||
“sed” 命令的语法是:
|
||||
|
||||
```
|
||||
sed [选项] 命令 [要编辑的文件]
|
||||
```
|
||||
|
||||
本文将在适当的部分中介绍这些“选项”。“命令”可以是正则表达式的搜索和替换模式。请继续阅读了解 “sed” 如何工作的并学习基本命令。正如我之前提到的,“sed” 是一个非常强大的工具,有更多的选项可用,我将在本文中介绍。
|
||||
|
||||
### 示例文件
|
||||
|
||||
如果你打开一个终端,那你可以创建一个用于 “sed” 示例的文件。执行以下命令:
|
||||
|
||||
```
|
||||
cd ~
|
||||
grep --help >grephelp.txt
|
||||
```
|
||||
|
||||
你现在应该在 HOME 文件夹中有一个名为 `grephelp.txt` 的文件。该文件的内容是 `grep` 命令的帮助说明。
|
||||
|
||||
### 搜索
|
||||
|
||||
搜索特定字符串是编辑器的常见功能,在 “sed” 中执行搜索也不例外。
|
||||
|
||||
执行搜索以在文件中查找字符串。我们来看一下基本的搜索。
|
||||
|
||||
如果我们想在示例文件搜索 `PATTERN` 这个词,我们将使用如下命令:
|
||||
|
||||
```
|
||||
sed -n 's/PATTERN/PATTERN/p' grephelp.txt
|
||||
```
|
||||
|
||||
**注意:** 如果剪切粘贴命令,请确保将单引号替换为键盘上的标准单引号。
|
||||
|
||||
参数 `-n` 用于抑制每行的自动打印(除了用 `p` 命令指定的行)。默认情况下,流入 “sed” 的每一行将被打印到标准输出(stdout)。如果你不使用 “-n” 选项运行上述命令,你将看到原始文件的每一行以及匹配的行。
|
||||
|
||||
要搜索的文件名是我们在“示例文件”部分中创建的 “grephelp.txt”。
|
||||
|
||||
剩下的部分是 `'s/PATTERN/PATTERN/p'` 。这一段基本分为四个部分。第一部分的 `s` 指定执行替换,或搜索并替换。
|
||||
|
||||
剩下的第二部分和第三部分是模式。第一个是要搜索的模式,最后一个是替换流中匹配字符串的模式。此例中,我们找到字符串 `PATTERN`,并用 `PATTERN` 替换。通过查找和替换相同的字符串,我们完全不会更改文件,甚至在屏幕上也一样。
|
||||
|
||||
最后一个命令是 `p`。 它指定在替换后打印新行。当然,因为替换的是相同的字符串,所以没有改变。由于我们使用 `-n` 参数抑制打印行,所以更改的行将使用 `p` 命令打印。
|
||||
|
||||
这个完整的命令允许我们执行搜索并查看匹配的结果。
|
||||
|
||||
### 替换
|
||||
|
||||
当搜索特定字符串时,你可能希望用匹配的字符串替换新字符串。用另一个字符串替换是很常见的操作。
|
||||
|
||||
我们可以使用以下命令执行相同的搜索:
|
||||
|
||||
```
|
||||
sed -n 's/PATTERN/Pattern/p' grephelp.txt
|
||||
```
|
||||
|
||||
在这时,字符串 “PATTERN” 变为 “Pattern” 并显示。如果你使用命令 `cat grephelp.txt` 查看文件,你会看到该文件没有更改。该更改仅对屏幕上的输出进行。你可以使用以下命令将输出通过管道传输到另一个文件:
|
||||
|
||||
```
|
||||
sed 's/PATTERN/Pattern/' grephelp.txt > grephelp1.txt
|
||||
```
|
||||
|
||||
现在将存在一个名为 `grephelp1.txt` 的新文件,其中保存了更改的文件。如果 `p` 作为第四个选项留下,那么有个问题是被替换的字符串的每一行将在文件中重复两次。我们也可以删除 “-n” 参数以允许所有的行打印。
|
||||
|
||||
使用相同字符串替换字符串的另一种方法是使用 `&` 符号来表示搜索字符串。例如,命令 `s/PATTERN/&/p` 效果是一样的。我们可以添加字符串,例如添加 `S`,可以使用命令 `s/PATTERN/&S/p`。
|
||||
|
||||
如果我们希望在每一行中只替换某种模式呢?可以指定要替换的匹配项的特定出现。当然,每一行的替换都是一个特定的编号。例如,示例文件上有很多破折号。一些行至少有两条破折号,所以我们可以用另一个字符代替每一行的第二个破折号。每行用星号 `*` 替换第二个破折号 `-` 的命令将是:
|
||||
|
||||
```
|
||||
sed 's/-/*/2' grephelp.txt
|
||||
```
|
||||
|
||||
在这里,我们用最初的 `s` 来执行替换。字符 `-` 被替换为 `*`。`2` 表示我们想要替换每行上的第二个 `-`(如果存在)。如果我们忽略了命令 `2`,则替换第一次出现的破折号。只有第一个破折号而不是每行的破折号都被替换。
|
||||
|
||||
如果要搜索并替换带有星号的行上的所有破折号,请使用 `g` 命令:
|
||||
|
||||
```
|
||||
sed 's/-/*/g' grephelp.txt
|
||||
```
|
||||
|
||||
命令也可以组合。假设你想要替换从第二次开始出现的破折号,命令将是:
|
||||
|
||||
```
|
||||
sed 's/-/*/2g' grephelp.txt
|
||||
```
|
||||
|
||||
现在从第二个开始出现的破折号将被星号取代。
|
||||
|
||||
### 删除
|
||||
|
||||
搜索过程中有很多时候你可能想要完全删除搜索字符串。
|
||||
|
||||
例如,如果要从文件中删除所有破折号,你可以使用以下命令:
|
||||
|
||||
```
|
||||
sed 's/-//g' grephelp.txt
|
||||
```
|
||||
|
||||
替换字符串为空白,因此匹配的字符串将被删除。
|
||||
|
||||
### 添加
|
||||
|
||||
当找到匹配时,你可以添加一行特定的文本,来使这行在浏览或打印中突出。
|
||||
|
||||
如果要在匹配后插入新行,那么使用 `a` 命令,后面跟上新行的字符串。还包括要匹配的字符串。例如,我们可以找到一个 `--`,并在匹配的行之后添加一行。新行的字符串将是 `double dash before this line`。
|
||||
|
||||
```
|
||||
sed '/--/ a "double dash before this line"' grephelp.txt
|
||||
```
|
||||
|
||||
如果要在包含匹配字符串的行之前加上这行,请使用 `i` 命令,如下所示:
|
||||
|
||||
```
|
||||
sed '/--/ i "double dash after this line"' grephelp.txt
|
||||
```
|
||||
|
||||
### 改变/变换
|
||||
|
||||
如果需要改变/变换一行,则可以使用命令 `c`。
|
||||
|
||||
假设我们有个有一些私人信息的文档,我们需要更改包含特定字符串的行。`c` 命令将改变整行,而不仅仅是搜索字符串。
|
||||
|
||||
假设我们想要阻止示例文件中包含单词 `PATTERN` 的每一行。更改的行将显示为 `This line is Top Secret`。命令是:
|
||||
|
||||
```
|
||||
sed '/PATTERN/ c This line is Top Secret' grephelp.txt
|
||||
```
|
||||
|
||||
可以进行更改特定字母的大小写的转换。例如,我们可以使用命令 `y` 将所有小写 `a` 更改为大写 `A`,如下所示:
|
||||
|
||||
```
|
||||
sed 'y/a/A/' grephelp.txt
|
||||
```
|
||||
|
||||
可以指定多个字母,如 `abdg`,如下命令所示:
|
||||
|
||||
```
|
||||
sed 'y/abdg/ABDG/' grephelp.txt
|
||||
```
|
||||
|
||||
确保第二组字母与第一组字母的顺序相同,否则会被替换和转换。例如,字符串 `y/a/D/` 将用大写 `D` 替换所有小写的 `a`。
|
||||
|
||||
### 就地更改
|
||||
|
||||
如果你确实要更改所使用的文件,请使用 `-i` 选项。
|
||||
|
||||
例如,要将 `PATTERN` 改为 `Pattern`,并对文件进行更改,则命令为:
|
||||
|
||||
```
|
||||
sed -i 's/PATTERN/Pattern/' grephelp.txt
|
||||
```
|
||||
|
||||
现在文件 `grephelp.txt` 将被更改。`-i` 选项可以与上述任何命令一起使用来更改原始文件的内容。
|
||||
|
||||
练习这些命令,并确保你理解它们。“sed” 命令非常强大。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.org/threads/lfcs-sed-command.4561/
|
||||
|
||||
作者:[Jarret B][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linux.org/threads/lfcs-sed-command.4561/
|
@ -1,35 +1,33 @@
|
||||
[调试器的工作原理: 第3篇 - 调试信息][25]
|
||||
调试器工作原理(三):调试信息
|
||||
============================================================
|
||||
|
||||
|
||||
这是调试器的工作原理系列文章的第三篇。阅读这篇文章之前应当先阅读[第一篇][26]与[第二篇][27]。
|
||||
|
||||
### 这篇文章的主要内容
|
||||
|
||||
本文将解释调试器是如何在机器码中,查找它将C语言源代码转换成机器语言代码时所需要的C语言函数、变量、与数据。
|
||||
本文将解释调试器是如何在机器码中查找它将 C 语言源代码转换成机器语言代码时所需要的 C 语言函数、变量、与数据。
|
||||
|
||||
### 调试信息
|
||||
|
||||
|
||||
现代编译器能够将有着各种排版或嵌套的程序流程、各种数据类型的变量的高级语言代码转换为一大堆称之为机器码的 0/1 数据,这么做的唯一目的是尽可能快的在目标 CPU 上运行程序。通常来说一行C语言代码能够转换为若干条机器码。变量被分散在机器码中的各个部分,有的在堆栈中,有的在寄存器中,或者直接被优化掉了。数据结构与对象在机器码中甚至不“存在”,它们只是用于将数据按一定的结构编码存储进缓存。
|
||||
现代编译器能够将有着各种缩进或嵌套的程序流程、各种数据类型的变量的高级语言代码转换为一大堆称之为机器码的 0/1 数据,这么做的唯一目的是尽可能快的在目标 CPU 上运行程序。通常来说一行 C 语言代码能够转换为若干条机器码。变量被分散在机器码中的各个部分,有的在堆栈中,有的在寄存器中,或者直接被优化掉了。数据结构与对象在机器码中甚至不“存在”,它们只是用于将数据按一定的结构编码存储进缓存。
|
||||
|
||||
那么调试器怎么知道,当你需要在某个函数入口处暂停时,程序要在哪停下来呢?它怎么知道当你查看某个变量值时,它怎么找到这个值?答案是,调试信息。
|
||||
|
||||
编译器在生成机器码时同时会生成相应的调试信息。调试信息代表了可执行程序与源代码之间的关系,并以一种提前定义好的格式,同机器码存放在一起。过去的数年里,人们针对不同的平台与可执行文件发明了很多种用于存储这些信息的格式。不过我们这篇文章不会讲这些格式的历史,而是将阐述这些调试信息是如何工作的,所以我们将专注于一些事情,比如 `DWARF`。`DWARF` 如今十分广泛的应用在类 `Unix` 平台上的可执行文件的调试。
|
||||
编译器在生成机器码时同时会生成相应的调试信息。调试信息代表了可执行程序与源代码之间的关系,并以一种提前定义好的格式,同机器码存放在一起。过去的数年里,人们针对不同的平台与可执行文件发明了很多种用于存储这些信息的格式。不过我们这篇文章不会讲这些格式的历史,而是将阐述这些调试信息是如何工作的,所以我们将专注于一些事情,比如 `DWARF`。`DWARF` 如今十分广泛的用作 Linux 和类 `Unix` 平台上的可执行文件的调试格式。
|
||||
|
||||
### ELF 中的 DWARF
|
||||
|
||||
![](http://eli.thegreenplace.net/images/2011/02/dwarf_logo.gif)
|
||||
![](http://eli.thegreenplace.net/images/2011/02/dwarf_logo.gif)
|
||||
|
||||
根据[它的维基百科][17] 所描述,虽然 `DWARF` 是同 `ELF` 一同设计的(`DWARF` 是由 `DWARF` 标准委员会推出的开放标准。上文中展示的 图标就来自这个网站。),但 `DWARF` 在理论上来说也可以嵌入到其他的可执行文件格式中。
|
||||
根据[它的维基百科][17] 所描述,虽然 `DWARF` 是同 `ELF` 一同设计的(`DWARF` 是由 `DWARF` 标准委员会推出的开放标准。上文中展示的图标就来自这个网站。),但 `DWARF` 在理论上来说也可以嵌入到其他的可执行文件格式中。
|
||||
|
||||
`DWARF` 是一种复杂的格式,它的构建基于过去多年中许多不同的编译器与操作系统。正是因为它解决了一个为任意语言在任何平台与业务系统中产生调试信息的这样棘手的难题,它也必须很复杂。想要透彻的讲解 `DWARF` 仅仅是通过这单薄的一篇文章是远远不够的,说实话我也并没有充分地了解 `DWARF` 到每一个微小的细节,所以我也不能十分透彻的讲解 (如果你感兴趣的话,文末有一些能够帮助你的资源。建议从 `DWARF` 教程开始上手)。这篇文章中我将以浅显易懂的方式展示 `DWARF` 在实际应用中调试信息是如何工作的。
|
||||
`DWARF` 是一种复杂的格式,它吸收了过去许多年各种不同的架构与操作系统的格式的经验。正是因为它解决了一个在任何平台与 ABI (应用二进制接口)上为任意高级语言产生调试信息这样棘手的难题,它也必须很复杂。想要透彻的讲解 `DWARF` 仅仅是通过这单薄的一篇文章是远远不够的,说实话我也并没有充分地了解 `DWARF` 到每一个微小的细节,所以我也不能十分透彻的讲解 (如果你感兴趣的话,文末有一些能够帮助你的资源。建议从 `DWARF` 教程开始上手)。这篇文章中我将以浅显易懂的方式展示 `DWARF`,以说明调试信息是如何实际工作的。
|
||||
|
||||
### ELF文件中的调试部分
|
||||
### ELF 文件中的调试部分
|
||||
|
||||
首先让我们看看 `DWARF` 处在 ELF 文件中的什么位置。`ELF` 定义了每一个生成的目标文件中的每一部分。 _section header table_ 声明并定义了每一部分。不同的工具以不同的方式处理不同的部分,例如连接器会寻找连接器需要的部分,调试器会查找调试器需要的部分。
|
||||
首先让我们看看 `DWARF` 处在 ELF 文件中的什么位置。`ELF` 定义了每一个生成的目标文件中的每一节。 <ruby>节头表<rt>section header table</rt></ruby> 声明并定义了每一节及其名字。不同的工具以不同的方式处理不同的节,例如连接器会寻找连接器需要的部分,调试器会查找调试器需要的部分。
|
||||
|
||||
我们本文的实验会使用从这个C语言源文件构建的可执行文件,编译成 tracedprog2:
|
||||
我们本文的实验会使用从这个 C 语言源文件构建的可执行文件,编译成 `tracedprog2`:
|
||||
|
||||
|
||||
```
|
||||
@ -52,7 +50,7 @@ int main()
|
||||
```
|
||||
|
||||
|
||||
使用 `objdump -h` 命令检查 `ELF` 可执行文件中的段落头,我们会看到几个以 .debug_ 开头的段落,这些就是 `DWARF` 的调试部分。
|
||||
使用 `objdump -h` 命令检查 `ELF` 可执行文件中的<ruby>节头<rt>section header</rt></ruby>,我们会看到几个以 `.debug_` 开头的节,这些就是 `DWARF` 的调试部分。
|
||||
|
||||
```
|
||||
26 .debug_aranges 00000020 00000000 00000000 00001037
|
||||
@ -73,23 +71,23 @@ int main()
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
```
|
||||
|
||||
每个段落的第一个数字代表了这个段落的大小,最后一个数字代表了这个段落开始位置距离 `ELF` 的偏移量。调试器利用这些信息从可执行文件中读取段落。
|
||||
每个节的第一个数字代表了该节的大小,最后一个数字代表了这个节开始位置距离 `ELF` 的偏移量。调试器利用这些信息从可执行文件中读取节。
|
||||
|
||||
现在让我们看看一些在 `DWARF` 中查找有用的调试信息的实际例子。
|
||||
|
||||
### 查找函数
|
||||
|
||||
调试器的基础任务之一,就是当我们在某个函数处设置断点时,调试器需要能够在入口处暂停。为此,必须为函数与函数在机器码地址这两者建立起某种映射关系。
|
||||
调试器的最基础的任务之一,就是当我们在某个函数处设置断点时,调试器需要能够在入口处暂停。为此,必须为高级代码中的函数名称与函数在机器码中指令开始的地址这两者之间建立起某种映射关系。
|
||||
|
||||
为了获取这种映射关系,我们可以查找 `DWARF` 中的 .debug_info 段落。在我们深入之前,需要一点基础知识。`DWARF` 中每一个描述类型被称之为调试信息入口(`DIE`)。每个 `DIE` 都有关于它的属性之类的标签。`DIE` 之间通过兄弟节点或子节点连接,属性的值也可以指向其他的 `DIE`.
|
||||
为了获取这种映射关系,我们可以查找 `DWARF` 中的 `.debug_info` 节。在我们深入之前,需要一点基础知识。`DWARF` 中每一个描述类型被称之为调试信息入口(`DIE`)。每个 `DIE` 都有关于它的类型、属性之类的标签。`DIE` 之间通过兄弟节点或子节点相互连接,属性的值也可以指向其它的 `DIE`。
|
||||
|
||||
运行以下命令
|
||||
运行以下命令:
|
||||
|
||||
```
|
||||
objdump --dwarf=info tracedprog2
|
||||
```
|
||||
|
||||
输出文件相当的长,为了方便举例我们只关注这些行(从这里开始,无用的冗长信息我会以 (...)代替,方便排版。):
|
||||
输出文件相当的长,为了方便举例我们只关注这些行(从这里开始,无用的冗长信息我会以 (...)代替,方便排版):
|
||||
|
||||
```
|
||||
<1><71>: Abbrev Number: 5 (DW_TAG_subprogram)
|
||||
@ -114,7 +112,7 @@ objdump --dwarf=info tracedprog2
|
||||
<c7> DW_AT_frame_base : 0x2c (location list)
|
||||
```
|
||||
|
||||
上面的代码中有两个带有 DW_TAG_subprogram 标签的入口,在 `DWARF` 中这是对函数的指代。注意,这是两个段落入口,其中一个是 do_stuff 函数的入口,另一个是主函数的入口。这些信息中有很多值得关注的属性,但其中最值得注意的是 DW_AT_low_pc。它代表了函数开始处程序指针的值(在x86平台上是 `EIP`)。此处 0x8048604 代表了 do_stuff 函数开始处的程序指针。下面我们将利用 `objdump -d` 命令对可执行文件进行反汇编。来看看这块地址中都有什么:
|
||||
上面的代码中有两个带有 `DW_TAG_subprogram` 标签的入口,在 `DWARF` 中这是对函数的指代。注意,这是两个节的入口,其中一个是 `do_stuff` 函数的入口,另一个是主(`main`)函数的入口。这些信息中有很多值得关注的属性,但其中最值得注意的是 `DW_AT_low_pc`。它代表了函数开始处程序指针的值(在 x86 平台上是 `EIP`)。此处 `0x8048604` 代表了 `do_stuff` 函数开始处的程序指针。下面我们将利用 `objdump -d` 命令对可执行文件进行反汇编。来看看这块地址中都有什么:
|
||||
|
||||
```
|
||||
08048604 <do_stuff>:
|
||||
@ -139,13 +137,13 @@ objdump --dwarf=info tracedprog2
|
||||
804863d: c3 ret
|
||||
```
|
||||
|
||||
显然,0x8048604 是 do_stuff 的开始地址,这样一来,调试器就可以建立函数与其在可执行文件中的位置间的映射关系。
|
||||
显然,`0x8048604` 是 `do_stuff` 的开始地址,这样一来,调试器就可以建立函数与其在可执行文件中的位置间的映射关系。
|
||||
|
||||
### 查找变量
|
||||
|
||||
假设我们当前在 do_staff 函数中某个位置上设置断点停了下来。我们想通过调试器取得 my_local 这个变量的值。调试器怎么知道在哪里去找这个值呢?很显然这要比查找函数更为困难。变量可能存储在全局存储区、堆栈、甚至是寄存器中。此外,同名变量在不同的作用域中可能有着不同的值。调试信息必须能够反映所有的这些变化,当然,`DWARF` 就能做到。
|
||||
假设我们当前在 `do_staff` 函数中某个位置上设置断点停了下来。我们想通过调试器取得 `my_local` 这个变量的值。调试器怎么知道在哪里去找这个值呢?很显然这要比查找函数更为困难。变量可能存储在全局存储区、堆栈、甚至是寄存器中。此外,同名变量在不同的作用域中可能有着不同的值。调试信息必须能够反映所有的这些变化,当然,`DWARF` 就能做到。
|
||||
|
||||
我不会逐一去将每一种可能的状况,但我会以调试器在 do_stuff 函数中查找 my_local 变量的过程来举个例子。下面我们再看一遍 .debug_info 中 do_stuff 的每一个入口,这次连它的子入口也要一起看。
|
||||
我不会逐一去将每一种可能的状况,但我会以调试器在 `do_stuff` 函数中查找 `my_local` 变量的过程来举个例子。下面我们再看一遍 `.debug_info` 中 `do_stuff` 的每一个入口,这次连它的子入口也要一起看。
|
||||
|
||||
```
|
||||
<1><71>: Abbrev Number: 5 (DW_TAG_subprogram)
|
||||
@ -178,11 +176,11 @@ objdump --dwarf=info tracedprog2
|
||||
<af> DW_AT_location : (...) (DW_OP_fbreg: -24)
|
||||
```
|
||||
|
||||
看到每个入口处第一对尖括号中的数字了吗?这些是嵌套的等级,在上面的例子中,以 <2> 开头的入口是以 <1> 开头的子入口。因此我们得知 my_local 变量(以 DW_TAG_variable 标签标记)是 do_stuff 函数的局部变量。除此之外,调试器也需要知道变量的数据类型,这样才能正确的使用与显示变量。上面的例子中 my_local 的变量类型指向另一个 `DIE` <0x4b>。如果使用 objdump 命令查看这个 `DIE` 部分的话,我们会发现这部分代表了有符号4字节整型数据。
|
||||
看到每个入口处第一对尖括号中的数字了吗?这些是嵌套的等级,在上面的例子中,以 `<2>` 开头的入口是以 `<1>` 开头的子入口。因此我们得知 `my_local` 变量(以 `DW_TAG_variable` 标签标记)是 `do_stuff` 函数的局部变量。除此之外,调试器也需要知道变量的数据类型,这样才能正确的使用与显示变量。上面的例子中 `my_local` 的变量类型指向另一个 `DIE` `<0x4b>`。如果使用 `objdump` 命令查看这个 `DIE` 的话,我们会发现它是一个有符号 4 字节整型数据。
|
||||
|
||||
而为了在实际运行的程序内存中查找变量的值,调试器需要使用到 DW_AT_location 属性。对于 my_local 而言,是 DW_OP_fbreg: -20。这个代码段的意思是说 my_local 存储在距离它所在函数起始地址偏移量为-20的地方。
|
||||
而为了在实际运行的程序内存中查找变量的值,调试器需要使用到 `DW_AT_location` 属性。对于 `my_local` 而言,是 `DW_OP_fbreg: -20`。这个代码段的意思是说 `my_local` 存储在距离它所在函数起始地址偏移量为 `-20` 的地方。
|
||||
|
||||
do_stuff 函数的 DW_AT_frame_base 属性值为 0x0 (location list)。这意味着这个属性的值需要在 location list 中查找。下面我们来一起看看。
|
||||
`do_stuff` 函数的 `DW_AT_frame_base` 属性值为 `0x0 (location list)`。这意味着这个属性的值需要在 `location list` 中查找。下面我们来一起看看。
|
||||
|
||||
```
|
||||
$ objdump --dwarf=loc tracedprog2
|
||||
@ -202,9 +200,9 @@ Contents of the .debug_loc section:
|
||||
0000002c <End of list>
|
||||
```
|
||||
|
||||
我们需要关注的是第一列(do_stuff 函数的 DW_AT_frame_base 属性包含 location list 中 0x0 的偏移量。而 main 函数的相同属性包含 0x2c 的偏移量,这个偏移量是第二套地址列表的偏移量。)。对于调试器可能定位到的每一个地址,它都会指定当前栈帧到变量间的偏移量,而这个偏移就是通过寄存器来计算的。对于x86平台而言,bpreg4 指向 esp,而 bpreg5 指向 ebp。
|
||||
我们需要关注的是第一列(`do_stuff` 函数的 `DW_AT_frame_base` 属性包含 `location list` 中 `0x0` 的偏移量。而 `main` 函数的相同属性包含 `0x2c` 的偏移量,这个偏移量是第二套地址列表的偏移量)。对于调试器可能定位到的每一个地址,它都会指定当前栈帧到变量间的偏移量,而这个偏移就是通过寄存器来计算的。对于 x86 平台而言,`bpreg4` 指向 `esp`,而 `bpreg5` 指向 `ebp`。
|
||||
|
||||
让我们再看看 do_stuff 函数的头几条指令。
|
||||
让我们再看看 `do_stuff` 函数的头几条指令。
|
||||
|
||||
```
|
||||
08048604 <do_stuff>:
|
||||
@ -216,15 +214,15 @@ Contents of the .debug_loc section:
|
||||
8048610: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
|
||||
```
|
||||
|
||||
只有当第二条指令执行后,ebp 寄存器才真正存储了有用的值。当然,前两条指令的基址是由上面所列出来的地址信息表计算出来的。一但 ebp 确定了,计算偏移量就十分方便了,因为尽管 esp 在操作堆栈的时候需要移动,但 ebp 作为栈底并不需要移动。
|
||||
只有当第二条指令执行后,`ebp` 寄存器才真正存储了有用的值。当然,前两条指令的基址是由上面所列出来的地址信息表计算出来的。一但 `ebp` 确定了,计算偏移量就十分方便了,因为尽管 `esp` 在操作堆栈的时候需要移动,但 `ebp` 作为栈底并不需要移动。
|
||||
|
||||
究竟我们应该去哪里找 my_local 的值呢?在 0x8048610 这块地址后, my_local 的值经过在 eax 中的计算后被存在了内存中,从这里开始我们才需要关注 my_local 的值。调试器会利用 DW_OP_breg5: 8 这个基址来查找。我们回想下,my_local 的 DW_AT_location 属性值为 DW_OP_fbreg: -20。所以应当从基址中 -20 ,同时由于 ebp 寄存器需要 + 8,所以最终结果为 - 12。现在再次查看反汇编代码,来看看数据从 eax 中被移动到哪里了。当然,这里 my_local 应当被存储在了 ebp - 12 的地址中。
|
||||
究竟我们应该去哪里找 `my_local` 的值呢?在 `0x8048610` 这块地址后, `my_local` 的值经过在 `eax` 中的计算后被存在了内存中,从这里开始我们才需要关注 `my_local` 的值。调试器会利用 `DW_OP_breg5: 8` 这个栈帧来查找。我们回想下,`my_local` 的 `DW_AT_location` 属性值为 `DW_OP_fbreg: -20`。所以应当从基址中 `-20` ,同时由于 `ebp` 寄存器需要 `+8`,所以最终结果为 `ebp - 12`。现在再次查看反汇编代码,来看看数据从 `eax` 中被移动到哪里了。当然,这里 `my_local` 应当被存储在了 `ebp - 12` 的地址中。
|
||||
|
||||
### 查看行号
|
||||
|
||||
当我们谈论调试信息的时候,我们利用了些技巧。当调试C语言源代码并在某个函数出放置断点的时候,我们并不关注第一条“机器码”指令(函数的调用准备工作已经完成而局部变量还没有初始化。)。我们真正关注的是函数的第一行“C代码”。
|
||||
当我们谈到在调试信息寻找函数的时候,我们利用了些技巧。当调试 C 语言源代码并在某个函数出放置断点的时候,我们并不关注第一条“机器码”指令(函数的调用准备工作已经完成而局部变量还没有初始化)。我们真正关注的是函数的第一行“C 代码”。
|
||||
|
||||
这就是 `DWARF` 完全覆盖映射C源代码与可执行文件中机器码地址的原因。下面是 .debug_line 段中所包含的内容,我们将其转换为可读的格式展示如下。
|
||||
这就是 `DWARF` 完全覆盖映射 C 源代码中的行与可执行文件中机器码地址的原因。下面是 `.debug_line` 节中所包含的内容,我们将其转换为可读的格式展示如下。
|
||||
|
||||
```
|
||||
$ objdump --dwarf=decodedline tracedprog2
|
||||
@ -247,27 +245,27 @@ tracedprog2.c 17 0x8048653
|
||||
tracedprog2.c 18 0x8048658
|
||||
```
|
||||
|
||||
很容易就可以看出其中C源代码与反汇编代码之间的对应关系。第5行指向 do_stuff 函数的入口,0x8040604。第6行,指向 0x804860a ,正是调试器在调试 do_stuff 函数时需要停下来的地方。这里已经完成了函数调用的准备工作。上面的这些信息形成了行号与地址间的双向映射关系。
|
||||
很容易就可以看出其中 C 源代码与反汇编代码之间的对应关系。第 5 行指向 `do_stuff` 函数的入口,`0x8040604`。第 6 行,指向 `0x804860a` ,正是调试器在调试 `do_stuff` 函数时需要停下来的地方。这里已经完成了函数调用的准备工作。上面的这些信息形成了行号与地址间的双向映射关系。
|
||||
|
||||
* 当在某一行设置断点的时候,调试器会利用这些信息去查找相应的地址来做断点工作(还记得上篇文章中的 int 3 指令吗?)
|
||||
* 当指令造成代码段错误时,调试器会利用这些信息来查看源代码中发生的状况。
|
||||
* 当在某一行设置断点的时候,调试器会利用这些信息去查找相应的地址来做断点工作(还记得上篇文章中的 `int 3` 指令吗?)
|
||||
* 当指令造成段错误时,调试器会利用这些信息来查看源代码中发生问题的行。
|
||||
|
||||
### libdwarf - 用 DWARF 编程
|
||||
|
||||
尽管使用命令行工具来获得 `DWARF` 很有用,但这仍然不够易用。作为程序员,我们应当知道当我们需要这些调试信息时应当怎么编程来获取这些信息。
|
||||
尽管使用命令行工具来获得 `DWARF` 很有用,但这仍然不够易用。作为程序员,我们希望知道当我们需要这些调试信息时应当怎么编程来获取这些信息。
|
||||
|
||||
自然我们想到的第一种方法就是阅读 `DWARF` 规范并按规范操作阅读使用。有句话说的好,分析 HTML 应当使用库函数,永远不要手工分析。对于 `DWARF` 来说这是如此。`DWARF` 比 HTML 要复杂得多。上面所展示出来的只是冰山一角。更糟糕的是,在实际的目标文件中,大部分信息是以压缩格式存储的,分析起来更加复杂(信息中的某些部分,例如位置信息与行号信息,在某些虚拟机下是以指令的方式编码的。)。
|
||||
自然我们想到的第一种方法就是阅读 `DWARF` 规范并按规范操作阅读使用。有句话说的好,分析 HTML 应当使用库函数,永远不要手工分析。对于 `DWARF` 来说正是如此。`DWARF` 比 HTML 要复杂得多。上面所展示出来的只是冰山一角。更糟糕的是,在实际的目标文件中,大部分信息是以非常紧凑的压缩格式存储的,分析起来更加复杂(信息中的某些部分,例如位置信息与行号信息,在某些虚拟机下是以指令的方式编码的)。
|
||||
|
||||
所以我们要使用库函数来处理 `DWARF`。下面是两种我熟悉的主流库(还有些不完整的库这里没有写)
|
||||
所以我们要使用库来处理 `DWARF`。下面是两种我熟悉的主要的库(还有些不完整的库这里没有写)
|
||||
|
||||
1. `BFD` (libbfd),包含了 `objdump` (对,就是这篇文章中我们一直在用的这货),`ld`(`GNU` 连接器)与 `as`(`GNU` 编译器)。`BFD` 主要用于[GNU binutils][11]。
|
||||
1. `BFD` (libbfd),包含了 `objdump` (对,就是这篇文章中我们一直在用的这货),`ld`(`GNU` 连接器)与 `as`(`GNU` 编译器)。`BFD` 主要用于 [GNU binutils][11]。
|
||||
2. `libdwarf` ,同它的哥哥 `libelf` 一同用于 `Solaris` 与 `FreeBSD` 中的调试信息分析。
|
||||
|
||||
相比较而言我更倾向于使用 `libdwarf`,因为我对它了解的更多,并且 `libdwarf` 的开源协议更开放。
|
||||
相比较而言我更倾向于使用 `libdwarf`,因为我对它了解的更多,并且 `libdwarf` 的开源协议更开放(`LGPL` 对比 `GPL`)。
|
||||
|
||||
因为 `libdwarf` 本身相当复杂,操作起来需要相当多的代码,所以我在这不会展示所有代码。你可以在 [这里][24] 下载代码并运行试试。运行这些代码需要提前安装 `libelfand` 与 `libdwarf` ,同时在使用连接器的时候要使用参数 `-lelf` 与 `-ldwarf`。
|
||||
|
||||
这个示例程序可以接受可执行文件并打印其中的函数名称与函数入口地址。下面是我们整篇文章中使用的C程序经过示例程序处理后的输出。
|
||||
这个示例程序可以接受可执行文件并打印其中的函数名称与函数入口地址。下面是我们整篇文章中使用的 C 程序经过示例程序处理后的输出。
|
||||
|
||||
```
|
||||
$ dwarf_get_func_addr tracedprog2
|
||||
@ -285,17 +283,17 @@ high pc : 0x0804865a
|
||||
|
||||
原理上讲,调试信息是个很简单的概念。尽管实现细节可能比较复杂,但经过了上面的学习我想你应该了解了调试器是如何从可执行文件中获取它需要的源代码信息的了。对于程序员而言,程序只是代码段与数据结构;对可执行文件而言,程序只是一系列存储在内存或寄存器中的指令或数据。但利用调试信息,调试器就可以将这两者连接起来,从而完成调试工作。
|
||||
|
||||
此文与这系列的前两篇,一同介绍了调试器的内部工作过程。利用这里所讲到的知识,再敲些代码,应该可以完成一个 `Linux` 中最简单基础但也有一定功能的调试器。
|
||||
此文与这系列的前两篇,一同介绍了调试器的内部工作过程。利用这里所讲到的知识,再敲些代码,应该可以完成一个 Linux 中最简单、基础但也有一定功能的调试器。
|
||||
|
||||
下一步我并不确定要做什么,这个系列文章可能就此结束,也有可能我要讲些堆栈调用的事情,又或者讲 `Windows` 下的调试。你们有什么好的点子或者相关材料,可以直接评论或者发邮件给我。
|
||||
下一步我并不确定要做什么,这个系列文章可能就此结束,也有可能我要讲些堆栈调用的事情,又或者讲 Windows 下的调试。你们有什么好的点子或者相关材料,可以直接评论或者发邮件给我。
|
||||
|
||||
### 参考
|
||||
|
||||
* objdump 参考手册
|
||||
* [ELF][12] 与 [DWARF][13]的维基百科
|
||||
* [Dwarf Debugging Standard home page][14],这里有很棒的 DWARF 教程与 DWARF 标准,作者是 Michael Eager。第二版基于 GCC 也许更能吸引你。
|
||||
* [libdwarf home page][15],这里可以下载到 libwarf 的完整库与参考手册
|
||||
* [BFD documentation][16]
|
||||
* [ELF][12] 与 [DWARF][13] 的维基百科
|
||||
* [Dwarf Debugging Standard 主页][14],这里有很棒的 DWARF 教程与 DWARF 标准,作者是 Michael Eager。第二版基于 GCC 也许更能吸引你。
|
||||
* [libdwarf 主页][15],这里可以下载到 libwarf 的完整库与参考手册
|
||||
* [BFD 文档][16]
|
||||
|
||||
* * *
|
||||
|
||||
@ -305,7 +303,7 @@ via: http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging
|
||||
|
||||
作者:[Eli Bendersky][a]
|
||||
译者:[YYforymj](https://github.com/YYforymj)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -335,5 +333,5 @@ via: http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging
|
||||
[23]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id12
|
||||
[24]:https://github.com/eliben/code-for-blog/blob/master/2011/dwarf_get_func_addr.c
|
||||
[25]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information
|
||||
[26]:http://eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1/
|
||||
[27]:http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints/
|
||||
[26]:https://linux.cn/article-8552-1.html
|
||||
[27]:https://linux.cn/article-8418-1.html
|
123
published/201706/20160808 What is open source.md
Normal file
123
published/201706/20160808 What is open source.md
Normal file
@ -0,0 +1,123 @@
|
||||
什么是开源?
|
||||
===========================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/resources/OSDC_Resource_Main_Page.png?itok=HP4NenAL)
|
||||
|
||||
“<ruby>开源<rt>open source</rt></ruby>”这个词,指的是事物规划为可以公开访问的,因此人们可以修改并分享。
|
||||
|
||||
这个词最初是起源于软件开发中,指的是一种开发软件的特殊形式。但到了今天,“开源”已经泛指一组概念——就是我们称之为的“[开源的方式][1]”。这些概念包括开源项目、产品,或是自发倡导并欢迎开放变化、协作参与、快速原型、公开透明、精英体制以及面向社区开发的原则。
|
||||
|
||||
### 什么是开源软件?
|
||||
|
||||
开源软件的源代码任何人都可以审查、修改和增强。
|
||||
|
||||
“<ruby>源代码<rt>source code</rt></ruby>”是软件中大部分计算机用户都没见过的部分,程序员可以修改代码来改变一个软件(“程序”或“应用”)工作的方式。程序员如果可以接触到计算机程序源代码,就可以通过添加功能或修复问题来改进这个软件。
|
||||
|
||||
### 开源软件和其它类型的软件有什么不同?
|
||||
|
||||
有些软件只有创建它的人、团队、组织才能修改,并且控制维护工作。人们称这种软件是“<ruby>专有<rt>proprietary</rt></ruby>”或“<ruby>闭源<rt>closed source</rt></ruby>”软件。
|
||||
|
||||
专有软件只有原作者可以合法地复制、审查,以及修改这个软件。为了使用专有软件,计算机用户必须同意(通常是在软件第一次运行的时候签署一份显示的许可)他们不会对软件做软件作者没有表态允许的事情。微软 Office 和 Adobe Photoshop 就是专有软件的例子。
|
||||
|
||||
开源软件不一样。它的作者[让源代码对其他人提供][2],需要的人都可以查看、复制、学习、修改或分享代码。[LibreOffice][3] 和 [GIMP][4] 是开源软件的例子。
|
||||
|
||||
就像专有软件那样,用户在使用开源软件时必须接受一份[许可证][5]的条款——但开源许可的法律条款和专有软件的许可截然不同。
|
||||
|
||||
开源许可证影响人们[使用、学习、修改以及分发][6]的方式。总的来说,开源许可证赋予计算机用户[按他们想要的目的来使用开源软件的许可][7]。一些开源许可证(人们称之为<ruby>左版<rt>copyleft</rt></ruby>”)规定任何发布了修改过的开源软件的人,同时还要一同发布它的源代码。此外,[另一些开源许可][8]规定任何修改和分享一个程序给其他人的人,还要分享这个程序的源代码,而且不能收取许可费用。
|
||||
|
||||
开源软件许可证有意地提升了协作和分享,因为它们允许其他人对代码作出修改并将改动包含到他们自己的项目中。开源许可证鼓励开发者随时访问、查看、修改开源软件,前提是开发者在分享成果的时候允许其他人也能够做相同的事情。
|
||||
|
||||
### 开源软件只是对开发者很重要?
|
||||
|
||||
不。开源技术和开源思想对开发者和非开发者都有益。
|
||||
|
||||
因为早期的创造者基于开源技术构建了互联网本身的大部分——比如 [Linux 操作系统][9]和 [Apache Web 服务器][10]应用——任何今天使用互联网的人都受益于开源软件。
|
||||
|
||||
每当计算机用户浏览网页、检查邮件、和朋友聊天、在线收听流媒体音乐、玩多人游戏的时候,他们的电脑、手机或游戏主机都会连接到一个全球性的计算机网络,使用开源软件来路由并将他们的数据传输到面前的“本地”设备上。完成这些重要工作的计算机通常位于很远的地方,用户不会实际看到或物理接触到它们——所以有些人称之为“远程计算机”。
|
||||
|
||||
越来越多的人开始依赖于远程计算机,在可以在本地完成的任务在线完成。举个例子,人们可能会使用在线文字处理、电子邮件管理、图片编辑工具,而在本地的个人电脑并没有安装运行相应的软件。人们轻松地使用浏览器或手机应用访问这些程序。当他们这么做的时候,他们参与到了“远程计算”中。
|
||||
|
||||
一些人将远程计算称为“云计算”,因为它涉及的活动(像是存储文件、分享照片、观看视频)不仅包含本地设备,还有一个远程计算机全球网络,像是围绕在周围的大气。
|
||||
|
||||
云计算是日常生活一个越来越重要的概念,离不开连接互联网的设备。一些云计算应用,比如 Google 应用,是专有的。其它的,像 OwnCloud 和 NextCould 是开源的。
|
||||
|
||||
云计算应用运行在一些额外的软件“之上”,这些软件帮助它们流畅高效地操作,所以人们经常说那个软件运行在云计算应用“之下”,为那些应用扮演一个“平台”。云计算平台可以是开源或闭源的。OpenStack 是一个开源云计算平台的例子。
|
||||
|
||||
### 为什么人们更倾向于使用开源软件?
|
||||
|
||||
人们相对于专有软件更倾向于开源软件有很多原因,包括:
|
||||
|
||||
**可控**。很多人青睐开源软件因为相对其它类型软件他们可以[拥有更多的可控][11]。他们可以检查代码来保证它没有做任何不希望它做的事情,并且可以改变不喜欢的部分。不是开发者的用户也可以从开源软件获益,因为他们可以以任何目的使用这个软件——而不仅仅是某些人认为他们应该有的目的。
|
||||
|
||||
**训练**。其他人喜欢开源软件是因为它可以帮助他们[成为更好的开发者][12]。因为开源代码可以公开访问,学生可以在学习创建更好的软件时轻松地从中学习。学生还可以在提升技能的时候分享他们的成果给别人,获得评价和批评。当人们发现程序源代码中的错误的时候,可以将这个错误分享给其他人,帮助他们避免犯同样的错误。
|
||||
|
||||
**安全**。一些人倾向开源软件是因为他们认为它比专有软件更[安全][13]和稳定。因为任何人都可以查看和修改开源软件,就会有人可能会注意到并修正原作者遗漏的错误或疏忽。并且因为这么多的开发者可以在同一开源软件上工作,而不用事先联系获取原作者的授权,相比专有软件,他们可以更[快速][14]地修复、更新和升级开源软件。
|
||||
|
||||
**稳定**。许多用户在重要、长期的项目中相较专有软件更加青睐开源软件。因为开发者[公开分发][15]开源软件的源代码,如果最初的开发者停止开发了,关键任务依赖该软件的用户可以确保他们的工具不会消失,或是陷入无法修复的状态。另外,开源软件趋向于同时包含和按照开放标准进行操作。
|
||||
|
||||
### “开源”不是只是意味着某样东西是免费的吗?
|
||||
|
||||
不。这是个“开源”实践中的[常见误解][16],“开源”概念的含义[不只是指经济方面的][17]。
|
||||
|
||||
开源软件开发者可以为他们创建或贡献的开源软件收取费用。但在一些情况下,由于开源许可证可能会要求他们在将软件卖给他人的时候发布源代码,一些开发者发现向用户收取软件服务和支持(而不是软件本身)的费用会更加合算。通过这种方式,他们的软件仍然保持免费,而他们[从帮助他人][18]安装、使用、解决问题中赚取费用。
|
||||
|
||||
尽管一些开源软件可能是免费的,但开源软件的编程和解决问题的技能可能[十分有价值][19]。许多雇主特别寻求[雇佣在开源软件方面有工作经验的开发者][20]。
|
||||
|
||||
### 什么是“在软件之外”的开源?
|
||||
|
||||
在 Opensource.com,我们想说我们对于开源价值和原则应用到软件之外领域的方式很有兴趣。我们更愿意不仅将开源视为一种计算机软件开发和许可的方式,也把它视作一种态度。
|
||||
|
||||
实现“[开源方式][21]”的生活的各个方面,意味着表达一种分享的意愿,通过透明的方式和他人协作(这样其他人也可以关注和加入),拥抱失败,将它作为一种改进的手段,以及期待(甚至鼓励)所有人都可以这么做。
|
||||
|
||||
这也意味着在让世界变得更好的过程中扮演一个积极的角色,这只有在[每个人都可以接触][22]到对世界进行规划的途径时才有可能。
|
||||
|
||||
这个世界充满了“源代码”——[蓝图][23]、[食谱][24]、[规则][25]——它们引导和塑造我们思考和行动的方式。我们相信这些深层代码(无论是什么形式)应该是开放、可接触、分享的——这样人们可以参与其中并让它变得更好。
|
||||
|
||||
在这里,我们诉说开源价值对生活所有领域的影响的故事——[科学][26]、[教育][27]、[政府][28]、[工业][29]、健康、法律,以及[组织动态][30]。我们是一个社区,告诉他人开源的方式如何成为最好的方式,因为对开源的爱和其它一样:当它被分享的时候它会变得更好。
|
||||
|
||||
在哪里能够获得关于开源的更多信息?
|
||||
|
||||
我们编辑了一些资源来帮助你学到更多关于开源的内容。我们推荐你从阅读我们的[开源问答、指南、教程][31]开始。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/resources/what-open-source
|
||||
|
||||
作者:[opensource.com][a]
|
||||
译者:[alim0x](https://github.com/alim0x)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: opensource.com
|
||||
[1]:https://opensource.com/open-source-way
|
||||
[2]:https://opensource.com/business/13/5/open-source-your-code
|
||||
[3]:https://www.libreoffice.org/
|
||||
[4]:http://www.gimp.org/
|
||||
[5]:https://opensource.com/law/13/1/which-open-source-software-license-should-i-use
|
||||
[6]:https://opensource.com/law/10/10/license-compliance-not-problem-open-source-users
|
||||
[7]:https://opensource.org/docs/osd
|
||||
[8]:https://opensource.com/law/13/5/does-your-code-need-license
|
||||
[9]:https://opensource.com/resources/what-is-linux
|
||||
[10]:http://httpd.apache.org/
|
||||
[11]:https://opensource.com/life/13/5/tumblr-open-publishing
|
||||
[12]:https://opensource.com/life/13/6/learning-program-open-source-way
|
||||
[13]:https://opensource.com/government/10/9/scap-computer-security-rest-us
|
||||
[14]:https://opensource.com/government/13/2/bug-fix-day
|
||||
[15]:https://opensource.com/life/12/9/should-we-develop-open-source-openly
|
||||
[16]:https://opensource.com/education/12/7/clearing-open-source-misconceptions
|
||||
[17]:https://opensource.com/open-organization/16/5/appreciating-full-power-open
|
||||
[18]:https://opensource.com/business/14/7/making-your-product-free-and-open-source-crazy-talk
|
||||
[19]:https://opensource.com/business/16/2/add-open-source-to-your-resume
|
||||
[20]:https://opensource.com/business/16/5/2016-open-source-jobs-report
|
||||
[21]:https://opensource.com/open-source-way
|
||||
[22]:https://opensource.com/resources/what-open-access
|
||||
[23]:https://opensource.com/life/11/6/architecture-open-source-applications-learn-those-you
|
||||
[24]:https://opensource.com/life/12/6/open-source-like-sharing-recipe
|
||||
[25]:https://opensource.com/life/12/4/day-my-mind-became-open-sourced
|
||||
[26]:https://opensource.com/resources/open-science
|
||||
[27]:https://opensource.com/resources/what-open-education
|
||||
[28]:https://opensource.com/resources/open-government
|
||||
[29]:https://opensource.com/resources/what-open-hardware
|
||||
[30]:https://opensource.com/resources/what-open-organization
|
||||
[31]:https://opensource.com/resources
|
@ -0,0 +1,122 @@
|
||||
Apache Spark 大规模应用:一个 60TB+ 规模的产品使用案例
|
||||
===========
|
||||
|
||||
Facebook 经常使用数据驱动的分析方法来做决策。在过去的几年,用户和产品的增长已经需要我们的分析工程师一次查询就要操作数十 TB 大小的数据集。我们的一些批量分析执行在古老的 [Hive][1] 平台( Apache Hive 由 Facebook 贡献于 2009 年)和 [Corona][2] 上——这是我们定制的 MapReduce 实现。Facebook 还不断增加其对 Presto 的用量,用于对几个包括 Hive 在内的内部数据存储的 ANSI-SQL 查询。我们也支持其他分析类型,比如图数据库处理(graph processing)和机器学习([Apache Giraph][3])和流(例如:[Puma][4]、[Swift][5] 和 [Stylus][6])。
|
||||
|
||||
同时 Facebook 的各种产品涵盖了广泛的分析领域,我们与开源社区不断保持沟通,以便共享我们的经验并从其他人那里学习。[Apache Spark][7] 于 2009 年在加州大学伯克利分校的 AMPLab 由 Matei Zaharia 发起,后来在2013 年贡献给 Apache。它是目前增长最快的数据处理平台之一,由于它能支持流、批量、命令式(RDD)、声明式(SQL)、图数据库和机器学习等用例,而且所有这些都内置在相同的 API 和底层计算引擎中。Spark 可以有效地利用更大量级的内存,优化整个流水线(pipeline)中的代码,并跨任务重用 JVM 以获得更好的性能。最近我们感觉 Spark 已经成熟,我们可以在一些批量处理用例方面把它与 Hive 相比较。在这篇文章其余的部分,我们讲述了在扩展 Spark 来替代我们一个 Hive 工作任务时的所得到经验和学习到的教训。
|
||||
|
||||
### 用例:实体排名的特征准备
|
||||
|
||||
Facebook 会以多种方式做实时的实体(entity)排名。对于一些在线服务平台,原始特征值是由 Hive 线下生成的,然后将数据加载到实时关联查询系统。我们在几年前建立的基于 Hive 的老式基础设施属于计算资源密集型,且很难维护,因为其流水线被划分成数百个较小的 Hive 任务。为了可以使用更加新的特征数据和提升可管理性,我们拿一个现有的流水线试着将其迁移至 Spark。
|
||||
|
||||
### 以前的 Hive 实现
|
||||
|
||||
基于 Hive 的流水线由三个逻辑阶段(stage)组成,每个阶段对应由 entity_id 划分的数百个较小的 Hive 作业,因为在每个阶段运行大型 Hive 作业(job)不太可靠,并受到每个作业的最大任务(task)数量的限制。
|
||||
|
||||
![](https://scontent-ort2-1.xx.fbcdn.net/v/t39.2365-6/14050196_257613611304247_245043082_n.jpg?oh=4dceed87af2b5ece78651a11ac2a0d7a&oe=59E87E32)
|
||||
|
||||
这三个逻辑阶段可以总结如下:
|
||||
|
||||
1. 过滤出非产品的特征和噪点。
|
||||
2. 在每个(entity\_id, target\_id)对上进行聚合。
|
||||
3. 将表格分割成 N 个分片,并通过自定义二进制文件管理每个分片,以生成用于在线查询的自定义索引文件。
|
||||
|
||||
基于 Hive 的流水线建立该索引大概要三天完成。它也难于管理,因为该流水线包含上百个分片的作业,使监控也变得困难。同时也没有好的方法来估算流水线进度或计算剩余时间。考虑到 Hive 流水线的上述限制,我们决定建立一个更快、更易于管理的 Spark 流水线。
|
||||
|
||||
### Spark 实现
|
||||
|
||||
全量的调试会很慢,有挑战,而且是资源密集型的。我们从转换基于 Hive 流水线的最资源密集型的第二阶段开始。我们以一个 50GB 的压缩输入例子开始,然后逐渐扩展到 300GB、1TB,然后到 20TB。在每次规模增长时,我们都解决了性能和稳定性问题,但是实验到 20TB 时,我们发现了最大的改善机会。
|
||||
|
||||
运行 20TB 的输入时,我们发现,由于大量的任务导致我们生成了太多输出文件(每个大小在 100MB 左右)。在 10 小时的作业运行时中,有三分之一是用在将文件从阶段目录移动到 HDFS 中的最终目录。起初,我们考虑两个方案:要么改善 HDFS 中的批量重命名来支持我们的用例,或者配置 Spark 生成更少的输出文件(这很难,由于在这一步有大量的任务 — 70000 个)。我们退一步来看这个问题,考虑第三种方案。由于我们在流水线的第二步中生成的 tmp_table2 表是临时的,仅用于存储流水线的中间输出,所以对于 TB 级数据的单一读取作业任务,我们基本上是在压缩、序列化和复制三个副本。相反,我们更进一步:移除两个临时表并整合 Hive 过程的所有三个部分到一个单独的 Spark 作业,读取 60TB 的压缩数据然后对 90TB 的数据执行重排(shuffle)和排序(sort)。最终的 Spark 作业如下:
|
||||
|
||||
![](https://scontent-ort2-1.xx.fbcdn.net/v/t39.2365-6/14146896_1073876729364007_1912864323_n.jpg?oh=77200f03e6713b6adc91033230dcd588&oe=59E17E46)
|
||||
|
||||
### 对于我们的作业如何规划 Spark?
|
||||
|
||||
当然,为如此大的流水线运行一个单独的 Spark 任务,第一次尝试没有成功,甚至是第十次尝试也没有。据我们所知,从重排(shuffle)的数据大小来说,这是现实世界最大的 Spark 作业([Databrick 的 PB 级排序](https://databricks.com/blog/2014/10/10/spark-petabyte-sort.html)是以合成数据来说)。我们对核心 Spark 基础架构和我们的应用程序进行了许多改进和优化使这个作业得以运行。这种努力的优势在于,许多这些改进适用于 Spark 的其他大型作业任务,我们将所有的工作回馈给开源 Apache Spark 项目 - 有关详细信息请参阅 JIRA。下面,我们将重点讲述将实体排名流水线之一部署到生产环境所做的重大改进。
|
||||
|
||||
### 可靠性修复
|
||||
|
||||
#### 处理频繁的节点重启
|
||||
|
||||
为了可靠地执行长时间运行作业,我们希望系统能够容错并可以从故障中恢复(主要是由于平时的维护或软件错误导致的机器重启所引发的)。虽然 Spark 设计为可以容忍机器重启,但我们发现它在足够强健到可以处理常见故障之前还有各种错误/问题需要解决。
|
||||
|
||||
- **使 PipedRDD 稳健的获取(fetch)失败**(SPARK-13793):PipedRDD 以前的实现不够强大,无法处理由于节点重启而导致的获取失败,并且只要出现获取失败,该作业就会失败。我们在 PipedRDD 中进行了更改,优雅的处理获取失败,使该作业可以从这种类型的获取失败中恢复。
|
||||
- **可配置的最大获取失败次数**(SPARK-13369):对于这种长时间运行的作业,由于机器重启而引起的获取失败概率显着增加。在 Spark 中每个阶段的最大允许的获取失败次数是硬编码的,因此,当达到最大数量时该作业将失败。我们做了一个改变,使它是可配置的,并且在这个用例中将其从 4 增长到 20,从而使作业更稳健。
|
||||
- **减少集群重启混乱**:长时间运行作业应该可以在集群重启后存留,所以我们不用等着处理完成。Spark 的可重启的重排(shuffle)服务功能可以使我们在节点重启后保留重排(shuffle)文件。最重要的是,我们在 Spark 驱动程序中实现了一项功能,可以暂停执行任务调度,所以不会由于集群重启而导致的过多的任务失败,从而导致作业失败。
|
||||
|
||||
#### 其他的可靠性修复
|
||||
|
||||
- **响应迟钝的驱动程序**(SPARK-13279):在添加任务时,由于 O(N ^ 2) 复杂度的操作,Spark 驱动程序被卡住,导致该作业最终被卡住和死亡。 我们通过删除不必要的 O(N ^ 2) 操作来修复问题。
|
||||
- **过多的驱动推测(speculation)**:我们发现,Spark 驱动程序在管理大量任务时花费了大量的时间推测。 在短期内,我们禁止这个作业的推测。在长期,我们正在努力改变 Spark 驱动程序,以减少推测时间。
|
||||
- **由于大型缓冲区的整数溢出导致的 TimSort 问题**(SPARK-13850):我们发现 Spark 的不安全内存操作有一个漏洞,导致 TimSort 中的内存损坏。 感谢 Databricks 的人解决了这个问题,这使我们能够在大内存缓冲区中运行。
|
||||
- **调整重排(shuffle)服务来处理大量连接**:在重排阶段,我们看到许多执行程序在尝试连接重排服务时超时。 增加 Netty 服务器的线程(spark.shuffle.io.serverThreads)和积压(spark.shuffle.io.backLog)的数量解决了这个问题。
|
||||
- **修复 Spark 执行程序 OOM**(SPARK-13958)(deal maker):首先在每个主机上打包超过四个聚合(reduce)任务是很困难的。Spark 执行程序会内存溢出,因为排序程序(sorter)中存在导致无限增长的指针数组的漏洞。当不再有可用的内存用于指针数组增长时,我们通过强制将数据溢出到磁盘来修复问题。因此,现在我们可以每主机运行 24 个任务,而不会内存溢出。
|
||||
|
||||
### 性能改进
|
||||
|
||||
在实施上述可靠性改进后,我们能够可靠地运行 Spark 作业了。基于这一点,我们将精力转向与性能相关的项目,以充分发挥 Spark 的作用。我们使用 Spark 的指标和几个分析器来查找一些性能瓶颈。
|
||||
|
||||
#### 我们用来查找性能瓶颈的工具
|
||||
|
||||
- **Spark UI 指标**:Spark UI 可以很好地了解在特定阶段所花费的时间。每个任务的执行时间被分为子阶段,以便更容易地找到作业中的瓶颈。
|
||||
- **Jstack**:Spark UI 还在执行程序进程上提供了一个按需分配的 jstack 函数,可用于中查找热点代码。
|
||||
- **Spark 的 Linux Perf / 火焰图(Flame Graph)支持**:尽管上述两个工具非常方便,但它们并不提供同时在数百台机器上运行的作业的 CPU 分析的聚合视图。在每个作业的基础上,我们添加了支持 Perf 分析(通过 libperfagent 的 Java 符号),并可以自定义采样的持续时间/频率。使用我们的内部指标收集框架,将分析样本聚合并显示为整个执行程序的火焰图。
|
||||
|
||||
#### 性能优化
|
||||
|
||||
- **修复排序程序(sorter)中的内存泄漏**(SPARK-14363)(30% 速度提升):我们发现了一个问题,当任务释放所有内存页时指针数组却未被释放。 因此,大量的内存未被使用,并导致频繁的溢出和执行程序 OOM。 我们现在进行了改变,正确地释放内存,并使大的分类运行更有效。 我们注意到,这一变化后 CPU 改善了 30%。
|
||||
- **Snappy 优化**(SPARK-14277)(10% 速度提升):有个 JNI 方法(Snappy.ArrayCopy)在每一行被读取/写入时都会被调用。 我们发现了这个问题,Snappy 的行为被改为使用非 JNI 的 System.ArrayCopy 代替。 这一改变节约了大约 10% 的 CPU。
|
||||
- **减少重排的写入延迟**(SPARK-5581)(高达 50% 的速度提升):在映射(map)方面,当将重排数据写入磁盘时,映射任务为每个分区打开并关闭相同的文件。 我们做了一个修复,以避免不必要的打开/关闭,对于大量写入重排分区的作业来说,我们观察到高达 50% 的 CPU 提升。
|
||||
- **解决由于获取失败导致的重复任务运行问题**(SPARK-14649):当获取失败发生时,Spark 驱动程序会重新提交已运行的任务,导致性能下降。 我们通过避免重新运行运行的任务来解决这个问题,我们看到当获取失败发生时该作业会更加稳定。
|
||||
- **可配置 PipedRDD 的缓冲区大小**(SPARK-14542)(10% 速度提升):在使用 PipedRDD 时,我们发现将数据从分类程序传输到管道进程的默认缓冲区的大小太小,我们的作业要花费超过 10% 的时间复制数据。我们使缓冲区大小可配置,以避免这个瓶颈。
|
||||
- **缓存索引文件以加速重排获取**(SPARK-15074):我们观察到重排服务经常成为瓶颈,减少程序(reducer)花费 10% 至 15% 的时间等待获取映射(map)数据。通过深入了解问题,我们发现,重排服务为每个重排获取打开/关闭重排索引文件。我们进行了更改以缓存索引信息,以便我们可以避免文件打开/关闭,并重新使用该索引信息以便后续获取。这个变化将总的重排时间减少了 50%。
|
||||
- **降低重排字节写入指标的更新频率**(SPARK-15569)(高达 20% 的速度提升):使用 Spark 的 Linux Perf 集成,我们发现大约 20% 的 CPU 时间正在花费探测和更新写入的重排字节写入指标上。
|
||||
- **可配置排序程序(sorter)的初始缓冲区大小**(SPARK-15958)(高达 5% 的速度提升):排序程序(sorter)的默认初始缓冲区大小太小(4 KB),我们发现它对于大型工作负载而言非常小 - 所以我们在缓冲区耗尽和内容复制上浪费了大量的时间。我们做了一个更改,使缓冲区大小可配置,并且缓冲区大小为 64 MB,我们可以避免大量的数据复制,使作业的速度提高约 5%。
|
||||
- **配置任务数量**:由于我们的输入大小为 60T,每个 HDFS 块大小为 256M,因此我们为该作业产生了超过 250,000 个任务。尽管我们能够以如此多的任务来运行 Spark 作业,但是我们发现,当任务数量过高时,性能会下降。我们引入了一个配置参数,使映射(map)输入大小可配置,因此我们可以通过将输入分割大小设置为 2 GB 来将该数量减少 8 倍。
|
||||
|
||||
在所有这些可靠性和性能改进之后,我们很高兴地报告,我们为我们的实体排名系统之一构建和部署了一个更快、更易于管理的流水线,并且我们提供了在 Spark 中运行其他类似作业的能力。
|
||||
|
||||
### Spark 流水线与 Hive 流水线性能对比
|
||||
|
||||
我们使用以下性能指标来比较 Spark 流水线与 Hive 流水线。请注意,这些数字并不是在查询或作业级别的直接比较 Spark 与 Hive ,而是比较使用灵活的计算引擎(例如 Spark)构建优化的流水线,而不是比较仅在查询/作业级别(如 Hive)操作的计算引擎。
|
||||
|
||||
CPU 时间:这是从系统角度看 CPU 使用。例如,你在一个 32 核机器上使用 50% 的 CPU 10 秒运行一个单进程任务,然后你的 CPU 时间应该是 32 * 0.5 * 10 = 160 CPU 秒。
|
||||
|
||||
![](https://scontent-ort2-1.xx.fbcdn.net/v/t39.2365-6/14146892_595234533986285_2004398348_n.jpg?oh=42b2bcc2b5b0d2b2f3141ee5639a62f2&oe=59DC7E21)
|
||||
|
||||
CPU 预留时间:这是从资源管理框架的角度来看 CPU 预留。例如,如果我们保留 32 位机器 10 秒钟来运行作业,则CPU 预留时间为 32 * 10 = 320 CPU 秒。CPU 时间与 CPU 预留时间的比率反映了我们如何在集群上利用预留的CPU 资源。当准确时,与 CPU 时间相比,预留时间在运行相同工作负载时可以更好地比较执行引擎。例如,如果一个进程需要 1 个 CPU 的时间才能运行,但是必须保留 100 个 CPU 秒,则该指标的效率要低于需要 10 个 CPU 秒而仅保留 10 个 CPU 秒来执行相同的工作量的进程。我们还计算内存预留时间,但不包括在这里,因为其数字类似于 CPU 预留时间,因为在同一硬件上运行实验,而在 Spark 和 Hive 的情况下,我们不会将数据缓存在内存中。Spark 有能力在内存中缓存数据,但是由于我们的集群内存限制,我们决定类似与 Hive 一样工作在核心外部。
|
||||
|
||||
![](https://scontent-ort2-1.xx.fbcdn.net/v/t39.2365-6/14129680_325754934432503_513809233_n.jpg?oh=c2c26e6ef20724eef32771c5953d386a&oe=59D61914)
|
||||
|
||||
等待时间:端到端的工作流失时间。
|
||||
|
||||
![](https://scontent-ort2-1.xx.fbcdn.net/v/t39.2365-6/14129681_178723715883876_1030939470_n.jpg?oh=9bc18e548bbd23ee675e15ac03ea8600&oe=599C4F25)
|
||||
|
||||
### 结论和未来工作
|
||||
|
||||
Facebook 的性能和可扩展的分析在产品开发中给予了协助。Apache Spark 提供了将各种分析用例统一为单一 API 和高效计算引擎的独特功能。我们挑战了 Spark,来将一个分解成数百个 Hive 作业的流水线替换成一个 Spark 作业。通过一系列的性能和可靠性改进之后,我们可以将 Spark 扩大到处理我们在生产中的实体排名数据处理用例之一。 在这个特殊用例中,我们展示了 Spark 可以可靠地重排和排序 90 TB+ 的中间数据,并在一个单一作业中运行了 25 万个任务。 与旧的基于 Hive 的流水线相比,基于 Spark 的流水线产生了显着的性能改进(4.5-6 倍 CPU,3-4 倍资源预留和大约 5 倍的延迟),并且已经投入使用了几个月。
|
||||
|
||||
虽然本文详细介绍了我们 Spark 最具挑战性的用例,越来越多的客户团队已将 Spark 工作负载部署到生产中。 性能
|
||||
、可维护性和灵活性是继续推动更多用例到 Spark 的优势。 Facebook 很高兴成为 Spark 开源社区的一部分,并将共同开发 Spark 充分发挥其潜力。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://code.facebook.com/posts/1671373793181703/apache-spark-scale-a-60-tb-production-use-case/
|
||||
|
||||
作者:[Sital Kedia][a], [王硕杰][b], [Avery Ching][c]
|
||||
译者:[wyangsun](https://github.com/wyangsun)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.facebook.com/sitalkedia
|
||||
[b]: https://www.facebook.com/shuojiew
|
||||
[c]: https://code.facebook.com/posts/1671373793181703/apache-spark-scale-a-60-tb-production-use-case/?utm_source=dbweekly&utm_medium=email#
|
||||
[1]: https://code.facebook.com/posts/370832626374903/even-faster-data-at-the-speed-of-presto-orc/
|
||||
[2]: https://www.facebook.com/notes/facebook-engineering/under-the-hood-scheduling-mapreduce-jobs-more-efficiently-with-corona/10151142560538920/
|
||||
[3]: https://code.facebook.com/posts/509727595776839/scaling-apache-giraph-to-a-trillion-edges/
|
||||
[4]: https://research.facebook.com/publications/realtime-data-processing-at-facebook/
|
||||
[5]: https://research.facebook.com/publications/realtime-data-processing-at-facebook/
|
||||
[6]: https://research.facebook.com/publications/realtime-data-processing-at-facebook/
|
||||
[7]: http://spark.apache.org/
|
211
published/201706/20161027 Network management with LXD.md
Normal file
211
published/201706/20161027 Network management with LXD.md
Normal file
@ -0,0 +1,211 @@
|
||||
在 LXD 2.3 及以上版本中管理网络
|
||||
===========
|
||||
|
||||
![LXD logo](https://linuxcontainers.org/static/img/containers.png)
|
||||
|
||||
### 介绍
|
||||
|
||||
|
||||
当 LXD 2.0 随着 Ubuntu 16.04 一起发布时,LXD 联网就简单了。要么你可以使用 `lxd init` 来配置,为你的容器自己提供一个 “lxdbr0” 网桥,要么使用一个已存在的物理接口。
|
||||
|
||||
虽然这确实有效,但是有点混乱,因为大部分的桥接配置发生在 Ubuntu 打包的 LXD 之外。那些脚本只能支持一个桥接,并且没有通过 API 暴露,这使得远程配置有点痛苦。
|
||||
|
||||
直到 LXD 2.3,LXD 终于发展了自己的网络管理 API ,并有相应的命令行工具。这篇文章试图来简述这些新的功能。
|
||||
|
||||
### 基础联网
|
||||
|
||||
在初始情况下,LXD 2.3 没有定义任何网络。`lxd init` 会为你设置一个,并且默认情况下将所有新的容器连接到它,但是让我们亲手尝试看下究竟发生了些什么。
|
||||
|
||||
要创建一个新的带有随机 IPv4 和 IP6 子网,并启用 NAT 的网络,只需要运行:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network create testbr0
|
||||
Network testbr0 created
|
||||
```
|
||||
|
||||
你可以如下查看它的配置:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network show testbr0
|
||||
name: testbr0
|
||||
config:
|
||||
ipv4.address: 10.150.19.1/24
|
||||
ipv4.nat: "true"
|
||||
ipv6.address: fd42:474b:622d:259d::1/64
|
||||
ipv6.nat: "true"
|
||||
managed: true
|
||||
type: bridge
|
||||
usedby: []
|
||||
```
|
||||
|
||||
如果你不想要那些自动配置的子网,你可以这么做:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network create testbr0 ipv6.address=none ipv4.address=10.0.3.1/24 ipv4.nat=true
|
||||
Network testbr0 created
|
||||
```
|
||||
|
||||
那就会这样:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network show testbr0
|
||||
name: testbr0
|
||||
config:
|
||||
ipv4.address: 10.0.3.1/24
|
||||
ipv4.nat: "true"
|
||||
ipv6.address: none
|
||||
managed: true
|
||||
type: bridge
|
||||
usedby: []
|
||||
```
|
||||
|
||||
如果你的容器没有使用它,那么创建的网络对你也没什么用。要将你新创建的网络连接到所有容器,你可以这么做:
|
||||
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
要将一个网络连接到一个已存在的容器中,你可以这么做:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network attach my-container default eth0
|
||||
```
|
||||
|
||||
现在,假设你已经在机器中安装了 openvswitch,并且要将这个网桥转换成 OVS 网桥,只需更改为正确的驱动:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network set testbr0 bridge.driver openvswitch
|
||||
```
|
||||
|
||||
如果你想要一次性做一系列修改。`lxc network edit` 可以让你在编辑器中交互编辑网络配置。
|
||||
|
||||
### 静态租约及端口安全
|
||||
|
||||
使用 LXD 管理 DHCP 服务器的一个好处是可以使得管理 DHCP 租约很简单。你所需要的是一个容器特定的网卡设备以及正确的属性设置。
|
||||
|
||||
```
|
||||
root@yak:~# lxc init ubuntu:16.04 c1
|
||||
Creating c1
|
||||
root@yak:~# lxc network attach testbr0 c1 eth0
|
||||
root@yak:~# lxc config device set c1 eth0 ipv4.address 10.0.3.123
|
||||
root@yak:~# lxc start c1
|
||||
root@yak:~# lxc list c1
|
||||
+------+---------+-------------------+------+------------+-----------+
|
||||
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
|
||||
+------+---------+-------------------+------+------------+-----------+
|
||||
| c1 | RUNNING | 10.0.3.123 (eth0) | | PERSISTENT | 0 |
|
||||
+------+---------+-------------------+------+------------+-----------+
|
||||
```
|
||||
|
||||
IPv6 也是相同的方法,但是换成 `ipv6.address` 属性。
|
||||
|
||||
相似地,如果你想要阻止你的容器更改它的 MAC 地址或者为其他 MAC 地址转发流量(比如嵌套),你可以用下面的命令启用端口安全:
|
||||
|
||||
```
|
||||
root@yak:~# lxc config device set c1 eth0 security.mac_filtering true
|
||||
```
|
||||
|
||||
### DNS
|
||||
|
||||
LXD 在网桥上运行 DNS 服务器。除了设置网桥的 DNS 域( `dns.domain` 网络属性)之外,还支持 3 种不同的操作模式(`dns.mode`):
|
||||
|
||||
* `managed` :每个容器都会有一条 DNS 记录,匹配它的名字以及已知的 IP 地址。容器无法通过 DHCP 改变这条记录。
|
||||
* `dynamic` :允许容器通过 DHCP 在 DNS 中自行注册。因此,在 DHCP 协商期间容器发送的任何主机名最终都出现在 DNS 中。
|
||||
* `none` : 针对那些没有任何本地 DNS 记录的递归 DNS 服务器。
|
||||
|
||||
默认的模式是 `managed`,并且典型的是最安全以及最方便的,因为它为容器提供了 DNS 记录,但是不允许它们通过 DHCP 发送虚假主机名嗅探其他的记录。
|
||||
|
||||
### 使用隧道
|
||||
|
||||
除了这些,LXD 还支持使用 GRE 或者 VXLAN 隧道连接到其他主机。
|
||||
|
||||
LXD 网络可以连接任何数量的隧道,从而轻松地创建跨多个主机的网络。这对于开发、测试和演示非常有用,生产环境通常更喜欢使用 VLAN 进行分割。
|
||||
|
||||
所以说,你想在主机 “edfu” 上有一个运行 IPv4 和 IPv6 的基础 “testbr0” 网络,并希望在主机 “djanet” 上使用它来生成容器。最简单的方法是使用组播 VXLAN 隧道。这种类型的隧道仅在两个主机位于同一物理段上时才起作用。
|
||||
|
||||
|
||||
```
|
||||
root@edfu:~# lxc network create testbr0 tunnel.lan.protocol=vxlan
|
||||
Network testbr0 created
|
||||
root@edfu:~# lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
它在主机 “edfu” 上定义了一个 “testbr0” 桥接,并为其他主机能加入它设置了一个组播 VXLAN。在这个设置中,“edfu” 为这个网络扮演了一个路由器角色,提供 DHCP、DNS 等等,其他主机只是通过隧道转发流量。
|
||||
|
||||
```
|
||||
root@djanet:~# lxc network create testbr0 ipv4.address=none ipv6.address=none tunnel.lan.protocol=vxlan
|
||||
Network testbr0 created
|
||||
root@djanet:~# lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
现在你可以在任何一台主机上启动容器,并看到它们从同一个地址池中获取 IP,通过隧道直接互相通讯。
|
||||
|
||||
如先前所述,这个使用了组播,它通常在跨越路由器时无法很好工作。在这些情况下,你可以用单播模式使用 VXLAN 或者 GRE 隧道。
|
||||
|
||||
要使用 GRE 加入另一台主机,首先配置服务主机:
|
||||
|
||||
```
|
||||
root@edfu:~# lxc network set testbr0 tunnel.nuturo.protocol gre
|
||||
root@edfu:~# lxc network set testbr0 tunnel.nuturo.local 172.17.16.2
|
||||
root@edfu:~# lxc network set testbr0 tunnel.nuturo.remote 172.17.16.9
|
||||
```
|
||||
|
||||
接着是“客户端”主机:
|
||||
|
||||
```
|
||||
root@nuturo:~# lxc network create testbr0 ipv4.address=none ipv6.address=none tunnel.edfu.protocol=gre tunnel.edfu.local=172.17.16.9 tunnel.edfu.remote=172.17.16.2
|
||||
Network testbr0 created
|
||||
root@nuturo:~# lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
如果你像使用 VXLAN,只要这么做:
|
||||
|
||||
```
|
||||
root@edfu:~# lxc network set testbr0 tunnel.edfu.id 10
|
||||
root@edfu:~# lxc network set testbr0 tunnel.edfu.protocol vxlan
|
||||
```
|
||||
|
||||
还有:
|
||||
|
||||
```
|
||||
root@nuturo:~# lxc network set testbr0 tunnel.edfu.id 10
|
||||
root@nuturo:~# lxc network set testbr0 tunnel.edfu.protocol vxlan
|
||||
```
|
||||
|
||||
这里需要隧道 id 以防与已经配置的多播 VXLAN 隧道冲突。
|
||||
|
||||
这就是如何使用最近的 LXD 简化跨主机联网了!
|
||||
|
||||
### 总结
|
||||
|
||||
LXD 使得从简单的单主机网络到数千个容器的非常复杂的跨主机网络的定义变得更加容易。它也使为一些容器定义一个新网络或者给容器添加第二个设备,并连接到隔离的私有网络变得很简单。
|
||||
|
||||
虽然这篇文章介绍了支持的大部分功能,但仍有一些可以微调 LXD 网络体验的窍门。可以在这里找到完整的列表:[https://github.com/lxc/lxd/blob/master/doc/configuration.md][2] 。
|
||||
|
||||
### 额外信息
|
||||
|
||||
- LXD 主站:[https://linuxcontainers.org/lxd][3]
|
||||
- Github 地址: [https://github.com/lxc/lxd][4]
|
||||
- 邮件列表支持:[https://lists.linuxcontainers.org][5]
|
||||
- IRC 频道:#lxcontainers on irc.freenode.net
|
||||
- 在线尝试 LXD:[https://linuxcontainers.org/lxd/try-it][6]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.stgraber.org/2016/10/27/network-management-with-lxd-2-3/
|
||||
|
||||
作者:[Stéphane Graber][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.stgraber.org/author/stgraber/
|
||||
[1]:https://www.stgraber.org/author/stgraber/
|
||||
[2]:https://github.com/lxc/lxd/blob/master/doc/configuration.md#network-configuration
|
||||
[3]:https://linuxcontainers.org/lxd
|
||||
[4]:https://github.com/lxc/lxd
|
||||
[5]:https://lists.linuxcontainers.org/
|
||||
[6]:https://linuxcontainers.org/lxd/try-it
|
||||
[7]:https://www.stgraber.org/2016/10/27/network-management-with-lxd-2-3/
|
@ -0,0 +1,74 @@
|
||||
2017 年的八大系统运维和工程发展趋势
|
||||
=================
|
||||
|
||||
![](https://d3tdunqjn7n0wj.cloudfront.net/720x480/operations-circle-binoculars-crop-84d7249dda092338c1a6f3b562203b3d.jpg)
|
||||
|
||||
预测趋势是棘手的,尤其是在快速发展的系统运维和工程领域。2016 年,在我们的 Velocity 大会上,我们讨论了分布式系统、SRE、容器化、无服务架构,人员倦怠以及与提供软件相关的人力与技术挑战等诸多问题。以下是我们认为的下一年的趋势:
|
||||
|
||||
### 1、 分布式系统
|
||||
|
||||
我们认为这个很重要,我们[在整个 Velocity 会议上再次关注了它][1]。
|
||||
|
||||
### 2、 站点可靠性工程(SRE)
|
||||
|
||||
[站点可靠性工程(Site Reliability Engineering)][3](SRE)-它只是运维么?[或者它是 DevOps 的另外一个名称吗][4]?这是 Google 对那些需要做大量系统及软件工程的运维专业人士的称呼。它由在像 Dropbox 公司的前 Google 人向业内推广,[招聘 SRE 的职位][5]正不断增加,特别是有大型数据中心的面向网络的公司。在某些情况下,SRE 的作用更多地是帮助开发人员运营自己的服务。
|
||||
|
||||
### 3、 容器化
|
||||
|
||||
公司将继续容器化它们的软件交付。Docker 公司本身已经将 Docker 定位为“[增量革命][6]”的工具,对遗留应用进行容器化已成为企业的常见案例。Docker 的未来是什么?随着工程师继续采用诸如 Kubernetes 和 Mesos 之类的编排工具,更高层次的抽象可能为其他容器(如 rkt、Garden 等)提供更多空间。
|
||||
|
||||
### 4、 Unikernels
|
||||
|
||||
unikernels 是容器化之后的下一步么?它们不合适产品环境么?有些人吹捧 unikernels 的安全和性能好处。关注一下 unikernels 在 2017 是如何进化的,[特别要关注下 Dokcer 公司在这个领域做的][7]。(今年它已经收购了 Unikernel Systems)
|
||||
|
||||
### 5、 无服务架构(Serverless)
|
||||
|
||||
无服务架构视功能为基础的计算单元。有些人认为这个术语是误导性的(让人想起 “noops”),并且更倾向于把这个趋势称为“功能即服务(Functions-as-a-Service)”(FaaS)。开发人员和架构师正在越来越多地尝试这个技术,并期望看到有越来越多的程序用这个范式编写。更多关于 serverless/FaaS 对运维的意义,请查看 Michael Hausenblas 的 [Serverless 运维][8]免费电子书。
|
||||
|
||||
### 6、 原生云程序开发
|
||||
|
||||
就像 DevOps,这个术语已经被市场人员使用并滥用很久了,但是云计算基金会(Cloud Native Computing Foundation)(CNCF)为这些新工具(通常是谷歌发起的)做了一个很好的例子,这些工具不仅利用了云,而且特别还在于分布式系统(即微服务,容器化和动态编排)所提供的优势和机会。
|
||||
|
||||
### 7、 监控
|
||||
|
||||
随着行业从 Nagios 风格的监控发展到流化指标和可视化,我们在生产越来越多的系统数据,而如何理解它们则是下一个挑战,因此,我们看到供应商开始提供具有机器学习功能的监控服务,以及更普遍的是 IT 运营人员开始去研究让机器学习分析系统数据的技术。同样,随着我们的基础设施变得更加动态和分布式,监控越来越少地检查某个资源的健康状况,更多的是在服务之间追踪流量。因此,分布式跟踪已经出现。
|
||||
|
||||
### 8、 DevOps 安全
|
||||
|
||||
随着 DevOps 安全的普及,[安全性正在迅速成为团队范围的关注][9]。当重视安全和合规方面的公司在速度的竞争上感到了压力时,要同时满足速度和可靠性的 DevOps 所面对的经典挑战尤其明显。
|
||||
|
||||
### 告诉我们关于你的工作
|
||||
|
||||
作为一名 IT 运维专业人员 - 你是否使用系统管理的术语如 DevOps、SRE、DBA 等等。- [欢迎你来分享你的见解][10]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Courtney Nash 主持 O'Reilly Media 的多个会议,是专注于现代网络运维、高性能程序和安全性的战略内容总监。一位前学术神经科学家,她仍然对大脑着迷,以及它如何告诉我们与技术互动和对技术的期望。自从移居西雅图,在一家蓬勃发展的在线书店工作之后,她花了 17 年的时间从事技术行业的各种工作。在外面,你可以看到 Courtney 在骑自行车、徒步旅行、滑雪。。。
|
||||
|
||||
O'Reilly Media 的基础架构和运维编辑 Brian Anderson 介绍了从传统系统管理到云计算、Web 性能、Docker 和 DevOps 等软件交付的重要内容。他一直从事在线教育,服务于学习者的需求超过十多年。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.oreilly.com/ideas/top-8-systems-operations-and-engineering-trends-for-2017
|
||||
|
||||
作者:[Courtney Nash][a], [Brian Anderson][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.oreilly.com/people/3f5d7-courtneyw-nash
|
||||
[b]:https://www.oreilly.com/people/brian_anderson
|
||||
[1]:https://www.oreilly.com/ideas/velocity-a-new-direction
|
||||
[2]:https://www.oreilly.com/ideas/top-8-systems-operations-and-engineering-trends-for-2017?imm_mid=0ec113&cmp=em-webops-na-na-newsltr_20170106
|
||||
[3]:https://www.oreilly.com/ideas/what-is-sre-site-reliability-engineering
|
||||
[4]:http://conferences.oreilly.com/velocity/devops-web-performance-ny/public/content/devops-sre-ama-video
|
||||
[5]:https://www.glassdoor.com/Salaries/site-reliability-engineer-salary-SRCH_KO0,25.htm
|
||||
[6]:http://blog.scottlowe.org/2016/06/21/dockercon-2016-day-2-keynote/
|
||||
[7]:http://www.infoworld.com/article/3024410/application-virtualization/docker-kicks-off-unikernel-revolution.html
|
||||
[8]:http://www.oreilly.com/webops-perf/free/serverless-ops.csp?intcmp=il-webops-free-lp-na_new_site_top_8_systems_operations_and_engineering_trends_for_2017_body_text_cta
|
||||
[9]:https://www.oreilly.com/learning/devopssec-securing-software-through-continuous-delivery
|
||||
[10]:http://www.oreilly.com/webops-perf/2016-ops-survey.html
|
||||
[11]:http://www.oreilly.com/webops-perf/2016-ops-survey.html
|
@ -0,0 +1,89 @@
|
||||
给非英语母语的人从事开源项目的若干建议
|
||||
====================================================
|
||||
|
||||
![Tips for non-native English speakers working on open source projects](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/world_hands_diversity.png?itok=LMT5xbxJ "Tips for non-native English speakers working on open source projects")
|
||||
|
||||
|
||||
大多数的开源项目的主要语言都是英语,但是开源项目的用户和贡献者却遍布全球。非英语母语的人在参与这个生态系统时会面临许多沟通和文化上的挑战。
|
||||
|
||||
在这篇文章中,作为不以英语为母语的 OpenStack 的贡献者的我们将会分享一些所面临挑战——如何去克服它们,还有一些好的方案,它们能够减轻不以英语为母语且刚开始从事的人的焦虑。我们的总部在日本、巴西和中国,每天都会与世界各地的大型 OpenStack 社区合作。
|
||||
|
||||
OpenStack 的官方语言是英语,这意味着我们是作为非英语为母语的人士来进行交流。
|
||||
|
||||
### 挑战
|
||||
|
||||
非英语为母语的人士在开源社区工作时会面临具体沟通挑战:它们与有限的语言技能和文化差异有关。
|
||||
|
||||
#### 语言技能
|
||||
|
||||
让我们来关注在阅读、写作、听力和口语背后的具体语言技能。
|
||||
|
||||
**阅读**:这是最简单也是最重要的技能。最简单是因为:如果你不明白写了什么,你有机会再次阅读它,或者需要的话可以多次阅读。如果你遇到了一个不常见的短语、表达式或者缩写,你可以使用一个词典或者翻译器。在另一方面,它是最重要的技能是因为:对大多数开源项目而言,主要的交流方式都是邮件列表和 IRC。
|
||||
|
||||
**写作**:英语语法是一个问题,尤其是对句子结构不同的语言而言。这可能会在用电子邮件进行通信和通过 IRC 频道进行通信时产生问题。对一些人来说,写出又长又漂亮的句子比较困难,而普遍依赖于简单句子,这是因为这些易于书写和理解。
|
||||
|
||||
**听力**:这对非英语为母语的人来说比阅读和写作更加困难。通常,英语为母语的人之间的对话在非常快的,这就使得那些仍然处于刚从事阶段的人很难理解他们的讨论,同时也限制了他们参与到讨论当中。此外,试图理解一个遍布全球的社区的各种口音也增加了复杂性。有意思的是,美国人的发音往往比其他的容易理解。
|
||||
|
||||
**口语**:口语比听力更加的困难,因为参与者的词汇量可能会比较有限。而且,英语的音素和语法通常与那些母语不是英语的人的母语相差很大,这就使得互动更加的难以理解。
|
||||
|
||||
#### 文化差异
|
||||
|
||||
在开源社区与其他人交流时,每种文化都有它自己不同的规范。例如,日本人通常不会明确的说好的或者不,他们认为这是尊重别人的一种方式,可以避免彼此间的争论。这通常与其他的文化大不一样,可能会对所表达的内容造成误解。
|
||||
|
||||
在中国文化中,人们倾向于只是说好的,而不是说不,或者试图商讨。在一个像 OpenStack 这样的分布于全球的社区里,这通常会导致在表达意见时缺乏自信。另外,中国人喜欢首先列出事实,然后在后面给出结论,而这会对来自其他文化中的人造成困惑,因为这不是他们所期望的。
|
||||
|
||||
例如,巴西人可能会认为讨论是以类似的方式进行的;然而,其他文化的反应会很直接和简短,这听起来可能会有点粗鲁。
|
||||
|
||||
### 克服障碍
|
||||
|
||||
语言技能方面的挑战要比文化差异方面的挑战容易克服。文化差异需要被受到尊重,然而英语技能却总是可以被改善的。
|
||||
|
||||
为了刷新你的语言技能,你应该尽可能多地接触该语言。不要担心你的局限,只管尽自己所能,你终将会得到改善。
|
||||
|
||||
尽可能多的阅读,因为这有助于你积累词汇。通过日常的聊天和邮件列表进行交流也很有帮助。一些工具,如实时字典和翻译器,对这些平台非常有用。
|
||||
|
||||
与别人或者你自己交谈可以帮助你更自如地频繁地说话。进行一对一的对话来表达你的想法比在更大的群体中讨论更容易。
|
||||
|
||||
### 新手的融入
|
||||
|
||||
来自新手和母语者的一些举措可能会对学习过程产生积极的影响。
|
||||
|
||||
#### 新手
|
||||
|
||||
说出和写下你的意见,并且提出你的问题;参与其中总是一个练习你的英语的很好的机会。不要害怕。
|
||||
|
||||
对于会议,确保你提前准备过,这样你将会对会议主题比较熟悉,而且会对自己要表达的意见更加的自信。
|
||||
|
||||
与英语为母语的人结交朋友,多和他们讨论来提高你的英语技能。
|
||||
|
||||
用英语写博客和技术文章也是不错的主意。
|
||||
|
||||
#### 给英语为母语的人士的建议
|
||||
|
||||
请说话慢一点儿,同时使用一些简单的单词和句子。如果你发现了非英语为母语的人使用英语中的一些错误请不要嘲笑他们,尝试鼓励新来的人表达自己的意见,让他们非常舒适地表达意见。
|
||||
|
||||
*这篇文章由 Masayuki Igawa、Dong Ma 和 Samuel de Medeiros Queiroz 共同协作完成,可以在 Hobart 的 linux.conf.au 2017([#lca2017][1]):[开源社区中的非英语母语者:一个真实的故事][2]中了解更多*
|
||||
|
||||
( 题图:opensource.com)
|
||||
|
||||
-------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/profile_pictures/public/pictures/myface_s.jpg?itok=-dy9_LQd)
|
||||
|
||||
Masayuki Igawa 是一名拥有 15 年大量软件项目经验的软件工程师,目前正在开发与 Linux 内核和虚拟化相关开源软件。自 2013 年起,他就一直是一名活跃的 OpenStack 项目贡献者。他是像 Tempest 和 subunit2sql 这样一些 OpenStack QA 项目的核心成员。他目前就职于 HPE 的 Upstream OpenStack 团队,该团队目的是使 OpenStack 更适合所有人。他以前曾在 OpenStack 峰会上发表演讲。
|
||||
|
||||
---
|
||||
|
||||
via: https://opensource.com/article/17/1/non-native-speakers-take-open-source-communities
|
||||
|
||||
作者:[Masayuki Igawa][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/masayukig
|
||||
[1]:https://twitter.com/search?q=%23lca2017&src=typd
|
||||
[2]:https://linux.conf.au/schedule/presentation/70/
|
@ -1,13 +1,11 @@
|
||||
Why every business should consider an open source point of sale system
|
||||
============================================================
|
||||
为什么每家企业都应该考虑使用开源的 POS 系统
|
||||
============================================================
|
||||
|
||||
![Why every business should consider an open source point of sale system](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BUS_lovemoneyglory2.png?itok=WxnzxyWP "Why every business should consider an open source point of sale system")
|
||||
图片来源 :
|
||||
|
||||
图片来源 : opensource.com
|
||||
|
||||
opensource.com
|
||||
|
||||
销售点终端 (POS) 系统是从很久以前的简单的收银机发展而来的。如今的 POS 系统可以提供一体化解决方案,包括支付流程,库存管理,营销工具等等。零售店也可以使用移动设备来接收现金流和各种成本支出相关的日报表。
|
||||
销售点终端 (POS) 系统是从很久以前的简单的收银机发展而来的。如今的 POS 系统可以提供一体化解决方案,包括支付流程、库存管理、营销工具等等。零售店也可以使用移动设备来接收现金流和各种成本支出相关的日报表。
|
||||
|
||||
POS 系统是每家企业重要的生命线,那就意味着你在选择 POS 系统的过程中要非常谨慎。目前可供选择的收银系统也很多,但是如果你想节约成本,适应不断变化的业务需求,跟上技术发展的脚步,你应该很明智地考虑使用开源系统。你可以随意使用一款源代码公开的开源 POS 系统,这比那些严格保密源代码的专有系统要有更大的优势。
|
||||
|
||||
@ -15,7 +13,7 @@ POS 系统是每家企业重要的生命线,那就意味着你在选择 POS
|
||||
|
||||
### 无限的灵活性
|
||||
|
||||
开源系统与其它系统的兼容性非常好。它们与第三方厂家系统进行集成的能力——从帐务和客户关系管理软件到订单管理和库存管理系统——当企业管理者想要扩展专有 POS 系统以外的其它功能时,开源系统有更强大的优势。
|
||||
开源系统与其它系统的兼容性非常好。它们与第三方厂家系统进行集成的能力——从帐务和客户关系管理软件(CRM)到订单管理和库存管理系统——使得当企业管理者想要扩展专有 POS 系统以外的其它功能时,开源系统具有更强大的优势。
|
||||
|
||||
在 [2014 年科技调查][7] 活动中,很多餐厅管理者声称 POS 系统的功能集成度将会是他们考虑更换新系统的主要因素。这是开源系统最具亮点的一方面。专有系统买来什么样就是什么样,很难与其它厂家的系统进行集成。但是使用开源系统,你就可以进行无限的集成及定制功能。如果你觉得你们公司的商业模式会不断的增长和变化,那么只有考虑使用开源的 POS 系统才能根据需要实时调整系统。
|
||||
|
||||
@ -25,11 +23,11 @@ POS 系统是每家企业重要的生命线,那就意味着你在选择 POS
|
||||
|
||||
### 更低的成本
|
||||
|
||||
也就是说,“更低的成本”意味着“基本免费”。你还需要购买相关硬件产品,只是软件本身是免费使用的。开源 POS 系统不像专有 POS 系统那样在购买时或是后期维护过程中需要支付高昂的费用,其每年的维护费在 3000 至 50000 美元之间,开源系统也不会像专有系统那样需要花钱来购买。
|
||||
也就是说,“更低的成本”意味着“基本免费”。你还需要购买相关硬件产品,只是软件本身是免费使用的。开源 POS 系统不像专有 POS 系统那样在购买时或是后期维护过程中需要支付高昂的费用,其每年的维护费在 3000 至 50000 美元之间,而开源系统则不会像专有系统那样需要花钱来购买。
|
||||
|
||||
在 [2013 年版][8] 的餐饮行业技术服务调查研究过程中,有超过一半的受访餐厅老板表示他们从很多的技术产商购买服务——有些餐厅所面对的技术厂家多达 10 个。而使用纯粹的开源定制化系统不需要支付维护费用,这从节约成本上来说意义非常重大。
|
||||
|
||||
然而,有一点我还得提醒大家。如果你们公司没有一个技术精湛的员工提供技术支持,你可能还需要聘请外部技术人员来帮助你们安装,调试和升级系统。开源系统允许用户无限制集成和定制化开发,但是你还需要有技术精湛的专家来支持才行,这也会产生额外的费用。尽管如此,开源系统仍然是一个非常具有成本效益的选择。
|
||||
然而,有一点我还得提醒大家。如果你们公司没有一个技术精湛的员工提供技术支持,你可能还需要聘请外部技术人员来帮助你们安装,调试和升级系统。开源系统允许用户无限制地集成和定制化开发,但是你还需要有技术精湛的专家来支持才行,这也会产生额外的费用。尽管如此,开源系统仍然是一个非常具有成本效益的选择。
|
||||
|
||||
### 更好的安全性
|
||||
|
@ -0,0 +1,70 @@
|
||||
10 个使用 Cinnamon 作为 Linux 桌面环境的理由
|
||||
============================================================
|
||||
|
||||
> Cinnamon 是一个让人怀旧 GNOME 2 的 Linux 桌面环境,它灵活、快速,并提供了种种的功能。
|
||||
|
||||
![10 reasons to use Cinnamon as your Linux desktop environment](https://opensource.com/sites/default/files/styles/image-full-size/public/cinnamon.jpg?itok=rPZvjqGr "10 reasons to use Cinnamon as your Linux desktop environment")
|
||||
|
||||
最近我安装了 Fedora 25,我觉得当前的 [KDE][3] Plasma 版本并不稳定。在我决定尝试其它的桌面之前一天崩溃了好几次。在我安装了几个其它的桌面,并每个尝试了几个小时后,我最终决定在 Plasma 打上补丁并且稳定之前就使用 Cinnamon 了。以下是我所发现的。
|
||||
|
||||
### Cinnamon 简介
|
||||
|
||||
在 2011,带有新的 GNOME Shell 的 GNOME 3 发布了,新的界面马上引来了或正或反的反馈。许多用户以及开发者非常喜欢原先的 GNOME 界面,因此有多个组织复刻了它,其中一个结果就是 Cinnamon。
|
||||
|
||||
开发 GNOME 3 的 GNOME shell 背后的原因之一是许多原先的 GNOME 用户界面组件不再活跃开发了。这同样也是 Cinnamon 以及其他 GNOME 复刻项目的问题。 Linux Mint 项目是 Cinnamon 的一个首要推动者,因为 GNOME 是 Mint 的官方桌面环境。Mint 开发者已经将 Cinnamon 推进到了不需要 GNOME 本身的地步,Cinnamon 已经是一个完全独立的桌面环境,它保留了许多用户喜欢的 GNOME 界面的功能。
|
||||
|
||||
![cinnamon-desktop-environment.jpg](https://opensource.com/sites/default/files/images/life-uploads/cinnamon-desktop-environment.jpg)
|
||||
|
||||
*图 1:打开系统设置工具的默认 Cinnamon 桌面。*
|
||||
|
||||
Cinnamon 3.2 是当前发布版本。除了 Mint,Cinnamon 还在许多发行版中可用,包括 Fedora、Arch、Gentoo、Debian 和 OpenSUSE 等。
|
||||
|
||||
### 使用 Cinnamon 的理由
|
||||
|
||||
这是我的使用 Cinnamon 的 10 个重要理由:
|
||||
|
||||
1. **集成。** 桌面的选择并不取决于在较长时间内是否有为它写的应用。我使用过的所有应用程序,不管它是在哪个桌面下写的,它都可以在任何其它桌面上运行正常,Cinnamon 也不例外。要运行那些为 KDE、GNOME 或其他桌面编写的程序所需要的库都有,可以在 Cinnamon 上面顺滑地使用这些程序。
|
||||
2. **外观。** 让我们面对它,外观是很重要的。Cinnamon 有一个明快的、干净的外观,它使用了易于阅读的字体以及颜色的组合。桌面没有不必要的阻碍,你可以使用“系统设置” => “桌面” 菜单配置显示在桌面上的的图标。这个菜单还允许你指定是否在主监视器、次监视器或者所有监视器上显示桌面图标。
|
||||
3. **桌面组件。** 桌面组件是一些小型的、可以添加到桌面的单一用途的程序。只有一些是可用的,但是你可以从 CPU 或者磁盘监视器、天气应用、便利贴、桌面相簿、时间和日期等之中选择。我喜欢时间和日期桌面组件,因为它比 Cinnamon 面板中的小程序易于阅读。
|
||||
4. **速度。** Cinnamon 快速又敏捷。程序加载和显示很快。桌面自身在登录时加载也很快,虽然这只是我的主观体验,并没有基于时间测试。
|
||||
5. **配置。 ** Cinnamon 不如 KDE Plasma 那样可配置,但是也要比我第一次尝试它的时候有更多的配置。Cinnamon 控制中心提供了许多桌面配置选项的集中访问。它有一个主窗口,可以从它启动特定功能的配置窗口。可以很容易地在 “系统设置” 的 “主题” 的可用外观中选择新的外观。你可以选择窗口边框、图标、控件、鼠标指针和桌面基本方案。其它选择还包括字体和背景。我发现这些配置工具中有许多是我遇到的最好的。它有适量的桌面主题,从而能够显著改变桌面的外观,而不会像 KDE 那样面临选择困难。
|
||||
6. **Cinnamon 面板。** Cinnamon 面板,即工具栏,最初的配置非常简单。它包含用于启动程序的菜单、基本的系统托盘和应用程序选择器。这个面板易于配置,并且添加新的程序启动器只需要定位你想要添加到主菜单的程序,右键单击程序图标,然后选择“添加到面板”。你还可以将启动器图标添加到桌面本身,以及 Cinnamon 的 “收藏” 的启动栏中。你还可以进入面板的**编辑**模式并重新排列图标。
|
||||
7. **灵活性。** 有时可能很难找到最小化或者隐藏的正在运行的程序,如果有许多正在运行的应用程序,则在工具栏的程序选择器上查找它可能会有挑战性。 在某种程度上,这是因为程序并不总是有序地排在选择器中使其易于查找,所以我最喜欢的功能之一就是可以拖动正在运行的程序的按钮并将其重新排列在选择器上。这可以使查找和显示属于程序的窗口更容易,因为现在它们现在在我放的位置上。
|
||||
|
||||
Cinnamon 桌面还有一个非常好的弹出菜单,你可以右键单击访问。此菜单有一些常用任务,例如访问桌面设置、添加桌面组件以及其他与桌面相关的任务。
|
||||
|
||||
其它菜单项之一是 “创建新文档”,它使用位于 `~/Templates` 目录中的文档模板,并列出它们中的每一个。只需点击要使用的模板,使用这个模板的文档就会使用默认的 Office 程序创建。在我的情况下,那就是 LibreOffice。
|
||||
8. **多工作空间。** Cinnamon 像其他桌面环境一样提供了多个桌面。Cinnamon 称它为“工作区”。工作区选择器位于 Cinnamon 面板中并展示每个工作区的窗口概览。窗口可以在工作区之间移动或指定到所有工作区。我确实发现工作区选择器有时候会比窗口位置的显示慢一些,所以我将工作区选择器切换为显示工作区编号,而不是在工作区中显示窗口概览。
|
||||
9. **Nemo。** 大部分桌面因种种目而使用它们自己偏好的默认程序,Cinnamon 也不例外。我偏好的桌面文件管理器是 Krusader,但是 Cinnamon 默认使用 Nemo,因此在测试中我就用它了。我发现我很喜欢 Nemo。它有一个美丽干净的界面,我喜欢大部分功能并经常使用。它易于使用,同时对我的需求也足够灵活。虽然 Nemo 是 Nautilus 的复刻,但是我发现 Nemo 更好地被集成进了 Cinnamon 环境。Nautilus 界面看上去没有与 Cinnamon 很好集成,与 Cinnamon 不太和谐。
|
||||
10. **稳定性。** Cinnamon 非常稳定且可用。
|
||||
|
||||
### 总结
|
||||
|
||||
Cinnamon 是 GNOME 3 桌面的复刻,它看上去像一个前所未有的 GNOME 桌面。它的发展看起来是符合逻辑的改进, Cinnamon 开发者认为需要在提升和扩展 GNOME 的同时保留它的独特性以及被大家非常喜欢的特性。它不再是 GNOME 3 - 它是不同的并且是更好的。Cinnamon 看上去很棒,并且对我而言也工作得很好,并且从 KDE 这个我仍旧非常喜欢的环境切换过来也很顺畅。我花费了几天时间学习 Cinnamon 的差异如何使我的桌面体验更好,并且我非常高兴了解这个很棒的桌面。
|
||||
|
||||
虽然我喜欢 Cinnamon,但我仍然喜欢体验其它的环境,我目前正切换到 LXDE 桌面,并已经用了几个星期。在我使用一段时间时候,我会分享我的 LXDE 体验。
|
||||
|
||||
(题图: [Sam Mugraby][1],Photos8.com. [CC BY 2.0][2])
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/profile_pictures/public/david-crop.jpg?itok=oePpOpyV)
|
||||
|
||||
David Both 是一个 Linux 和开源倡导者,他居住在北卡罗莱纳州的 Raleigh。他在 IT 行业已经超过 40 年,在他工作的 IBM 公司教授 OS/2 超过 20 年,他在 1981 年为最早的 IBM PC 写了第一个培训课程。他教过 Red Hat 的 RHCE 课程,在 MCI Worldcom、 Cisco 和北卡罗莱纳州 工作过。他一直在使用 Linux 和开源软件近 20 年。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/1/cinnamon-desktop-environment
|
||||
|
||||
作者:[David Both][a]
|
||||
译者:[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/dboth
|
||||
[1]:https://commons.wikimedia.org/wiki/File:Cinnamon-other.jpg
|
||||
[2]:https://creativecommons.org/licenses/by/2.0/deed.en
|
||||
[3]:https://opensource.com/life/15/4/9-reasons-to-use-kde
|
@ -1,8 +1,8 @@
|
||||
如何从参与开源项目的过程中获取自信
|
||||
===============
|
||||
|
||||
![如何从参与开源项目的过程中获取自信](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/open_community_lead.jpg?itok=anXgpnwG "How to gain confidence to participate in open source")
|
||||
|
||||
图片来源:[Gabriel Kamener, Sown Together][1] 原创,经 Jen Wike Huger 修改。
|
||||
|
||||
随着大脑的发育,你渐渐学会了这世上什么事情可以/应该做,以及什么事情不能/不应该做。你所有的行为都受到周围大众的影响,很多时候,阻碍你参与某事的原因就是你缺乏自信。
|
||||
|
||||
@ -18,13 +18,13 @@
|
||||
|
||||
你要时刻谨记着:你是完全独立的个人,他人对你做出的评论就像是不存在一样,只有这样才能更好的获得自信。
|
||||
|
||||
我们都习惯了这样理解,周围的人都是根据我们的行为来做出评判的。这一习惯相当于学习如何更像社会群体一样生活的副产品。而且很可能在我们的童年,父母根据我们的行为设置的奖励机制时,这个习惯就根植我们心底。到了青春期,老师们对我们的表现来评价,给我们划分等级和分数,拿我们和身边的小伙伴对比。这样的动力和奖励机制给我们的大脑建立了一个包括自我反思在内的反馈回路。我们需要预测自己能否得到回报,并要为那些可能发生的事情做好应对。
|
||||
我们都习惯了这样认知,周围的人都是根据我们的行为来做出评判的。这一习惯是学习如何更像社会群体一样生活的副产品。而且很可能在我们的童年,父母根据我们的行为设置的奖励机制时,这个习惯就根植我们心底。到了青春期,老师们对我们的表现来评价,给我们划分等级和分数,拿我们和身边的小伙伴对比。这样的动力和奖励机制给我们的大脑建立了一个包括自我反思在内的反馈回路。我们需要预测自己能否得到回报,并要为那些可能发生的事情做好应对。
|
||||
|
||||
现今的我们都有这样第一个疑惑:身边的人是如何看我的?然而,真相是多数人都不会花太多时间来对你进行正确客观的评价。我们所有人只是关注自己的回报,我们有自己热衷于某件事的的热情、有大量急待解决的问题。也有一些人忙于关心他们自己如何影响身边的人,他们并不会在身上花费时间。他们根本不会注意到你是否出错、大声谈话还是向他们的背景乐一样。所有的那些疑惑都只是在你自己的脑海中而已,而非在其他任何人脑中。
|
||||
现今的我们都有这样第一个疑惑:身边的人是如何看我的?然而,真相是多数人都不会花太多时间来对你进行正确客观的评价。我们所有人只是关注自己的回报,我们有自己热衷于某件事的的热情、有大量急待解决的问题。也有一些人忙于关心他们自己如何影响身边的人,他们并不会在身上花费时间。他们根本不会注意到你是否出错、大声谈话还是像他们的背景音乐一样。所有的那些疑惑都只是在你自己的脑海中而已,而非在其他任何人脑中。
|
||||
|
||||
我们需要为人们所接受的愿望也是人生意义的一部分,但是这类受我们所遇之人的一时兴起。这些人可能对我们缺乏全面认识,比如我们叫什么、我们来自哪里、形成我们认知的经历,等等。我们能否为人们所接受是一件不受我们自身控制的事情。但是,我们是可以通过与之交流来改变的。
|
||||
我们需要被人们所接受的愿望也是人生意义的一部分,但是这类受我们所遇之人的一时兴起。这些人可能对我们缺乏全面认识,比如我们叫什么、我们来自哪里、形成我们认知的经历,等等。我们能否为人们所接受是一件不受我们自身控制的事情。但是,我们是可以通过与之交流来改变的。
|
||||
|
||||
在开源的高密度社区的世界里,记住这一点是非常重要的:人们是不会过多的考虑你的。因为你的同事和导师都在忙于其他项目或则社区成员。
|
||||
在开源的社区化世界里,记住这一点是非常重要的:人们是不会过多的考虑你的感受的。因为你的同事和导师都在忙于其它项目或则社区成员。
|
||||
|
||||
一旦你认知了这一点,通过积极地沟通来热情拥抱这个世界吧。寻求帮助、告知他人你的需求、指出你的贡献、让人们知道你和他们在一起努力、你也是这个社区中的活跃分子。当人们向你靠拢 ——而非相反 —— 时,你的开源可信度和自信会得到极大的提高。
|
||||
|
||||
@ -32,9 +32,9 @@
|
||||
|
||||
任何成功的开源社区都是一个包含教和学的社区。为沐浴在开源中,你不仅需要用到自身的已有知识,还需要不断的吸收消化其他人提供课程中的知识。幸运的是,人们都普遍热衷于分享他们熟悉的事情。
|
||||
|
||||
思考一下,当他人问及你的观点时,你是什么感受。得知他人认可了你所说的观点,对你的 ID 和个人精神是多么美好的一件事。
|
||||
思考一下,当他人问及你的观点时,你是什么感受。得知他人认可了你所说的观点,对你的本我和自我是多么美好的一件事。
|
||||
|
||||
在儿童期时,我们的大脑并没有那么发达,无法为我们容纳现实世界中大量的信息量。我们曾一度认为自己是世界的中心。在六岁以前,我们的认知一直在不断成长。在此期间,我们的额父母会因我们哭泣而做出回应,周围的成年人都会满足我们要求。这会在我们心底形成自己在世界上最重要的证据。
|
||||
在儿童期时,我们的大脑并没有那么发达,无法为我们容纳现实世界中大量的信息量。我们曾一度认为自己是世界的中心。在六岁以前,我们的认知一直在不断成长。在此期间,我们的父母会因我们哭泣而做出回应,周围的成年人都会满足我们要求。这会在我们心底形成自己在世界上最重要的证据。
|
||||
|
||||
我们的神经回路在此期间建立完成,我们的性格也在此期间形成。随着我们学会参与社会和城市的生活,我们逐渐的认识到自己并非世界的中心。然而,最初形成并深植我们心底那种意识并不会因此马上就消除掉。正确理解我们在整个社会氛围中的个人意识将有助于你与他人建立连接并融洽相处。
|
||||
|
||||
@ -44,10 +44,9 @@
|
||||
|
||||
自信的人也许会说“是的,我不知道”,但却不会因此而沮丧。
|
||||
|
||||
### 一分耕耘,一分收获 (You reap what you sow)
|
||||
### 一分耕耘,一分收获
|
||||
|
||||
你一定听过“不懂装懂,永远是饭桶”。这样说吧,自信就像其他很多的心理现象。
|
||||
积极地提示自己:我很聪明、有趣、引人关注、极富天赋、健谈、是一个很好的伙伴、独一无二、知识面广、学习能力强、常常自省的思想者,或者是其他你想要具备的特质,久而久之你就会觉得自己就是这样的人。并且,如果这可以在你身上生效,在其他人身上也一样。。
|
||||
你一定听过“不懂装懂,永远是饭桶”。这样说吧,自信就像其他很多的心理现象。积极地提示自己:我很聪明、有趣、引人关注、极富天赋、健谈、是一个很好的伙伴、独一无二、知识面广、学习能力强、常常自省的思想者,或者是其他你想要具备的特质,久而久之你就会觉得自己就是这样的人。并且,如果这可以在你身上生效,在其他人身上也一样。。
|
||||
|
||||
我们把这个称为自我肯定。
|
||||
|
||||
@ -55,13 +54,15 @@
|
||||
|
||||
那么,你是否有其他增强自信的方法呢?记得在评论区告诉我们哦。
|
||||
|
||||
(题图:[Gabriel Kamener, Sown Together][1] 原创,经 Jen Wike Huger 修改。)
|
||||
|
||||
----------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/profile_pictures/public/profilepicsq_0.jpg?itok=CVMJs36A)
|
||||
|
||||
Laura Hilliger - 艺术家、教育事业者、作家、技术专家。她是一个多媒体设计师和开发者、技术联络员、项目经理、一个开放且喜欢协作环境的网络黑客。她主张变革,目前为发展壮大绿色和平组织二辛勤工作。Alum @Mozilla,UC Berkeley,BAVC, Adobe。Twitter @epilepticrabbit 。
|
||||
Laura Hilliger - 艺术家、教育事业者、作家、技术专家。她是一个多媒体设计师和开发者、技术联络员、项目经理、一个开放且喜欢协作环境的网络黑客。她主张变革,目前为发展壮大绿色和平组织而辛勤工作。Alum @Mozilla,UC Berkeley,BAVC, Adobe。Twitter @epilepticrabbit 。
|
||||
|
||||
----------------------------------
|
||||
|
@ -0,0 +1,323 @@
|
||||
在 Go 中如何使用切片的容量和长度
|
||||
============================================================
|
||||
|
||||
快速测试 - 下面的代码输出什么?
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
}
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
_[在 Go Playground 运行一下][1]_
|
||||
|
||||
如果你猜测的是 `[0 0 0 0 0 0 1 2 3 4]`,那你是对的。
|
||||
|
||||
_等等,什么?_ 为什么不是 `[0 1 2 3 4]`?
|
||||
|
||||
如果你在测试中做错了,你也不用担心。这是在过渡到 Go 语言的过程中相当常见的错误,在这篇文章中,我们将说明为什么输出不是你预期的,以及如何利用 Go 的细微差别来使你的代码更有效率。
|
||||
|
||||
### 切片 vs 数组
|
||||
|
||||
在 Go 中同时有数组(array)和切片(slice)。这可能令人困惑,但一旦你习惯了,你会喜欢上它。请相信我。
|
||||
|
||||
切片和数组之间存在许多差异,但我们要在本文中重点介绍的内容是数组的大小是其类型的一部分,而切片可以具有动态大小,因为它们是围绕数组的封装。
|
||||
|
||||
这在实践中意味着什么?那么假设我们有数组 `val a [10]int`。该数组具有固定大小,且无法更改。如果我们调用 `len(a)`,它总是返回 `10`,因为这个大小是类型的一部分。因此,如果你突然需要在数组中超过 10 个项,则必须创建一个完全不同类型的新对象,例如 `val b [11]int`,然后将所有值从 `a` 复制到 `b`。
|
||||
|
||||
在特定情况下,含有集合大小的数组是有价值的,但一般而言,这不是开发人员想要的。相反,他们希望在 Go 中使用类似于数组的东西,但是随着时间的推移,它们能够随时增长。一个粗略的方式是创建一个比它需要大得多的数组,然后将数组的一个子集视为数组。下面的代码是个例子。
|
||||
|
||||
```
|
||||
var vals [20]int
|
||||
for i := 0; i < 5; i++ {
|
||||
vals[i] = i * i
|
||||
}
|
||||
subsetLen := 5
|
||||
|
||||
fmt.Println("The subset of our array has a length of:", subsetLen)
|
||||
|
||||
// Add a new item to our array
|
||||
vals[subsetLen] = 123
|
||||
subsetLen++
|
||||
fmt.Println("The subset of our array has a length of:", subsetLen)
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][2]_
|
||||
|
||||
在代码中,我们有一个长度为 `20` 的数组,但是由于我们只使用一个子集,代码中我们可以假定数组的长度是 `5`,然后在我们向数组中添加一个新的项之后是 `6`。
|
||||
|
||||
这是(非常粗略地说)切片是如何工作的。它们包含一个具有设置大小的数组,就像我们前面的例子中的数组一样,它的大小为 `20`。
|
||||
|
||||
它们还跟踪程序中使用的数组的子集 - 这就是 `append` 属性,它类似于上一个例子中的 `subsetLen` 变量。
|
||||
|
||||
最后,一个切片还有一个 `capacity`,类似于前面例子中我们的数组的总长度(`20`)。这是很有用的,因为它会告诉你的子集在无法容纳切片数组之前可以增长的大小。当发生这种情况时,需要分配一个新的数组,但所有这些逻辑都隐藏在 `append` 函数的后面。
|
||||
|
||||
简而言之,使用 `append` 函数组合切片给我们一个非常类似于数组的类型,但随着时间的推移,它可以处理更多的元素。
|
||||
|
||||
我们再来看一下前面的例子,但是这次我们将使用切片而不是数组。
|
||||
|
||||
```
|
||||
var vals []int
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
fmt.Println("The length of our slice is:", len(vals))
|
||||
fmt.Println("The capacity of our slice is:", cap(vals))
|
||||
}
|
||||
|
||||
// Add a new item to our array
|
||||
vals = append(vals, 123)
|
||||
fmt.Println("The length of our slice is:", len(vals))
|
||||
fmt.Println("The capacity of our slice is:", cap(vals))
|
||||
|
||||
// Accessing items is the same as an array
|
||||
fmt.Println(vals[5])
|
||||
fmt.Println(vals[2])
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][3]_
|
||||
|
||||
我们仍然可以像数组一样访问我们的切片中的元素,但是通过使用切片和 `append` 函数,我们不再需要考虑背后数组的大小。我们仍然可以通过使用 `len` 和 `cap` 函数来计算出这些东西,但是我们不用担心太多。简洁吧?
|
||||
|
||||
### 回到测试
|
||||
|
||||
记住这点,让我们回顾前面的测试,看下什么出错了。
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
}
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
当调用 `make` 时,我们允许最多传入 3 个参数。第一个是我们分配的类型,第二个是类型的“长度”,第三个是类型的“容量”(_这个参数是可选的_)。
|
||||
|
||||
通过传递参数 `make([]int, 5)`,我们告诉程序我们要创建一个长度为 5 的切片,在这种情况下,默认的容量与长度相同 - 本例中是 5。
|
||||
|
||||
虽然这可能看起来像我们想要的那样,这里的重要区别是我们告诉我们的切片,我们要将“长度”和“容量”设置为 5,假设你想要在初始的 5 个元素_之后_添加新的元素,我们接着调用 `append` 函数,那么它会增加容量的大小,并且会在切片的最后添加新的元素。
|
||||
|
||||
如果在代码中添加一条 `Println()` 语句,你可以看到容量的变化。
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
fmt.Println("Capacity was:", cap(vals))
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
fmt.Println("Capacity is now:", cap(vals))
|
||||
}
|
||||
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][4]_
|
||||
|
||||
最后,我们最终得到 `[0 0 0 0 0 0 1 2 3 4]` 的输出而不是希望的 `[0 1 2 3 4]`。
|
||||
|
||||
如何修复它呢?好的,这有几种方法,我们将讲解两种,你可以选取任何一种在你的场景中最有用的方法。
|
||||
|
||||
#### 直接使用索引写入而不是 `append`
|
||||
|
||||
第一种修复是保留 `make` 调用不变,并且显式地使用索引来设置每个元素。这样,我们就得到如下的代码:
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
vals[i] = i
|
||||
}
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][5]_
|
||||
|
||||
在这种情况下,我们设置的值恰好与我们要使用的索引相同,但是你也可以独立跟踪索引。
|
||||
|
||||
比如,如果你想要获取 map 的键,你可以使用下面的代码。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
ret := make([]string, len(m))
|
||||
i := 0
|
||||
for key := range m {
|
||||
ret[i] = key
|
||||
i++
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][6]_
|
||||
|
||||
这样做很好,因为我们知道我们返回的切片的长度将与 map 的长度相同,因此我们可以用该长度初始化我们的切片,然后将每个元素分配到适当的索引中。这种方法的缺点是我们必须跟踪 `i`,以便了解每个索引要设置的值。
|
||||
|
||||
这就让我们引出了第二种方法……
|
||||
|
||||
#### 使用 `0` 作为你的长度并指定容量
|
||||
|
||||
与其跟踪我们要添加的值的索引,我们可以更新我们的 `make` 调用,并在切片类型之后提供两个参数。第一个,我们的新切片的长度将被设置为 `0`,因为我们还没有添加任何新的元素到切片中。第二个,我们新切片的容量将被设置为 map 参数的长度,因为我们知道我们的切片最终会添加许多字符串。
|
||||
|
||||
这会如前面的例子那样仍旧会在背后构建相同的数组,但是现在当我们调用 `append` 时,它会将它们放在切片开始处,因为切片的长度是 0。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
ret := make([]string, 0, len(m))
|
||||
for key := range m {
|
||||
ret = append(ret, key)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][7]_
|
||||
|
||||
### 如果 `append` 处理它,为什么我们还要担心容量呢?
|
||||
|
||||
接下来你可能会问:“如果 `append` 函数可以为我增加切片的容量,那我们为什么要告诉程序容量呢?”
|
||||
|
||||
事实是,在大多数情况下,你不必担心这太多。如果它使你的代码变得更复杂,只需用 `var vals []int` 初始化你的切片,然后让 `append` 函数处理接下来的事。
|
||||
|
||||
但这种情况是不同的。它并不是声明容量困难的例子,实际上这很容易确定我们的切片的最后容量,因为我们知道它将直接映射到提供的 map 中。因此,当我们初始化它时,我们可以声明切片的容量,并免于让我们的程序执行不必要的内存分配。
|
||||
|
||||
如果要查看额外的内存分配情况,请在 Go Playground 上运行以下代码。每次增加容量,程序都需要做一次内存分配。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
"mouse": struct{}{},
|
||||
"wolf": struct{}{},
|
||||
"alligator": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
var ret []string
|
||||
fmt.Println(cap(ret))
|
||||
for key := range m {
|
||||
ret = append(ret, key)
|
||||
fmt.Println(cap(ret))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][8]_
|
||||
|
||||
现在将此与相同的代码进行比较,但具有预定义的容量。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
"mouse": struct{}{},
|
||||
"wolf": struct{}{},
|
||||
"alligator": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
ret := make([]string, 0, len(m))
|
||||
fmt.Println(cap(ret))
|
||||
for key := range m {
|
||||
ret = append(ret, key)
|
||||
fmt.Println(cap(ret))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][9]_
|
||||
|
||||
在第一个代码示例中,我们的容量从 `0` 开始,然后增加到 `1`、 `2`、 `4`, 最后是 `8`,这意味着我们不得不分配 5 次数组,最后一个容纳我们切片的数组的容量是 `8`,这比我们最终需要的要大。
|
||||
|
||||
另一方面,我们的第二个例子开始和结束都是相同的容量(`5`),它只需要在 `keys()` 函数的开头分配一次。我们还避免了浪费任何额外的内存,并返回一个能放下这个数组的完美大小的切片。
|
||||
|
||||
### 不要过分优化
|
||||
|
||||
如前所述,我通常不鼓励任何人做这样的小优化,但如果最后大小的效果真的很明显,那么我强烈建议你尝试为切片设置适当的容量或长度。
|
||||
|
||||
这不仅有助于提高程序的性能,还可以通过明确说明输入的大小和输出的大小之间的关系来帮助澄清你的代码。
|
||||
|
||||
### 总结
|
||||
|
||||
>你好!我写了很多关于Go、Web 开发和其他我觉得有趣的话题。
|
||||
>
|
||||
>如果你想跟上最新的文章,请[注册我的邮件列表][10]。我会给你发送我新书的样例、Go 的 Web 开发、以及每当有新文章(通常每周 1-2 次)会给你发送邮件。
|
||||
>
|
||||
>哦,我保证不会发垃圾邮件。我像你一样讨厌它 :)
|
||||
|
||||
本文并不是对切片或数组之间差异的详细讨论,而是简要介绍了容量和长度如何影响切片,以及它们在方案中的用途。
|
||||
|
||||
为了进一步阅读,我强烈推荐 Go 博客中的以下文章:
|
||||
|
||||
* [Go Slices:使用及内部][11]
|
||||
* [数组、切片(和字符串):“append” 的机制][12]
|
||||
* [切片技巧][13]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jon 是一名软件顾问,也是 《Web Development with Go》 一书的作者。在此之前,他创立了 EasyPost,一家 Y Combinator 支持的创业公司,并在 Google 工作。
|
||||
|
||||
https://www.usegolang.com
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
via: https://www.calhoun.io/how-to-use-slice-capacity-and-length-in-go
|
||||
|
||||
作者:[Jon Calhoun][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.calhoun.io/hire-me
|
||||
[1]:https://play.golang.org/p/7PgUqBdZ6Z
|
||||
[2]:https://play.golang.org/p/Np6-NEohm2
|
||||
[3]:https://play.golang.org/p/M_qaNGVbC-
|
||||
[4]:https://play.golang.org/p/d6OUulTYM7
|
||||
[5]:https://play.golang.org/p/JI8Fx3fJCU
|
||||
[6]:https://play.golang.org/p/kIKxkdX35B
|
||||
[7]:https://play.golang.org/p/h5hVAHmqJm
|
||||
[8]:https://play.golang.org/p/fDbAxtAjLF
|
||||
[9]:https://play.golang.org/p/nwT8X9-7eQ
|
||||
[10]:https://www.calhoun.io/how-to-use-slice-capacity-and-length-in-go/?utm_source=golangweekly&utm_medium=email#mailing-list-form
|
||||
[11]:https://blog.golang.org/go-slices-usage-and-internals
|
||||
[12]:https://blog.golang.org/slices
|
||||
[13]:https://github.com/golang/go/wiki/SliceTricks
|
||||
[14]:https://www.calhoun.io/how-to-use-slice-capacity-and-length-in-go/
|
@ -0,0 +1,128 @@
|
||||
六大标志性的开源形象概览
|
||||
=====================
|
||||
|
||||
![六大标志性的开源形象概览](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BUSINESS_brandbalance.png?itok=opwotgEh "A look at 6 iconic open source brands")
|
||||
|
||||
品牌是营销的重要组成部分。完成了品牌的塑造并形成一定的影响力之后,一个简单的 Logo (比如说耐克旋风一样) 就会成为这个品牌的强大广告。如果你常常在美国各州之间穿梭,你将会看各种描述品牌的标志符号,如麦当劳的金色拱门(golden arches)。即便是没有任何文字或图像的简单色彩组合也是可以用来作为一个品牌的,比如美国弗吉尼亚理工大学的栗色和橙色,这种独特的色彩结合是很难被认错的。
|
||||
|
||||
所以,现在的问题是:品牌对于开源社区是否真的那么重要呢?
|
||||
|
||||
对于我和其他很多的人来说,是的,非常重要。开源软件要与付费软件进行竞争,那么它必须要将自己定义为切实可行的替代品。并且,它也必须要让人容易记住以及形成一定程度的影响力。如果某个开源软件项目以一种设计难看的 Logo、糟糕的口号、前后矛盾的信息来表现自己的话,那它就很难引起大众的注意、难以记住和得到广泛使用。
|
||||
|
||||
现有很多项目这方面做得很好,我们可以从中寻找灵感和指导方法。以下是我最喜欢的六个开源品牌。
|
||||
|
||||
### 六大开源品牌
|
||||
|
||||
|
||||
#### Linux
|
||||
|
||||
![Linux's Tux 吉祥物](https://opensource.com/sites/default/files/resize/linux-300x354.png "Linux&#039;s Tux mascot")
|
||||
|
||||
这个可爱的 Linux 企鹅叫做 Tux,人们通常将其称为吉祥物,而非 Logo。
|
||||
|
||||
Tux 是 Larry Ewing 在 1996 年使用 GIMP 0.54 创建出来的。按 Jeff Ayers 讲述的[故事][4]:自从 Linus Torvalds 1993 年在澳大利亚的某个动物园被一只企鹅咬了一口之后,他就特别的钟爱它们。Torvalds 当时正在为 Linux 寻找一个有趣的形象,他觉得一个饱食后正在休息的胖企鹅是一个不错的选择。Tux 同时也出现在视频游戏和麦片广告中,它甚至还有一个叫做 Gown 的异性同伴。正如 Mac 用户熟知那个被咬了一口的苹果、Windows 用户熟知那个飘动的窗口那样,作为 Linux 用户,你肯定也非常熟悉 Tux。
|
||||
|
||||
#### Mozilla
|
||||
|
||||
![Mozilla 2017 的新 Logo ](https://opensource.com/sites/default/files/resize/mozilla_1-650x185.png "Mozilla new logo 2017")
|
||||
|
||||
[Mozilla][5] 基金会是一个非营利组织和 [自由软件社区][6]。
|
||||
|
||||
近期,它完成了[品牌重建行动][7],其创意团队负责人 Tim Murray 这样写道:“该项目的核心就是应让人们更好地理解 Mozilla 自身的目的和商标的需求而生。我们的品牌标识,包括 Logo、口号及其设计,是我们用以传递我们自身的信仰和所做的工作的重要信号。”
|
||||
|
||||
以真正的开源方式,Mozilla 邀请所有的人来为项目贡献自己的力量。“数千个电子邮件、数百场会议、几十种理念,以及之后的三轮讨究,我们把自己的想法都分享了出来。”但是,他们仍然遵循指导方针进行,还需要你参与到贡献中来。
|
||||
|
||||
#### Firefox
|
||||
|
||||
![Firefox logo](https://opensource.com/sites/default/files/firefox_0.png "Firefox logo")
|
||||
|
||||
[Firefox][8] 是 Mozilla 开发的一款旗舰级软件产品,是一个非常受欢迎的 [web 浏览器][9]。
|
||||
|
||||
Firefox 中的 "fox" 实际上是一只红色的熊猫,这是一种中国本土的像猫一样的真实动物。故事是这样的:Firefox 原本有个 "Phoenix" 的别称,表明它是由 Netscape 浏览器发展而来的。但在经历了 Phoenix 科技的商标起诉之后,它更名为 Mozilla Firebird。然后,Firebird RDMS 项目说它给其自己项目带来了歧义,其名称最终在 2004 年 02 月变更为 Mozilla Firefox。
|
||||
|
||||
平面设计师 Steve Garrity 对 Firefox 和 Phoenix 早期的 Logo 作出了批评,在“[品牌化 Mozilla:走向 Mozilla 2.0][10] ”一文中详细阐述了各种缺陷。所以,Mozilla 邀请 Garrity 来领导更好的品牌化工作。新的形象是由 silverorange 开发出来的,但最终的渲染却是 Jon Hicks 完成的,他同时也为 Camino、MailChimp 和 Opera 进行过品牌化工作。
|
||||
|
||||
早在 2013 年,[Jeopardy!][11] 上边关于询问 Firefox 使用哪个动物做 Logo 的帖子则成了最后的线索。三位回答者都不知道答案就是一个红色熊猫,而是回答了 “su”、 “raccoon” 和 “Excel”。
|
||||
|
||||
#### GIMP
|
||||
|
||||
![Wilber the Gimp logo](https://opensource.com/sites/default/files/resize/gimp-300x300.png "Wilber the Gimp logo")
|
||||
|
||||
GIMP 的 Logo 是由 Tuomas Kuosmanen 在 1997 年 09 月 25 日创建的 [Wilber the GIMP][12]。
|
||||
|
||||
GIMP 是 GNU 图像处理程序(GNU Image Manipulation Program)的缩写,主要用于相片修整和图像处理。Wilber 现在已经有了一些配饰,比如 Simon Budig 设计的一顶安全帽、Raphaël Quintet 设计的巫师帽。根据 GIMP 的“[链接到我们][13]” 页面,它高度鼓励人们使用 Wilber,你甚至可以在源代码中的 `/docs/Wilber_Construction_Kit.xcf.gz` 获得 Wilber 的构建素材。
|
||||
|
||||
那么,Wilber 到底是那一种生物呢?很显然,这是一个值得热烈讨论的问题。在 [gimper.net][14] 上的一个论坛众说纷纭:一种产于北美大草原的小狼(coyote)、熊猫、狗,或者“高飞”(Goofy)的一种衍生形象,仅举几例。而 [GimpChat.com][15] 上一位叫做 TheWarrior 的用户直接发邮件给 Wilber 的创造者 Kuosmanen,被告知说 “Wilber 是一种独立物种的动物 —— 就叫 ‘GIMP’。什么是 GIMP,这是个玩笑,因为人们一直在问,说它是一只狗、狐狸或者其他什么的就太没意思了。我设计的这一个形象的时候,在我脑袋中并没有特定哪种动物原型。”
|
||||
|
||||
#### PostgreSQL
|
||||
|
||||
![PostgreSQL logo](https://opensource.com/sites/default/files/postgresql.png "PostgreSQL logo")
|
||||
|
||||
正如你所见和熟悉的一样,使用动物头像来做 Logo 非常普遍。
|
||||
|
||||
一只名为 [Slonik][16] 的大象就是 [PostgreSQL][17] 的 Logo 的一部分,这是一个开源的关系型数据库管理系统 (RDMS)。Patrycja Dybka 在 Vertabelo 上写过博文,解释了这一名称是由俄语单词的大象(slony)演化而来的。Oleg Bartunov 也说过,这个 Logo 是在一个[邮件讨论][18]中初步形成的。在讨论里,在费城圣约瑟夫大学的 David Yang 建议使用大象:“……但如果你想要一个动物头像的 Logo,那么使用某种大象如何? 毕竟就像阿加莎·克里斯蒂(侦探小说家 Agatha Christie)说的那样,_大象让人印象深刻_。”
|
||||
|
||||
#### VLC 媒体播放器
|
||||
|
||||
![VLC logo](https://opensource.com/sites/default/files/resize/vlc-300x340.png "VLC logo")
|
||||
|
||||
该 Logo 不再是动物主题了,而是交通锥筒。
|
||||
|
||||
VLC 是一款无处不在的媒体播放器,它神奇地出现在很多人的桌面电脑上,让很多人体验到了开源,即使不知道它是开源的。VLC 是由总部在法国的 VideoLAN 组织所支持的 VideoLAN 项目的一款产品。VideoLAN 源自 1996 年在法国中央理工大学的一个学生项目。根据维基百科的描述,这个交通锥标图标参考了由法国中央理工大学的网络学生协会收集自巴黎街道上的交通锥筒。最初的手绘 Logo 在 2006 年由 Richard Oistad 重新进行了渲染。
|
||||
|
||||
一些有趣的花絮:
|
||||
|
||||
* Seamus Islwyn 的帖子 “[VLC 中的交通锥表达了哪些含义?][1]” 告诉我们:在十二月的时候,VLC 锥筒会戴着一顶圣诞帽,但在 12 月 31 日它就会消失不见,恢复原样的锥筒。
|
||||
* 有人说,VLC 的意思是 “非常大的锥筒(Very Large Cone)” 或者选用它仅仅是为了和法国那些交通锥筒相关联而已。
|
||||
* “官方” 的故事背景是否准确?在 VLC 的 jean-baptiste Kempf 和用户在 [VideoLAN 论坛][2] 上的交流似乎表明,交通锥筒收集说法以及漏斗、建筑区、扩音器和其他一些说法,可能是不正确的。
|
||||
|
||||
我们是否完全解答了 VLC 的交通锥筒起源的问题了呢?我个人觉得:那就是 “星期六夜现场” 的尖头外星人。他们就是来自法国的,记得吗?确切地说是来自 Remulak 星球。
|
||||
|
||||
**我很期待看到你关于自己喜欢、讨厌以及为它所代表的品牌而倍感激动的那些开源 Logo 的评论。**
|
||||
|
||||
(题图:opensource.com)
|
||||
|
||||
------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jeff Macharyas - 他有多年的出版和印刷工作经验,他曾担任过快速印刷、美国观察家、USO 巡逻、今天校园和其他出版物的艺术总监以及项目经理、编辑和发行经理。杰夫持有佛罗里达州立大学的通信信息、罗格斯大学的社会媒体营销研究生证书以及 Utica 学院的网络安全与计算机取证硕士学位。
|
||||
|
||||
------------
|
||||
|
||||
译者简介:
|
||||
|
||||
[GHLandy](http://ghlandy.com) —— 另一种生活中,有属于你也适合你的舞台。或许有你狠心放弃的专业,或者不必上妆,不用摆出另外一副面孔。—— 摘自林特特《以自己喜欢的方式过一生》
|
||||
|
||||
------
|
||||
|
||||
via: https://opensource.com/article/17/2/six-open-source-brands
|
||||
|
||||
作者:[Jeff Macharyas][a]
|
||||
译者:[GHLandy](https://github.com/GHLandy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/jeffmacharyas
|
||||
[1]:http://www.ehow.com/info_10029162_traffic-cone-mean-vlc.html
|
||||
[2]:https://forum.videolan.org/viewtopic.php?f=5&t=92513
|
||||
[3]:https://opensource.com/article/17/2/six-open-source-brands?rate=Lmf1lD4etve4Apqfhw3NUV3SeENsNXhGqTh8OO4PzzQ
|
||||
[4]:https://en.wikipedia.org/wiki/Tux
|
||||
[5]:https://www.mozilla.org/en-US/
|
||||
[6]:https://en.wikipedia.org/wiki/Mozilla
|
||||
[7]:https://blog.mozilla.org/opendesign/arrival/
|
||||
[8]:https://en.wikipedia.org/wiki/Firefox
|
||||
[9]:https://en.wikipedia.org/wiki/Web_browser
|
||||
[10]:http://actsofvolition.com/steven/mozillabranding/
|
||||
[11]:http://www.complex.com/pop-culture/2013/09/firefox-jeopardy-answer
|
||||
[12]:https://www.gimp.org/about/ancient_history.html
|
||||
[13]:https://www.gimp.org/about/linking.html
|
||||
[14]:https://gimper.net/threads/what-is-wilber.793/
|
||||
[15]:http://gimpchat.com/viewtopic.php?f=4&t=10265
|
||||
[16]:http://www.vertabelo.com/blog/notes-from-the-lab/the-history-of-slonik-the-postgresql-elephant-logo
|
||||
[17]:https://wiki.postgresql.org/wiki/Logo
|
||||
[18]:http://www.pgsql.ru/db/mw/msg.html?mid=1238939
|
||||
[19]:https://opensource.com/user/83821/feed
|
||||
[20]:https://opensource.com/article/17/2/six-open-source-brands#comments
|
||||
[21]:https://opensource.com/users/jeffmacharyas
|
@ -0,0 +1,64 @@
|
||||
教职人员是否可以运用维基百科教学?
|
||||
============
|
||||
|
||||
![Can academic faculty members teach with Wikipedia?](https://camo.githubusercontent.com/47dfe3fec215387fa7bb1f2c038f4e78e0e2e47d/68747470733a2f2f6f70656e736f757263652e636f6d2f73697465732f64656661756c742f66696c65732f7374796c65732f696d6167652d66756c6c2d73697a652f7075626c69632f696d616765732f656475636174696f6e2f4544555f61636164656d6963735f353230783239325f6d612e706e673f69746f6b3d397846574f637436)
|
||||
|
||||
图片来自 : opensource.com
|
||||
|
||||
自从 2010 年,已经有 29000 个学生完成了 Wiki Ed 这一项目。他们在维基百科上添加了 2500 万词条,相当于 85000 页纸张的内容。这相当于最新出版的 Britannica 百科全书中全部词条的 66%。Wiki Ed 的学生们最积极的时候,他们贡献了维基百科上 10% 的内容, 极大地补充了贫乏的学术板块。
|
||||
|
||||
为了了解更多关于这个项目的信息,我联络了 LiAnna Davis -- Wiki Ed 项目的负责人。他极富热情地同意来回答我的问题。
|
||||
|
||||
提示:[Wiki 教育基金会 (Wiki Ed)](https://wikiedu.org/) 的平台是用自由软件搭建的,你可以在这里找到: [WikiEdu Dashboard GitHub](https://github.com/WikiEducationFoundation/WikiEduDashboard)。
|
||||
|
||||
**Wiki Ed 这一项目是如何启动的?说说你的背景以及你是如何参与进这个项目的。**
|
||||
|
||||
在2010年,[维基基金会](https://wikimediafoundation.org/wiki/Home)(简称 WMF,运营维基百科的非营利组织)注意到了一个趋势 -- 大学的教职人员如果本身也是维基词条的编辑者,会成功地将编辑维基词条作为一项任务交给了自己课堂里的学生。WMF 就此开展了一个试行项目试图解决这个问题:如果本身不编辑维基词条的教职人员支持课程中包含维基词条的编辑任务,他们是否可以通过维基百科实现教学呢?
|
||||
|
||||
我是这个团队的一员,在 2010 年被试行雇用,我对这个问题的回答是:“可以。” 在 2013年,WMF 将这个项目的美国分部和加拿大分部拆分,形成了一个新的非营利性组织 -- 维基教育基金会( Wiki Ed);自此我也从 WMF 到了Wiki Ed。自那以后我们便成为了一个独立组织,我们可以专注于这个项目并且将这个项目拓展开来 -- 起初 WMF 时期每年只有 75 个班级参与,而这个学期已经有 275 班级参与了 Wiki Ed。
|
||||
|
||||
**人们总是觉得大学生对科技相关的一切事物都很敏感,尤其是互联网,但是你们的网站上写道,“大学本科学生可能具有高科技敏感度,但这并不代表他们具有数字信息素养。” 你可以稍微解释一下这句话吗?**
|
||||
|
||||
仅仅因为一个人可以搞明白自己的 iPhone 如何使用不代表他们可以明辨他们在网上阅读的信息是否值得信赖。 [斯坦福的一项研究](https://sheg.stanford.edu/upload/V3LessonPlans/Executive%20Summary%2011.21.16.pdf) (“评估信息:公民在线推理的基石 November 22, 2016.”)在近期表明:学生们并不具有数字信息素养。然而,当学生们在撰写维基百科文章之时,他们必须这样。他们需要严格遵守维基百科的[可信来源](https://en.wikipedia.org/wiki/Wikipedia:Identifying_reliable_sources) 规范,这些规范明确了维基百科上的任何信息都必须注明来源,这些来源必须是独立的,而且是可以追溯的事实。对于很多学生,这样注明来源还是第一次,多数人之前仅仅是通过谷歌搜索话题或者注明他们亲眼所见的第一手资料来进行资料的检索和查证。他们需要理解哪些资料可靠,哪些资料不可靠,从而成为足够成熟的电子信息消费者。
|
||||
|
||||
**你想对那些声称“维基百科不是一个可靠的来源”的人说些什么?**
|
||||
|
||||
维基百科是一本百科全书,根据在词典中的定义,它是一个第三手资料。当学生们开始读本科的时候,他们应该学会参考一手和二手资料,而不是第三手资料,因此学生不应该,且不能引用维基百科的内容。但是维基百科在研究之初会是一个不错的选择,它可以给你对这个话题一个广泛的认识,并且帮你发现页面底部那些你可以参考的文章来源。就像我们所鼓励的:“不要引用!用你的语言写!”
|
||||
|
||||
> 这样做可以让学生们代入知识生产者的身份,而不是知识的消费者……
|
||||
|
||||
**一个教授在 Wiki Ed 项目中的参与是如何影响到他的学生的呢?**
|
||||
|
||||
通过运用维基百科教学,导师们可以给学生们提供有价值的媒体素养、批判性思维、线上交流以及写作能力,不论他们在毕业之后会继续选择科研或是加入工作大军,这些极富价值的品质和技能都能帮助他们成功。这样做可以让学生们代入知识生产者的身份,而不是知识的消费者,而且这可以给予他们一个真正在这个世界做出改变的机会,而不是学生们到了学期末便会抛之脑后的生硬习题。
|
||||
|
||||
我们正在积极鼓励新的班级在春季学期加入这个项目。感兴趣的教职人员可以点击 [维基教育基金会的教学页](https://teach.wikiedu.org/) 由此开始。
|
||||
|
||||
**一个教师会需要哪些职业素养来参与这个项目?学生又是需要哪些训练呢?**
|
||||
|
||||
当你在[维基教育基金会的教学页](http://teach.wikiedu.org/)上注册的时候,你会发现 Wiki Ed 为新加入的教职人员提供了如何运用维基百科实现教学的在线指南。我们还有为学生提供的一系列的在线训练,根据他们不同的任务自动分配不同的指南(例如,如果你希望你的学生在文章中插入图片,他们会得到一个如何插入编辑图片的教学单元,如果你不需要,他们便不会得到这个单元的指南)。在部分十几个学科中,我们还有特定的指南书展示了这几个学科的特定编辑方式。除此之外,我们还有熟练维基百科编辑的工作人员帮助回答学生和导师们的问题。我们的系统已经在逐步扩大;我们在这个秋季学期已经支持了超过 6300 个学生,并且已经适应了与没有维基编辑经验的教职人员合作,因此这样就保证了没有人会因为资历不够而无法参与。
|
||||
|
||||
**“<ruby>访问学者<rt>Visiting Scholars</rt></ruby>”这个项目是指?**
|
||||
|
||||
我们正在试着建立学术界和维基百科之间的联系,而鼓励运用维基百科教学的项目只是其中的一环。在“<ruby>访问学者<rt>Visiting Scholars</rt></ruby>”这一项目中,大学图书馆或者教学部门将公开他们的资料,并提供给一个缺乏资料的认证的维基百科编辑人员(被称作是“访问学者”)。通过大学这一渠道,“访问学者”们可以有机会使用这些资源来完善维基百科广泛领域中的文章。这是一个规模相对小却伟大的项目,因为我们花了很多时间来建立这样的联系,但是这些“学者”们都产出了许多真的很精彩的内容。
|
||||
|
||||
**你的合作伙伴有谁?他们的参与如何影响到你现在的成功呢,或者在未来将会如何呢?**
|
||||
|
||||
我们与那些将我们工作的价值看做对他们的学科的一种服务的学术机构合作。让我们面对这个现实:当人们想要获取关于一个话题的知识之时,他们不会去读那些同行审议过,并在这些机构发表的学术论文,他们会去维基百科。通过鼓励这些机构中的教职人员用维基百科教学,正可以完善维基百科的在这些学科中的内容和信息。我们的合作伙伴扩充了我们的潜在成员,并且让我们以合作身份大量完善了维基百科上特定学科的内容。
|
||||
|
||||
我们欢迎读者点击这个[支持我们](http://wikiedu.org/donate) 的页面通过捐赠来支持我们的工作。
|
||||
|
||||
***
|
||||
|
||||
作者简介:
|
||||
|
||||
Don Watkins 是一个教育家,专注教育技术,创业家,开源提倡者。教育心理学硕士、教育领导力硕士、Linux 系统管理员、思科认证网络支持工程师、Virtual Box 虚拟化认证。关注他: @Don_Watkins 。
|
||||
|
||||
----
|
||||
|
||||
via: https://opensource.com/article/17/1/Wiki-Education-Foundation
|
||||
|
||||
作者:Don Watkins
|
||||
译者:[scoutydren](https://github.com/scoutydren)
|
||||
校对:[Bestony](https://github.com/Bestony)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](http://linux.cn/) 荣誉推出
|
@ -0,0 +1,78 @@
|
||||
Linux 让我对电脑有了更深刻的理解
|
||||
============================================================
|
||||
|
||||
![投身-Linux](http://www.linuxinsider.com/article_images/story_graphics_xlarge/xl-2016-linux-1.jpg)
|
||||
|
||||
|
||||
我花了大量时间和耐心在 Linux 上,我的朋友们都能为我证明这点。说起来你可能不信,两年前我还根本不知道 Linux 是什么,放弃 Windows 转投 Linux 更是不可能。
|
||||
|
||||
虽然转投 Linux 这事有点跳跃,但事后证明这是很明智的选择。口说无凭,分析一下我的路线可能会更有说服力一点。通过这个路线来说说我是怎么从小白到精通 Linux 桌面系统的。
|
||||
|
||||
### 安全意识的觉醒
|
||||
|
||||
两年前我也是像一般的 Windows 用户一样,在 Windows 操作系统下工作。虽然我也有跟进了解主流的科技新闻的习惯,但是对计算机我也说不上深刻了解。
|
||||
|
||||
2013 年夏天,美国国家安全局的一份情报项目报告让我对个人隐私安全的态度迅速发生了变化。爱德华斯诺登揭露的网络监控的广度令人不安,而且也凸显出,我们大多数人——甚至不知道如何做——来保护自己的隐私。
|
||||
|
||||
在之前我没有对电脑或它们在我的个人事务中所扮演的角色作出任何特别的考虑,我开始意识到控制一个人的数字生活,以及控制它的设备的重要性。
|
||||
|
||||
按理来说下一步应该是确定该怎么去做。虽然我制订的目标似乎是合乎逻辑的,但要实现它并不简单。在接下来的几个月里,我把自己的空闲时间花在了互联网上,寻找关于隐私保护、加密以及其它任何可以保护我的技术的指南。
|
||||
|
||||
专家们说想逃避情报机构的监控几乎是不可能的。然而,这些专家们也会告诉你,能帮你避开那怕只是避开那么一丢丢的监视 -- 在较小的机构中有相当比例的监控更有可能针对普通民众 -- 唯一可行的办法就是使用开源软件。
|
||||
|
||||
Linux,我很快意识到需要去了解它,因为它是这些开源软件的头头。
|
||||
|
||||
### 闭源与开源
|
||||
|
||||
在进一步的研究中,我开始熟悉开源软件的一些特点。我们每天使用的软件的绝大多数 -- 从聊天软件到操作系统,包括Windows -- 它们都是开源软件的对立面:它们是闭源的。
|
||||
|
||||
例如,当微软的开发人员在 Windows 上进行开发工作时,他们会用一些编程语言编写源代码,并且只在他们的团队内部流传这些代码。当他们准备发布软件时,他们会编译它,将它从人类可读的代码转换成计算机运行的 1 和 0,面对这些机器码,即使是最聪明的人也很难逆向工程到原始源代码。
|
||||
|
||||
在这种模式下,只有软件的开发者才知道这些软件实际在做些什么,有没有私底下监控用户行为。
|
||||
|
||||
开源软件会提供软件的源代码和编译好的二进制代码给公众下载使用。不论是不是每个用户都有能力去阅读这些源代码,评估它们的安全性和隐私性,这都不重要。因为源代码是公开的,总有那么一部分人有这个能力做这些事,一但他们发现这些代码有问题他们就能及时通知其它用户,让公众一起来监督这些开源软件的行为,让那些故意隐藏的恶意代码片段或者非故意的代码漏洞能及时被发现并处理掉。
|
||||
|
||||
经过彻底的研究之后,很明显,唯一能保证我的隐私和用户的自主权的操作系统就是那些具备透明开放的源代码哲学的操作系统。一位知识渊博的朋友和隐私倡导者推荐的最多的是 Linux。如果这是必须的话,我已经准备好接受一个艰难的过渡,但是我对隐私的重要性的信念给了我信心去尝试。
|
||||
|
||||
### 婴儿学步
|
||||
|
||||
虽然我决心转向 Linux 的是急切的,但饭得一口吃,路也得一步一步走。我是最开始是从安装 Ubuntu 开始的 —— 一个容易配置对初学者很友好的 Linux 发行版 —— 在我的老笔记本电脑上它与原有的 Windows 相处融洽井水不犯河水。
|
||||
|
||||
每次启动我的电脑时,我都能选择 Ubuntu 或 Windows ,这样我就能在 Linux 上找到自己的下脚点,同时保留熟悉的 Windows 以防前者可能缺失的一些辅助性功能。
|
||||
|
||||
不久后,一个硬盘驱动器损坏严重让我无法再继续享受这个设置,不过我认为这是一个机会,让我考虑一下买一台 Linux 的新笔记本电脑。由于 Linux 对标准的英特尔处理器、图形卡和无线适配器的驱动程序支持得很好,所以我买了一台联想的 ThinkPad。
|
||||
|
||||
我做了一个全新的开始,完全擦除我的新机器上的 Windows ,安装了 Debian ,这是一个广泛兼容和稳定的发行版,Ubuntu 就是基于它衍生出来的。我不仅在没有熟悉的 Windows 安全网络的情况下挺过来了,我还在不断的进步提高。我很快就沉浸在以前神秘的命令行世界里。
|
||||
|
||||
在我用了一年的 Linux 操作系统之后,我又进行了一次冒险,安装了 Arch Linux ,它需要一个更加复杂的手动用户安装过程,并带有完全的磁盘加密。那天晚上,我和一位 Linux 资深管理人士一起安装了 Arch ,这标志着我生命中最值得骄傲的成就之一。
|
||||
|
||||
在这个过程中,我面临着挑战 -- 有时,在Windows上无缝工作的应用程序需要额外的步骤或需要安装必要的驱动 -- 但是我克服了它们,或者说绕过它们,继续按照我自己的节奏摸索 Linux。
|
||||
|
||||
### 全速前进
|
||||
|
||||
就我而言,那时我才真正开始进行我的学习。我用 Linux 来驾驭计算机,并确保它可以为我工作,不过最让我着迷的是它提供对系统进行修改的自由和个性化处理。
|
||||
|
||||
作为一个开源操作系统,Linux 是无限开放的。尽管我最初期望花时间阅读安全实践(我现在仍然这么做),但我也发现自己深入到配置面板中,并把所有的颜色、图标和菜单都列出来,只是这样而已。
|
||||
|
||||
我花了一些时间去适应,但我越是投入到新事物中,我就变得越自信,越好奇。
|
||||
|
||||
自从在这条路上走了两年多以后,我在电脑上从来没有像今天这么多的感受。我不能像我想要的那样去个性化 Windows,另外依据我从开源社区学到的东西来看,我也不能完全信任它。
|
||||
|
||||
有一个叫电脑的东西,它曾经只是我的的一件不起眼的硬件设备,现在它和我之间的关系变得非常美妙 —— 超越记者和他的笔记本、也超越小提琴家和他的小提琴的关系。
|
||||
|
||||
我甚至为自己的手机不像我的笔记本电脑那样是真正的 Linux 而感到悲哀,我都不知道我能对它做些什么。不管怎么样,我将继续对我的 Arch 系统进行优化,只要有机会我将会再去发现新的领域并探索新的可能性。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.linuxinsider.com/story/84286.html
|
||||
|
||||
作者:[Jonathan Terrasi][a]
|
||||
译者:[zschong](https://github.com/zschong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.linkedin.com/company/ect-news-network
|
||||
[1]:http://www.linuxinsider.com/story/84286.html?rss=1#
|
||||
[2]:http://www.linuxinsider.com/perl/mailit/?id=84286
|
@ -1,102 +1,101 @@
|
||||
How to install OTRS (OpenSource Trouble Ticket System) on Ubuntu 16.04
|
||||
如何在 Ubuntu 16.04 上安装 OTRS (开源问题单系统)
|
||||
============================================================
|
||||
|
||||
|
||||
### On this page
|
||||
OTRS ,及开源问题单(ticket)申请系统是一个用于客户服务、帮助台和 IT 服务管理的开源问题单软件。该软件是用 Perl 和 javascript 编写的。对于那些需要管理票据、投诉、支持请求或其他类型的报告的公司和组织来说,这是一个问题单解决方案。OTRS 支持包括 MySQL、PostgreSQL、Oracle 和 SQL Server 在内的多个数据库系统,它是一个可以安装在 Windows 和 Linux 上的多平台软件。
|
||||
|
||||
1. [Step 1 - Install Apache and PostgreSQL][1]
|
||||
2. [Step 2 - Install Perl Modules][2]
|
||||
3. [Step 3 - Create New User for OTRS][3]
|
||||
4. [Step 4 - Create and Configure the Database][4]
|
||||
5. [Step 5 - Download and Configure OTRS][5]
|
||||
6. [Step 6 - Import the Sample Database][6]
|
||||
7. [Step 7 - Start OTRS][7]
|
||||
8. [Step 8 - Configure OTRS Cronjob][8]
|
||||
9. [Step 9 - Testing OTRS][9]
|
||||
10. [Step 10 - Troubleshooting][10]
|
||||
11. [Reference][11]
|
||||
在本教程中,我将介绍如何在 Ubuntu 16.04 上安装和配置 OTRS。我将使用 PostgreSQL 作为 OTRS 的数据库,将 Apache Web 服务器用作 Web 服务器。
|
||||
|
||||
OTRS or Open-source Ticket Request System is an open source ticketing software used for Customer Service, Help Desk, and IT Service Management. The software is written in Perl and javascript. It is a ticketing solution for companies and organizations that have to manage tickets, complaints, support request or other kinds of reports. OTRS supports several database systems including MySQL, PostgreSQL, Oracle and SQL Server it is a multiplatform software that can be installed on Windows and Linux.
|
||||
**先决条件**
|
||||
|
||||
In this tutorial, I will show you how to install and configure OTRS on Ubuntu 16.04\. I will use PostgreSQL as the database for OTRS, and Apache web server as the web server.
|
||||
* Ubuntu 16.04。
|
||||
* 最小 2GB 的内存。
|
||||
* root 权限
|
||||
|
||||
**Prerequisites**
|
||||
### 步骤 1 - 安装 Apache 和 PostgreSQL
|
||||
|
||||
* Ubuntu 16.04.
|
||||
* Min 2GB of Memory.
|
||||
* Root privileges.
|
||||
在第一步中,我们将安装 Apache Web 服务器以及 PostgreSQL。我们将从 ubuntu 仓库中使用最新的版本。
|
||||
|
||||
### Step 1 - Install Apache and PostgreSQL
|
||||
使用 SSH 登录到你的 Ubuntu 服务器中:
|
||||
|
||||
In this first step, we will install the Apache web server and PostgreSQL. We will use the latest versions from the ubuntu repository.
|
||||
```
|
||||
ssh root@192.168.33.14
|
||||
```
|
||||
|
||||
Login to your Ubuntu server with SSH:
|
||||
更新 Ubuntu 仓库。
|
||||
|
||||
`ssh root@192.168.33.14`
|
||||
```
|
||||
sudo apt-get update
|
||||
```
|
||||
|
||||
Update Ubuntu repository.
|
||||
使用 apt 安装 Apache2 以及 PostgreSQL:
|
||||
|
||||
`sudo apt-get update`
|
||||
```
|
||||
sudo apt-get install -y apache2 libapache2-mod-perl2 postgresql
|
||||
```
|
||||
|
||||
Install Apache2 and a PostgreSQL with the apt:
|
||||
通过检查服务器端口确保 Apache 以及 PostgreSQL 运行了。
|
||||
|
||||
`sudo apt-get install -y apache2 libapache2-mod-perl2 postgresql`
|
||||
|
||||
Then make sure that Apache and PostgreSQL are running by checking the server port.
|
||||
|
||||
`netstat -plntu`
|
||||
```
|
||||
netstat -plntu
|
||||
```
|
||||
|
||||
[
|
||||
![Install Apache and PostgreSQL](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/1.png)
|
||||
][17]
|
||||
|
||||
You will see port 80 is used by apache, and port 5432 used by postgresql database.
|
||||
你可以看到 80 端口被 apache 使用了,5432 端口被 postgresql 数据库使用了。
|
||||
|
||||
### Step 2 - Install Perl Modules
|
||||
### 步骤 2 - 安装 Perl 模块
|
||||
|
||||
OTRS is based on Perl, so we need to install some Perl modules that are required by OTRS.
|
||||
OTRS 基于 Perl,因此我们需要安装一些 OTRS 需要的 Perl 模块。
|
||||
|
||||
Install perl modules for OTRS with this apt command:
|
||||
使用这个 apt 命令安装 perl 模块:
|
||||
|
||||
```
|
||||
sudo apt-get install -y libapache2-mod-perl2 libdbd-pg-perl libnet-dns-perl libnet-ldap-perl libio-socket-ssl-perl libpdf-api2-perl libsoap-lite-perl libgd-text-perl libgd-graph-perl libapache-dbi-perl libarchive-zip-perl libcrypt-eksblowfish-perl libcrypt-ssleay-perl libencode-hanextra-perl libjson-xs-perl libmail-imapclient-perl libtemplate-perl libtemplate-perl libtext-csv-xs-perl libxml-libxml-perl libxml-libxslt-perl libpdf-api2-simple-perl libyaml-libyaml-perl
|
||||
```
|
||||
|
||||
When the installation is finished, we need to activate the Perl module for apache, then restart the apache service.
|
||||
安装完成后,我们需要为 apache 激活 Perl 模块,接着重启 apache 服务。
|
||||
|
||||
```
|
||||
a2enmod perl
|
||||
systemctl restart apache2
|
||||
```
|
||||
|
||||
Next, check the apache module is loaded with the command below:
|
||||
接下来,使用下面的命令检查模块是否已经加载了:
|
||||
|
||||
`apachectl -M | sort`
|
||||
```
|
||||
apachectl -M | sort
|
||||
```
|
||||
|
||||
[
|
||||
![Enable Apache Perl Module](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/2.png)
|
||||
][18]
|
||||
|
||||
And you will see **perl_module** under 'Loaded Modules' section.
|
||||
你可以在 “Loaded Modules” 部分下看到 **perl_module**。
|
||||
|
||||
### Step 3 - Create New User for OTRS
|
||||
### 步骤 3 - 为 OTRS 创建新用户
|
||||
|
||||
OTRS is a web based application and running under the apache web server. For best security, we need to run it under a normal user, not the root user.
|
||||
OTRS 是一个基于 web 的程序并且运行与 apache web 服务器下。为了安全,我们需要以普通用户运行它,而不是 root 用户。
|
||||
|
||||
Create a new user named 'otrs' with the useradd command below:
|
||||
使用 useradd 命令创建一个 `otrs` 新用户:
|
||||
|
||||
```
|
||||
useradd -r -d /opt/otrs -c 'OTRS User' otrs
|
||||
|
||||
**-r**: make the user as a system account.
|
||||
**-d /opt/otrs**: define home directory for new user on '/opt/otrs'.
|
||||
**-c**: comment.
|
||||
```
|
||||
|
||||
Next, add the otrs user to 'www-data' group, because apache is running under 'www-data' user and group.
|
||||
* `-r`:将用户作为系统用户。
|
||||
* `-d /opt/otrs`:在 `/opt/otrs` 下放置新用户的主目录。
|
||||
* `-c`:备注。
|
||||
|
||||
`usermod -a -G www-data otrs`
|
||||
接下来,将 `otrs` 用户加入到 `www-data` 用户组,因为 apache 运行于 `www-data` 用户及用户组。
|
||||
|
||||
Check that the otrs user is available in the '/etc/passwd' file.
|
||||
```
|
||||
usermod -a -G www-data otrs
|
||||
```
|
||||
|
||||
在 `/etc/passwd` 文件中已经有 `otrs` 用户了。
|
||||
|
||||
```
|
||||
grep -rin otrs /etc/passwd
|
||||
@ -106,74 +105,76 @@ grep -rin otrs /etc/passwd
|
||||
![Create new user for OTRS](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/3.png)
|
||||
][19]
|
||||
|
||||
New user for OTRS is created.
|
||||
OTRS 的新用户已经创建了。
|
||||
|
||||
### Step 4 - Create and Configure the Database
|
||||
### 步骤 4 - 创建和配置数据库
|
||||
|
||||
In this section, we will create a new PostgreSQL database for the OTRS system and make some small changes in PostgreSQL database configuration.
|
||||
在这节中,我们会为 OTRS 系统创建一个新 PostgreSQL 数据库,并对 PostgreSQL 数据库的配置做一些小的更改。
|
||||
|
||||
Login to the **postgres** user and access the PostgreSQL shell.
|
||||
登录到 `postgres` 用户并访问 PostgreSQL shell。
|
||||
|
||||
```
|
||||
su - postgres
|
||||
psql
|
||||
```
|
||||
|
||||
Create a new role named '**otrs**' with the password '**myotrspw**' and the nosuperuser option.
|
||||
创建一个新的角色 `otrs`,密码是 `myotrspw`,并且是非特权用户。
|
||||
|
||||
```
|
||||
create user otrs password 'myotrspw' nosuperuser;
|
||||
```
|
||||
|
||||
Then create a new database named '**otrs**' under the '**otrs**' user privileges:
|
||||
接着使用 `otrs` 用户权限创建一个新的 `otrs` 数据库:
|
||||
|
||||
```
|
||||
create database otrs owner otrs;
|
||||
\q
|
||||
```
|
||||
|
||||
Next, edit the PostgreSQL configuration file for otrs role authentication.
|
||||
接下来为 `otrs` 角色验证编辑 PostgreSQL 配置文件。
|
||||
|
||||
```
|
||||
vim /etc/postgresql/9.5/main/pg_hba.conf
|
||||
```
|
||||
|
||||
Paste the cConfiguration below after line 84:
|
||||
在 84 行后粘贴下面的配置:
|
||||
|
||||
```
|
||||
local otrs otrs password
|
||||
host otrs otrs 127.0.0.1/32 password
|
||||
```
|
||||
|
||||
Save the file and exit vim.
|
||||
保存文件并退出 vim
|
||||
|
||||
[
|
||||
![Database Authentication OTRS](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/4.png)
|
||||
][20]
|
||||
|
||||
Back to the root privileges with "exit" and restart PostgreSQL:
|
||||
使用 `exit` 回到 root 权限并重启 PostgreSQL:
|
||||
|
||||
```
|
||||
exit
|
||||
systemctl restart postgresql
|
||||
```
|
||||
|
||||
PostgreSQL is ready for the OTRS installation.
|
||||
PostgreSQL 已经为 OTRS 的安装准备好了。
|
||||
|
||||
[
|
||||
![Configure PostgreSQL for OTRS](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/5.png)
|
||||
][21]
|
||||
|
||||
### Step 5 - Download and Configure OTRS
|
||||
### 步骤 5 - 下载和配置 OTRS
|
||||
|
||||
In this tutorial, we will use the latest OTRS version that is available on the OTRS web site.
|
||||
在本教程中,我们会使用 OTRS 网站中最新的版本。
|
||||
|
||||
Go to the '/opt' directory and download OTRS 5.0 with the wget command:
|
||||
进入 `/opt` 目录并使用 `wget` 命令下载 OTRS 5.0:
|
||||
|
||||
```
|
||||
cd /opt/
|
||||
wget http://ftp.otrs.org/pub/otrs/otrs-5.0.16.tar.gz
|
||||
```
|
||||
|
||||
Extract the otrs file, rename the directory and change owner of all otrs files and directories the 'otrs' user.
|
||||
展开该 otrs 文件,重命名目录并更改所有 otrs 的文件和目录的所属人为 `otrs`。
|
||||
|
||||
```
|
||||
tar -xzvf otrs-5.0.16.tar.gz
|
||||
@ -181,60 +182,62 @@ mv otrs-5.0.16 otrs
|
||||
chown -R otrs:otrs otrs
|
||||
```
|
||||
|
||||
Next, we need to check the system and make sure it's ready for OTRS installation.
|
||||
接下来,我们需要检查系统并确保可以安装 OTRS 了。
|
||||
|
||||
Check system packages for OTRS installation with the otrs script command below:
|
||||
使用下面的 otrs 脚本命令检查 OTRS 安装需要的系统软件包:
|
||||
|
||||
```
|
||||
/opt/otrs/bin/otrs.CheckModules.pl
|
||||
```
|
||||
|
||||
Make sure all results are ok, it means is our server ready for OTRS.
|
||||
确保所有的结果是对的,这意味着我们的服务器可以安装 OTRS 了。
|
||||
|
||||
[
|
||||
![OTRS Chek Module needed for Installation](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/6.png)
|
||||
][22]
|
||||
|
||||
OTRS is downloaded, and our server is ready for the OTRS installation.
|
||||
OTRS 已下载,并且我们的服务器可以安装 OTRS 了。
|
||||
|
||||
Next, go to the otrs directory and copy the configuration file.
|
||||
接下,进入 otrs 目录并复制配置文件。
|
||||
|
||||
```
|
||||
cd /opt/otrs/
|
||||
cp Kernel/Config.pm.dist Kernel/Config.pm
|
||||
```
|
||||
|
||||
Edit 'Config.pm' file with vim:
|
||||
使用 vim 编辑 `Config.pm` 文件:
|
||||
|
||||
```
|
||||
vim Kernel/Config.pm
|
||||
```
|
||||
|
||||
Change the database password line 42:
|
||||
更改 42 行的数据库密码:
|
||||
|
||||
```
|
||||
$Self->{DatabasePw} = 'myotrspw';
|
||||
```
|
||||
|
||||
Comment the MySQL database support line 45:
|
||||
注释 45 行的 MySQL 数据库支持:
|
||||
|
||||
```
|
||||
# $Self->{DatabaseDSN} = "DBI:mysql:database=$Self->{Database};host=$Self->{DatabaseHost};";
|
||||
```
|
||||
|
||||
Uncomment PostgreSQL database support line 49:
|
||||
取消注释 49 行的 PostgreSQL 数据库支持:
|
||||
|
||||
```
|
||||
$Self->{DatabaseDSN} = "DBI:Pg:dbname=$Self->{Database};";
|
||||
```
|
||||
|
||||
Save the file and exit vim.
|
||||
保存文件并退出 vim。
|
||||
|
||||
Then edit apache startup file to enable PostgreSQL support.
|
||||
接着编辑 apache 启动文件来启用 PostgreSQL 支持。
|
||||
|
||||
```
|
||||
vim scripts/apache2-perl-startup.pl
|
||||
```
|
||||
|
||||
Uncomment line 60 and 61:
|
||||
取消注释 60 和 61 行:
|
||||
|
||||
```
|
||||
# enable this if you use postgresql
|
||||
@ -242,9 +245,9 @@ use DBD::Pg ();
|
||||
use Kernel::System::DB::postgresql;
|
||||
```
|
||||
|
||||
Save the file and exit the editor.
|
||||
保存文件并退出编辑器。
|
||||
|
||||
Finally, check for any missing dependency and modules.
|
||||
最后,检查缺失的依赖和模块。
|
||||
|
||||
```
|
||||
perl -cw /opt/otrs/bin/cgi-bin/index.pl
|
||||
@ -252,23 +255,23 @@ perl -cw /opt/otrs/bin/cgi-bin/customer.pl
|
||||
perl -cw /opt/otrs/bin/otrs.Console.pl
|
||||
```
|
||||
|
||||
You should see that the result is '**OK**' asshown in the screenshot below:
|
||||
你可以在下面的截图中看到结果是 “**OK**”:
|
||||
|
||||
[
|
||||
![Check all modules again](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/7.png)
|
||||
][23]
|
||||
|
||||
### Step 6 - Import the Sample Database
|
||||
### 步骤 6 - 导入样本数据库
|
||||
|
||||
In this tutorial, we will use the sample database, it's available in the script directory. So we just need to import all sample databases and the schemes to the existing database created in step 4.
|
||||
在本教程中,我们会使用样本数据库,这可以在脚本目录中找到。因此我们只需要将所有的样本数据库以及表结构导入到第 4 步创建的数据库中。
|
||||
|
||||
Login to the postgres user and go to the otrs directory.
|
||||
登录到 `postgres` 用户并进入 otrs 目录中。
|
||||
|
||||
```
|
||||
su - postgres
|
||||
cd /opt/otrs/
|
||||
```
|
||||
Insert database and table scheme with psql command as otrs user.
|
||||
作为 otrs 用户使用 `psql` 命令插入数据库以及表结构。
|
||||
|
||||
```
|
||||
psql -U otrs -W -f scripts/database/otrs-schema.postgresql.sql otrs
|
||||
@ -276,46 +279,46 @@ psql -U otrs -W -f scripts/database/otrs-initial_insert.postgresql.sql otrs
|
||||
psql -U otrs -W -f scripts/database/otrs-schema-post.postgresql.sql otrs
|
||||
```
|
||||
|
||||
Type the database password '**myotrspw**' when requested.
|
||||
在需要的时候输入数据库密码 `myotrspw`。
|
||||
|
||||
[
|
||||
![Import OTRS Sample Database](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/8.png)
|
||||
][24]
|
||||
|
||||
### Step 7 - Start OTRS
|
||||
### 步骤 7 - 启动 OTRS
|
||||
|
||||
Database and OTRS are configured, now we can start OTRS.
|
||||
数据库以及 OTRS 已经配置了,现在我们可以启动 OTRS。
|
||||
|
||||
Set the permission of otrs file and directory to the www-data user and group.
|
||||
将 otrs 的文件及目录权限设置为 `www-data` 用户和用户组。
|
||||
|
||||
```
|
||||
/opt/otrs/bin/otrs.SetPermissions.pl --otrs-user=www-data --web-group=www-data
|
||||
```
|
||||
|
||||
Then enable the otrs apache configuration by creating a new symbolic link of the file to the apache virtual host directory.
|
||||
通过创建一个新的链接文件到 apache 虚拟主机目录中启用 otrs apache 配置。
|
||||
|
||||
```
|
||||
ln -s /opt/otrs/scripts/apache2-httpd.include.conf /etc/apache2/sites-available/otrs.conf
|
||||
```
|
||||
|
||||
Enable otrs virtual host and restart apache.
|
||||
启用 otrs 虚拟主机并重启 apache。
|
||||
|
||||
```
|
||||
a2ensite otrs
|
||||
systemctl restart apache2
|
||||
```
|
||||
|
||||
Make sure apache has no error.
|
||||
确保 apache 启动没有错误。
|
||||
|
||||
[
|
||||
![Enable OTRS Apache Virtual Host](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/9.png)
|
||||
][25]
|
||||
|
||||
### Step 8 - Configure OTRS Cronjob
|
||||
### 步骤 8 - 配置 OTRS 计划任务
|
||||
|
||||
OTRS is installed and now running under apache web server, but we still need to configure the OTRS Cronjob.
|
||||
OTRS 已经安装并运行在 Apache Web 服务器中了,但是我们仍然需要配置 OTRS 计划任务。
|
||||
|
||||
Login to the 'otrs' user, then go to the 'var/cron' directory as the otrs user.
|
||||
登录到 `otrs` 用户,接着以 otrs 用户进入 `var/cron` 目录。
|
||||
|
||||
```
|
||||
su - otrs
|
||||
@ -323,11 +326,13 @@ cd var/cron/
|
||||
pwd
|
||||
```
|
||||
|
||||
Copy all cronjob .dist scripts with the command below:
|
||||
使用下面的命令复制所有 `.dist` 计划任务脚本:
|
||||
|
||||
```
|
||||
for foo in *.dist; do cp $foo `basename $foo .dist`; done
|
||||
```
|
||||
|
||||
Back to the root privilege with exit and then start the cron script as otrs user.
|
||||
使用 `exit` 回到 root 权限,并使用 otrs 用户启动计划任务脚本。
|
||||
|
||||
```
|
||||
exit
|
||||
@ -338,22 +343,22 @@ exit
|
||||
![Enable OTRS Cron](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/10.png)
|
||||
][26]
|
||||
|
||||
Next, manually create a new cronjob for PostMaster which fetches the emails. I'll configure it tp fetch emails every 2 minutes.
|
||||
接下来,手动收取电子邮件的 PostMaster 创建一个新的计划任务。我会配置为每 2 分钟收取一次邮件。
|
||||
|
||||
```
|
||||
su - otrs
|
||||
crontab -e
|
||||
```
|
||||
|
||||
Paste the configuration below:
|
||||
粘贴下面的配置:
|
||||
|
||||
```
|
||||
*/2 * * * * $HOME/bin/otrs.PostMasterMailbox.pl >> /dev/null
|
||||
```
|
||||
|
||||
Save and exit.
|
||||
保存并退出。
|
||||
|
||||
Now stop otrs daemon and start it again.
|
||||
现在停止 otrs 守护进程并再次启动。
|
||||
|
||||
```
|
||||
bin/otrs.Daemon.pl stop
|
||||
@ -364,66 +369,63 @@ bin/otrs.Daemon.pl start
|
||||
![Enable OTRS Fetching Email](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/11.png)
|
||||
][27]
|
||||
|
||||
The OTRS installation and configuration is finished.
|
||||
OTRS 安装以及配置完成了。
|
||||
|
||||
### Step 9 - Testing OTRS
|
||||
### 步骤 9 - 测试 OTRS
|
||||
|
||||
Open your web browser and type in your server IP address:
|
||||
打开你的 web 浏览器并输入你的服务器 IP 地址: [http://192.168.33.14/otrs/][28]
|
||||
|
||||
[http://192.168.33.14/otrs/][28]
|
||||
|
||||
Login with default user '**root@localhost**' and password '**root**'.
|
||||
使用默认的用户 `root@localhost` 以及密码 `root` 登录。
|
||||
|
||||
[
|
||||
![Installation Successfully OTRS Home Page](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/12.png)
|
||||
][29]
|
||||
|
||||
You will see a warning about using default root account. Click on that warning message to create new admin root user.
|
||||
使用默认的 root 账户你会看到一个警告。点击警告信息来创建一个新的 admin root 用户。
|
||||
|
||||
Below the admin page after login with different admin root user, and there is no error message again.
|
||||
下面是用另外的 admin root 用户登录后出现的 admin 页面,这里没有出现错误信息。
|
||||
|
||||
[
|
||||
![OTRS Admin Dashboard Without Error Messages](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/13.png)
|
||||
][30]
|
||||
|
||||
If you want to log in as Customer, you can use 'customer.pl'.
|
||||
如果你想作为客户登录,你可以使用 `customer.pl` :[http://192.168.33.14/otrs/customer.pl][31]
|
||||
|
||||
[http://192.168.33.14/otrs/customer.pl][31]
|
||||
|
||||
You will see the customer login page. Type in a customer username and password.
|
||||
你会看到客户登录界面,输入客户的用户名和密码。
|
||||
|
||||
[
|
||||
![OTRS Customer Login Page](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/14.png)
|
||||
][32]
|
||||
|
||||
Below is the customer page for creating a new ticket.
|
||||
下面是一个创建新单据的客户页面。
|
||||
|
||||
[
|
||||
![Customer Open Ticket](https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/15.png)
|
||||
][33]
|
||||
|
||||
### Step 10 - Troubleshooting
|
||||
### 步骤 10 - 疑难排查
|
||||
|
||||
如果你仍旧看到 “OTRS Daemon is not running” 的错误,你可以像这样调试 OTRS 守护进程。
|
||||
|
||||
If you still have an error like 'OTRS Daemon is not running', you can enable debugging in the OTRS daemon like this.
|
||||
```
|
||||
|
||||
su - otrs
|
||||
cd /opt/otrs/
|
||||
```
|
||||
|
||||
Stop OTRS daemon:
|
||||
停止 OTRS 守护进程:
|
||||
|
||||
```
|
||||
bin/otrs.Daemon.pl stop
|
||||
```
|
||||
|
||||
And start OTRS daemon with --debug option.
|
||||
使用 `--debug` 选项启动 OTRS 守护进程。
|
||||
|
||||
```
|
||||
bin/otrs.Daemon.pl start --debug
|
||||
```
|
||||
|
||||
### Reference
|
||||
### 参考
|
||||
|
||||
* [http://wiki.otterhub.org/index.php?title=Installation_on_Debian_6_with_Postgres][12][][13]
|
||||
* [http://www.geoffstratton.com/otrs-installation-5011-ubuntu-1604][14][][15]
|
||||
@ -434,8 +436,8 @@ bin/otrs.Daemon.pl start --debug
|
||||
via: https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/
|
||||
|
||||
作者:[Muhammad Arul][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,101 @@
|
||||
软件定义存储(SDS)的发展:十个你应当知道的项目
|
||||
============================================================
|
||||
|
||||
![Software defined Storage](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/software-defined.jpg?itok=fRTy33a8 "Software Defined Storage")
|
||||
|
||||
*凭借 SDS,组织机构可以更好抽象出底层存储的管理功能,并且通过不同策略实现灵活配置。下面将要向你展示一些你应当知道的此类开源项目。Creative Commons Zero,Pixabay *
|
||||
|
||||
纵观 2016 年,SDS(Software-Defined Storage,软件定义存储)方面取得了很多里程碑式的进步,并且日益紧密的与云部署结合在了一起。凭借 SDS ,组织机构可以更好抽象出底层存储的管理功能,并且通过不同策略实现灵活配置。当然,他们也可以选择自由开源的 SDS 解决方案。人们熟知的 Ceph 正是凭借 OpenStack 部署在不断扩大自己的影响力,但是它离成为唯一的 SDS 开源项目还有很长的路要走。
|
||||
|
||||
Gartner 的一份市场调查报告中预测,截至到 2019 年,70% 已有的存储部署解决方案会支持以纯软件的方式来实施。同时 Gartner 还预测截至到 2020 年,70% 到 80% 的非结构化数据会存储在由 SDS 管理的廉价存储设备中。
|
||||
|
||||
最近,Dell EMC 公司加入到了由 Linux 基金会发起的 [OpenSDS][4] 项目中。 OpenSDS 致力于寻求解决 SDS 集成所面临的挑战,并推动企业对开放标准的采用。它由存储客户与厂商组成,包括 Fujitsu,Hitachi Data Systems,Huawei,Oregon State University 以及 Vodafone。同时 OpenSDS 也寻求与其它的上游开源社区进行合作,比如 Cloud Native Computing Foundation、Docker、OpenStack 以及 Open Container Initiative。
|
||||
|
||||
根据 Open SDS 项目的 [主页][5],2017 年会是 SDS 的一个元年:“社区希望在 2017 第二季度完成原型的发布,并且在第三季度中发布一个测试版本。OpenSDS 的最初组织者期望能通过这个项目来影响到一些开源技术,比如来自 Openstack 社区的 Cinder 和 Manila 项目,并且能够支持更广泛的云存储解决方案。”
|
||||
|
||||
与此同时,SDS 相关项目也呈现了爆发式的增长,其范围横跨 Apache Cassandra 到 Cehp。Linux 基金会最近发布了 2016 年度报告“[开放云指南:当前的趋势及开源项目][7]”,报告从整体上分析了开放云计算的现状,其中有一章涵盖了 SDS。你可以[下载][8]这篇报告,需要注意的是,这是一份综合了容器发展趋势、SDS,以及云计算的重新定义等等很多内容。报告中涵盖了当今对于开源云计算最重要的一些项目,并分类给出了描述和链接。
|
||||
|
||||
在这个系列的文章中,我们从该报告中整理了很多项目,并且针对它们是如何发展的提供了一些额外的视角及信息。在下面的内容当中,你会看到现今对 SDS 来说很重要的项目,并且能了解到它们为什么具有这么大的影响力。同时,根据上面的报告,我们提供了相关项目的 GitHub 仓库链接,方便大家查看。
|
||||
|
||||
### 软件定义存储(SDS)
|
||||
|
||||
- [Apache Cassandra][9]
|
||||
|
||||
Apache Cassandra 是一个可扩展的、高可用的,面向任务优先应用的数据库。它可以运行在商业设备或者云架构上,并且能实现跨数据中心的低延迟数据传输,同时具备良好的容错性。[Cassandra 的 GitHub 仓库][10]。
|
||||
|
||||
- [Ceph][11]
|
||||
|
||||
Ceph 是 Red Hat 构建的一个企业级可扩展的块设备、对象,以及文件存储平台,并且可部署在公有云或者私有云之上。Ceph 目前被广泛应用于 OpenStack。[Ceph 的 GitHub 仓库][12]。
|
||||
|
||||
- [CouchDB][13]
|
||||
|
||||
CouchDB 是一个 Apache 软件基金会项目,是一个单节点或者集群数据库管理系统。CouchDB 提供了 RESTful HTTP 接口来读取和更新数据库文件。[CouchDB 的 GitHub 仓库][14]。
|
||||
|
||||
- [Docker 数据卷插件][15]
|
||||
|
||||
Docker Engine 数据卷插件可以使 Engine 与外部的存储系统一起集成部署,并且数据卷的生命周期与单一 Engine 主机相同。目前存在很多第三方的数据卷管理插件,包括 Azure File Storage、NetApp、VMware vSphere 等等。你可以在 GitHub上查找到更多的插件。
|
||||
|
||||
- [GlusterFS][16]
|
||||
|
||||
Gluster 是 Red Hat 的可扩展网络文件系统,同时也是数据管理平台。Gluster 可以部署在公有云,私有云或者混合云之上,可用于 Linux 容器内的流媒体处理任务、数据分析任务,以及其它数据和带宽敏感型任务的执行。[GlusterFS 的 GitHub 仓库][17]。
|
||||
|
||||
- [MongoDB][18]
|
||||
|
||||
MongoDB 是一个高性能的文件数据库,并且部署和扩展都非常简单。[MongoDB 的 GitHub 仓库][19]。
|
||||
|
||||
- [Nexenta][20]
|
||||
|
||||
NexentaStor 是一个可扩展的、统一的软件定义的文件和块设备管理服务,同时支持数据管理功能。它能够与 VMware 集成,并且支持 Docker 和 OpenStack。[Nexenta 的 GitHub 仓库][21]。
|
||||
|
||||
- [Redis][22]
|
||||
|
||||
Redis 是一个基于内存的数据存储,一般被用作数据库、缓存,以及消息代理。它支持多种数据结构,并且本身支持复制、Lua 脚本、LRU 算法、事务,以及多层级的硬盘持久化。
|
||||
|
||||
- [Riak CS][24]
|
||||
|
||||
Riak CS(Cloud Storage)是基于 Basho 的分布式数据库 Riak KV 构建的对象存储软件。它提供了在不同规模的分布式云存储能力,可以用于公有云和私有云,还能为大压力的应用和服务提供基础的存储服务。其 API 兼容 Amazon S3,并且支持租户级别的费用计算和测量能力。[Riak CS 的 GitHub 仓库][25]。
|
||||
|
||||
- [Swift][26]
|
||||
|
||||
Swift 是 OpenStack 项目中的对象存储系统,设计初衷是通过简单 API 存储和获取非结构化数据。Swift 设计之初就是可扩展的,并且针对持久性、可靠性以及并发数据读取做了优化。[Swift 的 GitHub 仓库][27]。
|
||||
|
||||
_了解更多的开源云计算趋势以及更完整的开源云计算项目列表,请[下载 Linux 基金会的“开放云指南”][3]。_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/news/open-cloud-report/2016/guide-open-cloud-software-defined-storage-opens
|
||||
|
||||
作者:[SAM DEAN][a]
|
||||
译者:[toutoudnf](https://github.com/toutoudnf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linux.com/users/sam-dean
|
||||
[1]:https://www.linux.com/licenses/category/creative-commons-zero
|
||||
[2]:https://www.linux.com/files/images/software-definedjpg
|
||||
[3]:http://bit.ly/2eHQOwy
|
||||
[4]:http://ctt.marketwire.com/?release=11G125514-001&id=10559023&type=0&url=https%3A%2F%2Fwww.opensds.io%2F
|
||||
[5]:https://www.opensds.io/
|
||||
[6]:https://www.linux.com/blog/linux-foundation-issues-2016-guide-open-source-cloud-projects
|
||||
[7]:http://ctt.marketwire.com/?release=11G120876-001&id=10172077&type=0&url=http%3A%2F%2Fgo.linuxfoundation.org%2Frd-open-cloud-report-2016-pr
|
||||
[8]:http://go.linuxfoundation.org/l/6342/2016-10-31/3krbjr
|
||||
[9]:http://cassandra.apache.org/
|
||||
[10]:https://github.com/apache/cassandra
|
||||
[11]:http://ceph.com/
|
||||
[12]:https://github.com/ceph/ceph
|
||||
[13]:http://couchdb.apache.org/
|
||||
[14]:https://github.com/apache/couchdb
|
||||
[15]:https://docs.docker.com/engine/extend/plugins_volume/
|
||||
[16]:https://www.gluster.org/
|
||||
[17]:https://github.com/gluster/glusterfs
|
||||
[18]:https://www.mongodb.com/
|
||||
[19]:https://github.com/mongodb/mongo
|
||||
[20]:https://nexenta.com/
|
||||
[21]:https://github.com/Nexenta
|
||||
[22]:http://redis.io/
|
||||
[23]:https://github.com/antirez/redis
|
||||
[24]:http://docs.basho.com/riak/cs/2.1.1/
|
||||
[25]:https://github.com/basho/riak_cs
|
||||
[26]:https://wiki.openstack.org/wiki/Swift
|
||||
[27]:https://github.com/openstack/swift
|
@ -0,0 +1,401 @@
|
||||
许多 SQL 性能问题来自于“不必要的强制性工作”
|
||||
=====================================
|
||||
|
||||
在编写高效 SQL 时,你可能遇到的最有影响的事情就是[索引][1]。但是,一个很重要的事实就是很多 SQL 客户端要求数据库做很多**“不必要的强制性工作”**。
|
||||
|
||||
跟我再重复一遍:
|
||||
|
||||
> 不必要的强制性工作
|
||||
|
||||
什么是**“不必要的强制性工作”**?这个意思包括两个方面:
|
||||
|
||||
### 不必要的
|
||||
|
||||
假设你的客户端应用程序需要这些信息:
|
||||
|
||||
[
|
||||
![](https://lukaseder.files.wordpress.com/2017/03/title-rating.png?w=662)
|
||||
][2]
|
||||
|
||||
这没什么特别的。我们运行着一个电影数据库([例如 Sakila 数据库][3]),我们想要给用户显示每部电影的名称和评分。
|
||||
|
||||
这是能产生上面结果的查询:
|
||||
|
||||
```
|
||||
SELECT title, rating
|
||||
FROM film
|
||||
```
|
||||
|
||||
然而,我们的应用程序(或者我们的 ORM(LCTT 译注:Object-Relational Mapping,对象关系映射))运行的查询却是:
|
||||
|
||||
```
|
||||
SELECT *
|
||||
FROM film
|
||||
```
|
||||
|
||||
我们得到什么?猜一下。我们得到很多无用的信息:
|
||||
|
||||
[
|
||||
![](https://lukaseder.files.wordpress.com/2017/03/useless-information.png?w=662&h=131)
|
||||
][4]
|
||||
|
||||
甚至一些复杂的 JSON 数据全程在下列环节中加载:
|
||||
|
||||
* 从磁盘
|
||||
* 加载到缓存
|
||||
* 通过总线
|
||||
* 进入客户端内存
|
||||
* 然后被丢弃
|
||||
|
||||
是的,我们丢弃了其中大部分的信息。检索它所做的工作完全就是不必要的。对吧?没错。
|
||||
|
||||
### 强制性
|
||||
|
||||
这是最糟糕的部分。现今随着优化器变得越来越聪明,这些工作对于数据库来说都是强制执行的。数据库没有办法_知道_客户端应用程序实际上不需要其中 95% 的数据。这只是一个简单的例子。想象一下如果我们连接更多的表...
|
||||
|
||||
你想想那会怎样呢?数据库还快吗?让我们来看看一些之前你可能没有想到的地方:
|
||||
|
||||
### 内存消耗
|
||||
|
||||
当然,单次执行时间不会变化很大。可能是慢 1.5 倍,但我们可以忍受,是吧?为方便起见,有时候确实如此。但是如果你_每次_都为了方便而牺牲性能,这事情就大了。我们不说性能问题(单个查询的速度),而是关注在吞吐量上时(系统响应时间),事情就变得困难而难以解决。你就会受阻于规模的扩大。
|
||||
|
||||
让我们来看看执行计划,这是 Oracle 的:
|
||||
|
||||
```
|
||||
--------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes |
|
||||
--------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 1000 | 166K|
|
||||
| 1 | TABLE ACCESS FULL| FILM | 1000 | 166K|
|
||||
--------------------------------------------------
|
||||
```
|
||||
|
||||
对比一下:
|
||||
|
||||
```
|
||||
--------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes |
|
||||
--------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 1000 | 20000 |
|
||||
| 1 | TABLE ACCESS FULL| FILM | 1000 | 20000 |
|
||||
--------------------------------------------------
|
||||
```
|
||||
|
||||
当执行 `SELECT *` 而不是 `SELECT film, rating` 的时候,我们在数据库中使用了 8 倍之多的内存。这并不奇怪,对吧?我们早就知道了。在很多我们并不需要其中全部数据的查询中我们都是这样做的。我们为数据库产生了**不必要的强制性工作**,其后果累加了起来,就是我们使用了多达 8 倍的内存(当然,数值可能有些不同)。
|
||||
|
||||
而现在,所有其它的步骤(比如,磁盘 I/O、总线传输、客户端内存消耗)也受到相同的影响,我这里就跳过了。另外,我还想看看...
|
||||
|
||||
### 索引使用
|
||||
|
||||
如今大部分数据库都有[涵盖索引][5](LCTT 译注:covering index,包括了你查询所需列、甚至更多列的索引,可以直接从索引中获取所有需要的数据,而无需访问物理表)的概念。涵盖索引并不是特殊的索引。但对于一个特定的查询,它可以“意外地”或人为地转变为一个“特殊索引”。
|
||||
|
||||
看看这个查询:
|
||||
|
||||
```
|
||||
SELECT *
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
```
|
||||
|
||||
执行计划中没有什么特别之处。它只是个简单的查询。索引范围扫描、表访问,就结束了:
|
||||
|
||||
```
|
||||
-------------------------------------------------------------------
|
||||
| Id | Operation | Name | Rows |
|
||||
-------------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 8 |
|
||||
| 1 | TABLE ACCESS BY INDEX ROWID| ACTOR | 8 |
|
||||
|* 2 | INDEX RANGE SCAN | IDX_ACTOR_LAST_NAME | 8 |
|
||||
-------------------------------------------------------------------
|
||||
```
|
||||
|
||||
这是个好计划吗?如果我们只是想要这些,那么它就不是:
|
||||
|
||||
[
|
||||
![](https://lukaseder.files.wordpress.com/2017/03/first-name-last-name.png?w=662)
|
||||
][6]
|
||||
|
||||
当然,我们浪费了内存之类的。再来看看这个查询:
|
||||
|
||||
```
|
||||
SELECT first_name, last_name
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
```
|
||||
|
||||
它的计划是:
|
||||
|
||||
```
|
||||
----------------------------------------------------
|
||||
| Id | Operation | Name | Rows |
|
||||
----------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 8 |
|
||||
|* 1 | INDEX RANGE SCAN| IDX_ACTOR_NAMES | 8 |
|
||||
----------------------------------------------------
|
||||
```
|
||||
|
||||
现在我们可以完全消除表访问,因为有一个索引涵盖了我们查询需要的所有东西……一个涵盖索引。这很重要吗?当然!这种方法可以将你的某些查询加速一个数量级(如果在某个更改后你的索引不再涵盖,可能会降低一个数量级)。
|
||||
|
||||
你不能总是从涵盖索引中获利。索引也有它们自己的成本,你不应该添加太多索引,例如像这种情况就是不明智的。让我们来做个测试:
|
||||
|
||||
```
|
||||
SET SERVEROUTPUT ON
|
||||
DECLARE
|
||||
v_ts TIMESTAMP;
|
||||
v_repeat CONSTANT NUMBER := 100000;
|
||||
BEGIN
|
||||
v_ts := SYSTIMESTAMP;
|
||||
|
||||
FOR i IN 1..v_repeat LOOP
|
||||
FOR rec IN (
|
||||
-- Worst query: Memory overhead AND table access
|
||||
SELECT *
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
dbms_output.put_line('Statement 1 : ' || (SYSTIMESTAMP - v_ts));
|
||||
v_ts := SYSTIMESTAMP;
|
||||
|
||||
FOR i IN 1..v_repeat LOOP
|
||||
FOR rec IN (
|
||||
-- Better query: Still table access
|
||||
SELECT /*+INDEX(actor(last_name))*/
|
||||
first_name, last_name
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
dbms_output.put_line('Statement 2 : ' || (SYSTIMESTAMP - v_ts));
|
||||
v_ts := SYSTIMESTAMP;
|
||||
|
||||
FOR i IN 1..v_repeat LOOP
|
||||
FOR rec IN (
|
||||
-- Best query: Covering index
|
||||
SELECT /*+INDEX(actor(last_name, first_name))*/
|
||||
first_name, last_name
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
dbms_output.put_line('Statement 3 : ' || (SYSTIMESTAMP - v_ts));
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
|
||||
结果是:
|
||||
|
||||
```
|
||||
Statement 1 : +000000000 00:00:02.479000000
|
||||
Statement 2 : +000000000 00:00:02.261000000
|
||||
Statement 3 : +000000000 00:00:01.857000000
|
||||
```
|
||||
|
||||
注意,表 actor 只有 4 列,因此语句 1 和 2 的差别并不是太令人印象深刻,但仍然很重要。还要注意我使用了 Oracle 的提示来强制优化器为查询选择一个或其它索引。在这种情况下语句 3 明显胜利。这是一个好_很多_的查询,也是一个十分简单的查询。
|
||||
|
||||
当我们写 `SELECT *` 语句时,我们为数据库带来了**不必要的强制性工作**,这是无法优化的。它不会使用涵盖索引,因为比起它所使用的 `LAST_NAME` 索引,涵盖索引开销更多一点,不管怎样,它都要访问表以获取无用的 `LAST_UPDATE` 列。
|
||||
|
||||
使用 `SELECT *` 会变得更糟。考虑一下……
|
||||
|
||||
### SQL 转换
|
||||
|
||||
优化器工作的很好,因为它们转换了你的 SQL 查询([看我最近在 Voxxed Days Zurich 关于这方面的演讲][7])。例如,其中有一个称为“表连接消除”的转换,它真的很强大。看看这个辅助视图,我们写了这个视图是因为我们非常讨厌总是连接所有这些表:
|
||||
|
||||
```
|
||||
CREATE VIEW v_customer AS
|
||||
SELECT
|
||||
c.first_name, c.last_name,
|
||||
a.address, ci.city, co.country
|
||||
FROM customer c
|
||||
JOIN address a USING (address_id)
|
||||
JOIN city ci USING (city_id)
|
||||
JOIN country co USING (country_id)
|
||||
```
|
||||
|
||||
这个视图仅仅是把 `CUSTOMER` 和他们不同的 `ADDRESS` 部分所有“对一”关系连接起来。谢天谢地,它很工整。
|
||||
|
||||
现在,使用这个视图一段时间之后,想象我们非常习惯这个视图,我们都忘了所有它底层的表。然后,我们运行了这个查询:
|
||||
|
||||
```
|
||||
SELECT *
|
||||
FROM v_customer
|
||||
```
|
||||
|
||||
我们得到了一个相当令人印象深刻的计划:
|
||||
|
||||
```
|
||||
----------------------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes | Cost |
|
||||
----------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 599 | 47920 | 14 |
|
||||
|* 1 | HASH JOIN | | 599 | 47920 | 14 |
|
||||
| 2 | TABLE ACCESS FULL | COUNTRY | 109 | 1526 | 2 |
|
||||
|* 3 | HASH JOIN | | 599 | 39534 | 11 |
|
||||
| 4 | TABLE ACCESS FULL | CITY | 600 | 10800 | 3 |
|
||||
|* 5 | HASH JOIN | | 599 | 28752 | 8 |
|
||||
| 6 | TABLE ACCESS FULL| CUSTOMER | 599 | 11381 | 4 |
|
||||
| 7 | TABLE ACCESS FULL| ADDRESS | 603 | 17487 | 3 |
|
||||
----------------------------------------------------------------
|
||||
```
|
||||
|
||||
当然是这样。我们运行了所有这些表连接以及全表扫描,因为这就是我们让数据库去做的:获取所有的数据。
|
||||
|
||||
现在,再一次想一下,对于一个特定场景,我们真正想要的是:
|
||||
|
||||
[
|
||||
![](https://lukaseder.files.wordpress.com/2017/03/first-name-last-name-customers.png?w=662)
|
||||
][8]
|
||||
|
||||
是啊,对吧?现在你应该知道我的意图了。但想像一下,我们确实从前面的错误中学到了东西,现在我们实际上运行下面一个比较好的查询:
|
||||
|
||||
```
|
||||
SELECT first_name, last_name
|
||||
FROM v_customer
|
||||
```
|
||||
|
||||
再来看看结果!
|
||||
|
||||
```
|
||||
------------------------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes | Cost |
|
||||
------------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 599 | 16173 | 4 |
|
||||
| 1 | NESTED LOOPS | | 599 | 16173 | 4 |
|
||||
| 2 | TABLE ACCESS FULL| CUSTOMER | 599 | 11381 | 4 |
|
||||
|* 3 | INDEX UNIQUE SCAN| SYS_C007120 | 1 | 8 | 0 |
|
||||
------------------------------------------------------------------
|
||||
```
|
||||
|
||||
这是执行计划一个_极大的_进步。我们的表连接被消除了,因为优化器可以证明它们是**不必要的**,因此一旦它可以证明这点(而且你不会因使用 `select *` 而使其成为**强制性**工作),它就可以移除这些工作并不执行它。为什么会发生这种情况?
|
||||
|
||||
每个 `CUSTOMER.ADDRESS_ID` 外键保证了_有且只有一个_ `ADDRESS.ADDRESS_ID` 主键值,因此可以保证 `JOIN` 操作是对一连接,它不会产生或者删除行。如果我们甚至不选择行或查询行,当然我们就不需要真正地去加载行。可以证实地移除 `JOIN` 并不会改变查询的结果。
|
||||
|
||||
数据库总是会做这些事情。你可以在大部分数据库上尝试它:
|
||||
|
||||
```
|
||||
-- Oracle
|
||||
SELECT CASE WHEN EXISTS (
|
||||
SELECT 1 / 0 FROM dual
|
||||
) THEN 1 ELSE 0 END
|
||||
FROM dual
|
||||
|
||||
-- 更合理的 SQL 语句,例如 PostgreSQL
|
||||
SELECT EXISTS (SELECT 1 / 0)
|
||||
```
|
||||
|
||||
在这种情况下,当你运行这个查询时你可能预料到会抛出算术异常:
|
||||
|
||||
```
|
||||
SELECT 1 / 0 FROM dual
|
||||
```
|
||||
|
||||
产生了:
|
||||
|
||||
```
|
||||
ORA-01476: divisor is equal to zero
|
||||
```
|
||||
|
||||
但它并没有发生。优化器(甚至解析器)可以证明 `EXISTS (SELECT ..)` 谓词内的任何 `SELECT` 列表达式不会改变查询的结果,因此也就没有必要计算它的值。呵!
|
||||
|
||||
### 同时……
|
||||
|
||||
大部分 ORM 最不幸问题就是事实上他们很随意就写出了 `SELECT *` 查询。事实上,例如 HQL / JPQL,就设置默认使用它。你甚至可以完全抛弃 `SELECT` 从句,因为毕竟你想要获取所有实体,正如声明的那样,对吧?
|
||||
|
||||
例如:
|
||||
|
||||
`FROM` `v_customer`
|
||||
|
||||
例如 [Vlad Mihalcea][9](一个 Hibernate 专家和 Hibernate 开发倡导者)建议你每次确定不想要在获取后进行任何更改时再使用查询。ORM 使解决对象图持久化问题变得简单。注意:持久化。真正修改对象图并持久化修改的想法是固有的。
|
||||
|
||||
但如果你不想那样做,为什么要抓取实体呢?为什么不写一个查询?让我们清楚一点:从性能角度,针对你正在解决的用例写一个查询_总是_会胜过其它选项。你可以不会在意,因为你的数据集很小,没关系。可以。但最终,你需要扩展并重新设计你的应用程序以便在强制实体图遍历之上支持查询语言,就会变得很困难。你也需要做其它事情。
|
||||
|
||||
### 计算出现次数
|
||||
|
||||
资源浪费最严重的情况是在只是想要检验存在性时运行 `COUNT(*)` 查询。例如:
|
||||
|
||||
> 这个用户有没有订单?
|
||||
|
||||
我们会运行:
|
||||
|
||||
```
|
||||
SELECT count(*)
|
||||
FROM orders
|
||||
WHERE user_id = :user_id
|
||||
```
|
||||
|
||||
很简单。如果 `COUNT = 0`:没有订单。否则:是的,有订单。
|
||||
|
||||
性能可能不会很差,因为我们可能有一个 `ORDERS.USER_ID` 列上的索引。但是和下面的这个相比你认为上面的性能是怎样呢:
|
||||
|
||||
```
|
||||
-- Oracle
|
||||
SELECT CASE WHEN EXISTS (
|
||||
SELECT *
|
||||
FROM orders
|
||||
WHERE user_id = :user_id
|
||||
) THEN 1 ELSE 0 END
|
||||
FROM dual
|
||||
|
||||
-- 更合理的 SQL 语句,例如 PostgreSQL
|
||||
SELECT EXISTS (
|
||||
SELECT *
|
||||
FROM orders
|
||||
WHERE user_id = :user_id
|
||||
)
|
||||
```
|
||||
|
||||
它不需要火箭科学家来确定,一旦它找到一个,实际存在谓词就可以马上停止寻找额外的行。因此,如果答案是“没有订单”,速度将会是差不多。但如果结果是“是的,有订单”,那么结果在我们不计算具体次数的情况下就会_大幅_加快。
|
||||
|
||||
因为我们_不在乎_具体的次数。我们告诉数据库去计算它(**不必要的**),而数据库也不知道我们会丢弃所有大于 1 的结果(**强制性**)。
|
||||
|
||||
当然,如果你在 JPA 支持的集合上调用 `list.size()` 做同样的事情,情况会变得更糟!
|
||||
|
||||
[近期我有关于该情况的博客以及在不同数据库上的测试。去看看吧。][10]
|
||||
|
||||
### 总结
|
||||
|
||||
这篇文章的立场很“明显”。别让数据库做**不必要的强制性工作**。
|
||||
|
||||
它**不必要**,因为对于你给定的需求,你_知道_一些特定的工作不需要完成。但是,你告诉数据库去做。
|
||||
|
||||
它**强制性**,因为数据库无法证明它是**不必要的**。这些信息只包含在客户端中,对于服务器来说无法访问。因此,数据库需要去做。
|
||||
|
||||
这篇文章大部分在介绍 `SELECT *`,因为这是一个很简单的目标。但是这并不仅限于数据库。这关系到客户端要求服务器完成**不必要的强制性工作**的任何分布式算法。你的 AngularJS 应用程序平均有多少个 N+1 问题,UI 在服务结果 A 上循环,多次调用服务 B,而不是把所有对 B 的调用打包为一个调用?这是一个复发的模式。
|
||||
|
||||
解决方法总是相同。你给执行你命令的实体越多信息,(理论上)它能更快执行这样的命令。每次都写一个好的查询。你的整个系统都会为此感谢你的。
|
||||
|
||||
### 如果你喜欢这篇文章...
|
||||
|
||||
再看看近期我在 Voxxed Days Zurich 的演讲,其中我展示了一些在数据处理算法上为什么 SQL 总是会胜过 Java 的双曲线例子
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://blog.jooq.org/2017/03/08/many-sql-performance-problems-stem-from-unnecessary-mandatory-work
|
||||
|
||||
作者:[jooq][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://blog.jooq.org/
|
||||
[1]:http://use-the-index-luke.com/
|
||||
[2]:https://lukaseder.files.wordpress.com/2017/03/title-rating.png
|
||||
[3]:https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/Sakila
|
||||
[4]:https://lukaseder.files.wordpress.com/2017/03/useless-information.png
|
||||
[5]:https://blog.jooq.org/2015/04/28/do-not-think-that-one-second-is-fast-for-query-execution/
|
||||
[6]:https://lukaseder.files.wordpress.com/2017/03/first-name-last-name.png
|
||||
[7]:https://www.youtube.com/watch?v=wTPGW1PNy_Y
|
||||
[8]:https://lukaseder.files.wordpress.com/2017/03/first-name-last-name-customers.png
|
||||
[9]:https://vladmihalcea.com/2016/09/13/the-best-way-to-handle-the-lazyinitializationexception/
|
||||
[10]:https://blog.jooq.org/2016/09/14/avoid-using-count-in-sql-when-you-could-use-exists/
|
110
published/201706/20170314 One Year Using Go.md
Normal file
110
published/201706/20170314 One Year Using Go.md
Normal file
@ -0,0 +1,110 @@
|
||||
使用 Go 一年的体验
|
||||
============================================================
|
||||
|
||||
![](https://bugfender.com/wp-content/uploads/2017/03/one-year-using-go-social-1.jpg)
|
||||
|
||||
我们公司 [Mobile Jazz][6] 从一个内部试验性项目开始使用 [Go][5]。如公司名暗示的那样,我们是开发移动应用的。
|
||||
|
||||
在发布一个应用给公众后,我们很快意识到我们缺失一个工具来检查用户实际发生的情况以及他们是如何与应用交互的 - 如果有任何问题或者 bug 的报告,这将会相当方便。
|
||||
|
||||
现在有几款工具声称能在这个方面帮助开发者,但是没有一个能完全满足要求,因此我们决定自己构建一个。我们开始创建一组基础的脚本,如今它很快进化成了完整的工具,称为 [Bugfender][7]!
|
||||
|
||||
由于这最初是一个实验,我们决定使用一种新的趋势技术。对学习以及持续教育的热爱是 Mobile Jazz 的核心价值的之一,因此我们决定使用 Go 构建。这是一个由 Google 开发的相对较新的编程语言。它是编程世界的的新玩家,已经有许多受尊敬的开发者对它赞不绝口。
|
||||
|
||||
一年后,这个实验变成了一个初创项目,我们拥有了一个已经帮助了来自全世界的数以千计的开发者的令人难以置信的工具。我们的服务器每天处理来自 700 万台设备的超过 200GB 的数据。
|
||||
|
||||
在使用 Go 一年之后,我们想要分享我们将一个小小的实验变成处理百万日志的生产服务器的一些想法和经验。
|
||||
|
||||
### Go 生态系统
|
||||
|
||||
公司中没有人有使用 Go 的经验。Bugfender 是我们第一次深入这个语言。
|
||||
|
||||
学习基本上相当直接的。我们之前在 C/C++/Java/Objective-C/PHP 的经验让我们学习 Go 相当快,并且在几天内就开始开发了。当然会有一些新的和不常见的东西需要学习,包括 GOPATH 还有如何处理包,但这在我们的预期之内。
|
||||
|
||||
几天之内,我们意识到即使是一个以简化为设计目的的语言,Go 也是非常强大的。它能够做任何现代编程语言应该能做的事:能够处理 JSON、服务器之间通讯甚至访问数据库也没问题(并且只需要几行代码)。
|
||||
|
||||
在构建一个服务器时,你应该首先决定是否使用任何第三方库或者框架。对于 Bugfender,我们决定使用:
|
||||
|
||||
#### Martini
|
||||
|
||||
[Martini][8] 是一个强大的 Go 的 web 框架。我们开始这个实验时,它是一个很棒的解决方案,至今也是,我们还没遇到任何问题。然而如果我们今天再次开始这个实验的话,我们会选择一个不同的框架,因为 Martini 不在维护了。
|
||||
|
||||
我们还试验了 [Iris][9](我们目前的最爱)还有 [Gin][10]。Gin 是 Martini 继任者,并且迁移到这上能让我们重用已有的代码。
|
||||
|
||||
在过去的一年中,我们意识到 Go 的标准库是非常强大的,你不必依靠一个臃肿的 web 框架来构建一个服务器。最好在特定任务上使用专门的高性能库。
|
||||
|
||||
~~Iris 是我们目前最喜欢的,并且将来我们将使用它重写服务来替代 Martini/Gin,但这目前并不是优先的。~~
|
||||
|
||||
**修改:** 在讨论了 Iris 的各个方面之后,我们意识到 Iris 或许不是最好的选择。如果我们决定重写我们的 web 组件,我们或许会研究其他的选择,我们欢迎你的建议。
|
||||
|
||||
#### Gorm
|
||||
|
||||
有些人喜欢 ORM,而有些人则不喜欢。我们决定使用 ORM,更确切地说是 [GORM][11]。我们的实现只针对 web 前端,对于日志提取 API 仍然继续使用手工优化的 SQL。在一开始,我们确实很喜欢它,但是随着时间的推移,我们开始发现问题,并且我们很快将它从代码中完全移除,并且使用 [sqlx][12] 这个标准 SQL 库。
|
||||
|
||||
GORM 的一个主要问题是 Go 的生态系统。作为一个新语言,自我们开始开发产品以来 Go 已经有很多新版本。在这些新版本中的一些改变并不向后兼容,因此要使用最新的库版本,我们要经常重写已有代码并检查我们为解决版本问题所做的 hack。
|
||||
|
||||
上述这两个库是大多数 web 服务的主要组件,因此做一个好的选择很重要,因为将来更改会很困难,并且会影响你服务器的性能。
|
||||
|
||||
### 第三方服务
|
||||
|
||||
在创建一个实际使用的产品的另外一个重要方面是考虑库、第三方服务和工具的可用性。在这方面,Go 还缺乏成熟度,大多数公司还没有提供 Go 库,因此你或许需要依赖其他人写的不能一直保证质量的库。
|
||||
|
||||
比如,对于使用 [Redis][13] 和 [ElasticSearch][14] 有很好的库,但是对于其他服务比如 Mixpanel 或者 Stripe 还没有好的。
|
||||
|
||||
我们建议在使用 Go 之前事先检查对于你需要的产品是否有好的库可用。
|
||||
|
||||
我们在 Go 的包管理系统上也遇到了很多问题。它处理版本的方式远没有达到最好,并且在过去的一年中,我们在不同的团队成员之间使用同一个库的不同版本上遇到了很多问题。然而,最近要归功于 Go 新支持的 vendor 包特性,除了 [gopkg.in][15] 服务外,这个问题基本被解决了。
|
||||
|
||||
### 开发者工具
|
||||
|
||||
![](https://bugfender.com/wp-content/uploads/2017/03/go-ide.jpg)
|
||||
|
||||
由于 Go 是一门相对新的语言,你或许发现相比其他成熟的语言像 Java,它可用的开发工具并不很好。当我们开始 Bugfender 时,使用任何 IDE 都很困难,似乎没有 IDE 支持 Go。但是在过去的一年中,随着 [IntelliJ][16] 和 [Visual Studio Code Go][17] 插件的引入,这一切改善了很多。
|
||||
|
||||
最后看下其他的 Go 工具,调试器并不很好,而分析器甚至更糟,因此有时调试你的代码或者尝试优化它会很困难。
|
||||
|
||||
### 前往生产
|
||||
|
||||
这确实是 Go 最好的东西之一,如果你想要部署一些东西到生产环境中,你只需要构建你的二进制并发送到服务器中,没有依赖,不需要安装额外的软件,你只需要能在服务器中运行二进制文件就行。
|
||||
|
||||
如果你习惯于处理那些需要包管理器或者需要小心你使用的语言解释器的语言,用 Go 工作会感到很高兴。
|
||||
|
||||
我们对 Go 的稳定性也很满意,因为服务器似乎从没有崩溃过。我们在发送大量数据给 Go Routines 时遇到过一个问题,但是我们几乎没见到任何崩溃。注意:如果你需要发送大量数据给 Go Routine,你需要小心堆溢出。
|
||||
|
||||
如果你对性能感兴趣,我们没法与其他语言相比较,因为我们从零开始使用 Go,但是对于我们处理的数据量,我们感觉性能是非常好的,我们绝对不能如此轻松地使用 PHP 处理同等数量的请求。
|
||||
|
||||
### 总结
|
||||
|
||||
在过去的一年中,我们对 Go 的感觉起起伏伏。最初我们是兴奋的,但是在实验变成真实的产品后我们开始发现问题。我们几次考虑过用 Java 完全重写,但是目前为止,仍旧使用的是 Go,并且过去的一年中, Go 生态已经有了很大的提升,这简化了我们的工作。
|
||||
|
||||
如果你想要使用 Go 构建你的产品,你可以保证它可以工作,但是你确实需要小心一件事:可以雇佣的开发者。硅谷中只有很少的高级 Go 开发者,并且在其他地方寻找也是一件非常困难的任务。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://bugfender.com/one-year-using-go
|
||||
|
||||
作者:[ALEIX VENTAYOL][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://bugfender.com/author/aleixventayol
|
||||
[1]:https://bugfender.com/#facebook
|
||||
[2]:https://bugfender.com/#twitter
|
||||
[3]:https://bugfender.com/#google_plus
|
||||
[4]:https://www.addtoany.com/share#url=https%3A%2F%2Fbugfender.com%2Fone-year-using-go&title=One%20Year%20Using%20Go
|
||||
[5]:https://golang.org/
|
||||
[6]:http://mobilejazz.com/
|
||||
[7]:https://www.bugfender.com/
|
||||
[8]:https://github.com/go-martini/martini
|
||||
[9]:https://github.com/kataras/iris
|
||||
[10]:https://github.com/gin-gonic/gin
|
||||
[11]:https://github.com/jinzhu/gorm
|
||||
[12]:https://github.com/jmoiron/sqlx
|
||||
[13]:https://github.com/go-redis/redis
|
||||
[14]:https://github.com/olivere/elastic
|
||||
[15]:http://labix.org/gopkg.in
|
||||
[16]:https://plugins.jetbrains.com/plugin/5047-go
|
||||
[17]:https://github.com/Microsoft/vscode-go
|
||||
[18]:https://bugfender.com/one-year-using-go
|
@ -0,0 +1,141 @@
|
||||
Linux GRUB2 配置简介
|
||||
============================================================
|
||||
|
||||
> 学习 GRUB 引导加载程序是如何预备你的系统并启动操作系统内核的。
|
||||
|
||||
|
||||
![Linux GRUB2 配置简介](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/car-penguin-drive-linux-yellow.png?itok=ueZE5mph "Linux GRUB2 配置简介")
|
||||
|
||||
|
||||
自从上个月为我的文章《[Linux 引导和启动过程简介][2]》做研究开始,我对更深入了解 GRUB2 产生了兴趣。这篇文章提供了配置 GRUB2 的简要介绍。为了简便起见,我大多数情况下会使用 GRUB 指代 GRUB2。
|
||||
|
||||
### GRUB
|
||||
|
||||
GRUB 来自 GRand Unified Bootloader 的缩写。它的功能是在启动时从 BIOS 接管掌控、加载自身、加载 Linux 内核到内存,然后再把执行权交给内核。一旦内核开始掌控,GRUB 就完成了它的任务,也就不再需要了。
|
||||
|
||||
GRUB 支持多种 Linux 内核,并允许用户在启动时通过菜单在其中选择。我发现这是一种非常有用的工具,因为我有很多次遇到一个应用程序或者系统服务在特定内核版本下失败的问题。有好几次,引导到一个较旧的内核时就可以避免类似的问题。默认情况下,使用 `yum` 或 `dnf` 进行更新时会保存三个内核 - 最新的以及两个比较旧的。在被包管理器删除之前所保留的内核数目可以在 `/etc/dnf/dnf.conf` 或 `/etc/yum.conf` 文件中配置。我通常把 `installonly_limit` 的值修改为 9 以便保留 9 个内核。当我不得不恢复到低几个版本的内核时这非常有用。
|
||||
|
||||
### GRUB 菜单
|
||||
|
||||
GRUB 菜单的功能是当默认的内核不是想要的时,允许用户从已经安装的内核中选择一个进行引导。通过上下箭头键允许你选中想要的内核,敲击回车键会使用选中的内核继续引导进程。
|
||||
|
||||
GRUB 菜单也提供了超时机制,因此如果用户没有做任何选择,GRUB 就会在没有用户干预的情况下使用默认内核继续引导。敲击键盘上除了回车键之外的任何键会停止终端上显示的倒数计时器。立即敲击回车键会使用默认内核或者选中的内核继续引导进程。
|
||||
|
||||
GRUB 菜单提供了一个 “<ruby>救援<rt>rescue</rt></ruby>” 内核,用于故障排除或者由于某些原因导致的常规内核不能完成启动过程。不幸的是,这个救援内核不会引导到救援模式。文章后面会更详细介绍这方面的东西。
|
||||
|
||||
### grub.cfg 文件
|
||||
|
||||
`grub.cfg` 文件是 GRUB 配置文件。它由 `grub2-mkconfig` 程序根据用户的配置使用一组主配置文件以及 grub 默认文件而生成。`/boot/grub2/grub.cfg` 文件在 Linux 安装时会初次生成,安装新内核时又会重新生成。
|
||||
|
||||
`grub.cfg` 文件包括了类似 Bash 脚本的代码以及一个按照安装顺序排序的已安装内核列表。例如,如果你有 4 个已安装内核,最新的内核索引是 0,前一个内核索引是 1,最旧的内核索引是 3。如果你能访问 `grub.cfg` 文件,你应该去看看感受一下它看起来是什么样。`grub.cfg` 太大也就没有包含在这篇文章中。
|
||||
|
||||
### GRUB 配置文件
|
||||
|
||||
`grub.cfg` 的主要配置文件都在 `/etc/grub.d` 目录。该目录中的每个文件都包含了最终会整合到 `grub.cfg` 文件中的 GRUB 代码。这些配置文件的命名模式以排序方式设计,这使得最终的 `grub.cfg` 文件可以按正确的顺序整合而成。每个文件都有注释表明该部分的开始和结束,这些注释也是最终的 `grub.cfg` 文件的一部分,从而可以看出每个部分是由哪个文件生成。分隔注释看起来像这样:
|
||||
|
||||
```
|
||||
### BEGIN /etc/grub.d/10_linux ###
|
||||
|
||||
### END /etc/grub.d/10_linux ###
|
||||
```
|
||||
|
||||
不要修改这些文件,除非你是一个 GRUB 专家并明白更改会发生什么。无论如何,修改 `grub.cfg` 文件时你也总应该保留一个原始文件的备份。 `40_custom` 和 `41_custom` 这两个特别的文件用于生成用户对 GRUB 配置的修改。你仍然要注意对这些文件的更改的后果,并保存一份原始 `grub.cfg` 文件的备份。
|
||||
|
||||
你也可以把你自己的文件添加到 `/etc/grub.d` 目录。这样做的一个可能的原因是为非 Linux 操作系统添加菜单行。要注意遵循命名规则,确保配置文件中额外的菜单选项刚好在 `10_linux` 条目之前或之后。
|
||||
|
||||
### GRUB 默认文件
|
||||
|
||||
老版本 GRUB 的配置非常简单而明了,我只需要修改 `/boot/grub/grub.conf` 就可以了。对于新版本的 GRUB2,我虽然还可以通过更改 `/boot/grub2/grub.cfg` 来修改,但和老版本的 GRUB 相比,新版本相对更加复杂。另外,安装一个新内核时 `grub.cfg` 可能会被重写,因此任何修改都可能消失。当然,GNU.org 的 GRUB 手册确实有过直接创建和修改 `/boot/grub2/grub.cfg` 的讨论。
|
||||
|
||||
一旦你明白了如何做,更改 GRUB2 配置就会变得非常简单。我为之前的文章研究 GRUB2 的时候才明白这个。秘方就在 `/etc/default` 目录里面,一个自然而然称为 `grub` 的文件,它可以通过简单的终端命令操作。`/etc/default` 目录包括了一些类似 Google Chrome、 useradd、 和 grub 程序的配置文件。
|
||||
|
||||
`/etc/default/grub` 文件非常简单。这个 `grub` 默认文件已经列出了一些有效的键值对。你可以简单地更改现有键值或者添加其它文件中还没有的键。下面的列表 1 显示了一个没有更改过的 `/etc/default/grub` 文件。
|
||||
|
||||
```
|
||||
GRUB_TIMEOUT=5
|
||||
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g'
|
||||
/etc/system-release)"
|
||||
GRUB_DEFAULT=saved
|
||||
GRUB_DISABLE_SUBMENU=true
|
||||
GRUB_TERMINAL_OUTPUT="console"
|
||||
GRUB_CMDLINE_LINUX="rd.lvm.lv=fedora_fedora25vm/root
|
||||
rd.lvm.lv=fedora_fedora25vm/swap
|
||||
rd.lvm.lv=fedora_fedora25vm/usr rhgb quiet"
|
||||
GRUB_DISABLE_RECOVERY="true"
|
||||
```
|
||||
|
||||
_列表 1:Fedora 25 一个原始 grub 默认文件。_
|
||||
|
||||
[GRUB 手册 5.1 章节][7]包括了所有可以添加到该 `grub` 文件的键的信息。我只需要修改 `grub` 默认文件已经有的一些键值就够了。让我们看看这些键值以及一些在 grub 默认文件中没有出现的每个键的意义。
|
||||
|
||||
* `GRUB_TIMEOUT` 这个键的值决定了显示 GRUB 选择菜单的时间长度。GRUB 提供了同时保存多个安装内核并在启动时使用 GRUB 菜单在其中选择的功能。这个键的默认值是 5 秒,但我通常修改为 10 秒使得有更多时间查看选项并作出选择。
|
||||
* `GRUB_DISTRIBUTOR` 这个键定义了一个从 `/etc/system-release` 文件中提取发行版本的 [sed][3] 表达式。这个信息用于生成出现在 GRUB 菜单中的每个内核发布版的文本名称,例如 “Fedora” 等。由于不同发行版之间 `system-release` 文件结构的差异,在你的系统中这个 sed 表达式可能有些不同。
|
||||
* `GRUB_DEFAULT` 决定默认引导哪个内核。如果是 `saved`,这代表最新内核。这里的其它选项如果是数字则代表了 `grub.cfg` 中列表的索引。使用索引号 3,就会总是加载列表中的第四个内核,即使安装了一个新内核之后也是。因此使用索引数字的话,在安装一个新内核后会加载不同的内核。要确保引导特定内核版本的唯一方法是设置 `GRUB_DEFAULT` 的值为想要内核的名称,例如 `4.8.13-300.fc25.x86_64`。
|
||||
* `GRUB_SAVEDEFAULT` 通常,grub 默认文件中不会指定这个选项。当选择不同内核进行引导时,正常操作下该内核只会启动一次。默认内核不会改变。当其设置为 `true` 并和 `GRUB_DEFAULT=saved` 一起使用时,这个选项会保存一个不同内核作为默认值。当选择不同内核进行引导时会发生这种情况。
|
||||
* `GRUB_DISABLE_SUBMENU` 一些人可能会希望为 GRUB 菜单创建一个内核的层级菜单结构。这个键和 `grub.cfg` 中一些额外内核配置允许创建这样的层级结构。例如,主菜单中可能有 `production` 和 `test` 子菜单,每个子菜单中包括了一些合适的内核。设置它为 `false` 可以启用子菜单。
|
||||
* `GRUB_TERMINAL_OUTPUT` 一些环境下可能需要或者必要将输出重定向到一个不同的显示控制台或者终端。默认情况下是把输出发送到默认终端,通常 `console` 等价于 Intel 系列个人电脑的标准输出。另一个有用的选择是在使用串行终端或者 Integrated Lights Out (ILO) 终端连接的数据中心或者实验室环境中指定 `serial`。
|
||||
* `GRUB_TERMINAL_INPUT` 和 `GRUB_TERMINAL_OUTPUT` 类似,可能需要或者必要重定向输入为串行终端或者 ILO 设备、而不是标准键盘输入。
|
||||
* `GRUB_CMDLINE_LINUX` 这个键包括了在启动时会传递给内核的命令行参数。注意这些参数会被添加到 `grub.cfg` 所有已安装内核的内核行。这意味着所有已安装的内核在启动时都会有相同的参数。我通常删除 `rhgb` 和 `quiet` 参数以便我可以看到引导和启动时内核和 systemd 输出的所有内核信息消息。
|
||||
* `GRUB_DISABLE_RECOVERY` 当这个键的值被设置为 `false`,GRUB 菜单中就会为每个已安装的内核创建一个恢复条目。当设置为 `true` 时就不会创建任何恢复条目。但不管这个设置怎样,最后的内核条目总是一个 `rescue` 选项。不过在 rescue 选项中我遇到了一个问题,下面我会详细介绍。
|
||||
|
||||
还有一些你可能觉得有用但我没有在这里介绍的键。它们的描述可以在 [GRUB 手册 2][8] 的 5.1 章节找到。
|
||||
|
||||
### 生成 grub.cfg
|
||||
|
||||
完成所需的配置之后,就需要生成 `/boot/grub2/grub.cfg` 文件。这通过下面的命令完成。
|
||||
|
||||
```
|
||||
grub2-mkconfig > /boot/grub2/grub.cfg
|
||||
```
|
||||
|
||||
这个命令按照顺序使用位于 `/etc/grub.d` 的配置文件构建 `grub.cfg` 文件,然后使用 grub 默认文件的内容修改输出以便获得最终所需的配置。`grub2-mkconfig` 命令会尝试定位所有已安装的内核并在 `grub.cfg` 文件的 `10_Linux` 部分新建条目。它还创建一个 `rescue` 条目提供一个用于从 Linux 不能启动的严重问题中恢复的方法。
|
||||
|
||||
强烈建议你不要手动编辑 `grub.cfg` 文件,因为任何对该文件的直接修改都会在下一次安装新内核或者手动运行 `grub2-mkconfig` 时被重写。
|
||||
|
||||
### 问题
|
||||
|
||||
我遇到一个如果没有意识到就可能导致严重后果的 GRUB2 问题。这个救援内核没有启动,反而启动了另外一个内核。我发现那是列表中索引为 1 的内核,也就是列表中的第二个内核。额外的测试发现不管使用原始的还是我生成的 `grub.cfg` 配置文件都会发生这个问题。我在虚拟机和真实硬件上都尝试过而且都发生了这个问题。我只测试了 Fedora 25,因此其它 Fedora 发行版本可能没有这个问题。
|
||||
|
||||
注意,从救援内核生成的 “recovery” 内核条目不能引导到维护模式。
|
||||
|
||||
我推荐将 grub 默认文件中 `GRUB_DISABLE_RECOVERY` 的值更改为 “false”,然后生成你自己的 `grub.cfg`。这会在 GRUB 菜单中为每个已安装的内核生成可用的恢复条目。这些恢复配置能像期望那样工作,从而从那些需要输入密码登录的内核条目中引导到运行级别 1,也就是进入(不需要密码的)单用户维护模式。你也可以按 `Ctrl-D` 继续正常的引导进入默认运行级别。
|
||||
|
||||
### 总结
|
||||
|
||||
GRUB 是引导 Linux 计算机到可用状态过程的一系列事件中,发生在 BIOS 之后的第一步。理解如何配置 GRUB 对于恢复或者处理多种类型的问题非常重要。
|
||||
|
||||
这么多年来我多次不得不引导到恢复或者救援模式以便解决多种类型的问题。其中的一些问题确实是类似 `/etc/fstab` 或其它配置文件中不恰当条目导致的引导问题,也有一些是由于应用程序或者系统软件和最新的内核不兼容的问题。硬件兼容性问题也可能妨碍特定的内核启动。
|
||||
|
||||
我希望这些信息能对你开启 GRUB 配置之旅有所帮助。
|
||||
|
||||
( 题图 : Internet Archive [Book][5] [Images][6]. Opensource.com 修改。 CC BY-SA 4.0)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
David Both - David Both 是一个居住在 Raleigh,北卡罗来纳州的 Linux 和开源倡导者。他在 IT 界已经有超过 40 年,并在他工作的 IBM 执教 OS/2 20 多年。在 IBM 的时候,他在 1981 年开设了第一个最初 IBM 个人电脑的培训课程。他在红帽教授过 RHCE 课程并在 MCI Worldcom、 Cisco、 和北卡罗来纳州工作过。他已经在 Linux 和开源软件方面工作将近 20 年。
|
||||
|
||||
|
||||
----------------
|
||||
|
||||
via: https://opensource.com/article/17/3/introduction-grub2-configuration-linux
|
||||
|
||||
作者:[David Both][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/dboth
|
||||
[1]:https://opensource.com/article/17/2/linux-boot-and-startup
|
||||
[2]:https://opensource.com/article/17/2/linux-boot-and-startup
|
||||
[3]:https://en.wikipedia.org/wiki/Sed
|
||||
[4]:https://opensource.com/article/17/3/introduction-grub2-configuration-linux?rate=QrIzRpQ3YhewYlBD0AFp0JiF133SvhyAq783LOxjr4c
|
||||
[5]:https://www.flickr.com/photos/internetarchivebookimages/14746482994/in/photolist-ot6zCN-odgbDq-orm48o-otifuv-otdyWa-ouDjnZ-otGT2L-odYVqY-otmff7-otGamG-otnmSg-rxnhoq-orTmKf-otUn6k-otBg1e-Gm6FEf-x4Fh64-otUcGR-wcXsxg-tLTN9R-otrWYV-otnyUE-iaaBKz-ovcPPi-ovokCg-ov4pwM-x8Tdf1-hT5mYr-otb75b-8Zk6XR-vtefQ7-vtehjQ-xhhN9r-vdXhWm-xFBgtQ-vdXdJU-vvTH6R-uyG5rH-vuZChC-xhhGii-vvU5Uv-vvTNpB-vvxqsV-xyN2Ai-vdXcFw-vdXuNC-wBMhes-xxYmxu-vdXxwS-vvU8Zt
|
||||
[6]:https://www.flickr.com/photos/internetarchivebookimages/14774719031/in/photolist-ovAie2-otPK99-xtDX7p-tmxqWf-ow3i43-odd68o-xUPaxW-yHCtWi-wZVsrD-DExW5g-BrzB7b-CmMpC9-oy4hyF-x3UDWA-ow1m4A-x1ij7w-tBdz9a-tQMoRm-wn3tdw-oegTJz-owgrs2-rtpeX1-vNN6g9-owemNT-x3o3pX-wiJyEs-CGCC4W-owg22q-oeT71w-w6PRMn-Ds8gyR-x2Aodm-owoJQm-owtGp9-qVxppC-xM3Gw7-owgV5J-ou9WEs-wihHtF-CRmosE-uk9vB3-wiKdW6-oeGKq3-oeFS4f-x5AZtd-w6PNuv-xgkofr-wZx1gJ-EaYPED-oxCbFP
|
||||
[7]:https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration
|
||||
[8]:https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration
|
||||
[9]:https://opensource.com/user/14106/feed
|
||||
[10]:https://opensource.com/article/17/3/introduction-grub2-configuration-linux#comments
|
||||
[11]:https://opensource.com/users/dboth
|
184
published/201706/20170317 AWS cloud terminology.md
Normal file
184
published/201706/20170317 AWS cloud terminology.md
Normal file
@ -0,0 +1,184 @@
|
||||
AWS 云服务清单
|
||||
============================================================
|
||||
|
||||
|
||||
![AWS Cloud terminology](http://cdn2.kerneltalks.com/wp-content/uploads/2017/03/AWS-Cloud-terminology-150x150.png)
|
||||
|
||||
_认识 71 个 AWS 云服务的术语 ! 通过了解 AWS 世界中使用的术语开始你的 AWS 云服务使用生涯 !_
|
||||
|
||||
|
||||
AWS,即<ruby>亚马逊 Web 服务<rt>Amazon Web Services</rt></ruby>,是一个提供了一系列按使用计费的 web 服务的云平台。 它是迄今为止最为著名的云平台之一。由于其灵活性、有效性、弹性、可测量性和无须维护,所以有一些企业正逐步把他们的业务迁移到云端。 由于许多公司目前在使用这些服务,所以对于系统管理员和运维人员来说应该了解一下 AWS。
|
||||
|
||||
这篇文章旨在列出这些 AWS 提供的服务并且解释在 AWS 中出现的术语。
|
||||
|
||||
截止到目前为止(2017 年 3 月),AWS 提供了分为 17 组的共计 71 种服务:
|
||||
|
||||
|
||||
### 计算型服务
|
||||
|
||||
这是一个提供了虚拟服务器配置功能的服务,即所谓的云计算。它提供了包括以下这一系列的服务。
|
||||
|
||||
1. EC2:EC2 代表弹性计算云。这种服务提供了可根据个人需求扩展的 [虚拟机][11]。
|
||||
2. EC2 容器服务:其高性能,高可扩展性使其可在 EC2 集群环境中运行服务。
|
||||
3. Lightsail:该服务使用户非常容易地启动和管理虚拟服务器(EC2)。
|
||||
4. Elastic Beanstalk:该服务能够自动管理你的应用程序的容量配置、负载平衡、扩展以及健康监控从而减少你的管理压力。
|
||||
5. Lambda:它允许你只在你需要的时候运行代码而不用去管理服务器。
|
||||
6. Batch:它使用户能够以自定义的管理方式运行计算工作负载(批处理)。
|
||||
|
||||
### 存储型服务
|
||||
|
||||
它是一种云存储服务,即由 Amazon 提供的云存储设施。 该组服务包括:
|
||||
|
||||
1. S3:S3 代表简单存储服务(3 个 S)。 它给你提供了在线存储服务,你可随时从任何地方存储/检索任何数据。
|
||||
2. EFS:EFS 代表弹性文件系统。 它是一个可以和 EC2 服务器一起使用的在线存储服务。
|
||||
3. Glacier:它是一种低成本/低性能数据存储解决方案,主要针对存档或长期备份。
|
||||
4. Storage Gateway:这种服务的接口会将你的内部应用程序(托管在 AWS 之外)与 AWS 存储连接。
|
||||
|
||||
### 数据库
|
||||
|
||||
AWS 还提供在其基础设施上托管数据库,以便客户可以利用亚马逊最先进的技术来获得更快/高效/安全的数据处理。 该组包括:
|
||||
|
||||
1. RDS:RDS 代表关系数据库服务。 用于在云上设置,操作和管理关系数据库。
|
||||
2. DynamoDB:其 NoSQL 数据库提供了快速处理和高可扩展性。
|
||||
3. ElastiCache:这是一种为你的 Web 应用程序管理内存缓存以便更快运行它们的方案 !
|
||||
4. Redshift:它是一个巨大的(PB 级)的完全可升级的云端数据仓库服务。
|
||||
|
||||
### 网络 & 内容分发
|
||||
|
||||
由于 AWS 提供云端的 EC2 服务器,因此网络相关内容也将在出现在这里。 内容分发用于向位于最近位置的用户提供文件。 现如今有许多非常有名的加速网站。
|
||||
|
||||
1. VPC:VPC 代表虚拟私有云。 它是你自己的虚拟网络,是你的专用 AWS 帐户。
|
||||
2. CloudFront:这是 AWS 的内容分发网络(CDN)服务。
|
||||
3. Direct Connect:它是将数据中心/场所与 AWS 连接起来的网络方式,以提高吞吐量,降低网络成本,并避免由于基于互联网的连接而导致的连接问题。
|
||||
4. Route 53:它是一个云端的域名系统的 DNS Web 服务。
|
||||
|
||||
### 迁移
|
||||
|
||||
它提供了一系列服务来帮助你实现本地服务到 AWS 的迁移工作。 这包括 :
|
||||
|
||||
1. Application Discovery Service:专门用于分析您的服务器、网络、应用程序以帮助/加速迁移的服务。
|
||||
2. DMS:DMS 指的是数据库迁移服务。 它用于将数据从本地数据库迁移到 EC2 上托管的 RDS 或 DB。
|
||||
3. Server Migration:也称为 SMS(服务器迁移服务)是一种无代理服务,将您的工作负载从本地移动到 AWS。
|
||||
4. Snowball: 当你想要使用物理存储设备(而不是基于互联网/基于网络的传输)将大量数据传入/迁出 AWS 时,你应该使用它。
|
||||
|
||||
### 开发者工具
|
||||
|
||||
顾名思义, 这是一系列帮助开发者简化在云端编码的服务。
|
||||
|
||||
1. CodeCommit:它是一个安全的、可扩展的、可管理的源代码管理服务,用于托管代码仓库。
|
||||
2. CodeBuild:这是一个云端的代码生成器。主要用于执行、测试代码和构建部署软件包。
|
||||
3. CodeDeploy:这是一个可在 AWS 服务器或本地进行自动化应用程序部署的部署服务。
|
||||
4. CodePipeline:这个部署服务可以使编码人员可以在发布之前将其应用程序可视化。
|
||||
5. X-Ray:它可以使用事件调用分析应用程序。
|
||||
|
||||
### 管理工具
|
||||
|
||||
这是一组可帮助你管理 AWS 上的 Web 服务的服务。
|
||||
|
||||
1. CloudWatch:监控你的 AWS 资源或应用程序的监控服务。
|
||||
2. CloudFormation:基础设施即代码!以集体有序的方式管理 AWS 架构的方式。
|
||||
3. CloudTrail:AWS 帐户的审计和合规工具。
|
||||
4. Config : AWS 的资源清单、配置历史记录和配置更改通知,以实现安全性和治理。
|
||||
5. OpsWorks:它可以自动化地配置,部署 EC2 或内部部署计算。
|
||||
6. Service Catalog:创建和管理被批准在你/公司帐户中使用的 IT 服务目录。
|
||||
7. Trusted Advisor:它的 AWS AI 可以通过审查你的 AWS 基础设施使你的 AWS 基础设施更好,更省钱。
|
||||
8. Managed Service:提供持续的基础设施管理。
|
||||
|
||||
|
||||
### 安全性、身份和合规
|
||||
|
||||
这是一组很重要的 AWS 服务以确保你的 AWS 空间的安全性。
|
||||
|
||||
1. IAM:IAM 即身份和访问管理,控制用户访问你的 AWS 资源和服务。
|
||||
2. Inspector:自动安全评估可帮助你在 AWS 上的应用安全和合规。
|
||||
3. Certificate Manager:为 AWS 应用程序提供,管理和部署 SSL / TLS 证书。
|
||||
4. Directory Service:相当于 AWS 的 Microsoft Active Directory。
|
||||
5. WAF & Shield:WAF 即 Web 应用防火墙。 监控和控制对 CloudFront 或负载均衡器上的内容的访问。
|
||||
6. Compliance Reports:AWS 基础设施空间的合规报告,以确保您的应用程序符合您的策略。
|
||||
|
||||
### 数据分析
|
||||
|
||||
AWS 空间的数据分析服务,以帮助您查看、计划和对帐户中的事件采取行动。
|
||||
|
||||
1. Athena:它是一个基于 SQL 查询的服务,用于分析 S3 存储的数据。
|
||||
2. EMR:EMR 的全写是 Elastic Map Reduce。 是一个主要用于大数据处理和分析的服务。
|
||||
3. CloudSearch:AWS 在应用和服务中的搜索功能。
|
||||
4. Elasticsearch Service:它可以创建一个域并在 AWS Cloud 中部署、操作和扩展 Elasticsearch 集群。
|
||||
5. Kinesis:这种服务可以实现实时的大量流数据处理。
|
||||
6. Data Pipeline:它可以帮助我们在不同的 AWS 服务之间实现数据迁移。
|
||||
7. QuickSight:收集、分析和呈现 AWS 的业务数据。
|
||||
|
||||
### 人工智能
|
||||
|
||||
AWS 的 AI!
|
||||
|
||||
1. Lex:它可以帮助我们在一些使用语音和文本的应用中构建会话界面。
|
||||
2. Polly:这是一个提供文字到语音转换的服务。
|
||||
3. Rekognition:使您能够将图像分析添加到应用程序。
|
||||
4. Machine Learning:它具有学习数据中的模式的算法。
|
||||
|
||||
### 物联网
|
||||
|
||||
这个服务保证了 AWS 在不同设备上的高可用性。
|
||||
|
||||
1. AWS IoT:它使联网硬件设备与 AWS 的应用程序能够交互。
|
||||
|
||||
### 游戏开发
|
||||
|
||||
顾名思义,这个服务旨在游戏开发。
|
||||
|
||||
1. Amazon GameLift:该服务旨在部署、管理用于会话的多人游戏的专用游戏服务器。
|
||||
|
||||
### 移动服务
|
||||
|
||||
这是一组主要针对手持设备的服务。
|
||||
|
||||
1. Mobile Hub:帮助您创建移动应用的后台功能并将其集成到移动应用。
|
||||
2. Cognito:在连接了互联网设备上控制移动用户的身份验证和 AWS 的访问。
|
||||
3. Device Farm:移动应用测试服务使你可以在 Android 上托管的真实手机上跨 Android、iOS 测试应用。
|
||||
4. Mobile Analytics:在 AWS 上测量、跟踪和分析移动应用数据。
|
||||
5. Pinpoint:针对性的推送通知和移动互动。
|
||||
|
||||
### 应用服务
|
||||
|
||||
这是一组可以和你在 AWS 上的应用一起使用的服务。
|
||||
|
||||
1. Step Functions:定义和使用应用程序中的各种功能。
|
||||
2. SWF:SWF 代表简单的工作流服务。其云工作流程管理可帮助开发人员在应用程序生命周期的不同阶段进行协调和贡献。
|
||||
3. API Gateway:帮助开发人员创建、管理和托管 API。
|
||||
4. Elastic Transcoder:帮助开发人员将媒体文件转换为在各种设备上可以播放的格式。
|
||||
|
||||
### 消息
|
||||
|
||||
AWS 中的通知和消息服务。
|
||||
|
||||
1. SQS:SQS 表示简单队列服务。完全管理的消息队列服务,用于在 AWS 中的服务和应用之间进行通信。
|
||||
2. SNS:SNS 代表简单通知服务。 为 AWS 用户推送通知服务,提醒他们有关其在 AWS 空间中的服务。
|
||||
3. SES:SES 代表简单电子邮件服务。 这是 AWS 为自己的客户提供高性价比的电子邮件服务。
|
||||
|
||||
### 企业生产率
|
||||
|
||||
一组帮你提高业务生产率的服务。
|
||||
|
||||
1. WorkDocs:协同文件共享、存储和编辑服务。
|
||||
2. WorkMail:安全的商务邮件、日程服务。
|
||||
3. Amazon Chime:在线的企业会议!
|
||||
|
||||
### 桌面和应用程序流式传输
|
||||
|
||||
实现桌面应用程序通过云端进行流传输。
|
||||
|
||||
1. WorkSpaces:完全管理且安全的云计算服务。
|
||||
2. AppStream 2.0:来自云端的流式桌面应用。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://kerneltalks.com/virtualization/aws-cloud-terminology/
|
||||
|
||||
作者:[Shrikant Lavhate][a]
|
||||
译者:[chenxinlong](https://github.com/chenxinlong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://kerneltalks.com/virtualization/aws-cloud-terminology/
|
@ -0,0 +1,454 @@
|
||||
如何用树莓派控制 GOIO 引脚并操作继电器
|
||||
==========================================
|
||||
|
||||
> 学习如何用 PHP 和温度传感器实现树莓派控制 GPIO 并操作继电器
|
||||
|
||||
![How to control GPIO pins and operate relays with the Raspberry Pi](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/raspberry_pi_day_lead_0.jpeg?itok=lCxmviRD "How to control GPIO pins and operate relays with the Raspberry Pi")
|
||||
|
||||
你是否曾经想知道怎样使用手机或者电脑在任何地方控制你的风扇和灯等一些家用电器?
|
||||
|
||||
我现在想控制我的圣诞彩灯,是使用手机呢,还是使用平板电脑呢,或者是使用笔记本电脑呢?都不是,而是仅仅使用一个树莓派。让我来告诉你如何使用 PHP 和温度传感器实现树莓派控制 GPIO 引脚并操作继电器。我使用 AJAX 把它们整合在了一起。
|
||||
|
||||
### 硬件要求:
|
||||
|
||||
* 树莓派
|
||||
* 安装有 Raspbian 系统的 SD 卡(任何一张 SD 卡都可以,但是我更偏向使用大小为 32GB 等级为 class 10 的 SD 卡)
|
||||
* 电源适配器
|
||||
* 跳线(母对母跳线和公转母跳线)
|
||||
* 继电器板(我使用一个用于 12V 继电器的继电器板)
|
||||
* DS18B20 温度传感器
|
||||
* 树莓派的 Wi-Fi 适配器
|
||||
* 路由器(为了访问互联网,你需要有一个拥有端口转发的路由器)
|
||||
* 10KΩ 的电阻
|
||||
|
||||
### 软件要求:
|
||||
|
||||
* 下载并安装 Raspbian 系统到你的 SD 卡
|
||||
* 有效的互联网连接
|
||||
* Apache web 服务器
|
||||
* PHP
|
||||
* WiringPi
|
||||
* 基于 Mac 或者 Windows 的 SSH 客户端
|
||||
|
||||
### 一般的配置和设置
|
||||
|
||||
1、 插入 SD 卡到树莓派,然后使用以太网网线将它连接到路由器;
|
||||
|
||||
2、 连接 WiFi 适配器;
|
||||
|
||||
3、 使用 SSH 方式登录到树莓派,然后使用下面的命令编辑 `interfaces` 文件:
|
||||
|
||||
```
|
||||
sudo nano /etc/network/interfaces
|
||||
```
|
||||
|
||||
这个命令会用一个叫做 `nano` 的编辑器打开这个文件。它是一个非常简单又易于使用的文本编辑器。如果你不熟悉基 Linux 的操作系统,可以使用键盘上的方向键来操作。
|
||||
|
||||
用 `nano` 打开这个文件后,你会看到这样一个界面:
|
||||
|
||||
![File editor nano](https://opensource.com/sites/default/files/putty_0.png "File editor nano")
|
||||
|
||||
4、要配置你的无线网络,按照下面所示修改这个文件:
|
||||
|
||||
```
|
||||
iface lo inet loopback
|
||||
iface eth0 inet dhcp
|
||||
allow-hotplug wlan0
|
||||
auto wlan0
|
||||
iface wlan0 inet dhcp
|
||||
wpa-ssid "Your Network SSID"
|
||||
wpa-psk "Your Password"
|
||||
```
|
||||
|
||||
5、 按 `CTRL+O` 保存,然后按 `CTRL+X` 退出编辑器。
|
||||
|
||||
到目前为止,一切都已经配置完成,接下来你需要做的就是使用命令重新加载网络:
|
||||
|
||||
```
|
||||
sudo service networking reload
|
||||
```
|
||||
|
||||
(警告:如果你是使用远程连接的方式连接的树莓派,连接将会中断。)
|
||||
|
||||
### 软件配置
|
||||
|
||||
#### 安装 Apache web 服务器
|
||||
|
||||
Apache 是一个受欢迎的服务器应用,你可以在树莓派安装这个程序让它提供网页服务。Apache 原本就可以通过 HTTP 方式提供 HTML 文件服务,添加其他模块后,Apache 还可以使用像 PHP 这样的脚本语言来提供动态网页的服务。
|
||||
|
||||
可以在命令行输入下面命令安装 Apache:
|
||||
|
||||
```
|
||||
sudo apt-get install apache2 -y
|
||||
```
|
||||
|
||||
安装完成后,可以在浏览器地址栏输入树莓派的 IP 地址来测试 web 服务器。如果你可以获得下面图片的内容,说明你已经成功地安装并设置好了你的服务器。
|
||||
|
||||
![Successful server setup](https://opensource.com/sites/default/files/itworks.png "Successful server setup")
|
||||
|
||||
要改变这个默认的页面和添加你自己的 html 文件,进入 `var/www/html` 目录:
|
||||
|
||||
```
|
||||
cd /var/www/html
|
||||
```
|
||||
|
||||
添加一些文件来测试是否成功。
|
||||
|
||||
#### 安装 PHP
|
||||
|
||||
PHP 是一个预处理器,这意味着它是当服务器收到网页请求时才会运行的一段代码。它开始运行,处理网页上需要被显示的内容,然后把网页发送给浏览器。不像静态的 HTML,PHP 在不同的环境下可以显示不同的内容。其他的语言也可以做到这一点,但是由于 WordPress 是用 PHP 编写的,有些时候你需要使用它。PHP 是 web 上一种非常受欢迎的语言,像 Facebok 和 Wikipeadia 这样的大型项目都是用 PHP 编写的。
|
||||
|
||||
使用下面的命令安装 PHP 和 Apache 软件包:
|
||||
|
||||
```
|
||||
sudo apt-get install php5 libapache2-mod-php5 -y
|
||||
```
|
||||
|
||||
#### 测试 PHP
|
||||
|
||||
创建文件 `index.php`:
|
||||
|
||||
```
|
||||
sudo nano index.php
|
||||
```
|
||||
|
||||
在里面写入一些 PHP 内容:
|
||||
|
||||
```
|
||||
<?php echo "hello world"; ?>
|
||||
```
|
||||
|
||||
保存文件,接下来删除 `index.html`,因为它比 `index.php` 的优先级更高:
|
||||
|
||||
```
|
||||
sudo rm index.html
|
||||
```
|
||||
|
||||
刷新你的浏览器,你会看到 “hello world”。这并不是动态的,但是它仍然由 PHP 提供服务。如果你在上面看到提原始的 PHP 文件而不是“hello world”,重新加载和重启 Apahce(LCTT 译注,重启即可):
|
||||
|
||||
```
|
||||
sudo /etc/init.d/apache2 reload
|
||||
sudo /etc/init.d/apache2 restart
|
||||
```
|
||||
|
||||
#### 安装 WiringPi
|
||||
|
||||
为了可以对代码的更改进行跟踪,WiringPi 的维护采用 git。但假如你因为某些原因而没法使用 git,还有一种可以替代的方案。(通常你的防火墙会把你隔离开来,所以请先检查一下你的防火墙的设置情况!)
|
||||
|
||||
如果你还没有安装 git,那么在 Debian 及其衍生版本中(比如 Raspbian),你可以这样安装它:
|
||||
|
||||
```
|
||||
sudo apt-get install git-core
|
||||
```
|
||||
|
||||
若是你遇到了一些错误,请确保你的树莓派是最新版本的 Raspbian 系统:
|
||||
|
||||
```
|
||||
sudo apt-get update sudo apt-get upgrade
|
||||
```
|
||||
|
||||
使用 git 获取最 WiringPi:
|
||||
|
||||
```
|
||||
sudo git clone git://git.drogon.net/wiringPi
|
||||
```
|
||||
|
||||
如果你之前已经使用过 clone 操作,那么可以使用下面命令:
|
||||
|
||||
```
|
||||
cd wiringPi && git pull origin
|
||||
```
|
||||
|
||||
这个命令会将会获取更新的版本,你然后可以重新运行下面的构建脚本。
|
||||
|
||||
有一个新的简化的脚本来构建和安装:
|
||||
|
||||
```
|
||||
cd wiringPi && ./build
|
||||
```
|
||||
|
||||
这个新的构建脚本将会为你完成编译和安装 WiringPi。它曾一度需要使用 `sudo` 命令,所以在运行这它之前你可能需要检查一下这个脚本。
|
||||
|
||||
#### 测试 WiringPi
|
||||
|
||||
运行 `gpio` 命令来检查安装成功与否:
|
||||
|
||||
```
|
||||
gpio -v gpio readall
|
||||
```
|
||||
|
||||
这将给你一些信心,软件运行良好。
|
||||
|
||||
#### 连接 DS18B20 传感器到树莓派
|
||||
|
||||
* 传感器上的黑线用于 GND。
|
||||
* 红线用于 VCC。
|
||||
* 黄线是 GPIO 线。
|
||||
|
||||
![GPIO image](https://opensource.com/sites/default/files/gpio_0.png "GPIO image")
|
||||
|
||||
连线:
|
||||
|
||||
* VCC 连接 3V 的 1 号引脚。
|
||||
* GPIO 线连接 7 号引脚(GPIO4)。
|
||||
* 地线连接 GND 的 9 号引脚。
|
||||
|
||||
#### 软件配置
|
||||
|
||||
为了用 PHP 使用 DS18B20 温度传感器模块,你需要执行下面的命令来激活用于树莓派上 GPIO 引脚和 DS18B20 的内核模块:
|
||||
|
||||
```
|
||||
sudo modprobe w1-gpio
|
||||
sudo modprobe w1-therm
|
||||
```
|
||||
|
||||
你不想每次 Raspberry 重启后都手动执行上述命令,所以你想每次开机能自动启动这些模块。可以在文件 `/etc/modules` 中添加下面的命令行来做到:
|
||||
|
||||
```
|
||||
sudo nano /etc/modules/
|
||||
```
|
||||
|
||||
添加下面的命令行到它里面:
|
||||
|
||||
```
|
||||
w1-gpio
|
||||
w1-therm
|
||||
```
|
||||
|
||||
为了测试,输入:
|
||||
|
||||
```
|
||||
cd /sys/bus/w1/devices/
|
||||
```
|
||||
|
||||
现在输入 `ls`。
|
||||
|
||||
你会看到你的设备信息。在设备驱动程序中,你的 DS18B20 传感器应该作为一串字母和数字被列出。在本例中,设备被记录为 `28-000005e2fdc3`。然后你需要使用 `cd` 命令来访问传感器,用你自己的序列号替代我的: `cd 28-000005e2fdc3`。
|
||||
|
||||
DS18B20 会周期性的将数据写入文件 `w1_slave`,所以你只需要使用命令 `cat`来读出数据: `cat w1_slave`。
|
||||
|
||||
这会生成下面的两行文本,输出中 `t=` 表示摄氏单位的温度。在前两位数后面加上一个小数点(例如,我收到的温度读数是 30.125 摄氏度)。
|
||||
|
||||
### 连接继电器
|
||||
|
||||
1、 取两根跳线,把其中一根连接到树莓派上的 GPIO24(18 号引脚),另一根连接 GND 引脚。你可以参考下面这张图。
|
||||
|
||||
2、 现在将跳线的另一端连接到继电器板。GND 连接到继电器上的 GND,GPIO 输出线连接到继电器的通道引脚号,这取决于你正使用的继电器型号。记住,将树莓派上的 GND 与继电器上的 GND 连接连接起来,树莓派上的 GPIO 输出连接继电器上的输入引脚。
|
||||
|
||||
![Headers](https://opensource.com/sites/default/files/headers.png "Headers")
|
||||
|
||||
注意!将继电器连接树莓派的时候小心一些,因为它可能会导致电流回流,这会造成短路。
|
||||
|
||||
3、 现在将电源连接继电器,可以使用 12V 的电源适配器,也可以将 VCC 引脚连接到什么破上的 3.3V 或 5.5V 引脚。
|
||||
|
||||
### 使用 PHP 控制继电器
|
||||
|
||||
让我们先写一个借助于 WiringPi 软件用来控制 Paspberry Pi 上 GPIO 引脚的 PHP 脚本。
|
||||
|
||||
1、在 Apache 服务器的网站根目录下创建一个文件,使用下面命令切换到该目录:
|
||||
|
||||
```
|
||||
cd /var/www/html
|
||||
```
|
||||
|
||||
2、 新建一个叫 `Home` 的文件夹:
|
||||
|
||||
```
|
||||
sudo mkdir Home
|
||||
```
|
||||
|
||||
3、 新建一个叫 `on.php`的脚本
|
||||
|
||||
```
|
||||
sudo nano on.php
|
||||
```
|
||||
|
||||
4、 在脚本中加入下面的代码:
|
||||
|
||||
```
|
||||
<?php
|
||||
|
||||
system("gpio-g mode 24 out");
|
||||
system("gpio-g write 24 1");
|
||||
|
||||
?>
|
||||
```
|
||||
|
||||
5、 使用 `CTRL+O` 保存文件,`CTRL+X` 退出。
|
||||
|
||||
上面的代码中,你在第一行使用命令将 24 号 GPIO引脚设置为 output 模式:
|
||||
|
||||
```
|
||||
system("gpio-g mode 24 out") ;
|
||||
```
|
||||
|
||||
在第二行,你使用 `1` 将 24 号引脚 GPIO 打开,在二进制中"1"表示打开,"0"表示关闭。
|
||||
|
||||
6、 为了关闭继电器,可以创建另外一个 `off.php` 文件,并用 `0` 替换 `1`。
|
||||
|
||||
```
|
||||
<?php
|
||||
|
||||
system(" gpio-g mode 24 out ");
|
||||
system(" gpio-g write 24 1 ");
|
||||
|
||||
?>
|
||||
```
|
||||
|
||||
7、 如果你已经将继电器连接了树莓派,可以在浏览器中输入你的树莓派的 IP 地址,并在后面加上目录名和文件名来进行访问:
|
||||
|
||||
```
|
||||
http://{IPADDRESS}/home/on.php
|
||||
```
|
||||
|
||||
这将会打开继电器。
|
||||
|
||||
8、 要关闭它,可以访问叫 `off.php` 的文件:
|
||||
|
||||
```
|
||||
http://{IPADDRESS}/home/off.php
|
||||
```
|
||||
|
||||
现在你需要能够在一个单独的页面来控制这两样事情,而不用单独的刷新或者访问这两个页面。你可以使用 AJAX 来完成。
|
||||
|
||||
9、 新建一个 HTML 文件,并在其中加入下面代码:
|
||||
|
||||
```
|
||||
[html + php + ajax codeblock]
|
||||
|
||||
<html>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
|
||||
<script type="text/javascript">// <![CDATA[
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#on').click(function(){
|
||||
|
||||
var a= new XMLHttpRequest();
|
||||
|
||||
a.open("GET", "on.php"); a.onreadystatechange=function(){
|
||||
|
||||
if(a.readyState==4){ if(a.status ==200){
|
||||
|
||||
} else alert ("http error"); } }
|
||||
|
||||
a.send();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$(document).ready(function()
|
||||
|
||||
{ $('#Off').click(function(){
|
||||
|
||||
var a= new XMLHttpRequest();
|
||||
|
||||
a.open("GET", "off.php");
|
||||
|
||||
a.onreadystatechange=function(){
|
||||
|
||||
if(a.readyState==4){
|
||||
|
||||
if(a.status ==200){
|
||||
|
||||
} else alert ("http error"); } }
|
||||
|
||||
a.send();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<button id="on" type="button"``Switch Lights On </button>
|
||||
|
||||
<button id="off" type="button"``Switch Lights Off </button>
|
||||
```
|
||||
|
||||
10、 保存文件,进入你的 web 浏览器目录,然后打开那个网页。你会看到两个按钮,它们可以打开和关闭灯泡。基于同样的想法,你还可以使用 bootstrap 和 CSS 来创建一个更加漂亮的 web 界面。
|
||||
|
||||
### 在这个网页上观察温度
|
||||
|
||||
1、 新建一个 `temperature.php` 的文件:
|
||||
|
||||
```
|
||||
sudo nano temperature.php
|
||||
```
|
||||
|
||||
2、 在文件中加入下面的代码,用你自己的设备 ID 替换 `10-000802292522`:
|
||||
|
||||
```
|
||||
<?php
|
||||
//File to read
|
||||
$file = '/sys/devices/w1_bus_master1/10-000802292522/w1_slave';
|
||||
//Read the file line by line
|
||||
$lines = file($file);
|
||||
//Get the temp from second line
|
||||
$temp = explode('=', $lines[1]);
|
||||
//Setup some nice formatting (i.e., 21,3)
|
||||
$temp = number_format($temp[1] / 1000, 1, ',', '');
|
||||
//And echo that temp
|
||||
echo $temp . " °C";
|
||||
?>
|
||||
```
|
||||
|
||||
3、 打开你刚刚创建的 HTML 文件,并创建一个新的带有 `id` 为 “screen” 的 `<div>`标签
|
||||
|
||||
```
|
||||
<div id="screen"></div>
|
||||
```
|
||||
|
||||
4、 在这个标签后或者这个文档的尾部下面的代码:
|
||||
|
||||
```
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
setInterval(function(){
|
||||
$("#screen").load('temperature.php')
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
其中,`#screen` 是标签 `<div>` 的 `id` ,你想在它里面显示温度。它会每隔 1000 毫秒加载一次 `temperature.php` 文件。
|
||||
|
||||
我使用了 bootstrap 框架来制作一个漂亮的面板来显示温度,你还可以加入多个图标和图形让网页更有吸引力。
|
||||
|
||||
这只是一个控制继电器板并显示温度的基础的系统,你可以通过创建基于定时和从恒温器读数等基于事件触发来进一步地对系统进行开发。
|
||||
|
||||
( 题图:opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
作者简介:
|
||||
|
||||
Abdul Hannan Mustajab: 我 17 岁,生活在印度。我正在追求科学,数学和计算机科学方面的教育。我在 spunkytechnology.com 上发表关于我的项目的博客。我一直在对使用不同的微控制器和电路板的基于物联网的 AI 进行研究。
|
||||
|
||||
|
||||
via: https://opensource.com/article/17/3/operate-relays-control-gpio-pins-raspberry-pi
|
||||
|
||||
作者:[Abdul Hannan Mustajab][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/mustajabhannan
|
||||
[1]:http://www.php.net/system
|
||||
[2]:http://www.php.net/system
|
||||
[3]:http://www.php.net/system
|
||||
[4]:http://www.php.net/system
|
||||
[5]:http://www.php.net/system
|
||||
[6]:http://www.php.net/file
|
||||
[7]:http://www.php.net/explode
|
||||
[8]:http://www.php.net/number_format
|
||||
[9]:https://opensource.com/article/17/3/operate-relays-control-gpio-pins-raspberry-pi?rate=RX8QqLzmUb_wEeLw0Ee0UYdp1ehVokKZ-JbbJK_Cn5M
|
||||
[10]:https://opensource.com/user/123336/feed
|
||||
[11]:https://opensource.com/users/mustajabhannan
|
||||
|
||||
|
@ -0,0 +1,99 @@
|
||||
你为什么使用 Linux 和开源软件?
|
||||
============================================================
|
||||
|
||||
> LinuxQuestions.org 的用户分享了他们使用 Linux 和开源技术的原因。我们的用户如何回答这个问题?
|
||||
|
||||
![Why do you use Linux and open source software?](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BUS_consensuscollab2.png?itok=j5vPMv-V "Why do you use Linux and open source software?")
|
||||
|
||||
>图片来源:opensource.com
|
||||
|
||||
在网站问答区发布时我曾经提到过,尽管我一般会回答来自用户问题,但偶尔我也会反过来问读者一些问题。我并没有在问答区第一期文章这样做,看起来有点姗姗来迟。我最近在 LinuxQuestions.org 上提问了两个相关的问题,收到了很多回复。让我们看看我们的用户对同样的问题和 LinuxQuestions.org 的回答的对比。
|
||||
|
||||
### 你为什么使用 Linux?
|
||||
|
||||
我向 LinuxQuestions.org 社区提问的第一个问题是:**[你们使用 Linux 的原因是什么?][1]**
|
||||
|
||||
#### 回答集锦
|
||||
|
||||
_oldwierdal_:我用 Linux 是因为它运行快速、安全、可靠。在全世界的贡献者的参与下,Linux 或许已经成为当前我们能用到的最先进和最具创新的软件。Linux 的用户体验就像红丝绒蛋糕上的糖衣一样令人回味无穷;此外,Linux 是免费的。
|
||||
|
||||
_Timothy Miller_:我最开始使用 Linux 是因为它免费的,而且那时候我的经济条件无法承受购买新的 Windows 系统正版授权的费用。
|
||||
|
||||
_ondoho_ :因为它是一个拥有全球性社区为之努力、独立的草根操作系统。因为它在各方面都是自由的。因为它有足够多的理由让我们信任它。
|
||||
|
||||
_joham34_:稳定、免费、安全,能够运行在低配置的电脑上,提供良好技术支持的社区,感染病毒的几率更小。
|
||||
|
||||
_Ook_:我用 Linux 是因为它可以完成工作,对我来说 Windows 系统在某些事上从来都不能做好。我不得不浪费时间和金钱让 Windows 继续正常运行下去。
|
||||
|
||||
_rhamel_:我非常担心个人隐私泄露在网上。我意识到我不得不在隐私和便利性之间做出妥协。我可能是在骗自己但我确实认为 Linux 至少在某种程度上给了我一定的隐私权。
|
||||
|
||||
_educateme_:我使用 Linux 因为它的开放、好学、热情乐于助人的社区。而且,它是免费的。
|
||||
|
||||
_colinetsegers_:我为什么用 Linux?原因不止一个。简单的说有以下几点:
|
||||
|
||||
1. 自由分享知识的理念。
|
||||
2. 浏览网页的时候有安全感。
|
||||
3. 大量免费、有用的软件。
|
||||
|
||||
_bamunds_:因为我热爱自由。
|
||||
|
||||
_cecilskinner1989_:我用 Linux 的两个原因:稳定性和隐私。
|
||||
|
||||
### 你为什么使用开源软件?
|
||||
|
||||
第二个问题相对更加宽泛:**[你为什么使用开源软件?][2]**你会注意到尽管有些回复是有重复的部分,但用户的回答大体上的语气是不同的,有些用户的回答得到很多人的赞同和支持,也有不少用户的回答不怎么被其他人认同。
|
||||
|
||||
#### 回答集锦
|
||||
|
||||
_robert leleu_:温馨、合作的氛围是我沉溺于开源的主要原因。
|
||||
|
||||
_cjturner_:对于应用而言,开源正好反映了帕累托法则;不做二次开发的话,一个软件包最终可能只能满足你的 80% 的需求,而你需要自己解决剩下的 20%。开源给了你一个途径,通过社区来解决这种问题,你可以自己努力实现(如果你有相关的技能)或者花钱有偿请人实现你的需求。
|
||||
|
||||
_Timothy Miller_:我喜欢这种体验,我能够自己检查源代码来确定我所选择的软件是安全的。
|
||||
|
||||
_teckk_:没有繁琐的许可要求或者数字版权管理(DRM),而且每个人都可以获得它。
|
||||
|
||||
_rokytnji_ :像零花钱,摩托车部件,孙辈的生日礼物那样令人愉悦。
|
||||
|
||||
_timl_:没有自由软件避免隐私的泄露是不可能。
|
||||
|
||||
_hazel_:我喜欢自由软件的哲学,但如果 Linux 是一个糟糕的操作系统我也会理性的不去使用它。我使用 Linux 是因为我热爱 Linux,而且你也能免费获得它就像免费的啤酒一样。事实上它也如言论自由一般自由不受拘束,使用开源软件让我感觉很舒服。但是如果我发现我的计算机有一个硬件需要专有固件的配合才能发挥功能,我也会使用专有固件。
|
||||
|
||||
_lm8_:我使用开源软件是因为我不必担心由于开发公司的破产或者决定停止维护它而导致它可能会变得过时或者被废弃。我能够自己来完成后续的更新、维护。如果我想让软件能够做我想的任何事情,我也可以进一步定制它,但是如果有更多的特性,那就更好了。我也喜欢开源,因为开源我才能够和朋友、同事们分享我喜欢的程序。
|
||||
|
||||
_donguitar_:因为它能够让我学到很多,也让我让别人学到了很多。
|
||||
|
||||
### 该你回答了
|
||||
|
||||
所以,_**你**_ 使用 Linux 的原因是什么? _**你**_ 使用开源软件的原因是什么?请在评论区告诉我们。
|
||||
|
||||
|
||||
#### 最后的补充
|
||||
|
||||
最后,在以后的文章里你想看到什么问题的回答?是社区的建立和维护的相关问题,还是你想知道如何对一个开源项目作出贡献,还是更有技术性的问题 — [向我们提交你对 Linux 和 开源的问题][5]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jeremy Garcia - Jeremy Garcia 是 LinuxQuestions.org 的创立者同时也是一位热情中不乏现实主义的开源倡导者。你可以在 Twitter 上关注 Jeremy:@linuxquestions
|
||||
|
||||
------------------
|
||||
|
||||
via: https://opensource.com/article/17/3/why-do-you-use-linux-and-open-source-software
|
||||
|
||||
作者:[Jeremy Garcia][a]
|
||||
译者:[WangYueScream](https://github.com/WangYueScream)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/jeremy-garcia
|
||||
[1]:http://www.linuxquestions.org/questions/linux-general-1/what-are-the-reasons-you-use-linux-4175600842/
|
||||
[2]:http://www.linuxquestions.org/questions/linux-general-1/what-are-the-reasons-you-use-open-source-software-4175600843/
|
||||
[3]:https://opensource.com/article/17/3/why-do-you-use-linux-and-open-source-software?rate=lVazcbF6Oern5CpV86PgNrRNZltZ8aJZwrUp7SrZIAw
|
||||
[4]:https://opensource.com/tags/queue-column
|
||||
[5]:https://opensource.com/thequeue-submit-question
|
||||
[6]:https://opensource.com/user/86816/feed
|
||||
[7]:https://opensource.com/article/17/3/why-do-you-use-linux-and-open-source-software#comments
|
||||
[8]:https://opensource.com/users/jeremy-garcia
|
@ -1,7 +1,17 @@
|
||||
开发 Linux 调试器第一部分:启动
|
||||
开发一个 Linux 调试器(一):准备环境
|
||||
============================================================
|
||||
|
||||
任何写过 hello world 程序的人都应该使用过调试器(如果你还没有,那就停下手头的工作先学习一下吧)。但是,尽管这些工具已经得到了广泛的使用,却并没有太多的资源告诉你它们的工作原理以及如何开发[1][1],尤其是和其它类似编译器等工具链技术相比的时候。
|
||||
任何写过比 hello world 复杂一些的程序的人都应该使用过调试器(如果你还没有,那就停下手头的工作先学习一下吧)。但是,尽管这些工具已经得到了广泛的使用,却并没有太多的资源告诉你它们的工作原理以及如何开发,尤其是和其它那些比如编译器等工具链技术相比而言。
|
||||
|
||||
> 此处有一些其它的资源可以参考:
|
||||
|
||||
> - http://eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1
|
||||
|
||||
> - https://t-a-w.blogspot.co.uk/2007/03/how-to-code-debuggers.html
|
||||
|
||||
> - https://www.codeproject.com/Articles/43682/Writing-a-basic-Windows-debugger
|
||||
|
||||
> - http://system.joekain.com/debugger/
|
||||
|
||||
我们将会支持以下功能:
|
||||
|
||||
@ -29,37 +39,32 @@
|
||||
|
||||
在本项目中我会将重点放在 C 和 C++,但对于那些将源码编译为机器码并输出标准 DWARE 调试信息的语言也应该能起作用(如果你还不知道这些东西是什么,别担心,马上就会介绍到啦)。另外,我只关注如何将程序运行起来并在大部分情况下能正常工作,为了简便,会避开类似健壮错误处理方面的东西。
|
||||
|
||||
* * *
|
||||
|
||||
### 系列文章索引
|
||||
|
||||
随着后面文章的发布,这些链接会逐渐生效。
|
||||
|
||||
1. [启动][2]
|
||||
1. [准备环境][2]
|
||||
2. [断点][3]
|
||||
3. 寄存器和内存
|
||||
4. Elves 和 dwarves
|
||||
5. 逐步、源码和信号
|
||||
6. 使用 DWARF 调试信息逐步执行
|
||||
5. 源码和信号
|
||||
6. 源码层逐步执行
|
||||
7. 源码层断点
|
||||
8. 调用栈
|
||||
9. 读取变量
|
||||
10. 下一步
|
||||
10. 之后步骤
|
||||
|
||||
译者注:ELF([Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format "Executable and Linkable Format") 可执行文件格式),DWARF(一种广泛使用的调试数据格式,参考 [WIKI](https://en.wikipedia.org/wiki/DWARF "DWARF WIKI"))
|
||||
* * *
|
||||
LCTT 译注:ELF —— <ruby>可执行文件格式<rt>[Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format "Executable and Linkable Format")</rt></ruby>;DWARF(一种广泛使用的调试数据格式,参考 [WIKI](https://en.wikipedia.org/wiki/DWARF "DWARF WIKI"))。
|
||||
|
||||
### 准备环境
|
||||
|
||||
在我们正式开始之前,我们首先要设置环境。在这篇文章中我会依赖两个工具:[Linenoise][4] 用于处理命令行输入,[libelfin][5] 用于解析调试信息。你也可以使用更传统的 libdwarf 而不是 libelin,但是界面没有那么友好,另外 libelfin 还提供大部分完整的 DWARF 表达式求值程序,当你想读取变量的值时这能帮你节省很多时间。确认你使用的是我 libelfin 仓库中的 fbreg 分支,因为它提供 x86 上读取变量的额外支持。
|
||||
在我们正式开始之前,我们首先要设置环境。在这篇文章中我会依赖两个工具:[Linenoise][4] 用于处理命令行输入,[libelfin][5] 用于解析调试信息。你也可以使用更传统的 libdwarf 而不是 libelfin,但是界面没有那么友好,另外 libelfin 还提供了基本完整的 DWARF 表达式求值器,当你想读取变量的值时这能帮你节省很多时间。确认你使用的是 libelfin 我的 fbreg 分支,因为它提供 x86 上读取变量的额外支持。
|
||||
|
||||
一旦你在系统上安装或者使用你喜欢的编译系统编译好了这些依赖工具,就可以开始啦。我在 CMake 文件中把它们设置为和我其余的代码一起编译。
|
||||
|
||||
* * *
|
||||
|
||||
### 启动可执行程序
|
||||
|
||||
在真正调试任何程序之前,我们需要启动被调试的程序。我们会使用经典的 fork/exec 模式。
|
||||
在真正调试任何程序之前,我们需要启动被调试的程序。我们会使用经典的 `fork`/`exec` 模式。
|
||||
|
||||
```
|
||||
int main(int argc, char* argv[]) {
|
||||
@ -82,7 +87,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
```
|
||||
|
||||
我们调用 `fort` 把我们的程序分成两个进程。如果我们是在子进程,`fork` 返回 0,如果我们是在父进程,它会返回子进程的进程ID。
|
||||
我们调用 `fork` 把我们的程序分成两个进程。如果我们是在子进程,`fork` 返回 0,如果我们是在父进程,它会返回子进程的进程 ID。
|
||||
|
||||
如果我们是在子进程,我们要用希望调试的程序替换正在执行的程序。
|
||||
|
||||
@ -91,22 +96,20 @@ int main(int argc, char* argv[]) {
|
||||
execl(prog.c_str(), prog.c_str(), nullptr);
|
||||
```
|
||||
|
||||
这里我们第一次遇到了 `ptrace`,它会在我们编写调试器的时候经常遇到。`ptrace` 通过读取寄存器、内存、逐步调试等让我们观察和控制另一个进程的执行。API 非常简单;你需要给这个简单函数提供一个枚举值用于你想要进行的操作,然后是一些取决于你提供的值可能会被使用也可能会被忽略的参数。函数签名看起来类似:
|
||||
这里我们第一次遇到了 `ptrace`,它会在我们编写调试器的时候经常遇到。`ptrace` 通过读取寄存器、内存、逐步调试等让我们观察和控制另一个进程的执行。其 API 非常简单;你需要给这个简单函数提供一个枚举值指定你想要进行的操作,然后是一些取决于你所提供的值可能会被使用也可能会被忽略的参数。函数原型看起来类似:
|
||||
|
||||
```
|
||||
long ptrace(enum __ptrace_request request, pid_t pid,
|
||||
void *addr, void *data);
|
||||
```
|
||||
|
||||
`request` 是我们想对被跟踪进程进行的操作;`pid` 是被跟踪进程的进程 ID;`addr` 是一个内存地址,用于在一些调用中指定被跟踪程序的地址;`data` 是和 `request` 相应的资源。返回值通常是一些错误信息,因此在你实际的代码中你也许应该检查返回值;为了简洁我这里就省略了。你可以查看 man 手册获取更多(关于 ptrace)的信息。
|
||||
`request` 是我们想对被跟踪进程进行的操作;`pid` 是被跟踪进程的进程 ID;`addr` 是一个内存地址,用于在一些调用中指定被跟踪程序的地址;`data` 是 `request` 相应的资源。返回值通常是一些错误信息,因此在你实际的代码中你也许应该检查返回值;为了简洁我这里就省略了。你可以查看 man 手册获取更多(关于 ptrace)的信息。
|
||||
|
||||
上面代码中我们发送的请求 `PTRACE_TRACEME` 表示这个进程应该允许父进程跟踪它。所有其它参数都会被忽略,因为 API 设计并不是很重要
|
||||
上面代码中我们发送的请求 `PTRACE_TRACEME` 表示这个进程应该允许父进程跟踪它。所有其它参数都会被忽略,因为 API 设计并不是很重要,哈哈。
|
||||
|
||||
下一步,我们会调用 `execl`,这是很多类似的 `exec` 函数之一。我们执行指定的程序,通过命令行参数传递它的名称,然后用一个 `nullptr` 终止列表。如果你愿意,你还可以传递其它执行你的程序所需的参数。
|
||||
下一步,我们会调用 `execl`,这是很多诸多的 `exec` 函数格式之一。我们执行指定的程序,通过命令行参数传递它的名称,然后用一个 `nullptr` 终止列表。如果你愿意,你还可以传递其它执行你的程序所需的参数。
|
||||
|
||||
在完成这些后,我们就会结束子进程的执行;在我们结束它之前它会一直执行。
|
||||
|
||||
* * *
|
||||
在完成这些后,我们就会和子进程一起结束;在我们结束它之前它会一直执行。
|
||||
|
||||
### 添加调试循环
|
||||
|
||||
@ -134,7 +137,7 @@ private:
|
||||
};
|
||||
```
|
||||
|
||||
在 `run` 函数中,我们需要等待,直到子进程完成启动,然后一直从 linenoise 获取输入直到收到 EOF(ctrl+d)。
|
||||
在 `run` 函数中,我们需要等待,直到子进程完成启动,然后一直从 `linenoise` 获取输入直到收到 `EOF`(`CTRL+D`)。
|
||||
|
||||
```
|
||||
void debugger::run() {
|
||||
@ -151,15 +154,13 @@ void debugger::run() {
|
||||
}
|
||||
```
|
||||
|
||||
当被跟踪的进程启动时,会发送一个 `SIGTRAP` 信号给它,这是一个跟踪或者断点中断。我们可以使用 `waitpid` 函数等待直到这个信号被发送。
|
||||
当被跟踪的进程启动时,会发送一个 `SIGTRAP` 信号给它,这是一个跟踪或者断点中断。我们可以使用 `waitpid` 函数等待这个信号发送。
|
||||
|
||||
当我们知道进程可以被调试之后,我们监听用户输入。`linenoise` 函数它自己会用一个窗口显示和处理用户输入。这意味着我们不需要做太多的工作就会有一个有历史记录和导航命令的命令行。当我们获取到输入时,我们把命令发给我们写的小程序 `handle_command`,然后我们把这个命令添加到 linenoise 历史并释放资源。
|
||||
|
||||
* * *
|
||||
当我们知道进程可以被调试之后,我们监听用户输入。`linenoise` 函数它自己会用一个窗口显示和处理用户输入。这意味着我们不需要做太多的工作就会有一个支持历史记录和导航命令的命令行。当我们获取到输入时,我们把命令发给我们写的小程序 `handle_command`,然后我们把这个命令添加到 `linenoise` 历史并释放资源。
|
||||
|
||||
### 处理输入
|
||||
|
||||
我们的命令和 gdb 以及 lldb 有类似的格式。要继续执行程序,用户需要输入 `continue` 或 `cont` 甚至只需 `c`。如果他们想在一个地址中设置断点,他们会输入 `break 0xDEADBEEF`,其中 `0xDEADBEEF` 就是所需地址的 16 进制格式。让我们来增加对这些命令的支持吧。
|
||||
我们的命令类似 gdb 以及 lldb 的格式。要继续执行程序,用户需要输入 `continue` 或 `cont` 甚至只需 `c`。如果他们想在一个地址中设置断点,他们会输入 `break 0xDEADBEEF`,其中 `0xDEADBEEF` 就是所需地址的 16 进制格式。让我们来增加对这些命令的支持吧。
|
||||
|
||||
```
|
||||
void debugger::handle_command(const std::string& line) {
|
||||
@ -222,9 +223,9 @@ void debugger::continue_execution() {
|
||||
|
||||
via: http://blog.tartanllama.xyz/c++/2017/03/21/writing-a-linux-debugger-setup/
|
||||
|
||||
作者:[Simon Brand ][a]
|
||||
作者:[Simon Brand][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user