2012-02-06 6 views
0

좋아요. 그래서 나는 데몬으로 실행중인 C++로 작성된 프로그램에서 작업하고 있습니다. 그것은 주로 리눅스 사용자를 겨냥하고 있지만 Windows (서비스로 실행 중)와 Mac 사용자를 포함시키고 싶습니다.C++에서 시스템 중지 확인

데몬이 수동으로 종료 될 때마다 기록하도록합니다. 그러나 이 아닌 시스템 종료 또는 재부팅으로 인해 시스템이 로그를 종료해야합니다.

현재 모든 신호를 마스크 처리하고 sigaction()을 사용하여 일종의 처리를 구현했습니다. 시스템 종료를 로깅하기 전에 함수는 시스템의 런레벨도 확인하고, 0, 1 0 6이면 로깅이 생략됩니다. 런레벨을 검사하는 방법은 "runlevel"명령을 실행하고 출력을 처리하는 것입니다.

내 문제는 런레벨이 항상 내가 기대하는 것만은 아니다. 나는 우분투를 실행하고 있는데 평상시처럼 로그인 할 때 나는 런레벨 2에 있고 재부팅 할 때도 마찬가지다. 멈 추면 가끔 "런레벨"의 출력으로 얻지 못합니다. 다른 리눅스 배포판은 자체 런레벨을 사용하기 때문에 이식성이 좋지 않습니다.

그래서 시스템이 정지하는지 확인하는 더 좋은 방법이 있습니까? 또한 중단을 잡는 더 좋은 방법이 있습니까? 예 : 예외 처리 등을 통해?

여기에 도움이된다면 코드 스 니펫을 붙여 넣습니다. C++로 작성되었으며 Poco C++ libraries을 사용합니다.

void MainApplication::signalHandler(int sig) { 
#if defined(POCO_OS_FAMILY_UNIX) 
    switch(sig) { 
     case -1: 
      struct sigaction act; 
      act.sa_handler = signalHandler; 
      sigemptyset(&act.sa_mask); 
      act.sa_flags = 0; 
      sigaction(SIGINT, &act, 0); //Better way to do this? 
      sigaction(SIGQUIT, &act, 0); 
      sigaction(SIGKILL, &act, 0); 
      sigaction(SIGTERM, &act, 0); 
      sigaction(SIGHUP, &act, 0); 
      sigaction(SIGSTOP, &act, 0); 
      sigaction(SIGTSTP, &act, 0); 
      sigaction(SIGCONT, &act, 0); 
      sigaction(SIGUSR1, &act, 0); 
      sigaction(SIGUSR2, &act, 0); 
      break; 
     case SIGINT: 
     case SIGQUIT: 
     case SIGTSTP: 
     case SIGHUP: 
     case SIGKILL: 
     case SIGTERM: 
      //Log Shutdown! 
      if (!isHalting()) 
       _instance->_database->logBypass(BYPASS_SHUTDOWN); 
      terminateNicely(true); 
      break; 
     case SIGCONT: 
      //Continued, means stopped 
      break; 
     case SIGUSR1: 
      //Resetting Net Responsibility 
      _instance->uninitialize(); 
      _instance->initialize(*_instance); 
      break; 
     case SIGUSR2: 
      //Other action or just mask it 
      break; 
     default: 
      //Caught signal 
      break; 
    } 
#endif 
} 



bool MainApplication::isHalting() { 
#if defined(POCO_OS_FAMILY_UNIX) 
    string cmd("runlevel"); 
    vector<string> args; 
    Poco::Pipe outPipe; 
    ProcessHandle ph = Process::launch(cmd, args, 0, &outPipe, 0); 
    ph.wait(); 
    Poco::PipeInputStream istr(outPipe); 
    stringstream ss; 
    Poco::StreamCopier::copyStream(istr, ss); 
    int runlevel; 
    ss.seekg(-2, ios::end); 
    ss >> runlevel; 
    return (runlevel == 0 || runlevel == 1 || runlevel == 6); 
#else 
    return false; 
#endif 
} 
+0

왜 당신이 당신의 서비스에 대해 서로 다른 행동이'SIGTERM' 및 전체 시스템 인 종료와 함께 종료 될해야합니까? –

+0

그것은 프로그램의 개념에 놓여 있습니다. 항상 실행되도록 설계되었습니다. 그러나 종료해야하는 경우 특정 전자 메일 주소로보고해야합니다. 컴퓨터가 부팅되고 재부팅 된 모든 시간에 대한 통계를 원하지는 않지만 사용자가 수동으로 중단했는지 확인하고 싶습니다. 희망이 어떤 의미가있어 :) – roggan87

+0

예를 들어 가지고 sysadmin. 자신의 서버에서 프로그램을 업그레이드 (또는 사용중인 데이터베이스를 중지하십시오!)하면 "항상 실행되도록"하는 관점이 다를 수 있습니다. 그래서 그에게 그의 시스템을 관리 할 수있는 능력을 남겨주세요. –

답변

0

나는이 문제를 해결하기 위해 다른 길로 나갔다. 이제 컴퓨터의 부팅 기록을 읽고 소프트웨어가 실행되지 않았는지 확인하기 위해 소프트웨어 기록과 비교합니다. 그 정도면 충분하고 아마 더 정확할 것입니다.

리눅스 부팅 역사를 결정하는 데 사용되는 명령은

입니다
$ last reboot