2017-06-02 145 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(); 
     } 
    } 
相關問題