Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExecUtil.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2016 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.coreutils;
20 
21 import com.sun.javafx.PlatformUtil;
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.Writer;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.concurrent.TimeUnit;
30 import java.util.logging.Level;
32 
37 public final class ExecUtil {
38 
39  private static final long DEFAULT_TIMEOUT = 5;
40  private static final TimeUnit DEFAULT_TIMEOUT_UNITS = TimeUnit.SECONDS;
41 
50  public interface ProcessTerminator {
51 
58  boolean shouldTerminateProcess();
59  }
60 
65  public static class TimedProcessTerminator implements ProcessTerminator {
66 
67  private final long startTimeInSeconds;
68  private final long maxRunTimeInSeconds;
69 
76  public TimedProcessTerminator(long maxRunTimeInSeconds) {
77  this.maxRunTimeInSeconds = maxRunTimeInSeconds;
78  this.startTimeInSeconds = (new Date().getTime()) / 1000;
79  }
80 
90  // user specified time out
91  this.maxRunTimeInSeconds = UserPreferences.getProcessTimeOutHrs() * 3600;
92  } else {
93  // never time out
94  this.maxRunTimeInSeconds = Long.MAX_VALUE;
95  }
96  this.startTimeInSeconds = (new Date().getTime()) / 1000;
97  }
98 
99  @Override
100  public boolean shouldTerminateProcess() {
101  long currentTimeInSeconds = (new Date().getTime()) / 1000;
102  return (currentTimeInSeconds - this.startTimeInSeconds) > this.maxRunTimeInSeconds;
103  }
104  }
105 
118  public static int execute(ProcessBuilder processBuilder) throws SecurityException, IOException {
119  return ExecUtil.execute(processBuilder, 30, TimeUnit.DAYS, new ProcessTerminator() {
120  @Override
121  public boolean shouldTerminateProcess() {
122  return false;
123  }
124  });
125  }
126 
140  public static int execute(ProcessBuilder processBuilder, ProcessTerminator terminator) throws SecurityException, IOException {
141  return ExecUtil.execute(processBuilder, ExecUtil.DEFAULT_TIMEOUT, ExecUtil.DEFAULT_TIMEOUT_UNITS, terminator);
142  }
143 
159  public static int execute(ProcessBuilder processBuilder, long timeOut, TimeUnit units, ProcessTerminator terminator) throws SecurityException, IOException {
160  Process process = processBuilder.start();
161  try {
162  do {
163  process.waitFor(timeOut, units);
164  if (process.isAlive() && terminator.shouldTerminateProcess()) {
165  killProcess(process);
166  }
167  } while (process.isAlive());
168  } catch (InterruptedException ex) {
169  if (process.isAlive()) {
170  killProcess(process);
171  }
172  Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, "Thread interrupted while running {0}", processBuilder.command().get(0)); // NON-NLS
173  Thread.currentThread().interrupt();
174  }
175  return process.exitValue();
176  }
177 
183  public static void killProcess(Process process) {
184  if (process == null) {
185  return;
186  }
187 
188  try {
189  if (PlatformUtil.isWindows()) {
190  Win32Process parentProcess = new Win32Process(process);
191  List<Win32Process> children = parentProcess.getChildren();
192 
193  children.stream().forEach((child) -> {
194  child.terminate();
195  });
196  parentProcess.terminate();
197  } else {
198  process.destroyForcibly();
199  }
200  } catch (Exception ex) {
201  logger.log(Level.WARNING, "Error occurred when attempting to kill process: {0}", ex.getMessage()); // NON-NLS
202  }
203  }
204 
208  private static final Logger logger = Logger.getLogger(ExecUtil.class.getName());
209  private Process proc = null;
213  private int exitValue = -100;
214 
225  @Deprecated
226  public synchronized String execute(final String aCommand, final String... params) throws IOException, InterruptedException {
227  // build command array
228  String[] arrayCommand = new String[params.length + 1];
229  arrayCommand[0] = aCommand;
230 
231  StringBuilder arrayCommandToLog = new StringBuilder();
232  arrayCommandToLog.append(aCommand).append(" ");
233 
234  for (int i = 1; i < arrayCommand.length; i++) {
235  arrayCommand[i] = params[i - 1];
236  arrayCommandToLog.append(arrayCommand[i]).append(" ");
237  }
238 
239  final Runtime rt = Runtime.getRuntime();
240  logger.log(Level.INFO, "Executing {0}", arrayCommandToLog.toString()); //NON-NLS
241 
242  proc = rt.exec(arrayCommand);
243 
244  //stderr redirect
245  errorStringRedirect = new ExecUtil.StreamToStringRedirect(proc.getErrorStream(), "ERROR"); //NON-NLS
246  errorStringRedirect.start();
247 
248  //stdout redirect
249  outputStringRedirect = new ExecUtil.StreamToStringRedirect(proc.getInputStream(), "OUTPUT"); //NON-NLS
250  outputStringRedirect.start();
251 
252  //wait for process to complete and capture error core
253  this.exitValue = proc.waitFor();
254 
255  // wait for output redirectors to finish writing / reading
256  outputStringRedirect.join();
257  errorStringRedirect.join();
258 
259  return outputStringRedirect.getOutput();
260  }
261 
272  @Deprecated
273  public synchronized void execute(final Writer stdoutWriter, final String aCommand, final String... params) throws IOException, InterruptedException {
274 
275  // build command array
276  String[] arrayCommand = new String[params.length + 1];
277  arrayCommand[0] = aCommand;
278 
279  StringBuilder arrayCommandToLog = new StringBuilder();
280  arrayCommandToLog.append(aCommand).append(" ");
281 
282  for (int i = 1; i < arrayCommand.length; i++) {
283  arrayCommand[i] = params[i - 1];
284  arrayCommandToLog.append(arrayCommand[i]).append(" ");
285  }
286 
287  final Runtime rt = Runtime.getRuntime();
288  logger.log(Level.INFO, "Executing {0}", arrayCommandToLog.toString()); //NON-NLS
289 
290  proc = rt.exec(arrayCommand);
291 
292  //stderr redirect
293  errorStringRedirect = new ExecUtil.StreamToStringRedirect(proc.getErrorStream(), "ERROR"); //NON-NLS
294  errorStringRedirect.start();
295 
296  //stdout redirect
297  outputWriterRedirect = new ExecUtil.StreamToWriterRedirect(proc.getInputStream(), stdoutWriter);
298  outputWriterRedirect.start();
299 
300  //wait for process to complete and capture error core
301  this.exitValue = proc.waitFor();
302  logger.log(Level.INFO, "{0} exit value: {1}", new Object[]{aCommand, exitValue}); //NON-NLS
303 
304  // wait for them to finish writing / reading
305  outputWriterRedirect.join();
306  errorStringRedirect.join();
307 
308  //gc process with its streams
309  //proc = null;
310  }
311 
315  @Deprecated
316  public synchronized void stop() {
317 
318  if (errorStringRedirect != null) {
319  errorStringRedirect.stopRun();
320  errorStringRedirect = null;
321  }
322 
323  if (outputStringRedirect != null) {
324  outputStringRedirect.stopRun();
325  outputStringRedirect = null;
326  }
327 
328  if (outputWriterRedirect != null) {
329  outputWriterRedirect.stopRun();
330  outputWriterRedirect = null;
331  }
332 
333  if (proc != null) {
334  proc.destroy();
335  proc = null;
336  }
337  }
338 
345  @Deprecated
346  synchronized public int getExitValue() {
347  return this.exitValue;
348  }
349 
356  private static class StreamToStringRedirect extends Thread {
357 
358  private static final Logger logger = Logger.getLogger(StreamToStringRedirect.class.getName());
359  private final InputStream is;
360  private final StringBuffer output = new StringBuffer();
361  private volatile boolean doRun = false;
362 
363  StreamToStringRedirect(final InputStream anIs, final String aType) {
364  this.is = anIs;
365  this.doRun = true;
366  }
367 
374  @Override
375  public final void run() {
376  final String SEP = System.getProperty("line.separator");
377  InputStreamReader isr;
378  BufferedReader br = null;
379  try {
380  isr = new InputStreamReader(this.is);
381  br = new BufferedReader(isr);
382  String line = null;
383  while (doRun && (line = br.readLine()) != null) {
384  this.output.append(line).append(SEP);
385  }
386  } catch (final IOException ex) {
387  logger.log(Level.WARNING, "Error redirecting stream to string buffer", ex); //NON-NLS
388  } finally {
389  if (br != null) {
390  try {
391  br.close();
392  } catch (IOException ex) {
393  logger.log(Level.SEVERE, "Error closing stream reader", ex); //NON-NLS
394  }
395  }
396  }
397  }
398 
403  public void stopRun() {
404  doRun = false;
405  }
406 
413  public final String getOutput() {
414  return this.output.toString();
415  }
416  }
417 
426  private static class StreamToWriterRedirect extends Thread {
427 
428  private static final Logger logger = Logger.getLogger(StreamToStringRedirect.class.getName());
429  private final InputStream is;
430  private volatile boolean doRun = false;
431  private Writer writer = null;
432 
433  StreamToWriterRedirect(final InputStream anIs, final Writer writer) {
434  this.is = anIs;
435  this.writer = writer;
436  this.doRun = true;
437  }
438 
445  @Override
446  public final void run() {
447  final String SEP = System.getProperty("line.separator");
448  InputStreamReader isr;
449  BufferedReader br = null;
450  try {
451  isr = new InputStreamReader(this.is);
452  br = new BufferedReader(isr);
453  String line = null;
454  while (doRun && (line = br.readLine()) != null) {
455  writer.append(line).append(SEP);
456  }
457  } catch (final IOException ex) {
458  logger.log(Level.SEVERE, "Error reading output and writing to file writer", ex); //NON-NLS
459  } finally {
460  try {
461  if (doRun) {
462  writer.flush();
463  }
464  if (br != null) {
465  br.close();
466  }
467 
468  } catch (IOException ex) {
469  logger.log(Level.SEVERE, "Error flushing file writer", ex); //NON-NLS
470  }
471  }
472  }
473 
478  public void stopRun() {
479  doRun = false;
480  }
481  }
482 }
ExecUtil.StreamToStringRedirect errorStringRedirect
Definition: ExecUtil.java:210
static int execute(ProcessBuilder processBuilder, ProcessTerminator terminator)
Definition: ExecUtil.java:140
ExecUtil.StreamToWriterRedirect outputWriterRedirect
Definition: ExecUtil.java:212
static int execute(ProcessBuilder processBuilder)
Definition: ExecUtil.java:118
static final TimeUnit DEFAULT_TIMEOUT_UNITS
Definition: ExecUtil.java:40
synchronized void execute(final Writer stdoutWriter, final String aCommand, final String...params)
Definition: ExecUtil.java:273
ExecUtil.StreamToStringRedirect outputStringRedirect
Definition: ExecUtil.java:211
static void killProcess(Process process)
Definition: ExecUtil.java:183
synchronized static Logger getLogger(String name)
Definition: Logger.java:161
static int execute(ProcessBuilder processBuilder, long timeOut, TimeUnit units, ProcessTerminator terminator)
Definition: ExecUtil.java:159
synchronized String execute(final String aCommand, final String...params)
Definition: ExecUtil.java:226

Copyright © 2012-2016 Basis Technology. Generated on: Tue Oct 25 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.