To start ambari-server on Linux, all you need to do is execute ambari-server start, so let’s start with this command to analyze what the startup process is doing

$ ambari-server start --debug
Using python  /usr/bin/python
Starting ambari-server
Ambari Server running with administrator privileges.
Organizing resource files at /var/lib/ambari-server/resources...
Ambari database consistency check started...
Server PID at: /var/run/ambari-server/ambari-server.pid
Server out at: /var/log/ambari-server/ambari-server.out
Server log at: /var/log/ambari-server/ambari-server.log
Waiting for server start.................................
Server started listening on 8080

DB configs consistency check found warnings. See /var/log/ambari-server/ambari-server-check-database.log for more details.
Ambari Server 'start' completed successfully.

After when we execute this command, the script in/etc/init. D/ambari – server, this script defines a ambari – start/stop/restart/server status… In the source code, this file is installed as sbin/ambari-server in the ambari-server project directory and ambari-server is actually a soft link on unx

[root@host-10-1-yy-xx sbin]# ls -al /sbin/ambari-server
lrwxrwxrwx 1 root root 25 Apr  1 17:14 /sbin/ambari-server -> /etc/init.d/ambari-server

ambari-server

Ambari_Python_Executable ="$ROOT/usr/sbin/ambari-server.py" "echo "Using Python "$python ret=0 case "${1:-}" in start) echo -e "Starting ambari-server" $PYTHON "$AMBARI_PYTHON_EXECUTABLE" "$@" ;; stop) echo -e "Stopping ambari-server" $PYTHON "$AMBARI_PYTHON_EXECUTABLE" "$@" ;; .

/usr/sbin/ambari-server.py = /usr/sbin/ambari-server.py = /usr/sbin/ambari-server.py = /usr/sbin/ambari-server

ambari-server.py

# ambari-server.py @OsFamilyFuncImpl(OsFamilyImpl.DEFAULT) def start(args): Logger.info ("Starting ambari-server.") status, pid = is_server_runing() # Running status: err = "Ambari Server is already running." raise FatalException(1, Logger.info ("Started ambari-server."); logger.info("Started ambari-server.

ambari_server_main.py

# ambari_server_main.py
def server_process_main(options, scmStatus=None):
  #先去读取这个配置文件/etc/ambari-server/conf/ambari.properties
  properties = get_ambari_properties()
  if properties == -1:
    err ="Error getting ambari properties"
    raise FatalException(-1, err)

  properties_for_print = []
  logger.info("Ambari server properties config:")
  for key, value in properties.getPropertyDict().items():
     if "passwd" not in key and "password" not in key:
       properties_for_print.append(key + "=" + value)

  logger.info(properties_for_print)

  # debug mode, including stop Java process at startup
  try:
    #如果有--debug启动,就会在这里设置为debug模式
    set_debug_mode_from_options(options)
  except AttributeError:
    pass

  # 检查hostname dns
  if not check_reverse_lookup():
    print_warning_msg("The hostname was not found in the reverse DNS lookup. "
                      "This may result in incorrect behavior. "
                      "Please check the DNS setup and fix the issue.")

  #检查在/etc/ambari-server/conf/ambari.properties中是否有配置数据库名称    
  #server.jdbc.database_name=ambari
  check_database_name_property()
  #从配置文件/etc/ambari-server/conf/ambari.properties中,加载数据库连接相关属性
  parse_properties_file(options)

  #检查配置文件/etc/ambari-server/conf/ambari.properties中是否有配置active.instance
  #如果没有配置默认这个值就为true,如果有的话也应配置为true,如果不为true的话,这个节点就不能启动ambari-server
  is_active_instance = get_is_active_instance()
  if not is_active_instance:
      print_warning_msg("This instance of ambari server is not designated as active. Cannot start ambari server.")
      err = "This is not an active instance. Shutting down..."
      raise FatalException(1, err)

  #从配置/etc/ambari-server/conf/ambari.properties中读到ambari-server.user=root
  ambari_user = read_ambari_user()
  #会判断当前用户是不是$ambari_user,是不是root用户
  #如果不是,会提示必须用root用户,sudo或者$ambari_user启动服务
  current_user = ensure_can_start_under_current_user(ambari_user)

  print_info_msg("Ambari Server is not running...")
  
  # 会首先查检配置在/etc/ambari-server/conf/ambari.properties中java.home=/usr/jdk64/jdk1.8.0_112的jdk是否可用,然后再检查配置的默认jdk安装路径下是否有可用jdk
  jdk_path = find_jdk()
  if jdk_path is None:
    err = "No JDK found, please run the \"ambari-server setup\" " \
          "command to install a JDK automatically or install any " \
          "JDK manually to " + configDefaults.JDK_INSTALL_DIR
    raise FatalException(1, err)

  if not options.skip_properties_validation:
    #检查必须要配置的properties,在properties中是否都配置了
    missing_properties = get_missing_properties(properties)
    if missing_properties:
      err = "Required properties are not found: " + str(missing_properties) + ". To skip properties validation " \
            "use \"--skip-properties-validation\""
      raise FatalException(1, err)

  # Preparations
  if is_root():
    print configDefaults.MESSAGE_SERVER_RUNNING_AS_ROOT

  #检查jdbc driver安装,没有就去下载安装(/etc/ambari-server/conf/ambari.properties会配置jdbc信息)
  ensure_jdbc_driver_is_installed(options, properties)
  #检查数据库是否启动,没有就启动
  ensure_dbms_is_running(options, properties, scmStatus)

  if scmStatus is not None:
    scmStatus.reportStartPending()

  # 刷新resource、stacks路径下的archives
  #/var/lib/ambari-server/resources
  #/var/lib/ambari-server/resources/stacks
  refresh_stack_hash(properties)

  if scmStatus is not None:
    scmStatus.reportStartPending()

  #就查了下是不是root用户,
  #如果不是root用户提示了:如果没有root权限无法检查firewall status,
  #如果有需要disable或adjust firewall
  ensure_server_security_is_configured()

  if scmStatus is not None:
    scmStatus.reportStartPending()

  #获取java home路径
  java_exe = get_java_exe_path()

  #ambari server class 对象
  serverClassPath = ServerClassPath(properties, options)

  #前边有设置是否debug,这里获取一下
  #默认不开启_DEBUG_MODE = 0,如果开启了会为1
  debug_mode = get_debug_mode()
  #SERVER_START_DEBUG = False
  debug_start = (debug_mode & 1) or SERVER_START_DEBUG
  #SUSPEND_START_MODE = False
  suspend_start = (debug_mode & 2) or SUSPEND_START_MODE
  suspend_mode = 'y' if suspend_start else 'n'

  #如果没用启用security.passwords.encryption.enabled,比较简单直接返回系统环境变量
  #如果启用需要做一些处理,这里先不解释
  environ = generate_env(options, ambari_user, current_user)
  
  # ambari_class_path=/usr/lib/ambari-server:server.jdbc.driver.path:SERVER_CLASSPATH:jdbc driver classpath
  # conf_dir=/etc/ambari-server/conf
  # class_path=conf_dir + os.pathsep + ambari_class_path
  class_path = serverClassPath.get_full_ambari_classpath_escaped_for_shell(validate_classpath=True)

  if options.skip_database_check:
    global jvm_args
    jvm_args += " -DskipDatabaseConsistencyCheck"
    print "Ambari Server is starting with the database consistency check skipped. Do not make any changes to your cluster " \
          "topology or perform a cluster upgrade until you correct the database consistency issues. See \"" \
          + configDefaults.DB_CHECK_LOG + "\" for more details on the consistency issues."
    properties.process_pair(CHECK_DATABASE_SKIPPED_PROPERTY, "true")
  else:
    print "Ambari database consistency check started..."
    if options.fix_database_consistency:
      jvm_args += " -DfixDatabaseConsistency"
    properties.process_pair(CHECK_DATABASE_SKIPPED_PROPERTY, "false")

  #更新/etc/ambari-server/conf/ambari.properties文件
  update_properties(properties)
  #起实就是去拼启动命令去了......
  param_list = generate_child_process_param_list(ambari_user, java_exe, class_path, debug_start, suspend_mode)

  #这是server_process_main()的内部方法哈
    # The launched shell process and sub-processes should have a group id that
  # is different from the parent.
  def make_process_independent():
    if IS_FOREGROUND: # upstart script is not able to track process from different pgid.
      return
    
    processId = os.getpid()
    if processId > 0:
      try:
        os.setpgid(processId, processId)
      except OSError, e:
        print_warning_msg('setpgid({0}, {0}) failed - {1}'.format(pidJava, str(e)))
        pass

  print_info_msg("Running server: " + str(param_list))
  
  #通过param_list去启动ambari-server java 进程
  procJava = subprocess32.Popen(param_list, env=environ, preexec_fn=make_process_independent)
  #获取进程pid
  pidJava = procJava.pid
  if pidJava <= 0:
    procJava.terminate()
    exitcode = procJava.returncode
    exitfile = os.path.join(configDefaults.PID_DIR, EXITCODE_NAME)
    save_pid(exitcode, exitfile)

    if scmStatus is not None:
      scmStatus.reportStopPending()

    raise FatalException(-1, AMBARI_SERVER_DIE_MSG.format(exitcode, configDefaults.SERVER_OUT_FILE))
  else:
    pidfile = os.path.join(configDefaults.PID_DIR, PID_NAME)

    print "Server PID at: "+pidfile
    print "Server out at: "+configDefaults.SERVER_OUT_FILE
    print "Server log at: "+configDefaults.SERVER_LOG_FILE

    wait_for_server_start(pidfile, scmStatus)

  if scmStatus is not None:
    scmStatus.reportStarted()
    
  if IS_FOREGROUND:
    procJava.communicate()

  return procJava

The main code for the generate_child_process_param_list method, the startup command looks something like the following SERVER_START_CMD

Org. Apache. Ambari. Server. Controller. AmbariServer ambari – server engineering of the main entrance

SERVER_START_CMD = "{0} " \ "-server -XX:NewRatio=3 " \ "-XX:+UseConcMarkSweepGC " + \ "-XX:-UseGCOverheadLimit -XX:CMSInitiatingOccupancyFraction=60 " \ "-XX:+CMSClassUnloadingEnabled " \ "-Dsun.zip.disableMemoryMapping=true " + \ "{1} {2} " \ "-cp {3} "\ "org.apache.ambari.server.controller.AmbariServer " \ "> {4} 2>&1 || echo $? > {5}" SERVER_START_CMD_DEBUG = "{0} " \ "-server -XX:NewRatio=2 " \ "-XX:+UseConcMarkSweepGC " + \ "{1} {2} " \ " -Xdebug -Xrunjdwp:transport=dt_socket,address=5005," \ "server=y,suspend={6} " \ "-cp {3} " + \ "org.apache.ambari.server.controller.AmbariServer " \ "> {4} 2>&1 || echo $? > {5}" def generate_child_process_param_list(ambari_user, java_exe, class_path, debug_start, suspend_mode): from ambari_commons.os_linux import ULIMIT_CMD properties = get_ambari_properties() command_base = SERVER_START_CMD_DEBUG if debug_start else SERVER_START_CMD ulimit_cmd = "%s %s" % (ULIMIT_CMD, str(get_ulimit_open_files(properties))) command = command_base.format(java_exe, ambari_provider_module_option, jvm_args, class_path, configDefaults.SERVER_OUT_FILE, os.path.join(configDefaults.PID_DIR, EXITCODE_NAME), suspend_mode) # required to start properly server instance os.chdir(configDefaults.ROOT_FS_PATH) #For properly daemonization server should be started using shell as parent param_list = [locate_file('sh', '/bin'), "-c"] if is_root() and ambari_user ! = "root": # To inherit exported environment variables (especially AMBARI_PASSPHRASE), # from subprocess32, we have to skip --login option of su command. That's why # we change dir to / (otherwise subprocess32 can face with 'permission denied' # errors while trying to list current directory cmd = "{ulimit_cmd} ; {su} {ambari_user} -s {sh_shell} -c '. {ambari_env_file} && {command}'".format(ulimit_cmd=ulimit_cmd, su=locate_file('su', '/bin'), ambari_user=ambari_user, sh_shell=locate_file('sh', '/bin'), command=command, ambari_env_file=AMBARI_ENV_FILE) else: cmd = "{ulimit_cmd} ; {command}".format(ulimit_cmd=ulimit_cmd, command=command) param_list.append(cmd) return param_list