分类 技术 下的文章

本篇中,我们会展示一个很酷及简单的方法在屏幕中显示彩色的输出,并且可以为了某个原因减慢输出的速度。

lolcat 命令可以满足上面的需求。它基本上通过与 cat 命令类似的方式将文件或标准输入定向到标准输出来运行,覆盖某个命令的默认屏幕输出颜色,并为其添加彩色。

如何在 Linux 中安装 lolcat 程序

lolcat 可以在大多数现代 Linux 发行版的默认仓库中得到,但是可用的版本有点老。你可以使用下面的指导来从 git 仓库中安装最新的 lolcat 版本。

lolcat 安装后,基本的 lolcat 语法是:

$ lolcat [options] [files] ...

有几个选项可以控制它的行为,下面是一些我们在本指导中会强调的几个最重要的标志:

  1. -a - 将每行输出都显示动态效果。
  2. -d – 指定动画效果间隔(显示下一行之前的帧),默认是 12。
  3. -s – 它指定了动画效果的速度(帧速-每秒的显示帧数),默认是 20。
  4. -f – 强制显示彩色以防止标准输出不是 tty。

你可以在 lolcat 的 man 页可以找到更多的选项:

$ man lolcat 

如何在 Linux 中使用 lolcat

要使用 lolcat,直接将相关命令的输出通过管道给 lolcat,即可见证魔法。

比如:

$ ls -l | lolcat -as 25

colorful Linux Terminal Output

除此之外你也可以改变默认速度,在下面的命令中,我们会使用一个相对较慢的速度,每秒显示 10 帧:

$ ls -l | lolcat -as 10

你可以使用任何命令结合 lolcat 在 Linux 终端中输出彩色结果,比如 psdatecal

$ ps | lolcat
$ date | lolcat
$ cal | lolcat

本篇中,我们了解了如何显著降低屏幕输出的速度,并显示彩色效果。

通常上,你可以在下面的评论栏中留下任何关于本篇的问题或评论。最后,你可以留下任何你发现的有用命令。


via: http://www.tecmint.com/add-colors-to-command-output-terminal-linux/

作者:Aaron Kili 译者:geekpi 校对:wxy

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

在学习 Linux 的过程中,对于新手而言总是会使用几个命令来完成一个简单的任务。对正在熟悉使用终端的人这是很容易理解的行为。然而,如果你想要成为一个老手,学习我说的“快捷命令”会显著减少时间浪费。

在本篇中,我们会用一个简单的方法在 Linux 中用一个命令来将目录复制到多个文件夹中。

在 Linux 中,cp 命令常被用于从一个文件夹中复制文件到另一个文件夹中,最简单的语法如下:

# cp [options….] source(s) destination

另外,你也可以使用高级复制命令,它可以在复制大的文件或文件夹时显示进度条。

看下下面的命令,通常你会使用两个不同的命令来将相同的文件复制到不同的文件夹中:

# cp -v /home/aaronkilik/bin/sys_info.sh /home/aaronkilik/test
# cp -v /home/aaronkilik/bin/sys_info.sh /home/aaronkilik/tmp

Copy Files to Multiple Directories

复制文件到多个文件夹中

假设你想要复制一个特定文件到 5 个或者更多的文件夹中,这意味着你需要输入 5 次或者更多的cp命令么?

要摆脱这个问题,你可以用 cp 命令与 echo命令、管道、xargs 命令一起使用:

# echo /home/aaronkilik/test/ /home/aaronkilik/tmp | xargs -n 1 cp -v /home/aaronkilik/bin/sys_info.sh

上面的命令中,目录的路径(dir1、dir2、dir3...dirN)被管道作为输入到 xargs 命令中,含义是:

  1. -n 1 - 告诉 xargs 命令每个命令行最多使用一个参数,并发送到 cp 命令中。
  2. cp – 用于复制文件。
  3. -v – 启用详细模式来显示更多复制细节。

Copy File to Multiple Locations in Linux

在 Linux 中复制文件到多个位置中

试试阅读 cpechoxargs 的 man 页面来找出所有有用和高级的用法信息:

$ man cp
$ man echo
$ man xargs

就是这样了,你可以在下面的评论区给我们发送主题相关的问题或者反馈。你也可以阅读有关 progress 命令来帮助监控运行中的(cp、mv、dd、tar 等等)的进度。


作者简介:

Aaron Kili 是一个 Linux 及 F.O.S.S 热衷者,即将成为 Linux 系统管理员、web 开发者,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并坚信分享知识。


via: http://www.tecmint.com/copy-file-to-multiple-directories-in-linux/

作者:Aaron Kili 译者:geekpi 校对:wxy

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

在 Ubuntu 或者它的衍生版如 Linux Mint(我已经作为日常工作使用的系统)中使用 apt-get 命令或者其相对更新的APT 管理工具时,你可能会在命令行中看到一个 unable to lock the administration directory (/var/lib/dpkg/) is another process using it 的错误。

这个错误尤其对那些对这个错误原因不了解的 Linux(Ubuntu)新手而言更加恼人。

下面是一个例子,展示了出现在 Ubuntu 16.10 上的文件锁定错误:

tecmint@TecMint:~$ sudo apt install neofetch
[sudo] password for tecmint:
E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)
E: Unable to lock the administration directory (/var/lib/dpkg), is another process using it?

下面的输出是另外一个可能显示的错误:

E: Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily unavailable)
E: Unable to lock directory /var/lib/apt/lists/ 
E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable) 
E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?

你将来遇到这个错误该怎么去解决?有好几种方法处理这个错误,但是本篇中我们会用两种或许是最简单和最有效的方法来解决它。

1、找出并杀掉所有 apt-get 或者 apt 进程

运行下面的命令来生成所有含有 apt 的进程列表,你可以使用 psgrep 命令并用管道组合来得到含有 apt 或者 apt-get 的进程。

$ ps -A | grep apt

Find apt and apt-get Processes

找出 apt 以及 apt-get 进程

你可以看到上面命令输出的每个 apt-get 或者 apt 进程,使用下面的命令杀掉每个进程

上面截图中的第一列是进程 ID(PID)。

$ sudo kill -9 processnumber
或者
$ sudo kill -SIGKILL processnumber

比如,下面命令中的9SIGKILL 的信号数,它会杀掉第一个 apt 进程:

$ sudo kill -9 13431
或者
$ sudo kill -SIGKILL 13431

2、 删除锁定的文件

锁定的文件会阻止 Linux 系统中某些文件或者数据的访问,这个概念也存在于 Windows 或者其他的操作系统中。

一旦你运行了 apt-get 或者 apt 命令,锁定文件将会创建于 /var/lib/apt/lists//var/lib/dpkg//var/cache/apt/archives/ 中。

这有助于运行中的 apt-get 或者 apt 进程能够避免被其它需要使用相同文件的用户或者系统进程所打断。当该进程执行完毕后,锁定文件将会删除。

重要提醒:万一你在没有看到 apt-get 或者 apt 进程的情况下在上面两个不同的文件夹中看到了锁定文件,这是因为进程由于某个原因被杀掉了,因此你需要删除锁定文件来避免该错误。

首先运行下面的命令来移除 /var/lib/dpkg/ 文件夹下的锁定文件:

$ sudo rm /var/lib/dpkg/lock

之后像下面这样强制重新配置软件包:

$ sudo dpkg --configure -a

也可以删除 /var/lib/apt/lists/ 以及缓存文件夹下的锁定文件:

$ sudo rm /var/lib/apt/lists/lock
$ sudo rm /var/cache/apt/archives/lock

接下来,更新你的软件包源列表:

$ sudo apt update
或者
$ sudo apt-get update

总结一下,对于 Ubuntu(以及它的衍生版)用户在使用 apt-get 或者 apt 也叫 aptitude 命令时遇到的问题,我们已经用两种方法来解决了。

你有什么可以分享出来的有效的方法来处理这个错误么?在下面的评论区联系我们。

除此之外,你可能还希望了解如何找出并杀掉运行的进程,你可以阅读这篇用 kill、pkill、killall 来中止进程指南来了解。


via: http://www.tecmint.com/fix-unable-to-lock-the-administration-directory-var-lib-dpkg-lock

作者:Aaron Kili 译者:geekpi 校对:wxy

本文由 LCTT 组织编译,Linux中国 荣誉推出

httpstat 是一个 Python 脚本,它以美妙妥善的方式反映了 curl 统计分析,它是一个单一脚本,兼容 Python 3 ,在用户的系统上不需要安装额外的软件(依赖)。

从本质上来说它是一个 cURL 工具的封装,意味着你可以在 URL 后使用几个有效的 cURL 选项,但是不包括 -w-D-o-s-S 选项,这些已经被 httpstat 使用了。

httpstat Curl Statistics Tool

httpstat Curl 统计分析工具

你可以看到上图的一个 ASCII 表显示了每个过程消耗多长时间,对我来说最重要的一步是“ 服务器处理 server processing ” – 如果这个数字很高,那么你需要优化你网站服务器来加速访问速度

网站或服务器优化你可以查看我们的文章:

  1. 5 个优化 Apache Web 服务器性能的技巧
  2. 使 Apache 和 Nginx 性能提升 10 倍
  3. 如何使用 Gzip 模块提高 Nginx 性能
  4. 15 个优化 MySQL/MariaDB 性能的建议

使用下面安装说明和用法来获取 httpstat 检查出你的网站速度。

在 Linux 系统中安装 httpstat

你可以使用两种合理的方法安装 httpstat :

  1. 使用 wget 命令直接从它的 Github 仓库获取如下:
$ wget -c https://raw.githubusercontent.com/reorx/httpstat/master/httpstat.py
  1. 使用 pip(这个方法允许 httpstat 作为命令安装到你的系统中)像这样:
$ sudo pip install httpstat

注:确保 pip 包已经在系统上安装了,如果没使用你的发行版包管理器 yumapt安装它。

在 Linux 中如何使用 httpstat

httpstat 可以根据你安装它的方式来使用,如果你直接下载了它,进入下载目录使用下面的语句运行它:

$ python httpstat.py url cURL_options 

如果你使用 pip 来安装它,你可以作为命令来执行它,如下表:

$ httpstat url cURL_options  

查看 httpstat 帮助页,命令如下:

$ python httpstat.py --help
或
$ httpstat --help

httpstat 帮助:

Usage: httpstat URL [CURL_OPTIONS]
httpstat -h | --help
httpstat --version
Arguments:
URL     url to request, could be with or without `http(s)://` prefix
Options:
CURL_OPTIONS  any curl supported options, except for -w -D -o -S -s,
which are already used internally.
-h --help     show this screen.
--version     show version.
Environments:
HTTPSTAT_SHOW_BODY    Set to `true` to show response body in the output,
note that body length is limited to 1023 bytes, will be
truncated if exceeds. Default is `false`.
HTTPSTAT_SHOW_IP      By default httpstat shows remote and local IP/port address.
Set to `false` to disable this feature. Default is `true`.
HTTPSTAT_SHOW_SPEED   Set to `true` to show download and upload speed.
Default is `false`.
HTTPSTAT_SAVE_BODY    By default httpstat stores body in a tmp file,
set to `false` to disable this feature. Default is `true`
HTTPSTAT_CURL_BIN     Indicate the curl bin path to use. Default is `curl`
from current shell $PATH.
HTTPSTAT_DEBUG        Set to `true` to see debugging logs. Default is `false`

从上面帮助命令的输出,你可以看出 httpstat 已经具备了一些可以影响其行为的环境变量。

使用它们,只需输出适当的值的这些变量到 .bashrc.zshrc 文件。

例如:

export  HTTPSTAT_SHOW_IP=false
export  HTTPSTAT_SHOW_SPEED=true
export  HTTPSTAT_SAVE_BODY=false
export  HTTPSTAT_DEBUG=true

你一旦添加完它们,保存文件然后运行下面的命令使改变生效:

$ source  ~/.bashrc

你可以指定使用 cURL 执行文件的路径,默认使用的是当前 shell 的 $PATH 环境变量

下面是一些展示 httpstat 如何工作的例子。

$ python httpstat.py google.com
或
$ httpstat google.com

httpstat - Showing Website Statistics

httpstat – 展示网站统计分析

接下来的命令中:

  1. -X 命令标记指定一个客户与 HTTP 服务器连接的请求方法。
  2. --data-urlencode 这个选项将会把数据(这里是 a=b)按 URL 编码的方式编码后再提交。
  3. -v 开启详细模式。
$ python httpstat.py httpbin.org/post -X POST --data-urlencode "a=b" -v 

httpstat - Custom Post Request

httpstat – 定制提交请求

你可以查看 cURL 的帮助获取更多有用的高级选项,或者浏览 httpstat 的 Github 仓库: https://github.com/reorx/httpstat

这篇文章中,我们讲述了一个有效的工具,它以简单和整洁方式来查看 cURL 统计分析。如果你知道任何类似的工具,别犹豫,让我们知道,你也可以问问题或评论这篇文章或 httpstat,通过下面反馈。


via: http://www.tecmint.com/httpstat-curl-statistics-tool-check-website-performance/

作者:Aaron Kili 译者:wyangsun 校对:wxy

本文由 LCTT 组织编译,Linux中国 荣誉推出

本文作者 Brendan Gregg 目前是 Netflix 的高级性能架构师 ,他在那里做大规模计算机性能设计、分析和调优。他是《Systems Performance》等技术书的作者,因在系统管理员方面的成绩,获得过 2013年 USENIX LISA 大奖。他之前是 SUN 公司是性能领头人和内核工程师,研究存储和网络性能。他也发明和开发过一大波性能分析工具,很多已集成到操作系统中了 。

随着 BPF 追踪系统(基于时间采样)最后一个主要功能被合并至 Linux 4.9-rc1 版本的内核中,现在 Linux 内核拥有类似 DTrace 的原生追踪功能。DTrace 是 Solaris 系统中的高级追踪器。对于长期使用 DTrace 的用户和专家,这将是一个振奋人心的里程碑!现在在 Linux 系统上,你可以在生产环境中使用安全的、低负载的定制追踪系统,通过执行时间的柱状图和频率统计等信息,分析应用的性能以及内核。

用于 Linux 的追踪项目有很多,但是这个最终被合并进 Linux 内核的技术从一开始就根本不是一个追踪项目:它是最开始是用于 伯克利包过滤器 Berkeley Packet Filter (BPF)的增强功能。这些补丁允许 BPF 重定向数据包,从而创建软件定义网络(SDN)。久而久之,对事件追踪的支持就被添加进来了,使得程序追踪可用于 Linux 系统。

尽管目前 BPF 没有像 DTrace 一样的高级语言,但它所提供的前端已经足够让我创建很多 BPF 工具了,其中有些是基于我以前的 DTraceToolkit。这个帖子将告诉你怎么去用这些 BPF 提供的前端工具,以及畅谈这项技术将会何去何从。

示例

我已经将基于 BPF 的追踪工具添加到了开源的 bcc 项目里(感谢 PLUMgrid 公司的 Brenden Blanco 带领 bcc 项目的发展)。详见 bcc 安装 手册。它会在 /usr/share/bcc/tools 目录下添加一系列工具,包括接下来的那些工具。

捕获新进程:

# execsnoop
PCOMM            PID    RET ARGS
bash             15887    0 /usr/bin/man ls
preconv          15894    0 /usr/bin/preconv -e UTF-8
man              15896    0 /usr/bin/tbl
man              15897    0 /usr/bin/nroff -mandoc -rLL=169n -rLT=169n -Tutf8
man              15898    0 /usr/bin/pager -s
nroff            15900    0 /usr/bin/locale charmap
nroff            15901    0 /usr/bin/groff -mtty-char -Tutf8 -mandoc -rLL=169n -rLT=169n
groff            15902    0 /usr/bin/troff -mtty-char -mandoc -rLL=169n -rLT=169n -Tutf8
groff            15903    0 /usr/bin/grotty

硬盘 I/O 延迟的柱状图:

# biolatency -m
Tracing block device I/O... Hit Ctrl-C to end.
^C
     msecs           : count     distribution
       0 -> 1        : 96       |************************************  |
       2 -> 3        : 25       |*********                             |
       4 -> 7        : 29       |***********                           |
       8 -> 15       : 62       |***********************               |
      16 -> 31       : 100      |**************************************|
      32 -> 63       : 62       |***********************               |
      64 -> 127      : 18       |******                                |

追踪慢于 5 毫秒的 ext4 常见操作:

# ext4slower 5
Tracing ext4 operations slower than 5 ms
TIME     COMM           PID    T BYTES   OFF_KB   LAT(ms) FILENAME
21:49:45 supervise      3570   W 18      0           5.48 status.new
21:49:48 supervise      12770  R 128     0           7.55 run
21:49:48 run            12770  R 497     0          16.46 nsswitch.conf
21:49:48 run            12770  R 1680    0          17.42 netflix_environment.sh
21:49:48 run            12770  R 1079    0           9.53 service_functions.sh
21:49:48 run            12772  R 128     0          17.74 svstat
21:49:48 svstat         12772  R 18      0           8.67 status
21:49:48 run            12774  R 128     0          15.76 stat
21:49:48 run            12777  R 128     0           7.89 grep
21:49:48 run            12776  R 128     0           8.25 ps
21:49:48 run            12780  R 128     0          11.07 xargs
21:49:48 ps             12776  R 832     0          12.02 libprocps.so.4.0.0
21:49:48 run            12779  R 128     0          13.21 cut
[...]

追踪新建的 TCP 活跃连接(connect()):

# tcpconnect
PID    COMM         IP SADDR            DADDR            DPORT
1479   telnet       4  127.0.0.1        127.0.0.1        23
1469   curl         4  10.201.219.236   54.245.105.25    80
1469   curl         4  10.201.219.236   54.67.101.145    80
1991   telnet       6  ::1              ::1              23
2015   ssh          6  fe80::2000:bff:fe82:3ac fe80::2000:bff:fe82:3ac 22

通过跟踪 getaddrinfo()/gethostbyname() 库的调用来追踪 DNS 延迟:

# gethostlatency
TIME      PID    COMM          LATms HOST
06:10:24  28011  wget          90.00 www.iovisor.org
06:10:28  28127  wget           0.00 www.iovisor.org
06:10:41  28404  wget           9.00 www.netflix.com
06:10:48  28544  curl          35.00 www.netflix.com.au
06:11:10  29054  curl          31.00 www.plumgrid.com
06:11:16  29195  curl           3.00 www.facebook.com
06:11:25  29404  curl          72.00 foo
06:11:28  29475  curl           1.00 foo

按类别划分 VFS 操作的时间间隔统计:

# vfsstat
TIME         READ/s  WRITE/s CREATE/s   OPEN/s  FSYNC/s
18:35:32:       231       12        4       98        0
18:35:33:       274       13        4      106        0
18:35:34:       586       86        4      251        0
18:35:35:       241       15        4       99        0

对一个给定的 PID,通过内核和用户堆栈轨迹来追踪 CPU 处理之外的时间(由内核进行统计):

# offcputime -d -p 24347
Tracing off-CPU time (us) of PID 24347 by user + kernel stack... Hit Ctrl-C to end.
^C
[...]
    ffffffff810a9581 finish_task_switch
    ffffffff8185d385 schedule
    ffffffff81085672 do_wait
    ffffffff8108687b sys_wait4
    ffffffff81861bf6 entry_SYSCALL_64_fastpath
    --
    00007f6733a6b64a waitpid
    -                bash (24347)
        4952

    ffffffff810a9581 finish_task_switch
    ffffffff8185d385 schedule
    ffffffff81860c48 schedule_timeout
    ffffffff810c5672 wait_woken
    ffffffff8150715a n_tty_read
    ffffffff815010f2 tty_read
    ffffffff8122cd67 __vfs_read
    ffffffff8122df65 vfs_read
    ffffffff8122f465 sys_read
    ffffffff81861bf6 entry_SYSCALL_64_fastpath
    --
    00007f6733a969b0 read
    -                bash (24347)
        1450908

追踪 MySQL 查询延迟(通过 USDT 探针):

# mysqld_qslower `pgrep -n mysqld`
Tracing MySQL server queries for PID 14371 slower than 1 ms...
TIME(s)        PID          MS QUERY
0.000000       18608   130.751 SELECT * FROM words WHERE word REGEXP '^bre.*n$'
2.921535       18608   130.590 SELECT * FROM words WHERE word REGEXP '^alex.*$'
4.603549       18608    24.164 SELECT COUNT(*) FROM words
9.733847       18608   130.936 SELECT count(*) AS count FROM words WHERE word REGEXP '^bre.*n$'
17.864776      18608   130.298 SELECT * FROM words WHERE word REGEXP '^bre.*n$' ORDER BY word

监测 pam 库并使用多种追踪工具观察登录请求:

# trace 'pam:pam_start "%s: %s", arg1, arg2'
TIME     PID    COMM         FUNC             -
17:49:45 5558   sshd         pam_start        sshd: root
17:49:47 5662   sudo         pam_start        sudo: root
17:49:49 5727   login        pam_start        login: bgregg

bcc 项目里的很多工具都有帮助信息(-h 选项),并且都应该包含有示例的 man 页面和文本文件。

必要性

2014 年,Linux 追踪程序就有一些内核相关的特性(来自 ftracepref_events),但是我们仍然要转储并报告进程数据,这种几十年前的老技术有很多的限制。你不能频繁地访问进程名、函数名、堆栈轨迹或内核中的任意的其它数据。你不能在将变量保存到一个监测事件里,又在另一个事件里访问它们,这意味着你不能在你需要的地方计算延迟(或者说时间增量)。你也不能创建一个内核内部的延迟柱状图,也不能追踪 USDT 探针,甚至不能写个自定义的程序。DTrace 可以做到所有这些,但仅限于 Solaris 或 BSD 系统。在 Linux 系统中,有些不在主线内核的追踪器,比如 SystemTap 就可以满足你的这些需求,但它也有自身的不足。(理论上说,你可以写一个基于探针的内核模块来满足需求-但实际上没人这么做。)

2014 年我加入了 Netflix cloud performance 团队。做了这么久的 DTrace 方面的专家,转到 Linux 对我来说简直不可思议。但我确实这么做了,而且遇到了巨大的挑战:在应用快速变化、采用微服务架构和分布式系统的情况下,调优 Netflix cloud。有时要用到系统追踪,而我之前是用的 DTrace。在 Linux 系统上可没有 DTrace,我就开始用 Linux 内核内建的 ftraceperf_events 工具,构建了一个追踪工具(perf-tools)。这些工具很有用,但有些工作还是没法完成,尤其是延迟柱状图以及堆栈踪迹计数。我们需要的是内核追踪的可程序化。

发生了什么?

BPF 将程序化的功能添加到现有的内核追踪工具中(tracepointskprobesuprobes)。在 Linux 4.x 系列的内核里,这些功能大大加强了。

时间采样是最主要的部分,它被 Linux 4.9-rc1 所采用(patchset)。十分感谢 Alexei Starovoitov(在 Facebook 致力于 BPF 的开发),他是这些 BPF 增强功能的主要开发者。

Linux 内核现在内建有以下这些特性(自 2.6 版本到 4.9 版本之间增加):

  • 内核级的动态追踪(BPF 对 kprobes 的支持)
  • 用户级的动态追踪(BPF 对 uprobes 的支持)
  • 内核级的静态追踪(BPF 对 tracepoints 的支持)
  • 时间采样事件(BPF 的 pref_event_open
  • PMC 事件(BPF 的 pref_event_open
  • 过滤器(通过 BPF 程序)
  • 调试输出(bpf_trace_printk()
  • 按事件输出(bpf_perf_event_output()
  • 基础变量(全局的和每个线程的变量,基于 BPF 映射)
  • 关联数组(通过 BPF 映射)
  • 频率计数(基于 BPF 映射)
  • 柱状图(2 的冥次方、线性及自定义,基于 BPF 映射)
  • 时间戳和时间增量(bpf_ktime_get_ns(),和 BPF 程序)
  • 内核态的堆栈轨迹(BPF 栈映射)
  • 用户态的堆栈轨迹 (BPF 栈映射)
  • 重写 ring 缓存(pref_event_attr.write_backward

我们采用的前端是 bcc,它同时提供 Python 和 lua 接口。bcc 添加了:

  • 用户级静态追踪(基于 uprobes 的 USDT 探针)
  • 调试输出(Python 中调用 BPF.trace_pipe()BPF.trace_fields() 函数 )
  • 按事件输出(BPF_PERF_OUTPUT 宏和 BPF.open_perf_buffer()
  • 间隔输出(BPF.get_table()table.clear()
  • 打印柱状图(table.print_log2_hist()
  • 内核级的 C 结构体导航(bcc 重写器映射到 bpf_probe_read() 函数)
  • 内核级的符号解析(ksym()ksymaddr()
  • 用户级的符号解析(usymaddr()
  • BPF 跟踪点支持(通过 TRACEPOINT_PROBE
  • BPF 堆栈轨迹支持(包括针对堆栈框架的 walk 方法)
  • 其它各种辅助宏和方法
  • 例子(位于 /examples 目录)
  • 工具(位于 /tools 目录)
  • 教程(/docs/tutorial*.md
  • 参考手册(/docs/reference_guide.md

直到最新也是最主要的特性被整合进来,我才开始写这篇文章,现在它在 4.9-rc1 内核中。我们还需要去完成一些次要的东西,还有另外一些事情要做,但是现在我们所拥有的已经值得欢呼了。现在 Linux 拥有了内建的高级追踪能力。

安全性

设计 BPF 及其增强功能时就考虑到生产环境级安全,它被用在大范围的生产环境里。不过你想的话,你还是可以找到一个挂起内核的方法。这种情况是偶然的,而不是必然,类似的漏洞会被快速修复,尤其是当 BPF 合并入了 Linux。因为 Linux 可是公众的焦点。

在开发过程中我们碰到了一些非 BPF 的漏洞,它们需要被修复:rcu 不可重入,这可能导致内核由于 funccount 挂起,在 4.6 内核版本中这个漏洞被 “bpf: map pre-alloc” 补丁集所修复,旧版本内核的漏洞 bcc 有个临时处理方案。还有一个是 uprobe 的内存计算问题,这导致 uprobe 分配内存失败,在 4.8 内核版本这个漏洞由 “uprobes: Fix the memcg accounting” 补丁所修复,并且该补丁还将被移植到之前版本的内核中(例如,它现在被移植到了 4.4.27 和 4.4.0-45.66 版本中)。

为什么 Linux 追踪用了这么久才加进来?

首要任务被分到了若干追踪器中间:这些不是某个追踪器单个的事情。想要了解更多关于这个或其它方面的问题,可以看一看我在 2014 年 tracing summit 上的讲话。我忽视了部分方案的反面影响:有些公司发现其它追踪器(SystemTap 和 LTTng)能满足他们的需求,尽管他们乐于听到 BPF 的开发进程,但考虑到他们现有的解决方案,帮助 BPF 的开发就不那么重要了。

BPF 仅在近两年里在追踪领域得到加强。这一过程原本可以更快的,但早期缺少全职从事于 BPF 追踪的工程师。Alexei Starovoitov (BPF 领导者),Brenden Blanco (bcc 领导者),我还有其它一些开发者,都有其它的事情要做。我在 Netflix 公司花了大量时间(志愿地),大概有 7% 的时间是花在 BPF 和 bcc 上。某种程度上这不是我的首要任务,因为我还有自己的工作(包括我的 perf-tools,一个可以工作在旧版本内核上的程序)。

现在BPF 追踪器已经推出了,已经有科技公司开始寻找会 BPF 的人了。但我还是推荐 Netflix 公司。(如果你为了 BPF 而要聘请我,那我还是十分乐于待在 Netflix 公司的!)

使用简单

DTrace 和 bcc/BPF 现在的最大区别就是哪个更好使用。这取决于你要用 BPF 追踪做什么了。如果你要

  • 使用 BPF 工具/度量:应该是没什么区别的。工具的表现都差不多,图形用户界面都能取得类似度量指标。大部分用户通过这种方式使用 BPF。
  • 开发工具/度量:bcc 的开发可难多了。DTrace 有一套自己的简单语言,D 语音,和 awk 语言相似,而 bcc 使用已有的语言(C 语言,Python 和 lua)及其类库。一个用 C 和 Python 写的 bcc 工具与仅仅用 D 语言写出来的工具相比,可能要多十多倍行数的代码,或者更多。但是很多 DTrace 工具用 shell 封装来提供参数和差错检查,会让代码变得十分臃肿。编程的难处是不同的:重写 bcc 更需要巧妙性,这导致某些脚本更加难开发。(尤其是 bpf_probe_read() 这类的函数,需要了解更多 BPF 的内涵知识)。当计划改进 bcc 时,这一情形将得到改善。
  • 运行常见的命令:十分相近。通过 dtrace 命令,DTrace 能做很多事,但 bcc 有各种工具,traceargdistfunccountfunclatency 等等。
  • 编写自定义的特殊命令:使用 DTrace 的话,这就没有必要了。允许定制消息快速传递和系统快速响应,DTrace 的高级分析很快。而 bcc 现在受限于它的多种工具以及它们的适用范围。

简单来说,如果你只使用 BPF 工具的话,就不必关注这些差异了。如果你经验丰富,是个开发者(像我一样),目前 bcc 的使用更难一些。

举一个 bcc 的 Python 前端的例子,下面是追踪硬盘 I/O 并打印出 I/O 大小的柱状图代码:

from bcc import BPF
from time import sleep

# load BPF program
b = BPF(text="""
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>

BPF_HISTOGRAM(dist);

int kprobe__blk_account_io_completion(struct pt_regs *ctx, struct request *req)
{
    dist.increment(bpf_log2l(req->__data_len / 1024));
    return 0;
}
""")

# header
print("Tracing... Hit Ctrl-C to end.")

# trace until Ctrl-C
try:
    sleep(99999999)
except KeyboardInterrupt:
    print

# output
b["dist"].print_log2_hist("kbytes")

注意 Python 代码中嵌入的 C 语句(text=)。

这就完成了任务,但仍有改进的空间。好在我们有时间去做:人们使用 Linux 4.9 并能用上 BPF 还得好几个月呢,所以我们有时间来制造工具和前端。

高级语言

前端越简单,比如高级语言,所改进的可能就越不如你所期望的。绝大多数人使用封装好的工具(和图形界面),仅有少部分人能写出这些工具。但我不反对使用高级语言,比如 SystemTap,毕竟已经开发出来了。

#!/usr/bin/stap
/*
 * opensnoop.stp    Trace file open()s.  Basic version of opensnoop.
 */

probe begin
{
    printf("\n%6s %6s %16s %s\n", "UID", "PID", "COMM", "PATH");
}

probe syscall.open
{
    printf("%6d %6d %16s %s\n", uid(), pid(), execname(), filename);
}

如果拥有整合了语言和脚本的 SystemTap 前端与高性能的内置在内核中的 BPF 后端,会不会令人满意呢?RedHat 公司的 Richard Henderson 已经在进行相关工作了,并且发布了 初代版本

这是 ply,一个完全新颖的 BPF 高级语言:

#!/usr/bin/env ply

kprobe:SyS_*
{
    $syscalls[func].count()
}

这也是一份承诺。

尽管如此,我认为工具开发者的实际难题不是使用什么语言:而是要了解要用这些强大的工具做什么?

如何帮助我们

  • 推广:BPF 追踪器目前还没有什么市场方面的进展。尽管有公司了解并在使用它(Facebook、Netflix、Github 和其它公司),但要广为人知尚需时日。你可以分享关于 BPF 的文章和资源给业内的其它公司来帮助我们。
  • 教育:你可以撰写文章,发表演讲,甚至参与 bcc 文档的编写。分享 BPF 如何解决实际问题以及为公司带来收益的实例。
  • 解决 bcc 的问题:参考 bcc issue list,这包含了错误和需要的特性。
  • 提交错误:使用 bcc/BPF,提交你发现的错误。
  • 创造工具:有很多可视化的工具需要开发,但请不要太草率,因为大家会先花几个小时学习使用你做的工具,所以请尽量把工具做的直观好用(参考我的文档)。就像 Mike Muuss 提及到他自己的 ping 程序:“要是我早知道这是我一生中最出名的成就,我就多开发一两天,添加更多选项。”
  • 高级语言:如果现有的 bcc 前端语言让你很困扰,或许你能弄门更好的语言。要是你想将这门语言内建到 bcc 里面,你需要使用 libbcc。或者你可以帮助 SystemTap BPF 或 ply 的工作。
  • 整合图形界面:除了 bcc 可以使用的 CLI 命令行工具,怎么让这些信息可视呢?延迟热点图,火焰图等等。

其它追踪器

那么 SystemTap、ktap、sysdig、LTTng 等追踪器怎么样呢?它们有个共同点,要么使用了 BPF,要么在自己的领域做得更好。会有单独的文章介绍它们自己。

至于 DTrace ?我们公司目前还在基于 FreeBSD 系统的 CDN 中使用它。

更多 bcc/BPF 的信息

我已经写了一篇《bcc/BPF 工具最终用户教程》,一篇《bcc Python 开发者教程》,一篇《bcc/BPF 参考手册》,并提供了一些有用的工具,每一个工具都有一个 example.txt 文件和 man page。我之前写过的关于 bcc 和 BPF 的文章有:

我在 Facebook 的 Performance@Scale Linux BPF Superpowers 大会上发表过一次演讲。十二月份,我将在 Boston 发表关于 BPF/bcc 在 USENIX LISA 方面的演讲和教程。

致谢

  • Van Jacobson 和 Steve McCanne,他们创建了最初用作过滤器的 BPF 。
  • Barton P. Miller,Jeffrey K. Hollingsworth,and Jon Cargille,发明了动态追踪,并发表论文《Dynamic Program Instrumentation for Scalable Performance Tools》,可扩展高性能计算协议 (SHPCC),于田纳西州诺克斯维尔市,1994 年 5 月发表。
  • kerninst (ParaDyn, UW-Madison),展示了动态跟踪的价值的早期动态跟踪工具(上世纪 90 年代后期)
  • Mathieu Desnoyers (在 LTTng),内核的主要开发者,主导 tracepoints 项目。
  • IBM 开发的作为 DProbes 一部分的 kprobes,DProbes 在 2000 年时曾与 LTT 一起提供 Linux 动态追踪,但没有整合到一起。
  • Bryan Cantrill, Mike Shapiro, and Adam Leventhal (Sun Microsystems),DTrace 的核心开发者,DTrace 是一款很棒的动态追踪工具,安全而且简单(2004 年)。对于动态追踪技术,DTrace 是科技的重要转折点:它很安全,默认安装在 Solaris 以及其它以可靠性著称的系统里。
  • 来自 Sun Microsystems 的各部门的许多员工,促进了 DTrace,为我们带来了高级系统追踪的意识。
  • Roland McGrath (在 Red Hat),utrace 项目的主要开发者,utrace 变成了后来的 uprobes。
  • Alexei Starovoitov (PLUMgrid, 后来是 Facebook),加强版 BPF(可编程内核部件)的主要开发者。
  • 那些帮助反馈、提交代码、测试以及针对增强版 BPF 补丁(请在 lkml 搜索 BPF)的 Linux 内核工程师: Wang Nan、 Daniel Borkmann、 David S. Miller、 Peter Zijlstra 以及其它很多人。
  • Brenden Blanco (PLUMgrid),bcc 的主要开发者。
  • Sasha Goldshtein (Sela) 开发了 bcc 中的跟踪点支持,和功能最强大的 bcc 工具 trace 及 argdist,帮助 USDT 项目的开发。
  • Vicent Martí 和其它 Github 上的工程师,为 bcc 编写了基于 lua 的前端,帮助 USDT 部分项目的开发。
  • Allan McAleavy、 Mark Drayton,和其他的改进 bcc 的贡献者。

感觉 Netflix 提供的环境和支持,让我能够编写 BPF 和 bcc 跟踪器并完成它们。我已经编写了多年的追踪工具(使用 TNF/prex、DTrace、SystemTap、ktap、ftrace、perf,现在是 bcc/BPF),并写书、博客以及评论,

最后,感谢 Deirdré 编辑了另外一篇文章。

总结

Linux 没有 DTrace(语言),但它现在有了,或者说拥有了 DTraceTookit(工具)。

通过增强内置的 BPF 引擎,Linux 4.9 内核拥有了用来支持现代化追踪的最后一项能力。内核支持这一最难的部分已经做完了。今后的任务包括更多的命令行执行工具,以及高级语言和图形用户界面。

对于性能分析产品的客户,这也是一件好事:你能查看延迟柱状图和热点图,CPU 处理和 CPU 之外的火焰图,拥有更好的时延断点和更低耗的工具。在用户空间按包跟踪和处理是没有效率的方式。

那么你什么时候会升级到 Linux 4.9 呢?一旦官方发布,新的性能测试工具就来了:apt-get install bcc-tools

开始享受它吧!

Brendan


via: http://www.brendangregg.com/blog/2016-10-27/dtrace-for-linux-2016.html

作者:Brendan Gregg 译者:GitFuture 校对:wxy

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

编者注:本文是 2016 年 4 月 Nicole Whilte 在欧洲 GraphConnect 时所作。这儿我们快速回顾一下她所涉及的内容:

  • 图数据库推荐基础
  • 社会化推荐
  • 相似性推荐
  • 集群推荐

今天我们将要讨论的内容是数据科学和 图推荐 graph recommendations

我在 Neo4j 任职已经两年了,但实际上我已经使用 Neo4j 和 Cypher 工作三年了。当我首次发现这个特别的 图数据库 graph database 的时候,我还是一个研究生,那时候我在奥斯丁的德克萨斯大学攻读关于社交网络的统计学硕士学位。

实时推荐引擎是 Neo4j 中最广泛的用途之一,也是使它如此强大并且容易使用的原因之一。为了探索这个东西,我将通过使用示例数据集来阐述如何将统计学方法并入这些引擎中。

第一个很简单 - 将 Cypher 用于社交推荐。接下来,我们将看一看相似性推荐,这涉及到可被计算的相似性度量,最后探索的是集群推荐。

图数据库推荐基础

下面的数据集包含所有达拉斯 Fort Worth 国际机场的餐饮场所,达拉斯 Fort Worth 国际机场是美国主要的机场枢纽之一:

我们把节点标记成黄色并按照出入口和航站楼给它们的位置建模。同时我们也按照食物和饮料的主类别将地点分类,其中一些包括墨西哥食物、三明治、酒吧和烤肉。

让我们做一个简单的推荐。我们想要在机场的某一确定地点找到一种特定食物,大括号中的内容表示是的用户输入,它将进入我们的假想应用程序中。

这个英文句子表示成 Cypher 查询:

这将提取出该类别中用户所请求的所有地点、航站楼和出入口。然后我们可以计算出用户所在位置到出入口的准确距离,并以升序返回结果。再次说明,这个非常简单的 Cypher 推荐仅仅依据的是用户在机场中的位置。

社交推荐 Social Recommendations

让我们来看一下社交推荐。在我们的假想应用程序中,用户可以登录并且可以用和 Facebook 类似的方式标记自己“喜好”的地点,也可以在某地签到。

考虑位于我们所研究的第一个模型之上的数据模型,现在让我们在下面的分类中找到用户的朋友喜好的航站楼里面离出入口最近的餐饮场所:

MATCH 子句和我们第一次 Cypher 查询的 MATCH 子句相似,只是现在我们依据喜好和朋友来匹配:

前三行是完全一样的,但是现在要考虑的是那些登录的用户,我们想要通过 :FRIENDS_WITH 这一关系来找到他们的朋友。仅需通过在 Cypher 中增加一些行内容,我们现在已经把社交层面考虑到了我们的推荐引擎中。

再次说明,我们仅仅显示了用户明确请求的类别,并且这些类别中的地点与用户进入的地方是相同的航站楼。当然,我们希望按照登录并做出请求的用户来滤过这些目录,然后返回地点的名字、位置以及所在目录。我们也要显示出有多少朋友已经“喜好”那个地点以及那个地点到出入口的确切距离,然后在 RETURN 子句中同时返回所有这些内容。

相似性推荐 Similarity Recommendations

现在,让我们看一看相似性推荐引擎:

和前面的数据模型相似,用户可以标记“喜好”的地点,但是这一次他们可以用 1 到 10 的整数给地点评分。这是通过前期在 Neo4j 中增加一些属性到关系中建模实现的。

这将允许我们找到其他相似的用户,比如以上面的 Greta 和 Alice 为例,我们已经查询了他们共同喜好的地点,并且对于每一个地点,我们可以看到他们所设定的权重。大概地,我们可以通过他们的评分来确定他们之间的相似性大小。

现在我们有两个向量:

现在让我们按照 欧几里得距离 Euclidean distance 的定义来计算这两个向量之间的距离:

我们把所有的数字带入公式中计算,然后得到下面的相似度,这就是两个用户之间的“距离”:

你可以很容易地在 Cypher 中计算两个特定用户的“距离”,特别是如果他们仅仅同时“喜好”一个很小的地点子集。再次说明,这儿我们依据两个用户 Alice 和 Greta 来进行匹配,并尝试去找到他们同时“喜好”的地点:

他们都有对最后找到的地点的 :LIKES 关系,然后我们可以在 Cypher 中很容易的计算出他们之间的欧几里得距离,计算方法为他们对各个地点评分差的平方求和再开平方根。

在两个特定用户的例子中上面这个方法或许能够工作。但是,在实时情况下,当你想要通过和实时数据库中的其他用户比较,从而由一架飞机上的一个用户推断相似用户时,这个方法就不一定能够工作。不用说,至少它不能够很好的工作。

为了找到解决这个问题的好方法,我们可以预先计算好距离并存入实际关系中:

当遇到一个很大的数据集时,我们需要成批处理这件事,在这个很小的示例数据集中,我们可以按照所有用户的 迪卡尔乘积 Cartesian product 和他们共同“喜好”的地点来进行匹配。当我们使用 WHERE id(u1) < id(u2) 作为 Cypher 询问的一部分时,它只是来确定我们在左边和右边没有找到相同的对的一个技巧。

通过用户之间的欧几里得距离,我们创建了他们之间的一种关系,叫做 :DISTANCE,并且设置了一个叫做 euclidean 的欧几里得属性。理论上,我们可以也通过用户间的一些关系来存储其他相似度从而获取不同的相似度,因为在确定的环境下某些相似度可能比其他相似度更有用。

在 Neo4j 中,的确是对关系属性建模的能力使得完成像这样的事情无比简单。然而,实际上,你不会希望存储每一个可能存在的单一关系,因为你仅仅希望返回离他们“最近”的一些人。

因此你可以根据一些临界值来存入前几个,从而你不需要构建完整的连通图。这允许你完成一些像下面这样的实时的数据库查询,因为我们已经预先计算好了“距离”并存储在了关系中,在 Cypher 中,我们能够很快的攫取出数据。

在这个查询中,我们依据地点和类别来进行匹配:

再次说明,前三行是相同的,除了登录用户以外,我们找出了和他们有 :DISTANCE 关系的用户。这是我们前面查看的关系产生的作用 - 实际上,你只需要存储处于前几位的相似用户 :DISTANCE 关系,因此你不需要在 MATCH 子句中攫取大量用户。相反,我们只攫取和那些用户“喜好”的地方有 :DISTANCE 关系的用户。

这允许我们用少许几行内容表达较为复杂的模型。我们也可以攫取 :LIKES 关系并把它放入到变量中,因为后面我们将使用这些权重来评分。

在这儿重要的是,我们可以依据“距离”大小将用户按照升序进行排序,因为这是一个距离测度。同时,我们想要找到用户间的最小距离因为距离越小表明他们的相似度最大。

通过其他按照欧几里得距离大小排序好的用户,我们得到用户评分最高的三个地点并按照用户的平均评分高低来推荐这些地点。换句话说,我们先找出一个活跃用户,然后依据其他用户“喜好”的地点找出和他最相似的其他用户,接下来按照这些相似用户的平均评分把那些地点排序在结果的集合中。

本质上,我们通过把所有评分相加然后除以收集的用户数目来计算出平均分,然后按照平均评分的升序进行排序。其次,我们按照出入口距离排序。假想地,我猜测应该会有交接点,因此你可以按照出入口距离排序然后再返回名字、类别、出入口和航站楼。

集群推荐 Cluster Recommendations

我们最后要讲的一个例子是集群推荐,在 Cypher 中,这可以被想像成一个作为临时解决方案的离线计算工作流。这可能完全基于在欧洲 GraphConnect 上宣布的新方法,但是有时你必须进行一些 Cypher 2.3 版本所没有的算法逼近。

在这儿你可以使用一些统计软件,把数据从 Neo4j 取出然后放入像 Apache Spark、R 或者 Python 这样的软件中。下面是一段把数据从 Neo4j 中取出的 R 代码,运行该程序,如果正确,写下程序返回结果的给 Neo4j,可以是一个属性、节点、关系或者一个新的标签。

通过持续把程序运行结果放入到图表中,你可以在一个和我们刚刚看到的查询相似的实时查询中使用它:

下面是用 R 来完成这件事的一些示例代码,但是你可以使用任何你最喜欢的软件来做这件事,比如 Python 或 Spark。你需要做的只是登录并连接到图表。

在下面的例子中,我基于用户的相似性把他们聚合起来。每个用户作为一个观察点,然后得到他们对每一个目录评分的平均值。

假定用户对酒吧类评分的方式和一般的评分方式相似。然后我攫取出喜欢相同类别中的地点的用户名、类别名、“喜好”关系的平均权重,比如平均权重这些信息,从而我可以得到下面这样一个表格:

因为我们把每一个用户都作为一个观察点,所以我们必须巧妙的处理每一个类别中的数据,这些数据的每一个特性都是用户对该类中餐厅评分的平均权重。接下来,我们将使用这些数据来确定用户的相似性,然后我将使用 聚类 clustering 算法来确定在不同集群中的用户。

在 R 中这很直接:

在这个示例中我们使用 K-均值 k-means 聚类算法,这将使你很容易攫取集群分配。总之,我通过运行聚类算法然后分别得到每一个用户的集群分配。

Bob 和 David 在一个相同的集群中 - 他们在集群二中 - 现在我可以实时查看哪些用户被放在了相同的集群中。

接下来我把集群分配写入 CSV 文件中,然后存入图数据库:

我们只有用户和集群分配,因此 CSV 文件只有两列。 LOAD CSV 是 Cypher 中的内建语法,它允许你从一些其他文件路径或者 URL 调用 CSV ,并给它一个别名。接下来,我们将匹配图数据库中存在的用户,从 CSV 文件中攫取用户列然后合并到集群中。

我们在图表中创建了一个新的标签节点:Cluster ID, 这是由 K-平均聚类算法给出的。接下来我们创建用户和集群间的关系,通过创建这个关系,当我们想要找到在相同集群中的实际推荐用户时,就会很容易进行查询。

我们现在有了一个新的集群标签,在相同集群中的用户和那个集群存在关系。新的数据模型看起来像下面这样,它比我们前面探索的其他数据模型要更好:

现在让我们考虑下面的查询:

通过这个 Cypher 查询,我们在更远处找到了在同一个集群中的相似用户。由于这个原因,我们删除了“距离”关系:

在这个查询中,我们取出已经登录的用户,根据用户-集群关系找到他们所在的集群,找到他们附近和他们在相同集群中的用户。

我们把这些用户分配到变量 c1 中,然后我们得到其他被我取别名为 neighbor 变量的用户,这些用户和那个相同集群存在着用户-集群关系,最后我们得到这些附近用户“喜好”的地点。再次说明,我把“喜好”放入了变量 r 中,因为我们需要从关系中攫取权重来对结果进行排序。

在这个查询中,我们所做的改变是,不使用相似性距离,而是攫取在相同集群中的用户,然后对类别、航站楼以及我们所攫取的登录用户进行声明。我们收集所有的权重:来自附近用户“喜好”地点的“喜好”关系,得到的类别,确定的距离值,然后把它们按升序进行排序并返回结果。

在这些例子中,我们可以进行一个相当复杂的处理并且将其放到图数据库中,然后我们就可以使用实时算法结果-聚类算法和集群分配的结果。

我们更喜欢的工作流程是更新这些集群分配,更新频率适合你自己就可以,比如每晚一次或每小时一次。当然,你可以根据直觉来决定多久更新一次这些集群分配是可接受的。


via: https://neo4j.com/blog/real-time-recommendation-engine-data-science/

作者:Nicole White 译者:ucasFL 校对:wxy

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