LINUX下JMX502报错什么意思是啥个意思

他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)> 博客详情
今天,一个运行了近一年的程序突然挂掉了,问题定位到是system()函数出的问题,关于该函数的简单使用在我上篇文章做过介绍:
先看一下问题
简单封装了一下system()函数:
int pox_system(const char *cmd_line)
return system(cmd_line);
函数调用:
int ret = 0;
ret = pox_system("gzip -c /var/opt/I00005.xml & /var/opt/I00005.z");
if(0 != ret)
Log("zip file failed\n");
} 问题现象:每次执行到此处,都会zip failed。而单独把该命令拿出来在shell里执行却总是对的,事实上该段代码已运行了很长时间,从没出过问题。
糟糕的日志
分析log时,我们只能看到“zip file failed”这个我们自定义的信息,至于为什么fail,毫无线索。
那好,我们先试着找出更多的线索:
int ret = 0;
ret = pox_system("gzip -c /var/opt/I00005.xml & /var/opt/I00005.z");
if(0 != ret)
Log("zip file failed: %s\n", strerror(errno)); //尝试打印出系统错误信息
} 我们增加了log,通过system()函数设置的errno,我们得到一个非常有用的线索:system()函数失败是由于“
No child processes”。继续找Root Cause。
谁动了errno
我们通过上面的线索,知道system()函数设置了errno为ECHILD,然而从system()函数的man手册里我们找不到任何有关EHILD的信息。我们知道system()函数执行过程为:fork()-&exec()-&waitpid()。很显然waitpid()有重大嫌疑,我们去查一下man手册,看该函数有没有可能设置ECHILD:
(for waitpid() or waitid()) The process specified by pid (waitpid()) or idtype and id (waitid()) does not exist or is not a child of the calling process. (This can happen for one's own child if the action for SIGCHLD is set to SIG_IGN. See also the Linux Notes section about threads.)
果然有料,如果SIGCHLD信号行为被设置为SIG_IGN时,waitpid()函数有可能因为找不到子进程而报ECHILD错误。似乎我们找到了问题的解决方案:在调用system()函数前重新设置SIGCHLD信号为缺省值,即signal(SIGCHLD, SIG_DFL)。我们很兴奋,暂时顾不上看Linux Notes部分,直接加上代码测试!乖乖,问题解决了!
如此处理问题是你的风格吗
正当我们急于check in 代码时,一个疑问出现了:“这个错误为什么以前没发生”?是啊,运行良好的程序怎么突然就挂了呢?首先我们代码没有改动,那么肯定是外部因素了。一想到外部因素,我们开始抱怨:“肯定是其他组的程序影响我们了!”但抱怨这是没用的,如果你这么认为,那么请拿出证据!但静下来分析一下不难发现,这不可能是其他程序的影响,其他进程不可能影响我们进程对信号的处理方式。
system()函数之前没出错,是因为systeme()函数依赖了系统的一个特性,那就是内核初始化进程时对SIGCHLD信号的处理方式为SIG_DFL,这是什么什么意思呢?即内核发现进程的子进程终止后给进程发送一个SIGCHLD信号,进程收到该信号后采用SIG_DFL方式处理,那么SIG_DFL又是什么方式呢?SIG_DFL是一个宏,定义了一个信号处理函数指针,事实上该信号处理函数什么也没做。这个特性正是system()函数需要的,system()函数首先fork()一个子进程执行command命令,执行完后system()函数会使用waitpid()函数对子进程进行收尸。
通过上面的分析,我们可以清醒的得知,system()执行前,SIGCHLD信号的处理方式肯定变了,不再是SIG_DFL了,至于变成什么暂时不知道,事实上,我们也不需要知道,我们只需要记得使用system()函数前把SIGCHLD信号处理方式显式修改为SIG_DFL方式,同时记录原来的处理方式,使用完system()后再设为原来的处理方式。这样我们可以屏蔽因系统升级或信号处理方式改变带来的影响。
我们公司采用的是持续集成+敏捷开发模式,每天都会由专门的team负责自动化case的测试,每次称为一个build,我们分析了本次build与上次build使用的系统版本,发现版本确实升级了。于是我们找到了相关team进行验证,我们把问题详细的描述了一下,很快对方给了反馈,下面是邮件回复原文:
LIBGEN 里新增加了SIGCHLD的处理。将其ignore。为了避免僵尸进程的产生。
看来我们的猜想没错!问题分析到这里,解决方法也清晰了,于是我们修改了我们的pox_system()函数:
typedef void (*sighandler_t)(int);
int pox_system(const char *cmd_line)
int ret = 0;
sighandler_t old_
old_handler = signal(SIGCHLD, SIG_DFL);
ret = system(cmd_line);
signal(SIGCHLD, old_handler);
我想这是调用system()比较完美的解决方案了,同时使用pox_system()函数封装带来了非常棒的易维护性,我们只需要修改此处一个函数,其他调用处都不需要改。
后来,查看了对方修改的代码,果然从代码上找到了答案:
/* Ignore SIGCHLD to avoid zombie process */
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
return -1;
我们公司的代码使用SVN进程管理的,到目前为止有很多branch,逐渐的,几乎每个branch都出现了上面的问题,于是我逐个在各个branchc上fix这个问题,几乎忙了一天,因为有的branch已被锁定,再想merge代码必须找相关负责人说明问题的严重性,还要在不同的环境上测试,我边做这些边想,系统这样升级合适吗?
首先,由于系统的升级导致我们的代码在测试时发现问题,这时再急忙去fix,造成了我们的被动,我想这是他们的一个失误。你做的升级必须要考虑到对其他team的影响吧?何况你做的是系统升级。升级前需要做个风险评估,对可能造成的影响通知大家,这样才职业嘛。
再者,据他们的说法,修改信号处理方式是为了避免僵尸进程,当然初衷是好的,但这样的升级影响了一些函数的使用方式,比如system()函数、wait()函数、waipid()、fork()函数,这些函数都与子进程有关,如果你希望使用wait()或waitpid()对子进程收尸,那么你必须使用上面介绍的方式:在调用前(事实上是fork()前)将SIGCHLD信号置为SIG_DFL处理方式,调用后(事实上wait()/waitpid()后)再将信号处理方式设置为从前的值。你的系统升级,强制大家完善代码,确实提高了代码质量,但是对于这种升级我不是很认同,试想一下,你见过多少fork()-&waitpid()前后都设置SIGCHLD信号的代码?
使用system()函数的建议
上在给出了调用system()函数的比较安全的用法,但使用system()函数还是容易出错,错在哪?那就是system()函数的返回值,关于其返回值的介绍请见上篇文章。system()函数有时很方便,但不可滥用!
1、建议system()函数只用来执行shell命令,因为一般来讲,system()返回值不是0就说明出错了;
2、建议监控一下system()函数的执行完毕后的errno值,争取出错时给出更多有用信息;
3、建议考虑一下system()函数的替代函数popen();其用法在我的另一篇文章有介绍。
转载请注明出处。
”在线下联结了各位 OSCer,推广开源项目和理念,很荣幸有你的参与~
领取条件:参与过开源中国“源创会”的 OSCer 可以领取
你有兴趣做个demo探讨下么?
你有兴趣做个demo探讨下么? 解释一下我的看法,假设是如下的环境:0.父进程创建了10个子进程,然后一个信号处理函数来监视所有子进程的死活状态。1.父进程在调用pox_system函数时,将SIGCHLD信号的处理函数设置为默认(忽略)。2.恰巧在父进程执行pox_system函数的期间,子进程0挂掉了。此时,父进程将捕捉不到子进程挂掉的信息。我只是觉得存在这个可能性。由于上述问题的时机比较难以把握,所以不好写demo分析,不好意思。对于system函数的这个问题,我的做法是这样的:0.调用system函数执行所需的操作;1.在使用waitpid来处理子进程结束时,函数的options这个参数一定要设置为WNOHANG。这样确保父进程不会因为system函数返回的SIGCHLD信号,导致主进程发生堵塞;2.对waitpid函数的返回值进行判定,如果是需要处理的子进程,则进行相应处理。否则,丢弃SIGCHLD信号。
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥博客分类:
1 在java home下的bin目录下面创建文件java.all.policy文件,并添加一下内容:
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllP
2 执行命令
jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=10.12.49.64 &
注:10.12.49.64 为tomcat所在服务器的ip地址;如果执行jstatd 命令时,提示无法找到该命令,是因为你的java home下bin目录下不存在jstatd,重装一下jdk(我就遇到这个问题);如果你的java.all.policy文件不是放到java home的bin目录下的,那么执行上面命令的时候要使用绝对路径
3 上面两步成功之后,可以使用visualvm建立对远程机器上的监控,不过很多jmx相关功能无法使用,下面配置一下jmx
在tomcat的根目录下的bin目录下,vi catalina.sh修改此文件,在
# ----- Execute The Requested Command -----------------------------------------
这上面添加如下文字:
JAVA_OPTS="-Djava.rmi.server.hostname=10.12.49.64
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8081
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false $JAVA_OPTS"
export JAVA_OPTS
注:第一行的ip为tomcat所在服务器的ip;第三行的端口为jmx使用的端口,确保此端口是未被占用的;(不要少了第一行,我一开始配置的时候就是没有第一行,jmx一直连接不上)
4 启动tomcat,netstat -aux 看看端口是否被监听,如果被监听,说明配置成功了,然后在visualvm的远程选择ip,右键,添加“jmx连接”,成功连接就成功了
浏览: 270015 次
来自: 上海
多实例下就不行了吧
s3.getResourceUrl(bucketName, k ...
楼主请问WorkerEventHandler和EventHan ...
请问楼主使用的是什么UML工具啊?
stephenchow 写道sbjar都不放 那你放上来干嘛懒 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'热门文章热门标签
07月02日 |
07月02日 |
07月02日 |
07月02日 |
07月02日 |
07月02日 |
07月02日 |
07月02日 |linux下java报错_百度知道
linux下java报错
[root@localhost 桌面]# javac Hello.java
Hello.java:3: 错误: 找不到符号
public static void main(Sting []args)
位置: 类 Hello
Hello.java:5: 错误: 找不到符号
System.out.pin...
我有更好的答案
不应该是System.out.println(&Hello World&);么?应该是在out下找不到pintln方法,因为应该是println还有,main里面的参数是String
采纳率:76%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 冰点文库下载器报错 的文章

 

随机推荐