2017年12月

此前我们介绍了如何在命令行中使用 Google 搜索。许多读者反馈说他们平时使用 Duck Duck Go,这是一个功能强大而且保密性很强的搜索引擎。

正巧,最近出现了一款能够从命令行搜索 DuckDuckGo 的工具。它叫做 ddgr(我把它读作 “dodger”),非常好用。

Googler 一样,ddgr 是一个完全开源而且非官方的工具。没错,它并不属于 DuckDuckGo。所以,如果你发现它返回的结果有些奇怪,请先询问这个工具的开发者,而不是搜索引擎的开发者。

DuckDuckGo 命令行应用

DuckDuckGo Bangs(DuckDuckGo 快捷搜索) 可以帮助你轻易地在 DuckDuckGo 上找到想要的信息(甚至 本网站 omgubuntu 都有快捷搜索)。ddgr 非常忠实地呈现了这个功能。

和网页版不同的是,你可以更改每页返回多少结果。这比起每次查询都要看三十多条结果要方便一些。默认界面经过了精心设计,在不影响可读性的情况下尽量减少了占用空间。

ddgr 有许多功能和亮点,包括:

  • 更改搜索结果数
  • 支持 Bash 自动补全
  • 使用 DuckDuckGo Bangs
  • 在浏览器中打开链接
  • ”手气不错“选项
  • 基于时间、地区、文件类型等的筛选功能
  • 极少的依赖项

你可以从 Github 的项目页面上下载支持各种系统的 ddgr

另外,在 Ubuntu 16.04 LTS 或更新版本中,你可以使用 PPA 安装 ddgr。这个仓库由 ddgr 的开发者维护。如果你想要保持在最新版本的话,推荐使用这种方式安装。

需要提醒的是,在本文创作时,这个 PPA 中的 ddgr 并不是 最新版本,而是一个稍旧的版本(缺少 -num 选项)。

使用以下命令添加 PPA:

sudo add-apt-repository ppa:twodopeshaggy/jarun
sudo apt-get update

如何使用 ddgr 在命令行中搜索 DuckDuckGo

安装完毕后,你只需打开你的终端模拟器,并运行:

ddgr

然后输入查询内容:

search-term

你可以限制搜索结果数:

ddgr --num 5 search-term

或者自动在浏览器中打开第一条搜索结果:

ddgr -j search-term

你可以使用参数和选项来提高搜索精确度。使用以下命令来查看所有的参数:

ddgr -h

via: http://www.omgubuntu.co.uk/2017/11/duck-duck-go-terminal-app

作者:JOEY SNEDDON 译者:yixunx 校对:wxy

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

 title=

2017年开源工作报告(以下简称“报告”)显示,具有开源云技术认证的系统管理员往往能获得更高的薪酬。

报告调查的受访者中,53% 认为系统管理员是雇主们最期望被填补的职位空缺之一,因此,技术娴熟的系统管理员更受青睐而收获高薪职位,但这一职位,并没想象中那么容易填补。

系统管理员主要负责服务器和其他电脑操作系统的安装、服务支持和维护,及时处理服务中断和预防其他问题的出现。

总的来说,今年的报告指出开源领域人才需求最大的有开源云(47%),应用开发(44%),大数据(43%),开发运营和安全(42%)。

此外,报告对人事经理的调查显示,58% 期望招揽更多的开源人才,67% 认为开源人才的需求增长会比业内其他领域更甚。有些单位视开源人才为招聘最优选则,它们招聘的开源人才较上年增长了 2 个百分点。

同时,89% 的人事经理认为很难找到颇具天赋的开源人才。

为什么要获取认证

报告显示,对系统管理员的需求刺激着人事经理为 53% 的组织/机构提供正规的培训和专业技术认证,而这一比例去年为 47%。

对系统管理方面感兴趣的 IT 人才考虑获取 Linux 认证已成为行业规律。随便查看几个知名的招聘网站,你就能发现:CompTIA Linux+ 认证是入门级 Linux 系统管理员的最高认证;如果想胜任高级别的系统管理员职位,获取红帽认证工程师(RHCE)红帽认证系统管理员(RHCSA)则是不可或缺的。

戴士(Dice)2017 技术行业薪资调查显示,2016 年系统管理员的薪水为 79,538 美元,较上年下降了 0.8%;系统架构师的薪水为 125,946 美元,同比下降 4.7%。尽管如此,该调查发现“高水平专业人才仍最受欢迎,特别是那些精通支持产业转型发展所需技术的人才”。

在开源技术方面,HBase(一个开源的分布式数据库)技术人才的薪水在戴士 2017 技术行业薪资调查中排第一。在计算机网络和数据库领域,掌握 OpenVMS 操作系统技术也能获得高薪。

成为出色的系统管理员

出色的系统管理员须在问题出现时马上处理,这意味着你必须时刻准备应对可能出现的状况。这个职位追求“零责备的、精益的、流程或技术上交互式改进的”思维方式和善于自我完善的人格,成为一个系统管理员意味着“你必将与开源软件如 Linux、BSD 甚至开源 Solaris 等结下不解之缘”,Paul English 译注1opensource.com 上发文指出。

Paul English 认为,现在的系统管理员较以前而言,要更多地与软件打交道,而且要能够编写脚本来协助系统管理。

译注1:Paul English,计算机科学学士,UNIX/Linux 系统管理员,PreOS Security Inc. 公司 CEO,2015-2017 年于为推动系统管理员发展实践的非盈利组织—— 专业系统管理员联盟 League of Professional System Administrator 担任董事会成员。

展望 2018

Robert Half 2018 年技术人才薪资导览预测 2018 年北美地区许多单位将聘用大量系统管理方面的专业人才,同时个人软实力和领导力水平作为优秀人才的考量因素,越来越受到重视。

该报告指出:“良好的聆听能力和批判性思维能力对于理解和解决用户的问题和担忧至关重要,也是 IT 从业者必须具备的重要技能,特别是从事服务台和桌面支持工作相关的技术人员。”

这与Linux基金会 译注2 提出的不同阶段的系统管理员必备技能相一致,都强调了强大的分析能力和快速处理问题的能力。

译注2: Linux 基金会 The Linux Foundation ,成立于 2000 年,致力于围绕开源项目构建可持续发展的生态系统,以加速开源项目的技术开发和商业应用;它是世界上最大的开源非盈利组织,在推广、保护和推进 Linux 发展,协同开发,维护“历史上最大的共享资源”上功勋卓越。

如果想逐渐爬上系统管理员职位的金字塔上层,还应该对系统配置的结构化方法充满兴趣;且拥有解决系统安全问题的经验;用户身份验证管理的经验;与非技术人员进行非技术交流的能力;以及优化系统以满足最新的安全需求的能力。

  • 下载2017年开源工作报告全文,以获取更多信息。

via: https://www.linux.com/blog/open-source-cloud-skills-and-certification-are-key-sysadmins

作者:linux.com 译者:wangy325 校对:wxy

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

如果你尝试在 Ubuntu 下连接你的安卓手机,你也许可以试试 Linux 下的安卓文件传输助手。

本质上来说,这个应用是谷歌 macOS 版本的一个克隆。它是用 Qt 编写的,用户界面非常简洁,使得你能轻松在 Ubuntu 和安卓手机之间传输文件和文件夹。

现在,有可能一部分人想知道有什么是这个应用可以做,而 Nautilus(Ubuntu 默认的文件资源管理器)不能做的,答案是没有。

当我将我的 Nexus 5X(记得选择 媒体传输协议 MTP 选项)连接在 Ubuntu 上时,在 GVfs(LCTT 译注: GNOME 桌面下的虚拟文件系统)的帮助下,我可以打开、浏览和管理我的手机,就像它是一个普通的 U 盘一样。

Nautilus MTP integration with a Nexus 5X

但是一些用户在使用默认的文件管理器时,在 MTP 的某些功能上会出现问题:比如文件夹没有正确加载,创建新文件夹后此文件夹不存在,或者无法在媒体播放器中使用自己的手机。

这就是要为 Linux 系统用户设计一个安卓文件传输助手应用的原因,将这个应用当做将 MTP 设备安装在 Linux 下的另一种选择。如果你使用 Linux 下的默认应用时一切正常,你也许并不需要尝试使用它 (除非你真的很想尝试新鲜事物)。

Android File Transfer Linux App

该 app 特点:

  • 简洁直观的用户界面
  • 支持文件拖放功能(从 Linux 系统到手机)
  • 支持批量下载 (从手机到 Linux系统)
  • 显示传输进程对话框
  • FUSE 模块支持
  • 没有文件大小限制
  • 可选命令行工具

Ubuntu 下安装安卓手机文件助手的步骤

以上就是对这个应用的介绍,下面是如何安装它的具体步骤。

这有一个 [PPA](个人软件包集)源为 Ubuntu 14.04 LTS、16.04 LTS 和 Ubuntu 17.10 提供可用应用。

为了将这一 PPA 加入你的软件资源列表中,执行这条命令:

sudo add-apt-repository ppa:samoilov-lex/aftl-stable

接着,为了在 Ubuntu 下安装 Linux版本的安卓文件传输助手,执行:

sudo apt-get update && sudo apt install android-file-transfer

这样就行了。

你会在你的应用列表中发现这一应用的启动图标。

在你启动这一应用之前,要确保没有其他应用(比如 Nautilus)已经挂载了你的手机。如果其它应用正在使用你的手机,就会显示“无法找到 MTP 设备”。要解决这一问题,将你的手机从 Nautilus(或者任何正在使用你的手机的应用)上移除,然后再重新启动安卓文件传输助手。


via: http://www.omgubuntu.co.uk/2017/11/android-file-transfer-app-linux

作者:JOEY SNEDDON 译者:wenwensnow 校对:wxy

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

Linux 系统提供了许多有用的命令来检查网络配置和连接。下面来看几个,包括 ifqueryifupifdownifconfig

Linux 上有许多可用于查看网络设置和连接的命令。在今天的文章中,我们将会通过一些非常方便的命令来看看它们是如何工作的。

ifquery 命令

一个非常有用的命令是 ifquery。这个命令应该会显示一个网络接口列表。但是,你可能只会看到类似这样的内容 - 仅显示回环接口:

$ ifquery --list
lo

如果是这种情况,那说明你的 /etc/network/interfaces 不包括除了回环接口之外的网络接口信息。在下面的例子中,假设你使用 DHCP 来分配地址,且如果你希望它更有用的话,你可以添加例子最后的两行。

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp

ifup 和 ifdown 命令

可以使用相关的 ifupifdown 命令来打开网络连接并根据需要将其关闭,只要该文件具有所需的描述性数据即可。请记住,“if” 在这里意思是 接口 interface ,这与 ifconfig 命令中的一样,而不是 如果我只有一个大脑 if I only had a brain 中的 “if”。

ifconfig 命令

另外,ifconfig 命令完全不读取 /etc/network/interfaces,但是仍然提供了网络接口相当多的有用信息 —— 配置数据以及可以告诉你每个接口有多忙的数据包计数。ifconfig 命令也可用于关闭和重新启动网络接口(例如:ifconfig eth0 down)。

$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:1e:4f:c8:43:fc
          inet addr:192.168.0.6  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::b44b:bdb6:2527:6ae9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:60474 errors:0 dropped:0 overruns:0 frame:0
          TX packets:33463 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:43922053 (43.9 MB)  TX bytes:4000460 (4.0 MB)
          Interrupt:21 Memory:fe9e0000-fea00000

输出中的 RX 和 TX 数据包计数很低。此外,没有报告错误或数据包冲突。或许可以用 uptime 命令确认此系统最近才重新启动。

上面显示的广播 (Bcast) 和网络掩码 (Mask) 地址表明系统运行在 C 类等效网络(默认)上,所以本地地址范围从 192.168.0.1192.168.0.254

netstat 命令

netstat 命令提供有关路由和网络连接的信息。netstat -rn 命令显示系统的路由表。192.168.0.1 是本地网关 (Flags=UG)。

$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.0.1     0.0.0.0         UG        0 0          0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0
192.168.0.0     0.0.0.0         255.255.255.0   U         0 0          0 eth0

上面输出中的 169.254.0.0 条目仅在你正在使用或计划使用本地链路通信时才有必要。如果不是这样的话,你可以在 /etc/network/if-up.d/avahi-autoipd 中注释掉相关的行:

$ tail -12 /etc/network/if-up.d/avahi-autoipd
#if [ -x /bin/ip ]; then
#       # route already present?
#       ip route show | grep -q '^169.254.0.0/16[[:space:]]' && exit 0
#
#       /bin/ip route add 169.254.0.0/16 dev $IFACE metric 1000 scope link
#elif [ -x /sbin/route ]; then
#       # route already present?
#       /sbin/route -n | egrep -q "^169.254.0.0[[:space:]]" && exit 0
#
#       /sbin/route add -net 169.254.0.0 netmask 255.255.0.0 dev $IFACE metric 1000
#fi

netstat -a 命令

netstat -a 命令将显示“所有”网络连接。为了将其限制为显示正在监听和已建立的连接(通常更有用),请改用 netstat -at 命令。

$ netstat -at
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 *:ssh                   *:*                     LISTEN
tcp        0      0 localhost:ipp           *:*                     LISTEN
tcp        0      0 localhost:smtp          *:*                     LISTEN
tcp        0    256 192.168.0.6:ssh         192.168.0.32:53550      ESTABLISHED
tcp6       0      0 [::]:http               [::]:*                  LISTEN
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN
tcp6       0      0 ip6-localhost:ipp       [::]:*                  LISTEN
tcp6       0      0 ip6-localhost:smtp      [::]:*                  LISTEN

host 命令

host 命令就像 nslookup 一样,用来查询远程系统的 IP 地址,但是还提供系统的邮箱处理地址。

$ host world.std.com
world.std.com has address 192.74.137.5
world.std.com mail is handled by 10 smtp.theworld.com.

nslookup 命令

nslookup 还提供系统中(本例中是本地系统)提供 DNS 查询服务的信息。

$ nslookup world.std.com
Server:         127.0.1.1
Address:        127.0.1.1#53

Non-authoritative answer:
Name:   world.std.com
Address: 192.74.137.5

dig 命令

dig 命令提供了很多有关连接到远程系统的信息 - 包括与我们通信的名称服务器以及查询需要多长时间进行响应,并经常用于故障排除。

$ dig world.std.com

; <<>> DiG 9.10.3-P4-Ubuntu <<>> world.std.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28679
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;world.std.com.                 IN      A

;; ANSWER SECTION:
world.std.com.          78146   IN      A       192.74.137.5

;; Query time: 37 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Mon Oct 09 13:26:46 EDT 2017
;; MSG SIZE  rcvd: 58

nmap 命令

nmap 经常用于探查远程系统,但是同样也用于报告本地系统提供的服务。在下面的输出中,我们可以看到登录可以使用 ssh、smtp 用于电子邮箱、web 站点也是启用的,并且 ipp 打印服务正在运行。

$ nmap localhost

Starting Nmap 7.01 ( https://nmap.org ) at 2017-10-09 15:01 EDT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00016s latency).
Not shown: 996 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh
25/tcp  open  smtp
80/tcp  open  http
631/tcp open  ipp

Nmap done: 1 IP address (1 host up) scanned in 0.09 seconds

Linux 系统提供了很多有用的命令用于查看网络配置和连接。如果你都探索完了,请记住 apropos network 或许会让你了解更多。


via: https://www.networkworld.com/article/3230519/linux/examining-network-connections-on-linux-systems.html

作者:Sandra Henry-Stocker 译者:geekpi 校对:wxy

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

介绍

kprobes 是一种内核功能,它允许通过在执行(或模拟)断点指令之前和之后,设置调用开发者提供例程的任意断点来检测内核。可参见 kprobes 文档 注1 获取更多信息。基本的 kprobes 功能可使用 CONFIG_KPROBEES 来选择。在 arm64 的 v4.8 内核发行版中, kprobes 支持被添加到主线。

在这篇文章中,我们将介绍 kprobes 在 arm64 上的使用,通过在命令行中使用 debugfs 事件追踪接口来收集动态追踪事件。这个功能在一些架构(包括 arm32)上可用已经有段时间,现在在 arm64 上也能使用了。这个功能可以无需编写任何代码就能使用 kprobes。

探针类型

kprobes 子系统提供了三种不同类型的动态探针,如下所述。

kprobes

基本探针是 kprobes 插入的一个软件断点,用以替代你正在探测的指令,当探测点被命中时,它为最终的单步执行(或模拟)保存下原始指令。

kretprobes

kretprobes 是 kprobes 的一部分,它允许拦截返回函数,而不必在返回点设置一个探针(或者可能有多个探针)。对于支持的架构(包括 ARMv8),只要选择 kprobes,就可以选择此功能。

jprobes

jprobes 允许通过提供一个具有相同 调用签名 call signature 的中间函数来拦截对一个函数的调用,这里中间函数将被首先调用。jprobes 只是一个编程接口,它不能通过 debugfs 事件追踪子系统来使用。因此,我们将不会在这里进一步讨论 jprobes。如果你想使用 jprobes,请参考 kprobes 文档。

调用 kprobes

kprobes 提供一系列能从内核代码中调用的 API 来设置探测点和当探测点被命中时调用的注册函数。在不往内核中添加代码的情况下,kprobes 也是可用的,这是通过写入特定事件追踪的 debugfs 文件来实现的,需要在文件中设置探针地址和信息,以便在探针被命中时记录到追踪日志中。后者是本文将要讨论的重点。最后 kprobes 可以通过 perl 命令来使用。

kprobes API

内核开发人员可以在内核中编写函数(通常在专用的调试模块中完成)来设置探测点,并且在探测指令执行前和执行后立即执行任何所需操作。这在 kprobes.txt 中有很好的解释。

事件追踪

事件追踪子系统有自己的自己的文档 注2 ,对于了解一般追踪事件的背景可能值得一读。事件追踪子系统是 追踪点 tracepoints 和 kprobes 事件追踪的基础。事件追踪文档重点关注追踪点,所以请在查阅文档时记住这一点。kprobes 与追踪点不同的是没有预定义的追踪点列表,而是采用动态创建的用于触发追踪事件信息收集的任意探测点。事件追踪子系统通过一系列 debugfs 文件来控制和监视。事件追踪(CONFIG_EVENT_TRACING)将在被如 kprobe 事件追踪子系统等需要时自动选择。

kprobes 事件

使用 kprobes 事件追踪子系统,用户可以在内核任意断点处指定要报告的信息,只需要指定任意现有可探测指令的地址以及格式化信息即可确定。在执行过程中遇到断点时,kprobes 将所请求的信息传递给事件追踪子系统的公共部分,这些部分将数据格式化并追加到追踪日志中,就像追踪点的工作方式一样。kprobes 使用一个类似的但是大部分是独立的 debugfs 文件来控制和显示追踪事件信息。该功能可使用 CONFIG_KPROBE_EVENT 来选择。Kprobetrace 文档^ 注3 提供了如何使用 kprobes 事件追踪的基本信息,并且应当被参考用以了解以下介绍示例的详细信息。

kprobes 和 perf

perf 工具为 kprobes 提供了另一个命令行接口。特别地,perf probe 允许探测点除了由函数名加偏移量和地址指定外,还可由源文件和行号指定。perf 接口实际上是使用 kprobes 的 debugfs 接口的封装器。

Arm64 kprobes

上述所有 kprobes 的方面现在都在 arm64 上得到实现,然而实际上与其它架构上的有一些不同:

  • 注册名称参数当然是依架构而特定的,并且可以在 ARM ARM 中找到。
  • 目前不是所有的指令类型都可被探测。当前不可探测的指令包括 mrs/msr(除了 DAIF 读取)、异常生成指令、eret 和 hint(除了 nop 变体)。在这些情况下,只探测一个附近的指令来代替是最简单的。这些指令在探测的黑名单里是因为在 kprobes 单步执行或者指令模拟时它们对处理器状态造成的改变是不安全的,这是由于 kprobes 构造的单步执行上下文和指令所需要的不一致,或者是由于指令不能容忍在 kprobes 中额外的处理时间和异常处理(ldx/stx)。
  • 试图识别在 ldx/stx 序列中的指令并且防止探测,但是理论上这种检查可能会失败,导致允许探测到的原子序列永远不会成功。当探测原子代码序列附近时应该小心。
  • 注意由于 linux ARM64 调用约定的具体信息,为探测函数可靠地复制栈帧是不可能的,基于此不要试图用 jprobes 这样做,这一点与支持 jprobes 的大多数其它架构不同。这样的原因是被调用者没有足够的信息来确定需要的栈数量。
  • 注意当探针被命中时,一个探针记录的栈指针信息将反映出使用中的特定栈指针,它是内核栈指针或者中断栈指针。
  • 有一组内核函数是不能被探测的,通常因为它们作为 kprobes 处理的一部分被调用。这组函数的一部分是依架构特定的,并且也包含如异常入口代码等。

使用 kprobes 事件追踪

kprobes 的一个常用例子是检测函数入口和/或出口。因为只需要使用函数名来作为探针地址,它安装探针特别简单。kprobes 事件追踪将查看符号名称并且确定地址。ARMv8 调用标准定义了函数参数和返回值的位置,并且这些可以作为 kprobes 事件处理的一部分被打印出来。

例子: 函数入口探测

检测 USB 以太网驱动程序复位功能:

$ pwd
/sys/kernel/debug/tracing
$ cat > kprobe_events <<EOF
p ax88772_reset %x0
EOF
$ echo 1 > events/kprobes/enable

此时每次该驱动的 ax8872_reset() 函数被调用,追踪事件都将会被记录。这个事件将显示指向通过作为此函数的唯一参数的 X0(按照 ARMv8 调用标准)传入的 usbnet 结构的指针。插入需要以太网驱动程序的 USB 加密狗后,我们看见以下追踪信息:

$ cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 1/1   #P:8
#
#                           _—–=> irqs-off
#                          / _—-=> need-resched
#                         | / _—=> hardirq/softirq
#                         || / _–=> preempt-depth
#                         ||| / delay
#        TASK-PID   CPU#  |||| TIMESTAMP  FUNCTION
#           | |    |   ||||    |      |
kworker/0:0-4             [000] d… 10972.102939:   p_ax88772_reset_0:
(ax88772_reset+0x0/0x230)   arg1=0xffff800064824c80

这里我们可以看见传入到我们的探测函数的指针参数的值。由于我们没有使用 kprobes 事件追踪的可选标签功能,我们需要的信息自动被标注为 arg1。注意这指向我们需要 kprobes 记录这个探针的一组值的第一个,而不是函数参数的实际位置。在这个例子中它也只是碰巧是我们探测函数的第一个参数。

例子: 函数入口和返回探测

kretprobe 功能专门用于探测函数返回。在函数入口 kprobes 子系统将会被调用并且建立钩子以便在函数返回时调用,钩子将记录需求事件信息。对最常见情况,返回信息通常在 X0 寄存器中,这是非常有用的。在 %x0 中返回值也可以被称为 $retval。以下例子也演示了如何提供一个可读的标签来展示有趣的信息。

使用 kprobes 和 kretprobe 检测内核 do_fork() 函数来记录参数和结果的例子:

$ cd /sys/kernel/debug/tracing
$ cat > kprobe_events <<EOF
p _do_fork %x0 %x1 %x2 %x3 %x4 %x5
r _do_fork pid=%x0
EOF
$ echo 1 > events/kprobes/enable

此时每次对 _do_fork() 的调用都会产生两个记录到 trace 文件的 kprobe 事件,一个报告调用参数值,另一个报告返回值。返回值在 trace 文件中将被标记为 pid。这里是三次 fork 系统调用执行后的 trace 文件的内容:

_$ cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 6/6   #P:8
#
#                              _—–=> irqs-off
#                             / _—-=> need-resched
#                            | / _—=> hardirq/softirq
#                            || / _–=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
              bash-1671  [001] d…   204.946007: p__do_fork_0: (_do_fork+0x0/0x3e4) arg1=0x1200011 arg2=0x0 arg3=0x0 arg4=0x0 arg5=0xffff78b690d0 arg6=0x0
              bash-1671  [001] d..1   204.946391: r__do_fork_0: (SyS_clone+0x18/0x20 <- _do_fork) pid=0x724
              bash-1671  [001] d…   208.845749: p__do_fork_0: (_do_fork+0x0/0x3e4) arg1=0x1200011 arg2=0x0 arg3=0x0 arg4=0x0 arg5=0xffff78b690d0 arg6=0x0
              bash-1671  [001] d..1   208.846127: r__do_fork_0: (SyS_clone+0x18/0x20 <- _do_fork) pid=0x725
              bash-1671  [001] d…   214.401604: p__do_fork_0: (_do_fork+0x0/0x3e4) arg1=0x1200011 arg2=0x0 arg3=0x0 arg4=0x0 arg5=0xffff78b690d0 arg6=0x0
              bash-1671  [001] d..1   214.401975: r__do_fork_0: (SyS_clone+0x18/0x20 <- _do_fork) pid=0x726_

例子: 解引用指针参数

对于指针值,kprobes 事件处理子系统也允许解引用和打印所需的内存内容,适用于各种基本数据类型。为了展示所需字段,手动计算结构的偏移量是必要的。

检测 _do_wait() 函数:

$ cat > kprobe_events <<EOF
p:wait_p do_wait wo_type=+0(%x0):u32 wo_flags=+4(%x0):u32
r:wait_r do_wait $retval
EOF
$ echo 1 > events/kprobes/enable

注意在第一个探针中使用的参数标签是可选的,并且可用于更清晰地识别记录在追踪日志中的信息。带符号的偏移量和括号表明了寄存器参数是指向记录在追踪日志中的内存内容的指针。:u32 表明了内存位置包含一个无符号的 4 字节宽的数据(在这个例子中指局部定义的结构中的一个 emum 和一个 int)。

探针标签(冒号后)是可选的,并且将用来识别日志中的探针。对每个探针来说标签必须是独一无二的。如果没有指定,将从附近的符号名称自动生成一个有用的标签,如前面的例子所示。

也要注意 $retval 参数可以只是指定为 %x0

这里是两次 fork 系统调用执行后的 trace 文件的内容:

$ cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 4/4   #P:8
#
#                              _—–=> irqs-off
#                             / _—-=> need-resched
#                            | / _—=> hardirq/softirq
#                            || / _–=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
             bash-1702  [001] d…   175.342074: wait_p: (do_wait+0x0/0x260) wo_type=0x3 wo_flags=0xe
             bash-1702  [002] d..1   175.347236: wait_r: (SyS_wait4+0x74/0xe4 <- do_wait) arg1=0x757
             bash-1702  [002] d…   175.347337: wait_p: (do_wait+0x0/0x260) wo_type=0x3 wo_flags=0xf
             bash-1702  [002] d..1   175.347349: wait_r: (SyS_wait4+0x74/0xe4 <- do_wait) arg1=0xfffffffffffffff6

例子: 探测任意指令地址

在前面的例子中,我们已经为函数的入口和出口插入探针,然而探测一个任意指令(除少数例外)是可能的。如果我们正在 C 函数中放置一个探针,第一步是查看代码的汇编版本以确定我们要放置探针的位置。一种方法是在 vmlinux 文件上使用 gdb,并在要放置探针的函数中展示指令。下面是一个在 arch/arm64/kernel/modules.cmodule_alloc 函数执行此操作的示例。在这种情况下,因为 gdb 似乎更喜欢使用弱符号定义,并且它是与这个函数关联的存根代码,所以我们从 System.map 中来获取符号值:

$ grep module_alloc System.map
ffff2000080951c4 T module_alloc
ffff200008297770 T kasan_module_alloc

在这个例子中我们使用了交叉开发工具,并且在我们的主机系统上调用 gdb 来检查指令包含我们感兴趣函数。

$ ${CROSS_COMPILE}gdb vmlinux
(gdb) x/30i 0xffff2000080951c4
        0xffff2000080951c4 <module_alloc>:    sub    sp, sp, #0x30
        0xffff2000080951c8 <module_alloc+4>:    adrp    x3, 0xffff200008d70000
        0xffff2000080951cc <module_alloc+8>:    add    x3, x3, #0x0
        0xffff2000080951d0 <module_alloc+12>:    mov    x5, #0x713             // #1811
        0xffff2000080951d4 <module_alloc+16>:    mov    w4, #0xc0              // #192
        0xffff2000080951d8 <module_alloc+20>:
              mov    x2, #0xfffffffff8000000    // #-134217728
        0xffff2000080951dc <module_alloc+24>:    stp    x29, x30, [sp,#16]         0xffff2000080951e0 <module_alloc+28>:    add    x29, sp, #0x10
        0xffff2000080951e4 <module_alloc+32>:    movk    x5, #0xc8, lsl #48
        0xffff2000080951e8 <module_alloc+36>:    movk    w4, #0x240, lsl #16
        0xffff2000080951ec <module_alloc+40>:    str    x30, [sp]         0xffff2000080951f0 <module_alloc+44>:    mov    w7, #0xffffffff        // #-1
        0xffff2000080951f4 <module_alloc+48>:    mov    x6, #0x0               // #0
        0xffff2000080951f8 <module_alloc+52>:    add    x2, x3, x2
        0xffff2000080951fc <module_alloc+56>:    mov    x1, #0x8000            // #32768
        0xffff200008095200 <module_alloc+60>:    stp    x19, x20, [sp,#32]         0xffff200008095204 <module_alloc+64>:    mov    x20, x0
        0xffff200008095208 <module_alloc+68>:    bl    0xffff2000082737a8 <__vmalloc_node_range>
        0xffff20000809520c <module_alloc+72>:    mov    x19, x0
        0xffff200008095210 <module_alloc+76>:    cbz    x0, 0xffff200008095234 <module_alloc+112>
        0xffff200008095214 <module_alloc+80>:    mov    x1, x20
        0xffff200008095218 <module_alloc+84>:    bl    0xffff200008297770 <kasan_module_alloc>
        0xffff20000809521c <module_alloc+88>:    tbnz    w0, #31, 0xffff20000809524c <module_alloc+136>
        0xffff200008095220 <module_alloc+92>:    mov    sp, x29
        0xffff200008095224 <module_alloc+96>:    mov    x0, x19
        0xffff200008095228 <module_alloc+100>:    ldp    x19, x20, [sp,#16]         0xffff20000809522c <module_alloc+104>:    ldp    x29, x30, [sp],#32
        0xffff200008095230 <module_alloc+108>:    ret
        0xffff200008095234 <module_alloc+112>:    mov    sp, x29
        0xffff200008095238 <module_alloc+116>:    mov    x19, #0x0               // #0

在这种情况下,我们将在此函数中显示以下源代码行的结果:

p = __vmalloc_node_range(size, MODULE_ALIGN, VMALLOC_START,
VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
NUMA_NO_NODE, __builtin_return_address(0));

……以及在此代码行的函数调用的返回值:

if (p && (kasan_module_alloc(p, size) < 0)) {

我们可以在从调用外部函数的汇编代码中识别这些。为了展示这些值,我们将在目标系统上的 0xffff20000809520c0xffff20000809521c 处放置探针。

$ cat > kprobe_events <<EOF
p 0xffff20000809520c %x0
p 0xffff20000809521c %x0
EOF
$ echo 1 > events/kprobes/enable

现在将一个以太网适配器加密狗插入到 USB 端口后,我们看到以下写入追踪日志的内容:

$ cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 12/12   #P:8
#
#                           _—–=> irqs-off
#                          / _—-=> need-resched
#                         | / _—=> hardirq/softirq
#                         || / _–=> preempt-depth
#                         ||| / delay
#        TASK-PID   CPU#  |||| TIMESTAMP  FUNCTION
#           | |    |   ||||    |      |
      systemd-udevd-2082  [000] d… 77.200991: p_0xffff20000809520c: (module_alloc+0x48/0x98) arg1=0xffff200001188000
      systemd-udevd-2082  [000] d… 77.201059: p_0xffff20000809521c: (module_alloc+0x58/0x98) arg1=0x0
      systemd-udevd-2082  [000] d… 77.201115: p_0xffff20000809520c: (module_alloc+0x48/0x98) arg1=0xffff200001198000
      systemd-udevd-2082  [000] d… 77.201157: p_0xffff20000809521c: (module_alloc+0x58/0x98) arg1=0x0
      systemd-udevd-2082  [000] d… 77.227456: p_0xffff20000809520c: (module_alloc+0x48/0x98) arg1=0xffff2000011a0000
      systemd-udevd-2082  [000] d… 77.227522: p_0xffff20000809521c: (module_alloc+0x58/0x98) arg1=0x0
      systemd-udevd-2082  [000] d… 77.227579: p_0xffff20000809520c: (module_alloc+0x48/0x98) arg1=0xffff2000011b0000
      systemd-udevd-2082  [000] d… 77.227635: p_0xffff20000809521c: (module_alloc+0x58/0x98) arg1=0x0
      modprobe-2097  [002] d… 78.030643: p_0xffff20000809520c: (module_alloc+0x48/0x98) arg1=0xffff2000011b8000
      modprobe-2097  [002] d… 78.030761: p_0xffff20000809521c: (module_alloc+0x58/0x98) arg1=0x0
      modprobe-2097  [002] d… 78.031132: p_0xffff20000809520c: (module_alloc+0x48/0x98) arg1=0xffff200001270000
      modprobe-2097  [002] d… 78.031187: p_0xffff20000809521c: (module_alloc+0x58/0x98) arg1=0x0

kprobes 事件系统的另一个功能是记录统计信息,这可在 inkprobe_profile 中找到。在以上追踪后,该文件的内容为:

$ cat kprobe_profile
 p_0xffff20000809520c                                    6            0
p_0xffff20000809521c                                    6            0

这表明我们设置的两处断点每个共发生了 8 次命中,这当然与追踪日志数据是一致的。在 kprobetrace 文档中有更多 kprobe\_profile 的功能描述。

也可以进一步过滤 kprobes 事件。用来控制这点的 debugfs 文件在 kprobetrace 文档中被列出,然而它们内容的详细信息大多在 trace events 文档中被描述。

总结

现在,Linux ARMv8 对支持 kprobes 功能也和其它架构相当。有人正在做添加 uprobes 和 systemtap 支持的工作。这些功能/工具和其他已经完成的功能(如: perf、 coresight)允许 Linux ARMv8 用户像在其它更老的架构上一样调试和测试性能。


参考文献

  • 注1: Jim Keniston, Prasanna S. Panchamukhi, Masami Hiramatsu. “Kernel Probes (kprobes).” GitHub. GitHub, Inc., 15 Aug. 2016. Web. 13 Dec. 2016.
  • 注2: Ts’o, Theodore, Li Zefan, and Tom Zanussi. “Event Tracing.” GitHub. GitHub, Inc., 3 Mar. 2016. Web. 13 Dec. 2016.
  • 注3: Hiramatsu, Masami. “Kprobe-based Event Tracing.” GitHub. GitHub, Inc., 18 Aug. 2016. Web. 13 Dec. 2016.

作者简介 : David Long 在 Linaro Kernel - Core Development 团队中担任工程师。 在加入 Linaro 之前,他在商业和国防行业工作了数年,既做嵌入式实时工作又为Unix提供软件开发工具。之后,在 Digital(又名 Compaq)公司工作了十几年,负责 Unix 标准,C 编译器和运行时库的工作。之后 David 又去了一系列初创公司做嵌入式 Linux 和安卓系统,嵌入式定制操作系统和 Xen 虚拟化。他拥有 MIPS,Alpha 和 ARM 平台的经验(等等)。他使用过从 1979 年贝尔实验室 V6 开始的大部分Unix操作系统,并且长期以来一直是 Linux 用户和倡导者。他偶尔也因使用烙铁和数字示波器调试设备驱动而知名。


via: http://www.linaro.org/blog/kprobes-event-tracing-armv8/

作者:David Long 译者:kimii 校对:wxy

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

不久前,我们写过一篇关于 teleconsole 的介绍,该工具可用于快速分享终端给任何人(任何你信任的人)。今天我们要聊一聊另一款类似的应用,名叫 tmate

tmate 有什么用?它可以让你在需要帮助时向你的朋友们求助。

什么是 tmate?

tmate 的意思是 teammates,它是 tmux 的一个分支,并且使用相同的配置信息(例如快捷键配置,配色方案等)。它是一个终端多路复用器,同时具有即时分享终端的能力。它允许在单个屏幕中创建并操控多个终端,同时这些终端还能与其他同事分享。

你可以分离会话,让作业在后台运行,然后在想要查看状态时重新连接会话。tmate 提供了一个即时配对的方案,让你可以与一个或多个队友共享一个终端。

在屏幕的地步有一个状态栏,显示了当前会话的一些诸如 ssh 命令之类的共享信息。

tmate 是怎么工作的?

  • 运行 tmate 时,会通过 libssh 在后台创建一个连接到 tmate.io (由 tmate 开发者维护的后台服务器)的 ssh 连接。
  • tmate.io 服务器的 ssh 密钥通过 DH 交换进行校验。
  • 客户端通过本地 ssh 密钥进行认证。
  • 连接创建后,本地 tmux 服务器会生成一个 150 位(不可猜测的随机字符)会话令牌。
  • 队友能通过用户提供的 SSH 会话 ID 连接到 tmate.io。

使用 tmate 的必备条件

由于 tmate.io 服务器需要通过本地 ssh 密钥来认证客户机,因此其中一个必备条件就是生成 SSH 密钥 key。 记住,每个系统都要有自己的 SSH 密钥。

$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/magi/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/magi/.ssh/id_rsa.
Your public key has been saved in /home/magi/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:3ima5FuwKbWyyyNrlR/DeBucoyRfdOtlUmb5D214NC8 magi@magi-VirtualBox
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|                 |
|           .     |
|      . . =   o  |
|     *ooS= . + o |
|  . =.@*o.o.+ E .|
|   =o==B++o  = . |
|  o.+*o+..    .  |
| ..o+o=.         |
+----[SHA256]-----+

如何安装 tmate

tmate 已经包含在某些发行版的官方仓库中,可以通过包管理器来安装。

对于 Debian/Ubuntu,可以使用 APT-GET 命令或者 APT 命令to 来安装。

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:tmate.io/archive
$ sudo apt-get update
$ sudo apt-get install tmate

你也可以从官方仓库中安装 tmate。

$ sudo apt-get install tmate

对于 Fedora,使用 DNF 命令 来安装。

$ sudo dnf install tmate

对于基于 Arch Linux 的系统,使用 Yaourt 命令Packer 命令 来从 AUR 仓库中安装。

$ yaourt -S tmate

$ packer -S tmate

对于 openSUSE,使用 Zypper 命令 来安装。

$ sudo zypper in tmate

如何使用 tmate

成功安装后,打开终端然后输入下面命令,就会打开一个新的会话,在屏幕底部,你能看到 SSH 会话的 ID。

$ tmate

要注意的是,SSH 会话 ID 会在几秒后消失,不过不要紧,你可以通过下面命令获取到这些详细信息。

$ tmate show-messages

tmateshow-messages 命令会显示 tmate 的日志信息,其中包含了该 ssh 连接内容。

现在,分享你的 SSH 会话 ID 给你的朋友或同事从而允许他们观看终端会话。除了 SSH 会话 ID 以外,你也可以分享 web URL。

另外你还可以选择分享的是只读会话还是可读写会话。

如何通过 SSH 连接会话

只需要在终端上运行你从朋友那得到的 SSH 终端 ID 就行了。类似下面这样。

$ ssh session: ssh [email protected]

如何通过 Web URL 连接会话

打开浏览器然后访问朋友给你的 URL 就行了。像下面这样。

只需要输入 exit 就能退出会话了。

[Source System Output]
[exited]

[Remote System Output]
[server exited]
Connection to sg2.tmate.io closed by remote host。
Connection to sg2.tmate.io closed。

via: https://www.2daygeek.com/tmate-instantly-share-your-terminal-session-to-anyone-in-seconds/

作者:Magesh Maruthamuthu 译者:lujun9972 校对:wxy

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