2017-06-02 9 views
2

Ich habe eine geänderte Klasse verwendet, die ich gefunden habe, um zu überprüfen, ob eine andere Instanz des gleichen Prozesses bereits ausgeführt wird. Das Problem besteht darin, dass die Methode zur Überprüfung des Prozesses eine weitere Instanz desselben Prozesses hinzufügt.Wie überprüft man, ob der Prozess auf Red Hat Linux läuft?

Wenn meine Anwendung startet, wird ein neuer Prozess-ID erstellt und ist sichtbar mit:

ps -A | grep "AppName" 

Damit erhalte ich ein seit Eintrag zurückgekehrt, überprüfe ich dann für eine andere Instanz der Anwendung mit:

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; 
} 

Sobald die ‚Start‘ Methode eine andere Instanz derselben Anwendung in der Prozesstabelle wieder, verifiziert genannt wird angezeigt wird, mit:

ps -A | grep "AppName" 

Es erscheinen nun zwei Einträge mit jeweils einer anderen PID. Ich habe auch versucht:

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

Das Ergebnis ist das gleiche, zwei Einträge in der Prozesstabelle.

Gibt es eine Möglichkeit, die Prozesstabelle für eine andere Instanz zu überprüfen, ohne eine zusätzliche Instanz hinzuzufügen?

+0

Es gibt keine Möglichkeit zu sehen, ob eine bestimmte ausführbare Datei läuft, von innerhalb der spezifischen ausführbaren Datei selbst, nicht ohne tatsächlich die ausführbare Datei zu laden und auszuführen. Stattdessen empfehle ich Ihnen, eine Art Dateisperre für eine bestimmte Datei zu verwenden. Wenn die Datei gesperrt ist, läuft das Programm und Sie tun, was Sie tun müssen. Wenn es nicht gesperrt ist, sperren Sie es und fahren fort. Oder vielleicht ein gemeinsamer Semaphor oder etwas Ähnliches. –

+0

Das Problem mit dieser Methode ist, dass, wenn die Datei gesperrt ist und es dann ein Problem mit der ausführbaren Datei gibt, ein Watchdog den Prozess auch nicht neu starten kann. – SPlatten

+0

Wie wäre es mit einer PID-Datei? Eine Datei, deren Inhalt die PID des laufenden Prozesses ist? Wenn es vorhanden ist und die PID vorhanden ist und mit der ausführbaren Datei übereinstimmt, wird der Prozess ausgeführt. Wenn die Datei nicht existiert oder die PID nicht existiert oder existiert, aber nicht mit der ausführbaren Datei übereinstimmt, wird das Programm nicht ausgeführt und Sie überschreiben die PID-Datei. Funktioniert gut mit einem Watchdog, der denselben Check durchführt. –

Antwort

0

Ich empfehle die Verwendung einer PID-Datei. Es ist das Standardverfahren für Daemons unter 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; 
} 

Quelle Die Linux Programming Interface

Dies erzeugt eine Datei und sperrt es so kein anderer Prozess öffnen kann. Es wird beim Beenden als so nah angezeigt, dass die Datei geschlossen wird, wenn der Prozess durch normale oder abnormale Beendigung beendet wird. Wenn eine Instanz Ihres Programms bereits ausgeführt wird, schlägt diese Funktion fehl und Sie können einfach beenden.

EDIT: Die PID-Datei sollte in der temporären Partition sein. Der spezifische Standort hängt von Ihrer Distribution ab. Sehen Sie sich einfach Ihr System an, wo andere Daemons ihre PID-Dateien erstellen.

+0

Auf Redhat befinden sich PID-Dateien normalerweise in '/ var/run'. 'tmpwatch' kann Ihre Pidfile löschen, wenn Sie es in/tmp einfügen. – stark

0

Ich glaube, Sie versuchen zu validieren, dass nur "eine" Instanz Ihrer Anwendung auf einmal ausgeführt werden kann.

Um dies zu erreichen, benötigen Sie etwas wie QtSingleApplication.

Eine andere Alternative, d. H. SingleApplication.

+0

Es wäre toll, wenn es aus der Box funktioniert, aber leider gerade heruntergeladen und versucht es, es scheint nicht und scheint nicht fertig zu sein ... Ich habe nicht die Zeit, das zu beheben, wird mit meinem eigenen weitermachen . – SPlatten

+0

Hast du dieses Tutorial überprüft (https://www.youtube.com/watch?v=mKNovzcQMww)? Wenn nicht, glaube ich, dass es Ihnen bei Ihrer eigenen Implementierung helfen wird. – Azeem

+0

Entschuldigung ,, Ich habe keine Zeit, um auf Tangenten zu gehen und Fixes für etwas zu erforschen, das nicht out of the box funktioniert. – SPlatten

0

Die eigentliche Lösung, die ich verwendet, die ich selbst geschrieben habe, Prototyp: 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); 
}; 

Implementierung, 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(); 
     } 
    } 
Verwandte Themen