226 lines
6.8 KiB
C++
226 lines
6.8 KiB
C++
#include "WorkerTelegrafControl.h"
|
|
|
|
#include "Logger.h"
|
|
#include "TelegrafControl.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <syslog.h>
|
|
|
|
|
|
// Telegraf check 주기 (sec)
|
|
#define TELEGRAF_CHECK_INTERVAL 60
|
|
|
|
|
|
// telegraf 미기동 상태가 지정된 횟수 이상인 경우.. 기동 처리 수행
|
|
// - 운영자 요청으로 10분 초과 미기동 상태인 경우.. 자동 기동 처리
|
|
#define TELEGRAF_NO_ACTIVE_COUNT_MAX 10
|
|
|
|
// telegraf 가 hang 상태 관련 지정된 횟수 이상인 경우.. 재기동 처리 수행
|
|
#define TELEGRAF_HANG_COUNT_MAX 2
|
|
|
|
// telegraf 의 MAX 기동 시간 (sec)
|
|
// - telegraf 기동 후 elapsed time 이 현재 설정값을 초과하는 경우.. 재기동 처리를 수행한다.
|
|
// - 이는 telegraf 장기 운영시.. 삭제된 log 파일을 tail 에서 붙잡고 있어.... OS Disk full 상황을 방지하기 위함
|
|
// - 운영자 의견 수렴 결과.. 2일 단위로 재기동 요청.
|
|
#define TELEGRAF_ELAPSED_TIME_MAX 172800LL
|
|
|
|
|
|
|
|
// Worker::TelegrafControl 프로세스의 Main 역활을 수행하기 위한 함수.
|
|
int WorkerTelegrafControlMain( void )
|
|
{
|
|
setproctitle( "TelegrafControl [initialize]" );
|
|
|
|
// Set signal handler
|
|
SetWorkerTelegrafControlSignalHandler();
|
|
|
|
|
|
// telegraf control 객체 생성
|
|
CTelegrafControl telegraf;
|
|
|
|
|
|
// 전체 프로세스의 생성이 완료될때까지 대기 후 작업 시작
|
|
sleep( 2 );
|
|
setproctitle( "TelegrafControl" );
|
|
|
|
int iProcessId = 0;
|
|
int iProcessNotActiveCount = 0;
|
|
int iProcessHangCount = 0;
|
|
long long llProcessElapsedSec = 0;
|
|
|
|
// 주기적으로 telegraf 상태를 점검한다.
|
|
while( 1 )
|
|
{
|
|
// 지정된 시간동안 sleep 처리
|
|
sleep( TELEGRAF_CHECK_INTERVAL );
|
|
|
|
_LOG( LDBG, "[TelegrafControl:%d] check start.", getpid() );
|
|
|
|
// 1. process 기동 여부 check
|
|
iProcessId = telegraf.GetProcessId();
|
|
if( iProcessId == 0 )
|
|
{
|
|
// 미기동 상태인 경우
|
|
// - 패치 및 설정 등의 작업으로 인해 미기동 상태일 수 있으므로......
|
|
// - 미기동 상태가 지정된 횟수 이상인 경우에만.. 기동 처리를 시도한다.
|
|
|
|
++iProcessNotActiveCount;
|
|
if( iProcessNotActiveCount > TELEGRAF_NO_ACTIVE_COUNT_MAX )
|
|
{
|
|
_LOG( LINF, "[TelegrafControl:%d] telegraf process not found. try starting.", getpid() );
|
|
|
|
// 지정 횟수 초과의 미기동 상태인 경우... 기동 처리 try...
|
|
telegraf.ServiceStart();
|
|
|
|
// telegraf 기동을 시도했으므로... count 는 초기화 처리한다.
|
|
iProcessNotActiveCount = 0;
|
|
}
|
|
else
|
|
{
|
|
_LOG( LINF, "[TelegrafControl:%d] telegraf process not found. count[%d]", getpid(), iProcessNotActiveCount );
|
|
}
|
|
|
|
// telegraf 상태 처음부터 다시 check.
|
|
continue;
|
|
}
|
|
|
|
// telegraf 기동 중인 상태인 경우 not active count 초기화
|
|
iProcessNotActiveCount = 0;
|
|
|
|
|
|
// 2. process hang check
|
|
// - hang 상황인 경우... 재기동 처리
|
|
if( telegraf.IsHang() == true )
|
|
{
|
|
// telegraf hang 상황인 경우...
|
|
++iProcessHangCount;
|
|
if( iProcessHangCount > TELEGRAF_HANG_COUNT_MAX )
|
|
{
|
|
_LOG( LINF, "[TelegrafControl:%d] telegraf[%d] hang detected. try restarting.", getpid(), iProcessId );
|
|
|
|
// 지정 횟수 초과의 hang 상태인 경우... 재기동 처리 try...
|
|
telegraf.ServiceQuit();
|
|
|
|
// telegraf 재기동을 시도했으므로... count 는 초기화 처리한다.
|
|
iProcessHangCount = 0;
|
|
|
|
// 관련 사항은 /var/log/message 상에 기록해 둔다.
|
|
openlog( PROG_NAME, LOG_PID, LOG_USER );
|
|
syslog( LOG_WARNING, "telegraf[%d] hang detected. SIGQUIT send for telegraf restart.", iProcessId );
|
|
closelog();
|
|
}
|
|
else
|
|
{
|
|
_LOG( LINF, "[TelegrafControl:%d] telegraf[%d] is hang. count[%d]", getpid(), iProcessId, iProcessHangCount );
|
|
}
|
|
|
|
// telegraf 상태 처음부터 다시 check.
|
|
continue;
|
|
}
|
|
|
|
// telegraf hang count 초기화
|
|
iProcessHangCount = 0;
|
|
|
|
|
|
// 3. process 기동 후 지정된 시간 이상 되었는지 check
|
|
// - 지정된 시간 초과시 재기동 처리
|
|
// - ps -o etimes= -p `pgrep telegraf`
|
|
// - sec 단위
|
|
llProcessElapsedSec = telegraf.GetProcessElapsedSec();
|
|
if( llProcessElapsedSec > TELEGRAF_ELAPSED_TIME_MAX )
|
|
{
|
|
_LOG( LINF, "[TelegrafControl:%d] telegraf[%d] elapsed time too long [%lld / %lld sec]. try restarting."
|
|
, getpid(), iProcessId, llProcessElapsedSec, TELEGRAF_ELAPSED_TIME_MAX );
|
|
|
|
// 재기동 처리 시도
|
|
telegraf.ServiceRestart();
|
|
|
|
// telegraf 상태 처음부터 다시 check.
|
|
continue;
|
|
}
|
|
|
|
|
|
// 4. 기타
|
|
|
|
}
|
|
|
|
// 종료시 정리 작업 수행
|
|
ReadyToExitWorkerTelegrafControl();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
|
|
// 프로세스 종료 전 처리할 종료 관련 각 작업을 일괄로 처리하기 위한 함수.
|
|
void ReadyToExitWorkerTelegrafControl( void )
|
|
{
|
|
// Logger 객체 종료 처리
|
|
CLogger::Exit();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// Worker TelegrafControl 프로세스에 대한 종료 처리 수신시
|
|
static void SignalWorkerTelegrafControlTerminate( int nSignalNumber )
|
|
{
|
|
// Signal Number 에 따른 로깅처리.
|
|
if( nSignalNumber == SIGTERM )
|
|
{
|
|
_LOG( LINF, "[TelegrafControl:%d] Process exit by SIGTERM signal. Good Bye..", getpid() );
|
|
}
|
|
else
|
|
{
|
|
_LOG( LWAR, "[TelegrafControl:%d] Process exit by abnormal signal[%d], Good Bye..", getpid(), nSignalNumber );
|
|
}
|
|
|
|
ReadyToExitWorkerTelegrafControl();
|
|
|
|
// 종료전 잠시 대기
|
|
struct timespec sleep;
|
|
sleep.tv_sec = 0;
|
|
sleep.tv_nsec = 500000000; // 0.5 sec
|
|
nanosleep( &sleep, NULL );
|
|
|
|
exit( EXIT_SUCCESS );
|
|
}
|
|
|
|
|
|
// Worker::TelegrafControl Process 의 signal 처리기...
|
|
void SetWorkerTelegrafControlSignalHandler( void )
|
|
{
|
|
sigset_t set;
|
|
struct sigaction act;
|
|
|
|
memset( &act, 0x00, sizeof( act ) );
|
|
sigfillset( &set );
|
|
sigprocmask( SIG_SETMASK, &set, NULL );
|
|
sigfillset( &act.sa_mask );
|
|
|
|
// 무시 처리 signal
|
|
act.sa_handler = SIG_IGN;
|
|
sigaction( SIGPIPE, &act, NULL ); /* desciptor 오류 발생시 Process가 죽는 것은 방지하기 위하여 설정 */
|
|
sigaction( SIGHUP, &act, NULL ); /* process를 기동시킨 관리자의 로그아웃시, 또는 config reload 등의 처리 signal*/
|
|
sigaction( SIGINT, &act, NULL ); /* ^C 키를 누른 경우 받는 신호 => demon 으로 기동되기 땜시 이 신호 못받음 */
|
|
sigaction( SIGQUIT, &act, NULL ); /* 키보드에 의한 Abort 신호 처리 => ? */
|
|
|
|
// Worker 프로세스는 자식 프로세스가 존재하지 않으므로 그냥 무시처리함.
|
|
act.sa_handler = SIG_IGN;
|
|
sigaction( SIGCHLD, &act, NULL );
|
|
|
|
/* 각종 에러나 사용자의 종료 신호 처리 */
|
|
act.sa_handler = SignalWorkerTelegrafControlTerminate;
|
|
sigaction( SIGTERM, &act, NULL ); /* kill -TERM 에 의한 프로세스 종료시 */
|
|
|
|
// 나머지 신호는 default 처리.
|
|
|
|
sigemptyset( &set ); /* 신호 처리기 처리 설정 위한 블록 해제 */
|
|
sigprocmask( SIG_SETMASK, &set, NULL );
|
|
|
|
}
|