util/startup.lua
changeset 13465 c673ff1075bd
parent 13463 790f60c0843b
child 13466 720aed1f5cf2
equal deleted inserted replaced
13464:a688947fab1e 13465:c673ff1075bd
   529 		end
   529 		end
   530 	end
   530 	end
   531 	config.set("*", "log", { { levels = { min = log_level or "info" }, to = "console" } });
   531 	config.set("*", "log", { { levels = { min = log_level or "info" }, to = "console" } });
   532 end
   532 end
   533 
   533 
       
   534 local function check_posix()
       
   535 	if prosody.platform ~= "posix" then return end
       
   536 
       
   537 	local want_pposix_version = "0.4.0";
       
   538 	local have_pposix, pposix = pcall(require, "prosody.util.pposix");
       
   539 
       
   540 	if pposix._VERSION ~= want_pposix_version then
       
   541 		print(string.format("Unknown version (%s) of binary pposix module, expected %s",
       
   542 			tostring(pposix._VERSION), want_pposix_version));
       
   543 		os.exit(1);
       
   544 	end
       
   545 	if have_pposix and pposix then
       
   546 		return pposix;
       
   547 	end
       
   548 end
       
   549 
   534 function startup.switch_user()
   550 function startup.switch_user()
   535 	-- Switch away from root and into the prosody user --
   551 	-- Switch away from root and into the prosody user --
   536 	-- NOTE: This function is only used by prosodyctl.
   552 	-- NOTE: This function is only used by prosodyctl.
   537 	-- The prosody process is built with the assumption that
   553 	-- The prosody process is built with the assumption that
   538 	-- it is already started as the appropriate user.
   554 	-- it is already started as the appropriate user.
   539 
   555 
   540 	local want_pposix_version = "0.4.0";
   556 	local pposix = check_posix()
   541 	local have_pposix, pposix = pcall(require, "prosody.util.pposix");
   557 	if pposix then
   542 
       
   543 	if have_pposix and pposix then
       
   544 		if pposix._VERSION ~= want_pposix_version then
       
   545 			print(string.format("Unknown version (%s) of binary pposix module, expected %s",
       
   546 				tostring(pposix._VERSION), want_pposix_version));
       
   547 			os.exit(1);
       
   548 		end
       
   549 		prosody.current_uid = pposix.getuid();
   558 		prosody.current_uid = pposix.getuid();
   550 		local arg_root = prosody.opts.root;
   559 		local arg_root = prosody.opts.root;
   551 		if prosody.current_uid == 0 and config.get("*", "run_as_root") ~= true and not arg_root then
   560 		if prosody.current_uid == 0 and config.get("*", "run_as_root") ~= true and not arg_root then
   552 			-- We haz root!
   561 			-- We haz root!
   553 			local desired_user = config.get("*", "prosody_user") or "prosody";
   562 			local desired_user = config.get("*", "prosody_user") or "prosody";
   669 	for hostname in pairs(config.getconfig()) do
   678 	for hostname in pairs(config.getconfig()) do
   670 		prosody.hosts[hostname] = startup.make_host(hostname);
   679 		prosody.hosts[hostname] = startup.make_host(hostname);
   671 	end
   680 	end
   672 end
   681 end
   673 
   682 
       
   683 function startup.posix_umask()
       
   684 	if prosody.platform ~= "posix" then return end
       
   685 	local pposix = require "prosody.util.pposix";
       
   686 	local umask = config.get("*", "umask") or "027";
       
   687 	pposix.umask(umask);
       
   688 end
       
   689 
       
   690 function startup.check_user()
       
   691 	local pposix = check_posix();
       
   692 	if not pposix then return end
       
   693 	-- Don't even think about it!
       
   694 	if pposix.getuid() == 0 and not config.get("*", "run_as_root") then
       
   695 		log("error", "Danger, Will Robinson! Prosody doesn't need to be run as root, so don't do it!");
       
   696 		log("error", "For more information on running Prosody as root, see https://prosody.im/doc/root");
       
   697 		prosody.shutdown("Refusing to run as root", 1);
       
   698 	end
       
   699 end
       
   700 
       
   701 local function remove_pidfile()
       
   702 	local pidfile = prosody.pidfile;
       
   703 	if prosody.pidfile_handle then
       
   704 		prosody.pidfile_handle:close();
       
   705 		os.remove(pidfile);
       
   706 		prosody.pidfile, prosody.pidfile_handle = nil, nil;
       
   707 	end
       
   708 end
       
   709 
       
   710 function startup.write_pidfile()
       
   711 	local pposix = check_posix();
       
   712 	if not pposix then return end
       
   713 	local lfs = require "lfs";
       
   714 	local stat = lfs.attributes;
       
   715 	local pidfile = config.get("*", "pidfile") or nil;
       
   716 	if not pidfile then return end
       
   717 	pidfile = config.resolve_relative_path(prosody.paths.data, pidfile);
       
   718 	local mode = stat(pidfile) and "r+" or "w+";
       
   719 	local pidfile_handle, err = io.open(pidfile, mode);
       
   720 	if not pidfile_handle then
       
   721 		log("error", "Couldn't write pidfile at %s; %s", pidfile, err);
       
   722 		prosody.shutdown("Couldn't write pidfile", 1);
       
   723 	else
       
   724 		prosody.pidfile = pidfile;
       
   725 		if not lfs.lock(pidfile_handle, "w") then -- Exclusive lock
       
   726 			local other_pid = pidfile_handle:read("*a");
       
   727 			log("error", "Another Prosody instance seems to be running with PID %s, quitting", other_pid);
       
   728 			prosody.pidfile_handle = nil;
       
   729 			prosody.shutdown("Prosody already running", 1);
       
   730 		else
       
   731 			pidfile_handle:close();
       
   732 			pidfile_handle, err = io.open(pidfile, "w+");
       
   733 			if not pidfile_handle then
       
   734 				log("error", "Couldn't write pidfile at %s; %s", pidfile, err);
       
   735 				prosody.shutdown("Couldn't write pidfile", 1);
       
   736 			else
       
   737 				if lfs.lock(pidfile_handle, "w") then
       
   738 					pidfile_handle:write(tostring(pposix.getpid()));
       
   739 					pidfile_handle:flush();
       
   740 					prosody.pidfile_handle = pidfile_handle;
       
   741 				end
       
   742 			end
       
   743 		end
       
   744 	end
       
   745 	prosody.events.add_handler("server-stopped", remove_pidfile);
       
   746 end
       
   747 
       
   748 local function remove_log_sinks()
       
   749 	local lm = require "prosody.core.loggingmanager";
       
   750 	lm.register_sink_type("console", nil);
       
   751 	lm.register_sink_type("stdout", nil);
       
   752 	lm.reload_logging();
       
   753 end
       
   754 
       
   755 function startup.posix_daemonize()
       
   756 	if not prosody.opts.daemonize then return end
       
   757 	local pposix = check_posix();
       
   758 	log("info", "Prosody is about to detach from the console, disabling further console output");
       
   759 	remove_log_sinks();
       
   760 	local ok, ret = pposix.daemonize();
       
   761 	if not ok then
       
   762 		log("error", "Failed to daemonize: %s", ret);
       
   763 	elseif ret and ret > 0 then
       
   764 		os.exit(0);
       
   765 	else
       
   766 		log("info", "Successfully daemonized to PID %d", pposix.getpid());
       
   767 	end
       
   768 end
       
   769 
   674 function startup.hook_posix_signals()
   770 function startup.hook_posix_signals()
   675 	if prosody.platform ~= "posix" then return end
   771 	if prosody.platform ~= "posix" then return end
   676 	local have_signal, signal = pcall(require, "prosody.util.signal");
   772 	local have_signal, signal = pcall(require, "prosody.util.signal");
   677 	if not have_signal then
   773 	if not have_signal then
   678 		log("warn", "Couldn't load signal library, won't respond to SIGTERM");
   774 		log("warn", "Couldn't load signal library, won't respond to SIGTERM");
   763 
   859 
   764 function startup.prosody()
   860 function startup.prosody()
   765 	-- These actions are in a strict order, as many depend on
   861 	-- These actions are in a strict order, as many depend on
   766 	-- previous steps to have already been performed
   862 	-- previous steps to have already been performed
   767 	prosody.process_type = "prosody";
   863 	prosody.process_type = "prosody";
       
   864 	startup.check_user();
   768 	startup.parse_args();
   865 	startup.parse_args();
   769 	startup.init_global_state();
   866 	startup.init_global_state();
   770 	startup.read_config();
   867 	startup.read_config();
   771 	startup.init_logging();
   868 	startup.init_logging();
   772 	startup.init_gc();
   869 	startup.init_gc();
   788 	startup.init_promise();
   885 	startup.init_promise();
   789 	startup.init_async();
   886 	startup.init_async();
   790 	startup.init_http_client();
   887 	startup.init_http_client();
   791 	startup.init_data_store();
   888 	startup.init_data_store();
   792 	startup.init_global_protection();
   889 	startup.init_global_protection();
       
   890 	startup.posix_daemonize();
       
   891 	startup.write_pidfile();
   793 	startup.hook_posix_signals();
   892 	startup.hook_posix_signals();
   794 	startup.prepare_to_start();
   893 	startup.prepare_to_start();
   795 	startup.notify_started();
   894 	startup.notify_started();
   796 end
   895 end
   797 
   896