mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-15 03:53:41 +00:00
397 lines
11 KiB
Bash
Executable File
397 lines
11 KiB
Bash
Executable File
#!/bin/sh
|
|
### BEGIN INIT INFO
|
|
# Provides: clickhouse-server
|
|
# Default-Start: 2 3 4 5
|
|
# Default-Stop: 0 1 6
|
|
# Required-Start: $network
|
|
# Required-Stop: $network
|
|
# Short-Description: Yandex clickhouse-server daemon
|
|
### END INIT INFO
|
|
|
|
CLICKHOUSE_USER=clickhouse
|
|
CLICKHOUSE_GROUP=${CLICKHOUSE_USER}
|
|
SHELL=/bin/bash
|
|
PROGRAM=clickhouse-server
|
|
CLICKHOUSE_GENERIC_PROGRAM=clickhouse
|
|
CLICKHOUSE_PROGRAM_ENV=""
|
|
EXTRACT_FROM_CONFIG=${CLICKHOUSE_GENERIC_PROGRAM}-extract-from-config
|
|
CLICKHOUSE_CONFDIR=/etc/$PROGRAM
|
|
CLICKHOUSE_LOGDIR=/var/log/clickhouse-server
|
|
CLICKHOUSE_LOGDIR_USER=root
|
|
CLICKHOUSE_DATADIR=/var/lib/clickhouse
|
|
if [ -d "/var/lock" ]; then
|
|
LOCALSTATEDIR=/var/lock
|
|
else
|
|
LOCALSTATEDIR=/run/lock
|
|
fi
|
|
|
|
if [ ! -d "$LOCALSTATEDIR" ]; then
|
|
mkdir -p "$LOCALSTATEDIR"
|
|
fi
|
|
|
|
CLICKHOUSE_BINDIR=/usr/bin
|
|
CLICKHOUSE_CRONFILE=/etc/cron.d/clickhouse-server
|
|
CLICKHOUSE_CONFIG=$CLICKHOUSE_CONFDIR/config.xml
|
|
LOCKFILE=$LOCALSTATEDIR/$PROGRAM
|
|
CLICKHOUSE_PIDDIR=/var/run/$PROGRAM
|
|
CLICKHOUSE_PIDFILE="$CLICKHOUSE_PIDDIR/$PROGRAM.pid"
|
|
# CLICKHOUSE_STOP_TIMEOUT=60 # Disabled by default. Place to /etc/default/clickhouse if you need.
|
|
|
|
# Some systems lack "flock"
|
|
command -v flock >/dev/null && FLOCK=flock
|
|
|
|
# Override defaults from optional config file
|
|
test -f /etc/default/clickhouse && . /etc/default/clickhouse
|
|
|
|
# On x86_64, check for required instruction set.
|
|
if uname -mpi | grep -q 'x86_64'; then
|
|
if ! grep -q 'sse4_2' /proc/cpuinfo; then
|
|
# On KVM, cpuinfo could falsely not report SSE 4.2 support, so skip the check.
|
|
if ! grep -q 'Common KVM processor' /proc/cpuinfo; then
|
|
|
|
# Some other VMs also report wrong flags in cpuinfo.
|
|
# Tricky way to test for instruction set:
|
|
# create temporary binary and run it;
|
|
# if it get caught illegal instruction signal,
|
|
# then required instruction set is not supported really.
|
|
#
|
|
# Generated this way:
|
|
# gcc -xc -Os -static -nostdlib - <<< 'void _start() { __asm__("pcmpgtq %%xmm0, %%xmm1; mov $0x3c, %%rax; xor %%rdi, %%rdi; syscall":::"memory"); }' && strip -R .note.gnu.build-id -R .comment -R .eh_frame -s ./a.out && gzip -c -9 ./a.out | base64 -w0; echo
|
|
|
|
if ! (echo -n 'H4sICAwAW1cCA2Eub3V0AKt39XFjYmRkgAEmBjsGEI+H0QHMd4CKGyCUAMUsGJiBJDNQNUiYlQEZOKDQclB9cnD9CmCSBYqJBRxQOvBpSQobGfqIAWn8FuYnPI4fsAGyPQz/87MeZtArziguKSpJTGLQK0mtKGGgGHADMSgoYH6AhTMPNHyE0NQzYuEzYzEXFr6CBPQDANAsXKTwAQAA' | base64 -d | gzip -d > /tmp/clickhouse_test_sse42 && chmod a+x /tmp/clickhouse_test_sse42 && /tmp/clickhouse_test_sse42); then
|
|
echo 'Warning! SSE 4.2 instruction set is not supported'
|
|
#exit 3
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
|
|
SUPPORTED_COMMANDS="{start|stop|status|restart|forcestop|forcerestart|reload|condstart|condstop|condrestart|condreload|initdb}"
|
|
is_supported_command()
|
|
{
|
|
echo "$SUPPORTED_COMMANDS" | grep -E "(\{|\|)$1(\||})" &> /dev/null
|
|
}
|
|
|
|
|
|
is_running()
|
|
{
|
|
[ -r "$CLICKHOUSE_PIDFILE" ] && pgrep -s $(cat "$CLICKHOUSE_PIDFILE") 1> /dev/null 2> /dev/null
|
|
}
|
|
|
|
|
|
wait_for_done()
|
|
{
|
|
timeout=$1
|
|
attempts=0
|
|
while is_running; do
|
|
attempts=$(($attempts + 1))
|
|
if [ -n "$timeout" ] && [ $attempts -gt $timeout ]; then
|
|
return 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
}
|
|
|
|
|
|
die()
|
|
{
|
|
echo $1 >&2
|
|
exit 1
|
|
}
|
|
|
|
|
|
# Check that configuration file is Ok.
|
|
check_config()
|
|
{
|
|
if [ -x "$CLICKHOUSE_BINDIR/$EXTRACT_FROM_CONFIG" ]; then
|
|
su -s $SHELL ${CLICKHOUSE_USER} -c "$CLICKHOUSE_BINDIR/$EXTRACT_FROM_CONFIG --config-file=\"$CLICKHOUSE_CONFIG\" --key=path" >/dev/null || die "Configuration file ${CLICKHOUSE_CONFIG} doesn't parse successfully. Won't restart server. You may use forcerestart if you are sure.";
|
|
fi
|
|
}
|
|
|
|
|
|
initdb()
|
|
{
|
|
if [ -x "$CLICKHOUSE_BINDIR/$EXTRACT_FROM_CONFIG" ]; then
|
|
CLICKHOUSE_DATADIR_FROM_CONFIG=$(su -s $SHELL ${CLICKHOUSE_USER} -c "$CLICKHOUSE_BINDIR/$EXTRACT_FROM_CONFIG --config-file=\"$CLICKHOUSE_CONFIG\" --key=path")
|
|
if [ "(" "$?" -ne "0" ")" -o "(" -z "${CLICKHOUSE_DATADIR_FROM_CONFIG}" ")" ]; then
|
|
die "Cannot obtain value of path from config file: ${CLICKHOUSE_CONFIG}";
|
|
fi
|
|
echo "Path to data directory in ${CLICKHOUSE_CONFIG}: ${CLICKHOUSE_DATADIR_FROM_CONFIG}"
|
|
else
|
|
CLICKHOUSE_DATADIR_FROM_CONFIG=$CLICKHOUSE_DATADIR
|
|
fi
|
|
|
|
if ! getent group ${CLICKHOUSE_USER} >/dev/null; then
|
|
echo "Can't chown to non-existing user ${CLICKHOUSE_USER}"
|
|
return
|
|
fi
|
|
if ! getent passwd ${CLICKHOUSE_GROUP} >/dev/null; then
|
|
echo "Can't chown to non-existing group ${CLICKHOUSE_GROUP}"
|
|
return
|
|
fi
|
|
|
|
if ! $(su -s $SHELL ${CLICKHOUSE_USER} -c "test -r ${CLICKHOUSE_CONFIG}"); then
|
|
echo "Warning! clickhouse config [${CLICKHOUSE_CONFIG}] not readable by user [${CLICKHOUSE_USER}]"
|
|
fi
|
|
|
|
if ! $(su -s $SHELL ${CLICKHOUSE_USER} -c "test -O \"${CLICKHOUSE_DATADIR_FROM_CONFIG}\" && test -G \"${CLICKHOUSE_DATADIR_FROM_CONFIG}\""); then
|
|
if [ $(dirname "${CLICKHOUSE_DATADIR_FROM_CONFIG}") = "/" ]; then
|
|
echo "Directory ${CLICKHOUSE_DATADIR_FROM_CONFIG} seems too dangerous to chown."
|
|
else
|
|
if [ ! -e "${CLICKHOUSE_DATADIR_FROM_CONFIG}" ]; then
|
|
echo "Creating directory ${CLICKHOUSE_DATADIR_FROM_CONFIG}"
|
|
mkdir -p "${CLICKHOUSE_DATADIR_FROM_CONFIG}"
|
|
fi
|
|
|
|
echo "Changing owner of [${CLICKHOUSE_DATADIR_FROM_CONFIG}] to [${CLICKHOUSE_USER}:${CLICKHOUSE_GROUP}]"
|
|
chown -R ${CLICKHOUSE_USER}:${CLICKHOUSE_GROUP} "${CLICKHOUSE_DATADIR_FROM_CONFIG}"
|
|
fi
|
|
fi
|
|
|
|
if ! $(su -s $SHELL ${CLICKHOUSE_USER} -c "test -w ${CLICKHOUSE_LOGDIR}"); then
|
|
echo "Changing owner of [${CLICKHOUSE_LOGDIR}/*] to [${CLICKHOUSE_USER}:${CLICKHOUSE_GROUP}]"
|
|
chown -R ${CLICKHOUSE_USER}:${CLICKHOUSE_GROUP} ${CLICKHOUSE_LOGDIR}/*
|
|
echo "Changing owner of [${CLICKHOUSE_LOGDIR}] to [${CLICKHOUSE_LOGDIR_USER}:${CLICKHOUSE_GROUP}]"
|
|
chown ${CLICKHOUSE_LOGDIR_USER}:${CLICKHOUSE_GROUP} ${CLICKHOUSE_LOGDIR}
|
|
fi
|
|
}
|
|
|
|
|
|
start()
|
|
{
|
|
[ -x $CLICKHOUSE_BINDIR/$PROGRAM ] || exit 0
|
|
local EXIT_STATUS
|
|
EXIT_STATUS=0
|
|
|
|
echo -n "Start $PROGRAM service: "
|
|
|
|
if is_running; then
|
|
echo -n "already running "
|
|
EXIT_STATUS=1
|
|
else
|
|
ulimit -n 262144
|
|
mkdir -p $CLICKHOUSE_PIDDIR
|
|
chown -R $CLICKHOUSE_USER:$CLICKHOUSE_GROUP $CLICKHOUSE_PIDDIR
|
|
initdb
|
|
if ! is_running; then
|
|
# Lock should not be held while running child process, so we release the lock. Note: obviously, there is race condition.
|
|
# But clickhouse-server has protection from simultaneous runs with same data directory.
|
|
su -s $SHELL ${CLICKHOUSE_USER} -c "$FLOCK -u 9; $CLICKHOUSE_PROGRAM_ENV exec -a \"$PROGRAM\" \"$CLICKHOUSE_BINDIR/$PROGRAM\" --daemon --pid-file=\"$CLICKHOUSE_PIDFILE\" --config-file=\"$CLICKHOUSE_CONFIG\""
|
|
EXIT_STATUS=$?
|
|
if [ $EXIT_STATUS -ne 0 ]; then
|
|
return $EXIT_STATUS
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ $EXIT_STATUS -eq 0 ]; then
|
|
attempts=0
|
|
while ! is_running && [ $attempts -le ${CLICKHOUSE_START_TIMEOUT:=10} ]; do
|
|
attempts=$(($attempts + 1))
|
|
sleep 1
|
|
done
|
|
if is_running; then
|
|
echo "DONE"
|
|
else
|
|
echo "UNKNOWN"
|
|
fi
|
|
else
|
|
echo "FAILED"
|
|
fi
|
|
|
|
return $EXIT_STATUS
|
|
}
|
|
|
|
|
|
stop()
|
|
{
|
|
#local EXIT_STATUS
|
|
EXIT_STATUS=0
|
|
|
|
if [ -f $CLICKHOUSE_PIDFILE ]; then
|
|
|
|
echo -n "Stop $PROGRAM service: "
|
|
|
|
kill -TERM $(cat "$CLICKHOUSE_PIDFILE")
|
|
|
|
if ! wait_for_done ${CLICKHOUSE_STOP_TIMEOUT}; then
|
|
EXIT_STATUS=2
|
|
echo "TIMEOUT"
|
|
else
|
|
echo "DONE"
|
|
fi
|
|
|
|
fi
|
|
return $EXIT_STATUS
|
|
}
|
|
|
|
|
|
restart()
|
|
{
|
|
check_config
|
|
if stop; then
|
|
if start; then
|
|
return 0
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
|
|
forcestop()
|
|
{
|
|
local EXIT_STATUS
|
|
EXIT_STATUS=0
|
|
|
|
echo -n "Stop forcefully $PROGRAM service: "
|
|
|
|
kill -KILL $(cat "$CLICKHOUSE_PIDFILE")
|
|
|
|
wait_for_done
|
|
|
|
echo "DONE"
|
|
return $EXIT_STATUS
|
|
}
|
|
|
|
|
|
service_or_func()
|
|
{
|
|
if [ -x "/bin/systemctl" ] && [ -f /etc/systemd/system/clickhouse-server.service ] && [ -d /run/systemd/system ]; then
|
|
service $PROGRAM $1
|
|
else
|
|
$1
|
|
fi
|
|
}
|
|
|
|
forcerestart()
|
|
{
|
|
forcestop
|
|
# Should not use 'start' function if systemd active
|
|
service_or_func start
|
|
}
|
|
|
|
use_cron()
|
|
{
|
|
# 1. running systemd
|
|
if [ -x "/bin/systemctl" ] && [ -f /etc/systemd/system/clickhouse-server.service ] && [ -d /run/systemd/system ]; then
|
|
return 1
|
|
fi
|
|
# 2. disabled by config
|
|
if [ -z "$CLICKHOUSE_CRONFILE" ]; then
|
|
return 2
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
enable_cron()
|
|
{
|
|
use_cron && sed -i 's/^#*//' "$CLICKHOUSE_CRONFILE"
|
|
}
|
|
|
|
|
|
disable_cron()
|
|
{
|
|
use_cron && sed -i 's/^#*/#/' "$CLICKHOUSE_CRONFILE"
|
|
}
|
|
|
|
|
|
is_cron_disabled()
|
|
{
|
|
use_cron || return 0
|
|
|
|
# Assumes that either no lines are commented or all lines are commented.
|
|
# Also please note, that currently cron file for ClickHouse has only one line (but some time ago there was more).
|
|
grep -q -E '^#' "$CLICKHOUSE_CRONFILE";
|
|
}
|
|
|
|
|
|
main()
|
|
{
|
|
# See how we were called.
|
|
EXIT_STATUS=0
|
|
case "$1" in
|
|
start)
|
|
start && enable_cron
|
|
;;
|
|
stop)
|
|
# disable_cron returns false if cron disabled (with systemd) - not checking return status
|
|
disable_cron
|
|
stop
|
|
;;
|
|
restart)
|
|
restart && enable_cron
|
|
;;
|
|
forcestop)
|
|
disable_cron
|
|
forcestop
|
|
;;
|
|
forcerestart)
|
|
forcerestart && enable_cron
|
|
;;
|
|
reload)
|
|
restart
|
|
;;
|
|
condstart)
|
|
is_running || service_or_func start
|
|
;;
|
|
condstop)
|
|
is_running && service_or_func stop
|
|
;;
|
|
condrestart)
|
|
is_running && service_or_func restart
|
|
;;
|
|
condreload)
|
|
is_running && service_or_func restart
|
|
;;
|
|
initdb)
|
|
initdb
|
|
;;
|
|
enable_cron)
|
|
enable_cron
|
|
;;
|
|
disable_cron)
|
|
disable_cron
|
|
;;
|
|
*)
|
|
echo "Usage: $0 $SUPPORTED_COMMANDS"
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
exit $EXIT_STATUS
|
|
}
|
|
|
|
|
|
status()
|
|
{
|
|
if is_running; then
|
|
echo "$PROGRAM service is running"
|
|
exit 0
|
|
else
|
|
if is_cron_disabled; then
|
|
echo "$PROGRAM service is stopped";
|
|
else
|
|
echo "$PROGRAM: process unexpectedly terminated"
|
|
fi
|
|
exit 3
|
|
fi
|
|
}
|
|
|
|
|
|
# Running commands without need of locking
|
|
case "$1" in
|
|
status)
|
|
status
|
|
;;
|
|
esac
|
|
|
|
|
|
(
|
|
if $FLOCK -n 9; then
|
|
main "$@"
|
|
else
|
|
echo "Init script is already running" && exit 1
|
|
fi
|
|
) 9> $LOCKFILE
|