Commit 983cf57d authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[3939] keactrl now uses PID files to control servers

src/bin/keactrl/keactrl.in
    - get_pid_from_file() - new function which returns a server's PID from its
    pid file, or 0

    - check_running() - modified to use get_pid_from_file(), sets $_pid and $_pid_file
    globals

    - send_signal() - modified to use get_pid_from_file()

    - start_server() - modified log emitted if server is already running to
    contain the PID and pid file

    - stop_server() - new function to stop a given server, IF it is running.
    reload_server() - new function to reload a given server, IF it is running.

    - get_pids() - deleted

    - Replaced use of send_signal with stop_server or reload_server to provide
    better visual feedback to users.
~
parent cfeff322
#!/bin/sh
# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
......@@ -65,48 +65,75 @@ usage() {
}
### Functions managing Kea processes ###
# Contructs a server's PID file based on its binary name, the config file,
# and the --localstatedir and returns the contents as $_pid. If the file
# does not exist, the value of $_pid is 0. If the file exists but cannot
# be read the function exists with a error message. Note the PID file name
# is always returned in $_pid_file.
get_pid_from_file() {
local proc_name=${1} # Process name.
# Extract the name portion of the config file
local conf_name=$(basename ${kea_config_file} | cut -f1 -d'.')
# Default the directory to --localstatedir
local pid_file_dir=@localstatedir@/@PACKAGE@
# Use directory override if set (primarily for testing only)
if [ ! -z $KEA_PIDFILE_DIR ]; then
pid_file_dir=${KEA_PIDFILE_DIR}
fi
# Returns a list of existing PIDs and a number of PIDs for the process
# having a name specified as an argument to the function.
get_pids() {
local proc_name=${1} # Process name.
# Return the list of PIDs.
_get_pids=$(ps axwwo pid,command | grep ${proc_name} | grep -v grep \
| awk '{print $1}')
# Return the number of PIDs.
_get_pids_num=$(printf "%s" "${_get_pids}" | wc -w | awk '{print $1}')
# construct the PID file name
_pid_file="${pid_file_dir}/${conf_name}.${proc_name}.pid"
# Grab the PID if the file exists
if [ -e ${_pid_file} ]; then
_pid=`cat ${_pid_file}`
if [ $? -ne 0 ]; then
log_error "Error reading PID file: ${_pid_file}"
fi
else
# No file, means no pid
_pid=0;
fi
}
# Checks if the specified process is running. Internally it calls get_pids
# to get the number of processes.
# Checks if the specified process is running by reading its
# PID file and checking the PID it contains. If the file does
# not exist, the process is assumed to not be running.
check_running() {
local proc_name=${1} # Process name.
# Initially mark the process as not running.
_running=0
get_pids ${proc_name}
# If the number of pids is non-zero, the process is running.
if [ ${_get_pids_num} -gt 0 ]; then
_running=1
# Get the PID from the PID file (if it exists)
get_pid_from_file ${proc_name}
if [ ${_pid} -gt 0 ]; then
# Use kill -0 to check if PID is alive
kill -0 ${_pid}
if [ $? -eq 0 ]; then
# No error, so PID IS ALIVE
_running=1
fi
fi
}
# Sends a signal to a group of processes having a specified name.
# Sends a signal to a process based on its PID file
send_signal() {
local sig=${1} # Signal number
local proc_name=${2} # Process name.
# Get all PIDs for the specified process name.
get_pids ${proc_name}
# If no processes running, there is no process we can send the signal
# to. This is not neccessarily an error.
if [ -z ${_get_pids} ]; then
get_pid_from_file ${proc_name}
if [ ${_pid} -eq 0 ]; then
log_info "Skip sending signal ${sig} to process ${proc_name}: \
process is not running\n"
return
fi
# Send a signal to all processes.
kill -${sig} ${_get_pids} >/dev/null 2>&1
if [ $? -ne 0 ]; then
log_error "Failed to send signal ${sig} to process ${proc_name}.\n"
else
kill -${sig} ${_pid}
if [ $? -ne 0 ]; then
log_error "Failed to send signal ${sig} to process ${proc_name}, PID {$_pid}.\n"
fi
fi
}
......@@ -121,8 +148,8 @@ start_server() {
check_running ${binary_name}
# If process is running, don't start another one. Just log a message.
if [ ${_running} -ne 0 ]; then
log_info "Skip starting ${binary_name} \
as another instance is already running."
log_info "${binary_name} is already running as: \
PID ${_pid}, PID file: ${_pid_file}."
else
log_info "Starting ${binary_name} ${args}"
# Start the process.
......@@ -130,6 +157,50 @@ as another instance is already running."
fi
}
# Instruct Kea process to shutdown by sending it signal 15
stop_server() {
binary_path=${1} # Full path to the binary.
local sig=15
# Extract the name of the binary from the path.
local binary_name=$(basename ${binary_path})
# Use the binary name to check if the process is already running.
check_running ${binary_name}
# If process isn't running, don't start another one. Just log a message.
if [ ${_running} -eq 0 ]; then
log_info "${binary_name} isn't running."
else
log_info "Stopping ${binary_name}..."
kill -${sig} ${_pid}
if [ $? -ne 0 ]; then
log_error "Stop failed, could not send signal ${sig} \
to process ${proc_name}, PID ${_pid}.\n"
fi
fi
}
# Instruct Kea process to reload config by sending it signal 1
reload_server() {
binary_path=${1} # Full path to the binary.
local sig=1
# Extract the name of the binary from the path.
local binary_name=$(basename ${binary_path})
# Use the binary name to check if the process is already running.
check_running ${binary_name}
# If process isn't running, don't start another one. Just log a message.
if [ ${_running} -eq 0 ]; then
log_info "${binary_name} isn't running."
else
log_info "Reloading ${binary_name}..."
kill -${sig} ${_pid}
if [ $? -ne 0 ]; then
log_error "Reload failed, could not send signal ${sig} \
to process ${proc_name}, PID ${_pid}.\n"
fi
fi
}
# Run the specified command if the server has been enabled.
# In order for the command to run, the following conditions have to be met:
# - server must be on the list of servers (e.g. specified from command line)
......@@ -301,18 +372,18 @@ case ${command} in
# Stop running servers.
stop)
# Stop all servers or servers specified from the command line.
run_conditional "dhcp4" "send_signal 15 $(basename ${dhcp4_srv})" 0
run_conditional "dhcp6" "send_signal 15 $(basename ${dhcp6_srv})" 0
run_conditional "dhcp_ddns" "send_signal 15 $(basename ${dhcp_ddns_srv})" 0
run_conditional "dhcp4" "stop_server ${dhcp4_srv}" 0
run_conditional "dhcp6" "stop_server ${dhcp6_srv}" 0
run_conditional "dhcp_ddns" "stop_server ${dhcp_ddns_srv}" 0
exit 0 ;;
# Reconfigure the servers.
reload)
# Reconfigure all servers or servers specified from the command line.
run_conditional "dhcp4" "send_signal 1 $(basename ${dhcp4_srv})" 0
run_conditional "dhcp6" "send_signal 1 $(basename ${dhcp6_srv})" 0
run_conditional "dhcp_ddns" "send_signal 1 $(basename ${dhcp_ddns_srv})" 0
run_conditional "dhcp4" "reload_server ${dhcp4_srv}" 0
run_conditional "dhcp6" "reload_server ${dhcp6_srv}" 0
run_conditional "dhcp_ddns" "reload_server ${dhcp_ddns_srv}" 0
exit 0 ;;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment