mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-06 23:50:16 +08:00
commit
dda0733c99
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11960-1.html)
|
||||
[#]: subject: (Syncthing: Open Source P2P File Syncing Tool)
|
||||
[#]: via: (https://itsfoss.com/syncthing/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
@ -10,11 +10,11 @@
|
||||
Syncthing:开源 P2P 文件同步工具
|
||||
======
|
||||
|
||||
_ **简介:Syncthing 是一个开源的 P2P 文件同步工具,可用于在多个设备(包括 Android 手机)之间同步文件。** _
|
||||
> Syncthing 是一个开源的 P2P 文件同步工具,可用于在多个设备(包括 Android 手机)之间同步文件。
|
||||
|
||||
通常,我们有 [MEGA][1] 或 Dropbox 之类的云同步解决方案,以便在云上备份我们的文件,同时更易于共享。
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/05/094211oy2dosttvoaseovk.jpg)
|
||||
|
||||
但是,如果要跨多个设备同步文件而不将其存储在云中怎么办?
|
||||
通常,我们有 [MEGA][1] 或 Dropbox 之类的云同步解决方案,以便在云上备份我们的文件,同时更易于共享。但是,如果要跨多个设备同步文件而不将其存储在云中怎么办?
|
||||
|
||||
这就是 [Syncthing][2] 派上用场的地方了。
|
||||
|
||||
@ -22,7 +22,7 @@ _ **简介:Syncthing 是一个开源的 P2P 文件同步工具,可用于在
|
||||
|
||||
![][3]
|
||||
|
||||
Syncthing 可让你跨多个设备同步文件(包括对 Android 智能手机的支持)。它主要通过 Linux上 的 Web UI 进行工作,但也提供了 GUI(需要单独安装)。
|
||||
Syncthing 可让你跨多个设备同步文件(包括对 Android 智能手机的支持)。它主要通过 Linux 上的 Web UI 进行工作,但也提供了 GUI(需要单独安装)。
|
||||
|
||||
然而,Syncthing 完全没有利用云,它是 [P2P][4] 文件同步工具。你的数据不会被发送到中央服务器。而是会在所有设备之间同步。因此,它并不能真正取代 [Linux 上的典型云存储服务][5]。
|
||||
|
||||
@ -36,7 +36,7 @@ Syncthing 可让你跨多个设备同步文件(包括对 Android 智能手机
|
||||
|
||||
例如,你可能不想在云上存储一些敏感文件,因此你可以添加其他受信任的设备来同步并保留这些文件的副本。
|
||||
|
||||
即使我简单描述了它,但它并不像看到的那么简单。如果你感兴趣的话,我建议你阅读[官方 FAQ][7] 来了解它如何工作的。
|
||||
即使我对它的描述很简单,但它并不像看到的那么简单。如果你感兴趣的话,我建议你阅读[官方 FAQ][7] 来了解它如何工作的。
|
||||
|
||||
### Syncthing 的特性
|
||||
|
||||
@ -90,15 +90,15 @@ Syncthing 确实非常简单且易于理解。即使这样,如果你想使用
|
||||
|
||||
你可能无法在软件中心找到它(如果你找到了,那它可能不是最新版本)。
|
||||
|
||||
**注意:**_如果你需要一个 GUI 而不是浏览器来管理它,它还有一个 [Syncthing-GTK][16]。_
|
||||
**注意:**如果你需要一个 GUI 应用而不是浏览器来管理它,它还有一个 [Syncthing-GTK][16]。
|
||||
|
||||
[Syncthing][2]
|
||||
- [Syncthing][2]
|
||||
|
||||
如果你有基于 Debian 的发行版,你也可以利用终端来安装它,这些说明位于[官方下载页面][17] 上。
|
||||
如果你有基于 Debian 的发行版,你也可以利用终端来安装它,这些说明位于[官方下载页面][17]上。
|
||||
|
||||
### 我在 Syncthing 方面的体验
|
||||
|
||||
就个人而言,我把它安装在 Pop!\_OS 19.10 上,并在写这篇文章之前用了一会儿。
|
||||
就个人而言,我把它安装在 Pop!_OS 19.10 上,并在写这篇文章之前用了一会儿。
|
||||
|
||||
我尝试同步文件夹、删除它们、添加重复文件以查看文件版本控制是否工作,等等。它工作良好。
|
||||
|
||||
@ -108,7 +108,7 @@ Syncthing 确实非常简单且易于理解。即使这样,如果你想使用
|
||||
|
||||
总体而言,它工作良好,但我必须说,你不应该依赖它作为唯一的数据备份方案。
|
||||
|
||||
**总结**
|
||||
### 总结
|
||||
|
||||
你试过 Syncthing 了吗?如果有的话,你的体验如何?欢迎在下面的评论中分享。
|
||||
|
||||
@ -121,7 +121,7 @@ via: https://itsfoss.com/syncthing/
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,30 +1,30 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11961-1.html)
|
||||
[#]: subject: (4 open source productivity tools on my wishlist)
|
||||
[#]: via: (https://opensource.com/article/20/1/open-source-productivity-tools)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
我的愿望清单上的 4 个开源生产力工具
|
||||
我的愿望清单上的 4 种开源生产力工具
|
||||
======
|
||||
|
||||
> 在 2020 年用开源实现更高生产力的二十种方式的最后一篇文章中,了解开源世界需要做什么。
|
||||
> 在 2020 年用开源实现更高生产力的二十种方式的最后一篇文章中,了解开源世界还需要什么。
|
||||
|
||||
![Two diverse hands holding a globe][1]
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/05/100642k52u7oydcwnc1c2w.jpg)
|
||||
|
||||
去年,我在 19 天里给你介绍了 19 个新(对你而言)的生产力工具。今年,我换了一种方式:使用你在使用或者还没使用的工具,构建一个使你可以在新一年更加高效的环境。
|
||||
|
||||
### 不过…
|
||||
### 然而…
|
||||
|
||||
在搜索生产力应用程序时,我找不到想要的一切应用,而且几乎总是会丢失一些读者与我分享的精彩内容。 因此,当我结束本系列文章时,是时候[再次][2]谈论我在本年度系列文章中未能涵盖的一些主题。
|
||||
在搜索生产力应用程序时,我找不到想要的所有应用,而且几乎总是会丢失一些读者与我分享的精彩内容。 因此,当我结束本系列文章时,是时候[再次][2]谈论我在本年度系列文章中未能涵盖的一些主题。
|
||||
|
||||
![Desktop with Joplin, Emacs, and Firefox][3]
|
||||
|
||||
#### 在 Vim 中聊天
|
||||
|
||||
我试过了。我真的非常非常想能够在 Vim 中聊天,但我做不到。我找到的一个软件包 [VimIRC.vim][4] 一直就工作不起来,我试了几天也没用。我探索的另一个选项是 [Irc it][5],这需要我付出更多的[努力去设置][6],超过了我正常可以付出的耐心或时间。我尝试过了,也确实做到了,但对于同处于相同境地的 Vim 用户,对不起,我无法帮到你。
|
||||
我试过了。我真的非常、非常想能够在 Vim 中聊天,但我做不到。我找到的一个软件包 [VimIRC.vim][4] 一直就工作不起来,我试了几天也没用。我探索的另一个选项是 [Irc it][5],这需要我付出更多的[努力去设置][6],超过了我正常可以付出的耐心或时间。我尝试过了,也确实做到了,但对于同处于相同境地的 Vim 用户,对不起,我无法帮到你。
|
||||
|
||||
#### Org 模式
|
||||
|
||||
@ -36,15 +36,38 @@
|
||||
|
||||
#### 图形用户界面程序
|
||||
|
||||
在 2019 年的生产力系列中,我共享了很多图形用户界面程序,而今年几乎都是命令行应用程序。有一些很棒的图形程序可以帮助解决我今年谈论的一些问题,例如可以使用 Maildir 邮箱的[邮件][12]程序、用于读取本地日历文件的日历程序、[天气][13]应用程序等等。我甚至尝试了几项对我而言新奇的事物,看它们是否适合这个主题。除了 [twin][14] 之外,我没有感觉到有什么图形用户界面程序是新颖的(对我而言)或值得注意的(同样对我而言)今年要写的。至于……
|
||||
在 2019 年的生产力系列中,我共享了很多图形用户界面程序,而今年几乎都是命令行应用程序。有一些很棒的图形程序可以帮助解决我今年谈论的一些问题,例如可以使用 Maildir 邮箱的[邮件][12]程序、用于读取本地日历文件的日历程序、[天气][13]应用程序等等。我甚至尝试了几项对我而言新奇的事物,看它们是否适合这个主题。除了 [twin][14] 之外,我没有感觉到有什么图形用户界面程序是新颖的(对我而言)或值得注意的(同样对我而言)是今年要写的。至于……
|
||||
|
||||
#### 移动应用程序
|
||||
|
||||
越来越多的人将平板电脑(有时与笔记本电脑结合使用)作为主要设备。我将手机用于大多数社交媒体和即时消息传递,并且经常使用平板电脑(好的,老实说,好几个平板电脑)来阅读或浏览网络。可以肯定的是,并不是开源移动应用程序不存在,但是它们与我今年的主题不符。开源和移动应用程序正在发生很多变化,我正在仔细地寻找可以帮助我在手机和平板电脑上提高工作效率的事物。
|
||||
越来越多的人将平板电脑(有时与笔记本电脑结合使用)作为主要设备。我将手机用于大多数社交媒体和即时消息传递,并且经常使用平板电脑(好的,老实说,好几个平板电脑)来阅读或浏览网络。可以肯定的是,并不是没有开源移动应用程序,但是它们与我今年的主题不符。开源和移动应用程序正在发生很多变化,我正在仔细地寻找可以帮助我在手机和平板电脑上提高工作效率的事物。
|
||||
|
||||
### 该你了
|
||||
|
||||
非常感谢你阅读今年的系列文章。请你发表评论,告诉我错过的或需要在 2021 年看到的内容。正如我在 [Productivity Alchemy] [15] 播客上所说:“哥们,记着:保持生产力!”
|
||||
非常感谢你阅读今年的系列文章。请你发表评论,告诉我错过的或需要在 2021 年看到的内容。正如我在 [Productivity Alchemy][15] 播客上所说:“哥们,记着:要保持生产力!”
|
||||
|
||||
### 本系列汇总
|
||||
|
||||
1. [使用 Syncthing 在多个设备间同步文件](https://linux.cn/article-11793-1.html)
|
||||
2. [使用 Stow 管理多台机器配置](https://linux.cn/article-11796-1.html)
|
||||
3. [使用 OfflineIMAP 同步邮件](https://linux.cn/article-11804-1.html)
|
||||
4. [使用 Notmuch 组织你的邮件](https://linux.cn/article-11807-1.html)
|
||||
5. [使用 khal 和 vdirsyncer 组织和同步你的日历](https://linux.cn/article-11812-1.html)
|
||||
6. [用于联系人管理的三个开源工具](https://linux.cn/article-11834-1.html)
|
||||
7. [开始使用开源待办事项清单管理器](https://linux.cn/article-11835-1.html)
|
||||
8. [使用这个 Python 程序记录你的活动](https://linux.cn/article-11846-1.html)
|
||||
9. [一个通过 IRC 管理所有聊天的开源聊天工具](https://linux.cn/article-11856-1.html)
|
||||
10. [使用这个 Twitter 客户端在 Linux 终端中发推特](https://linux.cn/article-11858-1.html)
|
||||
11. [在 Linux 终端中阅读 Reddit](https://linux.cn/article-11869-1.html)
|
||||
12. [使用此开源工具在一起收取你的 RSS 订阅源和播客](https://linux.cn/article-11876-1.html)
|
||||
13. [使用这个开源工具获取本地天气预报](https://linux.cn/article-11879-1.html)
|
||||
14. [使用此开源窗口环境一次运行多个控制台](https://linux.cn/article-11892-1.html)
|
||||
15. [使用 tmux 创建你的梦想主控台](https://linux.cn/article-11900-1.html)
|
||||
16. [使用 Vim 发送邮件和检查日历](https://linux.cn/article-11908-1.html)
|
||||
17. [使用 Vim 管理任务列表和访问 Reddit 和 Twitter](https://linux.cn/article-11912-1.html)
|
||||
18. [使用 Emacs 发送电子邮件和检查日历](https://linux.cn/article-11932-1.html)
|
||||
19. [使用 Emacs 进行社交并跟踪你的待办事项列表](https://linux.cn/article-11956-1.html)
|
||||
20. [我的愿望清单上的 4 种开源生产力工具](https://linux.cn/article-11961-1.html)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -53,7 +76,7 @@ via: https://opensource.com/article/20/1/open-source-productivity-tools
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,79 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Seawater, humidity inspire new ways to generate power)
|
||||
[#]: via: (https://www.networkworld.com/article/3529893/seawater-humidity-inspire-new-ways-to-generate-power.html)
|
||||
[#]: author: (Patrick Nelson https://www.networkworld.com/author/Patrick-Nelson/)
|
||||
|
||||
Seawater, humidity inspire new ways to generate power
|
||||
======
|
||||
Researchers around the globe are working on new ways to generate huge amounts of power that will be needed for the shift to a data-driven society.
|
||||
Getty Imags
|
||||
|
||||
The possiblity of a future power-availability crunch – spurred in part by a global increase in data usage – is driving researchers to get creative with a slew of new and modified ways to generate and store energy.
|
||||
|
||||
Ongoing projects include the use of seawater for batteries; grabbing ambient humidity; massive water storage systems for hydropower; and solar panels that work at night. Here are some details:
|
||||
|
||||
### Batteries based on seawater
|
||||
|
||||
Seawater will provide "super-batteries," says the University of Southern Denmark. Researchers there have been studying how to use sodium, which is abundant in seawater, as an alternative to lithium in batteries.
|
||||
|
||||
[[Get regularly scheduled insights by signing up for Network World newsletters.]][1]
|
||||
|
||||
"Sodium is a very readily available resource," the school says in a [press release][2], and it can be easily extracted from seawater. Lithium, on the other hand, is a limited resource that's mined only in a few places in the world, says research leader Dorthe Bomholdt Ravnsbæk of the department of physics, chemistry and pharmacy at the university. Batteries based on seawater would also alleviate the need for cobalt, which is used in lithium cells. The team in Denmark (working with Massachusetts Institute of Technology) believes it has come up with a new electrode material, based on manganese, that will make the seawater battery ultimately viable.
|
||||
|
||||
### Using ambient moisture to generate power
|
||||
|
||||
Humidity captured with bio-electronics could end up being a viable power source for sensors, say some scientists.
|
||||
|
||||
"Harvesting energy from the environment offers the promise of clean power for self-sustained systems," notes University of Massachusetts researchers [in an article published in Nature][3]. However, known technologies often have restrictive environmental requirements – solar panels that must be mounted outside, for example – that limit their energy-producing potential.
|
||||
|
||||
Moisture harvesting with thin-film, protein nanowires doesn't have restrictive environmental requirements. Sustained voltages of about half a volt can be obtained from moisture present in normal, ambient air. "Connecting several devices linearly scales up the voltage and current to power electronics," the Amherst group claims. "Our results demonstrate the feasibility of a continuous energy-harvesting strategy that is less restricted by location or environmental conditions than other sustainable approaches."
|
||||
|
||||
[][4]
|
||||
|
||||
### Seasonally pumped hydropower storage
|
||||
|
||||
On a larger scale, inland water storage could solve renewable power issues, say scientists at the International Institute for Applied Systems Analysis.
|
||||
|
||||
One big problem collecting power from the environment, as opposed to using fossil fuels, is where to store the on-the-fly electricity being generated. The Austrian organization believes that hydropower systems should be used to contain renewable energy. It's cheap, for starters. In addition, seasonal pumped hydropower storage (SPHS) is better than wind or solar, the group claims, because it not only generates the power in real time as it’s needed, but also isn't affected by variations— a windy day isn't required, for example.
|
||||
|
||||
SPHS operates by pumping water into dammed, river-adjacent reservoirs when water flow is high but power demand is low. Water is then allowed to flow out of the reservoir, through turbines—similar to hydroelectric—when energy demand increases. Electricity is thus created. The group, in a [press release][5] related to a study just released, says the technique is highly economical, even including required land purchases, excavation and tunneling.
|
||||
|
||||
### Nighttime, anti-solar cells
|
||||
|
||||
Contrary to popular belief, photovoltaic solar panels don't actually need full sun to function. Cloud cover allows some to work just fine, just not as well. Nighttime photovoltaic, however, is something more radical:
|
||||
|
||||
The earth should be used as a heat source, and the night sky a heat sink, say Jeremy Munday and Tristan Deppe of the department of electrical and computer engineering at University of California, Davis. They shared their idea for nighttime photovoltaic cells in an [abstract of a paper][6] published by American Chemical Society's ACS Photonics.
|
||||
|
||||
What they are suggesting is using thermoradiative photovoltaics, where deep space radiative cooling ([which I’ve written about before][7]) is combined with photovoltaics. Current is created as infrared light – or heat, in other words – is radiated into extremely cold, deep space.
|
||||
|
||||
"Similar to the way a normal solar cell works, but in reverse," Munday says of their anti-solar panel concept, quoted in a [UC Davis news article][8].
|
||||
|
||||
Join the Network World communities on [Facebook][9] and [LinkedIn][10] to comment on topics that are top of mind.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3529893/seawater-humidity-inspire-new-ways-to-generate-power.html
|
||||
|
||||
作者:[Patrick Nelson][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/Patrick-Nelson/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.networkworld.com/newsletters/signup.html
|
||||
[2]: https://www.sdu.dk/en/nyheder/Forskningsnyheder/skal_fremtidens_superbatterier_laves_af_havvand
|
||||
[3]: https://www.nature.com/articles/s41586-020-2010-9
|
||||
[4]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
|
||||
[5]: https://iiasa.ac.at/web/home/about/news/200219-seasonal-pumped-storage.html
|
||||
[6]: https://pubs.acs.org/toc/apchd5/7/1
|
||||
[7]: https://www.networkworld.com/article/3222850/space-radiated-cooling-cuts-power-use-21.html
|
||||
[8]: https://www.ucdavis.edu/news/anti-solar-cells-photovoltaic-cell-works-night
|
||||
[9]: https://www.facebook.com/NetworkWorld/
|
||||
[10]: https://www.linkedin.com/company/network-world
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,240 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (heguangzhi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to find what you’re looking for on Linux with find)
|
||||
[#]: via: (https://www.networkworld.com/article/3527420/how-to-find-what-you-re-looking-for-on-linux-with-find.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
How to find what you’re looking for on Linux with find
|
||||
======
|
||||
The find command has a huge array of options to help you locate exactly the files you're looking for on a Linux system. This post explores a series of extremely useful commands.
|
||||
CSA Images / Getty Images
|
||||
|
||||
There are a number of commands for finding files on Linux systems, but there are also a huge number of options that you can deploy when looking for them.
|
||||
|
||||
For example, you can find files not just by their names, but by their owners and/or groups, their age, their size, the assigned permissions, the last time they were accessed, the associated inodes and even whether the files belong to an account or group that no longer exists on the system and so on.
|
||||
|
||||
[[Get regularly scheduled insights by signing up for Network World newsletters.]][1]
|
||||
|
||||
You can also specify where a search should start, how deeply into the file system the search should reach and how much the search result will tell you about the files it finds.
|
||||
|
||||
And all these criteria can be handled by the **find** command.
|
||||
|
||||
Examples of finding files by these criteria are provided below. In some commands, errors (such as trying to list files that you don’t have read access to), error output will be sent to **/dev/null** so that we don’t have to look at it. In others, we’ll simply run as root to avoid this problem.
|
||||
|
||||
Keep in mind that additional options exist. This post covers a lot of ground, but not all of the ways that the **find** command can help locate files for you.
|
||||
|
||||
### Picking a starting point
|
||||
|
||||
With **find**, you can either select a point or start where you are. To select a starting spot, enter it following the word “find”. For example, “find /usr” or “find ./bin” would search starting the **/usr** directory or the **bin** directory in the current location while “find ~” would start in your home directory even if you’re currently located in some other location in the file system.
|
||||
|
||||
[][2]
|
||||
|
||||
### Picking what you want to see
|
||||
|
||||
One of the most commonly used search strategies is to search for files by name. This requires using the **-name** option.
|
||||
|
||||
By default, **find** will show you the full path to the files it finds. This is the same thing you would see if you add **-print** to your command. If you want to see the details associated with a file – its length, permissions, etc., you would need to add **-ls** to the end of your **find** command.
|
||||
|
||||
```
|
||||
$ find ~/bin -name tryme
|
||||
/home/shs/bin/tryme
|
||||
$ find ~/bin -name tryme -print
|
||||
/home/shs/bin/tryme
|
||||
$ find ~/bin -name tryme -ls
|
||||
917528 4 -rwx------ 1 shs shs 139 Apr 8 2019 /home/shs/bin/tryme
|
||||
```
|
||||
|
||||
You can also find files using substrings. For example, if you replace "tryme" in the example above with "try*", you'll find all the files with names that begin with "try".
|
||||
|
||||
Finding files by name is probably the most typical use of the **find** command, but there are so many other ways to look for files and good reasons to want to. The sections below show how to use many of the other criteria available.
|
||||
|
||||
In addition, when searching for files by size, group, inode etc., you probably will want some confirmation that the files found match what you were looking for. Using the **-ls** option to display the details is often very helpful.
|
||||
|
||||
### Finding files by size
|
||||
|
||||
Finding files by size requires use of the **-size** option and a little finesse with the specifications. If you specify **-size 189b**, for you example, you’re going to find files that are 189 blocks long, not 189 bytes. For bytes, you would need to use **-size 189c** (characters). And, if you specify **-size 200w**, you’re going to find files that are 200 words – words as in "two-byte increments", not words as in "those things we all say to each other". You can also look for file by providing sizes in kilobytes (k), megabytes (M) and gigabytes (G).
|
||||
|
||||
Most of the time, Linux users will be searching for files that are larger than some selected size. For example, to find files that are larger than a gigabyte, you might use a command like this where the +1G means "larger than a gigabyte":
|
||||
|
||||
```
|
||||
$ find -size +1G -ls 2>/dev/null
|
||||
787715 1053976 -rw-rw-r-- 1 shs shs 1079263432 Dec 21 2018 ./backup.zip
|
||||
801834 1052556 -rw-rw-r-- 1 shs shs 1077809525 Dec 21 2018 ./2019/hold.zip
|
||||
```
|
||||
|
||||
### Finding files by inode #
|
||||
|
||||
You can find files by the inode that is used to maintain the file’s metadata (i.e., everything but the file content and file name).
|
||||
|
||||
```
|
||||
$ find -inum 919674 -ls 2>/dev/null
|
||||
919674 4 -rw-rw-r-- 1 shs shs 512 Dec 27 15:25 ./bin/my.log
|
||||
```
|
||||
|
||||
### Finding files with a specific file owner or group
|
||||
|
||||
Finding files by owner or group is also very straightforward. Here we use sudo to overcome permission issues.
|
||||
|
||||
```
|
||||
$ sudo find /home -user nemo -name "*.png"-ls
|
||||
1705219 4 drwxr-xr-x 2 nemo nemo 4096 Jan 28 08:50 /home/nemo/Pictures/me.png
|
||||
```
|
||||
|
||||
In this command, we look for a file that is owned by a multi-user group called “admins”.
|
||||
|
||||
```
|
||||
# find /tmp -group admins -ls
|
||||
262199 4 -rwxr-x--- 1 dory admins 27 Feb 16 18:57 /tmp/testscript
|
||||
```
|
||||
|
||||
### Finding files with no owners or groups
|
||||
|
||||
You can look for files that don't belong to any users currently set up on the system by using the **-nouser** option as shown in the command below.
|
||||
|
||||
```
|
||||
# find /tmp -nouser -ls
|
||||
262204 4 -rwx------ 1 1016 1016 17 Feb 17 16:42 /tmp/hello
|
||||
```
|
||||
|
||||
Notice that the listing shows the old user's UID and GID – a clear indication that this user is not defined on the system. This kind of command will find files that were likely created in other-than-home directories by users whose accounts have since been removed from the system or in home directories that were not removed after the user account was removed. Similarly, the **-nogroup** option would find such files – especially when these users were the only members of the associated groups.
|
||||
|
||||
### Finding files by last update time
|
||||
|
||||
In this command, we look for files that have been updated in the last 24 hours in a particular user's home directory. The **sudo** is being used to allow searching another user’s home directory.
|
||||
|
||||
```
|
||||
$ sudo find /home/nemo -mtime -1
|
||||
/home/nemo
|
||||
/home/nemo/snap/cheat
|
||||
/home/nemo/tryme
|
||||
```
|
||||
|
||||
### Finding files by when permissions were last changed
|
||||
|
||||
The **-ctime** option can help you find files that have had their status (e.g., permissions) changed within some referenced time frame. Here’s an example of looking for files that had permission changes within the last day:
|
||||
|
||||
```
|
||||
$ find . -ctime -1 -ls
|
||||
787987 4 -rwxr-xr-x 1 shs shs 189 Feb 11 07:31 ./tryme
|
||||
```
|
||||
|
||||
Keep in mind that the date and time displayed reflect the last updates to the file contents. You will have to use a command like **stat** to see all three times associated with a file (file creation, modification and status changes) .
|
||||
|
||||
### Finding files based on last access times
|
||||
|
||||
In this command, we look for local pdf files that were accessed within the last two days using the **-atime** option.
|
||||
|
||||
```
|
||||
$ find -name "*.pdf" -atime -2
|
||||
./Wingding_Invites.pdf
|
||||
```
|
||||
|
||||
### Finding files based on their age relative to another file
|
||||
|
||||
You can use the -newer option to find files that are newer than some other file.
|
||||
|
||||
```
|
||||
$ find . -newer dig1 -ls
|
||||
786434 68 drwxr-xr-x 67 shs shs 69632 Feb 16 19:05 .
|
||||
1064442 4 drwxr-xr-x 5 shs shs 4096 Feb 16 11:06 ./snap/cheat
|
||||
791846 4 -rw-rw-r-- 1 shs shs 649 Feb 13 14:26 ./dig
|
||||
```
|
||||
|
||||
There is no corresponding **-older** option, but you can get a similar result with **! -newer** (i.e., not newer), which means almost the same thing.
|
||||
|
||||
### Finding files by type
|
||||
|
||||
Finding a file by file type, you get a lot of choices – regular files, directories, block and character files, etc. Here’s a list of the file type options:
|
||||
|
||||
```
|
||||
b block (buffered) special
|
||||
c character (unbuffered) special
|
||||
d directory
|
||||
p named pipe (FIFO)
|
||||
f regular file
|
||||
l symbolic link
|
||||
s socket
|
||||
```
|
||||
|
||||
Here’s an example looking for symbolic links:
|
||||
|
||||
```
|
||||
$ find . -type l -ls
|
||||
805717 0 lrwxrwxrwx 1 shs shs 11 Apr 10 2019 ./volcano -> volcano.pdf
|
||||
918552 0 lrwxrwxrwx 1 shs shs 1 Jun 16 2018 ./letter -> pers/letter2mom
|
||||
```
|
||||
|
||||
### Limiting how deeply find should look
|
||||
|
||||
The **-mindepth** and **-maxdepth** options control how deeply into the file system (from the current location or starting point) your searches will look.
|
||||
|
||||
```
|
||||
$ find -maxdepth 3 -name "*loop"
|
||||
./bin/save/oldloop
|
||||
./bin/long-loop
|
||||
./private/loop
|
||||
```
|
||||
|
||||
### Finding files only if empty
|
||||
|
||||
In this command, we look for empty files, but no further than directories and their subdirectories.
|
||||
|
||||
```
|
||||
$ find . -maxdepth 2 -empty -type f -ls
|
||||
917517 0 -rw-rw-r-- 1 shs shs 0 Sep 23 11:00 ./complaints/newfile
|
||||
792050 0 -rw-rw-r-- 1 shs shs 0 Oct 4 19:02 ./junk
|
||||
```
|
||||
|
||||
### Finding files by permissions
|
||||
|
||||
You can find files that have specific permissions set using the **-perm** option. In the example below, we are looking only for regular files (**-type f**) to avoid seeing symbolic links that are given these permissions by default even if the file they refer to is restricted.
|
||||
|
||||
```
|
||||
$ find -perm 777 -type f -ls
|
||||
find: ‘./.dbus’: Permission denied
|
||||
798748 4 -rwxrwxrwx 1 shs shs 15 Mar 28 2019 ./runme
|
||||
```
|
||||
|
||||
### Using find to help you get rid of files
|
||||
|
||||
You can use the find command to both locate and then remove files if you use a command like this one:
|
||||
|
||||
```
|
||||
$ find . -name runme -exec rm {} \;
|
||||
```
|
||||
|
||||
The {} represents the name of each of the files located by the search criteria.
|
||||
|
||||
One very useful option is to replace **-exec** with **-ok**. When you do this, **find** will ask for a confirmation before it removes any file.
|
||||
|
||||
```
|
||||
$ find . -name runme -ok rm -rf {} \;
|
||||
< rm ... ./bin/runme > ?
|
||||
```
|
||||
|
||||
Removing a file isn't the only thing that **-ok** and **-rm** can do for you. For example, you could copy, rename or move files.
|
||||
|
||||
There are really a lot of options for using the find command effectively and undoubtedly some that haven’t been covered in this post. I hope you’ve found some that are new and especially promising.
|
||||
|
||||
Join the Network World communities on [Facebook][3] and [LinkedIn][4] to comment on topics that are top of mind.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3527420/how-to-find-what-you-re-looking-for-on-linux-with-find.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[heguangzhi](https://github.com/heguangzhi)
|
||||
校对:[校对者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://www.networkworld.com/newsletters/signup.html
|
||||
[2]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
|
||||
[3]: https://www.facebook.com/NetworkWorld/
|
||||
[4]: https://www.linkedin.com/company/network-world
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,105 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to Add New Brushes in GIMP [Quick Tip])
|
||||
[#]: via: (https://itsfoss.com/add-brushes-gimp/)
|
||||
[#]: author: (Community https://itsfoss.com/author/itsfoss/)
|
||||
|
||||
How to Add New Brushes in GIMP [Quick Tip]
|
||||
======
|
||||
|
||||
[GIMP][1], is the most popular free and open-source image editor and perhaps the best [Adobe Photoshop alternative][2] on Linux.
|
||||
|
||||
When you [install GIMP on Ubuntu][3] or any other operating system, you’ll find a few brushes already installed for basic image editing. If you need something more specific, you can always add new brushes in GIMP.
|
||||
|
||||
How? Let me show you that in this quick tutorial.
|
||||
|
||||
### How to add brushes in GIMP
|
||||
|
||||
![][4]
|
||||
|
||||
There are three steps involved in installing new brushes in GIMP:
|
||||
|
||||
* Get new brush
|
||||
* Put it in the designated folder
|
||||
* Refresh the brushes in GIMP
|
||||
|
||||
|
||||
|
||||
#### Step 1: Download new GIMP brushes
|
||||
|
||||
The first step is to get new brushes for GIMP. Where do you get it from? From the internet, of course.
|
||||
|
||||
You can search on Google or [alternative private search engines like Duck Duck Go][5] for ‘GIMP brushes’ and download the ones you like from a reputed website.
|
||||
|
||||
GIMP brushes are usually available in .gbr and .gih file formats. The .gbr file is for regular brushes while .gih is used for animated brushes.
|
||||
|
||||
Did you know?
|
||||
|
||||
For the versions 2.4 and above, GIMP makes installing and using Photoshop brushes (.abr file) quite straightforward. All you need to do is place the Photoshop brush files in the proper folder.
|
||||
Do keep in mind that the latest Photoshop brushes might not work with GIMP flawlessly.
|
||||
|
||||
#### Step 2: Copy the new brushes into its location
|
||||
|
||||
After you get your brush file, the next step is to copy and paste it to the right folder in GIMP configuration directory.
|
||||
|
||||
On **Windows**, you’ll have to go to a folder like “**C:\Documents and Settings\myusername.gimp-2.10\brushes**“.
|
||||
|
||||
I’ll show detailed steps for **Linux** because It’s FOSS is a Linux-focused website.
|
||||
|
||||
After selecting the brush files press **Ctrl+h** in your **Home** folder to [see hidden files in Linux][6].
|
||||
|
||||
![Press Ctrl+H to see hidden files in the home directory][7]
|
||||
|
||||
You should go to **.config/GIMP/2.10/brushes** folder (if you are using GIMP version 2.10). If you are using some other version, you should see an equivalent folder under .config/GIMP.
|
||||
|
||||
![Adding New Brushes in GIMP][8]
|
||||
|
||||
Paste the brush files in this folder. Optionally, you can hide the hidden files by pressing **Ctrl+h** again.
|
||||
|
||||
#### Step 3: Refresh the brushes (to avoid restarting GIMP)
|
||||
|
||||
GIMP will automatically load brushes when it’s launched. If you are already running it and don’t want to close it, you can refresh the brushes.
|
||||
|
||||
In GIMP go to **Windows**->**Dockable Dialogues**->**Brushes** in the main menu.
|
||||
|
||||
![Refresh GIMP Brushes by going go to Windows->Dockable Dialogues-> Brushes][9]
|
||||
|
||||
Locate the **refresh** icon in the **Brushes** dialog on the right side bar.
|
||||
|
||||
![Refresh GIMP Brushes][10]
|
||||
|
||||
If your brushes are not present, you can always try to restart GIMP.
|
||||
|
||||
Bonus Tip!
|
||||
|
||||
Adding new brushes in [GIMP also allows you easily watermark images][11]. Just use your logo as a brush and add it to the images in a single click.
|
||||
|
||||
I hope you enjoyed this quick GIMP tip. Stay tuned for more.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/add-brushes-gimp/
|
||||
|
||||
作者:[Community][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/itsfoss/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.gimp.org/
|
||||
[2]: https://itsfoss.com/open-source-photoshop-alternatives/
|
||||
[3]: https://itsfoss.com/gimp-2-10-release/
|
||||
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/Install-New-Brushes-in-GIMP.jpg?ssl=1
|
||||
[5]: https://itsfoss.com/privacy-search-engines/
|
||||
[6]: https://itsfoss.com/hide-folders-and-show-hidden-files-in-ubuntu-beginner-trick/
|
||||
[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/adding-brushes-GIMP-1.jpg?ssl=1
|
||||
[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/adding-brushes-GIMP.png?ssl=1
|
||||
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/Refresh-GIMP-Brushes.jpg?ssl=1
|
||||
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/Refresh-GIMP-Brushes-2.jpg?ssl=1
|
||||
[11]: https://itsfoss.com/add-watermark-gimp-linux/
|
@ -1,607 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Getting started with the Rust package manager, Cargo)
|
||||
[#]: via: (https://opensource.com/article/20/3/rust-cargo)
|
||||
[#]: author: (Gaurav Kamathe https://opensource.com/users/gkamathe)
|
||||
|
||||
Getting started with the Rust package manager, Cargo
|
||||
======
|
||||
Get to know Rust's package manager and build tool.
|
||||
![Shipping containers stacked in a yard][1]
|
||||
|
||||
[Rust][2] is a modern programming language that provides performance, reliability, and productivity. It has consistently been voted as the [most-loved language][3] on StackOverflow surveys for a few years now.
|
||||
|
||||
In addition to being a great programming language, Rust also features a build system and package manager called Cargo. Cargo handles a lot of tasks, like building code, downloading libraries or dependencies, and so on. The two are bundled together, so you get Cargo when you install Rust.
|
||||
|
||||
### Installing Rust and Cargo
|
||||
|
||||
Before getting started, you need to install Rust and Cargo. The Rust project provides a downloadable script to handle the installation. To get the script, open a browser to [https://sh.rustup.rs][4] and save the file. Read the script to make sure you're happy with what it intends to do, and then run it:
|
||||
|
||||
|
||||
```
|
||||
`$ sh ./rustup.rs`
|
||||
```
|
||||
|
||||
You can also refer to the [Install Rust][5] webpage for more information.
|
||||
|
||||
After installing Rust and Cargo, you must source the env file:
|
||||
|
||||
|
||||
```
|
||||
`$ source $HOME/.cargo/env`
|
||||
```
|
||||
|
||||
Better yet, add the required directory to your PATH variable:
|
||||
|
||||
|
||||
```
|
||||
`$ source $HOME/.cargo/env`
|
||||
```
|
||||
|
||||
If you prefer to use your package manager (such as DNF or Apt on Linux), look for Rust and Cargo packages in your distribution's repositories and install accordingly. For example:
|
||||
|
||||
|
||||
```
|
||||
`$ dnf install rust cargo`
|
||||
```
|
||||
|
||||
Once they're installed and set up, verify which versions of Rust and Cargo you have:
|
||||
|
||||
|
||||
```
|
||||
$ rustc --version
|
||||
rustc 1.41.0 (5e1a79984 2020-01-27)
|
||||
$ cargo --version
|
||||
cargo 1.41.0 (626f0f40e 2019-12-03)
|
||||
```
|
||||
|
||||
### Building and running Rust by hand
|
||||
|
||||
Start with a simple program that prints "Hello, world!" on the screen. Open your favorite text editor and type the following program:
|
||||
|
||||
|
||||
```
|
||||
$ cat hello.rs
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
Save the file with an **.rs** extension to identify it as a Rust source code file.
|
||||
|
||||
Compile your program using the Rust compiler, **rustc**:
|
||||
|
||||
|
||||
```
|
||||
`$ rustc hello.rs`
|
||||
```
|
||||
|
||||
After compilation, you will have a binary that has the same name as the source program:
|
||||
|
||||
|
||||
```
|
||||
$ ls -l
|
||||
total 2592
|
||||
-rwxr-xr-x. 1 user group 2647944 Feb 13 14:14 hello
|
||||
-rw-r--r--. 1 user group 45 Feb 13 14:14 hello.rs
|
||||
$
|
||||
```
|
||||
|
||||
Execute your program to verify that it runs as expected:
|
||||
|
||||
|
||||
```
|
||||
$ ./hello
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
These steps are sufficient for smaller programs or whenever you want to test out something quickly. However, when working on bigger programs involving multiple people, Cargo is the best way forward.
|
||||
|
||||
### Creating a new package using Cargo
|
||||
|
||||
Cargo is a build system and package manager for Rust. It helps developers download and manage dependencies and assists in creating Rust packages. Packages in Rust are often called "crates" in the Rust community, but in this article, the two words are interchangeable. Refer to the Cargo [FAQ][6] provided by the Rust community for clarification.
|
||||
|
||||
If you need any help with Cargo's command-line utility, use the **\--help** or **-h** command-line argument:
|
||||
|
||||
|
||||
```
|
||||
`$ cargo –help`
|
||||
```
|
||||
|
||||
To create a new package, use the **new** keyword, followed by the package name. For this example, use **hello_opensource** as your new package name. After running the command, you will see a message confirming that Cargo has created a binary package with the given name:
|
||||
|
||||
|
||||
```
|
||||
$ cargo new hello_opensource
|
||||
Created binary (application) `hello_opensource` package
|
||||
```
|
||||
|
||||
Running a **tree** command to see the directory structure reports that some files and directories were created. First, it creates a directory with the name of the package, and within that directory is an **src** directory for your source code files:
|
||||
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
└── hello_opensource
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
2 directories, 2 files
|
||||
```
|
||||
|
||||
Cargo not only creates a package, but it also creates a simple **Hello, world!** program. Open the **main.rs** file and have a look:
|
||||
|
||||
|
||||
```
|
||||
$ cat hello_opensource/src/main.rs
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
The next file to work with is **Cargo.toml**, which is a configuration file for your package. It contains information about the package, such as its name, version, author information, and Rust edition information.
|
||||
|
||||
A program often depends on external libraries or dependencies to run, which enables you to write applications that perform tasks that you don't know how to code or you don't want to spend time coding. All your dependencies will be listed in this file. At this point, you do not have any dependencies for your new program. Open the **Cargo.toml** file and view its contents:
|
||||
|
||||
|
||||
```
|
||||
$ cat hello_opensource/Cargo.toml
|
||||
[package]
|
||||
name = "hello_opensource"
|
||||
version = "0.1.0"
|
||||
authors = ["user <[user@mail.com][7]>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at <https://doc.rust-lang.org/cargo/reference/manifest.html>
|
||||
|
||||
[dependencies]
|
||||
```
|
||||
|
||||
### Building the program using Cargo
|
||||
|
||||
So far, so good. Now that you have a package in place, build a binary (also called an executable). Before doing that, move into the package directory:
|
||||
|
||||
|
||||
```
|
||||
`$ cd hello_opensource/`
|
||||
```
|
||||
|
||||
You can use Cargo's **build** command to build the package. Notice the messages that say it is **Compiling** your program:
|
||||
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.38s
|
||||
```
|
||||
|
||||
Check what happens to your project directory after you run the **build** command:
|
||||
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
├── src
|
||||
│ └── main.rs
|
||||
└── target
|
||||
└── debug
|
||||
├── build
|
||||
├── deps
|
||||
│ ├── hello_opensource-147b8a0f466515dd
|
||||
│ └── hello_opensource-147b8a0f466515dd.d
|
||||
├── examples
|
||||
├── hello_opensource
|
||||
├── hello_opensource.d
|
||||
└── incremental
|
||||
└── hello_opensource-3pouh4i8ttpvz
|
||||
├── s-fkmhjmt8tj-x962ep-1hivstog8wvf
|
||||
│ ├── 1r37g6m45p8rx66m.o
|
||||
│ ├── 2469ykny0eqo592v.o
|
||||
│ ├── 2g5i2x8ie8zed30i.o
|
||||
│ ├── 2yrvd7azhgjog6zy.o
|
||||
│ ├── 3g9rrdr4hyk76jtd.o
|
||||
│ ├── dep-graph.bin
|
||||
│ ├── query-cache.bin
|
||||
│ ├── work-products.bin
|
||||
│ └── wqif2s56aj0qtct.o
|
||||
└── s-fkmhjmt8tj-x962ep.lock
|
||||
|
||||
9 directories, 17 files
|
||||
```
|
||||
|
||||
Wow! The compilations process produced a lot of intermediate files. Your binary, though, is saved in the **./target/debug** directory with the same name as your package.
|
||||
|
||||
### Running your application using Cargo
|
||||
|
||||
Now that your binary is built, run it using Cargo's **run** command. As expected, it prints **Hello, world!** on the screen.
|
||||
|
||||
|
||||
```
|
||||
$ cargo run
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
|
||||
Running `target/debug/hello_opensource`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Alternatively, you can run the binary directly, which is located at:
|
||||
|
||||
|
||||
```
|
||||
$ ls -l ./target/debug/hello_opensource
|
||||
-rwxr-xr-x. 2 root root 2655552 Feb 13 14:19 ./target/debug/hello_opensource
|
||||
```
|
||||
|
||||
As expected, it produces the same results:
|
||||
|
||||
|
||||
```
|
||||
$ ./target/debug/hello_opensource
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Say you need to rebuild your package and get rid of all the binaries and the intermediate files created by the earlier compilation process. Cargo provides a handy **clean** option to remove all intermediate files except the source code and other required files:
|
||||
|
||||
|
||||
```
|
||||
$ cargo clean
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
1 directory, 3 files
|
||||
```
|
||||
|
||||
Make some changes to the program and run it again to see how it works. For example, this minor change adds **Opensource** to the **Hello, world!** string:
|
||||
|
||||
|
||||
```
|
||||
$ cat src/main.rs
|
||||
fn main() {
|
||||
println!("Hello, Opensource world!");
|
||||
}
|
||||
```
|
||||
|
||||
Now, build the program and run it again. This time you see **Hello, Opensource world!** displayed on the screen:
|
||||
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.39s
|
||||
|
||||
$ cargo run
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
|
||||
Running `target/debug/hello_opensource`
|
||||
Hello, Opensource world!
|
||||
```
|
||||
|
||||
### Adding dependencies using Cargo
|
||||
|
||||
Cargo allows you to add dependencies that your program needs to run. Adding a dependency is extremely easy with Cargo. Every Rust package includes a **Cargo.toml** file, which contains a list (empty by default) of dependencies. Open the file in your favorite text editor, find the **[dependencies]** section, and add the library you want to include in your package. For example, to add the **rand** library as your dependency:
|
||||
|
||||
|
||||
```
|
||||
$ cat Cargo.toml
|
||||
[package]
|
||||
name = "hello_opensource"
|
||||
version = "0.1.0"
|
||||
authors = ["test user <[test@mail.com][8]>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at <https://doc.rust-lang.org/cargo/reference/manifest.html>
|
||||
|
||||
[dependencies]
|
||||
rand = "0.3.14"
|
||||
```
|
||||
|
||||
Try building your package to see what happens.
|
||||
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Updating crates.io index
|
||||
Compiling libc v0.2.66
|
||||
Compiling rand v0.4.6
|
||||
Compiling rand v0.3.23
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 4.48s
|
||||
```
|
||||
|
||||
Cargo is now reaching out to [Crates.io][9], which is Rust's central repository for crates (or packages) and downloading and compiling **rand**. But wait—what about the **libc** package? You did not ask for **libc** to be installed. Well, the **rand** package is dependent on the **libc** package; hence, Cargo downloads and compiles **libc** as well.
|
||||
|
||||
New versions of libraries keep coming, and Cargo provides an easy way to update all of their dependencies using the **update** command:
|
||||
|
||||
|
||||
```
|
||||
`cargo update`
|
||||
```
|
||||
|
||||
You can also choose to update specific libraries using the **-p** flag followed by the package name:
|
||||
|
||||
|
||||
```
|
||||
`cargo update -p rand`
|
||||
```
|
||||
|
||||
### Compiling and running with a single command
|
||||
|
||||
So far, you have used **build** followed by **run** whenever you make changes to your program. There is an easier way: you can simply use the **run** command, which internally compiles and runs the program. To see how it works, first clean up your package directory:
|
||||
|
||||
|
||||
```
|
||||
$ cargo clean
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
1 directory, 3 files
|
||||
```
|
||||
|
||||
Now execute **run**. The output states that it compiled and then ran the program, and this means you don't need to explicitly run **build** each time:
|
||||
|
||||
|
||||
```
|
||||
$ cargo run
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
|
||||
Running `target/debug/hello_opensource`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
### Checking your code in development
|
||||
|
||||
You often go through multiple iterations when developing a program. You need to ensure that your program has no coding errors and compiles fine. You don't need the overhead of generating the binary on each compilation. Cargo has you covered with a **check** option that compiles your code but skips the final step of generating an executable.
|
||||
|
||||
Start by running **cargo clean** within your package directory:
|
||||
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
1 directory, 3 files
|
||||
```
|
||||
|
||||
Now run the **check** command and see what changes were made to the directory:
|
||||
|
||||
|
||||
```
|
||||
$ cargo check
|
||||
Checking hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.18s
|
||||
```
|
||||
|
||||
The output shows that, even though intermediate files were created as part of the compilation process, the final binary or executable was not created. This saves some time, which matters a lot if the package is huge with thousands of lines of code:
|
||||
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
├── src
|
||||
│ └── main.rs
|
||||
└── target
|
||||
└── debug
|
||||
├── build
|
||||
├── deps
|
||||
│ ├── hello_opensource-842d9a06b2b6a19b.d
|
||||
│ └── libhello_opensource-842d9a06b2b6a19b.rmeta
|
||||
├── examples
|
||||
└── incremental
|
||||
└── hello_opensource-1m3f8arxhgo1u
|
||||
├── s-fkmhw18fjk-542o8d-18nukzzq7hpxe
|
||||
│ ├── dep-graph.bin
|
||||
│ ├── query-cache.bin
|
||||
│ └── work-products.bin
|
||||
└── s-fkmhw18fjk-542o8d.lock
|
||||
|
||||
9 directories, 9 files
|
||||
```
|
||||
|
||||
To see if you are really saving time, time the **build** and **check** commands and compare them.
|
||||
|
||||
First, the **build** command:
|
||||
|
||||
|
||||
```
|
||||
$ time cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.40s
|
||||
|
||||
real 0m0.416s
|
||||
user 0m0.251s
|
||||
sys 0m0.199s
|
||||
```
|
||||
|
||||
Clean the directory before running the **check** command:
|
||||
|
||||
|
||||
```
|
||||
`$ cargo clean`
|
||||
```
|
||||
|
||||
The **check** command:
|
||||
|
||||
|
||||
```
|
||||
$ time cargo check
|
||||
Checking hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
|
||||
|
||||
real 0m0.166s
|
||||
user 0m0.086s
|
||||
sys 0m0.081s
|
||||
```
|
||||
|
||||
Clearly, the **check** command is much faster.
|
||||
|
||||
### Building external Rust packages
|
||||
|
||||
Everything you've done so far will apply to any Rust crate you get from the internet. You simply need to download or clone the repository, move to the package folder, and run the **build** command, and you are good to go:
|
||||
|
||||
|
||||
```
|
||||
git clone <github-like-url>
|
||||
cd <package-folder>
|
||||
cargo build
|
||||
```
|
||||
|
||||
### Building optimized Rust programs using Cargo
|
||||
|
||||
You've run **build** multiple times so far, but did you notice its output? No worries, build it again and watch closely:
|
||||
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
|
||||
```
|
||||
|
||||
See the **[unoptimized + debuginfo]** text after each compilation? This means that the binary generated by Cargo includes a lot of debugging information and is not optimized for execution. Developers often go through multiple iterations of development and need this debugging information for analysis. Also, performance is not the immediate goal while developing software. Therefore, this is OK for now.
|
||||
|
||||
However, once the software is ready for release, it doesn't need to have the debugging information anymore. But it does need to be optimized for best performance. In the final stages of development, you can use the **\--release** flag with **build**. Watch closely; you should see the **[optimized]** text after compilation:
|
||||
|
||||
|
||||
```
|
||||
$ cargo build --release
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished release [optimized] target(s) in 0.29s
|
||||
```
|
||||
|
||||
If you want to, you can go through the exercise to find out your time savings when running optimized vs. unoptimized software.
|
||||
|
||||
### Creating a library vs. a binary using Cargo
|
||||
|
||||
Any software program can be roughly categorized as either a standalone binary or a library. A standalone binary can be run as it is, even though it might make use of external libraries. A library, however, is utilized by another standalone binary. All the programs you've built so far in this tutorial are standalone binaries since that is Cargo's default. To create a **library**, add the **\--lib** option:
|
||||
|
||||
|
||||
```
|
||||
$ cargo new --lib libhello
|
||||
Created library `libhello` package
|
||||
```
|
||||
|
||||
This time, Cargo does not create a **main.rs** file; instead, it creates a **lib.rs** file. The code for your library should go here:
|
||||
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
└── libhello
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── lib.rs
|
||||
|
||||
2 directories, 2 files
|
||||
```
|
||||
|
||||
Knowing Cargo, don't be surprised that it put some code in your new library file. Find out what it added by moving to the package directory and viewing the file. By default, Cargo puts a test function within library files.
|
||||
|
||||
### Running tests using Cargo
|
||||
|
||||
Rust provides first-class support for unit and integration testing, and Cargo allows you to execute any of these tests:
|
||||
|
||||
|
||||
```
|
||||
$ cd libhello/
|
||||
|
||||
$ cat src/lib.rs
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Cargo has a handy **test** option to run any test that is present in your code. Try running the tests that Cargo put in the library code by default:
|
||||
|
||||
|
||||
```
|
||||
$ cargo test
|
||||
Compiling libhello v0.1.0 (/opensource/libhello)
|
||||
Finished test [unoptimized + debuginfo] target(s) in 0.55s
|
||||
Running target/debug/deps/libhello-d52e35bb47939653
|
||||
|
||||
running 1 test
|
||||
test tests::it_works ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
|
||||
Doc-tests libhello
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
```
|
||||
|
||||
### Looking under Cargo's hood
|
||||
|
||||
You may be interested in knowing what Cargo does under the hood when you run a command. After all, Cargo is, in many ways, a wrapper. To find out what it's doing, you can use the **-v** option with any Cargo command to output verbose information to the screen.
|
||||
|
||||
Here are a couple of examples that run **build** and **clean** using the **-v** option.
|
||||
|
||||
In the **build** command, you can see that the underlying **rustc** (Rust compiler) fired with the given command-line options:
|
||||
|
||||
|
||||
```
|
||||
$ cargo build -v
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Running `rustc --edition=2018 --crate-name hello_opensource src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=147b8a0f466515dd -C extra-filename=-147b8a0f466515dd --out-dir /opensource/hello_opensource/target/debug/deps -C incremental=/opensource/hello_opensource/target/debug/incremental -L dependency=/opensource/hello_opensource/target/debug/deps`
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
|
||||
```
|
||||
|
||||
Whereas the **clean** command shows that it is simply removing the directory that contains the intermediate files and the binary:
|
||||
|
||||
|
||||
```
|
||||
$ cargo clean -v
|
||||
Removing /opensource/hello_opensource/target
|
||||
```
|
||||
|
||||
### Don't let your skills get rusty
|
||||
|
||||
To expand your skills, try writing and running a slightly more complex program using Rust and Cargo. Something simple will do: for instance, try listing all files in the current directory (it can be done in nine lines of code), or try echoing input back out at yourself. Small practice applications help you get comfortable with the syntax and the process of writing and testing code.
|
||||
|
||||
This article offers plenty of information for budding Rust programmers to get started with Cargo. However, as you begin working on larger and more complicated programs, you'll need a more advanced understanding of Cargo. When you're ready for more, download and read the open source [Cargo Book][10] written by the Rust team, and see what you can create!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/rust-cargo
|
||||
|
||||
作者:[Gaurav Kamathe][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/gkamathe
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bus-containers2.png?itok=idd8duC_ (Shipping containers stacked in a yard)
|
||||
[2]: https://www.rust-lang.org/
|
||||
[3]: https://insights.stackoverflow.com/survey/2019#technology-_-most-loved-dreaded-and-wanted-languages
|
||||
[4]: https://sh.rustup.rs/
|
||||
[5]: https://www.rust-lang.org/tools/install
|
||||
[6]: https://doc.rust-lang.org/cargo/faq.html
|
||||
[7]: mailto:user@mail.com
|
||||
[8]: mailto:test@mail.com
|
||||
[9]: http://crates.io
|
||||
[10]: https://doc.rust-lang.org/cargo
|
@ -1,139 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Drauger OS Linux Aims to Bring Console Gaming Experience on the Desktop)
|
||||
[#]: via: (https://itsfoss.com/drauger-os/)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
Drauger OS Linux Aims to Bring Console Gaming Experience on the Desktop
|
||||
======
|
||||
|
||||
For years (or decades) people complained that one of the reasons to not [use Linux][1] is lack of mainstream games. [Gaming on Linux][2] has improved drastically in last few years specially with the [introduction of Steam Proton][3] project that enables you to [play a lot of Windows-only games on Linux][4].
|
||||
|
||||
This also has encourages several [Linux distributions centered around gaming][5]. Take [Lakka][6] for example. You can [turn your old computer into a retro gaming console thanks to Lakka Linux][7].
|
||||
|
||||
Another such gaming focused Linux distribution is [Draguer OS][8] and we are going to take a look at it today.
|
||||
|
||||
### What is Drauger OS?
|
||||
|
||||
Accord to [the project’s website][9], “Drauger OS is a Linux desktop gaming operating system. It aims to provide a platform for gamers to use where they can get great performance without sacrificing their security. Furthermore, it aims to make it easy for anyone to game, whether they use a keyboard and mouse, or some sort of controller.”
|
||||
|
||||
They stress that Drauger OS is not for everyday use. As such, many of the productivity tools that most other distros come with are not in Drauger OS.
|
||||
|
||||
![Drauger OS 7.4.1][10]
|
||||
|
||||
Drauger OS is [based][9] on the Ubuntu. The current version (7.4.1 Jiangshi) uses “[Liquorix][11] low latency Linux kernel, a pre-compiled ZEN kernel designed with a balance between latency and throughput in mind”. However, that will be changing in the next release. They only have one desktop environment choice, a modified version of [Xfce][12].
|
||||
|
||||
Drauger OS has several applications and tools installed out of the box to improve the gaming experience. These include:
|
||||
|
||||
* [PlayOnLinux][13]
|
||||
* WINE
|
||||
* [Lutris][14]
|
||||
* Steam
|
||||
* [DXVK][15]
|
||||
|
||||
|
||||
|
||||
It also has an interesting set of tools that are not gaming related. [Drauger Installer][16] is a .deb installer and alternative to Gdebi. [Multiple Repository App Installer][17] (mrai) is “an AUR-helper-like script for Debian-based Linux Operating Systems”. Mrai is designed to work with apt, snaps, flatpaks, and can install apps from GitHub.
|
||||
|
||||
Interestingly, Drauger OS’ name is an error. Lead dev [Thomas Castleman][18] (aka batcastle) has intended to name his distro Draugr, but had mistyped the name. In [episode 23][19] of the Drauger OS podcast, Castleman said the name will stay misspelled because it would be a lot of work to correct it. According to [Wikipedia][20], a draugr is “an undead creature from Norse mythology”.
|
||||
|
||||
Yes, you read that correctly. Drauger OS is one of only a few distros that have its own [podcast][21]. When asked about it, Castleman told me that “I wanted to ensure that we had the maximum transparency possible with our community, no matter their circumstances.” Most of the time, the podcast is an audio version of the Drauger OS blog, but sometimes they use it to make an announcement when they don’t have time to write a blog post.
|
||||
|
||||
### The Future for Drauger OS
|
||||
|
||||
![Drauger OS][22]
|
||||
|
||||
The developers behind Druager OS are working on their next major release: 7.5.1. This release will be based on Ubuntu 19.10. There will be three major changes. First, the Liquorix kernel will be [replaced][23] with “a kernel we are building in-house.” This kernel will be based on the Linux Kernel GitHub repository, “so it’s about as vanilla as it gets”.
|
||||
|
||||
The second major change in the new release will a new layout for their desktop. Based on user feedback, they have decided to change it to something that looks more GNOME-like.
|
||||
|
||||
Thirdly, they are dropping SystemBack as their backup tool and installer. They have instead written a new [installer][24] from scratch.
|
||||
|
||||
The Dev team is also working on an [ARM version][25] of Drauger OS. They hope to release it sometime in 2022.
|
||||
|
||||
### System requirements for Draguer OS
|
||||
|
||||
The Drauger OS [system requirements][25] are pretty modest. Keep in mind that Drauger OS will only run on 64-bit systems.
|
||||
|
||||
#### Minimum system requirements
|
||||
|
||||
* CPU: Dual-Core, 1.8GHz, 64-bit processor
|
||||
* RAM: 1 GB
|
||||
* Storage: 16 GB
|
||||
* Graphics Processor: Integrated
|
||||
* Screen Resolution: 1024×768 at 60Hz
|
||||
* External Ports: 1 Port for Display (HDMI / DisplayPort / VGA / DVI), 2 USB Ports for Installation USB Drive and Keyboard (Mouse optional, but recommended)
|
||||
|
||||
|
||||
|
||||
#### Recommended system requirements
|
||||
|
||||
* CPU: Quad-Core, 2.2Ghz, 64-bit processor
|
||||
* RAM: 4 GB
|
||||
* Storage: 128 GB
|
||||
* Graphics Processor: NVIDIA GTX 1050, AMD RX 460, or equivalent card
|
||||
* Screen Resolution: 1080p at 60Hz
|
||||
* External Ports: 1 Port for Display (HDMI / DisplayPort / VGA / DVI), 3 USB Ports for Installation USB Drive, Keyboard, and Mouse, 1 Audio Out Port
|
||||
|
||||
|
||||
|
||||
### How you can help out Drauger OS
|
||||
|
||||
There are several ways that you can help out the Drauger OS if you are interestedin doing so. They are always looking for [financial support][26] to keep development going.
|
||||
|
||||
If you want yo contribute code, they are looking for people with experience in BASH, C++, and Python. All of their code is up on [GitHub][27]. You can also [contact][28] them on social media.
|
||||
|
||||
### Final Thoughts
|
||||
|
||||
Drauger OS is quite a project. I’ve seen a couple of other [gaming-oriented distributions][29], but Drauger OS is single-minded in its focus on gaming. Since I am more of a casual gamer, this distro doesn’t appeal to me personally. But, I can see how it could lure gaming enthusiasts to Linux. I wish them good luck in their future releases.
|
||||
|
||||
What are your thoughts on this gaming-only distro? What is your favorite Linux gaming solution? Please 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][30].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/drauger-os/
|
||||
|
||||
作者:[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/why-use-linux/
|
||||
[2]: https://itsfoss.com/linux-gaming-guide/
|
||||
[3]: https://itsfoss.com/steam-play-proton/
|
||||
[4]: https://itsfoss.com/steam-play/
|
||||
[5]: https://itsfoss.com/linux-gaming-distributions/
|
||||
[6]: http://www.lakka.tv/
|
||||
[7]: https://itsfoss.com/lakka-retrogaming-linux/
|
||||
[8]: https://draugeros.org/go/
|
||||
[9]: https://www.draugeros.org/go/about/
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/drauger-os-7.4.1.jpg?ssl=1
|
||||
[11]: https://liquorix.net/
|
||||
[12]: https://www.xfce.org/
|
||||
[13]: https://www.playonlinux.com/en/
|
||||
[14]: https://lutris.net/
|
||||
[15]: https://github.com/doitsujin/dxvk
|
||||
[16]: https://github.com/drauger-os-development/drauger-installer
|
||||
[17]: https://github.com/drauger-os-development/mrai
|
||||
[18]: https://github.com/Batcastle
|
||||
[19]: https://anchor.fm/drauger-os/episodes/Episode-23-eapu47
|
||||
[20]: https://en.wikipedia.org/wiki/Draugr
|
||||
[21]: https://anchor.fm/drauger-os
|
||||
[22]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/drauger-os-7.5.1.png?ssl=1
|
||||
[23]: https://www.draugeros.org/go/2020/01/20/major-changes-in-drauger-os-7-5-1/
|
||||
[24]: https://github.com/drauger-os-development/system-installer
|
||||
[25]: https://www.draugeros.org/go/system-requirements/
|
||||
[26]: https://www.draugeros.org/go/contribute/
|
||||
[27]: https://github.com/drauger-os-development
|
||||
[28]: https://www.draugeros.org/go/contact-us/
|
||||
[29]: https://itsfoss.com/manjaro-gaming-linux/
|
||||
[30]: https://reddit.com/r/linuxusersgroup
|
@ -0,0 +1,122 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Getting started with the Gutenberg editor in Drupal)
|
||||
[#]: via: (https://opensource.com/article/20/3/gutenberg-editor-drupal)
|
||||
[#]: author: (MaciejLukianski https://opensource.com/users/maciejlukianski)
|
||||
|
||||
Getting started with the Gutenberg editor in Drupal
|
||||
======
|
||||
Learn how to use the WYSIWYG editor, made popular in WordPress, with
|
||||
Drupal.
|
||||
![Text editor on a browser, in blue][1]
|
||||
|
||||
Since 2017, WordPress has had a really great WYSIWYG editor in the [Gutenberg][2] plugin. But the Drupal community hasn't yet reached consensus on the best approach to the content management system's (CMS) editorial experience. But a strong new option appeared when, with a lot of community effort, [Gutenberg was integrated with Drupal][3].
|
||||
|
||||
Previously, there were two main approaches to content creation in Drupal 8:
|
||||
|
||||
* In the [**Paragraph-based approach**][4], content is assembled out of entities called paragraphs. Currently, approximately 100,000 websites use the Paragraphs module (according to Drupal).
|
||||
* The [**Layout-Builder approach**][5] uses an editorial tool shipped with Drupal 8.5. It is still undergoing improvements, but it is the next strong contender because it is really well integrated with the Drupal core. Stats on usage are not available since Layout Builder is part of Drupal.
|
||||
|
||||
|
||||
|
||||
At the end of 2018, the Drupal community, lead by Fronkom (a Norwegian digital agency strongly focused on open source solutions), ported the WordPress Gutenberg project as a contributed module into Drupal. Let's take a look at how Gutenberg works in Drupal (including some cool Drupal-specific integrations).
|
||||
|
||||
### Installation
|
||||
|
||||
Installing the [Gutenberg module][6] is as straightforward as installing any Drupal module, and it has good [installation documentation][7].
|
||||
|
||||
### Configuration
|
||||
|
||||
Gutenberg is integrated into Drupal's default content-entity creation workflow. You can use it on any of the content types you choose, provided that the content type has at least one text area field, which is where the Gutenberg editor's output will be saved.
|
||||
|
||||
To enable the Gutenberg project on a content type in Drupal, you have to navigate to its settings: **Structure > Content types** and, from the dropdown next to the content type where you want to use Gutenberg, click **Edit**.
|
||||
|
||||
![Drupal settings][8]
|
||||
|
||||
In the form that appears, scroll down and select the **Gutenberg experience** tab on the left, where you can find the settings described below. Select the **Enable Gutenberg experience** box.
|
||||
|
||||
![Drupal Gutenberg settings][9]
|
||||
|
||||
#### Template
|
||||
|
||||
This is one of the cool features that is not available in WordPress out of the box. It enables you to define a template for a new page in a JSON structure. This will pre-populate all newly created articles with dummy placeholder content, which will help editors structure content correctly. In the screenshot above, I added a heading and a paragraph. Note that any double-quotes have to be escaped.
|
||||
|
||||
#### Template lock
|
||||
|
||||
This setting allows you to define whether users are allowed to delete the placeholder content, add new blocks, or just edit the existing, pre-populated content.
|
||||
|
||||
#### Allowed Gutenberg and Drupal blocks
|
||||
|
||||
This is another super-cool feature on the Drupal side of Gutenberg. Drupal allows users to create various types of blocks to design a page. For example, you could create a block with a list of the five latest blog posts, the most recent comments, or a form to collect users' emails.
|
||||
|
||||
Gutenberg's deep integration with Drupal allows users to select which Drupal blocks are available to users while they are editing (e.g., limit embeds to YouTube) and use blocks as inline content. This is a very handy feature that allows granular control of the user experience.
|
||||
|
||||
There's not much to choose from in a blank Drupal installation, but a live site usually has many blocks that provide various functionalities. In the screenshot below, the **Search form** Drupal block is selected.
|
||||
|
||||
![Drupal Gutenberg blocks][10]
|
||||
|
||||
After you finish the configuration, hit **Save content type**.
|
||||
|
||||
### Publishing content with Drupal Gutenberg
|
||||
|
||||
When Gutenberg is enabled for a content type, it takes over most of the editorial experience.
|
||||
|
||||
![Drupal Gutenberg content screen][11]
|
||||
|
||||
In the main window, you can see the dummy placeholder content I added in the Template configuration above.
|
||||
|
||||
#### Drupal-specific options
|
||||
|
||||
On the right-hand side, there are a few fields and settings that Drupal provides. For example, the **Title** field is a required separate field in Drupal, and therefore it is not on the main Gutenberg screen.
|
||||
|
||||
Underneath the **Title**, there are additional settings that can vary, depending on the modules installed and options set up in Drupal. You can see **Revision log messages**, **Menu settings**, **Comment settings**, and a place to add a **URL alias**.
|
||||
|
||||
Typically, Drupal content types are composed of several text fields, such as tags, categories, checkboxes, image fields for teasers, etc. When you enable Gutenberg for a content type, these additional fields are available in the **More settings** tab.
|
||||
|
||||
You can now add your content—it works the same as it does in WordPress Gutenberg, with the additional option to add Drupal blocks.
|
||||
|
||||
In the screenshot below, you can see what happens when I add some text to replace the placeholder text, a search block from Drupal, a title, tags, and a custom URL alias.
|
||||
|
||||
![Drupal Gutenberg entering text][12]
|
||||
|
||||
After you hit **Save**, your content will be published.
|
||||
|
||||
![Drupal Gutenberg output][13]
|
||||
|
||||
And that is it. It works like a charm!
|
||||
|
||||
### Working together for better software experiences
|
||||
|
||||
Gutenberg in Drupal works well. It is an alternative option that allows editors to control the look and feel of their websites down to the tiniest details. Adoption is growing well, with over 1,000 installations as of this writing and 50 new ones every month. The Drupal integration adds other cool features like fine-grained permissions, placeholder content, and the ability to include Drupal blocks inline, which aren't available in the WordPress plugin.
|
||||
|
||||
It is great to see the communities of two separate projects working together to achieve the common goal of giving people better software.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/gutenberg-editor-drupal
|
||||
|
||||
作者:[MaciejLukianski][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/maciejlukianski
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_blue_text_editor_web.png?itok=lcf-m6N7 (Text editor on a browser, in blue)
|
||||
[2]: https://wordpress.org/plugins/gutenberg/
|
||||
[3]: https://drupalgutenberg.org/
|
||||
[4]: https://www.droptica.com/blog/flexible-and-easy-content-creation-drupal-paragraphs-module/
|
||||
[5]: https://www.droptica.com/blog/layout-builder-building-drupal-8-layouts/
|
||||
[6]: https://www.drupal.org/project/gutenberg
|
||||
[7]: https://www.drupal.org/docs/8/extending-drupal-8/installing-drupal-8-modules
|
||||
[8]: https://opensource.com/sites/default/files/uploads/gutenberg_edit.png (Drupal settings)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/gutenberg_settings.png (Drupal Gutenberg settings)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/gutenberg_blocks.png (Drupal Gutenberg blocks)
|
||||
[11]: https://opensource.com/sites/default/files/uploads/gutenberg_contentwindow.png (Drupal Gutenberg content screen)
|
||||
[12]: https://opensource.com/sites/default/files/uploads/gutenberg_entry.png (Drupal Gutenberg entering text)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/gutenberg-demo.png (Drupal Gutenberg output)
|
@ -0,0 +1,428 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How service virtualization relates to test-driven development)
|
||||
[#]: via: (https://opensource.com/article/20/3/service-virtualization-test-driven-development)
|
||||
[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic)
|
||||
|
||||
How service virtualization relates to test-driven development
|
||||
======
|
||||
Mountebank simulates services you're dependent on so autonomous teams
|
||||
can continue development activities without having to wait on anyone.
|
||||
![Person using a laptop][1]
|
||||
|
||||
The agile approach to software development relies on service virtualization to give each IT team autonomy. This approach removes blockages and allows autonomous teams to continue development activities without having to wait on anyone. That way, integration testing can commence as soon as teams start iterating/sprinting.
|
||||
|
||||
### How automated services work
|
||||
|
||||
Any automated service is available to consumers via a published endpoint. This means services can be automated only if they're made available online.
|
||||
|
||||
Any consumer wishing to leverage available automated services must be capable of sending requests to that service's endpoint via an HTTP protocol. Some of those services will, upon receiving the request via the HTTP protocol, respond by simply sending back some data. Other services may respond to receiving a request via HTTP protocol by actually performing some work. For example, a service may create a resource (for example, create an order), update a resource (update an order), or delete a resource (cancel an order).
|
||||
|
||||
All those activities get triggered via the HTTP protocol. In the simplest of cases, the action instigated by the service consumer is GET (e.g., HTTP GET). That request may arrive with some query values; those values will get used by the service to narrow down the search (such as "search for order number 12345 and return the data").
|
||||
|
||||
In more elaborate cases, a request may arrive with the instruction to POST some values; a service will accept that request and expect some values to be associated with it. Those values are usually called the payload. When the service accepts an HTTP POST request containing the payload, it will attempt to process it. It may or may not succeed in processing it, but either way, it will respond to the service consumer with a status code and an optional status message. That way, service consumers will be notified of the success/failure of their request so that they can decide what the next step should be.
|
||||
|
||||
### What is service virtualization?
|
||||
|
||||
Now that we understand how automated services work, it should be easier to understand how to virtualize them. In a nutshell, it is possible to simulate any service that is published on a hosting site. Instead of sending HTTP requests directly to the service provider's endpoint, you can interject a fake, pretend service that simulates the behavior of the real service.
|
||||
|
||||
From the service consumer's standpoint, it makes absolutely no difference whether it is interacting with a real or a fake service. The interaction remains identical.
|
||||
|
||||
### Virtualize one service
|
||||
|
||||
OK, enough talking, I'll roll up my sleeves and show how to do it in practical terms. Suppose your team is starting a new project and receives requirements in the form of a fully fleshed user story:
|
||||
|
||||
#### Authenticate user
|
||||
|
||||
_As a new app_
|
||||
_I want to authenticate the user_
|
||||
_Because we want to ensure proper security for the app_
|
||||
|
||||
#### Acceptance criteria
|
||||
|
||||
**Scenario #1:** _New app successfully authenticates the user_
|
||||
Given that the user has navigated to the login page
|
||||
And the user has submitted credentials
|
||||
When new app receives login request
|
||||
Then new app successfully authenticates the user
|
||||
And new app displays response message "User successfully logged in."
|
||||
|
||||
**Scenario #2:** _New app cannot authenticate the user on the first attempt_
|
||||
Given that the user has navigated to the login page
|
||||
And the user has submitted credentials
|
||||
When new app receives login request
|
||||
Then new app fails to successfully authenticate the user
|
||||
And new app displays response message "Incorrect login. You have 2 more attempts left."
|
||||
|
||||
**Scenario #3:** _New app cannot authenticate the user on the second attempt_
|
||||
Given that the user has navigated to the login page
|
||||
And the user has submitted credentials
|
||||
When new app receives login request
|
||||
Then new app fails to successfully authenticate the user
|
||||
And new app displays response message "Incorrect login. You have 1 more attempt left."
|
||||
|
||||
**Scenario #4:** _New app cannot authenticate the user on the third attempt_
|
||||
Given that the user has navigated to the login page
|
||||
And the user has submitted credentials
|
||||
When new app receives login request
|
||||
Then new app fails to successfully authenticate the user
|
||||
And new app displays response message "Incorrect login. You have no more attempts left."
|
||||
|
||||
The first thing to do when starting the work on this user story is to create the so-called "walking skeleton" (for this exercise, I will be using the standard **.Net Core** platform plus **xUnit.net** I discussed in my previous articles ([starting with this one][2] with [another example here][3]). Please refer to them for technical details on how to install, configure, and run the required tools.
|
||||
|
||||
Create the walking skeleton infrastructure by opening the command line and typing:
|
||||
|
||||
|
||||
```
|
||||
`mkdir AuthenticateUser`
|
||||
```
|
||||
|
||||
Then move inside the **AuthenticateUser** folder:
|
||||
|
||||
|
||||
```
|
||||
`cd AuthenticateUser`
|
||||
```
|
||||
|
||||
And create a separate folder for tests:
|
||||
|
||||
|
||||
```
|
||||
`mkdir tests`
|
||||
```
|
||||
|
||||
Move into the **tests** folder (**cd tests**) and initiate the **xUnit** framework:
|
||||
|
||||
|
||||
```
|
||||
`dotnet new xunit`
|
||||
```
|
||||
|
||||
Now move one folder up (back to **AuthenticateUser**) and create the app folder:
|
||||
|
||||
|
||||
```
|
||||
mkdir app
|
||||
cd app
|
||||
```
|
||||
|
||||
Create the scaffold necessary for C# code:
|
||||
|
||||
|
||||
```
|
||||
`dotnet new classlib`
|
||||
```
|
||||
|
||||
The walking skeleton is now ready! Open the editor of your choice and start coding.
|
||||
|
||||
### Write a failing test first
|
||||
|
||||
In the spirit of TDD, start by writing the failing test (refer to the [previous article][4] to learn why is it important to see your test fail before attempting to make it pass):
|
||||
|
||||
|
||||
```
|
||||
using System;
|
||||
using Xunit;
|
||||
using app;
|
||||
|
||||
namespace tests {
|
||||
public class UnitTest1 {
|
||||
Authenticate auth = [new][5] Authenticate();
|
||||
|
||||
[Fact]
|
||||
public void SuccessLogin(){
|
||||
var given = "credentials";
|
||||
var expected = "Successful login.";
|
||||
var actual = auth.Login(given);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This test states that if someone supplies some credentials (i.e., a secret username and password) to the **Login** method of the **Authenticate** component when it processes the request, it is expected to return the message "Successful login."
|
||||
|
||||
Of course, this is functionality that does not exist yet—the instantiated **Authenticate** module in the **SuccessLogin()** module hasn't been written yet. So you might as well go ahead and take the first stab at writing the desired functionality. Create a new file (**Authenticate.cs**) in the **app** folder and add the following code:
|
||||
|
||||
|
||||
```
|
||||
using System;
|
||||
|
||||
namespace app {
|
||||
public class Authenticate {
|
||||
public string Login(string credentials) {
|
||||
return "Not implemented";
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now, navigate to the **tests** folder and run:
|
||||
|
||||
|
||||
```
|
||||
`dotnet test`
|
||||
```
|
||||
|
||||
![Output of dotnet.test][6]
|
||||
|
||||
The test fails because it was expecting a "Successful login" output but instead got the "Not implemented" output.
|
||||
|
||||
### Increasing complexity for day two operations
|
||||
|
||||
Now that you have created the "happy path" expectation and made it fail, it is time to work on implementing the functionality that will make the failing test pass. The following day, you attend the standup and report that you have started on the "Authenticate user" story. You let the team know that you have created the first failing test for the "happy path," and today, the plan is to implement the code to make the failing test pass.
|
||||
|
||||
You explain your intention to first create a **User** table containing the **username**, **password**, and other pertinent attributes. But the scrum master interrupts and explains that the **User** module is being handled by another team. It would be bad practice to duplicate the maintenance of users, as the information will quickly get out of sync. So instead of building the **User** module (which would include the authentication logic), you are to leverage the authentication services that the **User** team is working on.
|
||||
|
||||
That's great news because it saves you the trouble of having to write a lot of code to implement the **User** processing. Emboldened, you enthusiastically announce that you will quickly cobble up a function that will take user credentials and send them to the service that the **User** team has built.
|
||||
|
||||
Alas, your intentions get squashed again as you learn that the **User** team hasn't started building the **User authentication** service yet. They're still in the process of assigning user stories to the backlog. Disheartened, you resign to the fact that it will be at least a few days (if not weeks?) before you can start working on the **User authentication** story.
|
||||
|
||||
The scrum master then says that there is no reason to wait for the **User authentication** service to be built and deployed to testing. You could start developing the authentication functionality right away. But how can you do that?
|
||||
|
||||
The scrum master offers a simple suggestion: leverage service virtualization. Since all specifications for the **User** module have been solidified and signed off, you have a solid, non-volatile contract to build your solution against. The contract published by the **User** services team states that in order to authenticate a user, specific expectations must be fulfilled:
|
||||
|
||||
1. A client wishing to authenticate a user should send an **HTTP POST** request to the endpoint <http://some-domain.com/api/v1/users/login>.
|
||||
2. The **HTTP POST** sent to the above endpoint must have a **JSON** payload that contains the user credentials (i.e., username and password).
|
||||
3. Upon receiving the request, the service will attempt to log the user in. If the username and password match the information on record, the service will return an **HTTP** response containing status code 200 with the body of the response containing the message "User successfully logged in."
|
||||
|
||||
|
||||
|
||||
So, now that you know the contract details, you can start building the solution. Here's the code that connects to the endpoint, sends the **HTTP POST** request, and receives the **HTTP** response:
|
||||
|
||||
|
||||
```
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace app {
|
||||
public class Authenticate {
|
||||
HttpClient client = [new][5] HttpClient();
|
||||
string endPoint = "<http://some-domain.com/api/v1/users/login>";
|
||||
|
||||
public string Login(string credentials) {
|
||||
Task<string> response = CheckLogin(credentials);
|
||||
return response.Result;
|
||||
}
|
||||
|
||||
private async Task<string> CheckLogin(string credentials) {
|
||||
var values = [new][5] Dictionary<string, string>{{"credentials", credentials}};
|
||||
var content = [new][5] FormUrlEncodedContent(values);
|
||||
var response = await client.PostAsync(endPoint, content);
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This code won't work because <http://some-domain.com> does not exist (yet). Are you stuck now, waiting for the other team to eventually build and deploy that service?
|
||||
|
||||
Not really. Service virtualization to rescue! Let's pretend that the service is already there and continue the development.
|
||||
|
||||
### How to virtualize a service
|
||||
|
||||
One way to virtualize the **User authentication** service would be to write a new app (the new API) and run it locally. This API will mirror the contract specified by the real **User authentication** API and will only return hard-coded stubbed data (it will be a fake service).
|
||||
|
||||
Sounds like a good plan. Again, the team pushes back during the standup, questioning the need for writing, building, testing, and deploying a brand new app just to accomplish this fake functionality. It kind of wouldn't be worth the trouble because, by the time you deliver that new fake app, the other team would probably be ready with the real service.
|
||||
|
||||
So you've reached an impasse. It looks like you are forced to wait on your dependency to materialize. You've failed to control your dependencies; you now have no recourse but to work in a sequential fashion.
|
||||
|
||||
Not so fast! There is a great new tool called [mountebank][7] that is ideal for virtualizing any service. Using this tool, you can quickly stand up a local server that listens on a port you specify and takes orders. To make it simulate a service, you only have to tell it which port to listen to and which protocol to handle. The choice of protocols is:
|
||||
|
||||
* HTTP
|
||||
* HTTPS
|
||||
* SMTP
|
||||
* TCP
|
||||
|
||||
|
||||
|
||||
In this case, you need the HTTP protocol. First, install mountebank—if you have **npm** on your computer, you can simply type on the command line:
|
||||
|
||||
|
||||
```
|
||||
`npm install -g mountebank`
|
||||
```
|
||||
|
||||
After it's installed, run mountebank by typing:
|
||||
|
||||
|
||||
```
|
||||
`mb`
|
||||
```
|
||||
|
||||
At startup, mountebank will show:
|
||||
|
||||
![mountebank startup][8]
|
||||
|
||||
Now you're ready to virtualize an HTTP service. In this case, the **User authentication** service expects to receive an HTTP POST request; here is how the implemented code sends an HTTP POST request:
|
||||
|
||||
|
||||
```
|
||||
`var response = await client.PostAsync(endPoint, content);`
|
||||
```
|
||||
|
||||
You now have to establish that **endPoint**. Ideally, all virtualized services should be propped in the **localhost** server to ensure quick execution of integration tests.
|
||||
|
||||
To do that, you need to configure the **imposter**. In its bare-bones form, the **imposter** is a simple JSON collection of key-value pairs containing the definition of a port and a protocol:
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"port": 3001,
|
||||
"protocol": "http"
|
||||
}
|
||||
```
|
||||
|
||||
This imposter is configured to handle the HTTP protocol and to listen to incoming requests on port 3001.
|
||||
|
||||
Just listening to incoming HTTP requests on port 3001 is not going to do much. Once the request arrives at that port, mountebank needs to be told what to do with that request. In other words, you are virtualizing not only the availability of a service on a specific port but also the way that virtualized service is going to respond to the request.
|
||||
|
||||
To accomplish that level of service virtualization, you need to tell mountebank how to configure stubs. Each stub consists of two components:
|
||||
|
||||
1. A collection of predicates
|
||||
2. A collection of expected responses
|
||||
|
||||
|
||||
|
||||
A predicate (sometimes called a matcher) narrows down the scope of the incoming request. For example, using the HTTP protocol, you can expect more than one type of method (e.g., GET, POST, PUT, DELETE, PATCH, etc.). In most service-virtualization scenarios, we are interested in simulating the behavior that is specific to a particular HTTP method. This scenario is about responding to the HTTP POST request, so you need to configure your stub to match on HTTP POST requests only:
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"port": 3001,
|
||||
"protocol": "http",
|
||||
"stubs": [
|
||||
{
|
||||
"predicates": [
|
||||
{
|
||||
"equals": {
|
||||
"method": "post"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This imposter defines one predicate that matches (using the keyword **equals**) on the HTTP POST request only.
|
||||
|
||||
Now take a closer look at the **endPoint** value, as defined in the implemented code:
|
||||
|
||||
|
||||
```
|
||||
`string endPoint = "http://localhost:3001/api/v1/users/login";`
|
||||
```
|
||||
|
||||
In addition to listening to port 3001 (as defined in <http://localhost:3001>), the **endPoint** is more specific, in that it expects the incoming HTTP POST request to go to the /api/v1/users/login path. How do you tell mountebank to only match exactly on the /api/v1/users/login path? By adding the path key-value pair to the stub's predicate:
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"port": 3001,
|
||||
"protocol": "http",
|
||||
"stubs": [
|
||||
{
|
||||
"predicates": [
|
||||
{
|
||||
"equals": {
|
||||
"method": "post",
|
||||
"path": "/api/v1/users/login"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This imposter now knows that HTTP requests arriving at port 3001 must be a POST method and must point at the /api/v1/users/login path. The only thing left to simulate is the expected HTTP response.
|
||||
|
||||
Add the response to the JSON imposter:
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"port": 3001,
|
||||
"protocol": "http",
|
||||
"stubs": [
|
||||
{
|
||||
"predicates": [
|
||||
{
|
||||
"equals": {
|
||||
"method": "post",
|
||||
"path": "/api/v1/users/login"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": [
|
||||
{
|
||||
"is": {
|
||||
"statusCode": 200,
|
||||
"body": "Successful login."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
With mountebank imposters, you define responses as a collection of JSON key-value pairs. In most cases, it is sufficient to simply state that a response is a **statusCode** and a **body**. This case is simulating the "happy path" response that has the status code **OK (200)** and the body containing a simple message **Successful login** (as specified in the acceptance criteria).
|
||||
|
||||
### How to run virtualized services?
|
||||
|
||||
OK, now that you have virtualized the **User authentication** service (at least its "happy path"), how do you run it?
|
||||
|
||||
Remember that you have already started mountebank, and it reported that it is running in memory as the <http://localhost> domain. Mountebank is listening on port 2525 and taking orders.
|
||||
|
||||
Great, now you have to tell mountebank that you have the imposter ready. How do you do that? Send an HTTP POST request to <http://localhost:2525/imposters>. The requests body must contain the JSON you created above. There are a few techniques available to send that request. If you're versed in [curl][9], using it to send HTTP POST requests would be the simplest, quickest way to stand up the imposter. But many people prefer a more user-friendly way to send the HTTP POST to mountebank.
|
||||
|
||||
The easy way to do that is to use [Postman][10]. If you download and install Postman, you can point it at <http://localhost:2525/imposters>, select the POST method from the pulldown menu, and copy and paste the imposter JSON into the raw body.
|
||||
|
||||
When you click Send, the imposter will be created, and you should get Status 201 (Created).
|
||||
|
||||
![Postman output][11]
|
||||
|
||||
Your virtualized service is now running! You can verify it by navigating to the **tests** folder and running the **dotnet test** command:
|
||||
|
||||
![dotnet test output][12]
|
||||
|
||||
### Conclusion
|
||||
|
||||
This demo shows how easy it is to remove blockages and control dependencies by simulating services you're dependent on. Mountebank is a fantastic tool that easily and cheaply simulates all kinds of very elaborate, sophisticated services.
|
||||
|
||||
In this installment, I just had time to illustrate how to virtualize a simple "happy path" service. If you go back to the actual user story, you will notice that its acceptance criteria contain several "less happy" paths (cases when someone is repeatedly trying to log in using invalid credentials). It's a bit trickier to properly virtualize and test those use cases, so I've left that exercise for the next installment in this series.
|
||||
|
||||
How will you use service virtualization to solve your testing needs? I would love to hear about it in the comments.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/service-virtualization-test-driven-development
|
||||
|
||||
作者:[Alex Bunardzic][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/alex-bunardzic
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD (Person using a laptop)
|
||||
[2]: https://opensource.com/article/19/8/mutation-testing-evolution-tdd
|
||||
[3]: https://opensource.com/article/19/9/mutation-testing-example-tdd
|
||||
[4]: https://opensource.com/article/20/2/automate-unit-tests
|
||||
[5]: http://www.google.com/search?q=new+msdn.microsoft.com
|
||||
[6]: https://opensource.com/sites/default/files/uploads/dotnet-test.png (Output of dotnet.test)
|
||||
[7]: http://www.mbtest.org/
|
||||
[8]: https://opensource.com/sites/default/files/uploads/mountebank-startup.png (mountebank startup)
|
||||
[9]: https://curl.haxx.se/
|
||||
[10]: https://www.postman.com/
|
||||
[11]: https://opensource.com/sites/default/files/uploads/status-201.png (Postman output)
|
||||
[12]: https://opensource.com/sites/default/files/uploads/dotnet-test2.png (dotnet test output)
|
@ -0,0 +1,219 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qianmingtian)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Install and Use Wireshark on Ubuntu Linux)
|
||||
[#]: via: (https://itsfoss.com/install-wireshark-ubuntu/)
|
||||
[#]: author: (Community https://itsfoss.com/author/itsfoss/)
|
||||
|
||||
Install and Use Wireshark on Ubuntu Linux
|
||||
======
|
||||
|
||||
_**Brief: You’ll learn to install the latest Wireshark on Ubuntu and other Ubuntu-based distribution in this tutorial. You’ll also learn how to run Wireshark without sudo and how to set it up for packet sniffing.**_
|
||||
|
||||
[Wireshark][1] is a free and open-source network protocol analyzer widely used around the globe.
|
||||
|
||||
With Wireshark, you can capture incoming and outgoing packets of a network in real-time and use it for network troubleshooting, packet analysis, software and communication protocol development, and many more.
|
||||
|
||||
It is available on all major desktop operating systems like Windows, Linux, macOS, BSD and more.
|
||||
|
||||
In this tutorial, I will guide you to install Wireshark on Ubuntu and other Ubuntu-based distributions. I’ll also show a little about setting up and configuring Wireshark to capture packets.
|
||||
|
||||
### Installing Wireshark on Ubuntu based Linux distributions
|
||||
|
||||
![][2]
|
||||
|
||||
Wireshark is available on all major Linux distributions. You should check out the [official installation instructions][3]. because in this tutorial, I’ll focus on installing the latest Wireshark version on Ubuntu-based distributions only.
|
||||
|
||||
Wireshark is available in the Universe repository of Ubuntu. You can [enable universe repository][4] and then install it like this:
|
||||
|
||||
```
|
||||
sudo add-apt-repository universe
|
||||
sudo apt install wireshark
|
||||
```
|
||||
|
||||
One slight problem in this approach is that you might not always get the latest version of Wireshark.
|
||||
|
||||
For example, in Ubuntu 18.04, if you [use the apt command][5] to check the available version of Wireshark, it is 2.6.
|
||||
|
||||
```
|
||||
[email protected]:~$ apt show wireshark
|
||||
Package: wireshark
|
||||
Version: 2.6.10-1~ubuntu18.04.0
|
||||
Priority: optional
|
||||
Section: universe/net
|
||||
Origin: Ubuntu
|
||||
Maintainer: Balint Reczey <[email protected]>
|
||||
```
|
||||
|
||||
However, [Wireshark 3.2 stable version][6] has been released months ago. New release brings new features, of course.
|
||||
|
||||
So, what do you do in such case? Thankfully, Wiresshark developers provide an official PPA that you can use to install the latest stable version of Wireshark on Ubuntu and other Ubuntu-based distributions.
|
||||
|
||||
I hope you are acquainted with PPA. If not, please [read our excellent guide on PPA to understand it completely][7].
|
||||
|
||||
Open a terminal and use the following commands one by one:
|
||||
|
||||
```
|
||||
sudo add-apt-repository ppa:wireshark-dev/stable
|
||||
sudo apt update
|
||||
sudo apt install wireshark
|
||||
```
|
||||
|
||||
Even if you have an older version of Wireshark installed, it will be updated to the newer version.
|
||||
|
||||
While installing, you will be asked whether to allow non-superusers to capture packets. Select Yes to allow and No to restrict non-superusers to capture packets & finish the installation.
|
||||
|
||||
### Running Wireshark without sudo
|
||||
|
||||
If you have selected **No** in the previous installation, then run the following command as root:
|
||||
|
||||
```
|
||||
sudo dpkg-reconfigure wireshark-common
|
||||
```
|
||||
|
||||
And select **Yes** by pressing the tab key and then using enter key:
|
||||
|
||||
![][8]
|
||||
|
||||
Since you have allowed the non-superuser to capture packets, you have to add the user to wireshark group. Use the [usermod command][9] to add yourself to the wireshark group.
|
||||
|
||||
```
|
||||
sudo usermod -aG wireshark $(whoami)
|
||||
```
|
||||
|
||||
Finally, [restart your Ubuntu system][10] to make the necessary changes to your system.
|
||||
|
||||
Trivia
|
||||
|
||||
First released in 1998, Wireshark was initially known as Ethereal. Developers had to change its name to Wireshark in 2006 due to trademark issues.
|
||||
|
||||
### Starting Wireshark
|
||||
|
||||
Launching Wireshark application can be done from the application launcher or the CLI.
|
||||
|
||||
To start from CLI, just type **wireshark** on your console:
|
||||
|
||||
```
|
||||
wireshark
|
||||
```
|
||||
|
||||
From **GUI**, search for Wireshark application on the search bar and hit enter.
|
||||
|
||||
![][11]
|
||||
|
||||
Now let’s play with Wireshark.
|
||||
|
||||
### Capturing packets using Wireshark
|
||||
|
||||
When you start Wireshark, you will see a list of interfaces that you can use to capture packets to and from.
|
||||
|
||||
There are many types of interfaces available which you can monitor using Wireshark such as, Wired, External devices, etc. According to your preference, you can choose to show specific types of interfaces in the welcome screen from the marked area in the given image below.
|
||||
|
||||
![Select interface][12]
|
||||
|
||||
For instance, I listed only the **Wired** network interfaces.
|
||||
|
||||
![][13]
|
||||
|
||||
Next, to start capturing packets, you have to select the interface (which in my case is ens33) and click on the **Start capturing packets** icon as marked in the image below.
|
||||
|
||||
![Start capturing packets with Wireshark][14]
|
||||
|
||||
You can also capture packets to and from multiple interfaces at the same time. Just press and hold the **CTRL** button while clicking on the interfaces that you want to capture to and from and then hit the **Start capturing packets** icon as marked in the image below.
|
||||
|
||||
![][15]
|
||||
|
||||
Next, I tried using **ping google.com** command in the terminal and as you can see, many packets were captured.
|
||||
|
||||
![Captured packets][16]
|
||||
|
||||
Now you can select on any packet to check that particular packet. After clicking on a particular packet you can see the information about different layers of TCP/IP Protocol associated with it.
|
||||
|
||||
![Packet info][17]
|
||||
|
||||
You can also see the RAW data of that particular packet at the bottom as shown in the image below.
|
||||
|
||||
![Check RAW data in the captured packets][18]
|
||||
|
||||
This is why end-to-end encryption is important
|
||||
|
||||
Imagine you are logging into a website that doesn’t use HTTPS. Anyone on the same network as you can sniff the packets and see the user name and password in the RAW data.
|
||||
This is why most chat applications use end to end encryption and most websites these days use https (instead of http).
|
||||
|
||||
#### Stopping packet capture in Wireshark
|
||||
|
||||
You can click on the red icon as marked in the given image to stop capturing Wireshark packets.
|
||||
|
||||
![Stop packet capture in Wireshark][19]
|
||||
|
||||
#### Save captured packets to a file
|
||||
|
||||
You can click on the marked icon in the image below to save captured packets to a file for future use.
|
||||
|
||||
![Save captured packets by Wireshark][20]
|
||||
|
||||
**Note**: _Output can be exported to XML, PostScript®, CSV, or plain text._
|
||||
|
||||
Next, select a destination folder, and type the file name and click on **Save**.
|
||||
Then select the file and click on **Open**.
|
||||
|
||||
![][21]
|
||||
|
||||
Now you can open and analyze the saved packets anytime. To open the file, press **\ + o**
|
||||
or go to **File > Open** from Wireshark.
|
||||
|
||||
The captured packets should be loaded from the file.
|
||||
|
||||
![][22]
|
||||
|
||||
### Conclusion
|
||||
|
||||
Wireshark supports many different communication protocols. There are many options and features that provide you the power to capture and analyze the network packets in a unique way. You can learn more about Wireshark from their [official documentation][23].
|
||||
|
||||
I hope this detailed helped you to install Wireshark on Ubuntu. Please let me know your questions and suggestions.
|
||||
|
||||
![][24]
|
||||
|
||||
### Kushal Rai
|
||||
|
||||
A computer science student & Linux and open source lover. He likes sharing knowledge for he believes technology shapes the perception of modern world. Kushal also loves music and photography.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/install-wireshark-ubuntu/
|
||||
|
||||
作者:[Community][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/itsfoss/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.wireshark.org/
|
||||
[2]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/wireshark_ubuntu.png?ssl=1
|
||||
[3]: https://www.wireshark.org/docs/wsug_html_chunked/ChBuildInstallUnixInstallBins.html
|
||||
[4]: https://itsfoss.com/ubuntu-repositories/
|
||||
[5]: https://itsfoss.com/apt-command-guide/
|
||||
[6]: https://www.wireshark.org/news/20191218.html
|
||||
[7]: https://itsfoss.com/ppa-guide/
|
||||
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/yes.png?ssl=1
|
||||
[9]: https://linuxhandbook.com/usermod-command/
|
||||
[10]: https://itsfoss.com/schedule-shutdown-ubuntu/
|
||||
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/wire.png?ssl=1
|
||||
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/interfaces.jpg?ssl=1
|
||||
[13]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/intoption.jpg?ssl=1
|
||||
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/singleinterface.jpg?ssl=1
|
||||
[15]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/selint.jpg?ssl=1
|
||||
[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/capture.jpg?ssl=1
|
||||
[17]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/packetinfo.png?ssl=1
|
||||
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/raw.png?ssl=1
|
||||
[19]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/stopcapture.png?ssl=1
|
||||
[20]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/savepackets.jpg?ssl=1
|
||||
[21]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/savename.jpg?ssl=1
|
||||
[22]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/openpacket.png?ssl=1
|
||||
[23]: https://www.wireshark.org/docs/https://www.wireshark.org/docs/
|
||||
[24]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/kushal_rai.jpg?ssl=1
|
@ -0,0 +1,241 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (heguangzhi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to find what you’re looking for on Linux with find)
|
||||
[#]: via: (https://www.networkworld.com/article/3527420/how-to-find-what-you-re-looking-for-on-linux-with-find.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
如何在 Linux上通过 find 命令找到你要找的东西
|
||||
======
|
||||
find 命令有大量选项可以帮助你准确定位你在 Linux 系统上需要寻找的文件。这篇文章讨论了一系列非常有用的选项。
|
||||
|
||||
CSA 图片/ Getty 图片
|
||||
|
||||
在 Linux 系统上有许多用于查找文件的命令,但是在查找文件时也有大量的选项可以选择。
|
||||
|
||||
例如,你不仅可以通过文件的名称来查找文件,还可以通过文件的所有者或者组、它们的创建时间、大小、分配的权限、最后一次访问它们的时间、关联的信息节点,甚至是文件是否属于系统上不再存在的帐户或组等等来查找文件。
|
||||
|
||||
[[Get regularly scheduled insights by signing up for Network World newsletters.]][1]
|
||||
你还可以指定搜索从哪里开始,搜索应该深入到文件系统的什么位置,以及搜索结果将告诉你它所找到的文件的数量。
|
||||
|
||||
而所有这些要求都可以通过 **find** 命令来处理。
|
||||
|
||||
下面提供了根据这些标准查找文件的示例。在某些命令中,错误(例如试图列出你没有读取权限的文件),错误输出将被发送到 **/dev/null**,以便我们不必查看它。在其他情况下,我们将简单地以 root 身份运行以避免这个问题。
|
||||
|
||||
请记住,还其他选项存在。这篇文章涵盖了很多内容,但并不是 **find** 命令帮助你定位查找文件的所有方式。
|
||||
|
||||
### 选择起点
|
||||
|
||||
使用 **find**,您可以选择一个起点或从你所在的位置开始。请在单词“find”后输入要选择起点。例如,“find /usr” 或 “find ./bin "将在 **/usr** 目录或 **bin** 目录开始搜索,而" find ~ " 将在你的主目录中开始,即使你位于当前文件系统中的其他位置。
|
||||
|
||||
[][2]
|
||||
|
||||
### 选择你想看的
|
||||
|
||||
最常用的搜索策略之一是按名称搜索文件。这需要使用 **-name** 选项。
|
||||
|
||||
默认情况下,**查找** 会显示找到的文件的完整路径。如果你在命令中添加 **-print**,你会看到同样的情况。如果你想查看与文件相关的详细信息—-例如:文件的长度、权限等,您需要在你的 **查找** 命令的末尾添加 **-ls** 命令。
|
||||
|
||||
```
|
||||
$ find ~/bin -name tryme
|
||||
/home/shs/bin/tryme
|
||||
$ find ~/bin -name tryme -print
|
||||
/home/shs/bin/tryme
|
||||
$ find ~/bin -name tryme -ls
|
||||
917528 4 -rwx------ 1 shs shs 139 Apr 8 2019 /home/shs/bin/tryme
|
||||
```
|
||||
|
||||
你也可以使用子字符串来查找文件。例如,如果你将上面示例中的“tryme”替换为“try*”,你将会找到所有名称以“try”开头的文件。
|
||||
|
||||
按名称查找文件可能是 **find** 命令最典型的用法,但是有很多其他的方式来查找文件,并且有很好的理由这样做。下面的部分展示了如何使用其他可用的方式。
|
||||
|
||||
此外,当按大小、组、索引节点等条件来搜索文件时,你需要确认找到的文件与你要查找的文件是否相匹配。使用 **-ls** 选项来显示细节是非常有用。
|
||||
|
||||
### 通过大小查找文件
|
||||
|
||||
按大小查找文件需要使用 **-size** 选项并且对相应规范使用一点技巧。如果你指定 **-size 189b**,例如,你将找到189个块长的文件,而不是189个字节。对于字节,你需要使用 **--size 189c**(字符)。而且,如果你指定 **--size 200w** ,你将会找到200个单词的文件——以“双字节增量”为单位的单词,而不是“我们彼此都在说的那些事情”中的单词。你还可以通过以千字节(k)、兆字节(M)和千兆字节(G)为单位提供大小来查找文件。
|
||||
|
||||
|
||||
大多数情况下,Linux用户会搜索比所选文件大的文件。例如,要查找大于1千兆字节的文件,你可以使用这样的命令,其中 +1G 表示“大于1千兆字节”:
|
||||
|
||||
```
|
||||
$ find -size +1G -ls 2>/dev/null
|
||||
787715 1053976 -rw-rw-r-- 1 shs shs 1079263432 Dec 21 2018 ./backup.zip
|
||||
801834 1052556 -rw-rw-r-- 1 shs shs 1077809525 Dec 21 2018 ./2019/hold.zip
|
||||
```
|
||||
|
||||
### 通过索引节点查找文件 #
|
||||
|
||||
你可以通过用于维护文件元数据(即除文件内容和文件名之外的所有内容)的索引节点来查找文件。
|
||||
|
||||
```
|
||||
$ find -inum 919674 -ls 2>/dev/null
|
||||
919674 4 -rw-rw-r-- 1 shs shs 512 Dec 27 15:25 ./bin/my.log
|
||||
```
|
||||
|
||||
### 查找具有特定文件所有者或组的文件
|
||||
|
||||
按所有者或组查找文件也非常简单。这里我们使用 sudo 来解决权限问题。
|
||||
|
||||
```
|
||||
$ sudo find /home -user nemo -name "*.png"-ls
|
||||
1705219 4 drwxr-xr-x 2 nemo nemo 4096 Jan 28 08:50 /home/nemo/Pictures/me.png
|
||||
```
|
||||
|
||||
在这个命令中,我们寻找一个被称为 “admins” 的多用户组拥有的文件。
|
||||
|
||||
```
|
||||
# find /tmp -group admins -ls
|
||||
262199 4 -rwxr-x--- 1 dory admins 27 Feb 16 18:57 /tmp/testscript
|
||||
```
|
||||
|
||||
### 查找没有所有者或组的文件
|
||||
|
||||
你可以使用如下命令所示的 **-nouser** 选项来查找系统上没有任何现存用户属性的文件。
|
||||
|
||||
```
|
||||
# find /tmp -nouser -ls
|
||||
262204 4 -rwx------ 1 1016 1016 17 Feb 17 16:42 /tmp/hello
|
||||
```
|
||||
|
||||
请注意,该列表显示了旧用户的 UID 和 GID,这清楚地表明该用户未在系统上定义。这种命令将查找由于帐户已从系统中删除的用户在非主目录中创建的文件,或者在用户帐户被删除后未被删除的主目录中创建的文件。类似地,**-nogroup** 选项会找到这样的文件,尤其是当这些用户是相关组的唯一成员时。
|
||||
|
||||
### 按上次更新时间查找文件
|
||||
|
||||
在此命令中,我们在特定用户的主目录中查找过去24小时内更新过的文件。**sudo** 用于搜索另一个用户的主目录。
|
||||
|
||||
```
|
||||
$ sudo find /home/nemo -mtime -1
|
||||
/home/nemo
|
||||
/home/nemo/snap/cheat
|
||||
/home/nemo/tryme
|
||||
```
|
||||
|
||||
### 按上次更改权限的时间查找文件
|
||||
|
||||
**-ctime** 选项可以帮助你查找在某个参考时间范围内状态(如权限)发生更改的文件。以下是查找在最后一天内权限发生更改的文件的示例:
|
||||
|
||||
```
|
||||
$ find . -ctime -1 -ls
|
||||
787987 4 -rwxr-xr-x 1 shs shs 189 Feb 11 07:31 ./tryme
|
||||
```
|
||||
|
||||
请记住,显示的日期和时间反映了文件内容的最后更新。你需要使用像 **stat** 这样的命令来查看与文件相关联的三个状态(文件创建、修改和状态更改)。
|
||||
|
||||
### Finding files based on last access times
|
||||
|
||||
在这个命令中,我们使用 **-atime** 选项查找在过去两天内访问过的本地 pdf 文件。
|
||||
|
||||
```
|
||||
$ find -name "*.pdf" -atime -2
|
||||
./Wingding_Invites.pdf
|
||||
```
|
||||
|
||||
### 根据文件相对于另一个文件的时间来查找文件
|
||||
|
||||
你可以使用 -newer 选项来查找比其他文件更新的文件。
|
||||
|
||||
```
|
||||
$ find . -newer dig1 -ls
|
||||
786434 68 drwxr-xr-x 67 shs shs 69632 Feb 16 19:05 .
|
||||
1064442 4 drwxr-xr-x 5 shs shs 4096 Feb 16 11:06 ./snap/cheat
|
||||
791846 4 -rw-rw-r-- 1 shs shs 649 Feb 13 14:26 ./dig
|
||||
```
|
||||
|
||||
没有相应的 **-older** 选项,但是你可以用**,得到类似的结果 **! -newer**(即更旧),这意味着几乎相同的事情。
|
||||
|
||||
### 按类型查找文件
|
||||
|
||||
通过文件类型找到一个文件,你有很多选项——常规文件、目录、块和字符文件等等。以下是文件类型选项列表:
|
||||
|
||||
```
|
||||
b block (buffered) special
|
||||
c character (unbuffered) special
|
||||
d directory
|
||||
p named pipe (FIFO)
|
||||
f regular file
|
||||
l symbolic link
|
||||
s socket
|
||||
```
|
||||
|
||||
这里有一个寻找符号链接的例子:
|
||||
|
||||
```
|
||||
$ find . -type l -ls
|
||||
805717 0 lrwxrwxrwx 1 shs shs 11 Apr 10 2019 ./volcano -> volcano.pdf
|
||||
918552 0 lrwxrwxrwx 1 shs shs 1 Jun 16 2018 ./letter -> pers/letter2mom
|
||||
```
|
||||
|
||||
### 限制查找的深度
|
||||
|
||||
**-mindepth** 和 **-maxdepth** 选项控制在文件系统中搜索的深度(从当前位置或起始点开始)。
|
||||
|
||||
```
|
||||
$ find -maxdepth 3 -name "*loop"
|
||||
./bin/save/oldloop
|
||||
./bin/long-loop
|
||||
./private/loop
|
||||
```
|
||||
|
||||
### 查找空文件
|
||||
|
||||
在这个命令中,我们寻找空文件,但不超过目录及其子目录。
|
||||
|
||||
```
|
||||
$ find . -maxdepth 2 -empty -type f -ls
|
||||
917517 0 -rw-rw-r-- 1 shs shs 0 Sep 23 11:00 ./complaints/newfile
|
||||
792050 0 -rw-rw-r-- 1 shs shs 0 Oct 4 19:02 ./junk
|
||||
```
|
||||
|
||||
### 按权限查找文件
|
||||
|
||||
你可以使用 **-perm** 选项查找具有特定权限集的文件。在下面的示例中,我们只查找常规文件(**-type f**),以避免看到默认情况下被赋予这些权限的符号链接,即使它们引用的文件是受限的。
|
||||
|
||||
```
|
||||
$ find -perm 777 -type f -ls
|
||||
find: ‘./.dbus’: Permission denied
|
||||
798748 4 -rwxrwxrwx 1 shs shs 15 Mar 28 2019 ./runme
|
||||
```
|
||||
|
||||
### 使用查找来帮助你删除文件
|
||||
|
||||
如果使用如下命令,你可以使用 find 命令定位并删除文件:
|
||||
|
||||
```
|
||||
$ find . -name runme -exec rm {} \;
|
||||
```
|
||||
|
||||
{} 代表根据搜索条件找到的每个文件的名称。
|
||||
|
||||
一个非常有用的选项是将 **-exec** 替换为 **-ok**。当您这样做时,**find** 会在删除任何文件之前要求确认。
|
||||
|
||||
```
|
||||
$ find . -name runme -ok rm -rf {} \;
|
||||
< rm ... ./bin/runme > ?
|
||||
```
|
||||
|
||||
删除文件并不是 **-ok** 和 **-rm** 能为你做的唯一事情。例如,你可以复制、重命名或移动文件。
|
||||
|
||||
确实有很多选择可以有效地使用 find 命令,毫无疑问还有一些在本文中没有涉及到。我希望你已经找到一些新的,特别有帮助的。
|
||||
|
||||
加入[Facebook][3]和[LinkedIn][4]上的网络世界社区,评论最热门的话题。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3527420/how-to-find-what-you-re-looking-for-on-linux-with-find.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[heguangzhi](https://github.com/heguangzhi)
|
||||
校对:[校对者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://www.networkworld.com/newsletters/signup.html
|
||||
[2]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
|
||||
[3]: https://www.facebook.com/NetworkWorld/
|
||||
[4]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,105 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to Add New Brushes in GIMP [Quick Tip])
|
||||
[#]: via: (https://itsfoss.com/add-brushes-gimp/)
|
||||
[#]: author: (Community https://itsfoss.com/author/itsfoss/)
|
||||
|
||||
如何在 GIMP 中添加新画笔(快速技巧)
|
||||
======
|
||||
|
||||
[GIMP][1] 是最流行的免费和开源图像编辑器,它也许是 Linux 上最好的 [Adobe Photoshop 替代品][2]。
|
||||
|
||||
当你[在 Ubuntu 或其他任何操作系统上安装了 GIMP 后][3],你会发现已经安装了一些用于基本图像编辑的画笔。如果你需要更具体的画笔,你可以随时在 GIMP 中添加新画笔。
|
||||
|
||||
怎么样?让我在这个快速教程中向你展示。
|
||||
|
||||
### 如何在 GIMP 中添加画笔
|
||||
|
||||
![][4]
|
||||
|
||||
在 GIMP 中安装新画笔需要三个步骤:
|
||||
|
||||
* 获取新画笔
|
||||
* 将其放入指定的文件夹中
|
||||
* 刷新 GIMP 中的画笔
|
||||
|
||||
|
||||
|
||||
#### 步骤 1:下载新的 GIMP 画笔
|
||||
|
||||
第一步是获取新的 GIMP 画笔。你从哪里获取?当然是从互联网上。
|
||||
|
||||
你可以在 Google 或[隐私搜索引擎,如 Duck Duck Go][5] 种搜索 “GIMP画笔”,并从网站下载一个你喜欢的。
|
||||
|
||||
GIMP 画笔通常以 .gbr 和 .gih 文件格式提供。.gbr 文件用于常规画笔,而 .gih 用于动画画笔。
|
||||
|
||||
你知道吗?
|
||||
|
||||
从 2.4 版本起,GIMP 使安装和使用 Photoshop 画笔(.abr 文件)非常简单。你只需将 Photoshop 画笔文件放在正确的文件夹中。
|
||||
请记住,最新的 Photoshop 画笔可能无法完美地在 GIMP 中使用。
|
||||
|
||||
#### 步骤 2:将新画笔复制到它的位置
|
||||
|
||||
获取画笔文件后,下一步是复制该文件并将其粘贴到 GIMP 配置目录中所在的文件夹。
|
||||
|
||||
在 **Windows** 上,你必须进入类似 “**C:\Documents and Settings\myusername.gimp-2.10\brushes**” 这样的文件夹。
|
||||
|
||||
我将展示 **Linux** 上的详细步骤,因为 It’s FOSS 是一个专注于 Linux 的网站。
|
||||
|
||||
选择画笔文件后,在 **Home** 目录中按下 **Ctrl+h** [查看 Linux 中的隐藏文件][6]。
|
||||
|
||||
![Press Ctrl+H to see hidden files in the home directory][7]
|
||||
|
||||
你应该进入 **.config/GIMP/2.10/brushes** 文件夹(如果你使用的是 GIMP 2.10)。如果使用其他版本,那么应在 .config/GIMP 下看到相应文件夹。
|
||||
|
||||
![Adding New Brushes in GIMP][8]
|
||||
|
||||
将画笔文件粘贴到此文件夹中。可选地,你可以通过再次按 **Ctrl+h** 来隐藏隐藏的文件。
|
||||
|
||||
#### 步骤 3:刷新画笔(避免重启 GIMP)
|
||||
|
||||
GIMP 将在启动时自动加载画笔。如果已在运行,并且不想关闭它,你可以刷新画笔。
|
||||
|
||||
在 GIMP 的主菜单中找到 **Windows**->**Dockable Dialogues**->**Brushes**。
|
||||
|
||||
![Refresh GIMP Brushes by going go to Windows->Dockable Dialogues-> Brushes][9]
|
||||
|
||||
在右侧栏的 **Brushes** 对话框中找到**刷新**图标。
|
||||
|
||||
![Refresh GIMP Brushes][10]
|
||||
|
||||
如果你的画笔没有出现,那么你可以试试重启 GIMP。
|
||||
|
||||
额外的技巧!
|
||||
|
||||
在 [GIMP 中添加新画笔还能让你轻松给图片添加水印][11]。只需将 logo 用作画笔,并点击一下就可添加到图片中。
|
||||
|
||||
我希望你喜欢这个快速 GIMP 技巧。敬请期待更多。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/add-brushes-gimp/
|
||||
|
||||
作者:[Community][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/itsfoss/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.gimp.org/
|
||||
[2]: https://itsfoss.com/open-source-photoshop-alternatives/
|
||||
[3]: https://itsfoss.com/gimp-2-10-release/
|
||||
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/Install-New-Brushes-in-GIMP.jpg?ssl=1
|
||||
[5]: https://itsfoss.com/privacy-search-engines/
|
||||
[6]: https://itsfoss.com/hide-folders-and-show-hidden-files-in-ubuntu-beginner-trick/
|
||||
[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/adding-brushes-GIMP-1.jpg?ssl=1
|
||||
[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/adding-brushes-GIMP.png?ssl=1
|
||||
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/Refresh-GIMP-Brushes.jpg?ssl=1
|
||||
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/Refresh-GIMP-Brushes-2.jpg?ssl=1
|
||||
[11]: https://itsfoss.com/add-watermark-gimp-linux/
|
@ -0,0 +1,561 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Getting started with the Rust package manager, Cargo)
|
||||
[#]: via: (https://opensource.com/article/20/3/rust-cargo)
|
||||
[#]: author: (Gaurav Kamathe https://opensource.com/users/gkamathe)
|
||||
|
||||
Rust 包管理器 Cargo 入门
|
||||
======
|
||||
|
||||
> 了解 Rust 的软件包管理器和构建工具。
|
||||
|
||||
![Shipping containers stacked in a yard][1]
|
||||
|
||||
[Rust][2] 是一种现代编程语言,可提供高性能、可靠性和生产力。几年来,它一直被 StackOverflow 调查评为[最受欢迎的语言][3]。
|
||||
|
||||
除了是一种出色的编程语言之外,Rust 还具有一个称为 Cargo 的构建系统和软件包管理器。Cargo 处理许多任务,例如构建代码、下载库或依赖项等等。这两者捆绑在一起,因此在安装 Rust 时会得到 Cargo。
|
||||
|
||||
### 安装 Rust 和 Cargo
|
||||
|
||||
在开始之前,你需要安装 Rust 和 Cargo。Rust 项目提供了一个可下载的脚本来处理安装。要获取该脚本,请打开浏览器以访问 [https://sh.rustup.rs][4] 并保存该文件。阅读脚本以确保你对它的具体行为有所了解,然后运行它:
|
||||
|
||||
```
|
||||
$ sh ./rustup.rs
|
||||
```
|
||||
|
||||
你也可以参考这个[安装 Rust][5]网页以获取更多信息。
|
||||
|
||||
安装 Rust 和 Cargo 之后,你必须<ruby>获取<rt>source</rt></ruby> `env` 文件:
|
||||
|
||||
```
|
||||
$ source $HOME/.cargo/env
|
||||
```
|
||||
|
||||
更好的是,将所需目录添加到 `PATH` 环境变量中:
|
||||
|
||||
```
|
||||
export PATH=$PATH:~/.cargo/bin
|
||||
```
|
||||
|
||||
如果你更喜欢使用软件包管理器(例如 Linux 上的 DNF 或 Apt),请在发行版本的存储库中查找 Rust 和 Cargo 软件包,并进行相应的安装。 例如:
|
||||
|
||||
```
|
||||
$ dnf install rust cargo
|
||||
```
|
||||
|
||||
安装并设置它们后,请验证你拥有的 Rust 和 Cargo 版本:
|
||||
|
||||
```
|
||||
$ rustc --version
|
||||
rustc 1.41.0 (5e1a79984 2020-01-27)
|
||||
$ cargo --version
|
||||
cargo 1.41.0 (626f0f40e 2019-12-03)
|
||||
```
|
||||
|
||||
### 手动构建和运行 Rust
|
||||
|
||||
从在屏幕上打印“Hello, world!”的简单程序开始。打开你喜欢的文本编辑器,然后键入以下程序:
|
||||
|
||||
```
|
||||
$ cat hello.rs
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
以扩展名 `.rs` 保存文件,以将其标识为 Rust 源代码文件。
|
||||
|
||||
使用 Rust 编译器 `rustc` 编译程序:
|
||||
|
||||
```
|
||||
$ rustc hello.rs
|
||||
```
|
||||
|
||||
编译后,你将拥有一个与源程序同名的二进制文件:
|
||||
|
||||
```
|
||||
$ ls -l
|
||||
total 2592
|
||||
-rwxr-xr-x. 1 user group 2647944 Feb 13 14:14 hello
|
||||
-rw-r--r--. 1 user group 45 Feb 13 14:14 hello.rs
|
||||
$
|
||||
```
|
||||
|
||||
执行程序以验证其是否按预期运行:
|
||||
|
||||
```
|
||||
$ ./hello
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
这些步骤对于较小的程序或任何你想快速测试的东西就足够了。但是,在进行涉及多人的大型计划时,Cargo 是前进的最佳之路。
|
||||
|
||||
### 使用 Cargo 创建新包
|
||||
|
||||
Cargo 是 Rust 的构建系统和包管理器。它可以帮助开发人员下载和管理依赖项,并帮助创建 Rust 包。在Rust 社区中,Rust 中的“包”通常被称为“crate”(板条箱),但是在本文中,这两个词是可以互换的。请参阅 Rust 社区提供的 Cargo [FAQ][6] 来区分。
|
||||
|
||||
如果你需要有关 Cargo 命令行实用程序的任何帮助,请使用 `--help` 或 `-h` 命令行参数:
|
||||
|
||||
```
|
||||
$ cargo –help
|
||||
```
|
||||
|
||||
要创建一个新的包,请使用关键字 `new`,跟上包名称。在这个例子中,使用 `hello_opensource` 作为新的包名称。运行该命令后,你将看到一条消息,确认 Cargo 已创建具有给定名称的二进制包:
|
||||
|
||||
```
|
||||
$ cargo new hello_opensource
|
||||
Created binary (application) `hello_opensource` package
|
||||
```
|
||||
|
||||
运行 `tree` 命令以查看目录结构,它会报告已创建了一些文件和目录。首先,它创建一个带有包名称的目录,并且在该目录内有一个存放你的源代码文件的 `src` 目录:
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
└── hello_opensource
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
2 directories, 2 files
|
||||
```
|
||||
|
||||
Cargo 不仅可以创建包,它也创建了一个简单的 “Hello, world” 程序。打开 `main.rs` 文件看看:
|
||||
|
||||
```
|
||||
$ cat hello_opensource/src/main.rs
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
下一个要处理的文件是 `Cargo.toml`,这是你的包的配置文件。它包含有关包的信息,例如其名称、版本、作者信息和 Rust 版本信息。
|
||||
|
||||
程序通常依赖于外部库或依赖项来运行,这使你可以编写应用程序来执行不知道如何编码或不想花时间编码的任务。你所有的依赖项都将在此文件中列出。此时,对你的新程序你没有任何依赖关系。打开 `Cargo.toml` 文件并查看其内容:
|
||||
|
||||
```
|
||||
$ cat hello_opensource/Cargo.toml
|
||||
[package]
|
||||
name = "hello_opensource"
|
||||
version = "0.1.0"
|
||||
authors = ["user <user@mail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
```
|
||||
|
||||
### 使用 Cargo 构建程序
|
||||
|
||||
到目前为止,一切都很顺利。现在你已经有了一个包,可构建一个二进制文件(也称为可执行文件)。在此之前,进入包目录:
|
||||
|
||||
```
|
||||
$ cd hello_opensource/
|
||||
```
|
||||
|
||||
你可以使用 Cargo 的 `build` 命令来构建包。注意消息说它正在“编译”你的程序:
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.38s
|
||||
```
|
||||
|
||||
运行 `build` 命令后,检查项目目录发生了什么:
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
├── src
|
||||
│ └── main.rs
|
||||
└── target
|
||||
└── debug
|
||||
├── build
|
||||
├── deps
|
||||
│ ├── hello_opensource-147b8a0f466515dd
|
||||
│ └── hello_opensource-147b8a0f466515dd.d
|
||||
├── examples
|
||||
├── hello_opensource
|
||||
├── hello_opensource.d
|
||||
└── incremental
|
||||
└── hello_opensource-3pouh4i8ttpvz
|
||||
├── s-fkmhjmt8tj-x962ep-1hivstog8wvf
|
||||
│ ├── 1r37g6m45p8rx66m.o
|
||||
│ ├── 2469ykny0eqo592v.o
|
||||
│ ├── 2g5i2x8ie8zed30i.o
|
||||
│ ├── 2yrvd7azhgjog6zy.o
|
||||
│ ├── 3g9rrdr4hyk76jtd.o
|
||||
│ ├── dep-graph.bin
|
||||
│ ├── query-cache.bin
|
||||
│ ├── work-products.bin
|
||||
│ └── wqif2s56aj0qtct.o
|
||||
└── s-fkmhjmt8tj-x962ep.lock
|
||||
|
||||
9 directories, 17 files
|
||||
```
|
||||
|
||||
哇!编译过程产生了许多中间文件。另外,你的二进制文件将以与软件包相同的名称保存在 `./target/debug` 目录中。
|
||||
|
||||
### 使用 Cargo 运行你的应用程序
|
||||
|
||||
现在你的二进制文件已经构建好了,使用 Cargo 的 `run` 命令运行它。如预期的那样,它将在屏幕上打印 `Hello, world!`。
|
||||
|
||||
```
|
||||
$ cargo run
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
|
||||
Running `target/debug/hello_opensource`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
或者,你可以直接运行二进制文件,该文件位于:
|
||||
|
||||
```
|
||||
$ ls -l ./target/debug/hello_opensource
|
||||
-rwxr-xr-x. 2 root root 2655552 Feb 13 14:19 ./target/debug/hello_opensource
|
||||
```
|
||||
|
||||
如预期的那样,它产生相同的结果:
|
||||
|
||||
```
|
||||
$ ./target/debug/hello_opensource
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
假设你需要重建包,并丢弃早期编译过程创建的所有二进制文件和中间文件。Cargo 提供了一个方便的`clean` 选项来删除所有中间文件,但源代码和其他必需文件除外:
|
||||
|
||||
```
|
||||
$ cargo clean
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
1 directory, 3 files
|
||||
```
|
||||
|
||||
对程序进行一些更改,然后再次运行以查看其工作方式。例如,下面这个较小的更改将 `Opensource` 添加到 `Hello, world!` 字符串中:
|
||||
|
||||
```
|
||||
$ cat src/main.rs
|
||||
fn main() {
|
||||
println!("Hello, Opensource world!");
|
||||
}
|
||||
```
|
||||
|
||||
现在,构建程序并再次运行它。这次,你会在屏幕上看到 `Hello, Opensource world!`:
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.39s
|
||||
|
||||
$ cargo run
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
|
||||
Running `target/debug/hello_opensource`
|
||||
Hello, Opensource world!
|
||||
```
|
||||
|
||||
### 使用 Cargo 添加依赖项
|
||||
|
||||
Cargo 允许你添加程序需要运行的依赖项。使用 Cargo 添加依赖项非常容易。每个 Rust 包都包含一个 `Cargo.toml` 文件,其中包含一个依赖关系列表(默认为空)。用你喜欢的文本编辑器打开该文件,找到 `[dependencies]` 部分,然后添加要包含在包中的库。例如,将 `rand` 库添加为依赖项:
|
||||
|
||||
```
|
||||
$ cat Cargo.toml
|
||||
[package]
|
||||
name = "hello_opensource"
|
||||
version = "0.1.0"
|
||||
authors = ["test user <test@mail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rand = "0.3.14"
|
||||
```
|
||||
|
||||
试试构建你的包,看看会发生什么。
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Updating crates.io index
|
||||
Compiling libc v0.2.66
|
||||
Compiling rand v0.4.6
|
||||
Compiling rand v0.3.23
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 4.48s
|
||||
```
|
||||
|
||||
现在,Cargo 会联系 [Crates.io][9],这是 Rust 用于存储 crate(或包)的中央仓库,并下载和编译 `rand`。但是,等等 —— `libc` 包是怎么回事?你没有要要安装 libc 啊。是的,`rand` 包依赖于 `libc` 包;因此,Cargo 也会下载并编译 `libc`。
|
||||
|
||||
库的新版本不断涌现,而 Cargo 提供了一种使用 `update` 命令更新其所有依赖关系的简便方法:
|
||||
|
||||
```
|
||||
cargo update
|
||||
```
|
||||
|
||||
你还可以选择使用 `-p` 标志跟上包名称来更新特定的库:
|
||||
|
||||
```
|
||||
cargo update -p rand
|
||||
```
|
||||
|
||||
### 使用单个命令进行编译和运行
|
||||
|
||||
到目前为止,每当对程序进行更改时,都先使用了 `build` 之后是 `run`。有一个更简单的方法:你可以直接使用 `run` 命令,该命令会在内部进行编译并运行该程序。要查看其工作原理,请首先清理你的软件包目录:
|
||||
|
||||
```
|
||||
$ cargo clean
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
1 directory, 3 files
|
||||
```
|
||||
|
||||
现在执行 `run`。输出信息表明它已进行编译,然后运行了该程序,这意味着你不需要每次都显式地运行 `build`:
|
||||
|
||||
```
|
||||
$ cargo run
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
|
||||
Running `target/debug/hello_opensource`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
### 在开发过程中检查代码
|
||||
|
||||
在开发程序时,你经常会经历多次迭代。你需要确保你的程序没有编码错误并且可以正常编译。你不需要负担在每次编译时生成二进制文件的开销。Cargo 为你提供了一个 `check` 选项,该选项可以编译代码,但跳过了生成可执行文件的最后一步。首先在包目录中运行 `cargo clean`:
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── main.rs
|
||||
|
||||
1 directory, 3 files
|
||||
```
|
||||
|
||||
现在运行 `check` 命令,查看对目录进行了哪些更改:
|
||||
|
||||
```
|
||||
$ cargo check
|
||||
Checking hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.18s
|
||||
```
|
||||
|
||||
该输出显示,即使在编译过程中创建了中间文件,但没有创建最终的二进制文件或可执行文件。这样可以节省一些时间,如果该包包含了数千行代码,这非常重要:
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
├── src
|
||||
│ └── main.rs
|
||||
└── target
|
||||
└── debug
|
||||
├── build
|
||||
├── deps
|
||||
│ ├── hello_opensource-842d9a06b2b6a19b.d
|
||||
│ └── libhello_opensource-842d9a06b2b6a19b.rmeta
|
||||
├── examples
|
||||
└── incremental
|
||||
└── hello_opensource-1m3f8arxhgo1u
|
||||
├── s-fkmhw18fjk-542o8d-18nukzzq7hpxe
|
||||
│ ├── dep-graph.bin
|
||||
│ ├── query-cache.bin
|
||||
│ └── work-products.bin
|
||||
└── s-fkmhw18fjk-542o8d.lock
|
||||
|
||||
9 directories, 9 files
|
||||
```
|
||||
|
||||
要查看你是否真的节省了时间,请对 `build` 和 `check` 命令进行计时并进行比较。首先,计时 `build` 命令:
|
||||
|
||||
```
|
||||
$ time cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.40s
|
||||
|
||||
real 0m0.416s
|
||||
user 0m0.251s
|
||||
sys 0m0.199s
|
||||
```
|
||||
|
||||
在运行 `check` 命令之前清理目录:
|
||||
|
||||
```
|
||||
$ cargo clean
|
||||
```
|
||||
|
||||
计时 `check` 命令:
|
||||
|
||||
```
|
||||
$ time cargo check
|
||||
Checking hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
|
||||
|
||||
real 0m0.166s
|
||||
user 0m0.086s
|
||||
sys 0m0.081s
|
||||
```
|
||||
|
||||
显然,`check` 命令要快得多。
|
||||
|
||||
### 建立外部 Rust 包
|
||||
|
||||
到目前为止,你所做的这些都可以应用于你从互联网上获得的任何 Rust crate。你只需要下载或克隆存储库,移至包文件夹,然后运行 `build` 命令,就可以了:
|
||||
|
||||
```
|
||||
git clone <github-like-url>
|
||||
cd <package-folder>
|
||||
cargo build
|
||||
```
|
||||
|
||||
### 使用 Cargo 构建优化的 Rust 程序
|
||||
|
||||
到目前为止,你已经多次运行 `build`,但是你注意到它的输出了吗?不用担心,再次构建它并密切注意:
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
|
||||
```
|
||||
|
||||
看到了每次编译后的 `[unoptimized + debuginfo]` 文本了吗?这意味着 Cargo 生成的二进制文件包含大量调试信息,并且未针对执行进行优化。开发人员经常经历开发的多次迭代,并且需要此调试信息进行分析。同样,性能并不是开发软件时的近期目标。因此,对于现在而言是没问题的。
|
||||
|
||||
但是,一旦准备好发布软件,就不再需要这些调试信息。而是需要对其进行优化以获得最佳性能。在开发的最后阶段,可以将 `--release` 标志与 `build` 一起使用。仔细看,编译后,你应该会看到 `[optimized]` 文本:
|
||||
|
||||
```
|
||||
$ cargo build --release
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Finished release [optimized] target(s) in 0.29s
|
||||
```
|
||||
|
||||
如果愿意,你可以通过这种练习来了解运行优化软件与未优化软件时节省的时间。
|
||||
|
||||
### 使用 Cargo 创建库还是二进制文件
|
||||
|
||||
任何软件程序都可以粗略地分类为独立二进制文件或库。一个独立二进制文件也许即使是当中外部库使用的,自身也是可以运行的。但是,作为一个库,是可以被另一个独立二进制文件所利用的。到目前为止,你在本教程中构建的所有程序都是独立二进制文件,因为这是 Cargo 的默认设置。 要创建一个**库**,请添加 `--lib` 选项:
|
||||
|
||||
```
|
||||
$ cargo new --lib libhello
|
||||
Created library `libhello` package
|
||||
```
|
||||
|
||||
这次,Cargo 不会创建 `main.rs` 文件,而是创建一个 `lib.rs` 文件。 你的库的代码应该是这样的:
|
||||
|
||||
```
|
||||
$ tree .
|
||||
.
|
||||
└── libhello
|
||||
├── Cargo.toml
|
||||
└── src
|
||||
└── lib.rs
|
||||
|
||||
2 directories, 2 files
|
||||
```
|
||||
|
||||
Cargo 就是这样的,不要奇怪,它在你的新库文件中添加了一些代码。通过移至包目录并查看文件来查找添加的内容。默认情况下,Cargo 在库文件中放置一个测试函数。
|
||||
|
||||
### 使用 Cargo 运行测试
|
||||
|
||||
Rust 为单元测试和集成测试提供了一流的支持,而 Cargo 允许你执行以下任何测试:
|
||||
|
||||
```
|
||||
$ cd libhello/
|
||||
|
||||
$ cat src/lib.rs
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Cargo 有一个方便的 `test` 命令,可以运行代码中存在的任何测试。尝试默认运行 Cargo 在库代码中放入的测试:
|
||||
|
||||
```
|
||||
$ cargo test
|
||||
Compiling libhello v0.1.0 (/opensource/libhello)
|
||||
Finished test [unoptimized + debuginfo] target(s) in 0.55s
|
||||
Running target/debug/deps/libhello-d52e35bb47939653
|
||||
|
||||
running 1 test
|
||||
test tests::it_works ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
|
||||
Doc-tests libhello
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
```
|
||||
|
||||
### 深入了解 Cargo 内部
|
||||
|
||||
你可能有兴趣了解在运行一个 Cargo 命令时它底下发生了什么。毕竟,在许多方面,Cargo 只是个封装器。要了解它在做什么,你可以将 `-v` 选项与任何 Cargo 命令一起使用,以将详细信息输出到屏幕。
|
||||
|
||||
这是使用 `-v` 选项运行 `build` 和 `clean` 的几个例子。
|
||||
|
||||
在 `build` 命令中,你可以看到这些给定的命令行选项触发了底层的 `rustc`(Rust编译器):
|
||||
|
||||
```
|
||||
$ cargo build -v
|
||||
Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)
|
||||
Running `rustc --edition=2018 --crate-name hello_opensource src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=147b8a0f466515dd -C extra-filename=-147b8a0f466515dd --out-dir /opensource/hello_opensource/target/debug/deps -C incremental=/opensource/hello_opensource/target/debug/incremental -L dependency=/opensource/hello_opensource/target/debug/deps`
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
|
||||
```
|
||||
|
||||
而 `clean` 命令表明它只是删除包含中间文件和二进制文件的目录:
|
||||
|
||||
```
|
||||
$ cargo clean -v
|
||||
Removing /opensource/hello_opensource/target
|
||||
```
|
||||
|
||||
### 不要让你的技能生锈
|
||||
|
||||
要扩展你的技能,请尝试使用 Rust 和 Cargo 编写并运行一个稍微复杂的程序。很简单就可以做到:例如,尝试列出当前目录中的所有文件(可以用 9 行代码完成),或者尝试自己回显输入。小型的实践应用程序可帮助你熟悉语法以及编写和测试代码的过程。
|
||||
|
||||
本文为刚起步的 Rust 程序员提供了大量信息,以使他们可以开始入门 Cargo。但是,当你开始处理更大、更复杂的程序时,你需要对 Cargo 有更深入的了解。当你准备好迎接更多内容时,请下载并阅读 Rust 团队编写的开源《[Cargo 手册][10]》,看看你可以创造什么!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/rust-cargo
|
||||
|
||||
作者:[Gaurav Kamathe][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/gkamathe
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bus-containers2.png?itok=idd8duC_ (Shipping containers stacked in a yard)
|
||||
[2]: https://www.rust-lang.org/
|
||||
[3]: https://insights.stackoverflow.com/survey/2019#technology-_-most-loved-dreaded-and-wanted-languages
|
||||
[4]: https://sh.rustup.rs/
|
||||
[5]: https://www.rust-lang.org/tools/install
|
||||
[6]: https://doc.rust-lang.org/cargo/faq.html
|
||||
[7]: mailto:user@mail.com
|
||||
[8]: mailto:test@mail.com
|
||||
[9]: http://crates.io
|
||||
[10]: https://doc.rust-lang.org/cargo
|
@ -0,0 +1,131 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Drauger OS Linux Aims to Bring Console Gaming Experience on the Desktop)
|
||||
[#]: via: (https://itsfoss.com/drauger-os/)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
Drauger OS Linux 旨在为台式机带来主机游戏体验
|
||||
======
|
||||
|
||||
多年来(或数十年),人们抱怨不[使用Linux][1] 的原因之一是缺乏主流游戏。[Linux 上的游戏][2]在最近几年有了显著改进,特别是 [Steam Proton][3] 项目的引入使你可以[在 Linux 上玩很多 Windows 专用的游戏][4]。
|
||||
|
||||
这也鼓励了一些[以游戏为中心的 Linux发行版][5]。以 [Lakka][6] 为例,你可以[借助 Lakka Linux 将旧计算机变成复古的街机游戏机][7]。
|
||||
|
||||
另一个以游戏为中心的 Linux 发行版是 [Draguer OS][8],我们今天将对其进行研究。
|
||||
|
||||
### Drauger OS
|
||||
|
||||
根据[该项目的网站][9],“Drauger OS 是 Linux 桌面游戏操作系统。它旨在为游戏玩家提供一个平台,使他们可以在不牺牲安全性的情况下获得出色的性能。此外,它旨在使任何人都可以轻松玩游戏,无论他们使用键盘和鼠标还是某种控制器。”
|
||||
|
||||
他们强调 Drauger OS 并非供日常使用。因此,大多数其他发行版附带的许多生产力工具都不在 Drauger OS 中。
|
||||
|
||||
![Drauger OS 7.4.1][10]
|
||||
|
||||
Drauger OS [基于][9] Ubuntu 之上。当前版本(7.4.1 Jiangshi)使用 “[Liquorix][11] 低延迟Linux 内核,这是一种预编译的 ZEN 内核,设计时考虑了延迟和吞吐量之间的平衡”。但是,这将在下一版本中更改。他们只有一个桌面环境可供选择,即一个修改版本的 [Xfce][12]。
|
||||
|
||||
Drauger OS 开箱即用地安装了多个应用程序和工具,以改善游戏体验。这些包括:
|
||||
|
||||
* [PlayOnLinux][13]
|
||||
* WINE
|
||||
* [Lutris][14]
|
||||
* Steam
|
||||
* [DXVK][15]
|
||||
|
||||
它还具有一组与游戏无关的有趣工具。[Drauger Installer][16] 是 .deb 安装程序,是 Gdebi 的替代品。[多软件库应用安装器][17](mrai)是“用于基于 Debian 的 Linux 操作系统的类似于 AUR-helper 的脚本”。Mrai 旨在与 apt、snap、flatpaks 配合使用,并且可以从 GitHub 安装应用程序。
|
||||
|
||||
有趣的是,Drauger OS 的名称是一个错误。首席开发者 [Thomas Castleman][18](即 batcastle)曾打算为其发行版命名为 Draugr,但是却打错了名字。在 Drauger OS 播客的[第 23 集][19]中,Castleman 说保持这个拼写错误的名称,因为要对其进行更正需要大量工作。根据 [Wikipedia][20] 的描述,Draugr 是“来自北欧神话中的不死生物”。
|
||||
|
||||
是的,你没看错。Drauger OS 是仅有的几个具有自己的[播客][21]的发行版之一。当被问到这个问题时,Castleman 告诉我:“无论他们的情况如何,我都希望确保我们的社区拥有最大的透明度。”多数情况下,播客是 Drauger OS 博客的音频版本,但有时他们会在没有时间撰写博客文章时使用它来发布公告。
|
||||
|
||||
### Drauger OS 的未来
|
||||
|
||||
![Drauger OS][22]
|
||||
|
||||
Druager OS 背后的开发人员正在开发其下一个主要版本:7.5.1。此版本将基于 Ubuntu 19.10。将有三个主要变化。首先,将使用“我们内部构建的内核” [替换][23] Liquorix 内核。该内核将基于 Linux Kernel GitHub 存储库,“因此,它变得越来越原汁原味”。
|
||||
|
||||
新版本的第二个主要变化将是为其桌面提供新布局。根据用户的反馈,他们决定将其更改为看起来更类似于 GNOME 的样子。
|
||||
|
||||
第三,他们放弃了 SystemBack 作为其备份工具和安装程序。相反,他们从头开始编写了新的[安装程序][24]。
|
||||
|
||||
开发团队也正在研究 Drauger OS 的 [ARM 版本][25]。他们希望在 2022 年的某个时候发布它。
|
||||
|
||||
### 系统要求
|
||||
|
||||
Drauger OS [系统要求][25]非常适中。请记住,Drauger OS 仅在 64 位系统上运行。
|
||||
|
||||
#### 最低系统要求
|
||||
|
||||
* CPU:双核、1.8GHz、64 位处理器
|
||||
* RAM:1 GB
|
||||
* 储存空间:16 GB
|
||||
* 图形处理器:集成
|
||||
* 屏幕分辨率:60Hz 时为 1024×768
|
||||
* 外部端口:1 个用于显示的端口(HDMI/DisplayPort/VGA/DVI),2 个用于安装 USB 驱动器和键盘的 USB 端口(鼠标可选,但建议使用)
|
||||
|
||||
#### 推荐系统要求
|
||||
|
||||
* CPU:四核、2.2Ghz、64 位处理器
|
||||
* RAM:4 GB
|
||||
* 储存空间:128 GB
|
||||
* 图形处理器:NVIDIA GTX 1050、AMD RX 460 或同等显卡
|
||||
* 屏幕分辨率:60Hz 时为 1080p
|
||||
* 外部端口:1 个用于显示的端口(HDMI/DisplayPort/VGA/DVI),3 个用于安装 USB 驱动器、键盘和鼠标的 USB 端口,1 个音频输出端口
|
||||
|
||||
### 如何为Drauger OS提供帮助
|
||||
|
||||
如果你有兴趣,可以通过多种方法来帮助 Drauger OS。他们一直在寻找[财政支持][26]以保持发展。
|
||||
|
||||
如果你想贡献代码,他们正在寻找具有 BASH、C++ 和 Python 经验的人员。他们所有的代码都在 [GitHub][27] 上。你也可以在社交媒体上[联系][28]他们。
|
||||
|
||||
### 结语
|
||||
|
||||
Drauger OS 只是这类项目之一。我还见过其他[面向游戏的发行版][29],但 Drauger OS 在专注于游戏方面一心一意。由于我更喜欢休闲游戏,因此该发行版对我个人而言并不具有吸引力。但是,我可以看到它如何吸引游戏爱好者使用 Linux。祝他们在以后的发行中好运。
|
||||
|
||||
你对这个仅限于游戏的发行版有何想法?你最喜欢的 Linux 游戏解决方案是什么?请在下面的评论中告诉我们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/drauger-os/
|
||||
|
||||
作者:[John Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[校对者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/why-use-linux/
|
||||
[2]: https://itsfoss.com/linux-gaming-guide/
|
||||
[3]: https://itsfoss.com/steam-play-proton/
|
||||
[4]: https://itsfoss.com/steam-play/
|
||||
[5]: https://itsfoss.com/linux-gaming-distributions/
|
||||
[6]: http://www.lakka.tv/
|
||||
[7]: https://itsfoss.com/lakka-retrogaming-linux/
|
||||
[8]: https://draugeros.org/go/
|
||||
[9]: https://www.draugeros.org/go/about/
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/drauger-os-7.4.1.jpg?ssl=1
|
||||
[11]: https://liquorix.net/
|
||||
[12]: https://www.xfce.org/
|
||||
[13]: https://www.playonlinux.com/en/
|
||||
[14]: https://lutris.net/
|
||||
[15]: https://github.com/doitsujin/dxvk
|
||||
[16]: https://github.com/drauger-os-development/drauger-installer
|
||||
[17]: https://github.com/drauger-os-development/mrai
|
||||
[18]: https://github.com/Batcastle
|
||||
[19]: https://anchor.fm/drauger-os/episodes/Episode-23-eapu47
|
||||
[20]: https://en.wikipedia.org/wiki/Draugr
|
||||
[21]: https://anchor.fm/drauger-os
|
||||
[22]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/02/drauger-os-7.5.1.png?ssl=1
|
||||
[23]: https://www.draugeros.org/go/2020/01/20/major-changes-in-drauger-os-7-5-1/
|
||||
[24]: https://github.com/drauger-os-development/system-installer
|
||||
[25]: https://www.draugeros.org/go/system-requirements/
|
||||
[26]: https://www.draugeros.org/go/contribute/
|
||||
[27]: https://github.com/drauger-os-development
|
||||
[28]: https://www.draugeros.org/go/contact-us/
|
||||
[29]: https://itsfoss.com/manjaro-gaming-linux/
|
||||
[30]: https://reddit.com/r/linuxusersgroup
|
Loading…
Reference in New Issue
Block a user