如何检查 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();
}
}
我一直在使用修改后的 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();
}
}