如何防止Linux程序多次运行?

发布于 2024-09-19 08:08:23 字数 41 浏览 4 评论 0原文

防止 Linux 程序/守护进程在给定时间执行多次的最佳方法是什么?

What is the best way to prevent a Linux program/daemon from being executed more than once at a given time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

能否归途做我良人 2024-09-26 08:08:23

最常见的方法是创建 PID 文件:定义文件所在的位置(常见的是 /var/run 内)。成功启动后,您会将 PID 写入此文件。在决定是否启动时,读取文件并检查以确保引用的进程不存在(或者如果存在,则它不是守护进程的实例:在 Linux 上,您可以查看 /proc /$PID/exe)。关闭时,您可以删除该文件,但这并不是绝对必要的。

有一些脚本可以帮助您执行此操作,您可能会发现 start-stop-daemon 很有用:它可以使用 PID 文件,甚至只是全局检查可执行文件是否存在。它是专门为这项任务而设计的,旨在帮助人们正确完成任务。

The most common way is to create a PID file: define a location where the file will go (inside /var/run is common). On successful startup, you'll write your PID to this file. When deciding whether to start up, read the file and check to make sure that the referenced process doesn't exist (or if it does, that it's not an instance of your daemon: on Linux, you can look at /proc/$PID/exe). On shutdown, you may remove the file but it's not strictly necessary.

There are scripts to help you do this, you may find start-stop-daemon to be useful: it can use PID files or even just check globally for the existence of an executable. It's designed precisely for this task and was written to help people get it right.

給妳壹絲溫柔 2024-09-26 08:08:23

使用 boost 进程间库 创建一个内存块将由该过程创建。如果它已经存在,则意味着该进程还有另一个实例。出口。

到您需要的内容的更精确链接是 这个

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/scoped_ptr.hpp>

int main()
{
  using boost::interprocess;
  boost::scoped_ptr<shared_memory_object> createSharedMemoryOrDie;
  try
  {
     createSharedMemoryOrDie.reset( 
       new shared_memory_object(create_only, "shared_memory", read_write));
  } catch(...)
  {
     // executable is already running
     return 1; 
  }

  // do your thing here
}

Use the boost interprocess library to create a memory block that will be created by the process. If it already exists, it means that there is another instance of the process. Exit.

The more precise link to what you need would be this one.

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/scoped_ptr.hpp>

int main()
{
  using boost::interprocess;
  boost::scoped_ptr<shared_memory_object> createSharedMemoryOrDie;
  try
  {
     createSharedMemoryOrDie.reset( 
       new shared_memory_object(create_only, "shared_memory", read_write));
  } catch(...)
  {
     // executable is already running
     return 1; 
  }

  // do your thing here
}
莫多说 2024-09-26 08:08:23

如果您有权访问代码(即正在编写代码):

  • 创建一个临时文件,锁定它,完成后删除,返回1;如果文件存在,或者
  • 列出进程,返回1 ; 如果进程名称在列表中

如果没有:

  • 为执行上述操作之一的程序创建一个启动器包装器

If you have access to the code (i.e. are writing it):

  • create a temporary file, lock it, remove when done, return 1; if file exists, or,
  • list processes, return 1; if the process name is in the list

If you don't:

  • create a launcher wrapper to the program that does one of the above
遇到 2024-09-26 08:08:23

我认为这个方案应该有效(并且对于崩溃也很有效):
前提条件:您的应用程序有一个 PID 文件(通常位于 /var/run/ 中)
1.尝试打开PID文件
2. 如果不存在,请创建它并将您的 PID 写入其中。继续程序的其余部分
3.如果存在,读取PID
4. 如果 PID 仍在运行并且是您的程序的实例,则退出
5. 如果 PID 不存在或被其他程序使用,请删除 PID 文件并转到步骤 2。
6. 程序终止时,删除PID 文件。

步骤5 中的循环可确保如果同时启动两个实例,最终只有一个实例运行。

I think this scheme should work (and is also robust against crashes):
Precondition: There is a PID file for your application (typically in /var/run/)
1. Try to open the PID file
2. If it does not exist, create it and write your PID to it. Continue with the rest of the program
3. If it exist, read the PID
4. If the PID is still running and is an instance of your program, then exit
5. If the PID does not exist or is used by another program, remove the PID file and go to step 2.
6. At program termination, remove the PID file.

The loop in step 5 ensures that, if two instances are started at the same time, only one will be running in the end.

┼── 2024-09-26 08:08:23

我不知道你的具体要求是什么,但我有类似的要求;在这种情况下,我从 Shell 脚本启动了我的守护进程(它是一台 HP-UX 机器),在启动守护进程之前,我检查了同名的 exec 是否已经在运行。如果是的话;然后就不要开始新的了。

通过这种方式,我还能够控制进程实例的数量。

I do not know what your exact requirement is but I had a similar requirement; in that case I started my daemon from a Shell script ( it was a HP-UX machine) and before starting the daemon I checked if an exec by same name is already running. If it is; then don't start a new one.

By this way I was also able control the number of instances of a process.

糖果控 2024-09-26 08:08:23

拥有一个 pid 文件,并在启动时执行 'kill -0'。从文件中读取的值在哪里。如果响应为 != 0,则守护进程不活动,您可以重新启动它。

另一种方法是绑定到端口并在第二次尝试启动守护进程时处理绑定异常。如果端口正在使用,则退出,否则继续运行守护程序。

Have a pid file and on the startup do a 'kill -0 <pid>'. Where is the value read from file. If the response is != 0 then the daemon is not alive and you might restart it

Another approach would be to bind to a port and handle the bind exception on the second attempt to start the daemon. If the port is in use then exit otherwise continue running the daemon.

蔚蓝源自深海 2024-09-26 08:08:23

我相信我的解决方案是最简单的:(

如果可能出现赛车状况,请不要使用它,但在任何其他情况下,这是一个简单且令人满意的解决方案)

#include <sys/types.h>
#include <unistd.h>
#include <sstream>

void main()
{
    // get this process pid
    pid_t pid = getpid();

    // compose a bash command that:
    //    check if another process with the same name as yours
    //    but with different pid is running
    std::stringstream command;
    command << "ps -eo pid,comm | grep <process name> | grep -v " << pid;
    int isRuning = system(command.str().c_str());
    if (isRuning == 0) {
        cout << "Another process already running. exiting." << endl;
        return 1;
    }
    return 0;
}

I believe my solution is the simplest:

(don't use it if racing condition is a possible scenario, but on any other case this is a simple and satisfying solution)

#include <sys/types.h>
#include <unistd.h>
#include <sstream>

void main()
{
    // get this process pid
    pid_t pid = getpid();

    // compose a bash command that:
    //    check if another process with the same name as yours
    //    but with different pid is running
    std::stringstream command;
    command << "ps -eo pid,comm | grep <process name> | grep -v " << pid;
    int isRuning = system(command.str().c_str());
    if (isRuning == 0) {
        cout << "Another process already running. exiting." << endl;
        return 1;
    }
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文