2012-02-06 3 views
0

Хорошо, поэтому я работаю над программой, написанной на C++, которая работает как демон. В первую очередь это касается пользователей Linux, но я хочу включить Windows (работает как сервис) и пользователей Mac.Определить остановку системы в C++

Я хочу, чтобы демон регистрировался всякий раз, когда он вручную отключается. Однако он должен не выключения журнала, сделанные системой из-за остановки системы или перезагрузки.

В настоящее время я маскировал все сигналы и реализовал какую-то обработку с помощью sigaction(). Перед протоколированием выключения функция также проверяет уровень запуска системы, а если она равна 0, 1 0r 6, то журнал опускается. Способ проверки уровня запуска - запустить команду «уровень выполнения» и обработать вывод.

Моя проблема заключается в том, что уровень выполнения не всегда является тем, чего я ожидал бы от него. Я запускаю Ubuntu, и когда я вошел в систему, как обычно, я нахожусь на уровне запуска 2, и это происходит при перезагрузке. Когда я останавливаюсь, я иногда ничего не получаю от вывода «runlevel». Различные дистрибутивы Linux используют свои собственные уровни запуска, поэтому это не оптимально для переносимости.

Итак, есть ли лучший способ определить, остановлена ​​ли система? Кроме того, существует ли лучший способ перехвата прерываний, например. через обработку исключений и т. д.?

Я вставлю фрагмент кода, если он здесь поможет. Написано в 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

Сисадмин, который должен, например, обновите свою программу (или остановите используемую вами базу данных!) на своем сервере может иметь другое представление о «предназначении всегда запускать». Поэтому оставляйте его способным управлять своей системой ... –

ответ

0

В итоге я решил пойти другим путем, чтобы решить проблему. Теперь я читаю историю загрузки компьютера и сравнивает его с историей программного обеспечения, чтобы узнать, загружен или остановлен компьютер без программного обеспечения. Этого достаточно и, вероятно, будет еще более точным.

Команда, используемая для определения истории загрузки в Linux является

$ last reboot