分类 技术 下的文章

我来介绍一下我是如何使用 Python 来节省成本的。

我最近在开一辆烧 93 号汽油的车子。根据汽车制造商的说法,它只需要加 91 号汽油就可以了。然而,在美国只能买到 87 号、89 号、93 号汽油。而我家附近的汽油的物价水平是每增加一号,每加仑就要多付 30 美分,因此如果加 93 号汽油,每加仑就要多花 60 美分。为什么不能节省一些钱呢?

一开始很简单,只需要先加满 93 号汽油,然后在油量表显示油箱半满的时候,用 89 号汽油加满,就得到一整箱 91 号汽油了。但接下来就麻烦了,剩下半箱 91 号汽油加上半箱 93 号汽油,只会变成一箱 92 号汽油,再接下来呢?如果继续算下去,只会越来越混乱。这个时候 Python 就派上用场了。

我的方案是,可以根据汽油的实时状态,不断向油箱中加入 93 号汽油或者 89 号汽油,而最终目标是使油箱内汽油的号数不低于 91。我需要做的是只是通过一些算法来判断新旧汽油混合之后的号数。使用多项式方程或许也可以解决这个问题,但如果使用 Python,好像只需要进行循环就可以了。

#!/usr/bin/env python
# octane.py

o = 93.0
newgas = 93.0   # 这个变量记录上一次加入的汽油号数
i = 1
while i < 21:                   # 20 次迭代 (加油次数)
    if newgas == 89.0:          # 如果上一次加的是 89 号汽油,改加 93 号汽油
        newgas = 93.0
        o = newgas/2 + o/2      # 当油箱半满的时候就加油
    else:                       # 如果上一次加的是 93 号汽油,则改加 89 号汽油
        newgas = 89.0
        o = newgas/2 + o/2      # 当油箱半满的时候就加油
    print str(i) + ': '+ str(o)
    i += 1

在代码中,我首先将变量 o(油箱中的当前混合汽油号数)和变量 newgas(上一次加入的汽油号数)的初始值都设为 93,然后循环 20 次,也就是分别加入 89 号汽油和 93 号汽油一共 20 次,以保持混合汽油号数稳定。

1: 91.0
2: 92.0
3: 90.5
4: 91.75
5: 90.375
6: 91.6875
7: 90.34375
8: 91.671875
9: 90.3359375
10: 91.66796875
11: 90.333984375
12: 91.6669921875
13: 90.3334960938
14: 91.6667480469
15: 90.3333740234
16: 91.6666870117
17: 90.3333435059
18: 91.6666717529
19: 90.3333358765
20: 91.6666679382

从以上数据来看,只需要 10 到 15 次循环,汽油号数就比较稳定了,也相当接近 91 号汽油的目标。这种交替混合直到稳定的现象看起来很有趣,每次交替加入同等量的不同号数汽油,都会趋于稳定。实际上,即使加入的 89 号汽油和 93 号汽油的量不同,也会趋于稳定。

因此,我尝试了不同的比例,我认为加入的 93 号汽油需要比 89 号汽油更多一点。在尽量少补充新汽油的情况下,我最终计算到的结果是 89 号汽油要在油箱大约 7/12 满的时候加进去,而 93 号汽油则要在油箱 ¼ 满的时候才加进去。

我的循环将会更改成这样:

    if newgas == 89.0:            
                                 
        newgas = 93.0
        o = 3*newgas/4 + o/4      
    else:                        
        newgas = 89.0
        o = 5*newgas/12 + 7*o/12

以下是从第十次加油开始的混合汽油号数:

10: 92.5122272978
11: 91.0487992571
12: 92.5121998143
13: 91.048783225
14: 92.5121958062
15: 91.048780887

如你所见,这个调整会令混合汽油号数始终略高于 91。当然,我的油量表并没有 1/12 的刻度,但是 7/12 略小于 5/8,我可以近似地计算。

一个更简单地方案是每次都首先加满 93 号汽油,然后在油箱半满时加入 89 号汽油直到耗尽,这可能会是我的常规方案。就我个人而言,这种方法并不太好,有时甚至会产生一些麻烦。但对于长途旅行来说,这种方案会相对简便一些。有时我也会因为油价突然下跌而购买一些汽油,所以,这个方案是我可以考虑的一系列选项之一。

当然最重要的是:开车不写码,写码不开车!


via: https://opensource.com/article/18/10/python-gas-pump

作者:Greg Pittman 选题:lujun9972 译者:HankChow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这几个工具对复杂软件系统中的实时事件做了可视化,能帮助你快速发现性能问题。

分布式追踪系统能够从头到尾地追踪跨越了多个应用、服务、数据库以及像代理这样的中间件的分布式软件的请求。它能帮助你更深入地理解系统中到底发生了什么。追踪系统以图形化的方式,展示出每个已知步骤以及某个请求在每个步骤上的耗时。

用户可以通过这些展示来判断系统的哪个环节有延迟或阻塞,当请求失败时,运维和开发人员可以看到准确的问题源头,而不需要去测试整个系统,比如用二叉查找树的方法去定位问题。在开发迭代的过程中,追踪系统还能够展示出可能引起性能变化的环节。通过异常行为的警告自动地感知到性能的退化,总是比客户告诉你要好。

这种追踪是怎么工作的呢?给每个请求分配一个特殊 ID,这个 ID 通常会插入到请求头部中。它唯一标识了对应的事务。一般把事务叫做 踪迹 trace ,“踪迹”是整个事务的抽象概念。每一个“踪迹”由 单元 span 组成,“单元”代表着一次请求中真正执行的操作,比如一次服务调用,一次数据库请求等。每一个“单元”也有自己唯一的 ID。“单元”之下也可以创建子“单元”,子“单元”可以有多个父“单元”。

当一次事务(或者说踪迹)运行过之后,就可以在追踪系统的表示层上搜索了。有几个工具可以用作表示层,我们下文会讨论,不过,我们先看下面的图,它是我在 Istio walkthrough 视频教程中提到的 Jaeger 界面,展示了单个踪迹中的多个单元。很明显,这个图能让你一目了然地对事务有更深的了解。

这个演示使用了 Istio 内置的 OpenTracing 实现,所以我甚至不需要修改自己的应用代码就可以获得追踪数据。我也用到了 Jaeger,它是兼容 OpenTracing 的。

那么 OpenTracing 到底是什么呢?我们来看看。

OpenTracing API

OpenTracing 是源自 Zipkin 的规范,以提供跨平台兼容性。它提供了对厂商中立的 API,用来向应用程序添加追踪功能并将追踪数据发送到分布式的追踪系统。按照 OpenTracing 规范编写的库,可以被任何兼容 OpenTracing 的系统使用。采用这个开放标准的开源工具有 Zipkin、Jaeger 和 Appdash 等。甚至像 DatadogInstana 这种付费工具也在采用。因为现在 OpenTracing 已经无处不在,这样的趋势有望继续发展下去。

OpenCensus

OpenTracing 已经说过了,可 OpenCensus 又是什么呢?它在搜索结果中老是出现。它是一个和 OpenTracing 完全不同或者互补的竞争标准吗?

这个问题的答案取决于你的提问对象。我先尽我所能地解释一下它们的不同(按照我的理解):OpenCensus 更加全面或者说它包罗万象。OpenTracing 专注于建立开放的 API 和规范,而不是为每一种开发语言和追踪系统都提供开放的实现。OpenCensus 不仅提供规范,还提供开发语言的实现,和连接协议,而且它不仅只做追踪,还引入了额外的度量指标,这些一般不在分布式追踪系统的职责范围。

使用 OpenCensus,我们能够在运行着应用程序的主机上查看追踪数据,但它也有个可插拔的导出器系统,用于导出数据到中心聚合器。目前 OpenCensus 团队提供的导出器包括 Zipkin、Prometheus、Jaeger、Stackdriver、Datadog 和 SignalFx,不过任何人都可以创建一个导出器。

依我看这两者有很多重叠的部分,没有哪个一定比另外一个好,但是重要的是,要知道它们做什么事情和不做什么事情。OpenTracing 主要是一个规范,具体的实现和独断的设计由其他人来做。OpenCensus 更加独断地为本地组件提供了全面的解决方案,但是仍然需要其他系统做远程的聚合。

可选工具

Zipkin

Zipkin 是最早出现的这类工具之一。 谷歌在 2010 年发表了介绍其内部追踪系统 Dapper 的论文,Twitter 以此为基础开发了 Zipkin。Zipkin 的开发语言 Java,用 Cassandra 或 ElasticSearch 作为可扩展的存储后端,这些选择能满足大部分公司的需求。Zipkin 支持的最低 Java 版本是 Java 6,它也使用了 Thrift 的二进制通信协议,Thrift 在 Twitter 的系统中很流行,现在作为 Apache 项目在托管。

这个系统包括上报器(客户端)、数据收集器、查询服务和一个 web 界面。Zipkin 只传输一个带事务上下文的踪迹 ID 来告知接收者追踪的进行,所以说在生产环境中是安全的。每一个客户端收集到的数据,会异步地传输到数据收集器。收集器把这些单元的数据存到数据库,web 界面负责用可消费的格式展示这些数据给用户。客户端传输数据到收集器有三种方式:HTTP、Kafka 和 Scribe。

Zipkin 社区 还提供了 Brave,一个跟 Zipkin 兼容的 Java 客户端的实现。由于 Brave 没有任何依赖,所以它不会拖累你的项目,也不会使用跟你们公司标准不兼容的库来搞乱你的项目。除 Brave 之外,还有很多其他的 Zipkin 客户端实现,因为 Zipkin 和 OpenTracing 标准是兼容的,所以这些实现也能用到其他的分布式追踪系统中。流行的 Spring 框架中一个叫 Spring Cloud Sleuth 的分布式追踪组件,它和 Zipkin 是兼容的。

Jaeger

Jaeger 来自 Uber,是一个比较新的项目,CNCF(云原生计算基金会)已经把 Jaeger 托管为孵化项目。Jaeger 使用 Golang 开发,因此你不用担心在服务器上安装依赖的问题,也不用担心开发语言的解释器或虚拟机的开销。和 Zipkin 类似,Jaeger 也支持用 Cassandra 和 ElasticSearch 做可扩展的存储后端。Jaeger 也完全兼容 OpenTracing 标准。

Jaeger 的架构跟 Zipkin 很像,有客户端(上报器)、数据收集器、查询服务和一个 web 界面,不过它还有一个在各个服务器上运行着的代理,负责在服务器本地做数据聚合。代理通过一个 UDP 连接接收数据,然后分批处理,发送到数据收集器。收集器接收到的数据是 Thrift 协议的格式,它把数据存到 Cassandra 或者 ElasticSearch 中。查询服务能直接访问数据库,并给 web 界面提供所需的信息。

默认情况下,Jaeger 客户端不会采集所有的追踪数据,只抽样了 0.1% 的( 1000 个采 1 个)追踪数据。对大多数系统来说,保留所有的追踪数据并传输的话就太多了。不过,通过配置代理可以调整这个值,客户端会从代理获取自己的配置。这个抽样并不是完全随机的,并且正在变得越来越好。Jaeger 使用概率抽样,试图对是否应该对新踪迹进行抽样进行有根据的猜测。 自适应采样已经在路线图当中,它将通过添加额外的、能够帮助做决策的上下文来改进采样算法。

Appdash

Appdash 也是一个用 Golang 写的分布式追踪系统,和 Jaeger 一样。Appdash 是 Sourcegraph 公司基于谷歌的 Dapper 和 Twitter 的 Zipkin 开发的。同样的,它也支持 Opentracing 标准,不过这是后来添加的功能,依赖了一个与默认组件不同的组件,因此增加了风险和复杂度。

从高层次来看,Appdash 的架构主要有三个部分:客户端、本地收集器和远程收集器。因为没有很多文档,所以这个架构描述是基于对系统的测试以及查看源码。写代码时需要把 Appdash 的客户端添加进来。Appdash 提供了 Python、Golang 和 Ruby 的实现,不过 OpenTracing 库可以与 Appdash 的 OpenTracing 实现一起使用。 客户端收集单元数据,并将它们发送到本地收集器。然后,本地收集器将数据发送到中心的 Appdash 服务器,这个服务器上运行着自己的本地收集器,它的本地收集器是其他所有节点的远程收集器。


via: https://opensource.com/article/18/9/distributed-tracing-tools

作者:Dan Barker 选题:lujun9972 译者:belitex 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

用自行托管的树莓派 NAS 云盘来保护数据的安全!

在前面两篇文章中,我们讨论了用树莓派搭建一个 NAS 云盘所需要的一些 软硬件环境及其操作步骤。我们还制定了适当的 备份策略 来保护 NAS 上的数据。本文中,我们将介绍讨论利用 Nestcloud 来方便快捷的存储、获取以及分享你的数据。

必要的准备工作

想要方便的使用 Nextcloud,需要一些必要的准备工作。首先,你需要一个指向 Nextcloud 的域名。方便起见,本文将使用 nextcloud.pi-nas.com 。如果你是在家庭网络里运行,你需要为该域名配置 DNS 服务(动态域名解析服务)并在路由器中开启 80 端口和 443 端口转发功能(如果需要使用 https,则需要开启 443 端口转发,如果只用 http,80 端口足以)。

你可以使用 ddclient 在树莓派中自动更新 DNS。

安装 Nextcloud

为了在树莓派(参考 第一篇 中步骤设置)中运行 Nextcloud,首先用命令 apt 安装 以下的一些依赖软件包。

sudo apt install unzip wget php apache2 mysql-server php-zip php-mysql php-dom php-mbstring php-gd php-curl

其次,下载 Nextcloud。在树莓派中利用 wget 下载其 最新的版本。在 第一篇 文章中,我们将两个磁盘驱动器连接到树莓派,一个用于存储当前数据,另一个用于备份。这里在数据存储盘上安装 Nextcloud,以确保每晚自动备份数据。

sudo mkdir -p /nas/data/nextcloud
sudo chown pi /nas/data/nextcloud
cd /nas/data/
wget https://download.nextcloud.com/server/releases/nextcloud-14.0.0.zip -O /nas/data/nextcloud.zip
unzip nextcloud.zip
sudo ln -s /nas/data/nextcloud /var/www/nextcloud
sudo chown -R www-data:www-data /nas/data/nextcloud

截止到写作本文时,Nextcloud 最新版更新到如上述代码中所示的 14.0.0 版本。Nextcloud 正在快速的迭代更新中,所以你可以在你的树莓派中安装更新一点的版本。

配置数据库

如上所述,Nextcloud 安装完毕。之前安装依赖软件包时就已经安装了 MySQL 数据库来存储 Nextcloud 的一些重要数据(例如,那些你创建的可以访问 Nextcloud 的用户的信息)。如果你更愿意使用 Pstgres 数据库,则上面的依赖软件包需要做一些调整。

以 root 权限启动 MySQL:

sudo mysql

这将会打开 SQL 提示符界面,在那里可以插入如下指令——使用数据库连接密码替换其中的占位符——为 Nextcloud 创建一个数据库。

CREATE USER nextcloud IDENTIFIED BY '<这里插入密码>';
CREATE DATABASE nextcloud;
GRANT ALL ON nextcloud.* TO nextcloud;

Ctrl+D 或输入 quit 退出 SQL 提示符界面。

Web 服务器配置

Nextcloud 可以配置以适配于 Nginx 服务器或者其他 Web 服务器运行的环境。但本文中,我决定在我的树莓派 NAS 中运行 Apache 服务器(如果你有其他效果更好的服务器选择方案,不妨也跟我分享一下)。

首先为你的 Nextcloud 域名创建一个虚拟主机,创建配置文件 /etc/apache2/sites-available/001-netxcloud.conf,在其中输入下面的参数内容。修改其中 ServerName 为你的域名。

<VirtualHost *:80>
ServerName nextcloud.pi-nas.com
ServerAdmin [email protected]
DocumentRoot /var/www/nextcloud/

<Directory /var/www/nextcloud/>
AllowOverride None
</Directory>
</VirtualHost>

使用下面的命令来启动该虚拟主机。

a2ensite 001-nextcloud
sudo systemctl reload apache2

现在,你应该可以通过浏览器中输入域名访问到 web 服务器了。这里我推荐使用 HTTPS 协议而不是 HTTP 协议来访问 Nextcloud。一个简单而且免费的方法就是利用 Certbot 下载 Let’s Encrypt 证书,然后设置定时任务自动刷新。这样就避免了自签证书等的麻烦。参考 如何在树莓派中安装 Certbot 。在配置 Certbot 的时候,你甚至可以配置将 HTTP 自动转到 HTTPS ,例如访问 http://nextcloud.pi-nas.com 自动跳转到 https://nextcloud.pi-nas.com。注意,如果你的树莓派 NAS 运行在家庭路由器的下面,别忘了设置路由器的 443 端口和 80 端口转发。

配置 Nextcloud

最后一步,通过浏览器访问 Nextcloud 来配置它。在浏览器中输入域名地址,插入上文中的数据库设置信息。这里,你可以创建 Nextcloud 管理员用户。默认情况下,数据保存目录在在 Nextcloud 目录下,所以你也无需修改我们在 第二篇 一文中设置的备份策略。

然后,页面会跳转到 Nextcloud 登陆界面,用刚才创建的管理员用户登陆。在设置页面中会有基础操作教程和安全安装教程(这里是访问 https://nextcloud.pi-nas.com/settings/admin)。

恭喜你,到此为止,你已经成功在树莓派中安装了你自己的云 Nextcloud。去 Nextcloud 主页 下载 Nextcloud 客户端,客户端可以同步数据并且离线访问服务器。移动端甚至可以上传图片等资源,然后电脑桌面都可以去访问它们。


via: https://opensource.com/article/18/9/host-cloud-nas-raspberry-pi

作者:Manuel Dewald 选题:lujun9972 译者:jrg 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

运行 Minikube 的分步指南。

Hello Minikube 教程页面上 Minikube 被宣传为基于 Docker 运行 Kubernetes 的一种简单方法。 虽然该文档非常有用,但它主要是为 MacOS 编写的。 你可以深入挖掘在 Windows 或某个 Linux 发行版上的使用说明,但它们不是很清楚。 许多文档都是针对 Debian / Ubuntu 用户的,比如安装 Minikube 的驱动程序

这篇指南旨在使得在基于 RHEL/Fedora/CentOS 的操作系统上更容易安装 Minikube。

先决条件

  1. 你已经安装了 Docker
  2. 你的计算机是一个基于 RHEL / CentOS / Fedora 的工作站。
  3. 你已经安装了正常运行的 KVM2 虚拟机管理程序
  4. 你有一个可以工作的 docker-machine-driver-kvm2。 以下命令将安装该驱动程序:
curl -Lo docker-machine-driver-kvm2 https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-kvm2 \
chmod +x docker-machine-driver-kvm2 \
&& sudo cp docker-machine-driver-kvm2 /usr/local/bin/ \
&& rm docker-machine-driver-kvm2

下载、安装和启动Minikube

1、为你要即将下载的两个文件创建一个目录,两个文件分别是:minikubekubectl

2、打开终端窗口并运行以下命令来安装 minikube。

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

请注意,minikube 版本(例如,minikube-linux-amd64)可能因计算机的规格而有所不同。

3、chmod 加执行权限。

chmod +x minikube

4、将文件移动到 /usr/local/bin 路径下,以便你能将其作为命令运行。

mv minikube /usr/local/bin

5、使用以下命令安装 kubectl(类似于 minikube 的安装过程)。

curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl

使用 curl 命令确定最新版本的Kubernetes。

6、chmodkubectl 加执行权限。

chmod +x kubectl

7、将 kubectl 移动到 /usr/local/bin 路径下作为命令运行。

mv kubectl /usr/local/bin

8、 运行 minikube start 命令。 为此,你需要有虚拟机管理程序。 我使用过 KVM2,你也可以使用 Virtualbox。 确保是以普通用户而不是 root 身份运行以下命令,以便为用户而不是 root 存储配置。

minikube start --vm-driver=kvm2

这可能需要一段时间,等一会。

9、 Minikube 应该下载并启动。 使用以下命令确保成功。

cat ~/.kube/config

10、 执行以下命令以运行 Minikube 作为上下文环境。 上下文环境决定了 kubectl 与哪个集群交互。 你可以在 ~/.kube/config 文件中查看所有可用的上下文环境。

kubectl config use-context minikube

11、再次查看 config 文件以检查 Minikube 是否存在上下文环境。

cat ~/.kube/config

12、最后,运行以下命令打开浏览器查看 Kubernetes 仪表板。

minikube dashboard

现在 Minikube 已启动并运行,请阅读通过 Minikube 在本地运行 Kubernetes 这篇官网教程开始使用它。


via: https://opensource.com/article/18/10/getting-started-minikube

作者:Bryant Son 选题:lujun9972 译者:Flowsnow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 Python behave 框架的行为驱动开发模式可以帮助你的团队更好的协作和测试自动化。

您是否听说过 行为驱动开发 behavior-driven development (BDD),并好奇这是个什么东西?也许你发现了团队成员在谈论“嫩瓜”(LCTT 译注:“ 嫩瓜 gherkin ” 是一种简单的英语文本语言,工具 cucumber 通过解释它来执行测试脚本,见下文),而你却不知所云。或许你是一个 Python 人 Pythonista ,正在寻找更好的方法来测试你的代码。 无论在什么情况下,了解 BDD 都可以帮助您和您的团队实现更好的协作和测试自动化,而 Python 的 behave 框架是一个很好的起点。

什么是 BDD?

在软件中,行为是指在明确定义的输入、动作和结果场景中功能是如何运转的。 产品可以表现出无数的行为,例如:

  • 在网站上提交表单
  • 搜索想要的结果
  • 保存文档
  • 进行 REST API 调用
  • 运行命令行界面命令

根据产品的行为定义产品的功能可以更容易地描述产品,并对其进行开发和测试。 BDD 的核心是:使行为成为软件开发的焦点。在开发早期使用示例语言的规范来定义行为。最常见的行为规范语言之一是 Gherkin,Cucumber项目中的Given-When-Then场景格式。 行为规范基本上是对行为如何工作的简单语言描述,具有一致性和焦点的一些正式结构。 通过将步骤文本“粘合”到代码实现,测试框架可以轻松地自动化这些行为规范。

下面是用Gherkin编写的行为规范的示例:

根据产品的行为定义产品的功能可以更容易地描述产品,开发产品并对其进行测试。 这是BDD的核心:使行为成为软件开发的焦点。 在开发早期使用示例规范的语言来定义行为。 最常见的行为规范语言之一是Gherkin,来自 Cucumber 项目中的 Given-When-Then 场景格式。 行为规范基本上是对行为如何工作的简单语言描述,具有一致性和聚焦点的一些正式结构。 通过将步骤文本“粘合”到代码实现,测试框架可以轻松地自动化这些行为规范。

下面是用 Gherkin 编写的行为规范的示例:

Scenario: Basic DuckDuckGo Search
  Given the DuckDuckGo home page is displayed
  When the user searches for "panda"
  Then results are shown for "panda"

快速浏览一下,行为是直观易懂的。 除少数关键字外,该语言为自由格式。 场景简洁而有意义。 一个真实的例子说明了这种行为。 步骤以声明的方式表明应该发生什么——而不会陷入如何如何的细节中。

BDD 的主要优点是良好的协作和自动化。 每个人都可以为行为开发做出贡献,而不仅仅是程序员。从流程开始就定义并理解预期的行为。测试可以与它们涵盖的功能一起自动化。每个测试都包含一个单一的、独特的行为,以避免重复。最后,现有的步骤可以通过新的行为规范重用,从而产生雪球效果。

Python 的 behave 框架

behave 是 Python 中最流行的 BDD 框架之一。 它与其他基于 Gherkin 的 Cucumber 框架非常相似,尽管没有得到官方的 Cucumber 定名。 behave 有两个主要层:

  1. 用 Gherkin 的 .feature 文件编写的行为规范
  2. 用 Python 模块编写的步骤定义和钩子,用于实现 Gherkin 步骤

如上例所示,Gherkin 场景有三部分格式:

  1. 鉴于(Given)一些初始状态
  2. 每当(When)行为发生时
  3. 然后(Then)验证结果

当 behave 运行测试时,每个步骤由装饰器“粘合”到 Python 函数。

安装

作为先决条件,请确保在你的计算机上安装了 Python 和 pip。 我强烈建议使用 Python 3.(我还建议使用 pipenv,但以下示例命令使用更基本的 pip。)

behave 框架只需要一个包:

pip install behave

其他包也可能有用,例如:

pip install requests    # 用于调用 REST API
pip install selenium    # 用于 web 浏览器交互

GitHub 上的 behavior-driven-Python 项目包含本文中使用的示例。

Gherkin 特点

behave 框架使用的 Gherkin 语法实际上是符合官方的 Cucumber Gherkin 标准的。.feature 文件包含了功能(Feature)部分,而场景部分又包含具有 Given-When-Then 步骤的场景(Scenario) 部分。 以下是一个例子:

Feature: Cucumber Basket
  As a gardener,
  I want to carry many cucumbers in a basket,
  So that I don’t drop them all.

  @cucumber-basket
  Scenario: Add and remove cucumbers
    Given the basket is empty
    When "4" cucumbers are added to the basket
    And "6" more cucumbers are added to the basket
    But "3" cucumbers are removed from the basket
    Then the basket contains "7" cucumbers

这里有一些重要的事情需要注意:

  • FeatureScenario 部分都有简短的描述性标题
  • 紧跟在 Feature 标题后面的行是会被 behave 框架忽略掉的注释。将功能描述放在那里是一种很好的做法。
  • ScenarioFeature 可以有标签(注意 @cucumber-basket 标记)用于钩子和过滤(如下所述)。
  • 步骤都遵循严格的 Given-When-Then 顺序
  • 使用 AndBut 可以为任何类型添加附加步骤。
  • 可以使用输入对步骤进行参数化——注意双引号里的值。

通过使用场景大纲(Scenario Outline),场景也可以写为具有多个输入组合的模板:

Feature: Cucumber Basket

  @cucumber-basket
  Scenario Outline: Add cucumbers
    Given the basket has “<initial>” cucumbers
    When "<more>" cucumbers are added to the basket
    Then the basket contains "<total>" cucumbers

    Examples: Cucumber Counts
      | initial | more | total |
      |    0    |   1  |   1   |
      |    1    |   2  |   3   |
      |    5    |   4  |   9   |

场景大纲总是有一个示例(Examples)表,其中第一行给出列标题,后续每一行给出一个输入组合。 只要列标题出现在由尖括号括起的步骤中,行值就会被替换。 在上面的示例中,场景将运行三次,因为有三行输入组合。 场景大纲是避免重复场景的好方法。

Gherkin 语言还有其他元素,但这些是主要的机制。 想了解更多信息,请阅读 Automation Panda 这个网站的文章 Gherkin by ExampleWriting Good Gherkin

Python 机制

每个 Gherkin 步骤必须“粘合”到步骤定义——即提供了实现的 Python 函数。 每个函数都有一个带有匹配字符串的步骤类型装饰器。它还接收共享的上下文和任何步骤参数。功能文件必须放在名为 features/ 的目录中,而步骤定义模块必须放在名为 features/steps/ 的目录中。 任何功能文件都可以使用任何模块中的步骤定义——它们不需要具有相同的名称。 下面是一个示例 Python 模块,其中包含 cucumber basket 功能的步骤定义。

from behave import *
from cucumbers.basket import CucumberBasket

@given('the basket has "{initial:d}" cucumbers')
def step_impl(context, initial):
    context.basket = CucumberBasket(initial_count=initial)

@when('"{some:d}" cucumbers are added to the basket')
def step_impl(context, some):
    context.basket.add(some)

@then('the basket contains "{total:d}" cucumbers')
def step_impl(context, total):
    assert context.basket.count == total

可以使用三个步骤匹配器parsecfparsere。默认的,也是最简单的匹配器是 parse,如上例所示。注意如何解析参数化值并将其作为输入参数传递给函数。一个常见的最佳实践是在步骤中给参数加双引号。

每个步骤定义函数还接收一个上下文变量,该变量保存当前正在运行的场景的数据,例如 featurescenariotags 字段。也可以添加自定义字段,用于在步骤之间共享数据。始终使用上下文来共享数据——永远不要使用全局变量!

behave 框架还支持钩子来处理 Gherkin 步骤之外的自动化问题。钩子是一个将在步骤、场景、功能或整个测试套件之前或之后运行的功能。钩子让人联想到面向方面的编程。它们应放在 features/ 目录下的特殊 environment.py 文件中。钩子函数也可以检查当前场景的标签,因此可以有选择地应用逻辑。下面的示例显示了如何使用钩子为标记为 @web 的任何场景生成和销毁一个 Selenium WebDriver 实例。

from selenium import webdriver

def before_scenario(context, scenario):
    if 'web' in context.tags:
        context.browser = webdriver.Firefox()
        context.browser.implicitly_wait(10)

def after_scenario(context, scenario):
    if 'web' in context.tags:
        context.browser.quit()

注意:也可以使用 fixtures 进行构建和清理。

要了解一个 behave 项目应该是什么样子,这里是示例项目的目录结构:

任何 Python 包和自定义模块都可以与 behave 框架一起使用。 使用良好的设计模式构建可扩展的测试自动化解决方案。步骤定义代码应简明扼要。

运行测试

要从命令行运行测试,请切换到项目的根目录并运行 behave 命令。 使用 -help 选项查看所有可用选项。

以下是一些常见用例:

# run all tests
behave

# run the scenarios in a feature file
behave features/web.feature

# run all tests that have the @duckduckgo tag
behave --tags @duckduckgo

# run all tests that do not have the @unit tag
behave --tags ~@unit

# run all tests that have @basket and either @add or @remove
behave --tags @basket --tags @add,@remove

为方便起见,选项可以保存在 config 文件中。

其他选择

behave 不是 Python 中唯一的 BDD 测试框架。其他好的框架包括:

  • pytest-bdd,是 pytest 的插件,和 behave 一样,它使用 Gherkin 功能文件和步骤定义模块,但它也利用了 pytest 的所有功能和插件。例如,它可以使用 pytest-xdist 并行运行 Gherkin 场景。 BDD 和非 BDD 测试也可以与相同的过滤器一起执行。pytest-bdd 还提供更灵活的目录布局。
  • radish 是一个 “Gherkin 增强版”框架——它将场景循环和前提条件添加到标准的 Gherkin 语言中,这使得它对程序员更友好。它还像 behave 一样提供了丰富的命令行选项。
  • lettuce 是一种较旧的 BDD 框架,与 behave 非常相似,在框架机制方面存在细微差别。然而,GitHub 最近显示该项目的活动很少(截至2018 年 5 月)。

任何这些框架都是不错的选择。

另外,请记住,Python 测试框架可用于任何黑盒测试,即使对于非 Python 产品也是如此! BDD 框架非常适合 Web 和服务测试,因为它们的测试是声明性的,而 Python 是一种很好的测试自动化语言

本文基于作者的 PyCon Cleveland 2018 演讲“行为驱动的Python”。


via: https://opensource.com/article/18/5/behavior-driven-python

作者:Andrew Knight 选题:lujun9972 译者:Flowsnow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在编辑或修改配置文件或旧文件前,我经常会把它们备份到硬盘的某个地方,因此我如果意外地改错了这些文件,我可以从备份中恢复它们。但问题是如果我忘记清理备份文件,一段时间之后,我的磁盘会被这些大量重复文件填满 —— 我觉得要么是懒得清理这些旧文件,要么是担心可能会删掉重要文件。如果你们像我一样,在类 Unix 操作系统中,大量多版本的相同文件放在不同的备份目录,你可以使用下面的工具找到并删除重复文件。

提醒一句:

在删除重复文件的时请尽量小心。如果你不小心,也许会导致意外丢失数据。我建议你在使用这些工具的时候要特别注意。

在 Linux 中找到并删除重复文件

出于本指南的目的,我将讨论下面的三个工具:

  1. Rdfind
  2. Fdupes
  3. FSlint

这三个工具是自由开源的,且运行在大多数类 Unix 系统中。

1. Rdfind

Rdfind 意即 redundant data find(冗余数据查找),是一个通过访问目录和子目录来找出重复文件的自由开源的工具。它是基于文件内容而不是文件名来比较。Rdfind 使用排序算法来区分原始文件和重复文件。如果你有两个或者更多的相同文件,Rdfind 会很智能的找到原始文件并认定剩下的文件为重复文件。一旦找到副本文件,它会向你报告。你可以决定是删除还是使用硬链接或者符号(软)链接代替它们。

安装 Rdfind

Rdfind 存在于 AUR 中。因此,在基于 Arch 的系统中,你可以像下面一样使用任一如 Yay AUR 程序助手安装它。

$ yay -S rdfind

在 Debian、Ubuntu、Linux Mint 上:

$ sudo apt-get install rdfind

在 Fedora 上:

$ sudo dnf install rdfind

在 RHEL、CentOS 上:

$ sudo yum install epel-release
$ sudo yum install rdfind

用法

一旦安装完成,仅带上目录路径运行 Rdfind 命令就可以扫描重复文件。

$ rdfind ~/Downloads

正如你看到上面的截屏,Rdfind 命令将扫描 ~/Downloads 目录,并将结果存储到当前工作目录下一个名为 results.txt 的文件中。你可以在 results.txt 文件中看到可能是重复文件的名字。

$ cat results.txt
# Automatically generated
# duptype id depth size device inode priority name
DUPTYPE_FIRST_OCCURRENCE 1469 8 9 2050 15864884 1 /home/sk/Downloads/tor-browser_en-US/Browser/TorBrowser/Tor/PluggableTransports/fte/tests/dfas/test5.regex
DUPTYPE_WITHIN_SAME_TREE -1469 8 9 2050 15864886 1 /home/sk/Downloads/tor-browser_en-US/Browser/TorBrowser/Tor/PluggableTransports/fte/tests/dfas/test6.regex
[...]
DUPTYPE_FIRST_OCCURRENCE 13 0 403635 2050 15740257 1 /home/sk/Downloads/Hyperledger(1).pdf
DUPTYPE_WITHIN_SAME_TREE -13 0 403635 2050 15741071 1 /home/sk/Downloads/Hyperledger.pdf
# end of file

通过检查 results.txt 文件,你可以很容易的找到那些重复文件。如果愿意你可以手动的删除它们。

此外,你可在不修改其他事情情况下使用 -dryrun 选项找出所有重复文件,并在终端上输出汇总信息。

$ rdfind -dryrun true ~/Downloads

一旦找到重复文件,你可以使用硬链接或符号链接代替他们。

使用硬链接代替所有重复文件,运行:

$ rdfind -makehardlinks true ~/Downloads

使用符号链接/软链接代替所有重复文件,运行:

$ rdfind -makesymlinks true ~/Downloads

目录中有一些空文件,也许你想忽略他们,你可以像下面一样使用 -ignoreempty 选项:

$ rdfind -ignoreempty true ~/Downloads

如果你不再想要这些旧文件,删除重复文件,而不是使用硬链接或软链接代替它们。

删除重复文件,就运行:

$ rdfind -deleteduplicates true ~/Downloads

如果你不想忽略空文件,并且和所哟重复文件一起删除。运行:

$ rdfind -deleteduplicates true -ignoreempty false ~/Downloads

更多细节,参照帮助部分:

$ rdfind --help

手册页:

$ man rdfind

2. Fdupes

Fdupes 是另一个在指定目录以及子目录中识别和移除重复文件的命令行工具。这是一个使用 C 语言编写的自由开源工具。Fdupes 通过对比文件大小、部分 MD5 签名、全部 MD5 签名,最后执行逐个字节对比校验来识别重复文件。

与 Rdfind 工具类似,Fdupes 附带非常少的选项来执行操作,如:

  • 在目录和子目录中递归的搜索重复文件
  • 从计算中排除空文件和隐藏文件
  • 显示重复文件大小
  • 出现重复文件时立即删除
  • 使用不同的拥有者/组或权限位来排除重复文件
  • 更多

安装 Fdupes

Fdupes 存在于大多数 Linux 发行版的默认仓库中。

在 Arch Linux 和它的变种如 Antergos、Manjaro Linux 上,如下使用 Pacman 安装它。

$ sudo pacman -S fdupes

在 Debian、Ubuntu、Linux Mint 上:

$ sudo apt-get install fdupes

在 Fedora 上:

$ sudo dnf install fdupes

在 RHEL、CentOS 上:

$ sudo yum install epel-release
$ sudo yum install fdupes

用法

Fdupes 用法非常简单。仅运行下面的命令就可以在目录中找到重复文件,如:~/Downloads

$ fdupes ~/Downloads

我系统中的样例输出:

/home/sk/Downloads/Hyperledger.pdf
/home/sk/Downloads/Hyperledger(1).pdf

你可以看到,在 /home/sk/Downloads/ 目录下有一个重复文件。它仅显示了父级目录中的重复文件。如何显示子目录中的重复文件?像下面一样,使用 -r 选项。

$ fdupes -r ~/Downloads

现在你将看到 /home/sk/Downloads/ 目录以及子目录中的重复文件。

Fdupes 也可用来从多个目录中迅速查找重复文件。

$ fdupes ~/Downloads ~/Documents/ostechnix

你甚至可以搜索多个目录,递归搜索其中一个目录,如下:

$ fdupes ~/Downloads -r ~/Documents/ostechnix

上面的命令将搜索 ~/Downloads 目录,~/Documents/ostechnix 目录和它的子目录中的重复文件。

有时,你可能想要知道一个目录中重复文件的大小。你可以使用 -S 选项,如下:

$ fdupes -S ~/Downloads
403635 bytes each:
/home/sk/Downloads/Hyperledger.pdf
/home/sk/Downloads/Hyperledger(1).pdf

类似的,为了显示父目录和子目录中重复文件的大小,使用 -Sr 选项。

我们可以在计算时分别使用 -n-A 选项排除空白文件以及排除隐藏文件。

$ fdupes -n ~/Downloads
$ fdupes -A ~/Downloads

在搜索指定目录的重复文件时,第一个命令将排除零长度文件,后面的命令将排除隐藏文件。

汇总重复文件信息,使用 -m 选项。

$ fdupes -m ~/Downloads
1 duplicate files (in 1 sets), occupying 403.6 kilobytes

删除所有重复文件,使用 -d 选项。

$ fdupes -d ~/Downloads

样例输出:

[1] /home/sk/Downloads/Hyperledger Fabric Installation.pdf
[2] /home/sk/Downloads/Hyperledger Fabric Installation(1).pdf

Set 1 of 1, preserve files [1 - 2, all]:

这个命令将提示你保留还是删除所有其他重复文件。输入任一号码保留相应的文件,并删除剩下的文件。当使用这个选项的时候需要更加注意。如果不小心,你可能会删除原文件。

如果你想要每次保留每个重复文件集合的第一个文件,且无提示的删除其他文件,使用 -dN 选项(不推荐)。

$ fdupes -dN ~/Downloads

当遇到重复文件时删除它们,使用 -I 标志。

$ fdupes -I ~/Downloads

关于 Fdupes 的更多细节,查看帮助部分和 man 页面。

$ fdupes --help
$ man fdupes

3. FSlint

FSlint 是另外一个查找重复文件的工具,有时我用它去掉 Linux 系统中不需要的重复文件并释放磁盘空间。不像另外两个工具,FSlint 有 GUI 和 CLI 两种模式。因此对于新手来说它更友好。FSlint 不仅仅找出重复文件,也找出坏符号链接、坏名字文件、临时文件、坏的用户 ID、空目录和非精简的二进制文件等等。

安装 FSlint

FSlint 存在于 AUR,因此你可以使用任一 AUR 助手安装它。

$ yay -S fslint

在 Debian、Ubuntu、Linux Mint 上:

$ sudo apt-get install fslint

在 Fedora 上:

$ sudo dnf install fslint

在 RHEL,CentOS 上:

$ sudo yum install epel-release
$ sudo yum install fslint

一旦安装完成,从菜单或者应用程序启动器启动它。

FSlint GUI 展示如下:

如你所见,FSlint 界面友好、一目了然。在 “Search path” 栏,添加你要扫描的目录路径,点击左下角 “Find” 按钮查找重复文件。验证递归选项可以在目录和子目录中递归的搜索重复文件。FSlint 将快速的扫描给定的目录并列出重复文件。

从列表中选择那些要清理的重复文件,也可以选择 “Save”、“Delete”、“Merge” 和 “Symlink” 操作他们。

在 “Advanced search parameters” 栏,你可以在搜索重复文件的时候指定排除的路径。

FSlint 命令行选项

FSlint 提供下面的 CLI 工具集在你的文件系统中查找重复文件。

  • findup — 查找重复文件
  • findnl — 查找名称规范(有问题的文件名)
  • findu8 — 查找非法的 utf8 编码的文件名
  • findbl — 查找坏链接(有问题的符号链接)
  • findsn — 查找同名文件(可能有冲突的文件名)
  • finded — 查找空目录
  • findid — 查找死用户的文件
  • findns — 查找非精简的可执行文件
  • findrs — 查找文件名中多余的空白
  • findtf — 查找临时文件
  • findul — 查找可能未使用的库
  • zipdir — 回收 ext2 目录项下浪费的空间

所有这些工具位于 /usr/share/fslint/fslint/fslint 下面。

例如,在给定的目录中查找重复文件,运行:

$ /usr/share/fslint/fslint/findup ~/Downloads/

类似的,找出空目录命令是:

$ /usr/share/fslint/fslint/finded ~/Downloads/

获取每个工具更多细节,例如:findup,运行:

$ /usr/share/fslint/fslint/findup --help

关于 FSlint 的更多细节,参照帮助部分和 man 页。

$ /usr/share/fslint/fslint/fslint --help
$ man fslint
总结

现在你知道在 Linux 中,使用三个工具来查找和删除不需要的重复文件。这三个工具中,我经常使用 Rdfind。这并不意味着其他的两个工具效率低下,因为到目前为止我更喜欢 Rdfind。好了,到你了。你的最喜欢哪一个工具呢?为什么?在下面的评论区留言让我们知道吧。

就到这里吧。希望这篇文章对你有帮助。更多的好东西就要来了,敬请期待。

谢谢!


via: https://www.ostechnix.com/how-to-find-and-delete-duplicate-files-in-linux/

作者:SK 选题:lujun9972 译者:pygmalion666 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出