在linux下我们启动ambari-server的时候只需要执行命令ambari-server start
,
那么我们就从这个命令开始分析一下这个启动过程都干了啥
$ 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.
当我们执行完这个命令后,脚本在/etc/init.d/ambari-server,这个脚本定义了ambari-server的start/stop/restart/status....
在源码中这个文件在ambari-server工程目录下的sbin/ambari-server
Ambari-server安装后在liunx上其实是个软链接
[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-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" "$@"
;;
...
从文件中我们可以看出ambari-server start,其实执行的是/usr/sbin/ambari-server.py start
ambari-server.py
# ambari-server.py
@OsFamilyFuncImpl(OsFamilyImpl.DEFAULT)
def start(args):
logger.info("Starting ambari-server.")
status, pid = is_server_runing() #先检查ambari-server是否已经在running
if status:
err = "Ambari Server is already running."
raise FatalException(1, err)
server_process_main(args) #这个里边儿才真正开始处理起动过程
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
generate_child_process_param_list方法主要代码,启动命令大概就是下面SERVER_START_CMD这个样子
org.apache.ambari.server.controller.AmbariServer是ambari-server工程的入口main
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