Issues of Java invocation of the Shell scripts

(1) The Process, ProcessBuilder, Runtime

The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process. 

In Java, the ProcessBuilder,start() and Runtime.exec() methods create a native process (the Parent Process) and return an instance of a subclass of Process (The Subprocess) that can be used to control the process (the Parent Process) and obtain information about it.

By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), andgetErrorStream(). The parent process uses these streams to feed input to and get output from the subprocess.  So, Process.getInputStream() method is used to obtain the output of the native process or parent process. Where desired, subprocess I/O can also be redirected using methods of the ProcessBuilder class, such as the redirect the output of the parent process to a log file

Notice:  Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock. Most block problems of invocation shell command is explained by this.

(2) example, a syncAction method to invoke a shell script which would tar a workspace, send the tar to a remote server, then invoke the restore.sh on that server.

  public Boolean syncAction() throws Exception {
  
		  String succe="ALL_END_SUC";
		  BufferedReader br=null;
		  Process p=null;
		  try {
				String cmd="/etc/abc/syncAction.sh";
				logger.info("syncCmd:"+cmd);
				Runtime r = Runtime.getRuntime();
				p = r.exec(cmd);
				Thread.sleep(1000);
				br = new BufferedReader(new InputStreamReader(p.getInputStream())); 
				String temp= br.readLine();
				while(temp!=null){
					logger.info("syncCmd:"+temp);
					temp= br.readLine();
					if(temp.contains(succe)){
						logger.info("syncCmd end:"+temp);
						return true;
					}
				}
				
				int rtnCode = -1;
				rtnCode = p.waitFor();
				logger.info("syncCmd return code=" + rtnCode);
				
				if (rtnCode != 0) {
					br = new BufferedReader(new InputStreamReader(
							p.getErrorStream()));
					String inline;
					String errMsg = "";
					while ((inline = br.readLine()) != null) {
						errMsg += inline;
						errMsg += System.getProperty("line.separator");
					}
					logger.error("error when exec SyncOne, error message is "+ errMsg);
					return false;
				}
				return true;
		  } catch (Exception e) {
				logger.error("SyncAction:",e);
				return false;
		  }finally{
				if(p!=null){
					p.destroy();
				}
			    if(br!=null){
				   try{
					   br.close(); 
				   }catch(Exception e){
				   }
			   }
			}
		}


(3) the problems

There are two parts in above method to finish the invocation,  one is to catch the SUC single, the other is to invoke p.waitFor(); the former one is preference, because the latter one is more complex.

No matter whether it needs to print the output of Parent Process, the while() loop is necessary, Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock. In java, Null is used to represent the end of the stream.

And even though this loop is used,  the block is still encountered, the further way is to reduce the output message of the Stream. Especially,  some linux command which have the V argument meaning verbose and leading to a mass of output, should always be thought highly of. For example, the tar -zcvf ,  tar -zxvf,  rm -vrf, and so on.



"Exception has been thrown by the target of an invocation" 是一种常见的异常信息,它通常表示在调用一个方法或属性时,目标对象引发了一个异常。这个异常可能是由目标对象本身抛出的,也可能是由目标对象调用的另一个对象引发的。 这种异常信息通常比较抽象,无法直接定位问题所在。如果你遇到了这个异常信息,可以尝试以下方法进行排查: 1. 打开 Visual Studio 的“调试”菜单,选择“Windows”>“异常设置”,将“常规”选项卡中的“常规异常”勾选上。这样,当程序抛出异常时,Visual Studio 将在调试时中断程序并显示异常的详细信息,帮助你更快速地定位问题所在。 2. 查看异常信息中的“InnerException”属性,看看是否有更具体的异常信息。 3. 可以尝试在代码中使用 try-catch 语句捕获异常,并将异常信息输出到控制台或日志文件中,以便更好地跟踪问题。 4. 检查代码中的变量是否为空或未初始化,这可能会导致引用空对象而抛出异常。 5. 如果是在调用其他程序集或服务时发生的异常,可能是由于配置文件、文件路径或网络连接等问题引起的。可以仔细检查相关配置信息,以确保程序能够正确访问所需的资源。 总之,处理这种异常信息通常需要一定的调试经验和技巧。需要仔细地分析异常信息,逐步排查可能的问题,才能找到问题所在并解决它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值