2018年12月

创建这样一个脚本,当指定的设备插入时触发你的计算机去做一个指定动作。

udev 是一个为你的计算机提供设备事件的 Linux 子系统。通俗来讲就是,当你的计算机上插入了像网卡、外置硬盘(包括 U 盘)、鼠标、键盘、游戏操纵杆和手柄、DVD-ROM 驱动器等等设备时,代码能够检测到它们。这样就能写出很多可能非常有用的实用程序,而它已经很好了,普通用户就可以写出脚本去做一些事情,比如当某个硬盘驱动器插入时,执行某个任务。

这篇文章教你去如何写一个由一些 udev 事件触发的 udev 脚本,比如插入了一个 U 盘。当你理解了 udev 的工作原理,你就可以用它去做各种事情,比如当一个游戏手柄连接后加载一个指定的驱动程序,或者当你用于备份的驱动器连接后,自动执行备份工作。

一个初级的脚本

使用 udev 的最佳方式是从一个小的代码块开始。不要指望从一开始就写出完整的脚本,而是从最简单的确认 udev 触发了某些指定的事件开始。

对于你的脚本,依据你的目标,并不是在任何情况下都能保证你亲眼看到你的脚本运行结果的,因此需要在你的脚本日志中确认它成功触发了。而日志文件通常放在 /var 目录下,但那个目录通常是 root 用户的领地。对于测试目的,可以使用 /tmp,它可以被普通用户访问并且在重启动后就被清除了。

打开你喜欢的文本编辑器,然后输入下面的简单脚本:

#!/usr/bin/bash

echo $date > /tmp/udev.log

把这个脚本放在 /usr/local/bin 或缺省可运行路径的位置中。将它命名为 trigger.sh,并运行 chmod +x 授予可运行权限:

$ sudo mv trigger.sh /usr/local/bin
$ sudo chmod +x /usr/local/bin/trigger.sh

这个脚本没有任何和 udev 有关的事情。当它运行时,这个脚本将在文件 /tmp/udev.log 中放入当前的时间戳。你可以自己测试一下这个脚本:

$ /usr/local/bin/trigger.sh
$ cat /tmp/udev.log
Tue Oct 31 01:05:28 NZDT 2035

接下来让 udev 去触发这个脚本。

唯一设备识别

为了让你的脚本能够被一个设备事件触发,udev 必须要知道在什么情况下调用该脚本。在现实中,你可以通过它的颜色、制造商、以及插入到你的计算机这一事实来识别一个 U 盘。而你的计算机,它需要一系列不同的标准。

udev 通过序列号、制造商、以及提供商 ID 和产品 ID 号来识别设备。由于现在你的 udev 脚本还处于它的生命周期的早期阶段,因此要尽可能地宽泛、非特定和包容。换句话说就是,你希望首先去捕获尽可能多的有效 udev 事件来触发你的脚本。

使用 udevadm monitor 命令你可以实时利用 udev,并且可以看到当你插入不同设备时发生了什么。用 root 权限试一试。

$ su
# udevadm monitor

该监视函数输出接收到的事件:

  • UDEV:在规则处理之后发出 udev 事件
  • KERNEL:内核发送 uevent 事件

udevadm monitor 命令运行时,插入一个 U 盘,你将看到各种信息在你的屏幕上滚动而出。注意那一个 ADD 事件的事件类型。这是你所需要的识别事件类型的一个好方法。

udevadm monitor 命令提供了许多很好的信息,但是你可以使用 udevadm info 命令以更好看的格式来看到它,假如你知道你的 U 盘当前已经位于你的 /dev 树。如果不在这个树下,拔下它并重新插入,然后立即运行这个命令:

$ su -c 'dmesg | tail | fgrep -i sd*'

举例来说,如果那个命令返回 sdb: sdb1,说明内核已经给你的 U 盘分配了 sdb 卷标。

或者,你可以使用 lsblk 命令去查看所有连接到你的系统上的驱动器,包括它的大小和分区。

现在,你的驱动器已经处于你的文件系统中了,你可以使用下面的命令去查看那个设备的相关 udev 信息:

# udevadm info -a -n /dev/sdb | less

这个命令将返回许多信息。现在我们只关心信息中的第一个块。

你的任务是从 udev 的报告中找出能唯一标识那个设备的部分,然后当计算机检测到这些唯一属性时,告诉 udev 去触发你的脚本。

udevadm info 命令处理一个(由设备路径指定的)设备上的报告,接着“遍历”父级设备链。对于找到的大多数设备,它以一个“键值对”格式输出所有可能的属性。你可以写一个规则,从一个单个的父级设备属性上去匹配插入设备的属性。

looking at device '/devices/000:000/blah/blah//block/sdb':
  KERNEL=="sdb"
  SUBSYSTEM=="block"
  DRIVER==""
  ATTR{ro}=="0"
  ATTR{size}=="125722368"
  ATTR{stat}==" 2765 1537 5393"
  ATTR{range}=="16"
  ATTR{discard\_alignment}=="0"
  ATTR{removable}=="1"
  ATTR{blah}=="blah"

一个 udev 规则必须包含来自单个父级设备的一个属性。

父级属性是描述一个设备的最基本的东西,比如它是插入到一个物理端口的东西、或是一个容量多大的东西、或这是一个可移除的设备。

由于 KERNEL 卷标 sdb 可能会由于分配给在它之前插入的其它驱动器而发生变化,因此卷标并不是一个 udev 规则的父级属性的好选择。但是,在做概念论证时你可以使用它。一个事件的最佳候选者是 SUBSYSTEM 属性,它表示那个设备是一个 “block” 系统设备(也就是为什么我们要使用 lsblk 命令来列出设备的原因)。

/etc/udev/rules.d 目录中打开一个名为 80-local.rules 的文件,然后输入如下代码:

SUBSYSTEM=="block", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"

保存文件,拔下你的测试 U 盘,然后重启动系统。

等等,重启动 Linux 机器?

理论上说,你只需要运行 udevadm control —reload 即可,它将重新加载所有规则,但是在我们实验的现阶段,最好要排除可能影响实验结果的所有因素。udev 是非常复杂的,为了不让你躺在床上整晚都在思考为什么这个规则不能正常工作,是因为语法错误吗?还是应该重启动一下。所以,不管 POSIX 自负地告诉你过什么,你都应该去重启动一下。

当你的系统重启动完毕之后,(使用 Ctl+Alt+F3 或类似快捷键)切换到一个文本控制台,并插入你的 U 盘。如果你运行了一个最新的内核,当你插入 U 盘后你或许可以看到一大堆输出。如果看到一个错误信息,比如 “Could not execute /usr/local/bin/trigger.sh”,或许是因为你忘了授予这个脚本可运行的权限。否则你将看到的是,一个设备插入,它得到内核设备分配的一些东西,等等。

现在,见证奇迹的时刻到了。

$ cat /tmp/udev.log
Tue Oct 31 01:35:28 NZDT 2035

如果你在 /tmp/udev.log 中看到了最新的日期和时间,那么说明 udev 已经成功触发了你的脚本。

改进规则做一些有用的事情

现在的问题是使用的规则太通用了。插入一个鼠标、一个 U 盘、或某个人的 U 盘都将盲目地触发这个脚本。现在,我们开始专注于希望触发你的脚本的是确定的某个 U 盘。

实现上述目标的一种方式是使用提供商 ID 和产品 ID。你可以使用 lsusb 命令去得到这些数字。

$ lsusb
Bus 001 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 002 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 003 Device 005: ID 03f0:3307 TyCoon Corp.
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 hub
Bus 001 Device 003: ID 13d3:5165 SBo Networks

在这个例子中,TyCoon Corp 前面的 03f0:3307 就表示了提供商 ID 和产品 ID 的属性。你也可以通过 udevadm info -a -n /dev/sdb | grep vendor 的输出来查看这些数字,但是从 lsusb 的输出中可以很容易地一眼找到这些数字。

现在,可以在你的脚本中包含这些属性了。

SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/thumb.sh"

测试它(是的,为了确保不会有来自 udev 的影响因素,我们仍然建议先重新启动一下),它应该会像前面一样工作,现在,如果你插入一个不同公司制造的 U 盘(因为它们的提供商 ID 不一样)、或插入一个鼠标、或插入一个打印机,这个脚本将不会被触发。

继续添加新属性来进一步专注于你希望去触发你的脚本的那个唯一的 U 盘。使用 udevadm info -a -n /dev/sdb 命令,你可以找出像提供商名字、序列号、或产品名这样的东西。

为了保证思路清晰,确保每次只添加一个新属性。我们(和在网上看到的其他人)在 udev 规则中所遇到的大多数错误都是因为一次添加了太多的属性,而奇怪为什么不能正常工作了。逐个测试属性是最安全的作法,这样可以确保 udev 能够成功识别到你的设备。

安全

编写 udev 规则当插入一个驱动器后自动去做一些事情,将带来安全方面的担忧。在我的机器上,我甚至都没有打开自动挂载功能,而基于本文的目的,当设备插入时,脚本和规则可以运行一些命令来做一些事情。

在这里需要记住两个事情。

  1. 聚焦于你的 udev 规则,当你真实地使用它们时,一旦让规则发挥作用将触发脚本。执行一个脚本去盲目地复制数据到你的计算上,或从你的计算机上复制出数据,是一个很糟糕的主意,因为有可能会遇到一个人拿着和你相同品牌的 U 盘插入到你的机器上的情况。
  2. 不要在写了 udev 规则和脚本后忘记了它们的存在。我知道哪个计算上有我的 udev 规则,这些机器一般是我的个人计算机,而不是那些我带着去开会或办公室工作的计算机。一台计算机的 “社交” 程度越高,它就越不能有 udev 规则存在于它上面,因为它将潜在地导致我的数据最终可能会出现在某个人的设备、或某个人的数据中、或在我的设备上出现恶意程序。

换句话说就是,随着一个 GNU 系统提供了一个这么强大的功能,你的任务是小心地如何使用它们的强大功能。如果你滥用它或不小心谨慎地使用它,最终将让你出问题,它非常可能会导致可怕的问题。

现实中的 Udev

现在,你可以确认你的脚本是由 udev 触发的,那么,可以将你的关注点转到脚本功能上了。到目前为止,这个脚本是没有用的,它除了记录脚本已经运行过了这一事实外,再没有做更多的事情。

我使用 udev 去触发我的 U 盘的 自动备份 。这个创意是,将我正在处理的文档的主副本保存在我的 U 盘上(因为我随身带着它,这样就可以随时处理它),并且在我每次将 U 盘插入到那台机器上时,这些主文档将备份回我的计算机上。换句话说就是,我的计算机是备份驱动器,而产生的数据是移动的。源代码是可用的,你可以随意查看 attachup 的代码,以进一步限制你的 udev 的测试示例。

虽然我使用 udev 最多的情况就是这个例子,但是 udev 能抓取很多的事件,像游戏手柄(当连接游戏手柄时,让系统去加载 xboxdrv 模块)、摄像头、麦克风(当指定的麦克风连接时用于去设置输入),所以应该意识到,它能做的事情远比这个示例要多。

我的备份系统的一个简化版本是由两个命令组成的一个过程:

SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", SYMLINK+="safety%n"
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"

第一行使用属性去检测我的 U 盘,这在前面已经讨论过了,接着在设备树中为我的 U 盘分配一个符号链接,给它分配的符号连接是 safety%n。这个 %n 是一个 udev 宏,它是内核分配给这个设备的任意数字,比如 sdb1、sdb2、sdb3、等等。因此 %n 应该是 1 或 2 或 3。

这将在 dev 树中创建一个符号链接,因此它不会干涉插入一个设备的正常过程。这意味着,如果你在自动挂载设备的桌面环境中使用它,将不会出现问题。

第二行运行这个脚本。

我的备份脚本如下:

#!/usr/bin/bash

mount /dev/safety1 /mnt/hd
sleep 2
rsync -az /mnt/hd/ /home/seth/backups/ && umount /dev/safety1

这个脚本使用符号链接,这将避免出现 udev 命名导致的意外情况(例如,假设一个命名为 DISK 的 U 盘已经插入到我的计算机上,而我插入的其它 U 盘恰好名字也是 DISK,那么第二个 U 盘的卷标将被命名为 DISK_,这将导致我的脚本不会正常运行),它在我喜欢的挂载点 /mnt/hd 上挂载了 safety1(驱动器的第一个分区)。

一旦 safely 挂载之后,它将使用 rsync 将驱动器备份到我的备份文件夹(我真实使用的脚本用的是 rdiff-backup,而你可以使用任何一个你喜欢的自动备份解决方案)。

udev 让你的设备你做主

udev 是一个非常灵活的系统,它可以让你用其它系统很少敢提供给用户的方式去定义规则和功能。学习它,使用它,去享受 POSIX 的强大吧。

本文内容来自 Slackermedia Handbook,它以 GNU Free Documentation License 1.3 许可证授权使用。


via: https://opensource.com/article/18/11/udev

作者:Seth Kenlon 选题:lujun9972 译者:qhwdw 校对:wxy

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

现在,大多数公司都试图将它们的 IT 基础设施和电信设施迁移到私有云, 如 OpenStack。如果你打算面试 OpenStack 管理员这个岗位,那么下面列出的这些面试问题可能会帮助你通过面试。

Q:1 说一下 OpenStack 及其主要组件?

答: OpenStack 是一系列开源软件,这些软件组成了一个云供给软件,也就是 OpenStack,意即开源软件或项目栈。

下面是 OpenStack 的主要关键组件:

  • Nova – 用于在计算级别管理虚拟机,并在计算或管理程序级别执行其他计算任务。
  • Neutron – 为虚拟机、计算和控制节点提供网络功能。
  • Keystone – 为所有云用户和 OpenStack 云服务提供身份认证服务。换句话说,我们可以说 Keystone 是一个提供给云用户和云服务访问权限的方法。
  • Horizon – 用于提供图形用户界面。使用图形化管理界面可以很轻松地完成各种日常操作任务。
  • Cinder – 用于提供块存储功能。通常来说 OpenStack 的 Cinder 中集成了 Chef 和 ScaleIO 来共同为计算和控制节点提供块存储服务。
  • Swift – 用于提供对象存储功能。通常来说,Glance 管理的镜像是存储在对象存储空间的。像 ScaleIO 这样的外部存储也可以提供对象存储,可以很容易的集成 Glance 服务。
  • Glance – 用于提供镜像服务。使用 Glance 的管理平台来上传和下载云镜像。
  • Heat – 用于提供编排服务或功能。使用 Heat 管理平台可以轻松地将虚拟机作为堆栈,并且根据需要可以将虚拟机扩展或收缩。
  • Ceilometer – 用于提供计量与监控功能。

Q:2 什么服务通常在控制节点上运行?

答: 以下服务通常在控制节点上运行:

  • 认证服务(KeyStone)
  • 镜像服务(Glance)
  • Nova 服务比如 Nova API、Nova Scheduler 和 Nova DB
  • 块存储和对象存储服务
  • Ceilometer 服务
  • MariaDB / MySQL 和 RabbitMQ 服务
  • 网络(Neutron)和网络代理的管理服务
  • 编排服务(Heat)

Q:3 什么服务通常在计算节点上运行?

答: 以下服务通常在计算节点运行:

  • Nova 计算
  • 网络服务,比如 OVS

Q:4 计算节点上虚拟机的默认地址是什么?

答: 虚拟机存储在计算节点的 /var/lib/nova/instances

Q:5 Glance 镜像的默认地址是什么?

答: 因为 Glance 服务运行在控制节点上,所以 Glance 镜像都被存储在控制节点的 /var/lib/glance/images 文件夹下。

想了解更多请访问:在 OpenStack 中如何使用命令行创建和删除虚拟机

Q:6 说一下如何使用命令行启动一个虚拟机?

答: 我们可以使用如下 OpenStack 命令来启动一个新的虚拟机:

# openstack server create --flavor {flavor-name} --image {Image-Name-Or-Image-ID}  --nic net-id={Network-ID} --security-group {Security_Group_ID} –key-name {Keypair-Name} <VM_Name>

Q:7 如何在 OpenStack 中显示用户的网络命名空间列表?

答: 可以使用 ip net ns 命令来列出用户的网络命名空间。

~# ip netns list
qdhcp-a51635b1-d023-419a-93b5-39de47755d2d
haproxy
vrouter

Q:8 如何在 OpenStack 中执行网络命名空间内的命令?

答: 假设我们想在 qdhcp-a51635b1-d023-419a-93b5-39de47755d2d 网络命名空间中执行 ifconfig 命令,我们可以执行如下命令。

命令格式 : ip netns exec {network-space} <command>

~# ip netns exec qdhcp-a51635b1-d023-419a-93b5-39de47755d2d "ifconfig"

Q:9 在 Glance 服务中如何使用命令行上传和下载镜像?

答: Glance 服务中云镜像上传可以使用如下 OpenStack 命令:

~# openstack image create --disk-format qcow2 --container-format bare   --public --file {Name-Cloud-Image}.qcow2     <Cloud-Image-Name>

下载云镜像则使用如下命令:

~# glance image-download --file <Cloud-Image-Name> --progress  <Image-ID>

Q:10 OpenStack 如何将虚拟机从错误状态转换为活动状态?

答: 在某些情况下虚拟机可能会进入错误状态,可以使用如下命令将错误状态转换为活动状态:

~# nova reset-state --active {Instance_id}

Q:11 如何使用命令行来获取可使用的浮动 IP 列表?

答: 可使用如下命令来显示可用浮动 IP 列表:

~]# openstack ip floating list | grep None | head -10

Q:12 如何在特定可用区域中或在计算主机上配置虚拟机?

答: 假设我们想在 compute-02 中的可用区 NonProduction 上配置虚拟机,可以使用如下命令:

~]# openstack server create --flavor m1.tiny --image cirros --nic net-id=e0be93b8-728b-4d4d-a272-7d672b2560a6 --security-group NonProd_SG  --key-name linuxtec --availability-zone NonProduction:compute-02  nonprod_testvm

Q:13 如何在特定计算节点上获取配置的虚拟机列表?

答: 假设我们想要获取在 compute-0-19 中配置的虚拟机列表,可以使用如下命令:

命令格式: openstack server list –all-projects –long -c Name -c Host | grep -i {Compute-Node-Name}

~# openstack server list --all-projects --long -c Name -c Host | grep -i  compute-0-19

Q:14 如何使用命令行查看 OpenStack 实例的控制台日志?

答: 使用如下命令可查看实例的控制台日志。

首先获取实例的 ID,然后使用如下命令:

~# openstack console log show {Instance-id}

Q:15 如何获取 OpenStack 实例的控制台的 URL 地址?

答: 可以使用以下 OpenStack 命令从命令行检索实例的控制台 URL 地址:

~# openstack console url show {Instance-id}

Q:16 如何使用命令行创建可启动的 cinder / block 存储卷?

答: 假设创建一个 8GB 可启动存储卷,可参考如下步骤:

  • 使用如下命令获取镜像列表
~# openstack image list | grep -i cirros
| 89254d46-a54b-4bc8-8e4d-658287c7ee92 | cirros  | active |
  • 使用 cirros 镜像创建 8GB 的可启动存储卷
~# cinder create --image-id 89254d46-a54b-4bc8-8e4d-658287c7ee92 --display-name cirros-bootable-vol  8

Q:17 如何列出所有在你的 OpenStack 中创建的项目或用户?

答: 可以使用如下命令来检索所有项目和用户:

~# openstack project list --long

Q:18 如何显示 OpenStack 服务端点列表?

答: OpenStack 服务端点被分为 3 类:

  • 公共端点
  • 内部端点
  • 管理端点

使用如下 OpenStack 命令来查看各种 OpenStack 服务端点:

~# openstack catalog list

可通过以下命令来显示特定服务端点(比如说 keystone)列表:

~# openstack catalog show keystone

想了解更多请访问:OpenStack 中的实例创建流程

Q:19 在控制节点上你应该按照什么步骤来重启 nova 服务?

答: 应该按照如下步骤来重启 OpenStack 控制节点的 nova 服务:

  • service nova-api restart
  • service nova-cert restart
  • service nova-conductor restart
  • service nova-consoleauth restart
  • service nova-scheduler restart

Q:20 假如计算节点上为数据流量配置了一些 DPDK 端口,你如何检查 DPDK 端口的状态呢?

答: 因为我们使用 openvSwitch (OVS) 来配置 DPDK 端口,因此可以使用如下命令来检查端口的状态:

root@compute-0-15:~# ovs-appctl bond/show | grep dpdk
active slave mac: 90:38:09:ac:7a:99(dpdk0)
slave dpdk0: enabled
slave dpdk1: enabled
root@compute-0-15:~#
root@compute-0-15:~# dpdk-devbind.py --status

Q:21 如何使用命令行在 OpenStack 中向存在的安全组 SG(安全组)中添加新规则?

答: 可以使用 neutron 命令向 OpenStack 已存在的安全组中添加新规则:

~# neutron security-group-rule-create --protocol <tcp or udp>  --port-range-min <port-number> --port-range-max <port-number> --direction <ingress or egress>  --remote-ip-prefix <IP-address-or-range> Security-Group-Name

Q:22 如何查看控制节点和计算节点的 OVS 桥配置?

答: 控制节点和计算节点的 OVS 桥配置可使用以下命令来查看:

~]# ovs-vsctl show

Q:23 计算节点上的集成桥(br-int)的作用是什么?

答: 集成桥(br-int)对来自和运行在计算节点上的实例的流量执行 VLAN 标记和取消标记。

数据包从实例的 n/w 接口发出使用虚拟接口 qvo 通过 Linux 桥(qbr)。qvb 接口是用来连接 Linux 桥的,qvo 接口是用来连接集成桥的。集成桥上的 qvo 端口有一个内部 VLAN 标签,这个标签是用于当数据包到达集成桥的时候贴到数据包头部的。

Q:24 隧道桥(br-tun)在计算节点上的作用是什么?

答: 隧道桥(br-tun)根据 OpenFlow 规则将 VLAN 标记的流量从集成网桥转换为隧道 ID。

隧道桥允许不同网络的实例彼此进行通信。隧道有利于封装在非安全网络上传输的流量,它支持两层网络,即 GRE 和 VXLAN。

Q:25 外部 OVS 桥(br-ex)的作用是什么?

答: 顾名思义,此网桥转发来往网络的流量,以允许外部访问实例。br-ex 连接物理接口比如 eth2,这样用户网络的浮动 IP 数据从物理网络接收并路由到用户网络端口。

Q:26 OpenStack 网络中 OpenFlow 规则的作用是什么?

答: OpenFlow 规则是一种机制,这种机制定义了一个数据包如何从源到达目的地。OpenFlow 规则存储在 flow 表中。flow 表是 OpenFlow 交换机的一部分。

当一个数据包到达交换机就会被第一个 flow 表检查,如果不匹配 flow 表中的任何入口,那这个数据包就会被丢弃或者转发到其他 flow 表中。

Q:27 怎样查看 OpenFlow 交换机的信息(比如端口、表编号、缓存编号等)?

答: 假如我们要显示 OpenFlow 交换机的信息(br-int),需要执行如下命令:

root@compute-0-15# ovs-ofctl show br-int
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000fe981785c443
n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 1(patch-tun): addr:3a:c6:4f:bd:3e:3b
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 2(qvob35d2d65-f3): addr:b2:83:c4:0b:42:3a
     config:     0
     state:      0
     current:    10GB-FD COPPER
     speed: 10000 Mbps now, 0 Mbps max
 ………………………………………

Q:28 如何显示交换机中的所有 flow 的入口?

答: 可以使用命令 ovs-ofctl dump-flows 来查看交换机的 flow 入口。

假设我们想显示 OVS 集成桥(br-int)的所有 flow 入口,可以使用如下命令:

[root@compute01 ~]# ovs-ofctl dump-flows br-int

Q:29 什么是 Neutron 代理?如何显示所有 Neutron 代理?

答: OpenStack Neutron 服务器充当中心控制器,实际网络配置是在计算节点或者网络节点上执行的。Neutron 代理是计算节点或者网络节点上进行配置更新的软件实体。Neutron 代理通过 Neuron 服务和消息队列来和中心 Neutron 服务通信。

可通过如下命令查看 Neutron 代理列表:

~# openstack network agent list -c ‘Agent type’ -c Host -c Alive -c State

Q:30 CPU Pinning 是什么?

答: CPU Pinning 是指为某个虚拟机保留物理核心。它也称为 CPU 隔离或处理器关联。有两个目的:

  • 它确保虚拟机只能在专用核心上运行
  • 它还确保公共主机进程不在这些核心上运行

我们也可以认为 Pinning 是物理核心到一个用户虚拟 CPU(vCPU)的一对一映射。


via: https://www.linuxtechi.com/openstack-interview-questions-answers/

作者:Pradeep Kumar 选题:lujun9972 译者:ScarboroughCoral 校对:wxy

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

这是 Emacs 和 Org 模式系列的第三篇。

Todo 的跟进及关键字

当你使用 Org 模式来跟进你的 TODO 时,它有多种状态。你可以用 C-c C-t 来快速切换状态。我将它设为这样:

(setq org-todo-keywords '(
  (sequence "TODO(t!)" "NEXT(n!)" "STARTED(a!)" "WAIT(w@/!)" "OTHERS(o!)" "|" "DONE(d)" "CANCELLED(c)")
))

在这里,我设置了一个任务未完成的五种状态:TODONEXTSTARTEDWAITOTHERS。每一个状态都有单个字的快捷键(tna 等)。管道符(|)之后的状态被认为是“完成”的状态。我有两个“完成”状态:DONE(已经完成)及 CANCELLED(还没完成,但由于其它的原因无法完成)。

! 的含义是记录某项更改为状态的时间。我不把这个添加到完成的状态,是因为它们已经被记录了。@ 符号表示带理由的提示,所以当切换到 WAIT 时,Org 模式会问我为什么,并将这个添加到笔记中。

以下是项目状态发生变化的例子:

** DONE This is a test
   CLOSED: [2018-03-02 Fri 03:05]
  
   - State "DONE"       from "WAIT"       [2018-03-02 Fri 03:05]
   - State "WAIT"       from "TODO"       [2018-03-02 Fri 03:05] \\
     waiting for pigs to fly
   - State "TODO"       from "NEXT"       [2018-03-02 Fri 03:05]
   - State "NEXT"       from "TODO"       [2018-03-02 Fri 03:05]

在这里,最新的项目在最上面。

议程模式,日程及期限

当你处在一个待办事项时,C-c C-sC-c C-d 可以为其设置相应的日程或期限。这些都是在议程模式中的功能。它们的区别在于其意图和表现。日程是你希望在某个时候完成的事情,而期限是在某个特定的时间应该完成的事情。默认情况下,议程视图将在项目的截止日期前提醒你。

在此过程中,议程视图将显示即将出现的项目,提供了一种基于纯文本或标记搜索项目的方法,甚至可以进行跨多个文件处理项目的批量操作。我在本系列的第 2 部分中介绍了为议程模式配置。

标签

Org 模式当然也支持标签了。你可以通过 C-c C-q 快速的建立标签。

你可能会想为一些常用的标签设置快捷键。就像这样:

  (setq org-tag-persistent-alist 
        '(("@phone" . ?p) 
          ("@computer" . ?c) 
          ("@websurfing" . ?w)
          ("@errands" . ?e)
          ("@outdoors" . ?o)
          ("MIT" . ?m)
          ("BIGROCK" . ?b)
          ("CONTACTS" . ?C)
          ("INBOX" . ?i)
          ))

你还可以按文件向该列表添加标记,也可以按文件为某些内容设置标记。我就在我的 inbox.orgemail.org 文件中设置了一个 INBOX 的标签。然后我可以每天从日程视图中查看所有标记为 INBOX 的项目,像将它们重新归档到其他文件中的这样的简单操作将让它们去掉 INBOX 标记。

重新归档

“重新归档”就是在文件中或其他地方移动。它是使用标题来完成的。C-c C-w 就是做这个的。我设置成这样:

(setq org-outline-path-complete-in-steps nil)         ; Refile in a single go
(setq org-refile-use-outline-path 'file)

归档分类

一段时间后,你的文件就会被已经完成的事情弄得乱七八糟。Org 模式有一个归档特性,可以将主 .org 文件移到其他文件中,以备将来参考。如果你在 git 或其他软件中 有 Org 文件,你可能希望删除这些其他文件,因为无论如何都会在历史中拥有这些文件,但是我发现它们对于析取和搜索非常方便。

我会定期检查并归档文件中的所有内容。基于 stackoverflow 的讨论,我有以下代码:

(defun org-archive-done-tasks ()
  (interactive)
  (org-map-entries
   (lambda ()
     (org-archive-subtree)
     (setq org-map-continue-from (outline-previous-heading)))
   "/DONE" 'file)
  (org-map-entries
   (lambda ()
     (org-archive-subtree)
     (setq org-map-continue-from (outline-previous-heading)))
   "/CANCELLED" 'file)
)

这基于一个特定的答案 —— 你可以从评论那获得一些额外的提示。现在你可以运行 M-x org-archive-done-tasks,当前文件中所有标记为 DONECANCELED 的内容都将放到另一个文件中。

下一篇

我将通过讨论在 Org 模式中自动接受邮件以及在不同的机器上同步来对 Org 模式进行总结。


via: https://changelog.complete.org/archives/9877-emacs-3-more-on-org-mode

作者:John Goerzen 选题:lujun9972 译者:oneforalone 校对:wxy

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

除了 pandas、scikit-learn 和 matplotlib,还要学习一些用 Python 进行数据科学的新技巧。

Python 是一种令人惊叹的语言。事实上,它是世界上增长最快的编程语言之一。它一次又一次地证明了它在各个行业的开发者和数据科学者中的作用。Python 及其库的整个生态系统使其成为全世界用户的恰当选择,无论是初学者还是高级用户。它成功和受欢迎的原因之一是它的一组强大的库,使它如此动态和快速。

在本文中,我们将看到 Python 库中的一些数据科学工具,而不是那些常用的工具,如 pandas、scikit-learn 和 matplotlib。虽然像 pandas、scikit-learn 这样的库是机器学习中最常想到的,但是了解这个领域的其他 Python 库也是非常有帮助的。

Wget

提取数据,尤其是从网络中提取数据,是数据科学家的重要任务之一。Wget 是一个免费的工具,用于从网络上非交互式下载文件。它支持 HTTP、HTTPS 和 FTP 协议,以及通过 HTTP 代理进行访问。因为它是非交互式的,所以即使用户没有登录,它也可以在后台工作。所以下次你想下载一个网站或者网页上的所有图片,wget 会提供帮助。

安装:

$ pip install wget

例子:

import wget
url = 'http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'

filename = wget.download(url)
100% [................................................] 3841532 / 3841532

filename
'razorback.mp3'

钟摆

对于在 Python 中处理日期时间感到沮丧的人来说, Pendulum 库是很有帮助的。这是一个 Python 包,可以简化日期时间操作。它是 Python 原生类的一个替代品。有关详细信息,请参阅其文档

安装:

$ pip install pendulum

例子:

import pendulum

dt_toronto = pendulum.datetime(2012, 1, 1, tz='America/Toronto')
dt_vancouver = pendulum.datetime(2012, 1, 1, tz='America/Vancouver')

print(dt_vancouver.diff(dt_toronto).in_hours())

3

不平衡学习

当每个类别中的样本数几乎相同(即平衡)时,大多数分类算法会工作得最好。但是现实生活中的案例中充满了不平衡的数据集,这可能会影响到机器学习算法的学习和后续预测。幸运的是,imbalanced-learn 库就是为了解决这个问题而创建的。它与 scikit-learn 兼容,并且是 scikit-learn-contrib 项目的一部分。下次遇到不平衡的数据集时,可以尝试一下。

安装:

pip install -U imbalanced-learn
# or
conda install -c conda-forge imbalanced-learn

例子:

有关用法和示例,请参阅其文档

FlashText

在自然语言处理(NLP)任务中清理文本数据通常需要替换句子中的关键词或从句子中提取关键词。通常,这种操作可以用正则表达式来完成,但是如果要搜索的术语数达到数千个,它们可能会变得很麻烦。

Python 的 FlashText 模块,基于 FlashText 算法,为这种情况提供了一个合适的替代方案。FlashText 的最佳部分是运行时间与搜索项的数量无关。你可以在其 文档 中读到更多关于它的信息。

安装:

$ pip install flashtext

例子:

提取关键词:

from flashtext import KeywordProcessor
keyword_processor = KeywordProcessor()

# keyword_processor.add_keyword(<unclean name>, <standardised name>)

keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('Bay Area')
keywords_found = keyword_processor.extract_keywords('I love Big Apple and Bay Area.')

keywords_found
['New York', 'Bay Area']

替代关键词:

keyword_processor.add_keyword('New Delhi', 'NCR region')

new_sentence = keyword_processor.replace_keywords('I love Big Apple and new delhi.')

new_sentence
'I love New York and NCR region.'

有关更多示例,请参阅文档中的 用法 一节。

模糊处理

这个名字听起来很奇怪,但是 FuzzyWuzzy 在字符串匹配方面是一个非常有用的库。它可以很容易地实现字符串匹配率、令牌匹配率等操作。对于匹配保存在不同数据库中的记录也很方便。

安装:

$ pip install fuzzywuzzy

例子:

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

# 简单的匹配率
fuzz.ratio("this is a test", "this is a test!")
97

# 部分的匹配率 
fuzz.partial_ratio("this is a test", "this is a test!")
 100

更多的例子可以在 FuzzyWuzy 的 GitHub 仓库得到。

PyFlux

时间序列分析是机器学习中最常遇到的问题之一。PyFlux 是 Python 中的开源库,专门为处理时间序列问题而构建的。该库拥有一系列优秀的现代时间序列模型,包括但不限于 ARIMA、GARCH 以及 VAR 模型。简而言之,PyFlux 为时间序列建模提供了一种概率方法。这值得一试。

安装:

pip install pyflux

例子:

有关用法和示例,请参阅其 文档

IPyvolume

交流结果是数据科学的一个重要方面,可视化结果提供了显著优势。 IPyvolume 是一个 Python 库,用于在 Jupyter 笔记本中可视化 3D 体积和形状(例如 3D 散点图),配置和工作量极小。然而,它目前处于 1.0 之前的阶段。一个很好的类比是这样的: IPyVolumee volshow 是 3D 阵列,Matplotlib 的 imshow 是 2D 阵列。你可以在其 文档 中读到更多关于它的信息。

安装:

Using pip
$ pip install ipyvolume

Conda/Anaconda
$ conda install -c conda-forge ipyvolume

例子:

动画:

体绘制:

Dash

Dash 是一个用于构建 Web 应用程序的高效 Python 框架。它构建于 Flask、Plotty.js 和 Response.js 之上,将下拉菜单、滑块和图形等流行 UI 元素与你的 Python 分析代码联系起来,而不需要JavaScript。Dash 非常适合构建可在 Web 浏览器中呈现的数据可视化应用程序。有关详细信息,请参阅其 用户指南

安装:

pip install dash==0.29.0  # The core dash backend
pip install dash-html-components==0.13.2  # HTML components
pip install dash-core-components==0.36.0  # Supercharged components
pip install dash-table==3.1.3  # Interactive DataTable component (new!)

例子:

下面的示例显示了一个具有下拉功能的高度交互的图表。当用户在下拉列表中选择一个值时,应用程序代码将数据从 Google Finance 动态导出到 Pandas 数据框架中。

Gym

OpenAI 而来的 Gym 是开发和比较强化学习算法的工具包。它与任何数值计算库兼容,如 TensorFlow 或 Theano。Gym 是一个测试问题的集合,也称为“环境”,你可以用它来制定你的强化学习算法。这些环境有一个共享的接口,允许您编写通用算法。

安装:

pip install gym

例子:

以下示例将在 CartPole-v0 环境中,运行 1000 次,在每一步渲染环境。

你可以在 Gym 网站上读到 其它的环境

结论

这些是我挑选的有用但鲜为人知的数据科学 Python 库。如果你知道另一个要添加到这个列表中,请在下面的评论中提及。

本文最初发表在 Analytics Vidhya 的媒体频道上,并经许可转载。


via: https://opensource.com/article/18/11/python-libraries-data-science

作者:Parul Pandey 选题:lujun9972 译者:heguangzhi 校对:wxy

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

我不仅写技术文档,还写小说。并且因为我对 GIMP 等工具感到满意,所以我也(LCTT 译注:此处应指使用 GIMP)为自己的书籍创作了封面(并为少数客户做了图形设计)。艺术创作取决于很多东西,包括字体。

虽然字体渲染已经在过去的几年里取得了长足进步,但它在 Linux 平台上仍是个问题。如果你在 Linux 和 macOS 平台上比较相同字体的外观,差别是显而易见的,尤其是你要盯着屏幕一整天的时候。虽然在 Linux 平台上尚未找到完美的字体渲染方案,但开源平台做的很好一件事的就是允许用户轻松地管理他们的字体。通过选择、添加、缩放和调整,你可以在 Linux 平台上相当轻松地使用字体。

此处,我将分享一些这些年来我的一些技巧,可以帮我在 Linux 上扩展“字体能力”。这些技巧将对那些在开源平台上进行艺术创作的人有特别的帮助。因为 Linux 平台上有非常多可用的桌面界面(每种界面以不同的方式处理字体),因此当桌面环境成为字体管理的中心时,我将主要聚焦在 GNOME 和 KDE 上。

话虽如此,让我们开始吧。

添加新字体

在相当长的一段时间里,我都是一个字体收藏家,甚至有些人会说我有些痴迷。从我使用 Linux 的早期开始,我就总是用相同的方法向我的桌面添加字体。有两种方法可以做到这一点:

  • 使字体按用户可用;
  • 使字体在系统范围内可用。

因为我的桌面从没有其他用户(除了我自己),我只使用了按用户可用的字体设置。然而,我会向你演示如何完成这两种设置。首先,让我们来看一下如何向用户添加新字体。你首先要做的是找到字体文件,True Type 字体(TTF)和 Open Type 字体(OTF)都可以添加。我选择手动添加字体,也就是说,我在 ~/ 目录下新建了一个名为 ~/.fonts 的隐藏目录。该操作可由以下命令完成:

mkdir ~/.fonts

当此文件夹新建完成,我将所有 TTF 和 OTF 字体文件移动到此文件夹中。也就是说,你在此文件夹中添加的所有字体都可以在已安装的应用中使用了。但是要记住,这些字体只会对这一个用户可用。

如果你想要使这个字体集合对所有用户可用,你可以如下操作:

  1. 打开一个终端窗口;
  2. 切换路径到包含你所有字体的目录中;
  3. 使用 sudo cp *.ttf *.TTF /usr/share/fonts/truetype/sudo cp *.otf *.OTF /usr/share/fonts/opentype 命令拷贝所有字体。

当下次用户登录时,他们就将可以使用所有这些漂亮的字体。

图形界面字体管理

在 Linux 上你有许多方式来管理你的字体,如何完成取决于你的桌面环境。让我们以 KDE 为例。使用以 KDE 作为桌面环境的 Kubuntu 18.04,你能够找到一个预装的字体管理工具。打开此工具,你就能轻松地添加、移除、启用或禁用字体(当然也包括获得所有已安装字体的详细信息)。这个工具也能让你轻松地针对每个用户或在系统范围内添加和删除字体。假如你想要为用户添加一个特定的字体,你需要下载该字体并打开“字体管理”工具。在此工具中(图 1),点击“个人字体”并点击“+”号添加按钮。

 title=

图 1: 在 KDE 中添加个人字体。

导航至你的字体路径,选择它们,然后点击打开。你的字体就会被添加进了个人区域,并且立即可用(图 2)。

 title=

图 2: 使用 KDE 字体管理添加字体

在 GNOME 中做同样的事需要安装一个应用。打开 GNOME 软件中心或者 Ubuntu 软件中心(取决于你使用的发行版)并搜索字体管理器。选择“字体管理器”并点击安装按钮。一但安装完成,你就可以从桌面菜单中启动它,然后让我们安装个人字体。下面是如何安装:

  1. 从左侧窗格选择“用户”(图 3);
  2. 点击窗口顶部的 “+” 按钮;
  3. 浏览并选择已下载的字体;
  4. 点击“打开”。

 title=

图 3: 在 GNOME 中添加字体

调整字体

首先你需要理解 3 个概念:

  • 字体提示: 使用数学指令调整字体轮廓显示,使其与光栅化网格对齐。
  • 抗锯齿: 一种通过使曲线和斜线锯齿状边缘光滑化,提高数字图像真实性的技术。
  • 缩放因子: 一个允许你倍增字体大小的缩放单元。也就是说如果你的字体是 12pt 并且缩放因子为 1,那么字体大小将会是 12pt。如果你的缩放因子为 2,那么字体将会是 24pt。

假设你已经安装好了你的字体,但它们看起来并不像你想的那么好。你将如何调整字体的外观?在 KDE 和 GNOME 中,你都可以做一些调整。在调整字体时需要考虑的一件事是,关于字体的口味是非常主观的。你也许会发现你只得不停地调整,直到你得到了看起来确实满意的字体(由你的需求和特殊口味决定)。让我们先看一下 KDE 下的情况吧。

打开“系统设置”工具并点击“字体”。在此节中,你不仅能切换不同字体,你也能够启用或配置抗锯齿或启用字体缩放因子(图 4)。

 title=

图 4: 在 KDE 中配置字体

要配置抗锯齿,在下拉菜单中选择“启用”并点击“配置”。在结果窗口中(图 5),你可以配置“排除范围”、“子像素渲染类型”和“提示类型”。

一但你做了更改,点击“应用”。重启所有正在运行的程序,然后新的设置就会生效。

要在 GNOME 中这么做,你需要安装“字体管理器”或 GNOME Tweaks。在此处,GNOME Tweaks 是更好的工具。如果你打开 GNOME Dash 菜单但没有找到 Tweaks,打开 GNOME “软件”(或 Ubuntu “软件”)并安装 GNOME Tweaks。安装完毕,打开并点击“字体”,此处你可以配置提示、抗锯齿和缩放因子(图 6)。

 title=

图 6: 在 GNOME 中调整字体

美化你的字体

以上便是使你的 Linux 字体尽可能漂亮的要旨。你可能得不到像 macOS 那样渲染的字体,但你一定可以提升字体外观。最后,你选择的字体会很大程度地影响视觉效果,因此请确保你安装的字体是干净并且完整适配的,否则你将输掉这次对抗。

通过 The Linux Foundation 和 edX 平台的免费课程 初识 Linux 了解更多关于 Linux 的信息。


via: https://www.linux.com/learn/intro-to-linux/2018/5/how-manage-fonts-linux

作者:Jack Wallen 选题:lujun9972 译者:cycoe 校对:wxy

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

在 Ubuntu 18.04 LTS 中配置 IP 地址的方法和以往使用的配置方法有很大的不同。和旧版本的不同之处在于,Ubuntu 18.04 使用 Netplan 来配置 IP 地址,Netplan 是一个新的命令行网络配置工具。其实在 Ubuntu 17.10 的时候 Ubuntu 开发者就已经介绍过 Netplan 了。接下来要介绍的新的 IP 配置方法不会再用到 /etc/network/interfaces 这个文件,取而代之的是一个 YAML 文件。默认的 Netplan 配置文件一般在 /etc/netplan 目录下。 在这篇教程中,我们会去学习在 Ubuntu 18.04 LTS 的最小化服务器中配置静态 IP 和动态 IP 。

在 Ubuntu 18.04 LTS 中配置静态 IP 地址

首先先找到 Netplan 默认的网络配置文件所在之处:

$ ls /etc/netplan/
50-cloud-init.yaml

我们可以看到,默认的网络配置文件是 50-cloud-init.yaml ,这是一个 YAML 文件。

然后我们再看一下这个文件的内容是什么:

$ cat /etc/netplan/50-cloud-init.yaml

我在之前安装 Ubuntu 18.04 的时候为了从 DHCP 服务器获取 IP 地址已经已经做过了网卡的相关配置,所以详细配置直接看下图:

可以看到这边有两个网卡,分别是 enp0s3enp0s8 ,并且这两个网卡都配置为从 DHCP 服务器中获取 IP。

现在我们给这两个网卡都配置为静态 IP 地址,先用任意一种编辑器来编辑配置文件。

$ sudo nano /etc/netplan/50-cloud-init.yaml

接下来我们分别添加 IP 地址、子网掩码、网关、DNS 服务器等配置。分别用 192.168.225.50 作为网卡 enp0s3 的 IP 地址, 192.168.225.51 作为网卡 enp0s8 的 IP 地址, 192.168.225.1 作为网关地址, 255.255.255.0 作为子网掩码。然后用 8.8.8.88.8.4.4 这两个 DNS 服务器 IP。

要注意的一点是,在 Ubuntu 18.04 里,这个配置文件的每一行都必须靠空格来缩进,不能用 TAB 来代替,否则配置会不起作用。如上图所示的配置文件中每行的缩进都是靠空格键实现的。

同时,在 Ubuntu 18.04 中,我们定义子网掩码的时候不是像旧版本的那样把 IP 和子网掩码分成两项配置。在旧版本的 Ubuntu 里,我们一般配置的 IP 和子网掩码是这样的:

address = 192.168.225.50
netmask = 255.255.255.0

而在 netplan 中,我们把这两项合并成一项,就像这样:

addresses : [192.168.225.50/24]

配置完成之后保存并关闭配置文件。然后用下面这行命令来应用刚才的配置:

$ sudo netplan apply

如果在应用配置的时候有出现问题的话,可以通过如下的命令来查看刚才配置的内容出了什么问题。

$ sudo netplan --debug apply

这行命令会输出这些 debug 信息:

** (generate:1556): DEBUG: 09:14:47.220: Processing input file //etc/netplan/50-cloud-init.yaml..
** (generate:1556): DEBUG: 09:14:47.221: starting new processing pass
** (generate:1556): DEBUG: 09:14:47.221: enp0s8: setting default backend to 1
** (generate:1556): DEBUG: 09:14:47.222: enp0s3: setting default backend to 1
** (generate:1556): DEBUG: 09:14:47.222: Generating output files..
** (generate:1556): DEBUG: 09:14:47.223: NetworkManager: definition enp0s8 is not for us (backend 1)
** (generate:1556): DEBUG: 09:14:47.223: NetworkManager: definition enp0s3 is not for us (backend 1)
DEBUG:netplan generated networkd configuration exists, restarting networkd
DEBUG:no netplan generated NM configuration exists
DEBUG:device enp0s3 operstate is up, not replugging
DEBUG:netplan triggering .link rules for enp0s3
DEBUG:device lo operstate is unknown, not replugging
DEBUG:netplan triggering .link rules for lo
DEBUG:device enp0s8 operstate is up, not replugging
DEBUG:netplan triggering .link rules for enp0s8

如果配置正常且生效的话,我们可以用下面这个命令来查看一下 ip:

$ ip addr

在我的 Ubuntu 18.04 中配置完之后执行命令输出的信息如下:

到此为止,我们已经成功地在 Ubuntu 18.04 LTS 中用 Netplan 完成了静态 IP 的配置。

更多关于 Netplan 的信息,可以在用 man 命令在手册中查看:

$ man netplan

在 Ubuntu 18.04 LTS 中配置动态 IP 地址

其实配置文件中的初始配置就是动态 IP 的配置,所以你想要使用动态 IP 的话不需要再去做任何的配置操作。如果你已经配置了静态 IP 地址,想要恢复之前动态 IP 的配置,就把在上面静态 IP 配置中所添加的相关配置项删除,把整个配置文件恢复成上面的图 1 所示的样子就行了。

现在你已经学会在 Ubuntu 18.04 中配置静态和动态 IP 地址了。个人而言,我其实不太喜欢这种方式,旧的配置方式反而来得简单。你们觉得呢 ?


via: https://www.ostechnix.com/how-to-configure-ip-address-in-ubuntu-18-04-lts/

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

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