公共看门狗程序

32 篇文章 14 订阅
15 篇文章 0 订阅
本文介绍了一种用于预防程序死锁的看门狗程序,能在Linux和Windows环境中实时监控进程状态,定期启动、检查响应并处理无响应情况,包括重启系统。使用了Qt的QTimer进行毫秒级监控,并展示了配置文件读取、命令执行及错误处理的相关代码段。
摘要由CSDN通过智能技术生成

概述

一些重要的程序,必须让它一直跑着;而且还要时时关心它的状态——不能让它出现死锁现象。当然,如果一个主程序会出现死锁,肯定是设计或者编程上的失误。我们首要做的事是,把这个Bug揪出来。但如果时间紧迫,这个Bug又“飘忽不定”,那么,我们还是先写一个软件“看门狗”,暂时应一下急吧。

“看门狗”的需求描述:“看门狗”的运行不出现界面窗口,具有一定的隐蔽性;定时判断目标进程是否运行在当前系统中,如果没有则启动目标进程;判断目标进程是否“没有响应”,如果是则终止目标进程;如果目标进程“没有响应”的次数超过一定的数量,则将计算机系统重启。

公共看门狗程序:
1、公共的制定一条规则,使用者根据规则写入配置文件,程序根据配置文件进行读取分析
2、可以部署在任意一台程序上,每毫秒检测程序进程是否存在,不存在的时候拉起程序。在这里插入图片描述

一、区分__linux__ 还是 __WIN32

void excuteorder::Getps()
{
    //#ifdef  __linux_
        CIniFile iniFile = CIniFile(QCoreApplication::applicationDirPath()+ CNEEDLEWATCHDOG);
        QString strSLBPort = iniFile.GetValue("demon", "SLBHPort");
        qDebug()<<"strSLBPort"<<strSLBPort;
        char cmd[128] = {0};
        sprintf(cmd, "ps -aux | grep 'aaa' | grep -v grep | wc -l");
        QString str = ExcuteCmd(cmd);
        qDebug()<<"str:"<<str;
        if ( str.toInt() <= 1 )
        {
            qDebug()<<"start";
            char ExcuteProcedureCMD[128] = {0};
            sprintf(ExcuteProcedureCMD, "cd /home/lky/Documents/aaa/binl && ./aaa &");  //执行程序命令
            QString result = ExcuteCmd(ExcuteProcedureCMD);
            qDebug()<<"result:"<<result;
        } else
        {
            qDebug()<<"no need";
            /***endl***/
        }

    //#elif _WIN32
        //qDebug()<<"Configuring on/for Windows";
    //#endif
}

二、监控要做到毫秒级别,Qt使用QTimer类来实现。(QTimer最小时间单位是毫秒)

    QTimer* mTimer = new QTimer(this);
    connect(mTimer,SIGNAL(timeout()),this,SLOT(Getps()));
    mTimer->start(1000);

每毫秒会回调Getps()这个函数。

三、然后就是程序运行Linux命令的接口,会返回命令的result

QString excuteorder::ExcuteCmd(QString Cmd)
{
    QString str;
    char line[512] = {0};
    FILE *pFile = popen(Cmd.toStdString().c_str(), "r");
    if(pFile == NULL)
    {
        return "";
    }
    while(fgets(line, sizeof(line), pFile)){
        RemoveSpecialChar("\n", line);
        str = line;
        break;
    }
    pclose(pFile);
    if(strlen(line) <= 0)
    {
        return "";
    }
    return str;
}

int excuteorder::RemoveSpecialChar(const char *SpeChar, char *src)
{
    int i,j,m,k;
    int intSpeCharLen = strlen(SpeChar);
    int intSrcLen     = strlen(src);
    for(i = 0; i < intSpeCharLen; i++){//有几个特特殊字符
        int intSpeCharNum = 0;
        for(j = 0;j < intSrcLen; j++){//遍历源串中某一特殊字符的个数
            if(SpeChar[i]== src[j]){
                    intSpeCharNum ++;
            }
        }
        for(j = 0;j < intSpeCharNum; j++){//遍历去除所有某一个字符
            for(m = 0; m < intSrcLen ; m++){//从源串中查找特殊字符
                if(SpeChar[i]== src[m]){
                    for(k = m; k < intSrcLen; k++){//查找到某一个特殊字符后面的字符一次向前移动
                         src[k] = src[k+1];
                    }
                    intSrcLen--;
                    break;
                }
            }
        }
    }
    return 0;
}

调用ExcuteCmd接口拼接要执行的命令就能返回结果了。
然后还有一块要读取配置文件的。因为要做成公共,所以程序放到任意一台其他的服务器上,只要根据规定的规则写道ini,程序就会识别。只需要导入已经成熟的Qt读写配置文件

#ifndef CINIFILE_H
#define CINIFILE_H
#include "CComm.h"
#include <QSettings>
class CIniFile
{
public:
    CIniFile(QString Path);
    virtual ~CIniFile();
    //向ini文件指定块中写key和value
    int SetValue(QString Block, QString Key, QString Value);
    //获取ini文件指定块中key和value
    QString GetValue(QString Block, QString Key, QString def = "");
	//设置编码格式,输入参数是 QTextCodec 支持的编码格式名称
    void setIniCodec(const char * CodecName);

private:
    QSettings         *m_IniFile;
};

#endif // CINIFILE_H

#include "CIniFile.h"

CIniFile::CIniFile(QString Path)
{
    m_IniFile = new  QSettings(Path, QSettings::IniFormat);
}

CIniFile::~CIniFile()
{
    if(m_IniFile != NULL){
        delete m_IniFile;
    }
}

/**
 * @brief CIniFile::SetValue
 *        向ini文件指定块中写key和value
 * @param Block 块名称
 * @param Key key名称
 * @param Value value值
 * @return 0 success
 */
int CIniFile::SetValue(QString Block, QString Key, QString Value)
{
    QString strLink = "/";
    m_IniFile->setValue(Block + strLink+Key, Value);
    return SUCCESS;
}

/**
 * @brief CIniFile::GetValue
 *        获取ini文件指定块中key和value
 * @param Block 块名称
 * @param Key key名称
 * @return 返回value值
 */
QString CIniFile::GetValue(QString Block, QString Key, QString def)
{
    QString strLink = "/";
    QString strRes = m_IniFile->value(Block + strLink + Key).toString();
    if(strRes.length() <= 0){
        strRes = def;
    }
    return strRes;
}

void CIniFile::setIniCodec(const char *CodecName)
{
    m_IniFile->setIniCodec(CodecName);
}

举例这个就是读取配置文件内容的规则

CIniFile iniFile = CIniFile(QCoreApplication::applicationDirPath()+ CNEEDLEWATCHDOG);
QString strSLBPort = iniFile.GetValue("demon", "SLBHPort");

配置内容
在这里插入图片描述

/---------------------------------以下是程序写入Linux命令的接口【命令带拼接的参数】---------------------------------/

/**
 * @brief CDevicesManagerDView::ExcuteCmdList
 *        执行shell指令 返回多行
 * @param Cmd  shell指令
 * @param strList 返回信息列表
 * @return 0 success  -1202 到 -1301 err
 */
int CNeedleDemon::ExcuteCmdList(QString Cmd, QStringList& strList)
{
    log_debug("@@@ ExcuteCmdList start Cmd:%s", Cmd.toStdString().c_str());
    char line[512] = {0};
    FILE *pFile = popen(Cmd.toStdString().c_str(), "r");
    if(pFile == NULL){
        log_error("fopen Cmd:%s failed!", Cmd.toStdString().c_str());
        return CNSTREAMSER_EXCUTECMDLIST_EXCUTEFAILED;
    }
    while(fgets(line, sizeof(line), pFile)){
        RemoveSpecialChar("\n", line);
        strList.append(line);
    }
    if(strList.count() <= 0){
        return CNSTREAMSER_EXCUTECMDLIST_RESULTNULL;
    }
    log_debug("@@@ ExcuteCmdList end");
    return SUCCESS;
}

//字符串中去除特殊字符函数
int CNeedleDemon::RemoveSpecialChar(const char *SpeChar, char* src)
{
    int i,j,m,k;
    int intSpeCharLen = strlen(SpeChar);
    int intSrcLen     = strlen(src);
    for(i = 0; i < intSpeCharLen; i++){//有几个特特殊字符
        int intSpeCharNum = 0;
        for(j = 0;j < intSrcLen; j++){//遍历源串中某一特殊字符的个数
            if(SpeChar[i]== src[j]){
                    intSpeCharNum ++;
            }
        }
        for(j = 0;j < intSpeCharNum; j++){//遍历去除所有某一个字符
            for(m = 0; m < intSrcLen ; m++){//从源串中查找特殊字符
                if(SpeChar[i]== src[m]){
                    for(k = m; k < intSrcLen; k++){//查找到某一个特殊字符后面的字符一次向前移动
                         src[k] = src[k+1];
                    }
                    intSrcLen--;
                    break;
                }
            }
        }
    }
    return 0;
}

/---------------------------------以下是程序写入Linux命令的接口---------------------------------/

int CNeedleDemon::Excute(QString Cmd)
{
    printf("cmd:%s\n", Cmd.toStdString().c_str());
    FILE *pFile = popen(Cmd.toStdString().c_str(), "r");
    if(pFile == NULL){
        qDebug()<<"fopen "<< Cmd << " failed!";
        return -1;
    }
    pclose(pFile);
    return SUCCESS;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值