背景:

系统是一个分布式架构,分为管理端和agent端。agent接收管理端命令,调用bash执行操作,获取结果后返回管理端。中间以jms为通讯机制。

现象:

管理端调用agent有时会显示jms超时。经查,脚本可以单独运行(不管运行结果如何,进程都能正常退出)。而agent中执行process.waitFor()的语句有时却被block,直至超时。

分析:

由于脚本看起来无错,所以主要集中在看java调用bash的写法,参考了多种,大同小异,问题仍然存在。经人指点,调用linux的进程操作,主要会和三个数据流打交道。一个是输入流,对应java中Process对象的OutputStream,一个是输出流,对应java中Process对象的InputStream,还有一个是错误流ErrorStream。我们在ErrorStream中发现了错误信息。原来,脚本会创建一个服务,并不断调用某个命令检测是否成功。在单独运行脚本时,该命令可以被脚本直接调用,但在java调用时,由于运行的用户不同,该命令无法执行而报错。此外该检测一直运行,所以整个被block。

解决:

  • java运行bash的命令中加上-l,以声明用登录用户来运行脚本。
  • 检测不是无休止,而是隔段时间检测若干次后退出。