2017-06-02 230 views
2

我一直在使用我发现的修改后的类来检查同一进程的另一个实例是否已在运行,问题是检查进程的方法是否会添加同一进程的另一个实例。如何检查进程是否在Red Hat Linux上运行?

当我的应用程序启动时,一个新的进程ID被创建并可见有:

ps -A | grep "AppName" 

有了这个,我得到一个在入境回来,我再检查应用程序的另一个实例使用:

QString strCMD = "ps -A | grep \"" + mcstrAppName + "\""; 
QProcess objProc; 
objProc.start("bash", QStringList() << "-c" << strCMD); 

if (objProc.waitForStarted() != true || objProc.waitForFinished() != true) { 
    mcpobjApp->exit(cleanExit(-1, "Unable to determine if another instance is running!")); 
    return; 
} 

只要“开始”方法被调用同一应用程序的另一个实例出现在进程表,再次与验证:

ps -A | grep "AppName" 

现在两个条目分别显示不同的PID。我也试过了:

QString strOptions = "-A | grep \"" + mcstrAppName + "\""; 
QProcess objProc; 
objProc.start("ps", QStringList() << strOptions); 

结果是一样的,两个条目在进程表中。

有没有办法检查另一个实例的进程表而不添加额外的实例?

+0

有没有看到,如果一个特定的可执行文件的方式从特定的可执行文件本身内部运行,而不是实际加载和运行可执行文件。相反,我建议你在特定文件上使用某种文件锁。如果文件被锁定,那么程序正在运行,你可以做任何你需要做的事情。如果没有锁定,则锁定并继续。或者也许是一个共享的信号灯或类似的东西。 –

+0

该方法的问题是,如果文件被锁定,然后可执行文件存在问题,则看门狗无法重新启动该进程。 – SPlatten

+0

PID文件如何?内容是正在运行的进程的PID的文件?如果它存在并且PID存在且与可执行文件匹配,则该进程正在运行。如果文件不存在,或者PID不存在,或者它存在但是与可执行文件不匹配,那么程序没有运行,并且您覆盖了PID文件。与同样检查的监督员一起工作良好。 –

回答

0

我建议使用pid文件。这是linux上的守护进程的标准程序。

int createPidFile(const char *pidFile, int flags) 
{ 
    int fd; 
    char buf[BUF_SIZE]; 
    fd = open(pidFile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 
    if (fd == -1) 
     errExit("Could not open PID file %s", pidFile); 
    if (flags & CPF_CLOEXEC) 
    { 
     /* Set the close-on-exec file descriptor flag */ 
     flags = fcntl(fd, F_GETFD); /* Fetch flags */ 
     if (flags == -1) 
      errExit("Could not get flags for PID file %s", pidFile); 
     flags |= FD_CLOEXEC; /* Turn on FD_CLOEXEC */ 
     if (fcntl(fd, F_SETFD, flags) == -1) /* Update flags */ 
      errExit("Could not set flags for PID file %s", pidFile); 
    } 
    return fd; 
} 

来源Linux的编程接口

这将创建一个文件,并锁定它,以便没有其他进程可以打开它。它在退出时将其标记为关闭,以便当进程通过正常或异常终止退出时文件将关闭。如果程序的一个实例已经运行,这个函数将失败,你可以退出。

编辑: 该pid文件应该在临时分区。具体位置根据您的发行版而不同,请在您的系统上查看其他守护进程创建其pid文件的位置。

+0

在Redhat上,pid文件通常在'/ var/run'中。如果你把它放在/ tmp中,'tmpwatch'可以删除你的pidfile。 – stark

0

我相信你正试图验证你的应用程序只有“一个”实例可能一次执行。

要达到此目的,您需要诸如QtSingleApplication之类的东西。

另一种替代方案,即SingleApplication

+0

如果它开箱即用会很好,但不幸的是刚刚下载并尝试过它,它并没有看起来没有完成......我没有时间来解决这个问题,将继续我自己的。 – SPlatten

+0

您是否检查过本教程(https://www.youtube.com/watch?v=mKNovzcQMww)?如果没有,我相信它会帮助你实现自己。 – Azeem

+0

对不起,我没有时间去切线,并探索一些无法使用的东西。 – SPlatten

0

我实际使用的解决方案,我写我自己,原型:clsSingleInstance.h:

class clsSingleInstance : public QObject { 
Q_OBJECT 

public: 
    explicit clsSingleInstance(const QString& strAppName, QApplication* pobjApp); 

public slots: 
    void check(); 

private: 
    const int mcintDelay = 3000; 
    const QString mcstrAppName; 

    qint64 mint64PID; 
    QApplication const* mcpobjApp; 
    QTimer* mptmrCheck; 

    Q_DISABLE_COPY(clsSingleInstance); 
}; 

实施,clsSingleInstance.cpp:

#include "clsSingleInstance.h" 
    /** 
    * @brief clsSingleInstance::clsSingleInstance 
    * @param strAppName : The application name as it will appear in the process list 
    * @param pobjApp : Pointer to the applicaiton instance 
    */ 
    clsSingleInstance::clsSingleInstance(const QString& strAppName 
             ,QApplication* pobjApp) 
             :QObject(pobjApp) 
             ,mcstrAppName(strAppName) 
             ,mcpobjApp(pobjApp) { 
    //Save the process ID 
     mint64PID = mcpobjApp->applicationPid(); 
    //Run check now to determine if another instance is running 
     check(); 
    //Set-up timer to check for another instance regularly 
     mptmrCheck = new QTimer(this); 

     if (mptmrCheck != NULL) { 
      connect(mptmrCheck, SIGNAL(timeout()), this, SLOT(check())); 
      mptmrCheck->start(mcintDelay); 
     } 
    } 
    /** 
    * @brief clsSingleInstance::check 
    * Checks application instances running 
    */ 
    void clsSingleInstance::check() { 
     const QString cstrCheckFile = clsMainWin::mcszConfigPath 
             + mcstrAppName + ".pid"; 
     QFile objPID(cstrCheckFile); 

     if (objPID.exists() == true) { 
    //Check the file date/time stamp 
      QDateTime dtCreated = QFileInfo(cstrCheckFile).created() 
        ,dtNow = QDateTime::currentDateTime(); 
      qint64 int64Created = dtCreated.toMSecsSinceEpoch() 
        ,int64Now = dtNow.toMSecsSinceEpoch() 
        ,int64Diff = int64Now - int64Created; 
    //Is the file current and being updated? 
      if (int64Diff < (mcintDelay * 2)) { 
    //PID file is live, read it 
       if (objPID.open(QIODevice::ReadOnly) == true) { 
    //PID file exists, it should only contain a single ID 
        QByteArray arybytContent = objPID.readAll(); 
        QString strContent = arybytContent.trimmed(); 
        objPID.close(); 

        if (strContent.toLongLong() != mint64PID) { 
         qInfo("Another instance already present..."); 
         exit(EXIT_FAILURE); 
        } 
       } 
      } 
     } 
    //Create/update PID file 
     if (objPID.open(QIODevice::WriteOnly) == true) { 
      QString strPID = QString::number(mint64PID); 
      objPID.write(strPID.toLatin1()); 
      objPID.close(); 
     } 
    } 
相关问题