包含linuxstap命令的词条

systemtap怎么调试脚本程序

其实下面要说的没多少硬货,算是个自己这些日子使用春哥写的那几个systemtap脚本调优的经验总结吧。

创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站建设、网站制作、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的大姚网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!

一、systemtap安装

因为一直在ubuntu上使用,所以安装很简单 sudo apt-get install systemtap,源码安装的话请参考这篇文章: 中的方法一。

二、内核调试信息

不用跟踪内核态性能大概也不需要,不过保不齐会用到所以我也把内核调试信息搞上了。对于ubuntu这种发行版内核来说好处是官方已经提供了(URL:),根据自己的内核(uname -a 查询)挑选版本。 如我的是Linux ubuntu 3.13.0-32-generic 那么对应的就是:linux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb。

下载后用 dpkg -i linux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb 安装。

三、Hello Systemtap!

上面这些完成以后可以使用命令:sudo stap -ve 'probe begin { log("hello Systemtap!") exit() }' 来测试是否安装成功。如果成功的话会有类似下面的输出:

春哥的nginx wbrsystemtap调试脚本简单介绍

四、nginx-systemtap-toolkit

进入正题,这个就是主要介绍的章亦春大神写的systemtap nginx调试的系列脚本了(URL:Github地址),提供了活动请求的查询、ngx_lua模块的当前lua堆栈查看、pcre模式串/运行时间分析、C堆栈采样等等炸裂功能。

首先介绍下C堆栈采样这个脚本,结合Brendan Gregg大神写的FlameGraph tools(URL:),可以画出功能实用、看着酷炫的火焰图。如图:春哥的nginx wbrsystemtap调试脚本简单介绍

这个东西的原理就是在程序运行的时候每隔一定的时间对指定进程的C堆栈进行采样,将当前各栈帧的函数名保存起来。因为采样时间是恒定的,所以最后的结果上如果一个函数占用cpu时间越长,那么得到的采样次数也就越多,最后反映到火焰图上的横轴长度就越长。另外颜色深浅其实没什么含义,只是方便查看。

使用方法:

1、首先确定编译的代码要带有调试i信息,以便调试脚本可以获得具体的代码信息。如nginx就要加上--with-debug开关。

2、其次要调优的进程已经启动,并且获得其pid,对于nginx这种多进程的程序,需要找到一个worker进程的pid,所以如果是开发环境调优的话,可以考虑使用单进程跑nginx。

3、命令sudo ./nginx-systemtap-toolkit/sample-bt -p 1147 -u -t 20 trace.txt

其中-p 指定进程的pid

-u 追踪用户态的调用堆栈(也可以使用-k追踪程序运行期间在内核态的堆栈)

-t 脚本的运行时间,达到时间之后脚本自动停止,将堆栈信息输出,单位为秒

启动后会有类似的信息:

WARNING: Tracing 1147 (/home/kawaru/nginx/sbin/nginx) in user-space only...

提示已经开始跟踪,这是可以用ab等等东西打点流量,等20秒之后会显示:

WARNING: Time's up. Quitting now...(it may take a while)

【性能】如何优化 NAT 性能?

NAT 技术可以重写 IP 数据包的源 IP 或者目的 IP,被普遍地用来解决公网 IP 地址短缺的问题。它的主要原理就是,网络中的多台主机,通过共享同一个公网 IP 地址,来访问外网资源。同时,由于 NAT 屏蔽了内网网络,自然也就为局域网中的机器提供了安全隔离。

你既可以在支持网络地址转换的路由器(称为 NAT 网关)中配置 NAT,也可以在 Linux 服务器中配置 NAT。如果采用第二种方式,Linux 服务器实际上充当的是“软”路由器的角色。

Linux 内核提供的 Netfilter 框架,允许对网络数据包进行修改(比如 NAT)和过滤(比如防火墙)。在这个基础上,iptables、ip6tables、ebtables 等工具,又提供了更易用的命令行接口,以便系统管理员配置和管理 NAT、防火墙的规则。

其中,iptables 就是最常用的一种配置工具。要掌握 iptables 的原理和使用方法,最核心的就是弄清楚,网络数据包通过 Netfilter 时的工作流向。

熟悉 iptables 中的表和链后,我们以 NAPT 的三个分类为例,来具体解读一下:

在使用 iptables 配置 NAT 规则时,Linux 需要转发来自其他 IP 的网络包,所以你 千万不要忘记开启 Linux 的 IP 转发功能 。

Linux 中的 NAT ,基于内核的连接跟踪模块实现。所以,它维护每个连接状态的同时,也会带来很高的性能成本,对网络性能有一定影响。

那么,碰到 NAT 性能问题时,我们又该怎么办呢?

SystemTap  是 Linux 的一种动态追踪框架,它把用户提供的脚本,转换为内核模块来执行,用来监测和跟踪内核的行为。关于它的原理,你暂时不用深究,这里你只要知道怎么安装就可以了。

# yum   -y  install systemtap kernel-devel

# yum info  systemtap 

我们之前使用 tcpdump 抓包的方法,找出了延迟增大的根源。那么今天的案例,我们仍然可以用类似的方法寻找线索。不过,现在换个思路,因为今天我们已经事先知道了问题的根源——那就是 NAT。

回忆一下 Netfilter 中,网络包的流向以及 NAT 的原理,你会发现,要保证 NAT 正常工作,就至少需要两个步骤:

这个脚本,跟踪内核函数 kfree_skb() 的调用,并统计丢包的位置。

文件保存好后,执行下面的 stap 命令,就可以运行丢包跟踪脚本。

这里的 stap,是 SystemTap 的命令行工具:

#  man 1 perf-record

###############################################################

-a, --all-cpus

    System-wide collection from all CPUs (default if no target is specified).

-g

      Enables call-graph (stack chain/backtrace) recording

#################################################################

在 perf report 界面中,输入查找命令 / 然后,在弹出的对话框中,输入 nf_hook_slow;最后再展开调用栈,就可以得到下面这个调用图:

不过,你可能还是很好奇,连接跟踪表里,到底都包含了哪些东西?这里的东西,又是怎么刷新的呢?

实际上,你可以用 conntrack 命令行工具 ,来查看连接跟踪表的内容。

# yum provides conntrack

# yum  -y install conntrack-tools

#  yum info   conntrack-tools

#  conntrack -L -o extended | wc -l

#  conntrack -L -o extended | awk '/^.*tcp.*$/ {sum[$6]++} END {for(i in sum) print i, sum[i]}'

#  conntrack -L -o extended | awk '{print $7}' | cut -d "=" -f 2 | sort | uniq -c | sort -nr | head -n 10

因为NAT 基于 Linux 内核的连接跟踪机制来实现,所以在分析 NAT 性能问题时,我们可以先从 conntrack 角度来分析,比如用 systemtap、perf 等,分析内核中 conntrack 的行文;然后,通过调整 netfilter 内核选项的参数,来进行优化。

其实,Linux 这种通过连接跟踪机制实现的 NAT,也常被称为有状态的 NAT,而维护状态,也带来了很高的性能成本。

所以,除了调整内核行为外,在不需要状态跟踪的场景下(比如只需要按预定的 IP 和端口进行映射,而不需要动态映射),我们也可以使用无状态的 NAT (比如用 tc 或基于 DPDK 开发),来进一步提升性能。

案例篇:如何优化 NAT 性能?(上)

案例篇:如何优化 NAT 性能?(下)

SystemTap工具的使用基础

查看当前内核版本是哪一个,然后使用

找到内核构建的详细信息,然后去对应发布网站上找kernel-debuginfo和kernel-debuginfo-common包。

完成安装后可以通过下面命令测试systemtap

进行测试,看看systemtap有无安装成功。

下面命令演示查看__lookup_hash()函数返回时刻可以查看到的变量

在上表中显示了lookup_hash在文件中的行号,显示了名为$return 的变量,其实这个return变量就是systemtap表示函数返回值的。而$name,$base,$flag我们对着linux源码看发现这是__lookup_hash的三个入参。

下面命令可以查看__lookup_hash函数入口可以查看的变量

也可以通过statement方式查看内核符号表里有的__lookup_hash相关的行

如果查找的内核函数位于某个模块里可以使用下面命令:

通过下面命令可以查看到某个正在运行的进程的函数

上例中看到找到了syscall.Mount函数,并且把它的所有参数和参数类型都打印了出来。

后面可以在stap脚本中,这个函数的上下文里直接使用这些参数,例如通过$source可以访问到参数source

systemtap支持print()和printf()函数,其中printf使用语法和c语言一致。支持%s,%d,%x格式

在systemtap里凡是以$开头的变量都是目标变量,如果目标变量结构体指针或者结构体对象,那么可以使用-直接访问其成员。例如上例中:

常规情况下,printf()打印target变量时刻,只打印其值。如果需要将其成员(指针类型的target需要将其指向的对象的成员展开)可以在target变量后面加$的方式例如:

一般情况下对struct的展开只会到成员值一级,如果相对成员内部继续展开可以在目标变量后面跟$$

在systemtap中支持逻辑if语句格式为:

逻辑语句支持以下比较

==,!=,=,,,=

上述例子对ls -l下的xmalloc进行堆栈回溯:

-d 可执行文件名

--ldd 指明共享库

-c “ls -l” 执行的子进程体

下面例子将打印__lookup_hash中return返回dentry*里inode指向的i_ino子成员

这一例子中-o zxy.txt的意思就是将结果写入文件zxy.txt中(默认输出到控制台)

下面例子将在内核中使用强制类型转换

这里解释一下,内核中方法强制转换

在用systemtap跟踪内核时使用堆栈打印命令,常常打印不出来另外模块的函数,这是因为这些模块没有被加载。可以在systemtap启动命令使用--all-modules 方法强制将所有模块符号加载起来。

下面例子对用golang写的dockerd进程syscall.Mount调用入口时刻打印syscall.Mount()函数的参数

source的string字段内容

下面例子打印golang写的dockerd进程xxx.Get函数返回时刻的参数情况

}

systemtap对golang支持不够完美,用户需要自己解析基本结构例如golang的string,array和slice这些都需要用户自己解析。string被systemtap识别为struct string,此结构systemtap可以识别的定义可以简化为:

需要注意的是 通过systemtap打印golang string的string-str会多打很多字符,因为string成员str并非按照c语言定义的字符串以\0表示字符串结束,我们只能结合string的字段len来获取精确的字符串内容

slice完全不被systemtap识别,我们可以将systemtap可以识别的slice简化为此种定义:

其中array就是指向slice存储单元的首地址。

要是我们想获取helo=[]string{“hello”,”world”}这样的字符串slice的内容可以通过systemtap提供的@cast(addr,”type”,”file”)函数将某个地址强转为file中定义的type结构。具体来说可以如下做获取hello的内容

linux运维常用命令

| 线上查询及帮助命令 |

man:全称为manual,用于查看系统中自带的各种参考手册;

help:用于显示shell内部命令的帮助信息;

| 文件和目录操作命令 |

ls:全拼list,列出目录的内容及其内容属性信息;

cd:全拼change directory,切换当前工作目录至dirName(目录参数);

cp:全称copy,复制文件或目录;

find:用于在指定目录及目录下查找文件;

mkdir:全拼make directories,创建目录;

mv:全拼move,移动或重命名文件;

pwd:全拼print working directory,显示当前工作目录的绝对路径;

rename:可用字符串替换的方式批量改变文件名;

rm:全拼remove,删除一个或多个文件或目录。必须格外小心地使用该命令;

rmdir:全拼remove empty directories,删除空目录;

touch:修改文件或者目录的时间属性,包括存取时间和更改时间。若文件不存在,系统会建立一个新的文件;

| 查看文件及内容处理命令 |

cat:全拼concatenate,用于连接多个文件并且打印到屏幕输出或重定向到指定文件中,可查看文件内容;

tac:cat的反向拼写,因此命令的功能为反向显示文件内容。文件内容的最后一行先显示,第一行最后显示;

less:可以随意浏览文件,而more仅能向前移动,却不能向后移动,而且less在查看之前不会加载整个文件;

head:显示文件的开头的内容。在默认情况下,head命令显示文件的头10行内容;

tail:查看文件尾部内容,有一个常用的参数-f常用于查阅正在改变的文件。可以看到最新的文件内容;

| 文件压缩及解压缩命令 |

tar:tar命令是用来建立,还原备份文件的工具程序,它可以加入,解开备份文件内的文件;

unzip:用于解压缩zip文件;

gzip:用于压缩文件。gzip是个使用广泛的压缩程序,文件经它压缩过后,其名称后面会多出".gz"的扩展名;

zip:用来将文件压缩成为常用的zip格式。

什么样的程序让linux负载变大

在linux系统里面,常见的有两个地方可以看到当前系统的最近平均负载,top命令和uptime,如果执行一下uptime命令的话,可以看到有一个load average,表示最近1分钟,5分钟,15分钟的系统负载。

# uptime

23:31:04 up 5 days, 10:20, 1 user, load average: 0.00, 0.01, 0.05

一般单核的CPU的话,负载到1证明系统已经运行比较满了,多核的话,有几个核就能到几。

但是,有没有仔细想过,这个负载值究竟可以有多高?

我们先用一个程序做下实验

等这个程序运行一会,再执行uptime看下负载

# uptime

23:44:53 up 5 days, 10:33, 2 users, load average: 16383.13, 14111.52, 7705.88

看到没,这个程序竟然把load神奇的刷到了16000这个级别,真是厉害,这个一下子似乎打破了对系统负载的认识。

原理是这样的,通过调用vfork产生指定数量的D状态的进程,从而提高负载。看看系统文档,是这样说的

vfork() differs from fork(2) in that the calling thread is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Untilthat point, the child shares all memory with its parent, including the stack.

vfork 的子进程只要不 execve 或者退出,父进程就一直挂着(在D状态)。这里就是让最后一个子进程用 scanf 等输入。

但是这个就是极限了吗?

程序员在这种事情上是不会停止追求的,下来再看一个终极版本的程序

执行一下

# stap -g loadavg.stp $(((1

看下效果

# uptime

23:48:19 up 5 days, 10:37, 2 users, load average: 9007199254740991.00, 14987.03, 9007199254740991.00

我天,这是要爆表了,终极load,系统要炸了吗?

不过,你知道其中的原理吗,vfork相当于还是利用了系统计算load的原理,通过增加D状态进程影响计算,这个终极版,则是直接修改计算过程中用到的参数,让系统算出一个极大值来,没有什么能够超越这个了。


网站栏目:包含linuxstap命令的词条
文章链接:http://scyanting.com/article/hhdsdo.html