Love Sun

Linux

Linux下,多线程程序死循环问题调试

当你的软件在某个时刻停止服务,CPU占用达到100%+,这种问题一个可能的原因是产生了死循环,假设程序某处存在潜在的死循环,并在某种条件下会引发,本文以一个示例来定位出现死循环的位置。 当程序某处存在死循环,通常定位问题及缩小范围的方法是,在可疑的代码处加log,或者注释掉可疑代码,这对于容易重现问题的程序来说还好,但对于“偶尔”才会产生问题程序却很难调试,因为我们很难重现程序故障。本文所述的调试过程正是在这种情况下,假设问题已经出现,我们要求环境保护现场,即出问题的程序还在运行中。 1.我们首先要知道是哪个线程出了问题: 首先查一下出问题进程的pid,例如

然后top命令查看线程信息:

从上面可以看出,出问题线程PID为11073 2.接下来,我们用gdb来attach目标进程 执行:

在gdb中,列出线程状态:

gdb已经列出了各线程正在执行的函数,我们需要更多信息,记住11073对应的行首标号,这是gdb为线程分配的id,这里为2,然后执行切换:

bt一下:

来看一下101行的代码:

现在我们定位到了出问题的代码位置,这里的循环只用来演示的。 最后别忘了detach refer to:http://www.cppblog.com/elva/archive/2010/08/02/121943.html

定位Linux下定位进程被谁KILL

今天上午有个同事问,自己的进程被莫名其妙的杀死了,想知道是被那个进程误杀了。 第一个想法是用kernel hack系统调用的方式,刚打算翻出hook的代码,想起了貌似audit不就是干这个的吗 #auditctl -a exit,always -S kill #auditctl -l #tail -f /var/log/audit/audit.log 加上这个规则后,再用kill杀死一个进程就可以看到是谁干的了。 type=SYSCALL msg=audit(1446528422.179:18502): arch=c000003e syscall=62 success=yes exit=0 a0=53f a1=8 a2=0 a3=53f items=0 ppid=1427 pid=2613 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=tty1 ses=1 comm=”bash” exe=”/usr/bin/bash”…

Linux大文件传输

我们经常需要在机器之间传输文件。比如备份,复制数据等等。这个是很常见,也是很简单的。用scp或者rsync就能很好的完成任务。但是如果文件很大,需要占用一些传输时间的时候,怎样又快又好地完成任务就很重要了。在我的测试用例中,一个最佳的方案比最差的方案,性能提高了10倍。 复制文件 如果我们是复制一个未压缩的文件。这里走如下步骤: 压缩数据 发送到另外一台机器上 数据解压缩 校验正确性 这样做会很有效率,数据压缩后可以更有效的利用带宽 使用ZIP+SCP 我们可以通过ZIP+SCP的组合实现这个功能。

这条命令是将/home/yankay/data经过GZIP压缩,通过ssh传输到yankay01的机器上。 data文件的大小是1.1GB,经过Zip压缩后是183MB,执行上面的命令需要45.6s。平均吞吐量为24.7MB/s 我们会发现Scp也有压缩功能,所以上面的语句可以写成

这样运行效果是相同的,不通之处在于我使用了blowfish算法作为Scp的密匙算法,使用这个算法可以比默认的情况快很多。单单对与scp,使用了blowfish 吞吐量是62MB/s,不使用只有46MB/s。 可是我执行上面一条命令的时候,发现还是需要45s。平均吞吐量还为24MB/s。没有丝毫的提升,可见瓶颈不在网络上。 那瓶颈在哪里呢? 性能分析 我们先定义几个变量 压缩工具的压缩比是 CompressRadio 压缩工具的压缩吞吐是CompressSpeed MB/s 网络传输的吞吐是 NetSpeed MB/s 由于使用了管道,管道的性能取决于管道中最慢的部分的性能,所以整体的性能是: speed=min(NetSpeed/CompressRadio,CompressSpeed) 当压缩吞吐较网络传输慢的时候,压缩是瓶颈;但网络较慢的时候,网络传输/吞吐 是瓶颈。 根据现有的测试数据(纯文本),可以得到表格: 压缩比 吞吐量 千兆网卡(100MB/s)吞吐量 千兆网卡吞吐量,基于ssh(62MB/s) 百兆网卡(10MB/s)吞吐量 ZLIB 35.80%…

Linux下常用的文件传输方式介绍与比较

本文介绍了linux之间传输文件的几种方式,并通过具体实验测试了几种文件传输方式之间的传输速度。这篇文章是我一次作业的实验报告,我经常查看这个文档,所以贴出来方便自己查略。 0. 实验环境以及实验数据 实验环境: 两台装有Ubuntu的电脑,两台电脑位于同一个局域网中,传输速度约4.1MB/s。 实验数据: 使用MySQL的日志文件(ib_logfile0)进行测试,日志文件压缩前1.1G,压缩后159M,具体应用中,压缩比例可能没有这么高,但是不影响我们的讨论。 1. scp scp是secure copy的缩写,scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令,主要用于linux服务器之间复制文件和目录。scp使用ssh安全协议传输数据,具有和ssh一样的验证机制,从而可以实现安全的远程拷贝文件。 下面介绍SCP三种不同用法的效率。注意:使用SCP前请配制好SSH。 1.1 scp 不使用压缩 将本地文件拷贝到远程服务器:

将远程服务器中的文件拷贝到本地的用法:

经测试,SCP不启用压缩功能的情况下,传输ib_logfile0文件需要4:12s。 1.2 压缩后传输 SCP传输ib_logfile0文件之所以需要那么多时间,是因为它没有对传输的数据进行压缩,可以先 将文件压缩,然后再进行远程拷贝。如下所示:

经测试,先手动压缩,然后再传输,4次测试结果的平均值为00:39s。 1.3 scp启用压缩 相对于第一种方法,第二种方法极大地减少了传输时间,但是需要执行三条语句,较为麻烦。更简单的方法如下所示:

-C选项启用了SSH的压缩功能,通过man ssh可以看到,在-C选项的解释部分有这么一句话:”the compression algorithm is the same used by gzip”。SSH与gzip使用的是同一种压缩算法,即第二种方法与第三种方法几乎一样,但是,第三种方法更为简单方便,所以,推荐使用第三种方法传输数据。…

将Linux命令的结果作为下一个命令的参数

1. 符号: 名称:反引号,上分隔符 位置:反引号()这个字符一般在键盘的左上角,数字1的左边,不要将其同单引号(’)混淆 作用:反引号括起来的字符串被shell解释为命令行,在执行时,shell首先执行该命令行,并以它的标准输出结果取代整个反引号(包括两个反引号)部分 举例:

2. $()  效果同 3. 命令:xargs xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。它把一个数据流分割为一些足够小的块,以方便过滤器和命令进行处理。通常情况下,xargs从管道或者stdin中读取数据,但是它也能够从文件的输出中读取数据。xargs的默认命令是echo,这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。

管道与xargs的区别: 管道是实现“将前面的标准输出作为后面的标准输入” xargs是实现“将标准输入作为命令的参数” 4. find命令的-exec参数 xargs:通过缓冲方式并以前面命令行的输出作为参数,随后的命令调用该参数 若忽略 xargs 的 options 来看的话, cm1 | xargs cm2 可以单纯看成: cm2 cm1 因此, find …. | xargs rm 也可作 rm…

查找Linux进程目录

Linux下我们一般使用ps查看进程信息,但是ps给出的进程信息比较有限,没有进程的工作路径,进程命令的绝对路径等等,这时候我们可以通过Linux下 /proc/ 目录下存储的信息进行查询进程命令路径信息。 Linux下,任何一个程序启动以后,系统会为其分配一个ID,即我们熟悉的PID,称为进程号,与此同时,系统会在/proc目录下为其创建一个独立的文件夹,文件夹以PID命名,在该文件夹内保存着该进程运行相关的详细信息,有兴趣的朋友可以进到这个目录下好好研究研究,不过今天的重点是获得该进程的绝对路径。 在 /proc/ 该目录下有一个名为exe的文件,像Windows系统下的可执行文件,这其实是一个符号链接(类似于Windows下的快捷方式),它指向该进程对应程序的绝对路径。用file命令或ls命令查看该符号链接的属性即可获取它所指向的绝对路径:

将上面命令中的PID换成你要查询的Linux进程号就可以。

加速Linux程序编译

项目越来越大,每次需要重新编译整个项目都是一件很浪费时间的事情。Research了一下,找到以下可以帮助提高速度的方法,总结一下。 1. tmpfs 有人说在Windows下用了RAMDisk把一个项目编译时间从4.5小时减少到了5分钟,也许这个数字是有点夸张了,不过粗想想,把文件放到内存上做编译应该是比在磁盘上快多了吧,尤其如果编译器需要生成很多临时文件的话。 这个做法的实现成本最低,在Linux中,直接mount一个tmpfs就可以了。而且对所编译的工程没有任何要求,也不用改动编译环境。 mount –t tmpfs tmpfs ~/build –o size=1G 用2.6.32.2的Linux Kernel来测试一下编译速度: 用物理磁盘:40分16秒 用tmpfs:39分56秒 呃……没什么变化。看来编译慢很大程度上瓶颈并不在IO上面。但对于一个实际项目来说,编译过程中可能还会有打包等IO密集的操作,所以只要可能,用tmpfs是有益无害的。当然对于大项目来说,你需要有足够的内存才能负担得起这个tmpfs的开销。 make -j 既然IO不是瓶颈,那CPU就应该是一个影响编译速度的重要因素了。 用make -j带一个参数,可以把项目在进行并行编译,比如在一台双核的机器上,完全可以用make -j4,让make最多允许4个编译命令同时执行,这样可以更有效的利用CPU资源。 还是用Kernel来测试: 用make: 40分16秒 用make -j4:23分16秒 用make -j8:22分59秒 由此看来,在多核CPU上,适当的进行并行编译还是可以明显提高编译速度的。但并行的任务不宜太多,一般是以CPU的核心数目的两倍为宜。 不过这个方案不是完全没有cost的,如果项目的Makefile不规范,没有正确的设置好依赖关系,并行编译的结果就是编译不能正常进行。如果依赖关系设置过于保守,则可能本身编译的可并行度就下降了,也不能取得最佳的效果。 ccache ccache用于把编译的中间结果进行缓存,以便在再次编译的时候可以节省时间。这对于玩Kernel来说实在是再好不过了,因为经常需要修改一些Kernel的代码,然后再重新编译,而这两次编译大部分东西可能都没有发生变化。对于平时开发项目来说,也是一样。为什么不是直接用make所支持的增量编译呢?还是因为现实中,因为Makefile的不规范,很可能这种“聪明”的方案根本不能正常工作,只有每次make clean再make才行。 安装完ccache后,可以在/usr/local/bin下建立gcc,g++,c++,cc的symbolic link,链到/usr/bin/ccache上。总之确认系统在调用gcc等命令时会调用到ccache就可以了(通常情况下/usr/local/bin会在PATH中排在/usr/bin前面)。 继续测试: 用ccache的第一次编译(make -j4):23分38秒…

linux下批量替换文件内容的三种办法

程序开发中,可能你会经常遇到批量替换文件内容的情况,如果你使用的是linux,那么恭喜你,你可以使用一下三种办法进行查找替换。 方法一:

这里使用了perl语言,使用-e加上一段代码,从而批量地将当前目录及所有子目录下的file.log文件中的string1替换成了string2 string支持正则表达式 方法二:

这里使用了sed命令,将/path目录及其子目录下的所有文件中的string1替换成了string2 这个命令,可能对返回多个文件不太支持,不太推荐! 方法三:

这里使用了shell命令,先查找出文件,再用awk分割(以:切分),再行替换! 注意: grep可以使用正则,也可以使用\转义一些特殊字符,比如”等

如何查看linux硬件配置信息

1.查看机器所有硬件信息: dmidecode |more dmesg |more 这2个命令出来的信息都非常多,所以建议后面使用”|more”便于查看 2.查看CPU信息 方法一: Linux下CPU相关的参数保存在 /proc/cpuinfo 文件里 cat /proc/cpuinfo |more 方法二: 采用命令 dmesg | grep CPU 可以查看到相关CPU的启动信息 查看CPU的位数: getconf LONG_BIT 3.查看Mem信息 cat /proc/meminfo |more (注意输出信息的最后一行:MachineMem:   41932272 kB) free -m top 4.查看磁盘信息 方法一: fdisk -l 可以看到系统上的磁盘(包括U盘)的分区以及大小相关信息。 方法二: 直接查看 cat /proc/partitions 5.查看网卡信息…

linux查看程序端口占用情况

今天发现服务器上Tomcat 8080端口起不来,老提示端口已经被占用。 使用命令: ps -aux | grep tomcat 发现并没有8080端口的Tomcat进程。 使用命令:netstat –apn 查看所有的进程和端口使用情况。发现下面的进程列表,其中最后一栏是PID/Program name 发现8080端口被PID为9658的Java进程占用。 进一步使用命令:ps -aux | grep java,或者直接:ps -aux | grep pid 查看 就可以明确知道8080端口是被哪个程序占用了!然后判断是否使用KILL命令干掉! 方法二:直接使用 netstat   -anp   |   grep  portno 即:netstat –apn | grep 8080 linux下查看端口占用情况: 1.查看哪个进程占用了819端口:…