mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-22 00:40:10 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
252b8af4c2
212
published/20181108 My Google-free Android life.md
Normal file
212
published/20181108 My Google-free Android life.md
Normal file
@ -0,0 +1,212 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (LuuMing)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10677-1.html)
|
||||
[#]: subject: (My Google-free Android life)
|
||||
[#]: via: (https://lushka.al/my-android-setup/)
|
||||
[#]: author: (Anxhelo Lushka https://lushka.al/)
|
||||
|
||||
我的去 Google 化的安卓之旅
|
||||
======
|
||||
> 一篇介绍如何在你的生活中和设备里去 Google 化的文章。
|
||||
|
||||
最近人们经常问我有关我手机的事情,比如安卓怎么安装,怎样绕过 Google Service 使用手机。好吧,这篇文章就来详细的解决那些问题。我尽可能让这篇文章适合初学者,因此我会慢慢介绍,一个一个来讲并且附上截图,你就能更好地看到它是怎样运作的。
|
||||
|
||||
首先我会告诉你为什么 Google Services(在我看来)对你的设备不好。我可以一言以概之,并让你看 [Richard Stallman][2] 写的这篇[文章][1],但我决定抓住几个要点附在这。
|
||||
|
||||
* 要用<ruby>非自由软件<rt>Nonfree software</rt></ruby>
|
||||
* 大体上,大多数 Google Services 需要运行在非自由的 Javascript 代码之上。现如今,如果禁用掉 Javascript,什么都没有了,甚至 Google 帐号都需要运行非自由软件(由站点发送的 JavaScript),对于登录也是。
|
||||
* 被监视
|
||||
* Google 悄悄地把它的<ruby>广告跟踪方式<rt>ad-tracking profiles</rt></ruby>与浏览方式结合在一起,并存储了每个用户的大量数据。
|
||||
* 服务条款
|
||||
* Google 会终止转卖了 Pixel 手机的用户账户。他们无法访问帐户下保存在 Google Services 中的所有邮件和文档。
|
||||
* 审查
|
||||
* Amazon 和 Google 切断了<ruby>域前置<rt>domain-fronting</rt></ruby>,该技术能使身处某些国家的人们访问到在那里禁止的通信系统。
|
||||
* Google 已经同意为巴基斯坦政府执行特殊的 Youtube 审查,删除对立观点。这将有助于压制异议。
|
||||
* Youtube 的“content ID”会自动删除已发布的视频,这并不包含在版权法中。
|
||||
|
||||
这只是几个原因,你可以阅读上面我提到的 RMS 的文章,他详细解释了这几点。尽管听起来骇人听闻,但这些行为在现实生活中已经每天在发生。
|
||||
|
||||
### 下一步,我的搭建教程
|
||||
|
||||
我有一款[小米红米 Note 5 Pro][3] 智能手机(代号 whyred),生产于中国的[小米][4]。它是 4 个月之前(距写这篇文章的时候)我花了大约 185 欧元买的。
|
||||
|
||||
现在你也许会想,“但你为什么买中国品牌,他们不可靠”。是的,它不是通常你所期望的(品牌)所生产的,例如三星(人们通常会将它和安卓联系在一起,这显然是错的)、一加、诺基亚等。但你应当知道几乎所有的手机都生产于中国。
|
||||
|
||||
我选择这款手机有几个原因,首先当然是价格。它是一款<ruby>性价比<rt>budget-friendly</rt></ruby>相当高的产品,大多数人都能买得起。下一个原因是说明书上的规格(不仅仅是),在这个<ruby>价位<rt>price tag</rt></ruby>上相当合适。拥有 6 英尺屏幕(<ruby>全高清分辨率<rt>Full HD resolution</rt></ruby>),4000 毫安电池(一流的电池寿命),4GB RAM,64GB 存储,双后摄像头(12 MP + 5 MP),一个带闪光灯的前摄像头(13 MP)和一个高性能的<ruby>骁龙<rt>Snapdragon</rt></ruby> 636,它可能是那时候最好的选择。
|
||||
|
||||
随之而来的问题是 [MIUI][5],大多数小米设备所附带的安卓外壳(除了 Android One 项目设备)。是的,它没有那么可怕,它有一些额外的功能,但问题在更深的地方。小米设备如此便宜(据我所知销售利润仅有 5-10%)的一个原因是**他们在系统里伴随 MIUI 添加了数据挖掘和广告**。这样的话,系统应用需要额外不必要的权限来获取你的数据并且进行广告轰炸,从中获取利润。
|
||||
|
||||
更有趣的是,所包含的“天气”应用想要访问我的联系人并且拨打电话,如果它仅是显示天气的话为什么需要访问联系人呢。另一个例子是“录音机”应用,它也需要联系人和网络权限,可能想把录音发送回小米。
|
||||
|
||||
为了解决它,我不得不格式化手机并且摆脱 MIUI。在市场上近来的手机上这就变得极为艰难。
|
||||
|
||||
格式化手机的想法很简单,删除掉现有的系统然后安装一个新的喜欢的系统(这次是原生安卓)。为了实现它,你先得解锁 [bootloader][6]。
|
||||
|
||||
> bootloader 是一个在计算机完成自检后为其加载操作系统或者运行环境的计算机程序。—[维基百科][7]
|
||||
|
||||
问题是小米关于解锁 bootloader 有明确的政策。几个月之前,流程就像这样:你需向小米[申请][8]解锁代码,并提供真实的原因,但不是每次都成功,因为他们可以拒绝你的请求并且不提供理由。
|
||||
|
||||
现在,流程变了。你要从小米那下载一个软件,叫做 [Mi Unlock][9],在 Windows 电脑上安装它,在手机的[开发者模式中打开调试选项][10],重启到 bootloader 模式(关机状态下长按向下音量键 + 电源键)并将手机连接到电脑上,开始一个叫做“许可”的流程。这个过程会在小米的服务器上启动一个定时器,允许你**在 15 天之后解锁手机**(在一些少数情况下或者一个月,完全随机)。
|
||||
|
||||
![Mi Unlock app][11]
|
||||
|
||||
15 天过去后,重新连接手机并重复之前的步骤,这时候按下解锁键,你的 bootloader 就会解锁,并且能够安装其他 ROM(系统)。**注意,确保你已经备份好了数据,因为解锁 bootloader 会清空手机。**
|
||||
|
||||
下一步就是找一个兼容的系统([ROM][12])。我在 [XDA 开发者论坛上][13]找了个遍,它是 Android 开发者和用户们交流想法、应用等东西的地方。幸运的是,我的手机相当流行,因此论坛上有它[专门的版块][14]。在那儿,我略过一些流行的 ROM 并决定使用 [AOSiP ROM][15]。(AOSiP 代表<ruby>安卓开源 illusion 项目<rt>Android Open Source illusion Project</rt></ruby>)
|
||||
|
||||
> **校订**:有人发邮件告诉我说文章里写的就是[/e/][16]的目的与所做的事情。我想说谢谢你的帮助,但完全不是这样。我关于 /e/ 的看法背后的原因可以见此[网站][17],但我仍会在此列出一些原因。
|
||||
|
||||
> eelo 是一个从 Kickstarter 和 IndieGoGo 上集资并超过 200K € 的“基金会”,承诺创造一个开放、安全且保护隐私的移动 OS 和网页服务器。
|
||||
|
||||
> 1. 他们的 OS 基于 LineageOS 14.1 (Android 7.1) 且搭载 microG 和其他开源应用,此系统已经存在很长一段时间了并且现在叫做 [Lineage for microG][18]。
|
||||
> 2. 所有的应用程序并非从源代码构建,而是从 [APKPure][19] 上下载安装包并推送进 ROM,不知道那些安装包中是否包含<ruby>专有代码<rt>proprietary code</rt></ruby>或<ruby>恶意软件<rt>malware</rt></ruby>。
|
||||
> 3. 有一段时间,它们就那样随意地从代码中删除 Lineage 的<ruby>版权标头<rt>copyright header</rt></ruby>并加入自己的。
|
||||
> 4. 他们喜欢删除负面反馈并且监视用户 Telegram 群聊中的舆论。
|
||||
|
||||
> 总而言之,我**不建议使用 /e/** ROM。(至少现在)
|
||||
|
||||
另一件你有可能要做的事情是获取手机的 [root 权限][20],让它真正的成为你的手机,并且修改系统中的文件,例如使用系统范围的 adblocker 等。为了实现它,我决定使用 [Magisk][21],一个天赐的应用,它由一个学生开发,可以帮你获取设备的 root 权限并安装一种叫做[模块][22]的东西,基本上是软件。
|
||||
|
||||
下载 ROM 和 Magisk 之后,我得在手机上安装它们。为了完成安装,我将文件移动到了 SD 卡上。现在,若要安装系统,我需要使用 [恢复系统][23]。我用的是较为普遍的 [TWRP][24](代表 TeamWin Recovery Project)。
|
||||
|
||||
要安装恢复系统(听起来有点难,我知道),我需要将文件[烧录][20]进手机。为了完成烧录,我将手机用一个叫做 [ADB 的工具][25]连接上电脑(Fedora Linux 系统)。使用命令让自己定制的恢复系统覆盖掉原先的。
|
||||
|
||||
```
|
||||
fastboot flash recovery twrp.img
|
||||
```
|
||||
|
||||
完成之后,我关掉手机并按住音量上和电源键,直到 TWRP 界面显示。这意味着我进行顺利,并且它已经准备好接收我的指令。
|
||||
|
||||
![TWRP screen][26]
|
||||
|
||||
下一步是**发送擦除命令**,在你第一次为手机安装自定义 ROM 时是必要的。如上图所示,擦除命令会清除掉<ruby>数据<rt>Data</rt></ruby>,<ruby>缓存<rt>Cache</rt></ruby>和 Dalvik 。(这里也有高级选项让我们可以勾选以删除掉系统,如果我们不再需要旧系统的话)
|
||||
|
||||
这需要几分钟去完成,之后,你的手机基本上就干净了。现在是时候**安装系统了**。通过按下主屏幕上的安装按钮,我们选择之前添加进的 zip 文件(ROM 文件)并滑动屏幕安装它。下一步,我们需要安装 Magisk,它可以给我们访问设备的 root 权限。
|
||||
|
||||
> **校订**:一些有经验的安卓用户或发烧友也许注意到了,手机上不包含 [GApps](谷歌应用)。这在安卓世界里称之为 GApps-less,一个 GAps 应用也不安装。
|
||||
|
||||
> 注意有一个不好之处在于若不安装 Google Services 有的应用无法正常工作,例如它们的通知也许会花更长的时间到达或者根本不起作用。(对我来说这一点是最影响应用程序使用的)原因是这些应用使用了 [Google Cloud Messaging][28](现在叫做 [Firebase][29])唤醒手机并推送通知。
|
||||
|
||||
> 你可以通过安装使用 [microG][30](部分地)解决它,microG 提供一些 Google Services 的特性且允许你拥有更多的控制。我不建议使用它,因为它仍然有助于 Google Services 并且你不一定信任它。但是,如果你没法<ruby>立刻放弃使用<rt>go cold turkey on it</rt><ruby>,只想慢慢地退出谷歌,这便是一个好的开始。
|
||||
|
||||
都成功地安装之后,现在我们重启手机,就进入了主屏幕。
|
||||
|
||||
### 下一个部分,安装应用并配置一切
|
||||
|
||||
事情开始变得简单了。为了安装应用,我使用了 [F-Droid][31],一个可替代的应用商店,里面**只包含自由及开源应用**。如果这里没有你要的应用,你可以使用 [Aurora Store][32],一个从应用商店里下载应用且不需要使用谷歌帐号或被追踪的客户端。
|
||||
|
||||
F-Droid 里面有名为 repos 的东西,它是一个包含你可以安装应用的“仓库”。我使用默认的仓库,并从 [IzzyOnDroid][33] 添加了另一个,它有更多默认仓库中没有的应用,并且它更新地更频繁。
|
||||
|
||||
![My repos][34]
|
||||
|
||||
从下面你可以发现我所安装的应用清单,它们替代的应用与用途。
|
||||
|
||||
- [AdAway](https://f-droid.org/en/packages/org.adaway) > 系统广告拦截器,使用 hosts 文件拦截所有的广告
|
||||
- [AfWall+](https://f-droid.org/en/packages/dev.ukanth.ufirewall) > 一个防火墙,可以阻止不想要的连接
|
||||
- [Amaze](https://f-droid.org/en/packages/com.amaze.filemanager) > 替代系统的文件管理器,允许文件的 root 访问权限,并且拥有 zip/unzip 功能
|
||||
- [Ameixa](https://f-droid.org/en/packages/org.xphnx.ameixa) > 大多数应用的图标包
|
||||
- [andOTP](https://f-droid.org/en/packages/org.shadowice.flocke.andotp) > 替代谷歌验证器/Authy,一个可以用来登录启用了<ruby>双因子验证<rt>2FA</rt></ruby>的网站账户的 TOTP 应用,可以使用 PIN 码备份和锁定
|
||||
- [AnySoftKeyboard/AOSP Keyboard](https://f-droid.org/packages/com.menny.android.anysoftkeyboard/) > 开源键盘,它有许多主题和语言包,我也是该[项目](https://anysoftkeyboard.github.io/)的一员
|
||||
- [Audio Recorder](https://f-droid.org/en/packages/com.github.axet.audiorecorder) > 如其名字,允许你从麦克风录制不同格式的音频文件
|
||||
- [Battery Charge Limit](https://f-droid.org/en/packages/com.slash.batterychargelimit) > 当到 80% 时自动停止充电,降低<ruby>电池磨损<rt>battery wear</rt></ruby>并增加寿命
|
||||
- [DAVx5](https://f-droid.org/en/packages/at.bitfire.davdroid) > 这是我最常用的应用之一,对我来说它基本上替代了谷歌联系人、谷歌日历和谷歌 Tasks,它连接着我的 Nextcloud 环境可以让我完全控制自己的数据
|
||||
- [Document Viewer](https://f-droid.org/en/packages/org.sufficientlysecure.viewer) > 一个可以打开数百种文件格式的查看器应用,快速、轻量
|
||||
- [Deezloader Remix](https://gitlab.com/Nick80835/DeezLoader-Android/) > 让我可以在 Deezer 上下载高质量 MP3 的应用
|
||||
- [Easy xkcd](https://f-droid.org/en/packages/de.tap.easy_xkcd) > xkcd 漫画阅读器,我喜欢这些 xkcd 漫画
|
||||
- [Etar](https://f-droid.org/en/packages/ws.xsoh.etar) > 日历应用,替代谷歌日历,与 DAVx5 一同工作
|
||||
- [FastHub-Libre](https://f-droid.org/en/packages/com.fastaccess.github.libre) > 一个 GitHub 客户端,完全 FOSS(自由及开源软件),非常实用如果你像我一样喜欢使用 Github 的话
|
||||
- [Fennec F-Droid](https://f-droid.org/en/packages/org.mozilla.fennec_fdroid) > 替代谷歌 Chrome 和其他类似的应用,一个为 F-Droid 打造的火狐浏览器,不含专有二进制代码并允许安装扩展提升浏览体验
|
||||
- [Gadgetbridge](https://f-droid.org/en/packages/nodomain.freeyourgadget.gadgetbridge) > 替代小米运动,可以用来配对小米硬件的应用,追踪你的健康、步数、睡眠等。
|
||||
- [K-9 Mail](https://f-droid.org/en/packages/com.fsck.k9) > 邮件客户端,替代 GMail 应用,可定制并可以添加多个账户
|
||||
- [Lawnchair](https://f-droid.org/en/packages/ch.deletescape.lawnchair.plah) > 启动器,可以替代 Nova Launcher 或 Pixel Launcher,允许自定义和各种改变,也支持图标包
|
||||
- [Mattermost](https://f-droid.org/en/packages/com.mattermost.mattermost) > 可以连接 Mattermost 服务器的应用。Mattermost 是一个 Slack 替代品
|
||||
- [NewPipe](https://f-droid.org/en/packages/org.schabi.newpipe) > 最好的 YouTube 客户端(我认为),可以替代 YoubTube,它完全是 FOSS,免除 YouTube 广告,占用更少空间,允许背景播放,允许下载视频/音频等。试一试吧
|
||||
- [Nextcloud SMS](https://f-droid.org/en/packages/fr.unix_experience.owncloud_sms) > 允许备份/同步 SMS 到我的 Nextcloud 环境
|
||||
- [Nextcloud Notes](https://f-droid.org/en/packages/it.niedermann.owncloud.notes) > 允许我创建,修改,删除,分享笔记并同步/备份到 Nextcloud 环境
|
||||
- [OpenTasks](https://f-droid.org/en/packages/org.dmfs.tasks) > 允许我创建、修改、删除任务并同步到我的 Nextcloud 环境
|
||||
- [OsmAnd~](https://f-droid.org/en/packages/net.osmand.plus) > 一个地图应用,使用 [OpenStreetMap](https://openstreetmap.org/),允许下载离线地图和导航
|
||||
- [QKSMS](https://f-droid.org/en/packages/com.moez.QKSMS) > 我最喜欢的短信应用,可以替代原来的 Messaging 应用,拥有漂亮的界面,拥有备份、个性化、延迟发送等特性。
|
||||
- [Resplash/Mysplash](https://f-droid.org/en/packages/com.wangdaye.mysplash) > 允许你无限地从 [Unsplash](https://unsplash.com/) 下载无数的漂亮壁纸,全都可以免费使用和修改。
|
||||
- [ScreenCam](https://f-droid.org/en/packages/com.orpheusdroid.screenrecorder) > 一个录屏工具,允许各样的自定义和录制模式,没有广告并且免费
|
||||
- [SecScanQR](https://f-droid.org/en/packages/de.t_dankworth.secscanqr) > 二维码识别应用,快速轻量
|
||||
- [Send Reduced Free](https://f-droid.org/en/packages/mobi.omegacentauri.SendReduced) > 这个应用可以在发送之前通过移除 PII(<ruby>个人识别信息<rt>personally identifiable information</rt></ruby>)和减小尺寸,让你立即分享大图
|
||||
- [Slide](https://f-droid.org/en/packages/me.ccrama.redditslide/) > 开源 Reddit 客户端
|
||||
- [Telegram FOSS](https://f-droid.org/en/packages/org.telegram.messenger) > 没有追踪和 Google Services 的纯净版 Telegram 安卓客户端
|
||||
- [TrebleShot](https://f-droid.org/en/packages/com.genonbeta.TrebleShot) > 这个天才般的应用可以让你通过 WIFI 分享文件给其它设备,真的超快,甚至无需连接网络
|
||||
- [Tusky](https://f-droid.org/en/packages/com.keylesspalace.tusky) > Tusky 是 [Mastodon](https://joinmastodon.org/) 平台的客户端(替代 Twitter)
|
||||
- [Unit Converter Ultimate](https://f-droid.org/en/packages/com.physphil.android.unitconverterultimate) > 这款应用可以一键在 200 种单位之间来回转换,非常快并且完全离线
|
||||
- [Vinyl Music Player](https://f-droid.org/en/packages/com.poupa.vinylmusicplayer) > 我首选的音乐播放器,可以替代谷歌音乐播放器或其他你已经安装的音乐播放器,它有漂亮的界面和许多特性
|
||||
- [VPN Hotspot](https://f-droid.org/en/packages/be.mygod.vpnhotspot) > 这款应用可以让我打开热点的时候分享 VPN,因此我可以在笔记本上什么都不用做就可以安全地浏览网页
|
||||
|
||||
这些差不多就是我列出的一张**最实用的 F-Droid 应用**清单,但不巧,这些并不是所有应用。我使用的专有应用如下(我知道,我也许听起来是一个伪君子,但并不是所有的应用都可以替代,至少现在不是):
|
||||
|
||||
* Google Camera(与 Camera API 2 结合起来,需要 F-Droid 的基本的 microG 才能工作)
|
||||
* Instagram
|
||||
* MyVodafoneAL (运营商应用)
|
||||
* ProtonMail (email 应用)
|
||||
* Titanium Backup(备份应用数据,wifi 密码,通话记录等)
|
||||
* WhatsApp (专有的端到端聊天应用,几乎我认识的所有人都有它)
|
||||
|
||||
差不多就是这样,这就是我用的手机上所有的应用。**配置非常简单明了,我可以给几点提示**。
|
||||
|
||||
1. 仔细阅读和检查应用的权限,不要无脑地点“安装”。
|
||||
2. 尽可能多地使用开源应用,它们即尊重你的隐私又是免费的(且自由)。
|
||||
3. 尽可能地使用 VPN,找一个有名气的,别用免费的,否则你将被收割数据然后成为产品。
|
||||
4. 不要一直打开 WIFI/移动数据/定位,有可能引起安全隐患。
|
||||
5. 不要只依赖指纹解锁,或者尽可能只用 PIN/密码/模式解锁,因为生物数据可以被克隆后针对你,例如解锁你的手机盗取你的数据。
|
||||
|
||||
作为坚持读到这儿的奖励,**一张主屏幕的截图奉上**
|
||||
|
||||
![Screenshot][35]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://lushka.al/my-android-setup/
|
||||
|
||||
作者:[Anxhelo Lushka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[LuuMing](https://github.com/luuming)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://lushka.al/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://stallman.org/google.html
|
||||
[2]: https://en.wikipedia.org/wiki/Richard_Stallman
|
||||
[3]: https://www.gsmarena.com/xiaomi_redmi_note_5_pro-8893.php
|
||||
[4]: https://en.wikipedia.org/wiki/Xiaomi
|
||||
[5]: https://en.wikipedia.org/wiki/MIUI
|
||||
[6]: https://forum.xda-developers.com/wiki/Bootloader
|
||||
[7]: https://en.wikipedia.org/wiki/Booting
|
||||
[8]: https://en.miui.com/unlock/
|
||||
[9]: http://www.miui.com/unlock/apply.php
|
||||
[10]: https://www.youtube.com/watch?v=7zhEsJlivFA
|
||||
[11]: https://lushka.al//assets/img/posts/mi-unlock.png
|
||||
[12]: https://www.xda-developers.com/what-is-custom-rom-android/
|
||||
[13]: https://forum.xda-developers.com/
|
||||
[14]: https://forum.xda-developers.com/redmi-note-5-pro
|
||||
[15]: https://forum.xda-developers.com/redmi-note-5-pro/development/rom-aosip-8-1-t3804473
|
||||
[16]: https://e.foundation
|
||||
[17]: https://ewwlo.xyz/evil
|
||||
[18]: https://lineage.microg.org/
|
||||
[19]: https://apkpure.com/
|
||||
[20]: https://lifehacker.com/5789397/the-always-up-to-date-guide-to-rooting-any-android-phone
|
||||
[21]: https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445
|
||||
[22]: https://forum.xda-developers.com/apps/magisk
|
||||
[23]: http://www.smartmobilephonesolutions.com/content/android-system-recovery
|
||||
[24]: https://dl.twrp.me/whyred/
|
||||
[25]: https://developer.android.com/studio/command-line/adb
|
||||
[26]: https://lushka.al//assets/img/posts/android-twrp.png
|
||||
[27]: https://opengapps.org/
|
||||
[28]: https://developers.google.com/cloud-messaging/
|
||||
[29]: https://firebase.google.com/docs/cloud-messaging/
|
||||
[30]: https://microg.org/
|
||||
[31]: https://f-droid.org/
|
||||
[32]: https://f-droid.org/en/packages/com.dragons.aurora/
|
||||
[33]: https://android.izzysoft.de/repo
|
||||
[34]: https://lushka.al//assets/img/posts/android-fdroid-repos.jpg
|
||||
[35]: https://lushka.al//assets/img/posts/android-screenshot.jpg
|
||||
[36]: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
@ -0,0 +1,97 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Managing changes in open source projects)
|
||||
[#]: via: (https://opensource.com/article/19/3/managing-changes-open-source-projects)
|
||||
[#]: author: (Ben Cotton (Red Hat, Community Moderator) https://opensource.com/users/bcotton)
|
||||
|
||||
Managing changes in open source projects
|
||||
======
|
||||
|
||||
Here's how to create a visible change process to support the community around an open source project.
|
||||
|
||||
![scrabble letters: "time for change"][1]
|
||||
|
||||
Why bother having a process for proposing changes to your open source project? Why not just let people do what they're doing and merge the features when they're ready? Well, you can certainly do that if you're the only person on the project. Or maybe if it's just you and a few friends.
|
||||
|
||||
But if the project is large, you might need to coordinate how some of the changes land. Or, at the very least, let people know a change is coming so they can adjust if it affects the parts they work on. A visible change process is also helpful to the community. It allows them to give feedback that can improve your idea. And if nothing else, it lets people know what's coming so that they can get excited, and maybe get you a little bit of coverage on Opensource.com or the like. Basically, it's "here's what I'm going to do" instead of "here's what I did," and it might save you some headaches as you scramble to QA right before your release.
|
||||
|
||||
So let's say I've convinced you that having a change process is a good idea. How do you build one?
|
||||
|
||||
**[Watch my talk on this topic]**
|
||||
<https://www.youtube.com/embed/cVV1K3Junkc>
|
||||
|
||||
### Right-size your change process
|
||||
|
||||
Before we start talking about what a change process looks like, I want to make it very clear that this is not a one-size-fits-all situation. The smaller your project is—mainly in the number of contributors—the less process you'll probably need. As [Richard Hackman says][2], the number of communication channels in a team goes up exponentially with the number of people on the team. In community-driven projects, this becomes even more complicated as people come and go, and even your long-time contributors might not be checking in every day. So the change process consolidates those communication channels into a single area where people can quickly check to see if they care and then get back to whatever it is they do.
|
||||
|
||||
At one end of the scale, there's the command-line Twitter client I maintain. The change process there is, "I pick something I want to work on, probably make a Git branch for it but I might forget that, merge it, and tag a release when I'm out of stuff that I can/want to do." At the other end is Fedora. Fedora isn't really a single project; it's a program of related projects that mostly move in the same direction. More than 200 people a week touch Fedora in a technical sense: spec file maintenance, build submission, etc. This doesn't even include the untold number of people who are working on the upstreams. And these upstreams all have their own release schedules and their own processes for how features land and when. Nobody can keep up with everything on their own, so the change process brings important changes to light.
|
||||
|
||||
### Decide who needs to review changes
|
||||
|
||||
One of the first things you need to consider when putting together a change process for your community is: "who needs to review changes?" This isn't necessarily approving the changes; we'll come to that shortly. But are there people who should take a look early in the process? Maybe your release engineering or infrastructure teams need to review them to make sure they don't require changes to build infrastructure. Maybe you have a legal review process to make sure licenses are in order. Or maybe you just have a change wrangler who looks to make sure all the required information is included. Or you may choose to do none of these and have change proposals go directly to the community.
|
||||
|
||||
But this brings up the next step. Do you want full community feedback or only a select group to provide feedback? My preference, and what we do in Fedora, is to publish changes to the community before they're approved. But the structure of your community may fit a model where some approval body signs off on the change before it is sent to the community as an announcement.
|
||||
|
||||
### Determine who approves changes
|
||||
|
||||
Even if you lack any sort of organizational structure, someone ends up approving changes. This should reflect the norms and values of your community. The simplest form of approval is the person who proposed the change implements it. Easy peasy! In loosely organized communities, that might work. Fully democratic communities might put it to a community-wide vote. If a certain number or proportion of members votes in favor, the change is approved. Other communities may give that power to an individual or group. They could be responsible for the entire project or certain subsections.
|
||||
|
||||
In Fedora, change approval is the role of the Fedora Engineering Steering Committee (FESCo). This is a nine-person body elected by community members. This gives the community the ability to remove members who are not acting in the best interests of the project but also enables relatively quick decisions without large overhead.
|
||||
|
||||
In much of this article, I am simply presenting information, but I'm going to take a moment to be opinionated. For any project with a significant contributor base, a model where a small body makes approval decisions is the right approach. A pure democracy can be pretty messy. People who may have no familiarity with the technical ramifications of a change will be able to cast a binding vote. And that process is subject to "brigading," where someone brings along a large group of otherwise-uninterested people to support their position. Think about what it might look like if someone proposed changing the default text editor. Would the decision process be rational?
|
||||
|
||||
### Plan how to enforce changes
|
||||
|
||||
The other advantage of having a defined approval body is it can mediate conflicts between changes. What happens if two proposed changes conflict? Or if a change turns out to have a negative impact? Someone needs to have the authority to say "this isn't going in after all" or make sure conflicting changes are brought into agreement. Your QA team and processes will be a part of this, and maybe they're the ones who will make the final call.
|
||||
|
||||
It's relatively straightforward to come up with a plan if a change doesn't work as expected or is incomplete by the deadline. If you require a contingency plan as part of the change process, then you implement that plan. The harder part is: what happens if someone makes a change that doesn't go through your change process? Here's a secret your friendly project manager doesn't want you to know: you can't force people to go through your process, particularly in community projects.
|
||||
|
||||
So if something sneaks in and you don't discover it until you have a release candidate, you have a couple of options: you can let it in, or you can get someone to forcibly remove it. In either case, you'll have someone who is very unhappy. Either the person who made the change, because you kicked their work out, or the people who had to deal with the breakage it caused. (If it snuck in without anyone noticing, then it's probably not that big of a deal.)
|
||||
|
||||
The answer, in either case, is going to be social pressure to follow the process. Processes are sometimes painful to follow, but a well-designed and well-maintained process will give more benefit than it costs. In this case, the benefit may be identifying breakages sooner or giving other developers a chance to take advantage of new features that are offered. And it can help prevent slips in the release schedule or hero effort from your QA team.
|
||||
|
||||
### Implement your change process
|
||||
|
||||
So we've thought about the life of a change proposal in your project. Throw in some deadlines that make sense for your release cadence, and you can now come up with the policy—but how do you implement it?
|
||||
|
||||
First, you'll want to identify the required information for a change proposal. At a minimum, I'd suggest the following. You may have more requirements depending on the specifics of what your community is making and how it operates.
|
||||
|
||||
* Name and summary
|
||||
* Benefit to the project
|
||||
* Scope
|
||||
* Owner
|
||||
* Test plan
|
||||
* Dependencies and impacts
|
||||
* Contingency plan
|
||||
|
||||
|
||||
|
||||
You'll also want one or several change wranglers. These aren't gatekeepers so much as shepherds. They may not have the ability to approve or reject change proposals, but they are responsible for moving the proposals through the process. They check the proposal for completeness, submit it to the appropriate bodies, make appropriate announcements, etc. You can have people wrangle their own changes, but this can be a specialized task and will generally benefit from a dedicated person who does this regularly, instead of making community members do it less frequently.
|
||||
|
||||
And you'll need some tooling to manage these changes. This could be a wiki page, a kanban board, a ticket tracker, something else, or a combination of these. But basically, you want to be able to track their state and provide some easy reporting on the status of changes. This makes it easier to know what is complete, what is at risk, and what needs to be deferred to a later release. You can use whatever works best for you, but in general, you'll want to minimize copy-and-pasting and maximize scriptability.
|
||||
|
||||
### Remember to iterate
|
||||
|
||||
Your change process may seem perfect. Then people will start using it. You'll discover edge cases you didn't consider. You'll find that the community hates a certain part of it. Decisions that were once valid will become invalid over time as technology and society change. In Fedora, our Features process revealed itself to be ambiguous and burdensome, so it was refined into the [Changes][3] process we use today. Even though the Changes process is much better than its predecessor, we still adjust it here and there to make sure it's best meeting the needs of the community.
|
||||
|
||||
When designing your process, make sure it fits the size and values of your community. Consider who gets a voice and who gets a vote in approving changes. Come up with a plan for how you'll handle incomplete changes and other exceptions. Decide who will guide the changes through the process and how they'll be tracked. And once you design your change policy, write it down in a place that's easy for your community to find so that they can follow it. But most of all, remember that the process is here to serve the community; the community is not here to serve the process.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/managing-changes-open-source-projects
|
||||
|
||||
作者:[Ben Cotton (Red Hat, Community Moderator)][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/bcotton
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/change_words_scrabble_letters.jpg?itok=mbRFmPJ1 (scrabble letters: "time for change")
|
||||
[2]: https://hbr.org/2009/05/why-teams-dont-work
|
||||
[3]: https://fedoraproject.org/wiki/Changes/Policy
|
@ -0,0 +1,139 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (9 open source tools for building a fault-tolerant system)
|
||||
[#]: via: (https://opensource.com/article/19/3/tools-fault-tolerant-system)
|
||||
[#]: author: (Bryant Son (Red Hat, Community Moderator) https://opensource.com/users/brson)
|
||||
|
||||
9 open source tools for building a fault-tolerant system
|
||||
======
|
||||
|
||||
Maximize uptime and minimize problems with these open source tools.
|
||||
|
||||
![magnifying glass on computer screen, finding a bug in the code][1]
|
||||
|
||||
I've always been interested in web development and software architecture because I like to see the broader picture of a working system. Whether you are building a mobile app or a web application, it has to be connected to the internet to exchange data among different modules, which means you need a web service.
|
||||
|
||||
If you use a cloud system as your application's backend, you can take advantage of greater computing power, as the backend service will scale horizontally and vertically and orchestrate different services. But whether or not you use a cloud backend, it's important to build a _fault-tolerant system_ —one that is resilient, stable, fast, and safe.
|
||||
|
||||
To understand fault-tolerant systems, let's use Facebook, Amazon, Google, and Netflix as examples. Millions and billions of users access these platforms simultaneously while transmitting enormous amounts of data via peer-to-peer and user-to-server networks, and you can be sure there are also malicious users with bad intentions, like hacking or denial-of-service (DoS) attacks. Even so, these platforms can operate 24 hours a day and 365 days a year without downtime.
|
||||
|
||||
Although machine learning and smart algorithms are the backbones of these systems, the fact that they achieve consistent service without a single minute of downtime is praiseworthy. Their expensive hardware and gigantic datacenters certainly matter, but the elegant software designs supporting the services are equally important. And the fault-tolerant system is one of the principles to build such an elegant system.
|
||||
|
||||
### Two behaviors that cause problems in production
|
||||
|
||||
Here's another way to think of a fault-tolerant system. When you run your application service locally, everything seems to be fine. Great! But when you promote your service to the production environment, all hell breaks loose. In a situation like this, a fault-tolerant system helps by addressing two problems: Fail-stop behavior and Byzantine behavior.
|
||||
|
||||
#### Fail-stop behavior
|
||||
|
||||
Fail-stop behavior is when a running system suddenly halts or a few parts of the system fail. Server downtime and database inaccessibility fall under this category. For example, in the diagram below, Service 1 can't communicate with Service 2 because Service 2 is inaccessible:
|
||||
|
||||
![Fail-stop behavior due to Service 2 downtime][2]
|
||||
|
||||
But the problem can also occur if there is a network problem between the services, like this:
|
||||
|
||||
![Fail-stop behavior due to network failure][3]
|
||||
|
||||
#### Byzantine behavior
|
||||
|
||||
Byzantine behavior is when the system continuously runs but doesn't produce the expected behavior (e.g., wrong data or an invalid value).
|
||||
|
||||
Byzantine failure can happen if Service 2 has corrupted data or values, even though the service looks to be operating just fine, like in this example:
|
||||
|
||||
![Byzantine failure due to corrupted service][4]
|
||||
|
||||
Or, there can be a malicious middleman intercepting between the services and injecting unwanted data:
|
||||
|
||||
![Byzantine failure due to malicious middleman][5]
|
||||
|
||||
Neither fail-stop nor Byzantine behavior is a desired situation, so we need ways to prevent or fix them. That's where fault-tolerant systems come into play. Following are eight open source tools that can help you address these problems.
|
||||
|
||||
### Tools for building a fault-tolerant system
|
||||
|
||||
Although building a truly practical fault-tolerant system touches upon in-depth _distributed computing theory_ and complex computer science principles, there are many software tools—many of them, like the following, open source—to alleviate undesirable results by building a fault-tolerant system.
|
||||
|
||||
#### Circuit-breaker pattern: Hystrix and Resilience4j
|
||||
|
||||
The [circuit-breaker pattern][6] is a technique that helps to return a prepared dummy response or a simple response when a service fails:
|
||||
|
||||
![Circuit breaker pattern][7]
|
||||
|
||||
Netflix's open source **[Hystrix][8]** is the most popular implementation of the circuit-breaker pattern.
|
||||
|
||||
Many companies where I've worked previously are leveraging this wonderful tool. Surprisingly, Netflix announced that it will no longer update Hystrix. (Yeah, I know.) Instead, Netflix recommends using an alternative solution like [**Resilence4j**][9], which supports Java 8 and functional programming, or an alternative practice like [Adaptive Concurrency Limit][10].
|
||||
|
||||
#### Load balancing: Nginx and HaProxy
|
||||
|
||||
Load balancing is one of the most fundamental concepts in a distributed system and must be present to have a production-quality environment. To understand load balancers, we first need to understand the concept of _redundancy_. Every production-quality web service has multiple servers that provide redundancy to take over and maintain services when servers go down.
|
||||
|
||||
![Load balancer][11]
|
||||
|
||||
Think about modern airplanes: their dual engines provide redundancy that allows them to land safely even if an engine catches fire. (It also helps that most commercial airplanes have state-of-art, automated systems.) But, having multiple engines (or servers) means that there must be some kind of scheduling mechanism to effectively route the system when something fails.
|
||||
|
||||
A load balancer is a device or software that optimizes heavy traffic transactions by balancing multiple server nodes. For instance, when thousands of requests come in, the load balancer acts as the middle layer to route and evenly distribute traffic across different servers. If a server goes down, the load balancer forwards requests to the other servers that are running well.
|
||||
|
||||
There are many load balancers available, but the two best-known ones are Nginx and HaProxy.
|
||||
|
||||
[**Nginx**][12] is more than a load balancer. It is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server. Companies like Groupon, Capital One, Adobe, and NASA use it.
|
||||
|
||||
[**HaProxy**][13] is also popular, as it is a free, very fast and reliable solution offering high availability, load balancing, and proxying for TCP and HTTP-based applications. Many large internet companies, including GitHub, Reddit, Twitter, and Stack Overflow, use HaProxy. Oh and yes, Red Hat Enterprise Linux also supports HaProxy configuration.
|
||||
|
||||
#### Actor model: Akka
|
||||
|
||||
The [actor model][14] is a concurrency design pattern that delegates responsibility when an _actor_ , which is a primitive unit of computation, receives a message. An actor can create even more actors and delegate the message to them.
|
||||
|
||||
[**Akka**][15] is one of the most well-known tools for the actor model implementation. The framework supports Java and Scala, which are both based on JVM.
|
||||
|
||||
#### Asynchronous, non-blocking I/O using messaging queue: Kafka and RabbitMQ
|
||||
|
||||
Multi-threaded development has been popular in the past, but this practice has been discouraged and replaced with asynchronous, non-blocking I/O patterns. For Java, this is explicitly stated in its [Enterprise Java Bean (EJB) specifications][16]:
|
||||
|
||||
> "An enterprise bean must not use thread synchronization primitives to synchronize execution of multiple instances.
|
||||
>
|
||||
> "The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread's priority or name. The enterprise bean must not attempt to manage thread groups."
|
||||
|
||||
Now, there are other practices like stream APIs and actor models. But messaging queues like [**Kafka**][17] and [**RabbitMQ**][18] offer the out-of-box support for asynchronous and non-blocking IO features, and they are powerful open source tools that can be replacements for threads by handling concurrent processes.
|
||||
|
||||
#### Other options: Eureka and Chaos Monkey
|
||||
|
||||
Other useful tools for fault-tolerant systems include monitoring tools, such as Netflix's **[Eureka][19]** , and stress-testing tools, like **[Chaos Monkey][20]**. They aim to discover potential issues earlier by testing in lower environments, like integration (INT), quality assurance (QA), and user acceptance testing (UAT), to prevent potential problems before moving to the production environment.
|
||||
|
||||
* * *
|
||||
|
||||
What open source tools are you using for building a fault-tolerant system? Please share your favorites in the comments.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/tools-fault-tolerant-system
|
||||
|
||||
作者:[Bryant Son (Red Hat, Community Moderator)][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/brson
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/mistake_bug_fix_find_error.png?itok=PZaz3dga (magnifying glass on computer screen, finding a bug in the code)
|
||||
[2]: https://opensource.com/sites/default/files/uploads/1_errordowntimeservice.jpg (Fail-stop behavior due to Service 2 downtime)
|
||||
[3]: https://opensource.com/sites/default/files/uploads/2_errordowntimenetwork.jpg (Fail-stop behavior due to network failure)
|
||||
[4]: https://opensource.com/sites/default/files/uploads/3_byzantinefailuremalicious.jpg (Byzantine failure due to corrupted service)
|
||||
[5]: https://opensource.com/sites/default/files/uploads/4_byzantinefailuremiddleman.jpg (Byzantine failure due to malicious middleman)
|
||||
[6]: https://martinfowler.com/bliki/CircuitBreaker.html
|
||||
[7]: https://opensource.com/sites/default/files/uploads/5_circuitbreakerpattern.jpg (Circuit breaker pattern)
|
||||
[8]: https://github.com/Netflix/Hystrix/wiki
|
||||
[9]: https://github.com/resilience4j/resilience4j
|
||||
[10]: https://medium.com/@NetflixTechBlog/performance-under-load-3e6fa9a60581
|
||||
[11]: https://opensource.com/sites/default/files/uploads/7_loadbalancer.jpg (Load balancer)
|
||||
[12]: https://www.nginx.com
|
||||
[13]: https://www.haproxy.org
|
||||
[14]: https://en.wikipedia.org/wiki/Actor_model
|
||||
[15]: https://akka.io
|
||||
[16]: https://jcp.org/aboutJava/communityprocess/final/jsr220/index.html
|
||||
[17]: https://kafka.apache.org
|
||||
[18]: https://www.rabbitmq.com
|
||||
[19]: https://github.com/Netflix/eureka
|
||||
[20]: https://github.com/Netflix/chaosmonkey
|
104
sources/tech/20171226 The shell scripting trap.md
Normal file
104
sources/tech/20171226 The shell scripting trap.md
Normal file
@ -0,0 +1,104 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (The shell scripting trap)
|
||||
[#]: via: (https://arp242.net/weblog/shell-scripting-trap.html)
|
||||
[#]: author: (Martin Tournoij https://arp242.net/)
|
||||
|
||||
The shell scripting trap
|
||||
======
|
||||
|
||||
|
||||
Shell scripting is great. It is amazingly simple to create something very useful. Even a simple no-brainer command such as:
|
||||
|
||||
```
|
||||
# Official way of naming Go-related things:
|
||||
$ grep -i ^go /usr/share/dict/american-english /usr/share/dict/british /usr/share/dict/british-english /usr/share/dict/catala /usr/share/dict/catalan /usr/share/dict/cracklib-small /usr/share/dict/finnish /usr/share/dict/french /usr/share/dict/german /usr/share/dict/italian /usr/share/dict/ngerman /usr/share/dict/ogerman /usr/share/dict/spanish /usr/share/dict/usa /usr/share/dict/words | cut -d: -f2 | sort -R | head -n1
|
||||
goldfish
|
||||
```
|
||||
|
||||
Takes several lines of code and a lot more brainpower in many programming languages. For example in Ruby:
|
||||
|
||||
```
|
||||
puts(Dir['/usr/share/dict/*-english'].map do |f|
|
||||
File.open(f)
|
||||
.readlines
|
||||
.select { |l| l[0..1].downcase == 'go' }
|
||||
end.flatten.sample.chomp)
|
||||
```
|
||||
|
||||
The Ruby version isn’t that long, or even especially complicated. But the shell script version was so simple that I didn’t even need to actually test it to make sure it is correct, whereas I did have to test the Ruby version to ensure I didn’t make a mistake. It’s also twice as long and looks a lot more dense.
|
||||
|
||||
This is why people use shell scripts, it’s so easy to make something useful. Here’s is another example:
|
||||
|
||||
```
|
||||
curl https://nl.wikipedia.org/wiki/Lijst_van_Nederlandse_gemeenten |
|
||||
grep '^<li><a href=' |
|
||||
sed -r 's|<li><a href="/wiki/.+" title=".+">(.+)</a>.*</li>|\1|' |
|
||||
grep -Ev '(^Tabel van|^Lijst van|Nederland)'
|
||||
```
|
||||
|
||||
This gets a list of all Dutch municipalities. I actually wrote this as a quick one-shot script to populate a database years ago, but it still works fine today, and it took me a minimum of effort to make it. Doing this in e.g. Ruby would take a lot more effort.
|
||||
|
||||
But there’s a downside, as your script grows it will become increasingly harder to maintain, but you also don’t really want to rewrite it to something else, as you’ve already spent so much time on the shell script version.
|
||||
|
||||
This is what I call ‘the shell script trap’, which is a special case of the [sunk cost fallacy][1].
|
||||
|
||||
And many scripts do grow beyond their original intended size, and often you will spend a lot more time than you should on “fixing that one bug”, or “adding just one small feature”. Rinse, repeat.
|
||||
|
||||
If you had written it in Python or Ruby or another similar language from the start, you would have spent some more time writing the original version, but would have spent much less time maintaining it, while almost certainly having fewer bugs.
|
||||
|
||||
Take my [packman.vim][2] script for example. It started out as a simple `for` loop over all directories and a `git pull` and has grown from there. At about 200 lines it’s hardly the most complex script, but had I written it in Go as I originally planned then it would have been much easier to add support for printing out the status or cloning new repos from a config file. It would also be almost trivial to add support for parallel clones, which is hard (though not impossible) to do correct in a shell script. In hindsight, I would have saved time, and gotten a better result to boot.
|
||||
|
||||
I regret writing most shell scripts I’ve written for similar reasons, and my 2018 new year’s pledge will be to not write any more.
|
||||
|
||||
#### Appendix: the problems
|
||||
|
||||
And to be clear, shell scripting does come with some real limitation. Some examples:
|
||||
|
||||
* Dealing with filenames that contain spaces or other ‘special’ characters requires careful attention to detail. The vast majority of scripts get this wrong, even when written by experienced authors who care about such things (e.g. me), because it’s so easy to do it wrong. [Adding quotes is not enough][3].
|
||||
|
||||
* There are many “right” and “wrong” ways to do things. Should you use `which` or `command`? Should you use `$@` or `$*`, and should that be quoted? Should you use `cmd $arg` or `cmd "$arg"`? etc. etc.
|
||||
|
||||
* You cannot store any NULL bytes (0x00) in variables; it is very hard to make shell scripts deal with binary data.
|
||||
|
||||
* While you can make something very useful very quickly, implementing more complex algorithms can be very painful – if not nigh-impossible – even when using the ksh/zsh/bash extensions. My ad-hoc HTML parsing in the example above was okay for a quick one-off script, but you really don’t want to do things like that in a production-script.
|
||||
|
||||
* It can be hard to write shell scripts that work well on all platforms. `/bin/sh` could be `dash` or `bash`, and will behave different. External tools such as `grep`, `sed`, etc. may or may not support certain flags. Are you sure that your script works on all versions (past, present, and future) of Linux, macOS, and Windows equally well?
|
||||
|
||||
* Debugging shell scripts can be hard, especially as the syntax can get fairly obscure quite fast, and not everyone is equally well versed in shell scripting.
|
||||
|
||||
* Error handling can be tricky (check `$?` or `set -e`), and doing something more advanced beyond “an error occurred” is practically impossible.
|
||||
|
||||
* Undefined variables are not an error unless you use `set -u`, leading to “fun stuff” like `rm -r ~/$undefined` deleting user’s home dir ([not a theoretical problem][4]).
|
||||
|
||||
* Everything is a string. Some shells add arrays, which works but the syntax is obscure and ugly. Numeric computations with fractions remain tricky and rely on external tools such as `bc` or `dc` (`$(( .. ))` expansion only works for integers).
|
||||
|
||||
|
||||
|
||||
|
||||
**Feedback**
|
||||
|
||||
You can mail me at [martin@arp242.net][5] or [create a GitHub issue][6] for feedback, questions, etc.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://arp242.net/weblog/shell-scripting-trap.html
|
||||
|
||||
作者:[Martin Tournoij][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://arp242.net/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://youarenotsosmart.com/2011/03/25/the-sunk-cost-fallacy/
|
||||
[2]: https://github.com/Carpetsmoker/packman.vim
|
||||
[3]: https://dwheeler.com/essays/filenames-in-shell.html
|
||||
[4]: https://github.com/ValveSoftware/steam-for-linux/issues/3671
|
||||
[5]: mailto:martin@arp242.net
|
||||
[6]: https://github.com/Carpetsmoker/arp242.net/issues/new
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,119 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Secure Email Service Tutanota Has a Desktop App Now)
|
||||
[#]: via: (https://itsfoss.com/tutanota-desktop)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
Secure Email Service Tutanota Has a Desktop App Now
|
||||
======
|
||||
|
||||
[Tutanota][1] recently [announced][2] the release of a desktop app for their email service. The beta is available for Linux, Windows, and macOS.
|
||||
|
||||
### What is Tutanota?
|
||||
|
||||
There are plenty of free, ad-supported email services available online. However, the majority of those email services are not exactly secure or privacy-minded. In this post-[Snowden][3] world, [Tutanota][4] offers a free, secure email service with a focus on privacy.
|
||||
|
||||
Tutanota has a number of eye-catching features, such as:
|
||||
|
||||
* End-to-end encrypted mailbox
|
||||
* End-to-end encrypted address book
|
||||
* Automatic end-to-end encrypted emails between users
|
||||
* End-to-end encrypted emails to any email address with a shared password
|
||||
* Secure password reset that gives Tutanota absolutely no access
|
||||
* Strips IP addresses from emails sent and received
|
||||
* The code that runs Tutanota is [open source][5]
|
||||
* Two-factor authentication
|
||||
* Focus on privacy
|
||||
* Passwords are salted and hashed locally with Bcrypt
|
||||
* Secure servers located in Germany
|
||||
* TLS with support for PFS, DMARC, DKIM, DNSSEC, and DANE
|
||||
* Full-text search of encrypted data executed locally
|
||||
|
||||
|
||||
|
||||
![][6]
|
||||
Tutanota on the web
|
||||
|
||||
You can [sign up for an account for free][7]. You can also upgrade your account to get extra features, such as custom domains, custom domain login, domain rules, extra storage, and aliases. They also have accounts available for businesses.
|
||||
|
||||
Tutanota is also available on mobile devices. In fact, it’s [Android app is open source as well][8].
|
||||
|
||||
This German company is planning to expand beyond email. They hope to offer an encrypted calendar and cloud storage. You can help them reach their goals by [donating][9] via PayPal and cryptocurrency.
|
||||
|
||||
### The New Desktop App from Tutanota
|
||||
|
||||
Tutanota announced the [beta release][2] of the desktop app right before Christmas. They based this app on [Electron][10].
|
||||
|
||||
![][11]
|
||||
Tutanota desktop app
|
||||
|
||||
They went the Electron route:
|
||||
|
||||
* to support all three major operating systems with minimum effort.
|
||||
* to quickly adapt the new desktop clients so that they match new features added to the webmail client.
|
||||
* to allocate development time to particular desktop features, e.g. offline availability, email import, that will simultaneously be available in all three desktop clients.
|
||||
|
||||
|
||||
|
||||
Because this is a beta, there are several features missing from the app. The development team at Tutanota is working to add the following features:
|
||||
|
||||
* Email import and synchronization with external mailboxes. This will “enable Tutanota to import emails from external mailboxes and encrypt the data locally on your device before storing it on the Tutanota servers.”
|
||||
* Offline availability of emails
|
||||
* Two-factor authentication
|
||||
|
||||
|
||||
|
||||
### How to Install the Tutanota desktop client?
|
||||
|
||||
![][12]Composing email in Tutanota
|
||||
|
||||
You can [download][2] the beta app directly from Tutanota’s website. They have an [AppImage file for Linux][13], a .exe file for Windows, and a .app file for macOS. You can post any bugs that you encounter to the Tutanota [GitHub account][14].
|
||||
|
||||
To prove the security of the app, Tutanota signed each version. “The signatures make sure that the desktop clients as well as any updates come directly from us and have not been tampered with.” You can verify the signature using from Tutanota’s [GitHub page][15].
|
||||
|
||||
Remember, you will need to create a Tutanota account before you can use it. This is email client is designed to work solely with Tutanota.
|
||||
|
||||
### Wrapping up
|
||||
|
||||
I tested out the Tutanota email app on Linux Mint MATE. As to be expected, it was a mirror image of the web app. At this point in time, I don’t see any difference between the desktop app and the web app. The only use case that I can see to use the app now is to have Tutanota in its own window.
|
||||
|
||||
Have you ever used [Tutanota][16]? If not, what is your favorite privacy conscience email service? Let us know in the comments below.
|
||||
|
||||
If you found this article interesting, please take a minute to share it on social media, Hacker News or [Reddit][17].
|
||||
|
||||
![][18]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/tutanota-desktop
|
||||
|
||||
作者:[John Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/john/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/tutanota-review/
|
||||
[2]: https://tutanota.com/blog/posts/desktop-clients/
|
||||
[3]: https://en.wikipedia.org/wiki/Edward_Snowden
|
||||
[4]: https://tutanota.com/
|
||||
[5]: https://tutanota.com/blog/posts/open-source-email
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/tutanota2.jpg?resize=800%2C490&ssl=1
|
||||
[7]: https://tutanota.com/pricing
|
||||
[8]: https://itsfoss.com/tutanota-fdroid-release/
|
||||
[9]: https://tutanota.com/community
|
||||
[10]: https://electronjs.org/
|
||||
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/tutanota-app1.png?fit=800%2C486&ssl=1
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/tutanota1.jpg?resize=800%2C405&ssl=1
|
||||
[13]: https://itsfoss.com/use-appimage-linux/
|
||||
[14]: https://github.com/tutao/tutanota
|
||||
[15]: https://github.com/tutao/tutanota/blob/master/buildSrc/installerSigner.js
|
||||
[16]: https://tutanota.com/polo/
|
||||
[17]: http://reddit.com/r/linuxusersgroup
|
||||
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/02/tutanota-featured.png?fit=800%2C450&ssl=1
|
301
sources/tech/20190317 How To Configure sudo Access In Linux.md
Normal file
301
sources/tech/20190317 How To Configure sudo Access In Linux.md
Normal file
@ -0,0 +1,301 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How To Configure sudo Access In Linux?)
|
||||
[#]: via: (https://www.2daygeek.com/how-to-configure-sudo-access-in-linux/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
How To Configure sudo Access In Linux?
|
||||
======
|
||||
|
||||
The root user has all the controls in Linux system.
|
||||
|
||||
root user is the most powerful user in the Linux system and can perform any action in the system.
|
||||
|
||||
If any users wants to perform some actions, don’t provide the root access to anybody because if he/she done anything wrong there is no option/way to rectify it.
|
||||
|
||||
To fix this, what will be the solution?
|
||||
|
||||
We can grant sudo permission to the corresponding user to overcome this situation.
|
||||
|
||||
The sudo command offers a mechanism for providing trusted users with administrative access to a system without sharing the password of the root user.
|
||||
|
||||
They can perform most of the administrative operations but not all operations like root.
|
||||
|
||||
### What Is sudo?
|
||||
|
||||
sudo is a program, which can be used by a normal users to execute a command as the super user or another user, as specified by the security policy.
|
||||
|
||||
sudo users access is controlled by `/etc/sudoers` file.
|
||||
|
||||
### What Is An Advantage Of sudo Users?
|
||||
|
||||
sudo is a safe way to run a command in Linux system if you are not familiar on it.
|
||||
|
||||
* The Linux system keeps a logs into the `/var/log/secure` and `/var/log/auth.log` file where you can verify what actions was made by the sudo user.
|
||||
* Every time, it will prompt a password to perform the current action. So, you will be getting a time to verify the action, which you are going to perform. If you feel it’s not a correct action then you can safely exit there itself without perform the current action.
|
||||
|
||||
|
||||
|
||||
It’s different for RHEL based systems such as Redhat (RHEL), CentOS and Oracle Enterprise Linux (OEL) and Debian based systems such as Debian, Ubuntu and LinuxMint.
|
||||
|
||||
We will tech you, how to perform this on both the distributions in this article.
|
||||
|
||||
It can be done in three ways in both the distributions.
|
||||
|
||||
* Add a user into corresponding groups. For RHEL based system, we need to add a user into `wheel` group. For Debian based system, we need to add a user into `sudo` or `admin` groups.
|
||||
* Add a user into `/etc/group` file manually.
|
||||
* Add a user into `/etc/sudoers` file using visudo.
|
||||
|
||||
|
||||
|
||||
### How To Configure sudo Access In RHEL/CentOS/OEL Systems?
|
||||
|
||||
It can be done on RHEL based systems such as Redhat (RHEL), CentOS and Oracle Enterprise Linux (OEL) using following three methods.
|
||||
|
||||
### Method-1: How To Grant The Super User Access To A Normal User In Linux Using wheel Group?
|
||||
|
||||
Wheel is a special group in the RHEL based systems that provides additional privileges that empower a user to execute restricted commands as the super user.
|
||||
|
||||
Make a note that the `wheel` group should be enabled in the `/etc/sudoers` file to gain this access.
|
||||
|
||||
```
|
||||
# grep -i wheel /etc/sudoers
|
||||
|
||||
## Allows people in group wheel to run all commands
|
||||
%wheel ALL=(ALL) ALL
|
||||
# %wheel ALL=(ALL) NOPASSWD: ALL
|
||||
```
|
||||
|
||||
I assume that we had already created an user account to perform this. In my case, I’m going to use `daygeek` user account.
|
||||
|
||||
Run the following command to add an user into wheel group.
|
||||
|
||||
```
|
||||
# usermod -aG wheel daygeek
|
||||
```
|
||||
|
||||
We can doube confirm this by running the following command.
|
||||
|
||||
```
|
||||
# getent group wheel
|
||||
wheel:x:10:daygeek
|
||||
```
|
||||
|
||||
I’m going to check whether `daygeek` user can access a file which is owned by the root user.
|
||||
|
||||
```
|
||||
$ tail -5 /var/log/secure
|
||||
tail: cannot open _/var/log/secure_ for reading: Permission denied
|
||||
```
|
||||
|
||||
I was getting an error when i try to access the `/var/log/secure` file as a normal user. I’m going to access the same file with sudo, let’s see the magic.
|
||||
|
||||
```
|
||||
$ sudo tail -5 /var/log/secure
|
||||
[sudo] password for daygeek:
|
||||
Mar 17 07:01:56 CentOS7 sudo: daygeek : TTY=pts/0 ; PWD=/home/daygeek ; USER=root ; COMMAND=/bin/tail -5 /var/log/secure
|
||||
Mar 17 07:01:56 CentOS7 sudo: pam_unix(sudo:session): session opened for user root by daygeek(uid=0)
|
||||
Mar 17 07:01:56 CentOS7 sudo: pam_unix(sudo:session): session closed for user root
|
||||
Mar 17 07:05:10 CentOS7 sudo: daygeek : TTY=pts/0 ; PWD=/home/daygeek ; USER=root ; COMMAND=/bin/tail -5 /var/log/secure
|
||||
Mar 17 07:05:10 CentOS7 sudo: pam_unix(sudo:session): session opened for user root by daygeek(uid=0)
|
||||
```
|
||||
|
||||
### Method-2: How To Grant The Super User Access To A Normal User In RHEL/CentOS/OEL using /etc/group file?
|
||||
|
||||
We can manually add an user into the wheel group by editing the `/etc/group` file.
|
||||
|
||||
Just open the file then append the corresponding user in the appropriate group to achieve this.
|
||||
|
||||
```
|
||||
$ grep -i wheel /etc/group
|
||||
wheel:x:10:daygeek,user1
|
||||
```
|
||||
|
||||
In this example, I’m going to use `user1` user account.
|
||||
|
||||
I’m going to check whether `user1` user has sudo access or not by restarting the `Apache` service in the system. let’s see the magic.
|
||||
|
||||
```
|
||||
$ sudo systemctl restart httpd
|
||||
[sudo] password for user1:
|
||||
|
||||
$ sudo grep -i user1 /var/log/secure
|
||||
[sudo] password for user1:
|
||||
Mar 17 07:09:47 CentOS7 sudo: user1 : TTY=pts/0 ; PWD=/home/user1 ; USER=root ; COMMAND=/bin/systemctl restart httpd
|
||||
Mar 17 07:10:40 CentOS7 sudo: user1 : TTY=pts/0 ; PWD=/home/user1 ; USER=root ; COMMAND=/bin/systemctl restart httpd
|
||||
Mar 17 07:12:35 CentOS7 sudo: user1 : TTY=pts/0 ; PWD=/home/user1 ; USER=root ; COMMAND=/bin/grep -i httpd /var/log/secure
|
||||
```
|
||||
|
||||
### Method-3: How To Grant The Super User Access To A Normal User In Linux Using /etc/sudoers file?
|
||||
|
||||
sudo users access is controlled by `/etc/sudoers` file. So, simply add an user into the sudoers file under wheel group.
|
||||
|
||||
Just append the desired user into /etc/suoders file by using visudo command.
|
||||
|
||||
```
|
||||
# grep -i user2 /etc/sudoers
|
||||
user2 ALL=(ALL) ALL
|
||||
```
|
||||
|
||||
In this example, I’m going to use `user2` user account.
|
||||
|
||||
I’m going to check whether `user2` user has sudo access or not by restarting the `MariaDB` service in the system. let’s see the magic.
|
||||
|
||||
```
|
||||
$ sudo systemctl restart mariadb
|
||||
[sudo] password for user2:
|
||||
|
||||
$ sudo grep -i mariadb /var/log/secure
|
||||
[sudo] password for user2:
|
||||
Mar 17 07:23:10 CentOS7 sudo: user2 : TTY=pts/0 ; PWD=/home/user2 ; USER=root ; COMMAND=/bin/systemctl restart mariadb
|
||||
Mar 17 07:26:52 CentOS7 sudo: user2 : TTY=pts/0 ; PWD=/home/user2 ; USER=root ; COMMAND=/bin/grep -i mariadb /var/log/secure
|
||||
```
|
||||
|
||||
### How To Configure sudo Access In Debian/Ubuntu Systems?
|
||||
|
||||
It can be done on Debian based systems such as Debian based systems such as Debian, Ubuntu and LinuxMint using following three methods.
|
||||
|
||||
### Method-1: How To Grant The Super User Access To A Normal User In Linux Using sudo or admin Groups?
|
||||
|
||||
sudo or admin is a special group in the Debian based systems that provides additional privileges that empower a user to execute restricted commands as the super user.
|
||||
|
||||
Make a note that the `sudo` or `admin` group should be enabled in the `/etc/sudoers` file to gain this access.
|
||||
|
||||
```
|
||||
# grep -i 'sudo\|admin' /etc/sudoers
|
||||
|
||||
# Members of the admin group may gain root privileges
|
||||
%admin ALL=(ALL) ALL
|
||||
|
||||
# Allow members of group sudo to execute any command
|
||||
%sudo ALL=(ALL:ALL) ALL
|
||||
```
|
||||
|
||||
I assume that we had already created an user account to perform this. In my case, I’m going to use `2gadmin` user account.
|
||||
|
||||
Run the following command to add an user into sudo group.
|
||||
|
||||
```
|
||||
# usermod -aG sudo 2gadmin
|
||||
```
|
||||
|
||||
We can doube confirm this by running the following command.
|
||||
|
||||
```
|
||||
# getent group sudo
|
||||
sudo:x:27:2gadmin
|
||||
```
|
||||
|
||||
I’m going to check whether `2gadmin` user can access a file which is owned by the root user.
|
||||
|
||||
```
|
||||
$ less /var/log/auth.log
|
||||
/var/log/auth.log: Permission denied
|
||||
```
|
||||
|
||||
I was getting an error when i try to access the `/var/log/auth.log` file as a normal user. I’m going to access the same file with sudo, let’s see the magic.
|
||||
|
||||
```
|
||||
$ sudo tail -5 /var/log/auth.log
|
||||
[sudo] password for 2gadmin:
|
||||
Mar 17 20:39:47 Ubuntu18 sudo: 2gadmin : TTY=pts/0 ; PWD=/home/2gadmin ; USER=root ; COMMAND=/bin/bash
|
||||
Mar 17 20:39:47 Ubuntu18 sudo: pam_unix(sudo:session): session opened for user root by 2gadmin(uid=0)
|
||||
Mar 17 20:40:23 Ubuntu18 sudo: pam_unix(sudo:session): session closed for user root
|
||||
Mar 17 20:40:48 Ubuntu18 sudo: 2gadmin : TTY=pts/0 ; PWD=/home/2gadmin ; USER=root ; COMMAND=/usr/bin/tail -5 /var/log/auth.log
|
||||
Mar 17 20:40:48 Ubuntu18 sudo: pam_unix(sudo:session): session opened for user root by 2gadmin(uid=0)
|
||||
```
|
||||
|
||||
Alternatively we can perform the same by adding an user to `admin` group.
|
||||
|
||||
Run the following command to add an user into sudo group.
|
||||
|
||||
```
|
||||
# usermod -aG admin user1
|
||||
```
|
||||
|
||||
We can doube confirm this by running the following command.
|
||||
|
||||
```
|
||||
# getent group admin
|
||||
admin:x:1011:user1
|
||||
```
|
||||
|
||||
Let’s see the output.
|
||||
|
||||
```
|
||||
$ sudo tail -2 /var/log/auth.log
|
||||
[sudo] password for user1:
|
||||
Mar 17 20:53:36 Ubuntu18 sudo: user1 : TTY=pts/0 ; PWD=/home/user1 ; USER=root ; COMMAND=/usr/bin/tail -2 /var/log/auth.log
|
||||
Mar 17 20:53:36 Ubuntu18 sudo: pam_unix(sudo:session): session opened for user root by user1(uid=0)
|
||||
```
|
||||
|
||||
### Method-2: How To Grant The Super User Access To A Normal User In Debian/Ubuntu using /etc/group file?
|
||||
|
||||
We can manually add an user into the sudo or admin group by editing the `/etc/group` file.
|
||||
|
||||
Just open the file then append the corresponding user in the appropriate group to achieve this.
|
||||
|
||||
```
|
||||
$ grep -i sudo /etc/group
|
||||
sudo:x:27:2gadmin,user2
|
||||
```
|
||||
|
||||
In this example, I’m going to use `user2` user account.
|
||||
|
||||
I’m going to check whether `user2` user has sudo access or not by restarting the `Apache` service in the system. let’s see the magic.
|
||||
|
||||
```
|
||||
$ sudo systemctl restart apache2
|
||||
[sudo] password for user2:
|
||||
|
||||
$ sudo tail -f /var/log/auth.log
|
||||
[sudo] password for user2:
|
||||
Mar 17 21:01:04 Ubuntu18 systemd-logind[559]: New session 22 of user user2.
|
||||
Mar 17 21:01:04 Ubuntu18 systemd: pam_unix(systemd-user:session): session opened for user user2 by (uid=0)
|
||||
Mar 17 21:01:33 Ubuntu18 sudo: user2 : TTY=pts/0 ; PWD=/home/user2 ; USER=root ; COMMAND=/bin/systemctl restart apache2
|
||||
```
|
||||
|
||||
### Method-3: How To Grant The Super User Access To A Normal User In Linux Using /etc/sudoers file?
|
||||
|
||||
sudo users access is controlled by `/etc/sudoers` file. So, simply add an user into the sudoers file under sudo or admin group.
|
||||
|
||||
Just append the desired user into /etc/suoders file by using visudo command.
|
||||
|
||||
```
|
||||
# grep -i user3 /etc/sudoers
|
||||
user3 ALL=(ALL:ALL) ALL
|
||||
```
|
||||
|
||||
In this example, I’m going to use `user3` user account.
|
||||
|
||||
I’m going to check whether `user3` user has sudo access or not by restarting the `MariaDB` service in the system. let’s see the magic.
|
||||
|
||||
```
|
||||
$ sudo systemctl restart mariadb
|
||||
[sudo] password for user3:
|
||||
|
||||
$ sudo tail -f /var/log/auth.log
|
||||
[sudo] password for user3:
|
||||
Mar 17 21:12:32 Ubuntu18 systemd-logind[559]: New session 24 of user user3.
|
||||
Mar 17 21:12:49 Ubuntu18 sudo: user3 : TTY=pts/0 ; PWD=/home/user3 ; USER=root ; COMMAND=/bin/systemctl restart mariadb
|
||||
Mar 17 21:12:49 Ubuntu18 sudo: pam_unix(sudo:session): session opened for user root by user3(uid=0)
|
||||
Mar 17 21:12:53 Ubuntu18 sudo: pam_unix(sudo:session): session closed for user root
|
||||
Mar 17 21:13:08 Ubuntu18 sudo: user3 : TTY=pts/0 ; PWD=/home/user3 ; USER=root ; COMMAND=/usr/bin/tail -f /var/log/auth.log
|
||||
Mar 17 21:13:08 Ubuntu18 sudo: pam_unix(sudo:session): session opened for user root by user3(uid=0)
|
||||
```
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-configure-sudo-access-in-linux/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
@ -0,0 +1,157 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Getting started with Jaeger to build an Istio service mesh)
|
||||
[#]: via: (https://opensource.com/article/19/3/getting-started-jaeger)
|
||||
[#]: author: (Daniel Oh (Red Hat) https://opensource.com/users/daniel-oh)
|
||||
|
||||
Getting started with Jaeger to build an Istio service mesh
|
||||
======
|
||||
|
||||
Improve monitoring and tracing of cloud-native apps on a distributed networking system.
|
||||
|
||||
![Mesh networking connected dots][1]
|
||||
|
||||
[Service mesh][2] provides a dedicated network for service-to-service communication in a transparent way. [Istio][3] aims to help developers and operators address service mesh features such as dynamic service discovery, mutual transport layer security (TLS), circuit breakers, rate limiting, and tracing. [Jaeger][4] with Istio augments monitoring and tracing of cloud-native apps on a distributed networking system. This article explains how to get started with Jaeger to build an Istio service mesh on the Kubernetes platform.
|
||||
|
||||
### Spinning up a Kubernetes cluster
|
||||
|
||||
[Minikube][5] allows you to run a single-node Kubernetes cluster based on a virtual machine such as [KVM][6], [VirtualBox][7], or [HyperKit][8] on your local machine. [Install Minikube][9] and use the following shell script to run it:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
export MINIKUBE_PROFILE_NAME=istio-jaeger
|
||||
minikube profile $MINIKUBE_PROFILE_NAME
|
||||
minikube config set cpus 3
|
||||
minikube config set memory 8192
|
||||
|
||||
# You need to replace appropriate VM driver on your local machine
|
||||
minikube config set vm-driver hyperkit
|
||||
|
||||
minikube start
|
||||
```
|
||||
|
||||
In the above script, replace the **\--vm-driver=xxx** option with the appropriate virtual machine driver on your operating system (OS).
|
||||
|
||||
### Deploying Istio service mesh with Jaeger
|
||||
|
||||
Download the Istio installation file for your OS from the [Istio release page][10]. In the Istio package directory, you will find the Kubernetes installation YAML files in **install/** and the sample applications in **sample/**. Use the following commands:
|
||||
|
||||
```
|
||||
$ curl -L <https://git.io/getLatestIstio> | sh -
|
||||
$ cd istio-1.0.5
|
||||
$ export PATH=$PWD/bin:$PATH
|
||||
```
|
||||
|
||||
The easiest way to deploy Istio with Jaeger on your Kubernetes cluster is to use [Custom Resource Definitions][11]. Install Istio with mutual TLS authentication between sidecars with these commands:
|
||||
|
||||
```
|
||||
$ kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml
|
||||
$ kubectl apply -f install/kubernetes/istio-demo-auth.yaml
|
||||
```
|
||||
|
||||
Check if all pods of Istio on your Kubernetes cluster are deployed and running correctly by using the following command and review the output:
|
||||
|
||||
```
|
||||
$ kubectl get pods -n istio-system
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
grafana-59b8896965-p2vgs 1/1 Running 0 3h
|
||||
istio-citadel-856f994c58-tk8kq 1/1 Running 0 3h
|
||||
istio-cleanup-secrets-mq54t 0/1 Completed 0 3h
|
||||
istio-egressgateway-5649fcf57-n5ql5 1/1 Running 0 3h
|
||||
istio-galley-7665f65c9c-wx8k7 1/1 Running 0 3h
|
||||
istio-grafana-post-install-nh5rw 0/1 Completed 0 3h
|
||||
istio-ingressgateway-6755b9bbf6-4lf8m 1/1 Running 0 3h
|
||||
istio-pilot-698959c67b-d2zgm 2/2 Running 0 3h
|
||||
istio-policy-6fcb6d655f-lfkm5 2/2 Running 0 3h
|
||||
istio-security-post-install-st5xc 0/1 Completed 0 3h
|
||||
istio-sidecar-injector-768c79f7bf-9rjgm 1/1 Running 0 3h
|
||||
istio-telemetry-664d896cf5-wwcfw 2/2 Running 0 3h
|
||||
istio-tracing-6b994895fd-h6s9h 1/1 Running 0 3h
|
||||
prometheus-76b7745b64-hzm27 1/1 Running 0 3h
|
||||
servicegraph-5c4485945b-mk22d 1/1 Running 1 3h
|
||||
```
|
||||
|
||||
### Building sample microservice apps
|
||||
|
||||
You can use the [Bookinfo][12] app to learn about Istio's features. Bookinfo consists of four microservice apps: _productpage_ , _details_ , _reviews_ , and _ratings_ deployed independently on Minikube. Each microservice will be deployed with an Envoy sidecar via Istio by using the following commands:
|
||||
|
||||
```
|
||||
// Enable sidecar injection automatically
|
||||
$ kubectl label namespace default istio-injection=enabled
|
||||
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
|
||||
|
||||
// Export the ingress IP, ports, and gateway URL
|
||||
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
|
||||
|
||||
$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
|
||||
$ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
|
||||
$ export INGRESS_HOST=$(minikube ip)
|
||||
|
||||
$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
|
||||
```
|
||||
|
||||
### Accessing the Jaeger dashboard
|
||||
|
||||
To view tracing information for each HTTP request, create some traffic by running the following commands at the command line:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
$ while true; do
|
||||
curl -s http://${GATEWAY_URL}/productpage > /dev/null
|
||||
echo -n .;
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
You can access the Jaeger dashboard through a web browser with [http://localhost:16686][13] if you set up port forwarding as follows:
|
||||
|
||||
```
|
||||
kubectl port-forward -n istio-system $(kubectl get pod -n istio-system -l app=jaeger -o jsonpath='{.items[0].metadata.name}') 16686:16686 &
|
||||
```
|
||||
|
||||
You can explore all traces by clicking "Find Traces" after selecting the _productpage_ service. Your dashboard will look similar to this:
|
||||
|
||||
![Find traces in Jaeger][14]
|
||||
|
||||
You can also view more details about each trace to dig into performance issues or elapsed time by clicking on a certain trace.
|
||||
|
||||
![Viewing details about a trace][15]
|
||||
|
||||
### Conclusion
|
||||
|
||||
A distributed tracing platform allows you to understand what happened from service to service for individual ingress/egress traffic. Istio sends individual trace information automatically to Jaeger, the distributed tracing platform, even if your modern applications aren't aware of Jaeger at all. In the end, this capability helps developers and operators do troubleshooting easier and quicker at scale.
|
||||
|
||||
* * *
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/getting-started-jaeger
|
||||
|
||||
作者:[Daniel Oh (Red Hat)][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/daniel-oh
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/mesh_networking_dots_connected.png?itok=ovINTRR3 (Mesh networking connected dots)
|
||||
[2]: https://blog.buoyant.io/2017/04/25/whats-a-service-mesh-and-why-do-i-need-one/
|
||||
[3]: https://istio.io/docs/concepts/what-is-istio/
|
||||
[4]: https://www.jaegertracing.io/docs/1.9/
|
||||
[5]: https://opensource.com/article/18/10/getting-started-minikube
|
||||
[6]: https://www.linux-kvm.org/page/Main_Page
|
||||
[7]: https://www.virtualbox.org/wiki/Downloads
|
||||
[8]: https://github.com/moby/hyperkit
|
||||
[9]: https://kubernetes.io/docs/tasks/tools/install-minikube/
|
||||
[10]: https://github.com/istio/istio/releases
|
||||
[11]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions
|
||||
[12]: https://github.com/istio/istio/tree/master/samples/bookinfo
|
||||
[13]: http://localhost:16686/
|
||||
[14]: https://opensource.com/sites/default/files/uploads/traces_productpages.png (Find traces in Jaeger)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/traces_performance.png (Viewing details about a trace)
|
@ -0,0 +1,191 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Quickly Go Back To A Specific Parent Directory Using bd Command In Linux)
|
||||
[#]: via: (https://www.2daygeek.com/bd-quickly-go-back-to-a-specific-parent-directory-in-linux/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
Quickly Go Back To A Specific Parent Directory Using bd Command In Linux
|
||||
======
|
||||
|
||||
Two days back we had written an article about autocd. It’s a builtin shell variable that helps us to **[navigate to inside a directory without cd command][1]**.
|
||||
|
||||
If you want to come back to previous directory then you have to type `cd ..`.
|
||||
|
||||
If you want to go back to two directories then you have to type `cd ../..`.
|
||||
|
||||
It’s normal in Linux but if you want to come back from 9th directory to 3rd directory, then it’s horrible to use cd command.
|
||||
|
||||
What will be the solution for this.
|
||||
|
||||
Yes, we have a solution in Linux for everything. We can go with bd command, to make easy this kind of situation.
|
||||
|
||||
### What Is bd Command?
|
||||
|
||||
bd command allow users to quickly go back to a parent directory in Linux instead of typing `cd ../../..` repeatedly.
|
||||
|
||||
You can list the contents of a given directory without mentioning the full path `ls `bd Directory_Name``. It supports following other commands such as ls, ln, echo, zip, tar etc..
|
||||
|
||||
Also, it allow us to execute a shell file without mentioning the full path `bd p`/shell_file.sh`.
|
||||
|
||||
### How To Install bd Command in Linux?
|
||||
|
||||
There is no official distribution package for bd except Debian/Ubuntu. Hence, we need to perform manual method.
|
||||
|
||||
For **`Debian/Ubuntu`** systems, use **[APT-GET Command][2]** or **[APT Command][3]** to install bd.
|
||||
|
||||
```
|
||||
$ sudo apt install bd
|
||||
```
|
||||
|
||||
For other Linux distributions.
|
||||
|
||||
Download the bd executable binary file using **[wget command][4]**.
|
||||
|
||||
```
|
||||
$ sudo wget --no-check-certificate -O /usr/local/bin/bd https://raw.github.com/vigneshwaranr/bd/master/bd
|
||||
```
|
||||
|
||||
Set executable permission to the bd binary file.
|
||||
|
||||
```
|
||||
$ sudo chmod +rx /usr/local/bin/bd
|
||||
```
|
||||
|
||||
Append the below values in the `.bashrc` file.
|
||||
|
||||
```
|
||||
$ echo 'alias bd=". bd -si"' >> ~/.bashrc
|
||||
```
|
||||
|
||||
Run the following command to make the changes to take effect.
|
||||
|
||||
```
|
||||
$ source ~/.bashrc
|
||||
```
|
||||
|
||||
To enable auto completion, perform the following two steps.
|
||||
|
||||
```
|
||||
$ 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
|
||||
```
|
||||
|
||||
We have successfully installed and configured the bd utility on the system. It’s time to test it.
|
||||
|
||||
I’m going to take the below directory path for this testing.
|
||||
|
||||
Run the `pwd` command or `dirs` command or `tree` command to know your current location.
|
||||
|
||||
```
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ pwd
|
||||
or
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ dirs
|
||||
|
||||
/usr/share/icons/Adwaita/256x256/apps
|
||||
```
|
||||
|
||||
I’m currently in `/usr/share/icons/Adwaita/256x256/apps` and if i want to go to `icons` directory quickly then simple type the following command.
|
||||
|
||||
```
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ bd icons
|
||||
/usr/share/icons/
|
||||
daygeek@Ubuntu18:/usr/share/icons$
|
||||
```
|
||||
|
||||
Even, you no need to type full directory name instead you can type few letters.
|
||||
|
||||
```
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ bd i
|
||||
/usr/share/icons/
|
||||
daygeek@Ubuntu18:/usr/share/icons$
|
||||
```
|
||||
|
||||
`Note:` If there are more than one directories with same name up in the hierarchy, bd will take you to the closest. (Not considering the immediate parent.)
|
||||
|
||||
If you would like to list a given directory contents then the following format. It prints the contents of `/usr/share/icons/`.
|
||||
|
||||
```
|
||||
$ ls -lh `bd icons`
|
||||
or
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ ls -lh `bd i`
|
||||
total 64K
|
||||
drwxr-xr-x 12 root root 4.0K Jul 25 2018 Adwaita
|
||||
lrwxrwxrwx 1 root root 51 Feb 25 14:32 communitheme -> /snap/communitheme/current/share/icons/communitheme
|
||||
drwxr-xr-x 2 root root 4.0K Jul 25 2018 default
|
||||
drwxr-xr-x 3 root root 4.0K Jul 25 2018 DMZ-Black
|
||||
drwxr-xr-x 3 root root 4.0K Jul 25 2018 DMZ-White
|
||||
drwxr-xr-x 9 root root 4.0K Jul 25 2018 gnome
|
||||
drwxr-xr-x 3 root root 4.0K Jul 25 2018 handhelds
|
||||
drwxr-xr-x 20 root root 4.0K Mar 9 14:52 hicolor
|
||||
drwxr-xr-x 9 root root 4.0K Jul 25 2018 HighContrast
|
||||
drwxr-xr-x 12 root root 4.0K Jul 25 2018 Humanity
|
||||
drwxr-xr-x 7 root root 4.0K Jul 25 2018 Humanity-Dark
|
||||
drwxr-xr-x 4 root root 4.0K Jul 25 2018 locolor
|
||||
drwxr-xr-x 3 root root 4.0K Feb 25 15:46 LoginIcons
|
||||
drwxr-xr-x 3 root root 4.0K Jul 25 2018 redglass
|
||||
drwxr-xr-x 10 root root 4.0K Feb 25 15:46 ubuntu-mono-dark
|
||||
drwxr-xr-x 10 root root 4.0K Feb 25 15:46 ubuntu-mono-light
|
||||
drwxr-xr-x 3 root root 4.0K Jul 25 2018 whiteglass
|
||||
```
|
||||
|
||||
If you want to execute a file somewhere in a parent directory then use the following format. It will run the following shell file `/usr/share/icons/users-list.sh`.
|
||||
|
||||
```
|
||||
$ `bd i`/users-list.sh
|
||||
or
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ `bd icon`/users-list.sh
|
||||
daygeek
|
||||
thanu
|
||||
renu
|
||||
2gadmin
|
||||
testuser
|
||||
demouser
|
||||
sudha
|
||||
suresh
|
||||
user1
|
||||
user2
|
||||
user3
|
||||
```
|
||||
|
||||
If you reside in `/usr/share/icons/Adwaita/256x256/apps` and would you like to navigate to different parent directory then use the following format. The below command will navigate to `/usr/share/icons/gnome` directory.
|
||||
|
||||
```
|
||||
$ cd `bd i`/gnome
|
||||
or
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ cd `bd icon`/gnome
|
||||
daygeek@Ubuntu18:/usr/share/icons/gnome$
|
||||
```
|
||||
|
||||
If you reside in `/usr/share/icons/Adwaita/256x256/apps` and would you like to create a new directory under `/usr/share/icons/` then use the following format.
|
||||
|
||||
```
|
||||
$ daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ sudo mkdir `bd icons`/2g
|
||||
|
||||
daygeek@Ubuntu18:/usr/share/icons/Adwaita/256x256/apps$ ls -ld `bd icon`/2g
|
||||
drwxr-xr-x 2 root root 4096 Mar 16 05:44 /usr/share/icons//2g
|
||||
```
|
||||
|
||||
This tutorial allows you to quickly go back to a specific parent directory but there is no option to move forward quickly.
|
||||
|
||||
We have another solution for this, will come up with new solution shortly. Please stay tune with us.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/bd-quickly-go-back-to-a-specific-parent-directory-in-linux/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/navigate-switch-directory-without-using-cd-command-in-linux/
|
||||
[2]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[3]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[4]: https://www.2daygeek.com/wget-command-line-download-utility-tool/
|
@ -0,0 +1,96 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (4 ways to jumpstart productivity at work)
|
||||
[#]: via: (https://opensource.com/article/19/3/guide-being-more-productive)
|
||||
[#]: author: (Sarah Wall https://opensource.com/users/sarahwall)
|
||||
|
||||
4 ways to jumpstart productivity at work
|
||||
======
|
||||
|
||||
This article includes six open source productivity tools.
|
||||
|
||||
![][1]
|
||||
|
||||
Time poverty—the idea that there's not enough time to do all the work we need to do—is it a perception or a reality?
|
||||
|
||||
The truth is you'll never get more than 24 hours out of any day. Working longer hours doesn't help. Your productivity actually decreases the longer you work in a given day. Your perception, or intuitive understanding of your time, is what matters. One key to managing productivity is how you use the time you've got.
|
||||
|
||||
You have lots of time that you can use more efficiently, including time lost to ineffective meetings, distractions, and context switching between tasks. By spending your time more wisely, you can get more done and achieve higher overall job performance. You will also have a higher level of job satisfaction and feel lower levels of stress.
|
||||
|
||||
### Jumpstart your productivity
|
||||
|
||||
#### 1\. Eliminate distractions
|
||||
|
||||
When you have too many things vying for your attention, it slows you down and decreases your productivity. Do your best to remove every distraction that pulls you off tasks.
|
||||
|
||||
Cellphones, email, and messaging apps are the most common drains on productivity. Set the ringer on your phone to vibrate, set specific times for checking email, and close irrelevant browser tabs. With this approach, your work will be interrupted less throughout the day.
|
||||
|
||||
#### 2\. Make your to-do list _verb-oriented_
|
||||
|
||||
To-do lists are a great way to help you focus on exactly what you need to accomplish each day. Some people do best with a physical list, like a notebook, and others do better with digital tools. Check out these suggestions for [open source productivity tools][2] to help you manage your workflow. Or check these six open source tools to stay organized:
|
||||
|
||||
* [Joplin, a note-taking app][3]
|
||||
* [Wekan, an open source kanban board][4]
|
||||
* [TaskBoard, a lightweight kanban board][5]
|
||||
* [Go For It, a flexible to-do list application][6]
|
||||
* [Org mode without Emacs][7]
|
||||
* [Freeplane, an open source mind-mapping application][8]
|
||||
|
||||
|
||||
|
||||
Your list can be as sophisticated or as simple as you like, but just making a list is not enough. What goes on your list makes all the difference. Every item that goes on your list should be actionable. The trick is to make sure there's a verb. For example, "Smith project" is not actionable enough. "Outline key deliverables on Smith project" gives you a more concrete task to complete.
|
||||
|
||||
#### 3\. Stick to the 10-minute rule
|
||||
|
||||
Overwhelmed by an unclear or unwieldy task? Break it into 10-minute mini-tasks instead. This can be a great way to take something unmanageable and turn it into something achievable.
|
||||
|
||||
The beauty of 10-minute tasks is they can be fit into many parts of your day. When you get into the office in the morning and are feeling fresh, kick off your day with a burst of productivity with a few 10-minute tasks. Losing momentum in the afternoon? A 10-minute job can help you regain speed.
|
||||
|
||||
Ten-minute tasks are also a good way to identify tasks that can be delegated to others. The ability to delegate work is often one of the most effective management techniques. By finding a simple task that can be accomplished by another member of your team, you can make short work of a big job.
|
||||
|
||||
#### 4\. Take a break
|
||||
|
||||
Another drain on productivity is the urge to keep pressing ahead on a task to complete it without taking a break. Suddenly you feel really fatigued or hungry, and you realize you haven't gone to the bathroom in hours! Your concentration is affected, and therefore your productivity decreases.
|
||||
|
||||
Set benchmarks for taking breaks and stick to them. For example, commit to once per hour to get up and move around for five minutes. If you're pressed for time, stand up and stretch for two minutes. Changing your body position and focusing on the present moment will help relieve any mental tension that has built up.
|
||||
|
||||
Hydrate your mind with a glass of water. When your body is not properly hydrated, it can put increased stress on your brain. As little as a one to three percent decrease in hydration can negatively affect your memory, concentration, and decision-making.
|
||||
|
||||
### Don't fall into the time-poverty trap
|
||||
|
||||
Time is limited and time poverty is just an idea. How you choose to spend the time you have each day is what's important. When you develop new, healthy habits, you can increase your productivity and direct your time in the ways that give the most value.
|
||||
|
||||
* * *
|
||||
|
||||
_This article was adapted from "[The Keys to Productivity][9]" on ImageX's blog._
|
||||
|
||||
_Sarah Wall will present_ [_Mindless multitasking: a dummy's guide to productivity_][10], _at_ [_DrupalCon_][11] _in Seattle, April 8-12, 2019._
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/guide-being-more-productive
|
||||
|
||||
作者:[Sarah Wall][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/sarahwall
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_commun_4604_02_mech_connections_rhcz0.5x.png?itok=YPPU4dMj
|
||||
[2]: https://opensource.com/article/16/11/open-source-productivity-hacks
|
||||
[3]: https://opensource.com/article/19/1/productivity-tool-joplin
|
||||
[4]: https://opensource.com/article/19/1/productivity-tool-wekan
|
||||
[5]: https://opensource.com/article/19/1/productivity-tool-taskboard
|
||||
[6]: https://opensource.com/article/19/1/productivity-tool-go-for-it
|
||||
[7]: https://opensource.com/article/19/1/productivity-tool-org-mode
|
||||
[8]: https://opensource.com/article/19/1/productivity-tool-freeplane
|
||||
[9]: https://imagexmedia.com/managing-productivity
|
||||
[10]: https://events.drupal.org/seattle2019/sessions/mindless-multitasking-dummy%E2%80%99s-guide-productivity
|
||||
[11]: https://events.drupal.org/seattle2019
|
@ -0,0 +1,540 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to use Spark SQL: A hands-on tutorial)
|
||||
[#]: via: (https://opensource.com/article/19/3/apache-spark-and-dataframes-tutorial)
|
||||
[#]: author: (Dipanjan (DJ) Sarkar (Red Hat) https://opensource.com/users/djsarkar)
|
||||
|
||||
How to use Spark SQL: A hands-on tutorial
|
||||
======
|
||||
|
||||
This tutorial explains how to leverage relational databases at scale using Spark SQL and DataFrames.
|
||||
|
||||
![Team checklist and to dos][1]
|
||||
|
||||
In the [first part][2] of this series, we looked at advances in leveraging the power of relational databases "at scale" using [Apache Spark SQL and DataFrames][3]. We will now do a simple tutorial based on a real-world dataset to look at how to use Spark SQL. We will be using Spark DataFrames, but the focus will be more on using SQL. In a separate article, I will cover a detailed discussion around Spark DataFrames and common operations.
|
||||
|
||||
I love using cloud services for my machine learning, deep learning, and even big data analytics needs, instead of painfully setting up my own Spark cluster. I will be using the Databricks Platform for my Spark needs. Databricks is a company founded by the creators of Apache Spark that aims to help clients with cloud-based big data processing using Spark.
|
||||
|
||||
![Apache Spark and Databricks][4]
|
||||
|
||||
The simplest (and free of charge) way is to go to the [Try Databricks page][5] and [sign up for a community edition][6] account. You get a cloud-based cluster, which is a single-node cluster with 6GB and unlimited notebooks—not bad for a free version! I recommend using the Databricks Platform if you have serious needs for analyzing big data.
|
||||
|
||||
Let's get started with our case study now. Feel free to create a new notebook from your home screen in Databricks or your own Spark cluster.
|
||||
|
||||
![Create a notebook][7]
|
||||
|
||||
You can also import my notebook containing the entire tutorial, but please make sure to run every cell and play around and explore with it, instead of just reading through it. Unsure of how to use Spark on Databricks? Follow [this short but useful tutorial][8].
|
||||
|
||||
This tutorial will familiarize you with essential Spark capabilities to deal with structured data often obtained from databases or flat files. We will explore typical ways of querying and aggregating relational data by leveraging concepts of DataFrames and SQL using Spark. We will work on an interesting dataset from the [KDD Cup 1999][9] and try to query the data using high-level abstractions like the dataframe that has already been a hit in popular data analysis tools like R and Python. We will also look at how easy it is to build data queries using the SQL language and retrieve insightful information from our data. This also happens at scale without us having to do a lot more since Spark distributes these data structures efficiently in the backend, which makes our queries scalable and as efficient as possible. We'll start by loading some basic dependencies.
|
||||
|
||||
```
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
plt.style.use('fivethirtyeight')
|
||||
```
|
||||
|
||||
#### Data retrieval
|
||||
|
||||
The [KDD Cup 1999][9] dataset was used for the Third International Knowledge Discovery and Data Mining Tools Competition, which was held in conjunction with KDD-99, the Fifth International Conference on Knowledge Discovery and Data Mining. The competition task was to build a network-intrusion detector, a predictive model capable of distinguishing between _bad connections_ , called intrusions or attacks, and _good, normal connections_. This database contains a standard set of data to be audited, which includes a wide variety of intrusions simulated in a military network environment.
|
||||
|
||||
We will be using the reduced dataset **kddcup.data_10_percent.gz** that contains nearly a half-million network interactions. We will download this Gzip file from the web locally and then work on it. If you have a good, stable internet connection, feel free to download and work with the full dataset, **kddcup.data.gz**.
|
||||
|
||||
#### Working with data from the web
|
||||
|
||||
Dealing with datasets retrieved from the web can be a bit tricky in Databricks. Fortunately, we have some excellent utility packages like **dbutils** that help make our job easier. Let's take a quick look at some essential functions for this module.
|
||||
|
||||
```
|
||||
dbutils.help()
|
||||
```
|
||||
|
||||
```
|
||||
This module provides various utilities for users to interact with the rest of Databricks.
|
||||
|
||||
fs: DbfsUtils -> Manipulates the Databricks filesystem (DBFS) from the console
|
||||
meta: MetaUtils -> Methods to hook into the compiler (EXPERIMENTAL)
|
||||
notebook: NotebookUtils -> Utilities for the control flow of a notebook (EXPERIMENTAL)
|
||||
preview: Preview -> Utilities under preview category
|
||||
secrets: SecretUtils -> Provides utilities for leveraging secrets within notebooks
|
||||
widgets: WidgetsUtils -> Methods to create and get bound value of input widgets inside notebooks
|
||||
```
|
||||
|
||||
#### Retrieve and store data in Databricks
|
||||
|
||||
We will now leverage the Python **urllib** library to extract the KDD Cup 99 data from its web repository, store it in a temporary location, and move it to the Databricks filesystem, which can enable easy access to this data for analysis
|
||||
|
||||
> **Note:** If you skip this step and download the data directly, you may end up getting a **InvalidInputException: Input path does not exist** error.
|
||||
|
||||
```
|
||||
import urllib
|
||||
urllib.urlretrieve("<http://kdd.ics.uci.edu/databases/kddcup99/kddcup.data\_10\_percent.gz>", "/tmp/kddcup_data.gz")
|
||||
dbutils.fs.mv("file:/tmp/kddcup_data.gz", "dbfs:/kdd/kddcup_data.gz")
|
||||
display(dbutils.fs.ls("dbfs:/kdd"))
|
||||
```
|
||||
|
||||
![Spark Job kddcup_data.gz][10]
|
||||
|
||||
#### Build the KDD dataset
|
||||
|
||||
Now that we have our data stored in the Databricks filesystem, let's load up our data from the disk into Spark's traditional abstracted data structure, the [Resilient Distributed Dataset][11] (RDD).
|
||||
|
||||
```
|
||||
data_file = "dbfs:/kdd/kddcup_data.gz"
|
||||
raw_rdd = sc.textFile(data_file).cache()
|
||||
raw_rdd.take(5)
|
||||
```
|
||||
|
||||
![Data in Resilient Distributed Dataset \(RDD\)][12]
|
||||
|
||||
You can also verify the type of data structure of our data (RDD) using the following code.
|
||||
|
||||
```
|
||||
type(raw_rdd)
|
||||
```
|
||||
|
||||
![output][13]
|
||||
|
||||
#### Build a Spark DataFrame on our data
|
||||
|
||||
A Spark DataFrame is an interesting data structure representing a distributed collecion of data. Typically the entry point into all SQL functionality in Spark is the **SQLContext** class. To create a basic instance of this call, all we need is a **SparkContext** reference. In Databricks, this global context object is available as **sc** for this purpose.
|
||||
|
||||
```
|
||||
from pyspark.sql import SQLContext
|
||||
sqlContext = SQLContext(sc)
|
||||
sqlContext
|
||||
```
|
||||
|
||||
![output][14]
|
||||
|
||||
#### Split the CSV data
|
||||
|
||||
Each entry in our RDD is a comma-separated line of data, which we first need to split before we can parse and build our dataframe.
|
||||
|
||||
```
|
||||
csv_rdd = raw_rdd.map(lambda row: row.split(","))
|
||||
print(csv_rdd.take(2))
|
||||
print(type(csv_rdd))
|
||||
```
|
||||
|
||||
![Splitting RDD entries][15]
|
||||
|
||||
#### Check the total number of features (columns)
|
||||
|
||||
We can use the following code to check the total number of potential columns in our dataset.
|
||||
|
||||
```
|
||||
len(csv_rdd.take(1)[0])
|
||||
|
||||
Out[57]: 42
|
||||
```
|
||||
|
||||
#### Understand and parse data
|
||||
|
||||
The KDD 99 Cup data consists of different attributes captured from connection data. You can obtain the [full list of attributes in the data][16] and further details pertaining to the [description for each attribute/column][17]. We will just be using some specific columns from the dataset, the details of which are specified as follows.
|
||||
|
||||
feature num | feature name | description | type
|
||||
---|---|---|---
|
||||
1 | duration | length (number of seconds) of the connection | continuous
|
||||
2 | protocol_type | type of the protocol, e.g., tcp, udp, etc. | discrete
|
||||
3 | service | network service on the destination, e.g., http, telnet, etc. | discrete
|
||||
4 | src_bytes | number of data bytes from source to destination | continuous
|
||||
5 | dst_bytes | number of data bytes from destination to source | continuous
|
||||
6 | flag | normal or error status of the connection | discrete
|
||||
7 | wrong_fragment | number of "wrong" fragments | continuous
|
||||
8 | urgent | number of urgent packets | continuous
|
||||
9 | hot | number of "hot" indicators | continuous
|
||||
10 | num_failed_logins | number of failed login attempts | continuous
|
||||
11 | num_compromised | number of "compromised" conditions | continuous
|
||||
12 | su_attempted | 1 if "su root" command attempted; 0 otherwise | discrete
|
||||
13 | num_root | number of "root" accesses | continuous
|
||||
14 | num_file_creations | number of file creation operations | continuous
|
||||
|
||||
We will be extracting the following columns based on their positions in each data point (row) and build a new RDD as follows.
|
||||
|
||||
```
|
||||
from pyspark.sql import Row
|
||||
|
||||
parsed_rdd = csv_rdd.map(lambda r: Row(
|
||||
duration=int(r[0]),
|
||||
protocol_type=r[1],
|
||||
service=r[2],
|
||||
flag=r[3],
|
||||
src_bytes=int(r[4]),
|
||||
dst_bytes=int(r[5]),
|
||||
wrong_fragment=int(r[7]),
|
||||
urgent=int(r[8]),
|
||||
hot=int(r[9]),
|
||||
num_failed_logins=int(r[10]),
|
||||
num_compromised=int(r[12]),
|
||||
su_attempted=r[14],
|
||||
num_root=int(r[15]),
|
||||
num_file_creations=int(r[16]),
|
||||
label=r[-1]
|
||||
)
|
||||
)
|
||||
parsed_rdd.take(5)
|
||||
```
|
||||
|
||||
![Extracting columns][18]
|
||||
|
||||
#### Construct the DataFrame
|
||||
|
||||
Now that our data is neatly parsed and formatted, let's build our DataFrame!
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
df = sqlContext.createDataFrame(parsed_rdd)
|
||||
display(df.head(10))
|
||||
|
||||
![DataFrame][19]
|
||||
|
||||
You can also now check out the schema of our DataFrame using the following code.
|
||||
|
||||
```
|
||||
df.printSchema()
|
||||
```
|
||||
|
||||
![Dataframe schema][20]
|
||||
|
||||
#### Build a temporary table
|
||||
|
||||
We can leverage the **registerTempTable()** function to build a temporary table to run SQL commands on our DataFrame at scale! A point to remember is that the lifetime of this temp table is tied to the session. It creates an in-memory table that is scoped to the cluster in which it was created. The data is stored using Hive's highly optimized, in-memory columnar format.
|
||||
|
||||
You can also check out **saveAsTable()** , which creates a permanent, physical table stored in S3 using the Parquet format. This table is accessible to all clusters. The table metadata, including the location of the file(s), is stored within the Hive metastore.
|
||||
|
||||
```
|
||||
help(df.registerTempTable)
|
||||
```
|
||||
|
||||
![help\(df.registerTempTable\)][21]
|
||||
|
||||
```
|
||||
df.registerTempTable("connections")
|
||||
```
|
||||
|
||||
### Execute SQL at Scale
|
||||
|
||||
Let's look at a few examples of how we can run SQL queries on our table based off of our dataframe. We will start with some simple queries and then look at aggregations, filters, sorting, sub-queries, and pivots in this tutorial.
|
||||
|
||||
#### Connections based on the protocol type
|
||||
|
||||
Let's look at how we can get the total number of connections based on the type of connectivity protocol. First, we will get this information using normal DataFrame DSL syntax to perform aggregations.
|
||||
|
||||
```
|
||||
display(df.groupBy('protocol_type')
|
||||
.count()
|
||||
.orderBy('count', ascending=False))
|
||||
```
|
||||
|
||||
![Total number of connections][22]
|
||||
|
||||
Can we also use SQL to perform the same aggregation? Yes, we can leverage the table we built earlier for this!
|
||||
|
||||
```
|
||||
protocols = sqlContext.sql("""
|
||||
SELECT protocol_type, count(*) as freq
|
||||
FROM connections
|
||||
GROUP BY protocol_type
|
||||
ORDER BY 2 DESC
|
||||
""")
|
||||
display(protocols)
|
||||
```
|
||||
|
||||
![protocol type and frequency][23]
|
||||
|
||||
You can clearly see that you get the same results and don't need to worry about your background infrastructure or how the code is executed. Just write simple SQL!
|
||||
|
||||
#### Connections based on good or bad (attack types) signatures
|
||||
|
||||
We will now run a simple aggregation to check the total number of connections based on good (normal) or bad (intrusion attacks) types.
|
||||
|
||||
```
|
||||
labels = sqlContext.sql("""
|
||||
SELECT label, count(*) as freq
|
||||
FROM connections
|
||||
GROUP BY label
|
||||
ORDER BY 2 DESC
|
||||
""")
|
||||
display(labels)
|
||||
```
|
||||
|
||||
![Connection by type][24]
|
||||
|
||||
We have a lot of different attack types. We can visualize this in the form of a bar chart. The simplest way is to use the excellent interface options in the Databricks notebook.
|
||||
|
||||
![Databricks chart types][25]
|
||||
|
||||
This gives us a nice-looking bar chart, which you can customize further by clicking on **Plot Options**.
|
||||
|
||||
![Bar chart][26]
|
||||
|
||||
Another way is to write the code to do it. You can extract the aggregated data as a Pandas DataFrame and plot it as a regular bar chart.
|
||||
|
||||
```
|
||||
labels_df = pd.DataFrame(labels.toPandas())
|
||||
labels_df.set_index("label", drop=True,inplace=True)
|
||||
labels_fig = labels_df.plot(kind='barh')
|
||||
|
||||
plt.rcParams["figure.figsize"] = (7, 5)
|
||||
plt.rcParams.update({'font.size': 10})
|
||||
plt.tight_layout()
|
||||
display(labels_fig.figure)
|
||||
```
|
||||
|
||||
![Bar chart][27]
|
||||
|
||||
### Connections based on protocols and attacks
|
||||
|
||||
Let's look at which protocols are most vulnerable to attacks by using the following SQL query.
|
||||
|
||||
```
|
||||
|
||||
attack_protocol = sqlContext.sql("""
|
||||
SELECT
|
||||
protocol_type,
|
||||
CASE label
|
||||
WHEN 'normal.' THEN 'no attack'
|
||||
ELSE 'attack'
|
||||
END AS state,
|
||||
COUNT(*) as freq
|
||||
FROM connections
|
||||
GROUP BY protocol_type, state
|
||||
ORDER BY 3 DESC
|
||||
""")
|
||||
display(attack_protocol)
|
||||
```
|
||||
|
||||
![Protocols most vulnerable to attacks][28]
|
||||
|
||||
Well, it looks like ICMP connections, followed by TCP connections have had the most attacks.
|
||||
|
||||
#### Connection stats based on protocols and attacks
|
||||
|
||||
Let's take a look at some statistical measures pertaining to these protocols and attacks for our connection requests.
|
||||
|
||||
```
|
||||
attack_stats = sqlContext.sql("""
|
||||
SELECT
|
||||
protocol_type,
|
||||
CASE label
|
||||
WHEN 'normal.' THEN 'no attack'
|
||||
ELSE 'attack'
|
||||
END AS state,
|
||||
COUNT(*) as total_freq,
|
||||
ROUND(AVG(src_bytes), 2) as mean_src_bytes,
|
||||
ROUND(AVG(dst_bytes), 2) as mean_dst_bytes,
|
||||
ROUND(AVG(duration), 2) as mean_duration,
|
||||
SUM(num_failed_logins) as total_failed_logins,
|
||||
SUM(num_compromised) as total_compromised,
|
||||
SUM(num_file_creations) as total_file_creations,
|
||||
SUM(su_attempted) as total_root_attempts,
|
||||
SUM(num_root) as total_root_acceses
|
||||
FROM connections
|
||||
GROUP BY protocol_type, state
|
||||
ORDER BY 3 DESC
|
||||
""")
|
||||
display(attack_stats)
|
||||
```
|
||||
|
||||
![Statistics pertaining to protocols and attacks][29]
|
||||
|
||||
Looks like the average amount of data being transmitted in TCP requests is much higher, which is not surprising. Interestingly, attacks have a much higher average payload of data being transmitted from the source to the destination.
|
||||
|
||||
#### Filtering connection stats based on the TCP protocol by service and attack type
|
||||
|
||||
Let's take a closer look at TCP attacks, given that we have more relevant data and statistics for the same. We will now aggregate different types of TCP attacks based on service and attack type and observe different metrics.
|
||||
|
||||
```
|
||||
tcp_attack_stats = sqlContext.sql("""
|
||||
SELECT
|
||||
service,
|
||||
label as attack_type,
|
||||
COUNT(*) as total_freq,
|
||||
ROUND(AVG(duration), 2) as mean_duration,
|
||||
SUM(num_failed_logins) as total_failed_logins,
|
||||
SUM(num_file_creations) as total_file_creations,
|
||||
SUM(su_attempted) as total_root_attempts,
|
||||
SUM(num_root) as total_root_acceses
|
||||
FROM connections
|
||||
WHERE protocol_type = 'tcp'
|
||||
AND label != 'normal.'
|
||||
GROUP BY service, attack_type
|
||||
ORDER BY total_freq DESC
|
||||
""")
|
||||
display(tcp_attack_stats)
|
||||
```
|
||||
|
||||
![TCP attack data][30]
|
||||
|
||||
There are a lot of attack types, and the preceding output shows a specific section of them.
|
||||
|
||||
#### Filtering connection stats based on the TCP protocol by service and attack type
|
||||
|
||||
We will now filter some of these attack types by imposing some constraints in our query based on duration, file creations, and root accesses.
|
||||
|
||||
```
|
||||
tcp_attack_stats = sqlContext.sql("""
|
||||
SELECT
|
||||
service,
|
||||
label as attack_type,
|
||||
COUNT(*) as total_freq,
|
||||
ROUND(AVG(duration), 2) as mean_duration,
|
||||
SUM(num_failed_logins) as total_failed_logins,
|
||||
SUM(num_file_creations) as total_file_creations,
|
||||
SUM(su_attempted) as total_root_attempts,
|
||||
SUM(num_root) as total_root_acceses
|
||||
FROM connections
|
||||
WHERE (protocol_type = 'tcp'
|
||||
AND label != 'normal.')
|
||||
GROUP BY service, attack_type
|
||||
HAVING (mean_duration >= 50
|
||||
AND total_file_creations >= 5
|
||||
AND total_root_acceses >= 1)
|
||||
ORDER BY total_freq DESC
|
||||
""")
|
||||
display(tcp_attack_stats)
|
||||
```
|
||||
|
||||
![Filtered by attack type][31]
|
||||
|
||||
It's interesting to see that [multi-hop attacks][32] can get root accesses to the destination hosts!
|
||||
|
||||
#### Subqueries to filter TCP attack types based on service
|
||||
|
||||
Let's try to get all the TCP attacks based on service and attack type such that the overall mean duration of these attacks is greater than zero ( **> 0** ). For this, we can do an inner query with all aggregation statistics and extract the relevant queries and apply a mean duration filter in the outer query, as shown below.
|
||||
|
||||
```
|
||||
tcp_attack_stats = sqlContext.sql("""
|
||||
SELECT
|
||||
t.service,
|
||||
t.attack_type,
|
||||
t.total_freq
|
||||
FROM
|
||||
(SELECT
|
||||
service,
|
||||
label as attack_type,
|
||||
COUNT(*) as total_freq,
|
||||
ROUND(AVG(duration), 2) as mean_duration,
|
||||
SUM(num_failed_logins) as total_failed_logins,
|
||||
SUM(num_file_creations) as total_file_creations,
|
||||
SUM(su_attempted) as total_root_attempts,
|
||||
SUM(num_root) as total_root_acceses
|
||||
FROM connections
|
||||
WHERE protocol_type = 'tcp'
|
||||
AND label != 'normal.'
|
||||
GROUP BY service, attack_type
|
||||
ORDER BY total_freq DESC) as t
|
||||
WHERE t.mean_duration > 0
|
||||
""")
|
||||
display(tcp_attack_stats)
|
||||
```
|
||||
|
||||
![TCP attacks based on service and attack type][33]
|
||||
|
||||
This is nice! Now another interesting way to view this data is to use a pivot table, where one attribute represents rows and another one represents columns. Let's see if we can leverage Spark DataFrames to do this!
|
||||
|
||||
#### Build a pivot table from aggregated data
|
||||
|
||||
We will build upon the previous DataFrame object where we aggregated attacks based on type and service. For this, we can leverage the power of Spark DataFrames and the DataFrame DSL.
|
||||
|
||||
```
|
||||
display((tcp_attack_stats.groupby('service')
|
||||
.pivot('attack_type')
|
||||
.agg({'total_freq':'max'})
|
||||
.na.fill(0))
|
||||
)
|
||||
```
|
||||
|
||||
![Pivot table][34]
|
||||
|
||||
We get a nice, neat pivot table showing all the occurrences based on service and attack type!
|
||||
|
||||
### Next steps
|
||||
|
||||
I would encourage you to go out and play with Spark SQL and DataFrames. You can even [import my notebook][35] and play with it in your own account.
|
||||
|
||||
Feel free to refer to [my GitHub repository][36] also for all the code and notebooks used in this article. It covers things we didn't cover here, including:
|
||||
|
||||
* Joins
|
||||
* Window functions
|
||||
* Detailed operations and transformations of Spark DataFrames
|
||||
|
||||
|
||||
|
||||
You can also access my tutorial as a [Jupyter Notebook][37], in case you want to use it offline.
|
||||
|
||||
There are plenty of articles and tutorials available online, so I recommend you check them out. One useful resource is Databricks' complete [guide to Spark SQL][38].
|
||||
|
||||
Thinking of working with JSON data but unsure of using Spark SQL? Databricks supports it! Check out this excellent guide to [JSON support in Spark SQL][39].
|
||||
|
||||
Interested in advanced concepts like window functions and ranks in SQL? Take a look at "[Introducing Window Functions in Spark SQL][40]."
|
||||
|
||||
I will write another article covering some of these concepts in an intuitive way, which should be easy for you to understand. Stay tuned!
|
||||
|
||||
In case you have any feedback or queries, you can reach out to me on [LinkedIn][41].
|
||||
|
||||
* * *
|
||||
|
||||
*This article originally appeared on Medium's [Towards Data Science][42] channel and is republished with permission. *
|
||||
|
||||
* * *
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/apache-spark-and-dataframes-tutorial
|
||||
|
||||
作者:[Dipanjan (DJ) Sarkar (Red Hat)][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/djsarkar
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/todo_checklist_team_metrics_report.png?itok=oB5uQbzf (Team checklist and to dos)
|
||||
[2]: https://opensource.com/article/19/3/sql-scale-apache-spark-sql-and-dataframes
|
||||
[3]: https://spark.apache.org/sql/
|
||||
[4]: https://opensource.com/sites/default/files/uploads/13_spark-databricks.png (Apache Spark and Databricks)
|
||||
[5]: https://databricks.com/try-databricks
|
||||
[6]: https://databricks.com/signup#signup/community
|
||||
[7]: https://opensource.com/sites/default/files/uploads/14_create-notebook.png (Create a notebook)
|
||||
[8]: https://databricks.com/spark/getting-started-with-apache-spark
|
||||
[9]: http://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html
|
||||
[10]: https://opensource.com/sites/default/files/uploads/15_dbfs-kdd-kddcup_data-gz.png (Spark Job kddcup_data.gz)
|
||||
[11]: https://spark.apache.org/docs/latest/rdd-programming-guide.html#resilient-distributed-datasets-rdds
|
||||
[12]: https://opensource.com/sites/default/files/uploads/16_rdd-data.png (Data in Resilient Distributed Dataset (RDD))
|
||||
[13]: https://opensource.com/sites/default/files/uploads/16a_output.png (output)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/16b_output.png (output)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/17_split-csv.png (Splitting RDD entries)
|
||||
[16]: http://kdd.ics.uci.edu/databases/kddcup99/kddcup.names
|
||||
[17]: http://kdd.ics.uci.edu/databases/kddcup99/task.html
|
||||
[18]: https://opensource.com/sites/default/files/uploads/18_extract-columns.png (Extracting columns)
|
||||
[19]: https://opensource.com/sites/default/files/uploads/19_build-dataframe.png (DataFrame)
|
||||
[20]: https://opensource.com/sites/default/files/uploads/20_dataframe-schema.png (Dataframe schema)
|
||||
[21]: https://opensource.com/sites/default/files/uploads/21_registertemptable.png (help(df.registerTempTable))
|
||||
[22]: https://opensource.com/sites/default/files/uploads/22_number-of-connections.png (Total number of connections)
|
||||
[23]: https://opensource.com/sites/default/files/uploads/23_sql.png (protocol type and frequency)
|
||||
[24]: https://opensource.com/sites/default/files/uploads/24_intrusion-type.png (Connection by type)
|
||||
[25]: https://opensource.com/sites/default/files/uploads/25_chart-interface.png (Databricks chart types)
|
||||
[26]: https://opensource.com/sites/default/files/uploads/26_plot-options-chart.png (Bar chart)
|
||||
[27]: https://opensource.com/sites/default/files/uploads/27_pandas-barchart.png (Bar chart)
|
||||
[28]: https://opensource.com/sites/default/files/uploads/28_most-attacked.png (Protocols most vulnerable to attacks)
|
||||
[29]: https://opensource.com/sites/default/files/uploads/29_data-transmissions.png (Statistics pertaining to protocols and attacks)
|
||||
[30]: https://opensource.com/sites/default/files/uploads/30_tcp-attack-metrics.png (TCP attack data)
|
||||
[31]: https://opensource.com/sites/default/files/uploads/31_attack-type.png (Filtered by attack type)
|
||||
[32]: https://attack.mitre.org/techniques/T1188/
|
||||
[33]: https://opensource.com/sites/default/files/uploads/32_tcp-attack-types.png (TCP attacks based on service and attack type)
|
||||
[34]: https://opensource.com/sites/default/files/uploads/33_pivot-table.png (Pivot table)
|
||||
[35]: https://databricks-prod-cloudfront.cloud.databricks.com/public/4027ec902e239c93eaaa8714f173bcfc/3137082781873852/3704545280501166/1264763342038607/latest.html
|
||||
[36]: https://github.com/dipanjanS/data_science_for_all/tree/master/tds_spark_sql_intro
|
||||
[37]: http://nbviewer.jupyter.org/github/dipanjanS/data_science_for_all/blob/master/tds_spark_sql_intro/Working%20with%20SQL%20at%20Scale%20-%20Spark%20SQL%20Tutorial.ipynb
|
||||
[38]: https://docs.databricks.com/spark/latest/spark-sql/index.html
|
||||
[39]: https://databricks.com/blog/2015/02/02/an-introduction-to-json-support-in-spark-sql.html
|
||||
[40]: https://databricks.com/blog/2015/07/15/introducing-window-functions-in-spark-sql.html
|
||||
[41]: https://www.linkedin.com/in/dipanzan/
|
||||
[42]: https://towardsdatascience.com/sql-at-scale-with-apache-spark-sql-and-dataframes-concepts-architecture-and-examples-c567853a702f
|
177
sources/tech/20190322 Printing from the Linux command line.md
Normal file
177
sources/tech/20190322 Printing from the Linux command line.md
Normal file
@ -0,0 +1,177 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Printing from the Linux command line)
|
||||
[#]: via: (https://www.networkworld.com/article/3373502/printing-from-the-linux-command-line.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
Printing from the Linux command line
|
||||
======
|
||||
|
||||
There's a lot more to printing from the Linux command line than the lp command. Check out some of the many available options.
|
||||
|
||||
![Sherry \(CC BY 2.0\)][1]
|
||||
|
||||
Printing from the Linux command line is easy. You use the **lp** command to request a print, and **lpq** to see what print jobs are in the queue, but things get a little more complicated when you want to print double-sided or use portrait mode. And there are lots of other things you might want to do — such as printing multiple copies of a document or canceling a print job. Let's check out some options for getting your printouts to look just the way you want them to when you're printing from the command line.
|
||||
|
||||
### Displaying printer settings
|
||||
|
||||
To view your printer settings from the command line, use the **lpoptions** command. The output should look something like this:
|
||||
|
||||
```
|
||||
$ lpoptions
|
||||
copies=1 device-uri=dnssd://HP%20Color%20LaserJet%20CP2025dn%20(F47468)._pdl-datastream._tcp.local/ finishings=3 job-cancel-after=10800 job-hold-until=no-hold job-priority=50 job-sheets=none,none marker-change-time=1553023232 marker-colors=#000000,#00FFFF,#FF00FF,#FFFF00 marker-levels=18,62,62,63 marker-names='Black\ Cartridge\ HP\ CC530A,Cyan\ Cartridge\ HP\ CC531A,Magenta\ Cartridge\ HP\ CC533A,Yellow\ Cartridge\ HP\ CC532A' marker-types=toner,toner,toner,toner number-up=1 printer-commands=none printer-info='HP Color LaserJet CP2025dn (F47468)' printer-is-accepting-jobs=true printer-is-shared=true printer-is-temporary=false printer-location printer-make-and-model='HP Color LaserJet cp2025dn pcl3, hpcups 3.18.7' printer-state=3 printer-state-change-time=1553023232 printer-state-reasons=none printer-type=167964 printer-uri-supported=ipp://localhost/printers/Color-LaserJet-CP2025dn sides=one-sided
|
||||
```
|
||||
|
||||
This output is likely to be a little more human-friendly if you turn its blanks into carriage returns. Notice how many settings are listed.
|
||||
|
||||
NOTE: In the output below, some lines have been reconnected to make this output more readable.
|
||||
|
||||
```
|
||||
$ lpoptions | tr " " '\n'
|
||||
copies=1
|
||||
device-uri=dnssd://HP%20Color%20LaserJet%20CP2025dn%20(F47468)._pdl-datastream._tcp.local/
|
||||
finishings=3
|
||||
job-cancel-after=10800
|
||||
job-hold-until=no-hold
|
||||
job-priority=50
|
||||
job-sheets=none,none
|
||||
marker-change-time=1553023232
|
||||
marker-colors=#000000,#00FFFF,#FF00FF,#FFFF00
|
||||
marker-levels=18,62,62,63
|
||||
marker-names='Black\ Cartridge\ HP\ CC530A,
|
||||
Cyan\ Cartridge\ HP\ CC531A,
|
||||
Magenta\ Cartridge\ HP\ CC533A,
|
||||
Yellow\ Cartridge\ HP\ CC532A'
|
||||
marker-types=toner,toner,toner,toner
|
||||
number-up=1
|
||||
printer-commands=none
|
||||
printer-info='HP Color LaserJet CP2025dn (F47468)'
|
||||
printer-is-accepting-jobs=true
|
||||
printer-is-shared=true
|
||||
printer-is-temporary=false
|
||||
printer-location
|
||||
printer-make-and-model='HP Color LaserJet cp2025dn pcl3, hpcups 3.18.7'
|
||||
printer-state=3
|
||||
printer-state-change-time=1553023232
|
||||
printer-state-reasons=none
|
||||
printer-type=167964
|
||||
printer-uri-supported=ipp://localhost/printers/Color-LaserJet-CP2025dn
|
||||
sides=one-sided
|
||||
```
|
||||
|
||||
With the **-v** option, the **lpinfo** command will list drivers and related information.
|
||||
|
||||
```
|
||||
$ lpinfo -v
|
||||
network ipp
|
||||
network https
|
||||
network socket
|
||||
network beh
|
||||
direct hp
|
||||
network lpd
|
||||
file cups-brf:/
|
||||
network ipps
|
||||
network http
|
||||
direct hpfax
|
||||
network dnssd://HP%20Color%20LaserJet%20CP2025dn%20(F47468)._pdl-datastream._tcp.local/ <== printer
|
||||
network socket://192.168.0.23 <== printer IP
|
||||
```
|
||||
|
||||
The lpoptions command will show the settings of your default printer. Use the **-p** option to specify one of a number of available printers.
|
||||
|
||||
```
|
||||
$ lpoptions -p LaserJet
|
||||
```
|
||||
|
||||
The **lpstat -p** command displays the status of a printer while **lpstat -p -d** also lists available printers.
|
||||
|
||||
```
|
||||
$ lpstat -p -d
|
||||
printer Color-LaserJet-CP2025dn is idle. enabled since Tue 19 Mar 2019 05:07:45 PM EDT
|
||||
system default destination: Color-LaserJet-CP2025dn
|
||||
```
|
||||
|
||||
### Useful commands
|
||||
|
||||
To print a document on the default printer, just use the **lp** command followed by the name of the file you want to print. If the filename includes blanks (rare on Linux systems), either put the name in quotes or start entering the file name and press the tab key to invoke file completion (as shown in the second example below).
|
||||
|
||||
```
|
||||
$ lp "never leave home angry"
|
||||
$ lp never\ leave\ home\ angry
|
||||
```
|
||||
|
||||
The **lpq** command displays the print queue.
|
||||
|
||||
```
|
||||
$ lpq
|
||||
Color-LaserJet-CP2025dn is ready and printing
|
||||
Rank Owner Job File(s) Total Size
|
||||
active shs 234 agenda 2048 bytes
|
||||
```
|
||||
|
||||
With the **-n** option, the lp command allows you to specify the number of copies of a printout you want.
|
||||
|
||||
```
|
||||
$ lp -n 11 agenda
|
||||
```
|
||||
|
||||
To cancel a print job, you can use the **cancel** or **lprm** command. If you don't act quickly, you might see this:
|
||||
|
||||
```
|
||||
$ cancel 229
|
||||
cancel: cancel-job failed: Job #229 is already completed - can't cancel.
|
||||
```
|
||||
|
||||
### Two-sided printing
|
||||
|
||||
To print in two-sided mode, you can issue your lp command with a **sides** option that says both to print on both sides of the paper and which edge to turn the paper on. This setting represents the normal way that you would expect two-sided portrait documents to look.
|
||||
|
||||
```
|
||||
$ lp -o sides=two-sided-long-edge Notes.pdf
|
||||
```
|
||||
|
||||
If you want all of your documents to print in two-side mode, you can change your lp settings by using the **lpoptions** command to change the setting for **sides**.
|
||||
|
||||
```
|
||||
$ lpoptions -o sides=two-sided-short-edge
|
||||
```
|
||||
|
||||
To revert to single-sided printing, you would use a command like this one:
|
||||
|
||||
```
|
||||
$ lpoptions -o sides=one-sided
|
||||
```
|
||||
|
||||
#### Printing in landscape mode
|
||||
|
||||
To print in landscape mode, you would use the **landscape** option with the lp command.
|
||||
|
||||
```
|
||||
$ lp -o landscape penguin.jpg
|
||||
```
|
||||
|
||||
### CUPS
|
||||
|
||||
The print system used on Linux systems is the standards-based, open source printing system called CUPS, originally standing for **Common Unix Printing System**. It allows a computer to act as a print server.
|
||||
|
||||
Join the Network World communities on [Facebook][2] and [LinkedIn][3] to comment on topics that are top of mind.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3373502/printing-from-the-linux-command-line.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://images.idgesg.net/images/article/2019/03/printouts-paper-100791390-large.jpg
|
||||
[2]: https://www.facebook.com/NetworkWorld/
|
||||
[3]: https://www.linkedin.com/company/network-world
|
314
sources/tech/20190325 Backup on Fedora Silverblue with Borg.md
Normal file
314
sources/tech/20190325 Backup on Fedora Silverblue with Borg.md
Normal file
@ -0,0 +1,314 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Backup on Fedora Silverblue with Borg)
|
||||
[#]: via: (https://fedoramagazine.org/backup-on-fedora-silverblue-with-borg/)
|
||||
[#]: author: (Steven Snow https://fedoramagazine.org/author/jakfrost/)
|
||||
|
||||
Backup on Fedora Silverblue with Borg
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
When it comes to backing up a Fedora Silverblue system, some of the traditional tools may not function as expected. BorgBackup (Borg) is an alternative available that can provide backup capability for your Silverblue based systems. This how-to explains the steps for using BorgBackup 1.1.8 as a layered package to back up Fedora Silverblue 29 system.
|
||||
|
||||
On a normal Fedora Workstation system, _dnf_ is used to install a package. However, on Fedora Silverblue, _rpm-ostree install_ is used to install new software. This is termed layering on the Silverblue system, since the core ostree is an immutable image and the rpm package is layered onto the core system during the install process resulting in a new local image with the layered package.
|
||||
|
||||
> “BorgBackup (short: Borg) is a deduplicating backup program. Optionally, it supports compression and authenticated encryption.”
|
||||
>
|
||||
> From the Borg website
|
||||
|
||||
Additionally, the main way to interact with Borg is via the command line. Reading the Quick Start guide it becomes apparent that Borg is well suited to scripting. In fact, it is pretty much necessary to use some form of shell script when performing repeated thorough backup’s of a system. A basic script is provided in the [Borg Quick Start guide][2] , as a point to get started.
|
||||
|
||||
### Installing Borg
|
||||
|
||||
In a terminal, type the following command to install BorgBackup as a layered package:
|
||||
|
||||
```
|
||||
$rpm-ostree install borgbackup
|
||||
```
|
||||
This installs BorgBackup to the Fedora Silverblue system. To use it, reboot into the new ostree with:
|
||||
|
||||
```
|
||||
$systemctl reboot
|
||||
```
|
||||
|
||||
Now Borg is installed, and ready to use.
|
||||
|
||||
### Some notes about Silverblue and its file system, layered packages and flatpaks
|
||||
|
||||
#### The file system
|
||||
|
||||
Silverblue is an immutable operating system based on ostree, with support for layering rpm’s through the use of rpm-ostree. At the user level, this means the path that appears as _/home_ in a flatpak, will actually be _/var/home_ to the system. For programs like Borg, and other backup tools this is important to remember since they often require the actual path, so in this example that would be _/var/home_ instead of just _/home_.
|
||||
|
||||
Before starting a backup it’s a good idea to understand where potential data could be stored, and then if that data should be backed up. Silverblue’s file system layout is very specific with respect to what is writable and what is not. On Silverblue _/etc_ and _/var_ are the only places that are not immutable, therefore writable. On a single user system, typically the user home directory would be a likely choice for data backup. Normally excluding Downloads, but including Documents and more. Also, _/etc_ is a logical choice for some configuration options you don’t want to go through again. Take notes of what to exclude from your home directory and from _/etc_. Some files and subdirectories of /etc you need root or sudo privileges to access.
|
||||
|
||||
#### Flatpaks
|
||||
|
||||
Flatpak applications store data in your home directory under _$HOME/.var/app/flatpakapp_ , regardless of whether they were installed as user or system. If installed at a user level, there is also data found in _$HOME/.local/share/flatpak/app/_ , or if installed at a system level it will be found in _/var/lib/flatpak/app_ For the purposes of this article, it was enough to list the flatpak’s installed and redirect the output to a file for backing up. Reasoning that if there is a need to reinstall them (flatpaks) the list file could be used to do it from. For a more robust approach, examining the flatpak file system layouts can be done [here.][3]
|
||||
|
||||
#### Layering and rpm-ostree
|
||||
|
||||
There is no easy way for a user to retrieve the layered package information aside from the
|
||||
|
||||
$rpm-ostree status
|
||||
|
||||
command. Which shows the current and previous ostree commit’s layered packages, and if any commits are pinned they would be listed too. Below is the output on my system, note the LayeredPackages label at the end of each commit listing.
|
||||
|
||||
![][4]
|
||||
|
||||
The command
|
||||
|
||||
$ostree log
|
||||
|
||||
is useful to retrieve a history of commits for the system. Type it in your terminal to see the output.
|
||||
|
||||
### Preparing the backup repo
|
||||
|
||||
In order to use Borg to back up a system, you need to first initialize a Borg repo. Before initializing, the decision must be made to use encryption (or not) and if so, what mode.
|
||||
|
||||
With Borg the data can be protected using 256-bit AES encryption. The integrity and authenticity of the data, which is encrypted on the clientside, is verified using HMAC-SHA256. The encryption modes are listed below.
|
||||
|
||||
#### Encryption modes
|
||||
|
||||
Hash/MAC | Not encrypted no auth | Not encrypted, but authenticated | Encrypted (AEAD w/ AES) and authenticated
|
||||
---|---|---|---
|
||||
SHA-256 | none | authenticated | repokey keyfile
|
||||
BLAKE2b | n/a | authenticated-blake2 | repokey-blake2 keyfile-blake2
|
||||
|
||||
The encryption mode decided on was keyfile-blake2, which requires a passphrase to be entered as well as the keyfile being needed.
|
||||
|
||||
Borg can use the following compression types which you can specify at backup creation time.
|
||||
|
||||
* lz4 (super fast, low compression)
|
||||
* zstd (wide range from high speed and low compression to high compression and lower speed)
|
||||
* zlib (medium speed and compression)
|
||||
* lzma (low speed, high compression)
|
||||
|
||||
|
||||
|
||||
For compression lzma was chosen at setting 6, the highest sensible compression level. The initial backup took 4 minutes 59.98 seconds to complete, while subsequent ones have taken less than 20 seconds as a rule.
|
||||
|
||||
#### Borg init
|
||||
|
||||
To be able to perform backups with Borg, first, create a directory for your Borg repo:
|
||||
|
||||
```
|
||||
$mkdir borg_testdir
|
||||
```
|
||||
|
||||
and then change to it.
|
||||
|
||||
```
|
||||
$cd borg_testdir
|
||||
```
|
||||
|
||||
Next, initialize the Borg repo with the borg init command:
|
||||
|
||||
```
|
||||
$borg init -e=keyfile-blake2 .
|
||||
```
|
||||
|
||||
Borg will prompt for your passphrase, which is case sensitive, and at creation must be entered twice. A suitable passphrase of alpha-numeric characters and symbols, and of a reasonable length should be created. It can be changed later on if needed without affecting the keyfile, or your encrypted data. The keyfile can be exported and should be for backup purposes, along with the passphrase, and stored somewhere secure.
|
||||
|
||||
#### Creating a backup
|
||||
|
||||
Next, create a test backup of the Documents directory, remember on Silverblue the actual path to the user Documents directory is _/var/home/username/Documents_. In practice on Silverblue, it is suitable to use _~/_ or _$HOME_ to indicate your home directory. The distinction between the actual path and environment variables being the real path does not change whereas the environment variable can be changed. From within the Borg repo, type the following command
|
||||
|
||||
```
|
||||
$borg create .::borgtest /var/home/username/Documents
|
||||
```
|
||||
|
||||
and that will create a backup of the Documents directory named **borgtest**. To break down the command a bit; **create** requires a **repo location** , in this case **.** since we are in the **top level** of the **repo**. That makes the path **.::borgtest** for the backup name. Finally **/var/home/username/Documents** is the location of the data we are backing up.
|
||||
|
||||
The following command
|
||||
|
||||
```
|
||||
$borg list
|
||||
```
|
||||
|
||||
returns a listing of your backups, after a few days it look similar to this:
|
||||
|
||||
![Output of borg list command in my backup repo.][5]
|
||||
|
||||
To delete the test backup, type the following in the terminal
|
||||
|
||||
```
|
||||
$borg delete .::borgtest
|
||||
```
|
||||
|
||||
at this time Borg will prompt for the encryption passphrase in order to delete the backup.
|
||||
|
||||
### Pulling it together into a shell script
|
||||
|
||||
As mentioned Borg is an eminently script friendly tool. The Borg documentation links provided are great places to find out more about BorgBackup, and there is more. The example script provided by Borg was modified to suit this article. Below is a version with the basic parts that others could use as a starting point if desired. It tries to capture the three information pieces of the system and apps mentioned earlier. The output of _flatpak list_ , _rpm-ostree status_ , and _ostree log_ as human readable files given the same names each time so overwritten each time. The repo setup had to be changed since the original example is for a remote server login with ssh, and this was intended to be used locally. The other changes mostly involved correcting directory paths, tailoring the excluded content to suit this systems home directory, and choosing the compression.
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
|
||||
# This gets the ostree commit data, this file is overwritten each time
|
||||
|
||||
sudo ostree log fedora-workstation:fedora/29/x86_64/silverblue > ostree.log
|
||||
|
||||
|
||||
|
||||
rpm-ostree status > rpm-ostree-status.lst
|
||||
|
||||
|
||||
|
||||
# Flatpaks get listed too
|
||||
|
||||
flatpak list > flatpak.lst
|
||||
|
||||
|
||||
|
||||
# Setting this, so the repo does not need to be given on the commandline:
|
||||
|
||||
export BORG_REPO=/var/home/usernamehere/borg_testdir
|
||||
|
||||
|
||||
|
||||
# Setting this, so you won't be asked for your repository passphrase:(Caution advised!)
|
||||
|
||||
export BORG_PASSPHRASE='usercomplexpassphrasehere'
|
||||
|
||||
|
||||
|
||||
# some helpers and error handling:
|
||||
|
||||
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
|
||||
|
||||
trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM
|
||||
|
||||
|
||||
|
||||
info "Starting backup"
|
||||
|
||||
|
||||
|
||||
# Backup the most important directories into an archive named after
|
||||
|
||||
# the machine this script is currently running on:
|
||||
|
||||
borg create \
|
||||
|
||||
--verbose \
|
||||
|
||||
--filter AME \
|
||||
|
||||
--list \
|
||||
|
||||
--stats \
|
||||
|
||||
--show-rc \
|
||||
|
||||
--compression auto,lzma,6 \
|
||||
|
||||
--exclude-caches \
|
||||
|
||||
--exclude '/var/home/*/borg_testdir'\
|
||||
|
||||
--exclude '/var/home/*/Downloads/'\
|
||||
|
||||
--exclude '/var/home/*/.var/' \
|
||||
|
||||
--exclude '/var/home/*/Desktop/'\
|
||||
|
||||
--exclude '/var/home/*/bin/' \
|
||||
|
||||
\
|
||||
|
||||
::'{hostname}-{now}' \
|
||||
|
||||
/etc \
|
||||
|
||||
/var/home/ssnow \
|
||||
|
||||
|
||||
|
||||
backup_exit=$?
|
||||
|
||||
|
||||
|
||||
info "Pruning repository"
|
||||
|
||||
|
||||
|
||||
# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
|
||||
|
||||
# archives of THIS machine. The '{hostname}-' prefix is very important to
|
||||
|
||||
# limit prune's operation to this machine's archives and not apply to
|
||||
|
||||
# other machines' archives also:
|
||||
|
||||
|
||||
|
||||
borg prune \
|
||||
|
||||
--list \
|
||||
|
||||
--prefix '{hostname}-' \
|
||||
|
||||
--show-rc \
|
||||
|
||||
--keep-daily 7 \
|
||||
|
||||
--keep-weekly 4 \
|
||||
|
||||
--keep-monthly 6 \
|
||||
|
||||
|
||||
|
||||
prune_exit=$?
|
||||
|
||||
|
||||
|
||||
# use highest exit code as global exit code
|
||||
|
||||
global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit ))
|
||||
|
||||
|
||||
|
||||
if [ ${global_exit} -eq 0 ]; then
|
||||
|
||||
info "Backup and Prune finished successfully"
|
||||
|
||||
elif [ ${global_exit} -eq 1 ]; then
|
||||
|
||||
info "Backup and/or Prune finished with warnings"
|
||||
|
||||
else
|
||||
|
||||
info "Backup and/or Prune finished with errors"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
exit ${global_exit}
|
||||
```
|
||||
|
||||
This listing is missing some more excludes that were specific to the test system setup and backup intentions, and is very basic with room for customization and improvement. For this test to write an article it wasn’t a problem having the passphrase inside of a shell script file. Under normal use it is better to enter the passphrase each time when performing the backup.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/backup-on-fedora-silverblue-with-borg/
|
||||
|
||||
作者:[Steven Snow][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/jakfrost/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/03/borg-816x345.jpg
|
||||
[2]: https://borgbackup.readthedocs.io/en/stable/quickstart.html
|
||||
[3]: https://github.com/flatpak/flatpak/wiki/Filesystem
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2019/03/Screenshot-from-2019-03-18-17-11-21-1024x285.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2019/03/Screenshot-from-2019-03-18-18-56-03.png
|
222
sources/tech/20190325 Getting started with Vim- The basics.md
Normal file
222
sources/tech/20190325 Getting started with Vim- The basics.md
Normal file
@ -0,0 +1,222 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Getting started with Vim: The basics)
|
||||
[#]: via: (https://opensource.com/article/19/3/getting-started-vim)
|
||||
[#]: author: (Bryant Son (Red Hat, Community Moderator) https://opensource.com/users/brson)
|
||||
|
||||
Getting started with Vim: The basics
|
||||
======
|
||||
|
||||
Learn to use Vim enough to get by at work or for a new project.
|
||||
|
||||
![Person standing in front of a giant computer screen with numbers, data][1]
|
||||
|
||||
I remember the very first time I encountered Vim. I was a university student, and the computers in the computer science department's lab were installed with Ubuntu Linux. While I had been exposed to different Linux variations (like RHEL) even before my college years (Red Hat sold its CDs at Best Buy!), this was the first time I needed to use the Linux operating system regularly, because my classes required me to do so. Once I started using Linux, like many others before and after me, I began to feel like a "real programmer."
|
||||
|
||||
![Real Programmers comic][2]
|
||||
|
||||
Real Programmers, by [xkcd][3]
|
||||
|
||||
Students could use a graphical text editor like [Kate][4], which was installed on the lab computers by default. For students who could use the shell but weren't used to the console-based editor, the popular choice was [Nano][5], which provided good interactive menus and an experience similar to Windows' graphical text editor.
|
||||
|
||||
I used Nano sometimes, but I heard awesome things about [Vi/Vim][6] and [Emacs][7] and really wanted to give them a try (mainly because they looked cool, and I was also curious to see what was so great about them). Using Vim for the first time scared me—I did not want to mess anything up! But once I got the hang of it, things became much easier and I could appreciate the editor's powerful capabilities. As for Emacs, well, I sort of gave up, but I'm happy I stuck with Vim.
|
||||
|
||||
In this article, I will walk through Vim (based on my personal experience) just enough so you can get by with it as an editor on a Linux system. This will neither make you an expert nor even scratch the surface of many of Vim's powerful capabilities. But the starting point always matters, and I want to make the beginning experience as easy as possible, and you can explore the rest on your own.
|
||||
|
||||
### Step 0: Open a console window
|
||||
|
||||
Before jumping into Vim, you need to do a little preparation. Open a console terminal from your Linux operating system. (Since Vim is also available on MacOS, Mac users can use these instructions, also.)
|
||||
|
||||
Once a terminal window is up, type the **ls** command to list the current directory. Then, type **mkdir Tutorial** to create a new directory called **Tutorial**. Go inside the directory by typing **cd Tutorial**.
|
||||
|
||||
![Create a folder][8]
|
||||
|
||||
That's it for preparation. Now it's time to move on to the fun part—starting to use Vim.
|
||||
|
||||
### Step 1: Create and close a Vim file without saving
|
||||
|
||||
Remember when I said I was scared to use Vim at first? Well, the scary part was thinking, "what if I change an existing file and mess things up?" After all, several computer science assignments required me to work on existing files by modifying them. I wanted to know: _How can I open and close a file without saving my changes?_
|
||||
|
||||
The good news is you can use the same command to create or open a file in Vim: **vim <FILE_NAME**>, where **< FILE_NAME>** represents the target file name you want to create or modify. Let's create a file named **HelloWorld.java** by typing **vim HelloWorld.java**.
|
||||
|
||||
Hello, Vim! Now, here is a very important concept in Vim, possibly the most important to remember: Vim has multiple modes. Here are three you need to know to do Vim basics:
|
||||
|
||||
Mode | Description
|
||||
---|---
|
||||
Normal | Default; for navigation and simple editing
|
||||
Insert | For explicitly inserting and modifying text
|
||||
Command Line | For operations like saving, exiting, etc.
|
||||
|
||||
Vim has other modes, like Visual, Select, and Ex-Mode, but Normal, Insert, and Command Line modes are good enough for us.
|
||||
|
||||
You are now in Normal mode. If you have text, you can move around with your arrow keys or other navigation keystrokes (which you will see later). To make sure you are in Normal mode, simply hit the **Esc** (Escape) key.
|
||||
|
||||
> **Tip:** **Esc** switches to Normal mode. Even though you are already in Normal mode, hit **Esc** just for practice's sake.
|
||||
|
||||
Now, this will be interesting. Press **:** (the colon key) followed by **q!** (i.e., **:q!** ). Your screen will look like this:
|
||||
|
||||
![Editing Vim][9]
|
||||
|
||||
Pressing the colon in Normal mode switches Vim to Command Line mode, and the **:q!** command quits the Vim editor without saving. In other words, you are abandoning all changes. You can also use **ZQ** ; choose whichever option is more convenient.
|
||||
|
||||
Once you hit **Enter** , you should no longer be in Vim. Repeat the exercise a few times, just to get the hang of it. Once you've done that, move on to the next section to learn how to make a change to this file.
|
||||
|
||||
### Step 2: Make and save modifications in Vim
|
||||
|
||||
Reopen the file by typing **vim HelloWorld.java** and pressing the **Enter** key. Insert mode is where you can make changes to a file. First, hit **Esc** to make sure you are in Normal mode, then press **i** to go into Insert mode. (Yes, that is the letter **i**.)
|
||||
|
||||
In the lower-left, you should see **\-- INSERT --**. This means you are in Insert mode.
|
||||
|
||||
![Vim insert mode][10]
|
||||
|
||||
Type some Java code. You can type anything you want, but here is an example for you to follow. Your screen will look like this:
|
||||
|
||||
|
||||
```
|
||||
public class HelloWorld {
|
||||
public static void main([String][11][] args) {
|
||||
}
|
||||
}
|
||||
```
|
||||
Very pretty! Notice how the text is highlighted in Java syntax highlight colors. Because you started the file in Java, Vim will detect the syntax color.
|
||||
|
||||
Save the file. Hit **Esc** to leave Insert mode and enter Command Line mode. Type **:** and follow that with **x!** (i.e., a colon followed by x and !). Hit **Enter** to save the file. You can also type **wq** to perform the same operation.
|
||||
|
||||
Now you know how to enter text using Insert mode and save the file using **:x!** or **:wq**.
|
||||
|
||||
### Step 3: Basic navigation in Vim
|
||||
|
||||
While you can always use your friendly Up, Down, Left, and Right arrow buttons to move around a file, that would be very difficult in a large file with almost countless lines. It's also helpful to be able to be able to jump around within a line. Although Vim has a ton of awesome navigation features, the first one I want to show you is how to go to a specific line.
|
||||
|
||||
Press the **Esc** key to make sure you are in Normal mode, then type **:set number** and hit **Enter** .
|
||||
|
||||
Voila! You see line numbers on the left side of each line.
|
||||
|
||||
![Showing Line Numbers][12]
|
||||
|
||||
OK, you may say, "that's cool, but how do I jump to a line?" Again, make sure you are in Normal mode, then press **: <LINE_NUMBER>**, where **< LINE_NUMBER>** is the number of the line you want to go to, and press **Enter**. Try moving to line 2.
|
||||
|
||||
```
|
||||
:2
|
||||
```
|
||||
|
||||
Now move to line 3.
|
||||
|
||||
![Jump to line 3][13]
|
||||
|
||||
But imagine a scenario where you are dealing with a file that is 1,000 lines long and you want to go to the end of the file. How do you get there? Make sure you are in Normal mode, then type **:$** and press **Enter**.
|
||||
|
||||
You will be on the last line!
|
||||
|
||||
Now that you know how to jump among the lines, as a bonus, let's learn how to move to the end of a line. Make sure you are on a line with some text, like line 3, and type **$**.
|
||||
|
||||
![Go to the last character][14]
|
||||
|
||||
You're now at the last character on the line. In this example, the open curly brace is highlighted to show where your cursor moved to, and the closing curly brace is highlighted because it is the opening curly brace's matching character.
|
||||
|
||||
That's it for basic navigation in Vim. Wait, don't exit the file, though. Let's move to basic editing in Vim. Feel free to grab a cup of coffee or tea, though.
|
||||
|
||||
### Step 4: Basic editing in Vim
|
||||
|
||||
Now that you know how to navigate around a file by hopping onto the line you want, you can use that skill to do some basic editing in Vim. Switch to Insert mode. (Remember how to do that, by hitting the **i** key?) Sure, you can edit by using the keyboard to delete or insert characters, but Vim offers much quicker ways to edit files.
|
||||
|
||||
Move to line 3, where it shows **public static void main(String[] args) {**. Quickly hit the **d** key twice in succession. Yes, that is **dd**. If you did it successfully, you will see a screen like this, where line 3 is gone, and every following line moved up by one (i.e., line 4 became line 3).
|
||||
|
||||
![Deleting A Line][15]
|
||||
|
||||
That's the _delete_ command. Don't fear! Hit **u** and you will see the deleted line recovered. Whew. This is the _undo_ command.
|
||||
|
||||
![Undoing a change in Vim][16]
|
||||
|
||||
The next lesson is learning how to copy and paste text, but first, you need to learn how to highlight text in Vim. Press **v** and move your Left and Right arrow buttons to select and deselect text. This feature is also very useful when you are showing code to others and want to identify the code you want them to see.
|
||||
|
||||
![Highlighting text in Vim][17]
|
||||
|
||||
Move to line 4, where it says **System.out.println("Hello, Opensource");**. Highlight all of line 4. Done? OK, while line 4 is still highlighted, press **y**. This is called _yank_ mode, and it will copy the text to the clipboard. Next, create a new line underneath by entering **o**. Note that this will put you into Insert mode. Get out of Insert mode by pressing **Esc** , then hit **p** , which stands for _paste_. This will paste the copied text from line 3 to line 4.
|
||||
|
||||
![Pasting in Vim][18]
|
||||
|
||||
As an exercise, repeat these steps but also modify the text on your newly created lines. Also, make sure the lines are aligned well.
|
||||
|
||||
> **Hint:** You need to switch back and forth between Insert mode and Command Line mode to accomplish this task.
|
||||
|
||||
Once you are finished, save the file with the **x!** command. That's all for basic editing in Vim.
|
||||
|
||||
### Step 5: Basic searching in Vim
|
||||
|
||||
Imagine your team lead wants you to change a text string in a project. How can you do that quickly? You might want to search for the line using a certain keyword.
|
||||
|
||||
Vim's search functionality can be very useful. Go into the Command Line mode by (1) pressing **Esc** key, then (2) pressing colon **:** ****key. We can search a keyword by entering : **/ <SEARCH_KEYWORD>**, where **< SEARCH_KEYWORD>** is the text string you want to find. Here we are searching for the keyword string "Hello." In the image below, the colon is missing but required.
|
||||
|
||||
![Searching in Vim][19]
|
||||
|
||||
However, a keyword can appear more than once, and this may not be the one you want. So, how do you navigate around to find the next match? You simply press the **n** key, which stands for _next_. Make sure that you aren't in Insert mode when you do this!
|
||||
|
||||
### Bonus step: Use split mode in Vim
|
||||
|
||||
That pretty much covers all the Vim basics. But, as a bonus, I want to show you a cool Vim feature called _split mode_.
|
||||
|
||||
Get out of _HelloWorld.java_ and create a new file. In a terminal window, type **vim GoodBye.java** and hit **Enter** to create a new file named _GoodBye.java_.
|
||||
|
||||
Enter any text you want; I decided to type "Goodbye." Save the file. (Remember you can use **:x!** or **:wq** in Command Line mode.)
|
||||
|
||||
In Command Line mode, type **:split HelloWorld.java** , and see what happens.
|
||||
|
||||
![Split mode in Vim][20]
|
||||
|
||||
Wow! Look at that! The **split** command created horizontally divided windows with _HelloWorld.java_ above and _GoodBye.java_ below. How can you switch between the windows? Hold **Control** (on a Mac) or **CTRL** (on a PC) then hit **ww** (i.e., **w** twice in succession).
|
||||
|
||||
As a final exercise, try to edit _GoodBye.java_ to match the screen below by copying and pasting from _HelloWorld.java_.
|
||||
|
||||
![Modify GoodBye.java file in Split Mode][21]
|
||||
|
||||
Save both files, and you are done!
|
||||
|
||||
> **TIP 1:** If you want to arrange the files vertically, use the command **:vsplit <FILE_NAME>** (instead of **:split <FILE_NAME>**, where **< FILE_NAME>** is the name of the file you want to open in Split mode.
|
||||
>
|
||||
> **TIP 2:** You can open more than two files by calling as many additional **split** or **vsplit** commands as you want. Try it and see how it looks.
|
||||
|
||||
### Vim cheat sheet
|
||||
|
||||
In this article, you learned how to use Vim just enough to get by for work or a project. But this is just the beginning of your journey to unlock Vim's powerful capabilities. Be sure to check out other great tutorials and tips on Opensource.com.
|
||||
|
||||
To make things a little easier, I've summarized everything you've learned into [a handy cheat sheet][22].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/getting-started-vim
|
||||
|
||||
作者:[Bryant Son (Red Hat, Community Moderator)][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/brson
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr (Person standing in front of a giant computer screen with numbers, data)
|
||||
[2]: https://opensource.com/sites/default/files/uploads/1_xkcdcartoon.jpg (Real Programmers comic)
|
||||
[3]: https://xkcd.com/378/
|
||||
[4]: https://kate-editor.org
|
||||
[5]: https://www.nano-editor.org
|
||||
[6]: https://www.vim.org
|
||||
[7]: https://www.gnu.org/software/emacs
|
||||
[8]: https://opensource.com/sites/default/files/uploads/2_createtestfolder.jpg (Create a folder)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/4_existingvim.jpg (Editing Vim)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/6_insertionmode.jpg (Vim insert mode)
|
||||
[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[12]: https://opensource.com/sites/default/files/uploads/10_setnumberresult_0.jpg (Showing Line Numbers)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/12_jumpintoline3.jpg (Jump to line 3)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/14_gotolastcharacter.jpg (Go to the last character)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/15_deletinglines.jpg (Deleting A Line)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/16_undoingtheline.jpg (Undoing a change in Vim)
|
||||
[17]: https://opensource.com/sites/default/files/uploads/17_highlighting.jpg (Highlighting text in Vim)
|
||||
[18]: https://opensource.com/sites/default/files/uploads/19_pasting.jpg (Pasting in Vim)
|
||||
[19]: https://opensource.com/sites/default/files/uploads/22_searchmode.jpg (Searching in Vim)
|
||||
[20]: https://opensource.com/sites/default/files/uploads/26_copytonewfiles.jpg (Split mode in Vim)
|
||||
[21]: https://opensource.com/sites/default/files/uploads/27_exercise.jpg (Modify GoodBye.java file in Split Mode)
|
||||
[22]: https://opensource.com/downloads/cheat-sheet-vim
|
@ -0,0 +1,166 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Reducing sysadmin toil with Kubernetes controllers)
|
||||
[#]: via: (https://opensource.com/article/19/3/reducing-sysadmin-toil-kubernetes-controllers)
|
||||
[#]: author: (Paul Czarkowski https://opensource.com/users/paulczar)
|
||||
|
||||
Reducing sysadmin toil with Kubernetes controllers
|
||||
======
|
||||
|
||||
Controllers can ease a sysadmin's workload by handling things like creating and managing DNS addresses and SSL certificates.
|
||||
|
||||
![][1]
|
||||
|
||||
Kubernetes is a platform for reducing toil cunningly disguised as a platform for running containers. The element that allows for both running containers and reducing toil is the Kubernetes concept of a **Controller**.
|
||||
|
||||
Most resources in Kubernetes are managed by **kube-controller-manager** , or "controller" for short. A [controller][2] is defined as "a control loop that watches the shared state of a cluster … and makes changes attempting to move the current state toward the desired state." Think of it like this: A Kubernetes controller is to a microservice as a Chef recipe (or an Ansible playbook) is to a monolith.
|
||||
|
||||
Each Kubernetes resource is controlled by its own control loop. This is a step forward from previous systems like Chef or Puppet, which both have control loops at the server level, but not the resource level. A controller is a fairly simple piece of code that creates a control loop over a single resource to ensure the resource is behaving correctly. These control loops can stack together to create complex functionality with simple interfaces.
|
||||
|
||||
The canonical example of this in action is in how we manage Pods in Kubernetes. A Pod is effectively a running copy of an application that a specific worker node is asked to run. If that application crashes, the kubelet running on that node will start it again. However, if that node crashes, the Pod is not recovered, as the control loop (via the kubelet process) responsible for the resource no longer exists. To make applications more resilient, Kubernetes has the ReplicaSet controller.
|
||||
|
||||
The ReplicaSet controller is bundled inside the Kubernetes **controller-manager** , which runs on the Kubernetes master node and contains the controllers for these more advanced resources. The ReplicaSet controller is responsible for ensuring that a set number of copies of your application is always running. To do this, the ReplicaSet controller requests that a given number of Pods is created. It then routinely checks that the correct number of Pods is still running and will request more Pods or destroy existing Pods to do so.
|
||||
|
||||
By requesting a ReplicaSet from Kubernetes, you get a self-healing deployment of your application. You can further add lifecycle management to your workload by requesting [a Deployment][3], which is a controller that manages ReplicaSets and provides rolling upgrades by managing multiple versions of your application's ReplicaSets.
|
||||
|
||||
These controllers are great for managing Kubernetes resources and fantastic for managing resources outside of Kubernetes. The [Cloud Controller Manager][4] is a grouping of Kubernetes controllers that acts on resources external to Kubernetes, specifically resources that provide functionality to Kubernetes on the underlying cloud infrastructure. This is what drives Kubernetes' ability to do things like having a **LoadBalancer** [Service][5] type create and manage a cloud-specific load-balancer (e.g., an Elastic Load Balancer on AWS).
|
||||
|
||||
Furthermore, you can extend Kubernetes by writing a controller that watches for events and annotations and performs extra work, acting on Kubernetes resources or external resources that have some form of programmable API.
|
||||
|
||||
To review:
|
||||
|
||||
* Controllers are a fundamental building block of Kubernetes' functionality.
|
||||
* A controller forms a control loop to ensure that the state of a given resource matches the requested state.
|
||||
* Kubernetes provides controllers via Controller Manager and Cloud Controller Manager processes that provide additional resilience and functionality.
|
||||
* The ReplicaSet controller adds resiliency to pods by ensuring the correct number of replicas is running.
|
||||
* A Deployment controller adds rolling upgrade capabilities to ReplicaSets.
|
||||
* You can extend Kubernetes' functionality by writing your own controllers.
|
||||
|
||||
|
||||
|
||||
### Controllers reduce sysadmin toil
|
||||
|
||||
Some of the most common tickets in a sysadmin's queue are for fairly simple tasks that should be automated, but for various reasons are not. For example, creating or updating a DNS record generally requires updating a [zone file][6], but one bad entry and you can take down your entire DNS infrastructure. Or how about those tickets that look like _[SYSAD-42214] Expired SSL Certificate - Production is down_?
|
||||
|
||||
[![DNS Haiku][7]][8]
|
||||
|
||||
DNS haiku, image by HasturHasturHamster
|
||||
|
||||
What if I told you that Kubernetes could manage these things for you by running some additional controllers?
|
||||
|
||||
Imagine a world where asking Kubernetes to run applications for you would automatically create and manage DNS addresses and SSL certificates. What a world we live in!
|
||||
|
||||
#### Example: External DNS controller
|
||||
|
||||
The **[external-dns][9]** controller is a perfect example of Kubernetes treating operations as a microservice. You configure it with your DNS provider, and it will watch resources including Services and Ingress controllers. When one of those resources changes, it will inspect them for annotations that will tell it when it needs to perform an action.
|
||||
|
||||
With the **external-dns** controller running in your cluster, you can add the following annotation to a service, and it will go out and create a matching [DNS A record][10] for that resource:
|
||||
```
|
||||
kubectl annotate service nginx \
|
||||
"external-dns.alpha.kubernetes.io/hostname=nginx.example.org."
|
||||
```
|
||||
You can change other characteristics, such as the DNS record's TTL value:
|
||||
```
|
||||
kubectl annotate service nginx \
|
||||
"external-dns.alpha.kubernetes.io/ttl=10"
|
||||
```
|
||||
Just like that, you now have automatic DNS management for your applications and services in Kubernetes that reacts to any changes in your cluster to ensure your DNS is correct.
|
||||
|
||||
#### Example: Certificate manager operator
|
||||
|
||||
Like the **external-dns** controller, the [**cert-manager**][11] will react to changes in resources, but it also comes with a custom resource definition (CRD) that will allow you to request certificates as a resource on their own, not just as a byproduct of an annotation.
|
||||
|
||||
**cert-manager** works with [Let's Encrypt][12] and other sources of certificates to request valid, signed Transport Layer Security (TLS) certificates. You can even use it in combination with **external-dns** , like in the following example, which registers **web.example.com** , retrieves a TLS certificate from Let's Encrypt, and stores it in a Secret.
|
||||
|
||||
```
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
certmanager.k8s.io/acme-http01-edit-in-place: "true"
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
|
||||
kubernetes.io/tls-acme: "true"
|
||||
name: example
|
||||
spec:
|
||||
rules:
|
||||
- host: web.example.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: example
|
||||
servicePort: 80
|
||||
path: /*
|
||||
tls:
|
||||
- hosts:
|
||||
- web.example.com
|
||||
secretName: example-tls
|
||||
```
|
||||
|
||||
You can also request a certificate directly from the **cert-manager** CRD, like in the following example. As in the above, it will result in a certificate key pair stored in a Kubernetes Secret:
|
||||
```
|
||||
apiVersion: certmanager.k8s.io/v1alpha1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: example-com
|
||||
namespace: default
|
||||
spec:
|
||||
secretName: example-com-tls
|
||||
issuerRef:
|
||||
name: letsencrypt-staging
|
||||
commonName: example.com
|
||||
dnsNames:
|
||||
- www.example.com
|
||||
acme:
|
||||
config:
|
||||
- http01:
|
||||
ingressClass: nginx
|
||||
domains:
|
||||
- example.com
|
||||
- http01:
|
||||
ingress: my-ingress
|
||||
domains:
|
||||
- www.example.com
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
This was a quick look at one way Kubernetes is helping enable a new wave of changes in how we operate software. This is one of my favorite topics, and I look forward to sharing more on [Opensource.com][14] and my [blog][15]. I'd also like to hear how you use controllers—message me on Twitter [@pczarkowski][16].
|
||||
|
||||
* * *
|
||||
|
||||
_This article is based on[Cloud Native Operations - Kubernetes Controllers][17] originally published on Paul Czarkowski's blog._
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/reducing-sysadmin-toil-kubernetes-controllers
|
||||
|
||||
作者:[Paul Czarkowski][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/paulczar
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_wheel_gear_devops_kubernetes.png?itok=xm4a74Kv
|
||||
[2]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/
|
||||
[3]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
|
||||
[4]: https://kubernetes.io/docs/tasks/administer-cluster/running-cloud-controller/
|
||||
[5]: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
|
||||
[6]: https://en.wikipedia.org/wiki/Zone_file
|
||||
[7]: https://opensource.com/sites/default/files/uploads/dns_haiku.png (DNS Haiku)
|
||||
[8]: https://www.reddit.com/r/sysadmin/comments/4oj7pv/network_solutions_haiku/
|
||||
[9]: https://github.com/kubernetes-incubator/external-dns
|
||||
[10]: https://en.wikipedia.org/wiki/List_of_DNS_record_types#Resource_records
|
||||
[11]: http://docs.cert-manager.io/en/latest/
|
||||
[12]: https://letsencrypt.org/
|
||||
[13]: http://www.example.com
|
||||
[14]: http://Opensource.com
|
||||
[15]: https://tech.paulcz.net/blog/
|
||||
[16]: https://twitter.com/pczarkowski
|
||||
[17]: https://tech.paulcz.net/blog/cloud-native-operations-k8s-controllers/
|
229
sources/tech/20190326 How to use NetBSD on a Raspberry Pi.md
Normal file
229
sources/tech/20190326 How to use NetBSD on a Raspberry Pi.md
Normal file
@ -0,0 +1,229 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to use NetBSD on a Raspberry Pi)
|
||||
[#]: via: (https://opensource.com/article/19/3/netbsd-raspberry-pi)
|
||||
[#]: author: (Seth Kenlon (Red Hat, Community Moderator) https://opensource.com/users/seth)
|
||||
|
||||
How to use NetBSD on a Raspberry Pi
|
||||
======
|
||||
|
||||
Experiment with NetBSD, an open source OS with direct lineage back to the original UNIX source code, on your Raspberry Pi.
|
||||
|
||||
![][1]
|
||||
|
||||
Do you have an old Raspberry Pi lying around gathering dust, maybe after a recent Pi upgrade? Are you curious about [BSD Unix][2]? If you answered "yes" to both of these questions, you'll be pleased to know that the first is the solution to the second, because you can run [NetBSD][3], as far back as the very first release, on a Raspberry Pi.
|
||||
|
||||
BSD is the Berkley Software Distribution of [Unix][4]. In fact, it's the only open source Unix with direct lineage back to the original source code written by Dennis Ritchie and Ken Thompson at Bell Labs. Other modern versions are either proprietary (such as AIX and Solaris) or clever re-implementations (such as Minix and GNU/Linux). If you're used to Linux, you'll feel mostly right at home with BSD, but there are plenty of new commands and conventions to discover. If you're still relatively new to open source, trying BSD is a good way to experience a traditional Unix.
|
||||
|
||||
Admittedly, NetBSD isn't an operating system that's perfectly suited for the Pi. It's a minimal install compared to many Linux distributions designed specifically for the Pi, and not all components of recent Pi models are functional under NetBSD yet. However, it's arguably an ideal OS for the older Pi models, since it's lightweight and lovingly maintained. And if nothing else, it's a lot of fun for any die-hard Unix geek to experience another side of the [POSIX][5] world.
|
||||
|
||||
### Download NetBSD
|
||||
|
||||
There are different versions of BSD. NetBSD has cultivated a reputation for being lightweight and versatile (its website features the tagline "Of course it runs NetBSD"). It offers an image of the latest version of the OS for every version of the Raspberry Pi since the original. To download a version for your Pi, you must first [determine what variant of the ARM architecture your Pi uses][6]. Some information about this is available on the NetBSD site, but for a comprehensive overview, you can also refer to [RPi Hardware History][7].
|
||||
|
||||
The Pi I used for this article is, as far as I can tell, a Raspberry Pi Model B Rev 2.0 (with two USB ports and no mounting holes). According to the [Raspberry Pi FAQ][8], this means the architecture is ARMv6, which translates to **earmv6hf** in NetBSD's architecture notation.
|
||||
|
||||
![NetBSD on Raspberry Pi][9]
|
||||
|
||||
If you're not sure what kind of Pi you have, the good news is that there are only two Pi images, so try **earmv7hf** first; if it doesn't work, fall back to **earmv6hf**.
|
||||
|
||||
For the easiest and quickest install, use the binary image instead of an installer. Using the image is the most common method of getting an OS onto your Pi: you copy the image to your SD card and boot it up. There's no install necessary, because the image is a generic installation of the OS, and you've just copied it, bit for bit, onto the media that the Pi uses as its boot drive.
|
||||
|
||||
The image files are found in the **binary > gzimg** directories of the NetBSD installation media server, which you can reach from the [front page][3] of NetBSD.org. The image is **rpi.img.gz** , a compressed **.img** file. Download it to your hard drive.
|
||||
|
||||
Once you have downloaded the entire image, extract it. If you're running Linux, BSD, or MacOS, you can use the **gunzip** command:
|
||||
|
||||
```
|
||||
$ gunzip ~/Downloads/rpi.img.gz
|
||||
```
|
||||
|
||||
If you're working on Windows, you can install the open source [7-Zip][10] archive utility.
|
||||
|
||||
### Copy the image to your SD card
|
||||
|
||||
Once the image file is uncompressed, you must copy it to your Pi's SD card. There are two ways to do this, so use the one that works best for you.
|
||||
|
||||
#### 1\. Using Etcher
|
||||
|
||||
Etcher is a cross-platform application specifically designed to copy OS images to USB drives and SD cards. Download it from [Etcher.io][11] and launch it.
|
||||
|
||||
In the Etcher interface, select the image file on your hard drive and the SD card you want to flash, then click the Flash button.
|
||||
|
||||
![Etcher][12]
|
||||
|
||||
That's it.
|
||||
|
||||
#### 2\. Using the dd command
|
||||
|
||||
On Linux, BSD, or MacOS, you can use the **dd** command to copy the image to your SD card.
|
||||
|
||||
1. First, insert your SD card into a card reader. Don't mount the card to your system because **dd** needs the device to be disengaged to copy data onto it.
|
||||
|
||||
2. Run **dmesg | tail** to find out where the card is located without it being mounted. On MacOS, use **diskutil list**.
|
||||
|
||||
3. Copy the image file to the SD card:
|
||||
|
||||
```
|
||||
$ sudo dd if=~/Downloads/rpi.img of=/dev/mmcblk0 bs=2M status=progress
|
||||
```
|
||||
|
||||
Before doing this, you _must be sure_ you have the correct location of the SD card. If you copy the image file to the incorrect device, you could lose data. If you are at all unsure about this, use Etcher instead!
|
||||
|
||||
|
||||
|
||||
|
||||
When either **dd** or Etcher has written the image to the SD card, place the card in your Pi and power it on.
|
||||
|
||||
### First boot
|
||||
|
||||
The first time it's booted, NetBSD detects that the SD card's filesystem does not occupy all the free space available and resizes the filesystem accordingly.
|
||||
|
||||
![Booting NetBSD on Raspberry Pi][13]
|
||||
|
||||
Once that's finished, the Pi reboots and presents a login prompt. Log into your NetBSD system using **root** as the user name. No password is required.
|
||||
|
||||
### Set up a user account
|
||||
|
||||
First, set a password for the root user:
|
||||
|
||||
```
|
||||
# passwd
|
||||
```
|
||||
|
||||
Then create a user account for yourself with the **-m** option to prompt NetBSD to create a home directory and the **-G wheel** option to add your account to the wheel group so that you can become the administrative user (root) as needed:
|
||||
|
||||
```
|
||||
# useradd -m -G wheel seth
|
||||
```
|
||||
|
||||
Use the **passwd** command again to set a password for your user account:
|
||||
|
||||
```
|
||||
# passwd seth
|
||||
```
|
||||
|
||||
Log out, and then log back in with your new credentials.
|
||||
|
||||
### Add software to NetBSD
|
||||
|
||||
If you've ever used a Pi, you probably know that the way to add more software to your system is with a special command like **apt** or **dnf** (depending on whether you prefer to run [Raspbian][14] or [FedBerry][15] on your Pi). On NetBSD, use the **pkg_add** command. But some setup is required before the command knows where to go to get the packages you want to install.
|
||||
|
||||
There are ready-made (pre-compiled) packages for NetBSD on NetBSD's servers using the scheme **<[ftp://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/[PORT]/[VERSION]/All>][16]**. Replace PORT with the architecture you are using, either **earmv6hf** or **earmv7hf**. Replace VERSION with the NetBSD release you are using; at the time of this writing, that's **8.0**.
|
||||
|
||||
Place this value in a file called **/etc/pkg_install.conf**. Since that's a system file outside your user folder, you must invoke root privileges to create it:
|
||||
|
||||
```
|
||||
$ su -
|
||||
<password>
|
||||
# echo "PKG_PATH=<ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/earmv6hf/8.0/All/>" >> /etc/pkg_install.conf
|
||||
```
|
||||
|
||||
Now you can install packages from the NetBSD software distribution. A good first candidate is Bash, commonly the default shell on a Linux (and Mac) system. Also, if you're not already a Vi text editor user, you may want to try something more intuitive such as [Jove][17] or [Nano][18]:
|
||||
|
||||
```
|
||||
# pkg_add -v bash jove nano
|
||||
# exit
|
||||
$
|
||||
```
|
||||
|
||||
Unlike many Linux distributions ([Slackware][19] being a notable exception), NetBSD does very little configuration on your behalf, and this is considered a feature. So, to use Bash, Jove, or Nano as your default toolset, you must set the configuration yourself.
|
||||
|
||||
You can set many of your preferences dynamically using environment variables, which are special variables that your whole system can access. For instance, most applications in Unix know that if there is a **VISUAL** or **EDITOR** variable set, the value of those variables should be used as the default text editor. You can set these two variables temporarily, just for your current login session:
|
||||
|
||||
```
|
||||
$ export EDITOR=nano
|
||||
# export VISUAL=nano
|
||||
```
|
||||
|
||||
Or you can make them permanent by adding them to the default NetBSD **.profile** file:
|
||||
|
||||
```
|
||||
$ sed -i 's/EDITOR=vi/EDITOR=nano/' ~/.profile
|
||||
```
|
||||
|
||||
Load your new settings:
|
||||
|
||||
```
|
||||
$ . ~/.profile
|
||||
```
|
||||
|
||||
To make Bash your default shell, use the **chsh** (change shell) command, which now loads into your preferred editor. Before running **chsh** , though, make sure you know where Bash is located:
|
||||
|
||||
```
|
||||
$ which bash
|
||||
/usr/pkg/bin/bash
|
||||
```
|
||||
|
||||
Set the value for **shell** in the **chsh** entry to **/usr/pkg/bin/bash** , then save the document.
|
||||
|
||||
### Add sudo
|
||||
|
||||
The **pkg_add** command is a privileged command, which means to use it, you must become the root user with the **su** command. If you prefer, you can also set up the **sudo** command, which allows certain users to use their own password to execute administrative tasks.
|
||||
|
||||
First, install it:
|
||||
|
||||
```
|
||||
# pkg_add -v sudo
|
||||
```
|
||||
|
||||
And then use the **visudo** command to edit its configuration file. You must use the **visudo** command to edit the **sudo** configuration, and it must be run as root:
|
||||
|
||||
```
|
||||
$ su
|
||||
# SUDO_EDITOR=nano visudo
|
||||
```
|
||||
|
||||
Once you are in the editor, find the line allowing members of the wheel group to execute any command, and uncomment it (by removing **#** from the beginning of the line):
|
||||
|
||||
```
|
||||
### Uncomment to allow members of group wheel to execute any command
|
||||
%wheel ALL=(ALL) ALL
|
||||
```
|
||||
|
||||
Save the document as described in Nano's bottom menu panel and exit the root shell.
|
||||
|
||||
Now you can use **pkg_add** with **sudo** instead of becoming root:
|
||||
|
||||
```
|
||||
$ sudo pkg_add -v fluxbox
|
||||
```
|
||||
|
||||
### Net gain
|
||||
|
||||
NetBSD is a full-featured Unix operating system, and now that you have it set up on your Pi, you can explore every nook and cranny. It happens to be a pretty lightweight OS, so even an old Pi with a 700mHz processor and 256MB of RAM can run it with ease. If this article has sparked your interest and you have an old Pi sitting in a drawer somewhere, try it out!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/netbsd-raspberry-pi
|
||||
|
||||
作者:[Seth Kenlon (Red Hat, Community Moderator)][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_development_programming.png?itok=4OM29-82
|
||||
[2]: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
|
||||
[3]: http://netbsd.org/
|
||||
[4]: https://en.wikipedia.org/wiki/Unix
|
||||
[5]: https://en.wikipedia.org/wiki/POSIX
|
||||
[6]: http://wiki.netbsd.org/ports/evbarm/raspberry_pi
|
||||
[7]: https://elinux.org/RPi_HardwareHistory
|
||||
[8]: https://www.raspberrypi.org/documentation/faqs/
|
||||
[9]: https://opensource.com/sites/default/files/uploads/pi.jpg (NetBSD on Raspberry Pi)
|
||||
[10]: https://www.7-zip.org/
|
||||
[11]: https://www.balena.io/etcher/
|
||||
[12]: https://opensource.com/sites/default/files/uploads/etcher_0.png (Etcher)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/boot.png (Booting NetBSD on Raspberry Pi)
|
||||
[14]: http://raspbian.org/
|
||||
[15]: http://fedberry.org/
|
||||
[16]: ftp://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/%5BPORT%5D/%5BVERSION%5D/All%3E
|
||||
[17]: https://opensource.com/article/17/1/jove-lightweight-alternative-vim
|
||||
[18]: https://www.nano-editor.org/
|
||||
[19]: http://www.slackware.com/
|
154
sources/tech/20190326 Using Square Brackets in Bash- Part 1.md
Normal file
154
sources/tech/20190326 Using Square Brackets in Bash- Part 1.md
Normal file
@ -0,0 +1,154 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Using Square Brackets in Bash: Part 1)
|
||||
[#]: via: (https://www.linux.com/blog/2019/3/using-square-brackets-bash-part-1)
|
||||
[#]: author: (Paul Brown https://www.linux.com/users/bro66)
|
||||
|
||||
Using Square Brackets in Bash: Part 1
|
||||
======
|
||||
|
||||
![square brackets][1]
|
||||
|
||||
This tutorial tackle square brackets and how they are used in different contexts at the command line.
|
||||
|
||||
[Creative Commons Zero][2]
|
||||
|
||||
After taking a look at [how curly braces (`{}`) work on the command line][3], now it’s time to tackle brackets (`[]`) and see how they are used in different contexts.
|
||||
|
||||
### Globbing
|
||||
|
||||
The first and easiest use of square brackets is in _globbing_. You have probably used globbing before without knowing it. Think of all the times you have listed files of a certain type, say, you wanted to list JPEGs, but not PNGs:
|
||||
|
||||
```
|
||||
ls *.jpg
|
||||
```
|
||||
|
||||
Using wildcards to get all the results that fit a certain pattern is precisely what we call globbing.
|
||||
|
||||
In the example above, the asterisk means " _zero or more characters_ ". There is another globbing wildcard, `?`, which means " _exactly one character_ ", so, while
|
||||
|
||||
```
|
||||
ls d*k*
|
||||
```
|
||||
|
||||
will list files called _darkly_ and _ducky_ (and _dark_ and _duck_ \-- remember `*` can also be zero characters),
|
||||
|
||||
```
|
||||
ls d*k?
|
||||
```
|
||||
|
||||
will not list _darkly_ (or _dark_ or _duck_ ), but it will list _ducky_.
|
||||
|
||||
Square brackets are used in globbing for sets of characters. To see what this means, make directory in which to carry out tests, `cd` into it and create a bunch of files like this:
|
||||
|
||||
```
|
||||
touch file0{0..9}{0..9}
|
||||
```
|
||||
|
||||
(If you don't know why that works, [take a look at the last installment that explains curly braces `{}`][3]).
|
||||
|
||||
This will create files _file000_ , _file001_ , _file002_ , etc., through _file097_ , _file098_ and _file099_.
|
||||
|
||||
Then, to list the files in the 70s and 80s, you can do this:
|
||||
|
||||
```
|
||||
ls file0[78]?
|
||||
```
|
||||
|
||||
To list _file022_ , _file027_ , _file028_ , _file052_ , _file057_ , _file058_ , _file092_ , _file097_ , and _file98_ you can do this:
|
||||
|
||||
```
|
||||
ls file0[259][278]
|
||||
```
|
||||
|
||||
Of course, you can use globbing (and square brackets for sets) for more than just `ls`. You can use globbing with any other tool for listing, removing, moving, or copying files, although the last two may require a bit of lateral thinking.
|
||||
|
||||
Let's say you want to create duplicates of files _file010_ through _file029_ and call the copies _archive010_ , _archive011_ , _archive012_ , etc..
|
||||
|
||||
You can't do:
|
||||
|
||||
```
|
||||
cp file0[12]? archive0[12]?
|
||||
```
|
||||
|
||||
Because globbing is for matching against existing files and directories and the _archive..._ files don't exist yet.
|
||||
|
||||
Doing this:
|
||||
|
||||
```
|
||||
cp file0[12]? archive0[1..2][0..9]
|
||||
```
|
||||
|
||||
won't work either, because `cp` doesn't let you copy many files to other many new files. Copying many files only works if you are copying them to a directory, so this:
|
||||
|
||||
```
|
||||
mkdir archive
|
||||
|
||||
cp file0[12]? archive
|
||||
```
|
||||
|
||||
would work, but it would copy the files, using their same names, into a directory called _archive/_. This is not what you set out to do.
|
||||
|
||||
However, if you look back at [the article on curly braces (`{}`)][3], you will remember how you can use `%` to lop off the end of a string contained in a variable.
|
||||
|
||||
Of course, there is a way you can also lop of the beginning of string contained in a variable. Instead of `%`, you use `#`.
|
||||
|
||||
For practice, you can try this:
|
||||
|
||||
```
|
||||
myvar="Hello World"
|
||||
|
||||
echo Goodbye Cruel ${myvar#Hello}
|
||||
```
|
||||
|
||||
It prints " _Goodbye Cruel World_ " because `#Hello` gets rid of the _Hello_ part at the beginning of the string stored in `myvar`.
|
||||
|
||||
You can use this feature alongside your globbing tools to make your _archive_ duplicates:
|
||||
|
||||
```
|
||||
for i in file0[12]?;\
|
||||
|
||||
do\
|
||||
|
||||
cp $i archive${i#file};\
|
||||
|
||||
done
|
||||
```
|
||||
|
||||
The first line tells the Bash interpreter that you want to loop through all the files that contain the string _file0_ followed by the digits _1_ or _2_ , and then one other character, which can be anything. The second line `do` indicates that what follows is the instruction or list of instructions you want the interpreter to loop through.
|
||||
|
||||
Line 3 is where the actually copying happens, and you use the contents of the loop variable _`i`_ **twice: First, straight out, as the first parameter of the `cp` command, and then you add _archive_ to its contents, while at the same time cutting of _file_. So, if _`i`_ contains, say, _file019_...
|
||||
|
||||
```
|
||||
"archive" + "file019" - "file" = "archive019"
|
||||
```
|
||||
|
||||
the `cp` line is expanded to this:
|
||||
|
||||
```
|
||||
cp file019 archive019
|
||||
```
|
||||
|
||||
Finally, notice how you can use the backslash `\` to split a chain of commands over several lines for clarity.
|
||||
|
||||
In part two, we’ll look at more ways to use square brackets. Stay tuned.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/2019/3/using-square-brackets-bash-part-1
|
||||
|
||||
作者:[Paul Brown][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/bro66
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/square-gabriele-diwald-475007-unsplash.jpg?itok=cKmysLfd (square brackets)
|
||||
[2]: https://www.linux.com/LICENSES/CATEGORY/CREATIVE-COMMONS-ZERO
|
||||
[3]: https://www.linux.com/blog/learn/2019/2/all-about-curly-braces-bash
|
235
sources/tech/20190327 How to make a Raspberry Pi gamepad.md
Normal file
235
sources/tech/20190327 How to make a Raspberry Pi gamepad.md
Normal file
@ -0,0 +1,235 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to make a Raspberry Pi gamepad)
|
||||
[#]: via: (https://opensource.com/article/19/3/gamepad-raspberry-pi)
|
||||
[#]: author: (Leon Anavi https://opensource.com/users/leon-anavi)
|
||||
|
||||
How to make a Raspberry Pi gamepad
|
||||
======
|
||||
|
||||
This DIY retro video game controller for the Raspberry Pi is fun and not difficult to build but requires some time.
|
||||
|
||||
![Raspberry Pi Gamepad device][1]
|
||||
|
||||
From time to time, I get nostalgic about the video games I played during my childhood in the late '80s and the '90s. Although most of my old computers and game consoles are long gone, my Raspberry Pi can fulfill my retro-gaming fix. I enjoy the simple games included in Raspbian, and the open source RetroPie project helped me turn my Raspberry Pi into an advanced retro-gaming machine.
|
||||
|
||||
But, for a more authentic experience, like back in the "old days," I needed a gamepad. There are a lot of options on the market for USB gamepads and joysticks, but as an open source enthusiast, maker, and engineer, I prefer doing it the hard way. So, I made my own simple open source hardware gamepad, which I named the [ANAVI Play pHAT][2]. I designed it as an add-on board for Raspberry Pi using an [EEPROM][3] and a devicetree binary overlay I created for mapping the keys.
|
||||
|
||||
### Get the gamepad buttons and EEPROM
|
||||
|
||||
There are a huge variety of gamepads available for purchase, and some of them are really complex. However, it's not hard to make a gamepad similar to the iconic NES controller using the design I created.
|
||||
|
||||
The gamepad uses eight "momentary" buttons (i.e., switches that are active only while they're pushed): four tactile (tact) switches for movement (Up, Down, Left, Right), two tact buttons for A and B, and two smaller tact buttons for Select and Start. I used [through-hole][4] tact switches: six 6x6x4.3mm switches for movement and the A and B buttons, and two 3x6x4.3mm switches for the Start and Select buttons.
|
||||
|
||||
While the gamepad's primary purpose is to play retro games, the add-on board is large enough to include home-automation features, such as monitoring temperature, humidity, light, or barometric pressure, that you can use when you're not playing games. I added three slots for attaching [I2C][5] sensors to the primary I2C bus on physical pins 3 and 5.
|
||||
|
||||
The most interesting and important part of the hardware design is the EEPROM (electrically erasable programmable read-only memory). A through-hole mounted EEPROM is easier to flash on a breadboard and solder to the gamepad. An article in the [MagPi magazine][6] recommends CAT24C32 EEPROM; if that model isn't available, try to find a model with similar technical specifications. All Raspberry Pi models and versions released after 2014 (Raspberry Pi B+ and newer) have a secondary I2C bus on physical pins 27 and 28.
|
||||
|
||||
Once you have this hardware, use a breadboard to check that it works.
|
||||
|
||||
### Create the printed circuit board
|
||||
|
||||
The next step is to create a printed circuit board (PCB) design and have it manufactured. As an open source enthusiast, I believe that free and open source software should be used for creating open source hardware. I rely on [KiCad][7], electronic design automation (EDA) software available under the GPLv3+ license. KiCad works on Windows, MacOS, and GNU/Linux. (I use KiCad version 5 on Ubuntu 18.04.)
|
||||
|
||||
KiCad allows you to create PCBs with up to 32 copper layers plus 14 fixed-purpose technical layers. It also has an integrated 3D viewer. It's actively developed, including many contributions by CERN developers, and used for industrial applications; for example, Olimex uses KiCad to design complex PCBs with multiple layers, like the one in its [TERES-I][8] DIY open source hardware laptop.
|
||||
|
||||
The KiCad workflow includes three major steps:
|
||||
|
||||
* Designing the schematics in the schematic layout editor
|
||||
* Drawing the edge cuts, placing the components, and routing the tracks in the PCB layout editor
|
||||
* Exporting Gerber and drill files for manufacture
|
||||
|
||||
|
||||
|
||||
If you haven't designed PCBs before, keep in mind there is a steep learning curve. Go through the [examples and user's guides][9] provided by KiCad to learn how to work with the schematic and the PCB layout editor. (If you are not in the mood to do everything from scratch, you can just clone the ANAVI Play pHAT project in my [GitHub repository][10].)
|
||||
|
||||
![KiCad schematic][11]
|
||||
|
||||
In KiCad's schematic layout editor, connect the Raspberry Pi's GPIOs to the buttons, the slots for sensors to the primary I2C, and the EEPROM to the secondary I2C. Assign an appropriate footprint to each component. Perform an electrical rule check and, if there are no errors, generate the [netlist][12], which describes an electronic circuit's connectivity.
|
||||
|
||||
Open the PCB layout editor. It contains several layers. Read the netlist. All components and tracks must be on the front and bottom copper layers (F.Cu and B.Cu), and the board's form must be created in the Edge.Cuts layer. Any text, including button labels, must be on the silkscreen layers.
|
||||
|
||||
![Printable circuit board design][13]
|
||||
|
||||
Finally, export the Gerber and drill files that you'll send to the company that will produce your PCB. The Gerber format is the de facto industry standard for PCBs. It is an open ASCII vector format for 2D binary images; simply explained, it is like a PDF for PCB manufacturing.
|
||||
|
||||
There are numerous companies that can make a simple two-layer board like the gamepad's. For a few prototypes, you can count on [OSHPark in the US][14] or [Aisler in Europe][15]. There are also a lot of Chinese manufacturers, such as JLCPCB, PCBWay, ALLPCB, Seeed Studio, and many more. Alternatively, if you prefer to skip the hassle of PCB manufacturing and sourcing components, you can order the [ANAVI Play pHAT maker kit from Crowd Supply][2] and solder all the through-hole components on your own.
|
||||
|
||||
### Understanding devicetree
|
||||
|
||||
[Devicetree][16] is a specification for a software data structure that describes the hardware components. Its purpose is to allow the compiled Linux kernel to handle a variety of different hardware configurations within a wider architecture family. The bootloader loads the devicetree into memory and passes it to the Linux kernel.
|
||||
|
||||
The devicetree includes three components:
|
||||
|
||||
* Devicetree source (DTS)
|
||||
* Devicetree blob (DTB) and overlay (DTBO)
|
||||
* Devicetree compiler (DTC)
|
||||
|
||||
|
||||
|
||||
The DTC creates binaries from a textual source. Devicetree overlays allow a central DTB to be overlaid on the devicetree. Overlays include a number of fragments.
|
||||
|
||||
For several years, a devicetree has been required for all new ARM systems on a chip (SoCs), including Broadcom SoCs in all Raspberry Pi models and versions. With the default bootloader in Raspberry Pi's popular Raspbian distribution, DTO can be set in the configuration file ( **config.txt** ) on the FAT partition of a bootable microSD card using the keyword **device_tree=**.
|
||||
|
||||
Since 2014, the Raspberry Pi's pin header has been extended to 40 pins. Pins 27 and 28 are dedicated for a secondary I2C bus. This way, the DTBO can be automatically loaded from an EEPROM attached to these pins. Furthermore, additional system information can be saved in the EEPROM. This feature is among the Raspberry Pi Foundation's requirements for any Raspberry Pi HAT (hardware attached on top) add-on board. On Raspbian and other GNU/Linux distributions for Raspberry Pi, the information from the EEPROM can be seen from userspace at **/proc/device-tree/hat/** after booting.
|
||||
|
||||
In my opinion, the devicetree is one of the most fascinating features added in the Linux ecosystem over the past decade. Creating devicetree blobs and overlays is an advanced task and requires some background knowledge. However, it's possible to create a devicetree binary overlay for the Raspberry Pi add-on board and flash it on an appropriate EEPROM. The device binary overlay defines the Linux key codes for each key of the gamepad. The result is a gamepad for Raspberry Pi with keys that work as soon as you boot Raspbian.
|
||||
|
||||
#### Creating the DTBO
|
||||
|
||||
There are three major steps to create a devicetree binary overlay for the gamepad:
|
||||
|
||||
* Creating the devicetree source with mapping for the keys based on the Linux key codes
|
||||
* Compiling the devicetree binary overlay using the devicetree compiles
|
||||
* Creating an **.eep** file and flashing it on an EEPROM using the open source tools provided by the Raspberry Pi Foundation
|
||||
|
||||
|
||||
|
||||
Linux key codes are defined in the file **/usr/include/linux/input-event-codes.h**. The device source file should describe which Raspberry Pi GPIO pin is connected to which hardware button and which Linux key code should be triggered when the button is pressed. In this gamepad, GPIO17 (pin 11) is connected to the tactile button for Right, GPIO4 (pin 7) to Left, GPIO22 (pin 15) to Up, GPIO27 (pin 13) to Down, GPIO5 (pin 29) to Start, GPIO6 (pin 31) to Select, GPIO19 (pin 35) to A, and GPIO26 (pin 37) to B.
|
||||
|
||||
Please note there is a difference between the GPIO numbers and the physical position of the pin on the header. For convenience, all pins are located on the second row of the Raspberry Pi's 40-pin header. This approach makes it easier to route the printed circuit board in KiCad.
|
||||
|
||||
The entire devicetree source for the gamepad is [available on GitHub][17]. As an example, the following is a short code snippet that demonstrates how GPIO17, corresponding to physical pin 11 on the Raspberry Pi, is mapped to the tact button for Right:
|
||||
|
||||
```
|
||||
button@17 {
|
||||
label = "right";
|
||||
linux,code = <106>;
|
||||
gpios = <&gpio 17 1>;
|
||||
};
|
||||
```
|
||||
|
||||
To compile the DTS directly on the Raspberry Pi, install the devicetree compiler on Raspbian by executing the following command in the terminal:
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install device-tree-compiler
|
||||
```
|
||||
Run DTC and provide as arguments the name of the output DTBO and the path to the source file. For example:
|
||||
|
||||
```
|
||||
dtc -I dts -O dtb -o anavi-play-phat.dtbo anavi-play-phat.dts
|
||||
```
|
||||
|
||||
The Raspberry Pi Foundation provides a [GitHub repository with the mechanical, hardware, and software specifications for HATs][18]. It also includes three very convenient tools:
|
||||
|
||||
* **eepmake:** Creates an **.eep** file from a text file with settings
|
||||
* **eepdump:** Useful for debugging, as it dumps a binary **.eep** file as human-readable text
|
||||
* **eepflash:** Writes or reads an **.eep** binary image to/from an EEPROM
|
||||
|
||||
|
||||
|
||||
The **eeprom_settings.txt** file can be used as a template. [The Raspberry Pi Foundation][19] and [MagPi magazine][6] have helpful articles and tutorials, so I won't go into too many details. As I wrote above, the recommended EEPROM is CAT24C32, but it can be replaced with any other EEPROM with the same technical specifications. Using an EEPROM with an eight-pin, through-hole, dual in-line (DIP) package is easier for hobbyists to flash because it can be done with a breadboard. The following example command creates a file ready to be flashed on the EEPROM using the **eepmake** tool from the Raspberry Pi GitHub repository:
|
||||
|
||||
```
|
||||
./eepmake settings.txt settings.eep anavi-play-phat.dtbo
|
||||
```
|
||||
|
||||
Before proceeding with flashing, ensure that the EEPROM is connected properly to the primary I2C bus (pins 3 and 5) on the Raspberry Pi. (You can consult the MagPi magazine article linked above for a discussion on wiring schematics.) Then run the following command and follow the onscreen instructions to flash the **.eep** file on the EEPROM:
|
||||
|
||||
```
|
||||
sudo ./eepflash.sh -w -f=settings.eep -t=24c32
|
||||
```
|
||||
|
||||
Before soldering the EEPROM to the printed circuit board, move it to the secondary I2C bus on the breadboard and test it to ensure it works as expected. If you detect any issues while testing the EEPROM on the breadboard, correct the settings files, move it back to the primary I2C bus, and flash it again.
|
||||
|
||||
### Testing the gamepad
|
||||
|
||||
Now comes the fun part! It is time to test the add-on board using Raspbian, which you can [download][20] from RaspberryPi.org. After booting, open a terminal and enter the following commands:
|
||||
|
||||
```
|
||||
cat /proc/device-tree/hat/product
|
||||
cat /proc/device-tree/hat/vendor
|
||||
```
|
||||
|
||||
The output should be similar to this:
|
||||
|
||||
![Testing output][21]
|
||||
|
||||
If it is, congratulations! The data from the EEPROM has been read successfully.
|
||||
|
||||
The next step is to verify that the keys on the Play pHAT are set properly and working. In a terminal or a text editor, press each of the eight buttons and verify they are acting as configured.
|
||||
|
||||
Finally, it is time to play games! By default, Raspbian's desktop includes [Python Games][22]. Launch them from the application menu. Make an audio output selection and pick a game from the list. My favorite is Wormy, a Snake-like game. As a former Symbian mobile application developer, I find playing Wormy brings back memories of the glorious days of Nokia.
|
||||
|
||||
### Retro gaming with RetroPie
|
||||
|
||||
![RetroPie with the Play pHAT][23]
|
||||
|
||||
Raspbian is amazing, but [RetroPie][24] offers so much more for retro games fans. It is a GNU/Linux distribution optimized for playing retro games and combines the open source projects RetroArch and Emulation Station. It's available for Raspberry Pi, the [Odroid][25] C1/C2, and personal computers running Debian or Ubuntu. It provides emulators for loading ROMs—the digital versions of game cartridges. Keep in mind that no ROMs are included in RetroPie due to copyright issues. You will have to [find appropriate ROMs and copy them][26] to the Raspberry Pi after booting RetroPie.
|
||||
|
||||
The open source hardware gamepad works fine in RetroPie's menus, but I discovered that the keys fail after launching some games and emulators. After debugging, I found a solution to ensuring they work in the game emulators: add a Python script for additional software emulation of the keys. [The script is available on GitHub.][27] Here's how to get it and install Python on RetroPie:
|
||||
|
||||
```
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y python-pip
|
||||
sudo pip install evdev
|
||||
cd ~
|
||||
git clone <https://github.com/AnaviTechnology/anavi-examples.git>
|
||||
```
|
||||
|
||||
Finally, add the following line to **/etc/rc.local** so it will be executed automatically when RetroPie boots:
|
||||
|
||||
```
|
||||
sudo python /home/pi/anavi-examples/anavi-play-phat/anavi-play-gamepad.py &
|
||||
```
|
||||
|
||||
That's it! After following these steps, you can create an entirely open source hardware gamepad as an add-on board for any Raspberry Pi model with a 40-pin header and use it with Raspbian and RetroPie!
|
||||
|
||||
### What's next?
|
||||
|
||||
Combining free and open source software with open source hardware is fun and not difficult, but it requires a significant amount of time. After creating the open source hardware gamepad in my spare time, I ran a modest crowdfunding campaign at [Crowd Supply][2] for low-volume manufacturing in my hometown in Plovdiv, Bulgaria. [The Open Source Hardware Association][28] certified the ANAVI Play pHAT as an open source hardware project under [BG000007][29]. Even [the acrylic enclosures][30] that protect the board from dust are open source hardware created with the free and open source software OpenSCAD.
|
||||
|
||||
![Game pad in acrylic enclosure][31]
|
||||
|
||||
If you enjoyed reading this article, I encourage you to try creating your own open source hardware add-on board for Raspberry Pi with KiCad. If you don't have enough spare time, you can order an [ANAVI Play pHAT maker kit][2], grab your soldering iron, and assemble the through-hole components. If you're not comfortable with the soldering iron, you can just order a fully assembled version.
|
||||
|
||||
Happy retro gaming everybody! Next time someone irritably asks what you can learn from playing vintage computer games, tell them about Raspberry Pi, open source hardware, Linux, and devicetree.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/3/gamepad-raspberry-pi
|
||||
|
||||
作者:[Leon Anavi][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/leon-anavi
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/gamepad_raspberrypi_hardware.jpg?itok=W16gOnay (Raspberry Pi Gamepad device)
|
||||
[2]: https://www.crowdsupply.com/anavi-technology/anavi-play-phat
|
||||
[3]: https://en.wikipedia.org/wiki/EEPROM
|
||||
[4]: https://en.wikipedia.org/wiki/Through-hole_technology
|
||||
[5]: https://en.wikipedia.org/wiki/I%C2%B2C
|
||||
[6]: https://www.raspberrypi.org/magpi/make-your-own-hat/
|
||||
[7]: http://kicad-pcb.org/
|
||||
[8]: https://www.olimex.com/Products/DIY-Laptop/
|
||||
[9]: http://kicad-pcb.org/help/getting-started/
|
||||
[10]: https://github.com/AnaviTechnology/anavi-play-phat
|
||||
[11]: https://opensource.com/sites/default/files/uploads/kicad-schematic.png (KiCad schematic)
|
||||
[12]: https://en.wikipedia.org/wiki/Netlist
|
||||
[13]: https://opensource.com/sites/default/files/uploads/circuitboard.png (Printable circuit board design)
|
||||
[14]: https://oshpark.com/
|
||||
[15]: https://aisler.net/
|
||||
[16]: https://www.devicetree.org/
|
||||
[17]: https://github.com/AnaviTechnology/hats/blob/anavi/eepromutils/anavi-play-phat.dts
|
||||
[18]: https://github.com/raspberrypi/hats
|
||||
[19]: https://www.raspberrypi.org/blog/introducing-raspberry-pi-hats/
|
||||
[20]: https://www.raspberrypi.org/downloads/
|
||||
[21]: https://opensource.com/sites/default/files/uploads/testing-output.png (Testing output)
|
||||
[22]: https://www.raspberrypi.org/documentation/usage/python-games/
|
||||
[23]: https://opensource.com/sites/default/files/uploads/retropie.jpg (RetroPie with the Play pHAT)
|
||||
[24]: https://retropie.org.uk/
|
||||
[25]: https://www.hardkernel.com/product-category/odroid-board/
|
||||
[26]: https://opensource.com/article/19/1/retropie
|
||||
[27]: https://github.com/AnaviTechnology/anavi-examples/blob/master/anavi-play-phat/anavi-play-gamepad.py
|
||||
[28]: https://www.oshwa.org/
|
||||
[29]: https://certification.oshwa.org/bg000007.html
|
||||
[30]: https://github.com/AnaviTechnology/anavi-cases/tree/master/anavi-play-phat
|
||||
[31]: https://opensource.com/sites/default/files/uploads/gamepad-acrylic.jpg (Game pad in acrylic enclosure)
|
@ -0,0 +1,85 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Setting kernel command line arguments with Fedora 30)
|
||||
[#]: via: (https://fedoramagazine.org/setting-kernel-command-line-arguments-with-fedora-30/)
|
||||
[#]: author: (Laura Abbott https://fedoramagazine.org/makes-fedora-kernel/)
|
||||
|
||||
Setting kernel command line arguments with Fedora 30
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
Adding options to the kernel command line is a common task when debugging or experimenting with the kernel. The upcoming Fedora 30 release made a change to use Bootloader Spec ([BLS][2]). Depending on how you are used to modifying kernel command line options, your workflow may now change. Read on for more information.
|
||||
|
||||
To determine if your system is running with BLS or the older layout, look in the file
|
||||
|
||||
```
|
||||
/etc/default/grub
|
||||
```
|
||||
|
||||
If you see
|
||||
|
||||
```
|
||||
GRUB_ENABLE_BLSCFG=true
|
||||
```
|
||||
|
||||
in there, you are running with the BLS setup and you may need to change how you set kernel command line arguments.
|
||||
|
||||
If you only want to modify a single kernel entry (for example, to temporarily work around a display problem) you can use a grubby command
|
||||
|
||||
```
|
||||
$ grubby --update-kernel /boot/vmlinuz-5.0.1-300.fc30.x86_64 --args="amdgpu.dc=0"
|
||||
```
|
||||
|
||||
To remove a kernel argument, you can use the
|
||||
|
||||
```
|
||||
--remove-args
|
||||
```
|
||||
argument to grubby
|
||||
|
||||
```
|
||||
$ grubby --update-kernel /boot/vmlinuz-5.0.1-300.fc30.x86_64 --remove-args="amdgpu.dc=0"
|
||||
```
|
||||
|
||||
If there is an option that should be added to every kernel command line (for example, you always want to disable the use of the rdrand instruction for random number generation) you can run a grubby command:
|
||||
|
||||
```
|
||||
$ grubby --update-kernel=ALL --args="nordrand"
|
||||
```
|
||||
|
||||
This will update the command line of all kernel entries and save the option to the saved kernel command line for future entries.
|
||||
|
||||
If you later want to remove the option from all kernels, you can again use
|
||||
|
||||
```
|
||||
--remove-args
|
||||
```
|
||||
with
|
||||
|
||||
```
|
||||
--update-kernel=ALL
|
||||
```
|
||||
|
||||
```
|
||||
$ grubby --update-kernel=ALL --remove-args="nordrand"
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/setting-kernel-command-line-arguments-with-fedora-30/
|
||||
|
||||
作者:[Laura Abbott][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/makes-fedora-kernel/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/03/f30-kernel-1-816x345.jpg
|
||||
[2]: https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault
|
@ -0,0 +1,347 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Standardizing WASI: A system interface to run WebAssembly outside the web)
|
||||
[#]: via: (https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/)
|
||||
[#]: author: (Lin Clark https://twitter.com/linclark)
|
||||
|
||||
Standardizing WASI: A system interface to run WebAssembly outside the web
|
||||
======
|
||||
|
||||
Today, we announce the start of a new standardization effort — WASI, the WebAssembly system interface.
|
||||
|
||||
**Why:** Developers are starting to push WebAssembly beyond the browser, because it provides a fast, scalable, secure way to run the same code across all machines.
|
||||
|
||||
But we don’t yet have a solid foundation to build upon. Code outside of a browser needs a way to talk to the system — a system interface. And the WebAssembly platform doesn’t have that yet.
|
||||
|
||||
**What:** WebAssembly is an assembly language for a conceptual machine, not a physical one. This is why it can be run across a variety of different machine architectures.
|
||||
|
||||
Just as WebAssembly is an assembly language for a conceptual machine, WebAssembly needs a system interface for a conceptual operating system, not any single operating system. This way, it can be run across all different OSs.
|
||||
|
||||
This is what WASI is — a system interface for the WebAssembly platform.
|
||||
|
||||
We aim to create a system interface that will be a true companion to WebAssembly and last the test of time. This means upholding the key principles of WebAssembly — portability and security.
|
||||
|
||||
**Who:** We are chartering a WebAssembly subgroup to focus on standardizing [WASI][1]. We’ve already gathered interested partners, and are looking for more to join.
|
||||
|
||||
Here are some of the reasons that we, our partners, and our supporters think this is important:
|
||||
|
||||
### Sean White, Chief R&D Officer of Mozilla
|
||||
|
||||
“WebAssembly is already transforming the way the web brings new kinds of compelling content to people and empowers developers and creators to do their best work on the web. Up to now that’s been through browsers, but with WASI we can deliver the benefits of WebAssembly and the web to more users, more places, on more devices, and as part of more experiences.”
|
||||
|
||||
### Tyler McMullen, CTO of Fastly
|
||||
|
||||
“We are taking WebAssembly beyond the browser, as a platform for fast, safe execution of code in our edge cloud. Despite the differences in environment between our edge and browsers, WASI means WebAssembly developers won’t have to port their code to each different platform.”
|
||||
|
||||
### Myles Borins, Node Technical Steering committee director
|
||||
|
||||
“WebAssembly could solve one of the biggest problems in Node — how to get close-to-native speeds and reuse code written in other languages like C and C++ like you can with native modules, while still remaining portable and secure. Standardizing this system interface is the first step towards making that happen.”
|
||||
|
||||
### Laurie Voss, co-founder of npm
|
||||
|
||||
“npm is tremendously excited by the potential WebAssembly holds to expand the capabilities of the npm ecosystem while hugely simplifying the process of getting native code to run in server-side JavaScript applications. We look forward to the results of this process.”
|
||||
|
||||
So that’s the big news! 🎉
|
||||
|
||||
There are currently 3 implementations of WASI:
|
||||
|
||||
|
||||
+ [wasmtime](https://github.com/CraneStation/wasmtime), Mozilla’s WebAssembly runtime
|
||||
+ [Lucet](https://www.fastly.com/blog/announcing-lucet-fastly-native-webassembly-compiler-runtime), Fastly’s WebAssembly runtime
|
||||
+ [a browser polyfill](https://wasi.dev/polyfill/)
|
||||
|
||||
|
||||
You can see WASI in action in this video:
|
||||
|
||||
<https://www.youtube.com/embed/ggtEJC0Jv8A>
|
||||
|
||||
And if you want to learn more about our proposal for how this system interface should work, keep reading.
|
||||
|
||||
### What’s a system interface?
|
||||
|
||||
Many people talk about languages like C giving you direct access to system resources. But that’s not quite true.
|
||||
|
||||
These languages don’t have direct access to do things like open or create files on most systems. Why not?
|
||||
|
||||
Because these system resources — such as files, memory, and network connections— are too important for stability and security.
|
||||
|
||||
If one program unintentionally messes up the resources of another, then it could crash the program. Even worse, if a program (or user) intentionally messes with the resources of another, it could steal sensitive data.
|
||||
|
||||
[![A frowning terminal window indicating a crash, and a file with a broken lock indicating a data leak][2]][3]
|
||||
|
||||
So we need a way to control which programs and users can access which resources. People figured this out pretty early on, and came up with a way to provide this control: protection ring security.
|
||||
|
||||
With protection ring security, the operating system basically puts a protective barrier around the system’s resources. This is the kernel. The kernel is the only thing that gets to do operations like creating a new file or opening a file or opening a network connection.
|
||||
|
||||
The user’s programs run outside of this kernel in something called user mode. If a program wants to do anything like open a file, it has to ask the kernel to open the file for it.
|
||||
|
||||
[![A file directory structure on the left, with a protective barrier in the middle containing the operating system kernel, and an application knocking for access on the right][4]][5]
|
||||
|
||||
This is where the concept of the system call comes in. When a program needs to ask the kernel to do one of these things, it asks using a system call. This gives the kernel a chance to figure out which user is asking. Then it can see if that user has access to the file before opening it.
|
||||
|
||||
On most devices, this is the only way that your code can access the system’s resources — through system calls.
|
||||
|
||||
[![An application asking the operating system to put data into an open file][6]][7]
|
||||
|
||||
The operating system makes the system calls available. But if each operating system has its own system calls, wouldn’t you need a different version of the code for each operating system? Fortunately, you don’t.
|
||||
|
||||
How is this problem solved? Abstraction.
|
||||
|
||||
Most languages provide a standard library. While coding, the programmer doesn’t need to know what system they are targeting. They just use the interface.
|
||||
|
||||
Then, when compiling, your toolchain picks which implementation of the interface to use based on what system you’re targeting. This implementation uses functions from the operating system’s API, so it’s specific to the system.
|
||||
|
||||
This is where the system interface comes in. For example, `printf` being compiled for a Windows machine could use the Windows API to interact with the machine. If it’s being compiled for Mac or Linux, it will use POSIX instead.
|
||||
|
||||
[![The interface for putc being translated into two different implementations, one implemented using POSIX and one implemented using Windows APIs][8]][9]
|
||||
|
||||
This poses a problem for WebAssembly, though.
|
||||
|
||||
With WebAssembly, you don’t know what kind of operating system you’re targeting even when you’re compiling. So you can’t use any single OS’s system interface inside the WebAssembly implementation of the standard library.
|
||||
|
||||
[![an empty implementation of putc][10]][11]
|
||||
|
||||
I’ve talked before about how WebAssembly is [an assembly language for a conceptual machine][12], not a real machine. In the same way, WebAssembly needs a system interface for a conceptual operating system, not a real operating system.
|
||||
|
||||
But there are already runtimes that can run WebAssembly outside the browser, even without having this system interface in place. How do they do it? Let’s take a look.
|
||||
|
||||
### How is WebAssembly running outside the browser today?
|
||||
|
||||
The first tool for producing WebAssembly was Emscripten. It emulates a particular OS system interface, POSIX, on the web. This means that the programmer can use functions from the C standard library (libc).
|
||||
|
||||
To do this, Emscripten created its own implementation of libc. This implementation was split in two — part was compiled into the WebAssembly module, and the other part was implemented in JS glue code. This JS glue would then call into the browser, which would then talk to the OS.
|
||||
|
||||
[![A Rube Goldberg machine showing how a call goes from a WebAssembly module, into Emscripten's JS glue code, into the browser, into the kernel][13]][14]
|
||||
|
||||
Most of the early WebAssembly code was compiled with Emscripten. So when people started wanting to run WebAssembly without a browser, they started by making Emscripten-compiled code run.
|
||||
|
||||
So these runtimes needed to create their own implementations for all of these functions that were in the JS glue code.
|
||||
|
||||
There’s a problem here, though. The interface provided by this JS glue code wasn’t designed to be a standard, or even a public facing interface. That wasn’t the problem it was solving.
|
||||
|
||||
For example, for a function that would be called something like `read` in an API that was designed to be a public interface, the JS glue code instead uses `_system3(which, varargs)`.
|
||||
|
||||
[![A clean interface for read, vs a confusing one for system3][15]][16]
|
||||
|
||||
The first parameter, `which`, is an integer which is always the same as the number in the name (so 3 in this case).
|
||||
|
||||
The second parameter, `varargs`, are the arguments to use. It’s called `varargs` because you can have a variable number of them. But WebAssembly doesn’t provide a way to pass in a variable number of arguments to a function. So instead, the arguments are passed in via linear memory. This isn’t type safe, and it’s also slower than it would be if the arguments could be passed in using registers.
|
||||
|
||||
That was fine for Emscripten running in the browser. But now runtimes are treating this as a de facto standard, implementing their own versions of the JS glue code. They are emulating an internal detail of an emulation layer of POSIX.
|
||||
|
||||
This means they are re-implementing choices (like passing arguments in as heap values) that made sense based on Emscripten’s constraints, even though these constraints don’t apply in their environments.
|
||||
|
||||
[![A more convoluted Rube Goldberg machine, with the JS glue and browser being emulated by a WebAssembly runtime][17]][18]
|
||||
|
||||
If we’re going to build a WebAssembly ecosystem that lasts for decades, we need solid foundations. This means our de facto standard can’t be an emulation of an emulation.
|
||||
|
||||
But what principles should we apply?
|
||||
|
||||
### What principles does a WebAssembly system interface need to uphold?
|
||||
|
||||
There are two important principles that are baked into WebAssembly :
|
||||
|
||||
* portability
|
||||
* security
|
||||
|
||||
|
||||
|
||||
We need to maintain these key principles as we move to outside-the-browser use cases.
|
||||
|
||||
As it is, POSIX and Unix’s Access Control approach to security don’t quite get us there. Let’s look at where they fall short.
|
||||
|
||||
### Portability
|
||||
|
||||
POSIX provides source code portability. You can compile the same source code with different versions of libc to target different machines.
|
||||
|
||||
[![One C source file being compiled to multiple binaries][19]][20]
|
||||
|
||||
But WebAssembly needs to go one step beyond this. We need to be able to compile once and run across a whole bunch of different machines. We need portable binaries.
|
||||
|
||||
[![One C source file being compiled to a single binary][21]][22]
|
||||
|
||||
This kind of portability makes it much easier to distribute code to users.
|
||||
|
||||
For example, if Node’s native modules were written in WebAssembly, then users wouldn’t need to run node-gyp when they install apps with native modules, and developers wouldn’t need to configure and distribute dozens of binaries.
|
||||
|
||||
### Security
|
||||
|
||||
When a line of code asks the operating system to do some input or output, the OS needs to determine if it is safe to do what the code asks.
|
||||
|
||||
Operating systems typically handle this with access control that is based on ownership and groups.
|
||||
|
||||
For example, the program might ask the OS to open a file. A user has a certain set of files that they have access to.
|
||||
|
||||
When the user starts the program, the program runs on behalf of that user. If the user has access to the file — either because they are the owner or because they are in a group with access — then the program has that same access, too.
|
||||
|
||||
[![An application asking to open a file that is relevant to what it's doing][23]][24]
|
||||
|
||||
This protects users from each other. That made a lot of sense when early operating systems were developed. Systems were often multi-user, and administrators controlled what software was installed. So the most prominent threat was other users taking a peek at your files.
|
||||
|
||||
That has changed. Systems now are usually single user, but they are running code that pulls in lots of other, third party code of unknown trustworthiness. Now the biggest threat is that the code that you yourself are running will turn against you.
|
||||
|
||||
For example, let’s say that the library you’re using in an application gets a new maintainer (as often happens in open source). That maintainer might have your interest at heart… or they might be one of the bad guys. And if they have access to do anything on your system — for example, open any of your files and send them over the network — then their code can do a lot of damage.
|
||||
|
||||
[![An evil application asking for access to the users bitcoin wallet and opening up a network connection][25]][26]
|
||||
|
||||
This is why using third-party libraries that can talk directly to the system can be dangerous.
|
||||
|
||||
WebAssembly’s way of doing security is different. WebAssembly is sandboxed.
|
||||
|
||||
This means that code can’t talk directly to the OS. But then how does it do anything with system resources? The host (which might be a browser, or might be a wasm runtime) puts functions in the sandbox that the code can use.
|
||||
|
||||
This means that the host can limit what a program can do on a program-by-program basis. It doesn’t just let the program act on behalf of the user, calling any system call with the user’s full permissions.
|
||||
|
||||
Just having a mechanism for sandboxing doesn’t make a system secure in and of itself — the host can still put all of the capabilities into the sandbox, in which case we’re no better off — but it at least gives hosts the option of creating a more secure system.
|
||||
|
||||
[![A runtime placing safe functions into the sandbox with an application][27]][28]
|
||||
|
||||
In any system interface we design, we need to uphold these two principles. Portability makes it easier to develop and distribute software, and providing the tools for hosts to secure themselves or their users is an absolute must.,
|
||||
|
||||
### What should this system interface look like?
|
||||
|
||||
Given those two key principles, what should the design of the WebAssembly system interface be?
|
||||
|
||||
That’s what we’ll figure out through the standardization process. We do have a proposal to start with, though:
|
||||
|
||||
* Create a modular set of standard interfaces
|
||||
* Start with standardizing the most fundamental module, wasi-core
|
||||
|
||||
|
||||
|
||||
[![Multiple modules encased in the WASI standards effort][29]][30]
|
||||
|
||||
What will be in wasi-core?
|
||||
|
||||
wasi-core will contain the basics that all programs need. It will cover much of the same ground as POSIX, including things such as files, network connections, clocks, and random numbers.
|
||||
|
||||
And it will take a very similar approach to POSIX for many of these things. For example, it will use POSIX’s file-oriented approach, where you have system calls such as open, close, read, and write and everything else basically provides augmentations on top.
|
||||
|
||||
But wasi-core won’t cover everything that POSIX does. For example, the process concept does not map clearly onto WebAssembly. And beyond that, it doesn’t make sense to say that every WebAssembly engine needs to support process operations like `fork`. But we also want to make it possible to standardize `fork`.
|
||||
|
||||
This is where the modular approach comes in. This way, we can get good standardization coverage while still allowing niche platforms to use only the parts of WASI that make sense for them.
|
||||
|
||||
[![Modules filled in with possible areas for standardization, such as processes, sensors, 3D graphics, etc][31]][32]
|
||||
|
||||
Languages like Rust will use wasi-core directly in their standard libraries. For example, Rust’s `open` is implemented by calling `__wasi_path_open` when it’s compiled to WebAssembly.
|
||||
|
||||
For C and C++, we’ve created a [wasi-sysroot][33] that implements libc in terms of wasi-core functions.
|
||||
|
||||
[![The Rust and C implementations of openat with WASI][34]][35]
|
||||
|
||||
We expect compilers like Clang to be ready to interface with the WASI API, and complete toolchains like the Rust compiler and Emscripten to use WASI as part of their system implementations
|
||||
|
||||
How does the user’s code call these WASI functions?
|
||||
|
||||
The runtime that is running the code passes the wasi-core functions in as imports.
|
||||
|
||||
[![A runtime placing an imports object into the sandbox][36]][37]
|
||||
|
||||
This gives us portability, because each host can have their own implementation of wasi-core that is specifically written for their platform — from WebAssembly runtimes like Mozilla’s wasmtime and Fastly’s Lucet, to Node, or even the browser.
|
||||
|
||||
It also gives us sandboxing because the host can choose which wasi-core functions to pass in — so, which system calls to allow — on a program-by-program basis. This preserves security.
|
||||
|
||||
[
|
||||
][38][![Three runtimes—wastime, Node, and the browser—passing their own implementations of wasi_fd_open into the sandbox][39]][40]
|
||||
|
||||
WASI gives us a way to extend this security even further. It brings in more concepts from capability-based security.
|
||||
|
||||
Traditionally, if code needs to open a file, it calls `open` with a string, which is the path name. Then the OS does a check to see if the code has permission (based on the user who started the program).
|
||||
|
||||
With WASI, if you’re calling a function that needs to access a file, you have to pass in a file descriptor, which has permissions attached to it. This could be for the file itself, or for a directory that contains the file.
|
||||
|
||||
This way, you can’t have code that randomly asks to open `/etc/passwd`. Instead, the code can only operate on the directories that are passed in to it.
|
||||
|
||||
[![Two evil apps in sandboxes. The one on the left is using POSIX and succeeds at opening a file it shouldn't have access to. The other is using WASI and can't open the file.][41]][42]
|
||||
|
||||
This makes it possible to safely give sandboxed code more access to different system calls — because the capabilities of these system calls can be limited.
|
||||
|
||||
And this happens on a module-by-module basis. By default, a module doesn’t have any access to file descriptors. But if code in one module has a file descriptor, it can choose to pass that file descriptor to functions it calls in other modules. Or it can create more limited versions of the file descriptor to pass to the other functions.
|
||||
|
||||
So the runtime passes in the file descriptors that an app can use to the top level code, and then file descriptors get propagated through the rest of the system on an as-needed basis.
|
||||
|
||||
[![The runtime passing a directory to the app, and then then app passing a file to a function][43]][44]
|
||||
|
||||
This gets WebAssembly closer to the principle of least privilege, where a module can only access the exact resources it needs to do its job.
|
||||
|
||||
These concepts come from capability-oriented systems, like CloudABI and Capsicum. One problem with capability-oriented systems is that it is often hard to port code to them. But we think this problem can be solved.
|
||||
|
||||
If code already uses `openat` with relative file paths, compiling the code will just work.
|
||||
|
||||
If code uses `open` and migrating to the `openat` style is too much up-front investment, WASI can provide an incremental solution. With [libpreopen][45], you can create a list of file paths that the application legitimately needs access to. Then you can use `open`, but only with those paths.
|
||||
|
||||
### What’s next?
|
||||
|
||||
We think wasi-core is a good start. It preserves WebAssembly’s portability and security, providing a solid foundation for an ecosystem.
|
||||
|
||||
But there are still questions we’ll need to address after wasi-core is fully standardized. Those questions include:
|
||||
|
||||
* asynchronous I/O
|
||||
* file watching
|
||||
* file locking
|
||||
|
||||
|
||||
|
||||
This is just the beginning, so if you have ideas for how to solve these problems, [join us][1]!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/
|
||||
|
||||
作者:[Lin Clark][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://twitter.com/linclark
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://wasi.dev/
|
||||
[2]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/01-01_crash-data-leak-1-500x220.png
|
||||
[3]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/01-01_crash-data-leak-1.png
|
||||
[4]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/01-02-protection-ring-sec-1-500x298.png
|
||||
[5]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/01-02-protection-ring-sec-1.png
|
||||
[6]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/01-03-syscall-1-500x227.png
|
||||
[7]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/01-03-syscall-1.png
|
||||
[8]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/02-01-implementations-1-500x267.png
|
||||
[9]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/02-01-implementations-1.png
|
||||
[10]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/02-02-implementations-1-500x260.png
|
||||
[11]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/02-02-implementations-1.png
|
||||
[12]: https://hacks.mozilla.org/2017/02/creating-and-working-with-webassembly-modules/
|
||||
[13]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/03-01-emscripten-1-500x329.png
|
||||
[14]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/03-01-emscripten-1.png
|
||||
[15]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/03-02-system3-1-500x179.png
|
||||
[16]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/03-02-system3-1.png
|
||||
[17]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/03-03-emulation-1-500x341.png
|
||||
[18]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/03-03-emulation-1.png
|
||||
[19]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-01-portability-1-500x375.png
|
||||
[20]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-01-portability-1.png
|
||||
[21]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-02-portability-1-500x484.png
|
||||
[22]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-02-portability-1.png
|
||||
[23]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-03-access-control-1-500x224.png
|
||||
[24]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-03-access-control-1.png
|
||||
[25]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-04-bitcoin-1-500x258.png
|
||||
[26]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-04-bitcoin-1.png
|
||||
[27]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-05-sandbox-1-500x278.png
|
||||
[28]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/04-05-sandbox-1.png
|
||||
[29]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-01-wasi-1-500x419.png
|
||||
[30]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-01-wasi-1.png
|
||||
[31]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-02-wasi-1-500x251.png
|
||||
[32]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-02-wasi-1.png
|
||||
[33]: https://github.com/CraneStation/wasi-sysroot
|
||||
[34]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-03-open-imps-1-500x229.png
|
||||
[35]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-03-open-imps-1.png
|
||||
[36]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-04-imports-1-500x285.png
|
||||
[37]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-04-imports-1.png
|
||||
[38]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-05-sec-port-1.png
|
||||
[39]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-05-sec-port-2-500x705.png
|
||||
[40]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-05-sec-port-2.png
|
||||
[41]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-06-openat-path-1-500x192.png
|
||||
[42]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-06-openat-path-1.png
|
||||
[43]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-07-file-perms-1-500x423.png
|
||||
[44]: https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2019/03/05-07-file-perms-1.png
|
||||
[45]: https://github.com/musec/libpreopen
|
@ -0,0 +1,202 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to Install and Configure Plex on Ubuntu Linux)
|
||||
[#]: via: (https://itsfoss.com/install-plex-ubuntu)
|
||||
[#]: author: (Chinmay https://itsfoss.com/author/chinmay/)
|
||||
|
||||
How to Install and Configure Plex on Ubuntu Linux
|
||||
======
|
||||
|
||||
When you are a media hog and have a big collection of movies, photos or music, the below capabilities would be very handy.
|
||||
|
||||
* Share media with family and other people.
|
||||
* Access media from different devices and platforms.
|
||||
|
||||
|
||||
|
||||
Plex ticks all of those boxes and more. Plex is a client-server media player system with additional features. Plex supports a wide array of platforms, both for the server and the player. No wonder it is considered one of the [best media servers for Linux][1].
|
||||
|
||||
Note: Plex is not a completely open source media player. We have covered it because this is one of the frequently [requested tutorial][2].
|
||||
|
||||
### Install Plex on Ubuntu
|
||||
|
||||
For this guide I am installing Plex on Elementary OS, an Ubuntu based distribution. You can still follow along if you are installing it on a headless Linux machine.
|
||||
|
||||
Go to the Plex [downloads][3] page, select Ubuntu 64-bit (I would not recommend installing it on a 32-bit CPU) and download the .deb file.
|
||||
|
||||
![][4]
|
||||
|
||||
[Download Plex][3]
|
||||
|
||||
You can [install the .deb file][5] by just clicking on the package. If it does not work, you can use an installer like **Eddy** or **[GDebi][6].**
|
||||
|
||||
You can also install it via the terminal using dpkg as shown below.
|
||||
|
||||
Install Plex on a headless Linux system
|
||||
|
||||
For a [headless system][7], you can use **wget** to download the .deb package. This example uses the current link for Ubuntu, at the time of writing. Be sure to use the up-to-date version supplied on the Plex website.
|
||||
|
||||
```
|
||||
wget https://downloads.plex.tv/plex-media-server-new/1.15.1.791-8bec0f76c/debian/plexmediaserver_1.15.1.791-8bec0f76c_amd64.deb
|
||||
```
|
||||
|
||||
The above command downloads the 64-bit .deb package. Once downloaded install the package using the following command.
|
||||
|
||||
```
|
||||
dpkg -i plexmediaserver*.deb
|
||||
```
|
||||
|
||||
Enable version upgrades for Plex
|
||||
|
||||
The .deb installation does create an entry in sources.d, but [repository updates][8] are not enabled by default and the contents of _plexmediaserver.list_ are commented out. This means that if there is a new Plex version available, your system will not be able to update your Plex install.
|
||||
|
||||
To enable repository updates you can either remove the # from the line starting with deb or run the following commands.
|
||||
|
||||
```
|
||||
echo deb https://downloads.plex.tv/repo/deb public main | sudo tee /etc/apt/sources.list.d/plexmediaserver.list
|
||||
```
|
||||
|
||||
The above command updates the entry in sources.d directory.
|
||||
|
||||
We also need to add Plex’s public key to facilitate secure and safe downloads. You can try running the command below, unfortunately this **did not work for me** and the [GPG][9] key was not added.
|
||||
|
||||
```
|
||||
curl https://downloads.plex.tv/plex-keys/PlexSign.key | sudo apt-key add -
|
||||
```
|
||||
|
||||
To fix this issue I found out the key hash for from the error message after running _sudo apt-get update._
|
||||
|
||||
![][10]
|
||||
|
||||
```
|
||||
97203C7B3ADCA79D
|
||||
```
|
||||
|
||||
The above hash can be used to add the key from the key-server. Run the below commands to add the key.
|
||||
|
||||
```
|
||||
gpg --keyserver https://downloads.plex.tv/plex-keys/PlexSign.key --recv-keys 97203C7B3ADCA79D
|
||||
```
|
||||
|
||||
```
|
||||
gpg --export --armor 97203C7B3ADCA79D|sudo apt-key add -
|
||||
```
|
||||
|
||||
You should see an **OK** once the key is added.
|
||||
|
||||
Run the below command to verify that the repository is added to the sources list successfully.
|
||||
|
||||
```
|
||||
sudo apt update
|
||||
```
|
||||
|
||||
To update Plex to the newest version available on the repository, run the below [apt-get command][11].
|
||||
|
||||
```
|
||||
sudo apt-get --only-upgrade install plexmediaserver
|
||||
```
|
||||
|
||||
Once installed the Plex service automatically starts running. You can check if its running by running the this command in a terminal.
|
||||
|
||||
```
|
||||
systemctl status plexmediaserver
|
||||
```
|
||||
|
||||
If the service is running properly you should see something like this.
|
||||
|
||||
![Check the status of Plex Server][12]
|
||||
|
||||
### Configuring Plex as a Media Server
|
||||
|
||||
The Plex server is accessible on the ports 32400 and 32401. Navigate to **localhost:32400** or **localhost:32401** using a browser. You should replace the ‘localhost’ with the IP address of the machine running Plex server if you are going headless.
|
||||
|
||||
The first time you are required to sign up or log in to your Plex account.
|
||||
|
||||
![Plex Login Page][13]
|
||||
|
||||
Now you can go ahead and give a friendly name to your Plex Server. This name will be used to identify the server over the network. You can also have multiple Plex servers identified by different names on the same network.
|
||||
|
||||
![Plex Server Setup][14]
|
||||
|
||||
Now it is finally time to add all your collections to the Plex library. Here your collections will be automatically get indexed and organized.
|
||||
|
||||
You can click the add library button to add all your collections.
|
||||
|
||||
![Add Media Library][15]
|
||||
|
||||
![][16]
|
||||
|
||||
Navigate to the location of the media you want to add to Plex .
|
||||
|
||||
![][17]
|
||||
|
||||
You can add multiple folders and different types of media.
|
||||
|
||||
When you are done, you are taken to a very slick looking Plex UI. You can already see the contents of your libraries showing up on the home screen. It also automatically selects a thumbnail and also fills the metadata.
|
||||
|
||||
![][18]
|
||||
|
||||
You can head over to the settings and configure some of the settings. You can create new users( **only with Plex Pass** ), adjust the transcoding settings set scheduled library updates and more.
|
||||
|
||||
If you have a public IP assigned to your router by the ISP you can also enable Remote Access. This means that you can be traveling and still access your libraries at home, considering you have your Plex server running all the time.
|
||||
|
||||
Now you are all set up and ready, but how do you access your media? Yes you can access through your browser but Plex has a presence in almost all platforms you can think of including Android Auto.
|
||||
|
||||
### Accessing Your Media and Plex Pass
|
||||
|
||||
You can access you media either by using the web browser (the same address you used earlier) or Plex’s suite of apps. The web browser experience is pretty good on computers and can be better on phones.
|
||||
|
||||
Plex apps provide a much better experience. But, the iOS and Android apps need to be activated with a [Plex Pass][19]. Without activation you are limited to 1 minute of video playback and images are watermarked.
|
||||
|
||||
Plex Pass is a premium subscription service which activates the mobile apps and enables more features. You can also individually activate your apps tied to a particular phone for a cheaper price. You can also create multiple users and set permissions with the Plex Pass which is a very handy feature.
|
||||
|
||||
You can check out all the benefits of Plex Pass [here][19].
|
||||
|
||||
_Note: Plex Meida Player is free on all platforms other than Android and iOS App._
|
||||
|
||||
**Conclusion**
|
||||
|
||||
That’s about all things you need to know for the first time configuration, go ahead and explore the Plex UI, it also gives you access to free online content like podcasts and music through Tidal.
|
||||
|
||||
There are alternatives to Plex like [Jellyfin][20] which is free but native apps are in beta and on road to be published on the App stores.You can also use a NAS with any of the freely available media centers like Kodi, OpenELEC or even VLC media player.
|
||||
|
||||
Here is an article listing the [best Linux media servers.][1]
|
||||
|
||||
Let us know your experience with Plex and what you use for your media sharing needs.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/install-plex-ubuntu
|
||||
|
||||
作者:[Chinmay][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/chinmay/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/best-linux-media-server/
|
||||
[2]: https://itsfoss.com/request-tutorial/
|
||||
[3]: https://www.plex.tv/media-server-downloads/
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/03/downloads-plex.png?ssl=1
|
||||
[5]: https://itsfoss.com/install-deb-files-ubuntu/
|
||||
[6]: https://itsfoss.com/gdebi-default-ubuntu-software-center/
|
||||
[7]: https://www.lions-wing.net/lessons/servers/home-server.html
|
||||
[8]: https://itsfoss.com/ubuntu-repositories/
|
||||
[9]: https://www.gnupg.org/
|
||||
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/03/Screenshot-from-2019-03-26-07-21-05-1.png?ssl=1
|
||||
[11]: https://itsfoss.com/apt-get-linux-guide/
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/03/check-plex-service.png?ssl=1
|
||||
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/03/plex-home-page.png?ssl=1
|
||||
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/03/Plex-server-setup.png?ssl=1
|
||||
[15]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/03/add-library.png?ssl=1
|
||||
[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/03/add-plex-library.png?ssl=1
|
||||
[17]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/03/add-plex-folder.png?ssl=1
|
||||
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/03/Screenshot-from-2019-03-17-22-27-56.png?ssl=1
|
||||
[19]: https://www.plex.tv/plex-pass/
|
||||
[20]: https://jellyfin.readthedocs.io/en/latest/
|
@ -0,0 +1,189 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (What are Ubuntu Repositories? How to enable or disable them?)
|
||||
[#]: via: (https://itsfoss.com/ubuntu-repositories)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
What are Ubuntu Repositories? How to enable or disable them?
|
||||
======
|
||||
|
||||
_**This detailed article tells you about various repositories like universe, multiverse in Ubuntu and how to enable or disable them.**_
|
||||
|
||||
So, you are trying to follow a tutorial from the web and installing a software using apt-get command and it throws you an error:
|
||||
|
||||
```
|
||||
E: Unable to locate package xyz
|
||||
```
|
||||
|
||||
You are surprised because others the package should be available. You search on the internet and come across a solution that you have to enable universe or multiverse repository to install that package.
|
||||
|
||||
**You can enable universe and multiverse repositories in Ubuntu using the commands below:**
|
||||
|
||||
```
|
||||
sudo add-apt-repository universe multiverse
|
||||
sudo apt update
|
||||
```
|
||||
|
||||
You installed the universe and multiverse repository but do you know what are these repositories? How do they play a role in installing packages? Why there are several repositories?
|
||||
|
||||
I’ll explain all these questions in detail here.
|
||||
|
||||
### The concept of repositories in Ubuntu
|
||||
|
||||
Okay, so you already know that to [install software in Ubuntu][1], you can use the [apt command][2]. This is the same [APT package manager][3] that Ubuntu Software Center utilizes underneath. So all the software (except Snap packages) that you see in the Software Center are basically from APT.
|
||||
|
||||
Have you ever wondered where does the apt program install the programs from? How does it know which packages are available and which are not?
|
||||
|
||||
Apt basically works on the repository. A repository is nothing but a server that contains a set of software. Ubuntu provides a set of repositories so that you won’t have to search on the internet for the installation file of various software of your need. This centralized way of providing software is one of the main strong points of using Linux.
|
||||
|
||||
The APT package manager gets the repository information from the /etc/apt/sources.list file and files listed in /etc/apt/sources.list.d directory. Repository information is usually in the following format:
|
||||
|
||||
```
|
||||
deb http://us.archive.ubuntu.com/ubuntu/ bionic main
|
||||
```
|
||||
|
||||
In fact, you can [go to the above server address][4] and see how the repository is structured.
|
||||
|
||||
When you [update Ubuntu using the apt update command][5], the apt package manager gets the information about the available packages (and their version info) from the repositories and stores them in local cache. You can see this in /var/lib/apt/lists directory.
|
||||
|
||||
Keeping this information locally speeds up the search process because you don’t have to go through the network and search the database of available packages just to check if a certain package is available or not.
|
||||
|
||||
Now you know how repositories play an important role, let’s see why there are several repositories provided by Ubuntu.
|
||||
|
||||
### Ubuntu Repositories: Main, Universe, Multiverse, Restricted and Partner
|
||||
|
||||
![][6]
|
||||
|
||||
Software in Ubuntu repository are divided into five categories: main, universe, multiverse, restricted and partner.
|
||||
|
||||
Why Ubuntu does that? Why not put all the software into one single repository? To answer this question, let’s see what are these repositories:
|
||||
|
||||
#### **Main**
|
||||
|
||||
When you install Ubuntu, this is the repository enabled by default. The main repository consists of only FOSS (free and open source software) that can be distributed freely without any restrictions.
|
||||
|
||||
Software in this repository are fully supported by the Ubuntu developers. This is what Ubuntu will provide with security updates until your system reaches end of life.
|
||||
|
||||
#### **Universe**
|
||||
|
||||
This repository also consists free and open source software but Ubuntu doesn’t guarantee of regular security updates to software in this category.
|
||||
|
||||
Software in this category are packaged and maintained by the community. The Universe repository has a vast amount of open source software and thus it enables you to have access to a huge number of software via apt package manager.
|
||||
|
||||
#### **Multiverse**
|
||||
|
||||
Multiverse contains the software that are not FOSS. Due to licensing and legal issues, Ubuntu cannot enable this repository by default and cannot provide fix and updates.
|
||||
|
||||
It’s up to you to decide if you want to use Multiverse repository and check if you have the right to use the software.
|
||||
|
||||
#### **Restricted**
|
||||
|
||||
Ubuntu tries to provide only free and open source software but that’s not always possible specially when it comes to supporting hardware.
|
||||
|
||||
The restricted repositories consists of proprietary drivers.
|
||||
|
||||
#### **Partner**
|
||||
|
||||
This repository consist of proprietary software packaged by Ubuntu for their partners. Earlier, Ubuntu used to provide Skype trough this repository.
|
||||
|
||||
#### Third party repositories and PPA (Not provided by Ubuntu)
|
||||
|
||||
The above five repositories are provided by Ubuntu. You can also add third party repositories (it’s up to you if you want to do it) to access more software or to access newer version of a software (as Ubuntu might provide old version of the same software).
|
||||
|
||||
For example, if you add the repository provided by [VirtualBox][7], you can get the latest version of VurtualBox. It will add a new entry in your sources.list.
|
||||
|
||||
You can also install additional application using PPA (Personal Package Archive). I have written about [what is PPA and how it works][8] in detail so please read that article.
|
||||
|
||||
Tip
|
||||
|
||||
Try NOT adding anything other than Ubuntu’s repositories in your sources.list file. You should keep this file in pristine condition because if you mess it up, you won’t be able to update your system or (at times) even install new packages.
|
||||
|
||||
### Add universe, multiverse and other repositories
|
||||
|
||||
As I had mentioned earlier, only the Main repository is enabled by default when you install Ubuntu. To access more software, you can add the additional repositories.
|
||||
|
||||
Let me show you how to do it in command line first and then I’ll show you the GUI ways as well.
|
||||
|
||||
To enable Universe repository, use:
|
||||
|
||||
```
|
||||
sudo add-apt-repository universe
|
||||
```
|
||||
|
||||
To enable Restricted repository, use:
|
||||
|
||||
```
|
||||
sudo add-apt-repository restricted
|
||||
```
|
||||
|
||||
To enable Multiverse repository, use this command:
|
||||
|
||||
```
|
||||
sudo add-apt-repository multiverse
|
||||
```
|
||||
|
||||
You must use sudo apt update command after adding the repository so that you system creates the local cache with package information.
|
||||
|
||||
If you want to **remove a repository** , simply add -r like **sudo add-apt-repository -r universe**.
|
||||
|
||||
Graphically, go to Software & Updates and you can enable the repositories here:
|
||||
|
||||
![Adding Universe, Restricted and Multiverse repositories][9]
|
||||
|
||||
You’ll find the option to enable partner repository in the Other Software tab.
|
||||
|
||||
![Adding Partner repository][10]
|
||||
|
||||
To disable a repository, simply uncheck the box.
|
||||
|
||||
### Bonus Tip: How to know which repository a package belongs to?
|
||||
|
||||
Ubuntu has a dedicated website that provides you with information about all the packages available in the Ubuntu archive. Go to Ubuntu Packages website.
|
||||
|
||||
[Ubuntu Packages][11]
|
||||
|
||||
You can search for a package name in the search field. You can select if you are looking for a particular Ubuntu release or a particular repository. I prefer using ‘any’ option in both fields.
|
||||
|
||||
![][12]
|
||||
|
||||
It will show you all the matching packages, Ubuntu releases and the repository information.
|
||||
|
||||
![][13]
|
||||
|
||||
As you can see above the package tor is available in the Universe repository for various Ubuntu releases.
|
||||
|
||||
**Conclusion**
|
||||
|
||||
I hope this article helped you in understanding the concept of repositories in Ubuntu.
|
||||
|
||||
If you have any questions or suggestions, please feel free to leave a comment below. If you liked the article, please share it on social media sites like Reddit and Hacker News.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/ubuntu-repositories
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/remove-install-software-ubuntu/
|
||||
[2]: https://itsfoss.com/apt-command-guide/
|
||||
[3]: https://wiki.debian.org/Apt
|
||||
[4]: http://us.archive.ubuntu.com/ubuntu/
|
||||
[5]: https://itsfoss.com/update-ubuntu/
|
||||
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/03/ubuntu-repositories.png?resize=800%2C450&ssl=1
|
||||
[7]: https://itsfoss.com/install-virtualbox-ubuntu/
|
||||
[8]: https://itsfoss.com/ppa-guide/
|
||||
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/03/enable-repositories-ubuntu.png?resize=800%2C490&ssl=1
|
||||
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/03/enable-partner-repository-ubuntu.png?resize=800%2C490&ssl=1
|
||||
[11]: https://packages.ubuntu.com
|
||||
[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/03/search-packages-ubuntu-archive.png?ssl=1
|
||||
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/03/search-packages-ubuntu-archive-1.png?resize=800%2C454&ssl=1
|
@ -1,217 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (LuuMing)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (My Google-free Android life)
|
||||
[#]: via: (https://lushka.al/my-android-setup/)
|
||||
[#]: author: (Anxhelo Lushka https://lushka.al/)
|
||||
|
||||
我的 Google-free 安卓之旅
|
||||
======
|
||||
|
||||
最近人们经常问我有关我手机的事情,比如安卓怎么安装,怎样绕过 Google Service 使用手机。好吧,这篇文章就来详细的解决那些问题。我尽可能让这篇文章适合初学者,因此我会说的很慢,一个一个来讲并且附上截图,你就能更好地看到它是怎样运作的。
|
||||
|
||||
首先我会告诉你为什么 Google Services(在我看来)对你的设备不好。我可以让你看 [Richard Stallman][2] 写的这篇[文章][1]并摘取一部分,但我决定抓住几个要点附在这。
|
||||
|
||||
* 需要<ruby>非自由软件<rt>Nonfree software</rt></ruby>
|
||||
* 大体上,许多 Google Services 需要运行在非自由的 Javascript 代码之上。现如今,如果禁用掉 Javascript,什么都没有了,甚至 Google 帐号都需要运行非自由软件(由站点发送的 JavaScript),对于登录也是。
|
||||
* 被监视
|
||||
* Google 悄悄地把他的<ruby>广告跟踪配置文件<rt>ad-tracking profiles</rt></ruby>与浏览配置文件结合在一起,并为每个用户存储大量数据。
|
||||
* 服务条款
|
||||
* Google 会终止转售 Pixel 手机用户的账户。他们无法访问帐户下保存在 Google Services 中的所有邮件和文档。
|
||||
* 审查
|
||||
* Amazon 和 Google 切断了<ruby>域前置<rt>domain-fronting</rt></ruby>,该技术能使身处专制国家的人们访问到那里禁止的通信系统。
|
||||
* Google 已经同意为巴基斯坦政府执行特殊的 Youtube 审查,删除反动内容。
|
||||
* Youtube 的“content ID”会自动删除已发布的视频,这并不包含在版权法中。
|
||||
|
||||
这只是几个原因,你可以阅读上面我提到的 RMS 的文章,他详细解释了这几点。尽管听起来骇人听闻,但这些行为在现实生活中已经每天在发生。
|
||||
|
||||
### 下一步, 我的搭建教程
|
||||
|
||||
我有一款[小米 Redmi Note 5 Pro][3] 智能手机(代号**whyred**),生产于中国的[小米][4]。它是 4 个月之前(写这篇文章的时候)我花了大约 185 欧元买的。
|
||||
|
||||
现在你也许会想,“但你为什么买中国品牌,他们不可靠”。是的,它不是通常你所期望的(品牌)所生产的,例如三星(人们通常会将它和安卓联系在一起,这显然是错的)、一加、诺基亚等。但你应当知道几乎所有的手机都生产于中国。
|
||||
|
||||
我选择这款手机有几个原因,首先当然是价格。它是一款相当高<ruby>**性价比**<rt>budget-friendly</rt></ruby>的产品,大多数人都能买得起。下一个原因(不仅仅)是说明书上的规格,在这个<ruby>价位<rt>price tag</rt></ruby>上相当合适。拥有 6 英尺屏幕(<ruby>全高清分辨率<rt>Full HD resolution</rt></ruby>),**4000 毫安电池**(一流的电池寿命),4GB RAM,64GB 存储,双后摄像头(12 MP + 5 MP),一个带闪光灯的前摄像头(13 MP)和一个高性能的<ruby>骁龙<rt>Snapdragon</rt></ruby> 636,它可能是那时候最好的选择。
|
||||
|
||||
随之而来的问题是 [MIUI][5],大多数小米设备附带的安卓皮肤(除了 Android One 项目设备)。是的,它没有那么可怕,它有一些额外的功能,但问题在更深的地方。小米设备如此便宜(据我所知销售利润仅有 5-10%)的一个原因是**他们在系统里伴随 MIUI 添加了数据挖掘和广告**。这样的话,系统应用需要额外不必要的权限来获取你的数据并且进行广告轰炸,从中获取利润。
|
||||
|
||||
更有趣的是,包含在内的天气应用想要访问我的联系人并且打电话,如果它仅是显示天气的话为什么需要访问。另一个例子是录音机应用,它也需要联系人和网络权限,可能想把录音发送回小米。
|
||||
|
||||
为了解决它,我不得不格式化手机并且摆脱 MIUI。这在最近市场上的手机上就变得极为艰难。
|
||||
|
||||
格式化手机的想法很简单,删除掉现有的系统然后安装一个新的喜欢的系统(这次是原生安卓)。为了实现它,你先得解锁 [bootloader][6]。
|
||||
|
||||
> bootloader 是一个在计算机完成自检后为其加载操作系统或者运行环境的计算机程序。—[维基百科][7]
|
||||
|
||||
问题是小米关于解锁 bootloader 有明确的政策。几个月之前,流程就像这样。你需向小米[申请][8]解锁代码,并提供真实的原因,但不是每次都成功,因为他们可以拒绝你的请求并且不提供理。
|
||||
|
||||
现在,流程变了。你要从小米那下载一个软件,叫做 [Mi Unlock][9],在 Windows 电脑上安装它,在手机的[开发者模式中打开调试选项][10],重启到 bootloader 模式(关机状态下长按音量下 + 电源键)并将手机连接到电脑上,开始一个叫做“同意”的流程。这个过程会在小米的服务器上启动一个定时器,允许你**在 15 天之后解锁手机**(在一些少数情况下或者一个月,完全随机)。
|
||||
|
||||
![Mi Unlock app][11]
|
||||
|
||||
15 天过去后,重新连接手机并重复之前的步骤,这时候按下解锁键,你的 bootloader 就会解锁,并且能够安装其他 ROM(系统)。**注意,确保你已经备份好了数据,因为解锁 bootloader 会清空手机。**
|
||||
|
||||
下一步就是找一个兼容的系统([ROM][12])。我在 [XDA 开发者论坛上][13]找了个遍,它是 Android 开发者和用户们交流想法、应用等东西的地方。幸运的是,我的手机相当流行,因此论坛上有它[专门的版块][14]。在那儿,我掠过一些流行的 ROM 并决定使用 [AOSiP ROM][15]。(AOSiP 代表<ruby>安卓开源 illusion 项目<rt>Android Open Source illusion Project</rt></ruby>)
|
||||
|
||||
**校订**:有人发邮件告诉我说文章里写的东西与目的就是[/e/][16]。我想说谢谢你的帮助,但完全不是这样。我关于 /e/ 的看法背后的原因可以见此[网站][17],但我仍会在此列出一些原因。
|
||||
|
||||
eelo 是一个从 Kickstarter 和 IndieGoGo 上集资并超过 200K € 的“基金会”,承诺创造一个开放、安全且保护隐私的移动 OS 和网页服务器。
|
||||
|
||||
1. 他们的 OS 基于 LineageOS 14.1 (Android 7.1) 且搭载 microG 和其他开源应用,此系统已经存在很长一段时间了并且现在叫做 [Lineage for microG][18]。
|
||||
2. 所有的应用程序并非从源代码构建,而是从 [APKPure][19] 上下载安装包并推送进 ROM,不知道那些安装包中是否包含<ruby>专有代码<rt>proprietary code</rt></ruby>或<ruby>恶意软件<rt>malware</rt></ruby>。
|
||||
3. 有一段时间,它们就那样随意地从代码中删除 Lineage <ruby>版权标头<rt>copyright header</rt></ruby>并加入自己的。
|
||||
4. 他们喜欢删除负面反馈并且监视用户 Telegram 群聊中的舆论。
|
||||
|
||||
总而言之,我**不建议使用 /e/** ROM。(至少现在)
|
||||
|
||||
另一件你有可能要做的事情是获取手机的 [root 权限][20],让它真正的成为你的手机,并且修改系统中的文件,例如使用系统范围的 adblocker 等。为了实现它,我决定使用 [Magisk][21],一个天赐的应用,它由一个学生开发,可以帮你获取设备的 root 权限并安装叫做[模块][22]的基础软件。
|
||||
|
||||
下载 ROM 和 Magisk 之后,我得在手机上安装它们。为了完成安装,我将文件移动到了 SD 卡上。现在,若要安装系统,我需要使用 [recovery system][23]。我用的是较为普遍的 [TWRP][24](代表 TeamWin Recovery Project)。
|
||||
|
||||
要安装 recovery system(听起来有点难,我知道),我需要将文件[烧录][20]进手机。为了完成烧录,我将手机用一个叫做 [ADB 的工具][25]连接上电脑(Fedora Linux 系统)。使用命令让自己定制的 recovery 系统覆盖掉原先的。
|
||||
|
||||
> fastboot flash recovery twrp.img
|
||||
|
||||
完成之后,我关掉手机并按住音量上和电源键,直到 TWRP 界面显示。这意味着我进行顺利,并且它已经准备好接收我的指令。
|
||||
|
||||
![TWRP screen][26]
|
||||
|
||||
下一步是**发送擦除命令**,在你第一次为手机安装自定义 ROM 时是必要的。如上图所示,擦除命令会清除掉<ruby>数据<rt>Data</rt></ruby>,<ruby>缓存<rt>Cache</rt></ruby>和 Dalvik 。(这里也有高级选项让我们可以勾选上来删除掉系统,如果我们不再需要旧系统的话)
|
||||
|
||||
这需要几分钟去完成,之后,你的手机基本上就干净了。现在是时候**安装系统了**。通过按下主屏幕上的安装按钮,我们选择之前添加进的 zip 文件(ROM 文件)并滑动屏幕安装它。下一步,我们需要安装 Magisk,它可以给我们访问设备的 root 权限。
|
||||
|
||||
**校订**:一些有经验的安卓用户或发烧友也许注意到了,手机上不包含 [GApps](谷歌应用)。这在安卓世界里称之为 GApps-less,一个 GAps 应用也不安装。
|
||||
|
||||
注意有一个不好之处在于若不安装 Google Services 有的应用无法正常工作,例如它们的通知也许会花更长的时间到达或者根本不起作用。(对我来说这一点是最影响应用程序使用的)原因是这些应用使用了 [Google Cloud Messaging][28](现在叫做 [Firebase][29])唤醒手机并推送通知。
|
||||
|
||||
你可以通过安装使用 [microG][30](部分地)解决它,microG 提供一些 Google Services 的特性且允许你拥有更多的控制。我不建议使用它,因为它仍然有助于 Google Services 并且你不一定信任它。但是,如果你没法<ruby>立刻放弃使用<rt>go cold turkey on it</rt><ruby>,只想慢慢地退出谷歌,这便是一个好的开始。
|
||||
|
||||
都成功地安装之后,现在我们重启手机,就进入了主屏幕。
|
||||
|
||||
### 下一个部分,安装应用并配置一切
|
||||
|
||||
事情开始变得简单了。为了安装应用,我使用了 [F-Droid][31],一个可替代的应用商店,里面**只包含免费和开源应用**。如果这里没有你要的应用,你可以使用 [Aurora Store][32],一个从应用商店里下载应用且不需要使用谷歌帐号或被追踪的客户端。
|
||||
|
||||
F-Droid 里面有 repos,一个包含你可以安装应用的“仓库”。我使用默认的仓库,并从 [IzzyOnDroid][33] 添加了另一个,它有更多默认仓库中没有的应用,并且它更新地更频繁。
|
||||
|
||||
![My repos][34]
|
||||
|
||||
从下面你可以发现我所安装的应用清单,它们替代的应用与用途。
|
||||
|
||||
AdAway > 系统广告拦截器,使用 hosts 文件拦截所有的广告
|
||||
AfWall+ > 一个防火墙,可以阻止不想要的连接
|
||||
Amaze > 替代系统的文件管理器,允许文件的 root 访问权限,并且拥有 zip/unzip 功能。
|
||||
Ameixa > 大多数应用的图标包
|
||||
andOTP > 替代谷歌验证/Authy,一个可以用来登录网站并报告哪里开启了<ruby>双因子验证<rt>2FA</rt></ruby>的 TOTP 应用。
|
||||
AnySoftKeyboard/AOSP Keyboard > 开源键盘,它有许多主题和语言包,我也是其项目一员
|
||||
Battery Charge Limit > 当到 80% 时自动停止充电,降低<ruby>电池磨损<rt>battery wear</rt></ruby>并增加寿命
|
||||
DAVx5 > 这是我最常用的应用之一,对我来说它基本上替代了谷歌联系人,谷歌日历和谷歌 Tasks,它连接着我的 Nextcloud 实例让我完全控制自己的数据
|
||||
Document Viewer > 一个可以打开数百种文件格式的查看器应用,快速、轻量
|
||||
Deezloader Remix (让我可以在 Deezer 上下载高质量 MP3 的应用)
|
||||
Easy xkcd > xkcd 漫画阅读器,我喜欢这些 xkcd 漫画
|
||||
Etar > 日历应用,替代谷歌日历,与 DAVx5 一同工作
|
||||
FastHub-Libre > 一个 GitHub 客户端,完全 FOSS(自由及开源软件),非常实用如果你像我一样喜欢使用 Github 扩展。
|
||||
Fennec F-Droid > 替代谷歌 Chrome 和其他类似的应用,一个 F-Droid 品牌的火狐浏览器,不含专有二进制代码并允许安装扩展提升浏览体验
|
||||
Gadgetbridge > 替代小米运动,可以用来配对小米硬件的应用,追踪你的健康,步数,睡眠等。
|
||||
K-9 Mail > 邮件客户端,替代 GMail 应用,可定制并可以添加多个账户
|
||||
Lawnchair > 启动器,可以替代 Nova Launcher 或 Pixel Launcher,允许自定义并有各样的改变,也支持图标包
|
||||
Mattermost > 可以连接 Mattermost 服务器的应用,Mattermost 可替代 Slack
|
||||
NewPipe > 最好的 YouTube 客户端 IMO,替代 YoubTube,它完全是 FOSS,免除 YouTube 广告,占用更少空间,允许背景播放,允许下载视频/音频等。试一试吧。
|
||||
Nextcloud SMS > 允许备份/同步 SMS 到我的 Nextcloud 实例
|
||||
Nextcloud Notes > 允许我创建,修改,删除,分享笔记并同步/备份到 Nextcloud 实例
|
||||
OpenTasks > 允许我创建,修改,删除任务并同步到 Nextcloud 实例
|
||||
OsmAnd~ > 一个地图应用,使用 OpenStreetMap,允许下载离线地图和导航
|
||||
QKSMS > 我最喜欢的 SMS 应用,替代 stock Messaging 应用,拥有漂亮的界面,拥有备份,个性化,延迟发送等特性。
|
||||
Resplash/Mysplash > 允许你无限地从 Unsplash 下载漂亮的壁纸,全部免费使用与修改。
|
||||
ScreenCam > 一个录屏工具,允许各样的自定义和录制模式,没有广告并且免费
|
||||
SecScanQR > QR 码识别应用,快速轻量
|
||||
Send Reduced Free > 这个应用可以在发送之前通过减少 PPI(<ruby>个人识别信息<rt>personally identifiable information</rt></ruby>)让你立即分享大图
|
||||
Slide > 开源 Reddit 客户端
|
||||
Telegram FOSS > 没有追踪和 Google Services 的干净版本 Telegram 安卓客户端
|
||||
TrebleShot > 这个天才般的应用可以让你通过 WIFI 分享文件,真的非常快,且无需连接网络
|
||||
Tusky > Tusky 是 Mastodon 平台的客户端(Mastodon 替代 Twitter)
|
||||
Unit Converter Ultimate > 这款应用可以在 200 种单位之间来回转换,非常快并且完全离线
|
||||
Vinyl Music Player > 我喜欢的音乐播放器,替代谷歌音乐播放器或任何其他音乐播放器,它有漂亮的界面和许多特性
|
||||
VPN Hotspot > 这款应用可以让我打开热点的时候分享 VPN,因此我可以不用做任何别的事情来安全地浏览网页,甚至是在笔记本上
|
||||
|
||||
这些差不多就是我列出的一张**最实用的 F-Droid 应用**清单,但不巧,这些并不是所有应用。我使用的专有应用如下(我知道,我也许听起来是一个伪君子,但并不是所有的应用都可以替代,至少现在不是):
|
||||
|
||||
* AliExpress
|
||||
* Boost for Reddit
|
||||
* Google Camera(与 Camera API 2 耦合,它可以让我用 185 欧元的手机拍一张非常棒的图片,真是太不可思议了)
|
||||
* Instagram
|
||||
* MediaBox HD (让我可以看流媒体电影)
|
||||
* Mi Fit (与小米手环 2 配对的应用)
|
||||
* MyVodafoneAL (运营商应用)
|
||||
* ProtonMail (email 应用)
|
||||
* Shazam Encore (识别咖啡店里你经常能听到的歌曲)
|
||||
* Snapseed (图片编辑应用,非常简单,强大,相当棒)
|
||||
* Spotify (在线音乐)
|
||||
* Titanium Backup(备份应用数据,wifi 密码,通话记录等)
|
||||
* ViPER4Android FX (音乐均衡器)
|
||||
* VSCO (图片编辑,从没真正用过)
|
||||
* WhatsApp (E2E 专有聊天应用,几乎我认识的所有人都有它)
|
||||
* WiFi Map(地图标注可用的热点,在国外非常方便)
|
||||
|
||||
差不多就是这样,我用的手机上所有的应用。**配置非常简单明了,我可以给几点提示**。
|
||||
|
||||
1. 仔细阅读和检查应用的权限,不要无脑地点“安装”。
|
||||
2. 尽可能多地使用开源应用,它们即尊重你的隐私又是免费的。(既“<ruby>free beer<rt>软件好用下次请我喝一杯</rt></ruby>” 又自由)
|
||||
3. 尽可能地使用 VPN,找一个有名气的,别用免费的,否则你将被收割数据然后成为产品。
|
||||
4. 不要一直打开 WIFI/移动数据/定位,有可能引起安全隐患。
|
||||
5. 不要只依赖指纹解锁,或者尽可能只用 PIN/密码/模式解锁,因为生物数据可以被克隆后反对你,例如解锁你的手机盗取你的数据。
|
||||
|
||||
作为坚持读到这儿的奖励,**一张主屏幕的截图奉上**
|
||||
|
||||
![Screenshot][35]
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://lushka.al/my-android-setup/
|
||||
|
||||
作者:[Anxhelo Lushka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[LuuMing](https://github.com/luuming)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://lushka.al/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://stallman.org/google.html
|
||||
[2]: https://en.wikipedia.org/wiki/Richard_Stallman
|
||||
[3]: https://www.gsmarena.com/xiaomi_redmi_note_5_pro-8893.php
|
||||
[4]: https://en.wikipedia.org/wiki/Xiaomi
|
||||
[5]: https://en.wikipedia.org/wiki/MIUI
|
||||
[6]: https://forum.xda-developers.com/wiki/Bootloader
|
||||
[7]: https://en.wikipedia.org/wiki/Booting
|
||||
[8]: https://en.miui.com/unlock/
|
||||
[9]: http://www.miui.com/unlock/apply.php
|
||||
[10]: https://www.youtube.com/watch?v=7zhEsJlivFA
|
||||
[11]: https://lushka.al//assets/img/posts/mi-unlock.png
|
||||
[12]: https://www.xda-developers.com/what-is-custom-rom-android/
|
||||
[13]: https://forum.xda-developers.com/
|
||||
[14]: https://forum.xda-developers.com/redmi-note-5-pro
|
||||
[15]: https://forum.xda-developers.com/redmi-note-5-pro/development/rom-aosip-8-1-t3804473
|
||||
[16]: https://e.foundation
|
||||
[17]: https://ewwlo.xyz/evil
|
||||
[18]: https://lineage.microg.org/
|
||||
[19]: https://apkpure.com/
|
||||
[20]: https://lifehacker.com/5789397/the-always-up-to-date-guide-to-rooting-any-android-phone
|
||||
[21]: https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445
|
||||
[22]: https://forum.xda-developers.com/apps/magisk
|
||||
[23]: http://www.smartmobilephonesolutions.com/content/android-system-recovery
|
||||
[24]: https://dl.twrp.me/whyred/
|
||||
[25]: https://developer.android.com/studio/command-line/adb
|
||||
[26]: https://lushka.al//assets/img/posts/android-twrp.png
|
||||
[27]: https://opengapps.org/
|
||||
[28]: https://developers.google.com/cloud-messaging/
|
||||
[29]: https://firebase.google.com/docs/cloud-messaging/
|
||||
[30]: https://microg.org/
|
||||
[31]: https://f-droid.org/
|
||||
[32]: https://f-droid.org/en/packages/com.dragons.aurora/
|
||||
[33]: https://android.izzysoft.de/repo
|
||||
[34]: https://lushka.al//assets/img/posts/android-fdroid-repos.jpg
|
||||
[35]: https://lushka.al//assets/img/posts/android-screenshot.jpg
|
||||
[36]: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
@ -0,0 +1,120 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Secure Email Service Tutanota Has a Desktop App Now)
|
||||
[#]: via: (https://itsfoss.com/tutanota-desktop)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
加密邮件服务 Tutanota 现在有桌面应用了
|
||||
======
|
||||
|
||||
[Tutanota][1] 最近[宣布][2]发布针对其电子邮件服务的桌面应用。该 Beta 版适用于 Linux、Windows 和 macOS。
|
||||
|
||||
### 什么是 Tutanota?
|
||||
|
||||
网上有大量免费的、带有广告的电子邮件服务。但是,大多数电子邮件服务并不完全安全或在意隐私。在这个后[[斯诺登][3]世界中,[Tutanota][4] 提供了免费、安全的电子邮件服务,它专注于隐私。
|
||||
|
||||
Tutanota 有许多引人注目的功能,例如:
|
||||
|
||||
* 端到端加密邮箱
|
||||
* 端到端加密地址簿
|
||||
* 用户之间自动端到端加密邮件
|
||||
* 使用共享密码将端到端加密电子邮件发送到任何电子邮件地址
|
||||
* 安全密码重置,使 Tutanota 完全无法访问
|
||||
* 从发送和接收的电子邮件中去除 IP 地址
|
||||
* 运行Tutanota 的代码是[开源][5]的
|
||||
* 双重身份验证
|
||||
* 专注于隐私
|
||||
* 密码加盐,并本地使用 Bcrypt 哈希
|
||||
* 位于德国的安全服务器
|
||||
* 支持PFS、DMARC、DKIM、DNSSEC 和 DANE 的 TLS
|
||||
* 本地执行加密数据的全文搜索
|
||||
|
||||
|
||||
|
||||
![][6]
|
||||
web 中的 Tutanota
|
||||
|
||||
你可以[免费注册一个帐户][7]。你还可以升级帐户获取其他功能,例如自定义域、自定义域登录、域规则、额外的存储和别名。他们还提供企业帐户。
|
||||
|
||||
Tutanota 也可以在移动设备上使用。事实上,它的 [Android 应用也是开源的][8]。
|
||||
|
||||
这家德国公司计划扩展邮件之外的其他业务。他们希望提供加密的日历和云存储。你可以通过 PayPal 和加密货币[捐赠][9]帮助他们实现目标。
|
||||
|
||||
### Tutanota 的新桌面应用
|
||||
|
||||
Tutanota 在圣诞节前宣布了桌面应用的 [Beta 版][2]。该应用基于 [Electron][10]。
|
||||
|
||||
![][11]
|
||||
Tutanota 桌面应用
|
||||
|
||||
他们选择 Electron 的原因:
|
||||
|
||||
* 以最小的成本支持三个主流操作系统。
|
||||
* 快速调整新桌面客户端,使其与添加到网页客户端的新功能一致。
|
||||
* 将开发时间留给桌面功能,例如离线可用、电子邮件导入,将同时在所有三个桌面客户端中提供。
|
||||
|
||||
|
||||
|
||||
由于这是 Beta 版,因此应用中缺少一些功能。Tutanota 的开发团队正在努力添加以下功能:
|
||||
|
||||
* 电子邮件导入和与外部邮箱同步。这将“使 Tutanota 能够从外部邮箱导入电子邮件,并在将数据存储在 Tutanota 服务器上之前在设备本地加密数据。”
|
||||
* 电子邮件的离线可用
|
||||
* 双重身份验证
|
||||
|
||||
|
||||
|
||||
### 如何安装 Tutanota 桌面客户端?
|
||||
|
||||
![][12]
|
||||
在 Tutanota 中写邮件
|
||||
|
||||
你可以直接从 Tutanota 的网站[下载][2] Beta 版应用。它们有[适用于 Linux 的 AppImage 文件][13]、适用于 Windows 的 .exe 文件和适用于 macOS 的 .app 文件。你可以将你遇到的任何 bug 发布到 Tutanota 的 [GitHub 帐号中][14]。
|
||||
|
||||
为了证明应用的安全性,Tutanota 签名了每个版本。 “签名确保桌面客户端以及任何更新直接来自我们且未被篡改。”你可以使用 Tutanota 的 [GitHub 页面][15]来验证签名。
|
||||
|
||||
请记住,你需要先创建一个 Tutanota 帐户才能使用它。该邮件客户端设计上只能用在 Tutanota。
|
||||
|
||||
### 总结
|
||||
|
||||
我在 Linux Mint MATE 上测试了 Tutanota 的邮件应用。正如所料,它是网络应用的镜像。同时,我发现桌面应用和 Web 应用程序之间没有任何区别。我目前觉得使用该应用的唯一场景是在自己的窗口中使用。
|
||||
|
||||
你曾经使用过 [Tutanota][16] 么?如果没有,你最喜欢的关心隐私的邮件服务是什么?请在下面的评论中告诉我们。
|
||||
|
||||
如果你觉得这篇文章很有趣,请花些时间在社交媒体、Hacker News 或 [Reddit][17] 上分享。
|
||||
|
||||
![][18]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/tutanota-desktop
|
||||
|
||||
作者:[John Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/john/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/tutanota-review/
|
||||
[2]: https://tutanota.com/blog/posts/desktop-clients/
|
||||
[3]: https://en.wikipedia.org/wiki/Edward_Snowden
|
||||
[4]: https://tutanota.com/
|
||||
[5]: https://tutanota.com/blog/posts/open-source-email
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/tutanota2.jpg?resize=800%2C490&ssl=1
|
||||
[7]: https://tutanota.com/pricing
|
||||
[8]: https://itsfoss.com/tutanota-fdroid-release/
|
||||
[9]: https://tutanota.com/community
|
||||
[10]: https://electronjs.org/
|
||||
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/tutanota-app1.png?fit=800%2C486&ssl=1
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/tutanota1.jpg?resize=800%2C405&ssl=1
|
||||
[13]: https://itsfoss.com/use-appimage-linux/
|
||||
[14]: https://github.com/tutao/tutanota
|
||||
[15]: https://github.com/tutao/tutanota/blob/master/buildSrc/installerSigner.js
|
||||
[16]: https://tutanota.com/polo/
|
||||
[17]: http://reddit.com/r/linuxusersgroup
|
||||
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/02/tutanota-featured.png?fit=800%2C450&ssl=1
|
Loading…
Reference in New Issue
Block a user