Add --reload command-line parameter.

Refs #5788
This commit is contained in:
Gerd von Egidy 2014-04-14 00:16:48 +02:00 committed by Gunnar Beutner
parent 19afcd894a
commit 33bd909b71
4 changed files with 111 additions and 15 deletions

View File

@ -61,11 +61,13 @@ start() {
chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $ICINGA2_STATE_DIR/run/icinga2/cmd
chmod 2755 $ICINGA2_STATE_DIR/run/icinga2/cmd
echo "Starting Icinga 2: "
$DAEMON -c $ICINGA2_CONFIG_FILE -d -e $ICINGA2_ERROR_LOG -u $ICINGA2_USER -g $ICINGA2_GROUP
echo "Done"
echo
echo "Starting Icinga 2: "
if ! $DAEMON -c $ICINGA2_CONFIG_FILE -d -e $ICINGA2_ERROR_LOG -u $ICINGA2_USER -g $ICINGA2_GROUP; then
echo "Error starting Icinga."
exit 1
else
echo "Done"
fi
}
# Restart Icinga 2
@ -104,15 +106,9 @@ stop() {
# Reload Icinga 2
reload() {
printf "Reloading Icinga 2: "
if [ ! -e $ICINGA2_PID_FILE ]; then
echo "The PID file '$ICINGA2_PID_FILE' does not exist."
if ! $DAEMON -c $ICINGA2_CONFIG_FILE -d --reload -e $ICINGA2_ERROR_LOG -u $ICINGA2_USER -g $ICINGA2_GROUP; then
echo "Error reloading Icinga."
exit 1
fi
pid=`cat $ICINGA2_PID_FILE`
if ! kill -HUP $pid >/dev/null 2>&1; then
echo "Failed - Icinga 2 is not running."
else
echo "Done"
fi
@ -162,7 +158,6 @@ case "$1" in
start
;;
reload)
checkconfig reload fail
reload
;;
checkconfig)

View File

@ -187,6 +187,34 @@ static bool Daemonize(const String& stderrFile)
return true;
}
/**
* Terminate another process and wait till it has ended
*
* @params target PID of the process to end
*/
static void TerminateAndWaitForEnd(pid_t target)
{
#ifndef _WIN32
// allow 15 seconds timeout
double timeout = Utility::GetTime() + 15;
int ret = kill(target, SIGTERM);
while(Utility::GetTime() < timeout && (ret==0 || errno!=ESRCH))
{
Utility::Sleep(0.1);
ret = kill(target, 0);
}
// timeout and the process still seems to live: kill it
if (ret == 0 || errno != ESRCH)
kill(target, SIGKILL);
#else
// TODO: implement this for Win32
#endif /* _WIN32 */
}
int Main(void)
{
int argc = Application::GetArgC();
@ -252,6 +280,7 @@ int Main(void)
("validate,C", "exit after validating the configuration")
("debug,x", "enable debugging")
("errorlog,e", po::value<std::string>(), "log fatal errors to the specified log file (only works in combination with --daemonize)")
("reload,r", "reload a running icinga instance")
#ifndef _WIN32
("daemonize,d", "detach from the controlling terminal")
("user,u", po::value<std::string>(), "user to run Icinga as")
@ -405,6 +434,17 @@ int Main(void)
return EXIT_FAILURE;
}
pid_t runningpid = Application::ReadPidFile(Application::GetPidPath());
if (g_AppParams.count("reload")) {
if (runningpid < 0) {
Log(LogCritical, "icinga-app", "No instance of Icinga currently running: can't reload.");
return EXIT_FAILURE;
}
} else if (!g_AppParams.count("validate") && runningpid >= 0) {
Log(LogCritical, "icinga-app", "Another instance of Icinga already running at PID " + Convert::ToString(runningpid));
return EXIT_FAILURE;
}
if (!LoadConfigFiles(appType))
return EXIT_FAILURE;
@ -413,6 +453,12 @@ int Main(void)
return EXIT_SUCCESS;
}
if (g_AppParams.count("reload")) {
Log(LogInformation, "icinga-app", "Terminating previous instance of icinga (PID " + Convert::ToString(runningpid) + ")");
TerminateAndWaitForEnd(runningpid);
Log(LogInformation, "icinga-app", "Previous instance has ended, taking over now.");
}
if (g_AppParams.count("daemonize")) {
String errorLog;

View File

@ -638,7 +638,7 @@ void Application::UpdatePidFile(const String& filename)
}
#endif /* _WIN32 */
fprintf(m_PidFile, "%d", Utility::GetPid());
fprintf(m_PidFile, "%d\n", Utility::GetPid());
fflush(m_PidFile);
}
@ -656,6 +656,60 @@ void Application::ClosePidFile(void)
m_PidFile = NULL;
}
/**
* Checks if another process currently owns the pidfile and read it
*
* @param filename The name of the PID file.
* @returns -1: no process owning the pidfile, pid of the process otherwise
*/
pid_t Application::ReadPidFile(const String& filename)
{
FILE *pidfile = fopen(filename.CStr(), "r");
if (pidfile == NULL)
return -1;
#ifndef _WIN32
int fd = fileno(pidfile);
struct flock lock;
lock.l_start = 0;
lock.l_len = 0;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
if (fcntl(fd, F_GETLK, &lock) < 0) {
int error = errno;
fclose(pidfile);
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("fcntl")
<< boost::errinfo_errno(error));
}
if (lock.l_type == F_UNLCK) {
// nobody has locked the file: no icinga running
fclose(pidfile);
return -1;
}
#endif /* _WIN32 */
pid_t runningpid;
int res = fscanf(pidfile, "%d", &runningpid);
fclose(pidfile);
// bogus result?
if (res != 1)
return -1;
#ifdef _WIN32
// TODO: add check if the read pid is still running or not
#endif /* _WIN32 */
return runningpid;
}
/**
* Retrieves the path of the installation prefix.
*

View File

@ -69,6 +69,7 @@ public:
void UpdatePidFile(const String& filename);
void ClosePidFile(void);
static pid_t ReadPidFile(const String& filename);
static String GetExePath(const String& argv0);