交流群的风格突然骤变,没有了往日的灌水扯淡,居然聊起了技术。
看了大家的全部的聊天记录,发现问题并没解决。群里难得这么多人聊技术,抱着问答不断,必有回响的原则,主动勾搭一起看看是什么问题。
大概了解其问题是这样,apache 子进程一直异常退出
$ sudo tail -f /var/log/httpd/error_log [Sun Jun 13 19:32:25.660349 2021] [core:notice] [pid 23340] AH00052: child pid 20605 exit signal Bus error (7) [Sun Jun 13 19:32:25.660413 2021] [core:notice] [pid 23340] AH00052: child pid 20606 exit signal Bus error (7) [Sun Jun 13 19:35:39.862368 2021] [core:notice] [pid 23340] AH00052: child pid 21332 exit signal Bus error (7) [Sun Jun 13 19:35:50.872363 2021] [core:notice] [pid 23340] AH00052: child pid 21369 exit signal Bus error (7) [Sun Jun 13 19:39:43.079650 2021] [core:notice] [pid 23340] AH00052: child pid 18595 exit signal Bus error (7) [Sun Jun 13 19:42:08.210353 2021] [core:notice] [pid 23340] AH00052: child pid 21348 exit signal Bus error (7) [Sun Jun 13 19:42:16.221076 2021] [core:notice] [pid 23340] AH00052: child pid 21331 exit signal Bus error (7) [Sun Jun 13 19:42:16.221177 2021] [core:notice] [pid 23340] AH00052: child pid 23156 exit signal Bus error (7) [Sun Jun 13 19:44:11.329344 2021] [core:notice] [pid 23340] AH00052: child pid 27824 exit signal Bus error (7)现场复现
了解到其架构是 apache + php ,群友也是临时接受的祖传代码,项目也不是很清楚。可以使用strace来看看,背后到底是什么问题
$ ps -ef|grep apache
首先看到主进程 id 是 23340,这里需要跟着其子进程,所以我执行了如下命令
$ sudo strace -o strace.log -s 1024 $(pidof "/usr/sbin/httpd" -o 23340|sed 's/\([0-9]*\)/-p \1/g') strace: Process 26212 attached strace: Process 26211 attached strace: Process 26191 attached strace: Process 25940 attached ...
参数大概解释下
code释义-o strace.log输出 strace 日志到 strace.log-s 1024当系统调用的某个参数是字符串时,最多输出指定长度的内容,默认是32个字节pidof "/usr/sbin/httpd" -o 23340排除主进程 23340 之外的 httpd 子进程然后新开一个窗口监控日志
$ sudo tail -f strace.log |grep SIGBUS -B 500 28741 open("/xxxx/www/data/cache/xxx.php", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 15 28741 write(15, " ?php defined('DYMall') or exit('Access Invalid!'); return array ( ) ? ", 71) = 71 28741 close(15) 28741 open("/xxxx/www/data/cache/xxx.php", O_RDONLY) = 15 28741 fstat(15, {st_mode=S_IFREG|0644, st_size=71, ...}) = 0 28741 fstat(15, {st_mode=S_IFREG|0644, st_size=71, ...}) = 0 28741 fstat(15, {st_mode=S_IFREG|0644, st_size=71, ...}) = 0 28741 mmap(NULL, 71, PROT_READ, MAP_SHARED, 15, 0) = 0x7f584aee8000 28741 --- SIGBUS {si_signo=SIGBUS, si_code=BUS_ADRERR, si_addr=0x7f584aee8000} --- 28741 chdir("/etc/httpd") = 0 28741 rt_sigaction(SIGBUS, {SIG_DFL, [], SA_RESTORER|SA_INTERRUPT, 0x7f58499bc5e0}, {SIG_DFL, [], SA_RESTORER|SA_RESETHAND, 0x7f58499bc5e0}, 8) = 0 28741 kill(28741, SIGBUS) = 0 28741 rt_sigreturn({mask=[]}) = 140017190993928 28741 --- SIGBUS {si_signo=SIGBUS, si_code=SI_USER, si_pid=28741, si_uid=48} --- 28741 +++ killed by SIGBUS +++SIGBUS 在用户态最为常见的场景,也最容易触发,通常来说根本原因都是进程 mmap 了一个文件后,另外的进程把这个文件截断了,导致 mmap 出来的某些内存页超出文件的实际大小,访问那些超出的内存页就会触发 SIGBUS验证文件大小变化
监控文件的大小来验证文件是否一直在变化
$ while :; do cat /xxxx/www/data/cache/xxx.php|wc -L ;done $ while :; do cat /xxxx/www/data/cache/xxx.php|wc -L ;done|grep -v 71
发现文件确实在少数情况下会变为 0 个字节,根据文件的路径,初步估计应该是缓存文件被重写了
确认文件写操作来源$ sudo yum -y install audit auditd-libs
监控topic_goodsclass.php文件的写入操作
$ sudo auditctl -w /xxxx/www/data/cache/xxx.php -p w
结果类似于
time- Mon Jun 14 21:21:39 2021 type=PROCTITLE msg=audit(1623676899.778:1883303): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44 type=PATH msg=audit(1623676899.778:1883303): item=1 name="/xxxx/www/data/cache/xxx.php" inode=30151674 dev=fd:11 mode=0100644 ouid=48 ogid=48 rdev=00:00 objtype=NORMAL type=PATH msg=audit(1623676899.778:1883303): item=0 name="/xxxx/www/data/cache/" inode=30151667 dev=fd:11 mode=040755 ouid=48 ogid=48 rdev=00:00 objtype=PARENT type=CWD msg=audit(1623676899.778:1883303): cwd="/xxxx/www" type=SYSCALL msg=audit(1623676899.778:1883303): arch=c000003e syscall=2 success=yes exit=16 a0=55b452b93078 a1=241 a2=1b6 a3=2a items=2 ppid=31318 pid=18269 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" key=(null)
收集一段时间,做下统计
$ sudo ausearch -f /xxxx/www/data/cache/xxx.php |grep "exe="|awk '{print $12,$26}'|sort|uniq -c 44200 ppid=31318 exe="/usr/sbin/httpd"
发现都是来自于/usr/sbin/httpd,并没有CLI模式的写入(担心有定时任务来生成缓存),清理掉监控
sudo auditctl -D多进程文件读写冲突的解决方案
需要注意,在对文件进行fopen($filename, "w+")的时候,就已经将文件清空了,所以加锁需要在fopen目标文件之前,所以我的方式是增加一个文件一一对应的锁文件。如下:
aa.php
function addFileLock($filename, $lock) $fp = fopen($filename . ".lock", "w+"); flock($fp, $lock); return $fp; function releaseLock($fp) flock($fp, LOCK_UN); $filename = "cc.log";
本文转自网络,原文链接:https://developer.aliyun.com/article/784756
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!
基本介绍 给定 n 个权值作为 n 个叶子节点,构造一颗二叉树,若该树的带权路径长...
背景 我们知道 如果在Kubernetes中支持GPU设备调度 需要做如下的工作 节点上安装...
想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区 https://...
TIOBE 公布了 2021 年 3 月的编程语言排行榜。 本月 TIOBE 指数没有什么有趣的变...
本文转载自公众号读芯术(ID:AI_Discovery)。 这一刻你正在应对什么挑战?这位前...
前言 统计科学家使用交互式的统计工具(比如R)来回答数据中的问题,获得全景的认...
溢价 域名 的续费价格如何?通常来说,因为溢价域名的价值高于普通域名,所以溢...
在Python开发过程中,我们难免会遇到多重条件判断的情况的情况,此时除了用很多...
近几年,互联网行业蓬勃发展,在互联网浪潮的冲击下,互联网创业已成为一种比较...
本文转载自微信公众号「bugstack虫洞栈」,作者小傅哥 。转载本文请联系bugstack...