Хорошо, поэтому я работаю над программой, написанной на 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
}
Почему вы должны иметь различное поведение для вашей службы быть прекращены с 'SIGTERM' и вся система будучи остановкой? –
Он лежит в концепции программы. Он предназначен для работы всегда. Однако, если он должен быть отключен, это должно быть сообщено на конкретный адрес электронной почты. Я не хочу получать статистику за все время, когда компьютер был загружен и перезагружен, но я хочу определить, прервал ли он его вручную. Надеюсь, это имеет смысл :) – roggan87
Сисадмин, который должен, например, обновите свою программу (или остановите используемую вами базу данных!) на своем сервере может иметь другое представление о «предназначении всегда запускать». Поэтому оставляйте его способным управлять своей системой ... –