View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  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.apache.hadoop.hbase.util;
20  
21  import java.lang.management.ManagementFactory;
22  import java.lang.management.RuntimeMXBean;
23  import java.util.Arrays;
24  import java.util.HashSet;
25  import java.util.Locale;
26  import java.util.Map.Entry;
27  import java.util.Set;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.hadoop.hbase.classification.InterfaceAudience;
32  import org.apache.hadoop.conf.Configuration;
33  import org.apache.hadoop.conf.Configured;
34  import org.apache.hadoop.hbase.HBaseConfiguration;
35  import org.apache.hadoop.util.Tool;
36  import org.apache.hadoop.util.ToolRunner;
37  import static org.apache.hadoop.hbase.util.Threads.isNonDaemonThreadRunning;
38  
39  /**
40   * Base class for command lines that start up various HBase daemons.
41   */
42  @InterfaceAudience.Private
43  public abstract class ServerCommandLine extends Configured implements Tool {
44    private static final Log LOG = LogFactory.getLog(ServerCommandLine.class);
45    @SuppressWarnings("serial")
46    private static final Set<String> DEFAULT_SKIP_WORDS = new HashSet<String>() {
47      {
48        add("secret");
49        add("passwd");
50        add("password");
51        add("credential");
52      }
53    };
54  
55    /**
56     * Implementing subclasses should return a usage string to print out.
57     */
58    protected abstract String getUsage();
59  
60    /**
61     * Print usage information for this command line.
62     *
63     * @param message if not null, print this message before the usage info.
64     */
65    protected void usage(String message) {
66      if (message != null) {
67        System.err.println(message);
68        System.err.println("");
69      }
70  
71      System.err.println(getUsage());
72    }
73  
74    /**
75     * Log information about the currently running JVM.
76     */
77    public static void logJVMInfo() {
78      // Print out vm stats before starting up.
79      RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
80      if (runtime != null) {
81        LOG.info("vmName=" + runtime.getVmName() + ", vmVendor=" +
82                 runtime.getVmVendor() + ", vmVersion=" + runtime.getVmVersion());
83        LOG.info("vmInputArguments=" + runtime.getInputArguments());
84      }
85    }
86  
87    /**
88     * Logs information about the currently running JVM process including
89     * the environment variables. Logging of env vars can be disabled by
90     * setting {@code "hbase.envvars.logging.disabled"} to {@code "true"}.
91     * <p>If enabled, you can also exclude environment variables containing
92     * certain substrings by setting {@code "hbase.envvars.logging.skipwords"}
93     * to comma separated list of such substrings.
94     */
95    public static void logProcessInfo(Configuration conf) {
96      // log environment variables unless asked not to
97      if (conf == null || !conf.getBoolean("hbase.envvars.logging.disabled", false)) {
98        Set<String> skipWords = new HashSet<String>(DEFAULT_SKIP_WORDS);
99        if (conf != null) {
100         String[] confSkipWords = conf.getStrings("hbase.envvars.logging.skipwords");
101         if (confSkipWords != null) {
102           skipWords.addAll(Arrays.asList(confSkipWords));
103         }
104       }
105 
106       nextEnv:
107       for (Entry<String, String> entry : System.getenv().entrySet()) {
108         String key = entry.getKey().toLowerCase(Locale.ROOT);
109         String value = entry.getValue().toLowerCase(Locale.ROOT);
110         // exclude variables which may contain skip words
111         for(String skipWord : skipWords) {
112           if (key.contains(skipWord) || value.contains(skipWord))
113             continue nextEnv;
114         }
115         LOG.info("env:"+entry);
116       }
117     }
118     // and JVM info
119     logJVMInfo();
120   }
121 
122   /**
123    * Parse and run the given command line. This will exit the JVM with
124    * the exit code returned from <code>run()</code>.
125    * If return code is 0, wait for atmost 30 seconds for all non-daemon threads to quit,
126    * otherwise exit the jvm
127    */
128   public void doMain(String args[]) {
129     try {
130       int ret = ToolRunner.run(HBaseConfiguration.create(), this, args);
131       if (ret != 0) {
132         System.exit(ret);
133       }
134       // Return code is 0 here.
135       boolean forceStop = false;
136       long startTime = EnvironmentEdgeManager.currentTime();
137       while (isNonDaemonThreadRunning()) {
138         if (EnvironmentEdgeManager.currentTime() - startTime > 30 * 1000) {
139           forceStop = true;
140           break;
141         }
142         Thread.sleep(1000);
143       }
144       if (forceStop) {
145         LOG.error("Failed to stop all non-daemon threads, so terminating JVM");
146         System.exit(-1);
147       }
148     } catch (Exception e) {
149       LOG.error("Failed to run", e);
150       System.exit(-1);
151     }
152   }
153 }