private void startServer(ServerType serverType, int rsPort) {
    // create working directory for this region server.
    String dir = serverWorkingDir(serverType, rsPort);
    String confStr = generateConfig(serverType, rsPort, dir);
    LOG.debug("Creating directory " + dir);
    new File(dir).mkdirs();

    writeStringToFile(confStr, dir + "/hbase-site.xml");

    // Set debug options to an empty string so that hbase-config.sh does not configure them
    // using default ports. If we want to run remote debugging on process-based local cluster's
    // daemons, we can automatically choose non-conflicting JDWP and JMX ports for each daemon
    // and specify them here.
    writeStringToFile("unset HBASE_MASTER_OPTS\n" + "unset HBASE_REGIONSERVER_OPTS\n"
      + "unset HBASE_ZOOKEEPER_OPTS\n" + "HBASE_MASTER_DBG_OPTS=' '\n"
      + "HBASE_REGIONSERVER_DBG_OPTS=' '\n" + "HBASE_ZOOKEEPER_DBG_OPTS=' '\n"
      + "HBASE_MASTER_JMX_OPTS=' '\n" + "HBASE_REGIONSERVER_JMX_OPTS=' '\n"
      + "HBASE_ZOOKEEPER_JMX_OPTS=' '\n", dir + "/hbase-env.sh");

    Map<String, String> envOverrides = new HashMap<>();
    envOverrides.put("HBASE_LOG_DIR", dir);
    envOverrides.put("HBASE_PID_DIR", dir);
    try {
      FileUtils.copyFile(new File(hbaseHome, "conf/log4j.properties"),
        new File(dir, "log4j.properties"));
    } catch (IOException ex) {
      LOG.error("Could not install log4j.properties into " + dir);
    }

    executeCommand(hbaseDaemonScript + " --config " + dir + " start " + serverType.fullName,
      envOverrides);
    daemonPidFiles.add(pidFilePath(serverType, rsPort));
    logTailDirs.add(dir);
  }
Generates a list of random port numbers in the sorted order. A sorted order makes sense if we
ever want to refer to these servers by their index in the returned array, e.g. server #0, #1,
etc.
hbase-diagnostics/src/test/java/org/apache/hadoop/hbase/util/ProcessBasedLocalHBaseCluster.java