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; 022 023import org.apache.commons.cli.CommandLine; 024import org.apache.commons.cli.CommandLineParser; 025import org.apache.commons.cli.GnuParser; 026import org.apache.commons.cli.HelpFormatter; 027import org.apache.commons.cli.Option; 028import org.apache.commons.cli.Options; 029import org.apache.commons.cli.ParseException; 030import org.apache.hadoop.classification.InterfaceAudience.Public; 031import org.apache.hadoop.classification.InterfaceStability.Evolving; 032import org.apache.hadoop.conf.Configuration; 033import org.apache.hadoop.conf.Configured; 034import org.apache.hadoop.security.UserGroupInformation; 035import org.apache.hadoop.util.Tool; 036import org.apache.hadoop.yarn.api.records.ApplicationId; 037import org.apache.hadoop.yarn.api.records.ApplicationReport; 038import org.apache.hadoop.yarn.client.api.YarnClient; 039import org.apache.hadoop.yarn.conf.YarnConfiguration; 040import org.apache.hadoop.yarn.exceptions.YarnException; 041import org.apache.hadoop.yarn.logaggregation.LogCLIHelpers; 042import org.apache.hadoop.yarn.util.ConverterUtils; 043 044import com.google.common.annotations.VisibleForTesting; 045 046@Public 047@Evolving 048public class LogsCLI extends Configured implements Tool { 049 050 private static final String CONTAINER_ID_OPTION = "containerId"; 051 private static final String APPLICATION_ID_OPTION = "applicationId"; 052 private static final String NODE_ADDRESS_OPTION = "nodeAddress"; 053 private static final String APP_OWNER_OPTION = "appOwner"; 054 055 @Override 056 public int run(String[] args) throws Exception { 057 058 Options opts = new Options(); 059 Option appIdOpt = new Option(APPLICATION_ID_OPTION, true, "ApplicationId (required)"); 060 appIdOpt.setRequired(true); 061 opts.addOption(appIdOpt); 062 opts.addOption(CONTAINER_ID_OPTION, true, 063 "ContainerId (must be specified if node address is specified)"); 064 opts.addOption(NODE_ADDRESS_OPTION, true, "NodeAddress in the format " 065 + "nodename:port (must be specified if container id is specified)"); 066 opts.addOption(APP_OWNER_OPTION, true, 067 "AppOwner (assumed to be current user if not specified)"); 068 opts.getOption(APPLICATION_ID_OPTION).setArgName("Application ID"); 069 opts.getOption(CONTAINER_ID_OPTION).setArgName("Container ID"); 070 opts.getOption(NODE_ADDRESS_OPTION).setArgName("Node Address"); 071 opts.getOption(APP_OWNER_OPTION).setArgName("Application Owner"); 072 073 Options printOpts = new Options(); 074 printOpts.addOption(opts.getOption(CONTAINER_ID_OPTION)); 075 printOpts.addOption(opts.getOption(NODE_ADDRESS_OPTION)); 076 printOpts.addOption(opts.getOption(APP_OWNER_OPTION)); 077 078 if (args.length < 1) { 079 printHelpMessage(printOpts); 080 return -1; 081 } 082 083 CommandLineParser parser = new GnuParser(); 084 String appIdStr = null; 085 String containerIdStr = null; 086 String nodeAddress = null; 087 String appOwner = null; 088 try { 089 CommandLine commandLine = parser.parse(opts, args, true); 090 appIdStr = commandLine.getOptionValue(APPLICATION_ID_OPTION); 091 containerIdStr = commandLine.getOptionValue(CONTAINER_ID_OPTION); 092 nodeAddress = commandLine.getOptionValue(NODE_ADDRESS_OPTION); 093 appOwner = commandLine.getOptionValue(APP_OWNER_OPTION); 094 } catch (ParseException e) { 095 System.err.println("options parsing failed: " + e.getMessage()); 096 printHelpMessage(printOpts); 097 return -1; 098 } 099 100 if (appIdStr == null) { 101 System.err.println("ApplicationId cannot be null!"); 102 printHelpMessage(printOpts); 103 return -1; 104 } 105 106 ApplicationId appId = null; 107 try { 108 appId = ConverterUtils.toApplicationId(appIdStr); 109 } catch (Exception e) { 110 System.err.println("Invalid ApplicationId specified"); 111 return -1; 112 } 113 114 try { 115 int resultCode = verifyApplicationState(appId); 116 if (resultCode != 0) { 117 System.out.println("Logs are not avaiable right now."); 118 return resultCode; 119 } 120 } catch (Exception e) { 121 System.err.println("Unable to get ApplicationState." 122 + " Attempting to fetch logs directly from the filesystem."); 123 } 124 125 LogCLIHelpers logCliHelper = new LogCLIHelpers(); 126 logCliHelper.setConf(getConf()); 127 128 if (appOwner == null || appOwner.isEmpty()) { 129 appOwner = UserGroupInformation.getCurrentUser().getShortUserName(); 130 } 131 int resultCode = 0; 132 if (containerIdStr == null && nodeAddress == null) { 133 resultCode = logCliHelper.dumpAllContainersLogs(appId, appOwner, System.out); 134 } else if ((containerIdStr == null && nodeAddress != null) 135 || (containerIdStr != null && nodeAddress == null)) { 136 System.out.println("ContainerId or NodeAddress cannot be null!"); 137 printHelpMessage(printOpts); 138 resultCode = -1; 139 } else { 140 resultCode = 141 logCliHelper.dumpAContainersLogs(appIdStr, containerIdStr, 142 nodeAddress, appOwner); 143 } 144 145 return resultCode; 146 } 147 148 private int verifyApplicationState(ApplicationId appId) throws IOException, 149 YarnException { 150 YarnClient yarnClient = createYarnClient(); 151 152 try { 153 ApplicationReport appReport = yarnClient.getApplicationReport(appId); 154 switch (appReport.getYarnApplicationState()) { 155 case NEW: 156 case NEW_SAVING: 157 case SUBMITTED: 158 return -1; 159 case ACCEPTED: 160 case RUNNING: 161 case FAILED: 162 case FINISHED: 163 case KILLED: 164 default: 165 break; 166 167 } 168 } finally { 169 yarnClient.close(); 170 } 171 return 0; 172 } 173 174 @VisibleForTesting 175 protected YarnClient createYarnClient() { 176 YarnClient yarnClient = YarnClient.createYarnClient(); 177 yarnClient.init(getConf()); 178 yarnClient.start(); 179 return yarnClient; 180 } 181 182 public static void main(String[] args) throws Exception { 183 Configuration conf = new YarnConfiguration(); 184 LogsCLI logDumper = new LogsCLI(); 185 logDumper.setConf(conf); 186 int exitCode = logDumper.run(args); 187 System.exit(exitCode); 188 } 189 190 private void printHelpMessage(Options options) { 191 System.out.println("Retrieve logs for completed YARN applications."); 192 HelpFormatter formatter = new HelpFormatter(); 193 formatter.printHelp("yarn logs -applicationId <application ID> [OPTIONS]", new Options()); 194 formatter.setSyntaxPrefix(""); 195 formatter.printHelp("general options are:", options); 196 } 197}