From 4ec6e306a9bfb036e994acd447eb3a383d9ea746 Mon Sep 17 00:00:00 2001 From: vvaltman Date: Wed, 10 Sep 2014 00:47:34 +0400 Subject: [PATCH] Added scripts to help run telegram as daemon --- start-telegram-daemon | 206 ++++++++++++++++++++++++++ telegram-daemon | 332 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 538 insertions(+) create mode 100755 start-telegram-daemon create mode 100755 telegram-daemon diff --git a/start-telegram-daemon b/start-telegram-daemon new file mode 100755 index 0000000..85c8584 --- /dev/null +++ b/start-telegram-daemon @@ -0,0 +1,206 @@ +#!/usr/bin/perl -w + +# start-engine +# derived from start-memcached +# 2003/2004 - Jay Bonci +# This script handles the parsing of the /etc/memcached.conf file +# and was originally created for the Debian distribution. +# Anyone may use this little script under the same terms as +# memcached itself. + +# a bit changed it for telegram-daemon to generate config before start (Vitaly Valtman) + +use POSIX qw(strftime); +use strict; + +my $id = defined($ARGV[0]) ? $ARGV[0] : ''; +my $idx = $id eq '' ? '' : " '$id'"; +my $idl = ($id =~ /^\.(.*)$/ ? "-$1" : $id); + +my $root = ""; + +my $params; my $etchandle; my $etcfile = "$root/etc/telegram-daemon/telegram-daemon$id.conf"; + +# This script assumes that engine is located at /usr/bin/engine, and +# that the pidfile is writable at /var/run/engine.pid + +my $engine_pfx = "$root/usr/share/telegram-daemon/bin/"; +my $pidfile = "$root/var/run/telegram-daemon$id.pid"; + +# If we don't get a valid logfile parameter in the /etc/engine.conf file, +# we'll just throw away all of our in-daemon output. We need to re-tie it so +# that non-bash shells will not hang on logout. Thanks to Michael Renner for +# the tip +my $fd_reopened = "/dev/null"; +$fd_reopened = "$root/var/log/telegram-daemon/telegram-daemon$idl.log" if -d "$root/var/log/telegram-daemon/"; + +sub handle_logfile +{ + my ($logfile) = @_; + $logfile = "$root/var/log/telegram-daemon/$logfile" unless $logfile =~ /\//; + $fd_reopened = $logfile; +} + +sub reopen_logfile +{ + my ($logfile) = @_; + + open *STDERR, ">>$logfile"; + open *STDOUT, ">>$logfile"; + open *STDIN, ">>/dev/null"; + chown 239, 239, $logfile; + $fd_reopened = $logfile; +} + +sub adjust_arg +{ + my ($arg) = @_; + if ($arg =~ /^newest:(.*)$/) { + my @L = split /:/, $1; + my $x = $arg; + my $xt = 0; + for my $y (@L) { + my @S = stat($y); + if (scalar @S && $S[9] > $xt) { + $x = $y; + $xt = $S[9]; + } + } + return $x; + } + return $arg; +} + +# This is set up in place here to support other non -[a-z] directives + +my $conf_directives = { + "logfile" => \&handle_logfile, +}; + +my %Vars = ( + "execute" => "msg-search-engine", + "work_dir" => "$root/var/lib/telegram-daemon" + ); + +my $have_c = 0; +my $have_l = 0; +my $have_u = 0; +my $have_aes = 0; + +if(open $etchandle, $etcfile) +{ + foreach my $line (<$etchandle>) + { + $line ||= ""; + $line =~ s/\#.*//g; + $line =~ s/\s+$//g; + $line =~ s/^\s+//g; + next unless $line; + next if $line =~ /^\-[dh]/; + + if($line =~ /^[^\-]/) + { + my ($directive, $int, $arg) = $line =~ /^(.*?)(\s+|\s*=\s*)(.*)/; + next unless $directive; + if (exists $conf_directives->{$directive}) { + $conf_directives->{$directive}->($arg); + } else { + $Vars{$directive} = $arg; + } + next; + } + + $have_l = 1 if $line =~ /^-L\s/; + $have_c = 1 if $line =~ /^-c\s/; + $have_u = 1 if $line =~ /^-u\s/; + push @$params, $line; + } + +}else{ + $params = []; +} + +push @$params, "-u telegramd" unless($have_u); +push @$params, "-L $fd_reopened" unless($have_l); +push @$params, "-c config$idl" unless($have_c); +$params = join " ", @$params; + +if(-e $pidfile) +{ + open PIDHANDLE, "$pidfile"; + my $localpid = ; + close PIDHANDLE; + + if ($localpid && $localpid =~ /(\d+)/) { $localpid = $1; } else { $localpid = -1; } + if (-d "/proc/$localpid") + { + print STDERR "telegram-daemon$idl is already running.\n"; + exit; + } else { + print STDERR "removing stale $pidfile.\n"; + `rm -f $pidfile`; + } + +} + +if (exists $Vars{'quit'}) { + print STDERR "telegram-daemon$idl disabled\n"; + exit(0); +} + +my $engine = $engine_pfx.$Vars{'execute'}; +my $wdir = $Vars{'work_dir'}; +chdir $wdir if -d $wdir; + +unless (-x $engine) { + print STDERR "executable $engine not found\n"; + exit(1); +} + +unless (-d $wdir) { + print STDERR "work directory $wdir not found\n"; + exit(1); +} + +for my $x ('s', 0 .. 9) { + if (defined($Vars{"arg$x"})) { + $params .= " ".adjust_arg($Vars{"arg$x"}); + } +} + +my $pid = fork(); + + + +if (!$pid) { + reopen_logfile ($fd_reopened); + chdir $wdir; + open(my $fh, '>', "config$idl"); + + my $text = <<"END_MSG" +config_directory="$wdir"; +test=false; +msg_num=true; +binlog_enabled=true; +binlog="binlog$idl.bin"; +pfs_enabled=true; +log_level = 0; +lua_script="script$idl.lua"; +END_MSG +; + print $fh $text; + close $fh; + my $t; + $t = strftime ("%Y-%m-%d %H:%M:%S %Z", localtime); + print STDERR "[$t] invoking telegram-daemon$idl: $engine $params\n"; + exec "$engine $params"; + exit (0); +} else { + if (open PIDHANDLE,">$pidfile") { + print PIDHANDLE $pid; + close PIDHANDLE; + } else { + print STDERR "Can't write pidfile to $pidfile.\n"; + } +} + diff --git a/telegram-daemon b/telegram-daemon new file mode 100755 index 0000000..e174283 --- /dev/null +++ b/telegram-daemon @@ -0,0 +1,332 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: engine +# Required-Start: $local_fs $syslog +# Required-Stop: $local_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: KittenDB Meta Engine +### END INIT INFO + +# +# run script for KittenDB Engine +# author: kot +# author: burunduk +# author: burunduk +# +# Version: 2013-06-06 +# + +# Features added: +# -- flock to avoid parallel execution +# -- checks to avoid creating empty engine configuration files + + +# a bit changed it for telegram-daemon to use different folders +# and to have posiiblilities to have fake root +# Vitaly Valtman + +ROOT="" +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMONDIR=$ROOT/usr/share/telegram-daemon/bin +DAEMONBOOTSTRAP=$ROOT/usr/share/telegram-daemon/bin/start-telegram-daemon +NAME=telegram-daemon +DESC="KOT's meta engine" +PIDFILE=$ROOT/var/run/$NAME +LOCKFILE=$ROOT/var/lock/$NAME +CONFFILE=$ROOT/etc/telegram-daemon/$NAME +LOCK_WAIT=5 +STOP_TIMEOUT=5 +KILL_TIMEOUT=5 + +test -x $DAEMONDIR || exit 0 +test -x $DAEMONBOOTSTRAP || exit 0 + +set -e + +## Utilitary functions + +# Send information to stderr +function echo_stderr() { + echo "$*" 1>&2 +} + +# Get engine status. Returns 0 on running engine, 1 otherwise. +function engine_status() { + local id="$1" + local pif="$PIDFILE.$id.pid" + if ! [ -f "$pif" ] ; then + echo "stopped" + return 1 + fi + local pid="$(<$pif)" + if [ -z "$pid" ]; then + echo "corrupt pid file" + return 1 + fi + if [ -d "/proc/$pid/" ]; then + echo "$pid" + return 0 + else + echo "failed (pid $pid)" + return 1 + fi +} + +# Start engine. Usage: engine_start +function engine_start() { + local eid="$1" + local r='' + local pid='' + pid="$(engine_status "$eid")" && r='ok' || r='fail' + if [ "$r" == 'ok' ] ; then + echo_stderr "telegram-daemon-$eid: already running ($pid)" + else + start-stop-daemon --start --quiet --exec $DAEMONBOOTSTRAP -- .$eid 100> /dev/null + fi + return 0 +} + +# Stop engine. Usage: engine_stop +function engine_stop() { + local eid="$1" + local r='' + local status="$(engine_status "$eid")" && r='ok' || r='fail' + local pif="$PIDFILE.$eid.pid" + if [ "$r" == 'ok' ] ; then + start-stop-daemon --stop --quiet --oknodo --pidfile "$pif" + local ti=0 + while [ $ti -lt $((10 * $STOP_TIMEOUT)) ] ; do + status="$(engine_status "$eid")" && r='ok' || r='fail' + if [ "$r" == 'fail' ]; then + break + fi + sleep 0.1 + ti=$(($ti + 1)) + done + if [ "$r" == 'ok' ] ; then + echo_stderr "telegram-daemon-$eid: not stopped, sending SIGKILL..." + start-stop-daemon --stop --quiet --oknodo --pidfile "$pif" --signal KILL + ti=0 + while [ $ti -lt $((10 * $KILL_TIMEOUT)) ] ; do + status="$(engine_status "$eid")" && r='ok' || r='fail' + if [ "$r" == 'fail' ]; then + break + fi + sleep 0.1 + ti=$(($ti + 1)) + done + fi + if [ "$r" == 'ok' ] ; then + echo_stderr "telegram-daemon-$eid: not stopped with SIGKILL, giving up" + return 1 + else + if [ -f "$pif" ] ; then + rm "$pif" + fi + echo "telegram-daemon-$eid: stopped" + fi + else + echo_stderr "telegram-daemon-$eid: not running: $status" + fi + return 0 +} + +# usage: engine_disable +function engine_disable() { + local eid="$1" + local conf="$CONFFILE.$eid.conf" + [ -e "$conf" ] || return 1 # work only with existing engines + if grep -E '^quit 1$' "$conf" > /dev/null ; then + echo_stderr "telegram-daemon-$eid: already disabled" + else + echo 'quit 1' >> "$conf" + fi + return 0 +} + +# usage: engine_enable +function engine_enable() { + local eid="$1" + local conf="$CONFFILE.$eid.conf" + [ -e "$conf" ] || return 1 # work only with existing engines + if ! grep -E '^quit' "$conf" > /dev/null ; then + echo_stderr "telegram-daemon-$eid: already enabled" + else + sed -i~ -e '/^quit/d' -- "$conf" + fi + return 0 +} + +# Wait for engine's command to be completed +function engine_wait() { + local eid="$1" + ( + flock -x -w $(($LOCK_WAIT + $STOP_TIMEOUT + $KILL_TIMEOUT)) 100 || exit 1 + ) 100> $LOCKFILE.$eid.lock || echo "Unable to wait for $eid" + return 0 +} + +# Run a single command +# Only one instance of this command per engine is supposed to work +function run_one() { + local eid="$1" + shift + local command="$*" + [ "${#eid}" -gt 5 ] && return 0 # avoid long engine ids + ( + flock -x -w $LOCK_WAIT 100 || exit 1 + $command "$eid" + ) 100> $LOCKFILE.$eid.lock + return 0 +} + +# Run commands +function run() { + local mode="$1" + shift + local command="$*" + local eid='' + if [ "$mode" == 'parallel' ] ; then + for eid in $arguments ; do + run_one "$eid" "$command" & + done + sleep 0.1 + for eid in $arguments ; do + engine_wait "$eid" + done + else + for eid in $arguments ; do + run_one "$eid" "$command" + done + fi + return 0 +} + +# Get all actual engine ids +function arguments_all() { + local file='' + local id='' + local list='' + for file in $(ls $CONFFILE.?*.conf 2> /dev/null) ; do + id=${file#$CONFFILE.} + id=${id%.conf} + list="$list $id" + done + for file in $(ls $PIDFILE.?*.pid 2> /dev/null) ; do + id=${file#$PIDFILE.} + id=${id%.pid} + list="$list $id" + done + local f='' + for f in $list ; do echo "$f" ; done | sort -u + return 0 +} + +## Commands + +# Start engine. +function engine_command_start() { + local eid="$1" + engine_start "$eid" +} + +# Stop engine. +function engine_command_stop() { + local eid="$1" + engine_stop "$eid" +} + +# Enable engine. +function engine_command_enable() { + local eid="$1" + engine_enable "$eid" + engine_start "$eid" +} + +# Disable engine. +function engine_command_disable() { + local eid="$1" + engine_disable "$eid" + engine_stop "$eid" +} + +# Restart engine. +function engine_command_restart() { + local eid="$1" + engine_stop "$eid" + echo "restarting telegram-daemon-$eid..." + engine_start "$eid" +} + +# Send signal to engine. Usage: engine_command_signal +function engine_command_signal() { + local id="$2" + local signal="$1" + local r='' + local comment="$(engine_status "$id")" && r='ok' || r='fail' + local res='' + if [ "$r" == 'ok' ]; then + start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE.$id.pid --signal "$signal" + else + echo_stderr "telegram-daemon-$id: not running: $comment" + fi + return 0 +} + +# Get engine status +function engine_command_status() { + local id="$1" + local res="telegram-daemon-$id: " + local r='' + local pid='' + pid="$(engine_status "$id")" && r='ok' || r='fail' + if [ "$r" == 'ok' ]; then + res="$res $(COLUMNS=10000 ps -o pid,c,stime,time,cmd --no-header --pid $pid | sed -e 's/\/usr\/share\/telegram-daemon\/bin\///')" + else + res="$res $pid" + fi + echo "$res" + return 0 +} + +## Entry point + +command="$1" +shift + +arguments="$*" +if [ -z "$arguments" ] ; then + if [ "$command" == "status" -o "$command" == "start" -o "$command" == "rotate-logs" -o "$command" == "stop" ] ; then + arguments="$(arguments_all)" + fi +elif [ "$arguments" == "all" ] ; then + arguments="$(arguments_all)" +fi +if [ -z "$arguments" ] ; then + echo "nothing to do" + exit 0 +fi + +case "$command" in + ('disable') run parallel engine_command_disable ;; + ('enable') run parallel engine_command_enable ;; + # + ('start') run parallel engine_command_start ;; + ('status') run normal engine_command_status ;; + ('stop') run parallel engine_command_stop ;; + # + ('rotate-logs') run parallel engine_command_signal USR1 ;; + # + ('restart'|'force-reload') run parallel engine_command_restart ;; + (*) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|rotate-logs|status} [|all]" >&2 + echo " additional commands: disable , enable , reindex (use with caution)" >&2 + exit 1 + ;; +esac + +exit 0 +