我在哪里放置启动和关机任务?

我已经写了下面的程序,当我的Linux系统从电源故障重新启动时,通过电子邮件通知我。

我这样做的方式是启用BIOS中的电源故障恢复,然后在每次计算机启动或closures时在SQlite数据库中注册。

当SQlite数据库中的最后一次closures时间为NULL时,我发现了一个powerfailure,并发送了电子邮件通知。

现在,我已经完成了大部分工作,但是我仍然需要将这个程序添加到各自的启动和closures脚本中。

我需要把它放在哪里? 需要特别注意的是,它会通过smtp服务器向我的android手机发送powerfail通知,这意味着启动脚本应该只在networking(最好是无线)已经初始化后运行。

这是我的问题在这里的一个交叉post。

#ifdef __cplusplus #include <cstdio> #include <cstdlib> #include <ctime> //#include <cstdint> #include <cstdarg> #include <cstring> #include <cctype> #include <sqlite3.h> #else #include <stdio.h> #include <stdlib.h> #include <time.h> //#include <stdint.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <sqlite3.h> #endif #include <unistd.h> // for gethostname // Requires: // apt-get install sendemail // Compile with: // gcc -Wall -lsqlite3 powerfail.c -o hel // g++ -Wall -lsqlite3 powerfail.c -o hel // With stdint: // g++ -Wall -Wno-write-strings -std=c++0x -lsqlite3 powerfail.c -o hel // getconf GNU_LIBPTHREAD_VERSION // getconf PAGESIZE // Doc: // http://stackoverflow.com/questions/1409453/how-to-store-and-get-datetime-value-in-sqlite // http://docs.python.org/library/sqlite3.html // http://www.devshed.com/c/a/Python/Using-SQLite-in-Python/ int bDebug = 0; int bStartupRequested = 1; int bShutdownRequested = 0; int bSimulatePowerFailure = 0; int bList = 0; int bClear = 0; int bTestMail = 0; int Debug_Printf(const char* szFormat, ...) { if(!bDebug) return 0; va_list arglist; int iReturnValue; int iSize = 100; char *p; if ((p = (char*) malloc (iSize)) == NULL) { printf("Error in Debug_Printf: Malloc failed.\n"); return (int) NULL; } va_start(arglist, szFormat); iReturnValue = vsnprintf (p, iSize, szFormat, arglist); va_end(arglist); printf("%s", p); free(p); return iReturnValue; } char* ToLower(char* szInputString) { if(szInputString != NULL) { int iStringLength = strlen(szInputString); char* szTempString = (char*) malloc((iStringLength+1) * sizeof(char)); int i ; for(i =0; i < iStringLength; ++i) szTempString[i] = (char) tolower(szInputString[i]); return szTempString; } return NULL; } /* Callback called when the query is exceuted */ /* static int callback(void *NotUsed, int argc, char **argv, char **azColName) { printf ("\n ******** Inside Callback\n"); int i; int rowpr=argc-1; NotUsed=0; printf("\n %s ",__FUNCTION__); for(i=0; i<rowpr; i++) printf("%s ",azColName[i]); printf("%s\n",azColName[rowpr]); for(i=0; i<rowpr; i++){ printf("%s ", argv[i] ? argv[i] : "NULL"); } printf("%s\n", argv[rowpr] ? argv[rowpr] : "NULL"); return 0; } */ void ExecuteNonQuery(char* szSQLstatement, sqlite3 *handle) { Debug_Printf("SQL: %s\n", szSQLstatement); char* szErrMsg = NULL; // Execute the query int iExecutionResult = sqlite3_exec(handle, szSQLstatement, NULL, handle, &szErrMsg); if(iExecutionResult != SQLITE_OK) { if(szErrMsg != NULL) { Debug_Printf("\n\n******************************************************\n"); Debug_Printf("* Error while doing ExecuteNonQuery: \n*\t%s\n", szErrMsg); Debug_Printf("******************************************************\n\n"); sqlite3_free(szErrMsg); } } } void ClearTable(const char* szTableName, sqlite3 *handle) { char* szDeleteStatement = (char*) malloc(1000 * sizeof(char)); if(szDeleteStatement != NULL) { sprintf(szDeleteStatement, "DELETE FROM %s", szTableName); ExecuteNonQuery(szDeleteStatement, handle); free(szDeleteStatement); } else Debug_Printf("Error: Malloc failed. Insufficient RAM for DELETE statement allocation.\n"); } int SelectFromTable(const char* szTableName, sqlite3 *handle) { //char szSelectStatement[] = "SELECT * FROM T_StartStopLog "; char* szSelectStatement = (char*) malloc(1000 * sizeof(char)); if(szSelectStatement != NULL) { sprintf(szSelectStatement, "SELECT * FROM %s", szTableName); sqlite3_stmt *stmt; // select query from the table int iRetVal = sqlite3_prepare_v2(handle, szSelectStatement, -1, &stmt, 0); if(iRetVal) { Debug_Printf("Selecting data from DB Failed\n"); return -1; } // Read the number of rows fetched int cols = sqlite3_column_count(stmt); int col = 0; while(1) { // fetch a row's status iRetVal = sqlite3_step(stmt); if(iRetVal == SQLITE_ROW) { // SQLITE_ROW means fetched a row // sqlite3_column_text returns a const void* , typecast it to const char* for(col=0 ; col < cols; col++) { const char *val = (const char*)sqlite3_column_text(stmt,col); printf("%s = %s\t",sqlite3_column_name(stmt,col),val); } printf("\n"); } else if(iRetVal == SQLITE_DONE) { // All rows finished Debug_Printf("All rows fetched\n"); break; } else { // Some error encountered Debug_Printf("Some error encountered\n"); return -1; } } free(szSelectStatement); } else { Debug_Printf("Error: Malloc failed. Insufficient RAM for SELECT statement allocation.\n"); return -1; } return 0; } int GetScalarInt(const char* szSelectStatement, sqlite3 *handle) { //char szSelectStatement[] = "SELECT * FROM T_StartStopLog "; int iReturnValue =0 ; if(szSelectStatement != NULL) { sqlite3_stmt *stmt; // select query from the table int iRetVal = sqlite3_prepare_v2(handle, szSelectStatement, -1, &stmt, 0); if(iRetVal) { Debug_Printf("Selecting data from DB Failed\n"); return -1; } // Read the number of rows fetched int cols = sqlite3_column_count(stmt); int col = 0; while(1) { // fetch a row's status iRetVal = sqlite3_step(stmt); if(iRetVal == SQLITE_ROW) { // SQLITE_ROW means fetched a row // sqlite3_column_text returns a const void* , typecast it to const char* for(col=0 ; col < cols; col++) { const char *val = (const char*)sqlite3_column_text(stmt,col); Debug_Printf("%s = %s\n",sqlite3_column_name(stmt,col),val); if(val != NULL) { iReturnValue= atoi(val); } else iReturnValue = 0; } Debug_Printf("\n"); } else if(iRetVal == SQLITE_DONE) { // All rows finished Debug_Printf("All rows fetched\n"); break; } else { // Some error encountered Debug_Printf("Some error encountered\n"); return -1; } } //free(szSelectStatement); } else { Debug_Printf("Error: No valid query-parameter passed to function GetScalarInt.\n"); return -1; } return iReturnValue; } // http://www.cplusplus.com/reference/clibrary/ctime/tm/ int GetSequentialDate(int iDay, int iMonth, int iYear, int iHour, int iMinute, int iSecond) { struct tm a_tm_struct ; a_tm_struct.tm_year = iYear - 1900; a_tm_struct.tm_mon = iMonth - 1; a_tm_struct.tm_mday = iDay; a_tm_struct.tm_hour = iHour; a_tm_struct.tm_min = iMinute; a_tm_struct.tm_sec = iSecond; //time_t mktime( struct tm * ptm ); //time_t xy = mktime(&a_tm_struct); return (int) mktime(&a_tm_struct); } int Now() { /* time_t now = time(NULL); char szTime[100] ; sprintf(szTime, "%d", (int) now); printf("Time: %s\n", szTime); */ return (int) time(NULL); } // http://www.gamedev.net/community/forums/topic.asp?topic_id=399702 char* GetLocalTime(int iSequentialDate) { time_t tThisTime = (time_t) iSequentialDate; struct tm *ts; ts = localtime(&tThisTime); //ts = gmtime ( &tThisTime ); char* szBuffer = (char*) malloc(80 * sizeof(char)); //strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts); strftime(szBuffer, 80, "%A %d.%m.%Y %H:%M:%S %Z", ts); Debug_Printf("%s\n", szBuffer); return szBuffer; } // apt-get install mailutils // apt-get install sendemail void SendMail() { char szHostname[128]; gethostname(szHostname, sizeof szHostname); Debug_Printf("Current hostname: %s\n", szHostname); // /usr/bin/mail ~'TEST' -s 'MailMngr Message' -t '[email protected]' //sendemail -f powerfail.hostname@localhost -t [email protected] -u "subj" -m "hello" -s "smtp.example.com" char* szMailCommand = (char*) malloc(1000* sizeof(char)); char szSender[250] ; sprintf(szSender, "powerfail.%s@localhost", szHostname); char szReceiver[] = "[email protected]"; char szSubject[] = "Power-failure"; char* szCurrentTime = GetLocalTime(Now()); char* szMessage = (char*) malloc(1000); sprintf(szMessage, "Your humble server has suffered a fatal powerfailure and recovered now (%s).", szCurrentTime); char szServer[] = "smtp.example.com"; sprintf(szMailCommand, "sendemail -f %s -t %s -u \"%s\" -m \"%s\" -s \"%s\"", szSender, szReceiver, szSubject, szMessage, szServer); free(szCurrentTime); free(szMessage); Debug_Printf("szMailCommand: %s\n", szMailCommand); FILE* mFile = popen(szMailCommand, "w"); pclose(mFile); free(szMailCommand); } int OnStartup() { Debug_Printf("Entering OnStartup.\n"); sqlite3 *handle; int iSQLconnectionError = sqlite3_open("PowerlossDetectionDB.sqlite3", &handle); if(iSQLconnectionError) { // If connection failed, handle returns NULL Debug_Printf("Database connection failed\n"); return -1; } Debug_Printf("Connection successful\n"); char szCreateTableStatement[] = "CREATE TABLE IF NOT EXISTS T_StartStopLog (SSL_Session_UID INTEGER PRIMARY KEY, SSL_StartTime INTEGER NOT NULL, SSL_StopTime INTEGER)"; ExecuteNonQuery(szCreateTableStatement, handle); int iLastStartupEntry = GetScalarInt("SELECT MAX(SSL_StartTime) FROM T_StartStopLog", handle); if(iLastStartupEntry!= 0) { char* szLastStartupTime = GetLocalTime(iLastStartupEntry); printf("Last startup-date:\t%s\n", szLastStartupTime); free(szLastStartupTime); } else printf("This is the first-time startup with PowerFailure tracking!\n"); char* szQuery = (char*) malloc(1000* sizeof(char)); sprintf(szQuery, "SELECT SSL_Session_UID FROM T_StartStopLog WHERE SSL_StartTime = %d", iLastStartupEntry); int iLastSession = GetScalarInt(szQuery, handle); Debug_Printf("Last session: %d\n", iLastSession); sprintf(szQuery, "SELECT SSL_StopTime FROM T_StartStopLog WHERE SSL_Session_UID = %d", iLastSession); int iLastShutdownEntry = GetScalarInt(szQuery, handle); free(szQuery); if(iLastSession != 0) { if(iLastShutdownEntry == 0) { Debug_Printf("Sending powerfail notification.\n"); SendMail(); Debug_Printf("Powerfail notification sent.\n"); } else { char* szLastShutdownTime = GetLocalTime(iLastShutdownEntry); printf("Last shutdown-date:\t%s\n", szLastShutdownTime); free(szLastShutdownTime); } } char szInsertStatement[1000]; int iUID = ++iLastSession; Debug_Printf("iUID: %d\n", iUID); if(iUID != 0) { sprintf(szInsertStatement, "INSERT INTO T_StartStopLog VALUES(%d, %d, NULL)", iUID, Now()); ExecuteNonQuery(szInsertStatement, handle); } else Debug_Printf("Error, last UID could not be determined..."); if(!iSQLconnectionError) sqlite3_close(handle); else Debug_Printf("Not closing connection.\n"); Debug_Printf("Exiting OnStartup.\n"); return EXIT_SUCCESS; } int OnShutDown(int bSimulatePowerFail) { Debug_Printf("Entering OnShutDown.\n"); sqlite3 *handle; int iSQLconnectionError = sqlite3_open("PowerlossDetectionDB.sqlite3",&handle); if(iSQLconnectionError) { // If connection failed, handle returns NULL Debug_Printf("Database connection failed\n"); return -1; } Debug_Printf("Connection successful\n"); char szInsertStatement[1000]; int iUID = GetScalarInt("SELECT MAX(SSL_Session_UID) FROM T_StartStopLog", handle); if(iUID == -1) { Debug_Printf("Error, last UID could not be determined..."); if(!iSQLconnectionError) sqlite3_close(handle); return EXIT_FAILURE; } if(!bSimulatePowerFail) { sprintf(szInsertStatement, "UPDATE T_StartStopLog SET SSL_StopTime = %d WHERE SSL_Session_UID = %d", Now(), iUID); ExecuteNonQuery(szInsertStatement, handle); } else Debug_Printf("Simulated power failure !\n"); if(!iSQLconnectionError) sqlite3_close(handle); else Debug_Printf("Not closing connection.\n"); Debug_Printf("Exiting OnShutDown.\n"); return EXIT_SUCCESS; } int Clear() { Debug_Printf("Entering Clear.\n"); sqlite3 *handle; int iSQLconnectionError = sqlite3_open("PowerlossDetectionDB.sqlite3",&handle); if(iSQLconnectionError) { // If connection failed, handle returns NULL Debug_Printf("Database connection failed\n"); return EXIT_FAILURE; } Debug_Printf("Connection successful\n"); ClearTable("T_StartStopLog", handle); if(!iSQLconnectionError) sqlite3_close(handle); else Debug_Printf("Not closing connection.\n"); Debug_Printf("Exiting Clear.\n"); return EXIT_SUCCESS; } int List() { Debug_Printf("Entering List.\n"); sqlite3 *handle; int iSQLconnectionError = sqlite3_open("PowerlossDetectionDB.sqlite3",&handle); if(iSQLconnectionError) { // If connection failed, handle returns NULL Debug_Printf("Database connection failed\n"); return EXIT_FAILURE; } Debug_Printf("Connection successful\n"); SelectFromTable("T_StartStopLog", handle); if(!iSQLconnectionError) sqlite3_close(handle); else Debug_Printf("Not closing connection.\n"); Debug_Printf("Exiting List.\n"); return EXIT_SUCCESS; } int SwitchArgs(int argc, char* argv[]) { int i; for(i=0; i < argc; ++i) { if(i==0) continue; Debug_Printf("argv[%d] = %s\n", i, argv[i]); char* szThisArgument = ToLower(argv[i]); Debug_Printf("szThisArgument: %s\n", szThisArgument); if(!strcmp(szThisArgument, "--debug")) { Debug_Printf("Debug requested...\n"); bDebug = 1; free(szThisArgument); continue; } else if(!strcmp(szThisArgument, "-dg")) { Debug_Printf("Debug requested...\n"); bDebug = 1; free(szThisArgument); continue; } if(!strcmp(szThisArgument, "-shutdown")) { Debug_Printf("Shutdown requested...\n"); bShutdownRequested = 1; bStartupRequested = 0; free(szThisArgument); continue; } else if(!strcmp(szThisArgument, "-d")) { Debug_Printf("Shutdown requested...\n"); bShutdownRequested = 1; bStartupRequested = 0; free(szThisArgument); continue; } if(!strcmp(szThisArgument, "-s")) { Debug_Printf("Startup requested...\n"); bStartupRequested = 1; free(szThisArgument); continue; } else if(!strcmp(szThisArgument, "--startup")) { Debug_Printf("Startup requested...\n"); bStartupRequested = 1; free(szThisArgument); continue; } if(!strcmp(szThisArgument, "-s")) { Debug_Printf("Powerfail-simulation requested...\n"); bSimulatePowerFailure = 1; free(szThisArgument); continue; } else if(!strcmp(szThisArgument, "--simulate")) { Debug_Printf("Powerfail-simulation requested...\n"); bSimulatePowerFailure = 1; free(szThisArgument); continue; } if(!strcmp(szThisArgument, "-l")) { Debug_Printf("List requested...\n"); bList = 1; free(szThisArgument); continue; } else if(!strcmp(szThisArgument, "--list")) { Debug_Printf("List requested...\n"); bList = 1; free(szThisArgument); continue; } if(!strcmp(szThisArgument, "-c")) { Debug_Printf("Clear requested...\n"); bClear = 1; free(szThisArgument); continue; } else if(!strcmp(szThisArgument, "--clear")) { Debug_Printf("Clear requested...\n"); bClear = 1; free(szThisArgument); continue; } if(!strcmp(szThisArgument, "-t")) { Debug_Printf("Testmail requested...\n"); bTestMail = 1; free(szThisArgument); continue; } else if(!strcmp(szThisArgument, "--testmail")) { Debug_Printf("Testmail requested...\n"); bTestMail = 1; free(szThisArgument); continue; } printf("Usage error: Argument %s is not a valid argument.\nTerminating program.\n\n", szThisArgument); free(szThisArgument); return EXIT_FAILURE; } return EXIT_SUCCESS; } int main(int argc, char* argv[]) { SwitchArgs(argc, argv); /* int iSeqDate = GetSequentialDate(31, 12, 2010, 23, 59, 59); char* szDate = GetLocalTime(iSeqDate); printf("Sequential date: %s\n", szDate); time_t result = time(NULL); printf("%s%ju secs since the Epoch\n", asctime(localtime(&result)), (uintmax_t) result); */ if(bTestMail) { SendMail(); return EXIT_SUCCESS; } if(bClear) { Debug_Printf("Calling Clear\n"); Clear(); } if(bStartupRequested) { Debug_Printf("Calling OnStartup\n"); OnStartup(); } if(bShutdownRequested) { Debug_Printf("Calling OnShutDown\n"); OnShutDown(bSimulatePowerFailure); } if(bList) { Debug_Printf("Calling List\n"); List(); } Debug_Printf("Powerfail notification finished !\n"); return EXIT_SUCCESS; } 

已经有一个在/etc/rc.d/local运行本地命令的启动脚本。 你可以在那里添加一行执行你的程序。

如果脚本需要启动/closures/重新启动function,则可以将自己的脚本添加到/etc/init.d 。 首先看看现有的脚本,找出如何指定依赖关系。 创build脚本后,可以使用update-rc将其添加到给定的运行级别。

你可以在启动和closures的时候用适当的参数从initscript调用它。