001/** 002* Licensed to the Apache Software Foundation (ASF) under one 003* or more contributor license agreements. See the NOTICE file 004* distributed with this work for additional information 005* regarding copyright ownership. The ASF licenses this file 006* to you under the Apache License, Version 2.0 (the 007* "License"); you may not use this file except in compliance 008* with the License. You may obtain a copy of the License at 009* 010* http://www.apache.org/licenses/LICENSE-2.0 011* 012* Unless required by applicable law or agreed to in writing, software 013* distributed under the License is distributed on an "AS IS" BASIS, 014* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015* See the License for the specific language governing permissions and 016* limitations under the License. 017*/ 018 019package org.apache.hadoop.yarn.client.cli; 020 021import java.io.IOException; 022import java.io.StringReader; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Collections; 026import java.util.List; 027 028import javax.ws.rs.core.MediaType; 029import javax.xml.parsers.DocumentBuilder; 030import javax.xml.parsers.DocumentBuilderFactory; 031 032import org.apache.commons.cli.CommandLine; 033import org.apache.commons.cli.CommandLineParser; 034import org.apache.commons.cli.GnuParser; 035import org.apache.commons.cli.HelpFormatter; 036import org.apache.commons.cli.Option; 037import org.apache.commons.cli.Options; 038import org.apache.commons.cli.ParseException; 039import org.apache.commons.lang.StringUtils; 040import org.apache.hadoop.classification.InterfaceAudience.Public; 041import org.apache.hadoop.classification.InterfaceStability.Evolving; 042import org.apache.hadoop.conf.Configuration; 043import org.apache.hadoop.conf.Configured; 044import org.apache.hadoop.security.UserGroupInformation; 045import org.apache.hadoop.util.Tool; 046import org.apache.hadoop.yarn.api.records.ApplicationId; 047import org.apache.hadoop.yarn.api.records.ApplicationReport; 048import org.apache.hadoop.yarn.api.records.ContainerId; 049import org.apache.hadoop.yarn.api.records.ContainerReport; 050import org.apache.hadoop.yarn.api.records.YarnApplicationState; 051import org.apache.hadoop.yarn.client.api.YarnClient; 052import org.apache.hadoop.yarn.conf.YarnConfiguration; 053import org.apache.hadoop.yarn.exceptions.YarnException; 054import org.apache.hadoop.yarn.logaggregation.LogCLIHelpers; 055import org.apache.hadoop.yarn.util.ConverterUtils; 056import org.apache.hadoop.yarn.util.Times; 057import org.apache.hadoop.yarn.webapp.util.WebAppUtils; 058import org.codehaus.jettison.json.JSONArray; 059import org.codehaus.jettison.json.JSONException; 060import org.codehaus.jettison.json.JSONObject; 061 062import com.google.common.annotations.VisibleForTesting; 063import com.sun.jersey.api.client.Client; 064import com.sun.jersey.api.client.ClientHandlerException; 065import com.sun.jersey.api.client.ClientResponse; 066import com.sun.jersey.api.client.UniformInterfaceException; 067import com.sun.jersey.api.client.WebResource; 068import org.w3c.dom.Document; 069import org.w3c.dom.NodeList; 070import org.xml.sax.InputSource; 071 072@Public 073@Evolving 074public class LogsCLI extends Configured implements Tool { 075 076 private static final String CONTAINER_ID_OPTION = "containerId"; 077 private static final String APPLICATION_ID_OPTION = "applicationId"; 078 private static final String NODE_ADDRESS_OPTION = "nodeAddress"; 079 private static final String APP_OWNER_OPTION = "appOwner"; 080 private static final String AM_CONTAINER_OPTION = "am"; 081 private static final String CONTAINER_LOG_FILES = "logFiles"; 082 public static final String HELP_CMD = "help"; 083 084 @Override 085 public int run(String[] args) throws Exception { 086 087 Options opts = new Options(); 088 opts.addOption(HELP_CMD, false, "Displays help for all commands."); 089 Option appIdOpt = 090 new Option(APPLICATION_ID_OPTION, true, "ApplicationId (required)"); 091 appIdOpt.setRequired(true); 092 opts.addOption(appIdOpt); 093 opts.addOption(CONTAINER_ID_OPTION, true, "ContainerId. " 094 + "By default, it will only print syslog if the application is runing." 095 + " Work with -logFiles to get other logs."); 096 opts.addOption(NODE_ADDRESS_OPTION, true, "NodeAddress in the format " 097 + "nodename:port"); 098 opts.addOption(APP_OWNER_OPTION, true, 099 "AppOwner (assumed to be current user if not specified)"); 100 Option amOption = new Option(AM_CONTAINER_OPTION, true, 101 "Prints the AM Container logs for this application. " 102 + "Specify comma-separated value to get logs for related AM Container. " 103 + "For example, If we specify -am 1,2, we will get the logs for " 104 + "the first AM Container as well as the second AM Container. " 105 + "To get logs for all AM Containers, use -am ALL. " 106 + "To get logs for the latest AM Container, use -am -1. " 107 + "By default, it will only print out syslog. Work with -logFiles " 108 + "to get other logs"); 109 amOption.setValueSeparator(','); 110 amOption.setArgs(Option.UNLIMITED_VALUES); 111 amOption.setArgName("AM Containers"); 112 opts.addOption(amOption); 113 Option logFileOpt = new Option(CONTAINER_LOG_FILES, true, 114 "Work with -am/-containerId and specify comma-separated value " 115 + "to get specified container log files. Use \"ALL\" to fetch all the " 116 + "log files for the container."); 117 logFileOpt.setValueSeparator(','); 118 logFileOpt.setArgs(Option.UNLIMITED_VALUES); 119 logFileOpt.setArgName("Log File Name"); 120 opts.addOption(logFileOpt); 121 122 opts.getOption(APPLICATION_ID_OPTION).setArgName("Application ID"); 123 opts.getOption(CONTAINER_ID_OPTION).setArgName("Container ID"); 124 opts.getOption(NODE_ADDRESS_OPTION).setArgName("Node Address"); 125 opts.getOption(APP_OWNER_OPTION).setArgName("Application Owner"); 126 opts.getOption(AM_CONTAINER_OPTION).setArgName("AM Containers"); 127 128 Options printOpts = new Options(); 129 printOpts.addOption(opts.getOption(HELP_CMD)); 130 printOpts.addOption(opts.getOption(CONTAINER_ID_OPTION)); 131 printOpts.addOption(opts.getOption(NODE_ADDRESS_OPTION)); 132 printOpts.addOption(opts.getOption(APP_OWNER_OPTION)); 133 printOpts.addOption(opts.getOption(AM_CONTAINER_OPTION)); 134 printOpts.addOption(opts.getOption(CONTAINER_LOG_FILES)); 135 136 if (args.length < 1) { 137 printHelpMessage(printOpts); 138 return -1; 139 } 140 if (args[0].equals("-help")) { 141 printHelpMessage(printOpts); 142 return 0; 143 } 144 CommandLineParser parser = new GnuParser(); 145 String appIdStr = null; 146 String containerIdStr = null; 147 String nodeAddress = null; 148 String appOwner = null; 149 boolean getAMContainerLogs = false; 150 String[] logFiles = null; 151 List<String> amContainersList = new ArrayList<String>(); 152 try { 153 CommandLine commandLine = parser.parse(opts, args, true); 154 appIdStr = commandLine.getOptionValue(APPLICATION_ID_OPTION); 155 containerIdStr = commandLine.getOptionValue(CONTAINER_ID_OPTION); 156 nodeAddress = commandLine.getOptionValue(NODE_ADDRESS_OPTION); 157 appOwner = commandLine.getOptionValue(APP_OWNER_OPTION); 158 getAMContainerLogs = commandLine.hasOption(AM_CONTAINER_OPTION); 159 if (getAMContainerLogs) { 160 String[] amContainers = commandLine.getOptionValues(AM_CONTAINER_OPTION); 161 for (String am : amContainers) { 162 boolean errorInput = false; 163 if (!am.trim().equalsIgnoreCase("ALL")) { 164 try { 165 int id = Integer.parseInt(am.trim()); 166 if (id != -1 && id <= 0) { 167 errorInput = true; 168 } 169 } catch (NumberFormatException ex) { 170 errorInput = true; 171 } 172 if (errorInput) { 173 System.err.println( 174 "Invalid input for option -am. Valid inputs are 'ALL', -1 " 175 + "and any other integer which is larger than 0."); 176 printHelpMessage(printOpts); 177 return -1; 178 } 179 amContainersList.add(am.trim()); 180 } else { 181 amContainersList.add("ALL"); 182 break; 183 } 184 } 185 } 186 if (commandLine.hasOption(CONTAINER_LOG_FILES)) { 187 logFiles = commandLine.getOptionValues(CONTAINER_LOG_FILES); 188 } 189 } catch (ParseException e) { 190 System.err.println("options parsing failed: " + e.getMessage()); 191 printHelpMessage(printOpts); 192 return -1; 193 } 194 195 if (appIdStr == null) { 196 System.err.println("ApplicationId cannot be null!"); 197 printHelpMessage(printOpts); 198 return -1; 199 } 200 201 ApplicationId appId = null; 202 try { 203 appId = ApplicationId.fromString(appIdStr); 204 } catch (Exception e) { 205 System.err.println("Invalid ApplicationId specified"); 206 return -1; 207 } 208 209 LogCLIHelpers logCliHelper = new LogCLIHelpers(); 210 logCliHelper.setConf(getConf()); 211 212 if (appOwner == null || appOwner.isEmpty()) { 213 appOwner = UserGroupInformation.getCurrentUser().getShortUserName(); 214 } 215 216 YarnApplicationState appState = YarnApplicationState.NEW; 217 try { 218 appState = getApplicationState(appId); 219 if (appState == YarnApplicationState.NEW 220 || appState == YarnApplicationState.NEW_SAVING 221 || appState == YarnApplicationState.SUBMITTED) { 222 System.out.println("Logs are not avaiable right now."); 223 return -1; 224 } 225 } catch (IOException | YarnException e) { 226 System.err.println("Unable to get ApplicationState." 227 + " Attempting to fetch logs directly from the filesystem."); 228 } 229 230 // To get am logs 231 if (getAMContainerLogs) { 232 // if we do not specify the value for CONTAINER_LOG_FILES option, 233 // we will only output syslog 234 if (logFiles == null || logFiles.length == 0) { 235 logFiles = new String[] { "syslog" }; 236 } 237 // If the application is running, we will call the RM WebService 238 // to get the AppAttempts which includes the nodeHttpAddress 239 // and containerId for all the AM Containers. 240 // After that, we will call NodeManager webService to get the 241 // related logs 242 if (appState == YarnApplicationState.ACCEPTED 243 || appState == YarnApplicationState.RUNNING) { 244 return printAMContainerLogs(getConf(), appIdStr, amContainersList, 245 logFiles, logCliHelper, appOwner, false); 246 } else { 247 // If the application is in the final state, we will call RM webservice 248 // to get all AppAttempts information first. If we get nothing, 249 // we will try to call AHS webservice to get related AppAttempts 250 // which includes nodeAddress for the AM Containers. 251 // After that, we will use nodeAddress and containerId 252 // to get logs from HDFS directly. 253 if (getConf().getBoolean(YarnConfiguration.APPLICATION_HISTORY_ENABLED, 254 YarnConfiguration.DEFAULT_APPLICATION_HISTORY_ENABLED)) { 255 return printAMContainerLogs(getConf(), appIdStr, amContainersList, 256 logFiles, logCliHelper, appOwner, true); 257 } else { 258 System.out 259 .println( 260 "Can not get AMContainers logs for the application:" + appId); 261 System.out.println("This application:" + appId + " is finished." 262 + " Please enable the application history service. Or Using " 263 + "yarn logs -applicationId <appId> -containerId <containerId> " 264 + "--nodeAddress <nodeHttpAddress> to get the container logs"); 265 return -1; 266 } 267 } 268 } 269 270 int resultCode = 0; 271 if (containerIdStr != null) { 272 // if we provide the node address and the application is in the final 273 // state, we could directly get logs from HDFS. 274 if (nodeAddress != null && isApplicationFinished(appState)) { 275 // if user specified "ALL" as the logFiles param, pass null 276 // to logCliHelper so that it fetches all the logs 277 List<String> logs; 278 if (logFiles == null) { 279 logs = null; 280 } else if (fetchAllLogFiles(logFiles)) { 281 logs = null; 282 } else { 283 logs = Arrays.asList(logFiles); 284 } 285 return logCliHelper.dumpAContainersLogsForALogType(appIdStr, 286 containerIdStr, nodeAddress, appOwner, logs); 287 } 288 try { 289 // If the nodeAddress is not provided, we will try to get 290 // the ContainerReport. In the containerReport, we could get 291 // nodeAddress and nodeHttpAddress 292 ContainerReport report = getContainerReport(containerIdStr); 293 String nodeHttpAddress = 294 report.getNodeHttpAddress().replaceFirst( 295 WebAppUtils.getHttpSchemePrefix(getConf()), ""); 296 String nodeId = report.getAssignedNode().toString(); 297 // If the application is not in the final state, 298 // we will provide the NodeHttpAddress and get the container logs 299 // by calling NodeManager webservice. 300 if (!isApplicationFinished(appState)) { 301 if (logFiles == null || logFiles.length == 0) { 302 logFiles = new String[] { "syslog" }; 303 } 304 printContainerLogsFromRunningApplication(getConf(), appIdStr, 305 containerIdStr, nodeHttpAddress, nodeId, logFiles, logCliHelper, 306 appOwner); 307 } else { 308 String [] requestedLogFiles = logFiles; 309 if(fetchAllLogFiles(logFiles)) { 310 requestedLogFiles = null; 311 } 312 // If the application is in the final state, we will directly 313 // get the container logs from HDFS. 314 printContainerLogsForFinishedApplication(appIdStr, containerIdStr, 315 nodeId, requestedLogFiles, logCliHelper, appOwner); 316 } 317 return resultCode; 318 } catch (IOException | YarnException ex) { 319 System.err.println("Unable to get logs for this container:" 320 + containerIdStr + "for the application:" + appId); 321 if (!getConf().getBoolean(YarnConfiguration.APPLICATION_HISTORY_ENABLED, 322 YarnConfiguration.DEFAULT_APPLICATION_HISTORY_ENABLED)) { 323 System.out.println("Please enable the application history service. Or "); 324 } 325 System.out.println("Using " 326 + "yarn logs -applicationId <appId> -containerId <containerId> " 327 + "--nodeAddress <nodeHttpAddress> to get the container logs"); 328 return -1; 329 } 330 } else { 331 if (nodeAddress == null) { 332 resultCode = 333 logCliHelper.dumpAllContainersLogs(appId, appOwner, System.out); 334 } else { 335 System.out.println("Should at least provide ContainerId!"); 336 printHelpMessage(printOpts); 337 resultCode = -1; 338 } 339 } 340 return resultCode; 341 } 342 343 private YarnApplicationState getApplicationState(ApplicationId appId) 344 throws IOException, YarnException { 345 YarnClient yarnClient = createYarnClient(); 346 347 try { 348 ApplicationReport appReport = yarnClient.getApplicationReport(appId); 349 return appReport.getYarnApplicationState(); 350 } finally { 351 yarnClient.close(); 352 } 353 } 354 355 @VisibleForTesting 356 protected YarnClient createYarnClient() { 357 YarnClient yarnClient = YarnClient.createYarnClient(); 358 yarnClient.init(getConf()); 359 yarnClient.start(); 360 return yarnClient; 361 } 362 363 public static void main(String[] args) throws Exception { 364 Configuration conf = new YarnConfiguration(); 365 LogsCLI logDumper = new LogsCLI(); 366 logDumper.setConf(conf); 367 int exitCode = logDumper.run(args); 368 System.exit(exitCode); 369 } 370 371 private void printHelpMessage(Options options) { 372 System.out.println("Retrieve logs for completed YARN applications."); 373 HelpFormatter formatter = new HelpFormatter(); 374 formatter.printHelp("yarn logs -applicationId <application ID> [OPTIONS]", new Options()); 375 formatter.setSyntaxPrefix(""); 376 formatter.printHelp("general options are:", options); 377 } 378 379 private List<JSONObject> getAMContainerInfoForRMWebService( 380 Configuration conf, String appId) throws ClientHandlerException, 381 UniformInterfaceException, JSONException { 382 Client webServiceClient = Client.create(); 383 String webAppAddress = WebAppUtils.getRMWebAppURLWithScheme(conf); 384 385 WebResource webResource = webServiceClient.resource(webAppAddress); 386 387 ClientResponse response = 388 webResource.path("ws").path("v1").path("cluster").path("apps") 389 .path(appId).path("appattempts").accept(MediaType.APPLICATION_JSON) 390 .get(ClientResponse.class); 391 JSONObject json = 392 response.getEntity(JSONObject.class).getJSONObject("appAttempts"); 393 JSONArray requests = json.getJSONArray("appAttempt"); 394 List<JSONObject> amContainersList = new ArrayList<JSONObject>(); 395 for (int i = 0; i < requests.length(); i++) { 396 amContainersList.add(requests.getJSONObject(i)); 397 } 398 return amContainersList; 399 } 400 401 private List<JSONObject> getAMContainerInfoForAHSWebService(Configuration conf, 402 String appId) throws ClientHandlerException, UniformInterfaceException, 403 JSONException { 404 Client webServiceClient = Client.create(); 405 String webAppAddress = 406 WebAppUtils.getHttpSchemePrefix(conf) 407 + WebAppUtils.getAHSWebAppURLWithoutScheme(conf); 408 WebResource webResource = webServiceClient.resource(webAppAddress); 409 410 ClientResponse response = 411 webResource.path("ws").path("v1").path("applicationhistory").path("apps") 412 .path(appId).path("appattempts").accept(MediaType.APPLICATION_JSON) 413 .get(ClientResponse.class); 414 JSONObject json = response.getEntity(JSONObject.class); 415 JSONArray requests = json.getJSONArray("appAttempt"); 416 List<JSONObject> amContainersList = new ArrayList<JSONObject>(); 417 for (int i = 0; i < requests.length(); i++) { 418 amContainersList.add(requests.getJSONObject(i)); 419 } 420 Collections.reverse(amContainersList); 421 return amContainersList; 422 } 423 424 private boolean fetchAllLogFiles(String[] logFiles) { 425 if(logFiles != null) { 426 List<String> logs = Arrays.asList(logFiles); 427 if(logs.contains("ALL")) { 428 return true; 429 } 430 } 431 return false; 432 } 433 434 private String[] getContainerLogFiles(Configuration conf, 435 String containerIdStr, String nodeHttpAddress) throws IOException { 436 List<String> logFiles = new ArrayList<>(); 437 Client webServiceClient = Client.create(); 438 try { 439 WebResource webResource = webServiceClient 440 .resource(WebAppUtils.getHttpSchemePrefix(conf) + nodeHttpAddress); 441 ClientResponse response = 442 webResource.path("ws").path("v1").path("node").path("containers") 443 .path(containerIdStr).accept(MediaType.APPLICATION_XML) 444 .get(ClientResponse.class); 445 if (response.getClientResponseStatus().equals(ClientResponse.Status.OK)) { 446 try { 447 String xml = response.getEntity(String.class); 448 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 449 DocumentBuilder db = dbf.newDocumentBuilder(); 450 InputSource is = new InputSource(); 451 is.setCharacterStream(new StringReader(xml)); 452 Document dom = db.parse(is); 453 NodeList elements = dom.getElementsByTagName("containerLogFiles"); 454 for (int i = 0; i < elements.getLength(); i++) { 455 logFiles.add(elements.item(i).getTextContent()); 456 } 457 } catch (Exception e) { 458 System.out.println("Unable to parse xml from webservice. Error:"); 459 System.out.println(e.getMessage()); 460 throw new IOException(e); 461 } 462 } 463 464 } catch (ClientHandlerException | UniformInterfaceException ex) { 465 System.out.println("Unable to fetch log files list"); 466 throw new IOException(ex); 467 } 468 return logFiles.toArray(new String[0]); 469 } 470 471 private void printContainerLogsFromRunningApplication(Configuration conf, 472 String appId, String containerIdStr, String nodeHttpAddress, 473 String nodeId, String[] logFiles, LogCLIHelpers logCliHelper, 474 String appOwner) throws IOException { 475 String [] requestedLogFiles = logFiles; 476 // fetch all the log files for the container 477 if (fetchAllLogFiles(logFiles)) { 478 requestedLogFiles = 479 getContainerLogFiles(getConf(), containerIdStr, nodeHttpAddress); 480 } 481 Client webServiceClient = Client.create(); 482 String containerString = "\n\nContainer: " + containerIdStr; 483 System.out.println(containerString); 484 System.out.println(StringUtils.repeat("=", containerString.length())); 485 486 for (String logFile : requestedLogFiles) { 487 System.out.println("LogType:" + logFile); 488 System.out.println("Log Upload Time:" 489 + Times.format(System.currentTimeMillis())); 490 System.out.println("Log Contents:"); 491 try { 492 WebResource webResource = 493 webServiceClient.resource(WebAppUtils.getHttpSchemePrefix(conf) 494 + nodeHttpAddress); 495 ClientResponse response = 496 webResource.path("ws").path("v1").path("node") 497 .path("containerlogs").path(containerIdStr).path(logFile) 498 .accept(MediaType.TEXT_PLAIN).get(ClientResponse.class); 499 System.out.println(response.getEntity(String.class)); 500 System.out.println("End of LogType:" + logFile); 501 } catch (ClientHandlerException | UniformInterfaceException ex) { 502 System.out.println("Can not find the log file:" + logFile 503 + " for the container:" + containerIdStr + " in NodeManager:" 504 + nodeId); 505 } 506 } 507 // for the case, we have already uploaded partial logs in HDFS 508 logCliHelper.dumpAContainersLogsForALogType(appId, containerIdStr, nodeId, 509 appOwner, Arrays.asList(requestedLogFiles)); 510 } 511 512 private void printContainerLogsForFinishedApplication(String appId, 513 String containerId, String nodeAddress, String[] logFiles, 514 LogCLIHelpers logCliHelper, String appOwner) throws IOException { 515 String containerString = "\n\nContainer: " + containerId; 516 System.out.println(containerString); 517 System.out.println(StringUtils.repeat("=", containerString.length())); 518 logCliHelper.dumpAContainersLogsForALogType(appId, containerId, 519 nodeAddress, appOwner, logFiles != null ? Arrays.asList(logFiles) : null); 520 } 521 522 private ContainerReport getContainerReport(String containerIdStr) 523 throws YarnException, IOException { 524 YarnClient yarnClient = createYarnClient(); 525 try { 526 return yarnClient.getContainerReport( 527 ContainerId.fromString(containerIdStr)); 528 } finally { 529 yarnClient.close(); 530 } 531 } 532 533 private boolean isApplicationFinished(YarnApplicationState appState) { 534 return appState == YarnApplicationState.FINISHED 535 || appState == YarnApplicationState.FAILED 536 || appState == YarnApplicationState.KILLED; 537 } 538 539 private int printAMContainerLogs(Configuration conf, String appId, 540 List<String> amContainers, String[] logFiles, LogCLIHelpers logCliHelper, 541 String appOwner, boolean applicationFinished) throws Exception { 542 List<JSONObject> amContainersList = null; 543 List<AMLogsRequest> requests = new ArrayList<AMLogsRequest>(); 544 boolean getAMContainerLists = false; 545 String errorMessage = ""; 546 try { 547 amContainersList = getAMContainerInfoForRMWebService(conf, appId); 548 if (amContainersList != null && !amContainersList.isEmpty()) { 549 getAMContainerLists = true; 550 for (JSONObject amContainer : amContainersList) { 551 AMLogsRequest request = new AMLogsRequest(applicationFinished); 552 request.setAmContainerId(amContainer.getString("containerId")); 553 request.setNodeHttpAddress(amContainer.getString("nodeHttpAddress")); 554 request.setNodeId(amContainer.getString("nodeId")); 555 requests.add(request); 556 } 557 } 558 } catch (Exception ex) { 559 errorMessage = ex.getMessage(); 560 if (applicationFinished) { 561 try { 562 amContainersList = getAMContainerInfoForAHSWebService(conf, appId); 563 if (amContainersList != null && !amContainersList.isEmpty()) { 564 getAMContainerLists = true; 565 for (JSONObject amContainer : amContainersList) { 566 AMLogsRequest request = new AMLogsRequest(applicationFinished); 567 request.setAmContainerId(amContainer.getString("amContainerId")); 568 requests.add(request); 569 } 570 } 571 } catch (Exception e) { 572 errorMessage = e.getMessage(); 573 } 574 } 575 } 576 577 if (!getAMContainerLists) { 578 System.err.println("Unable to get AM container informations " 579 + "for the application:" + appId); 580 System.err.println(errorMessage); 581 return -1; 582 } 583 584 if (amContainers.contains("ALL")) { 585 for (AMLogsRequest request : requests) { 586 outputAMContainerLogs(request, conf, appId, logFiles, logCliHelper, 587 appOwner); 588 } 589 System.out.println(); 590 System.out.println("Specified ALL for -am option. " 591 + "Printed logs for all am containers."); 592 } else { 593 for (String amContainer : amContainers) { 594 int amContainerId = Integer.parseInt(amContainer.trim()); 595 if (amContainerId == -1) { 596 outputAMContainerLogs(requests.get(requests.size() - 1), conf, appId, 597 logFiles, logCliHelper, appOwner); 598 } else { 599 if (amContainerId <= requests.size()) { 600 outputAMContainerLogs(requests.get(amContainerId - 1), conf, appId, 601 logFiles, logCliHelper, appOwner); 602 } 603 } 604 } 605 } 606 return 0; 607 } 608 609 private void outputAMContainerLogs(AMLogsRequest request, Configuration conf, 610 String appId, String[] logFiles, LogCLIHelpers logCliHelper, 611 String appOwner) throws Exception { 612 String nodeHttpAddress = request.getNodeHttpAddress(); 613 String containerId = request.getAmContainerId(); 614 String nodeId = request.getNodeId(); 615 616 if (request.isAppFinished()) { 617 if (containerId != null && !containerId.isEmpty()) { 618 if (nodeId == null || nodeId.isEmpty()) { 619 try { 620 nodeId = 621 getContainerReport(containerId).getAssignedNode().toString(); 622 } catch (Exception ex) { 623 System.err.println(ex); 624 nodeId = null; 625 } 626 } 627 if (nodeId != null && !nodeId.isEmpty()) { 628 String [] requestedLogFilesList = null; 629 if(!fetchAllLogFiles(logFiles)) { 630 requestedLogFilesList = logFiles; 631 } 632 printContainerLogsForFinishedApplication(appId, containerId, nodeId, 633 requestedLogFilesList, logCliHelper, appOwner); 634 } 635 } 636 } else { 637 if (nodeHttpAddress != null && containerId != null 638 && !nodeHttpAddress.isEmpty() && !containerId.isEmpty()) { 639 String [] requestedLogFiles = logFiles; 640 // fetch all the log files for the AM 641 if (fetchAllLogFiles(logFiles)) { 642 requestedLogFiles = 643 getContainerLogFiles(getConf(), containerId, nodeHttpAddress); 644 } 645 printContainerLogsFromRunningApplication(conf, appId, containerId, 646 nodeHttpAddress, nodeId, requestedLogFiles, logCliHelper, appOwner); 647 } 648 } 649 } 650 651 private static class AMLogsRequest { 652 private String amContainerId; 653 private String nodeId; 654 private String nodeHttpAddress; 655 private final boolean isAppFinished; 656 657 AMLogsRequest(boolean isAppFinished) { 658 this.isAppFinished = isAppFinished; 659 this.setAmContainerId(""); 660 this.setNodeId(""); 661 this.setNodeHttpAddress(""); 662 } 663 664 public String getAmContainerId() { 665 return amContainerId; 666 } 667 668 public void setAmContainerId(String amContainerId) { 669 this.amContainerId = amContainerId; 670 } 671 672 public String getNodeId() { 673 return nodeId; 674 } 675 676 public void setNodeId(String nodeId) { 677 this.nodeId = nodeId; 678 } 679 680 public String getNodeHttpAddress() { 681 return nodeHttpAddress; 682 } 683 684 public void setNodeHttpAddress(String nodeHttpAddress) { 685 this.nodeHttpAddress = nodeHttpAddress; 686 } 687 688 public boolean isAppFinished() { 689 return isAppFinished; 690 } 691 } 692}