如何检查 Red Hat Linux 上的进程是否为 运行?

How to check if process is running on Red Hat Linux?

我一直在使用修改后的 class 我发现检查同一进程的另一个实例是否已经 运行,问题是检查进程的方法添加了另一个实例相同的过程。

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

ps -A | grep "AppName"

有了这个,我得到了一个 since 返回的条目,然后我使用以下方法检查应用程序的另一个实例:

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

一旦调用 'start' 方法,同一应用程序的另一个实例就会出现在进程 table 中,再次验证:

ps -A | grep "AppName"

现在出现了两个条目,每个条目都有不同的 PID。我也试过:

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

结果相同,两个条目在处理 table。

有没有办法在不添加额外实例的情况下检查另一个实例的进程 table?

我建议使用 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 文件的位置即可。

我实际使用的方案,自己写的,原型: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();
        }
    }