Как предотвратить запуск программы Linux более одного раза?

Каков наилучший способ предотвратить выполнение программой или демоном Linux более одного раза в данный момент?

Ответы

Ответ 1

Наиболее распространенным способом является создание PID файла: определение местоположения, в котором будет проходить файл (обычно внутри /var/run ). При успешном запуске вы напишете свой PID в этот файл. Когда вы решаете, запускать ли, прочитайте файл и убедитесь, что ссылочный процесс не существует (или если он делает это, а не экземпляр вашего демона: в Linux вы можете посмотреть /proc/$PID/exe). При выключении вы можете удалить файл, но это не обязательно.

Есть сценарии, которые помогут вам сделать это, вы можете найти start-stop-daemon полезным: он может использовать файлы PID или даже просто проверять глобальность на наличие исполняемого файла. Он был разработан именно для этой задачи и был написан, чтобы помочь людям понять это.

Ответ 2

Используйте увеличить библиотеку interprocess, чтобы создать блок памяти, который будет создан процессом. Если он уже существует, это означает, что есть еще один экземпляр процесса. Выход.

Более точная ссылка на то, что вам нужно, будет этот.

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

Ответ 3

Если у вас есть доступ к коду (т.е. пишут его):

  • создать временный файл, заблокировать его, удалить, когда закончите, return 1;, если файл существует, или
  • return 1;, если имя процесса находится в списке

Если вы этого не сделаете:

  • создайте оболочку пусковой установки для программы, которая делает одно из указанных выше

Ответ 4

Я не знаю, каково ваше точное требование, но у меня было аналогичное требование; в этом случае я запустил мой демон из Shell script (это был компьютер HP-UX), и перед запуском демона я проверил, работает ли exec с таким же именем. Если это; то не начинайте новый.

Таким образом, я также мог контролировать количество экземпляров процесса.

Ответ 5

Я думаю, что эта схема должна работать (и также устойчива к сбоям):
 Предварительное условие: для вашего приложения есть файл PID (обычно в /var/run/ )
 1. Попробуйте открыть файл PID
 2. Если он не существует, создайте его и напишите свой PID. Продолжайте работу с остальной частью программы
 3. Если он существует, прочитайте PID
 4. Если PID все еще запущен и является экземпляром вашей программы, выйдите
 5. Если PID не существует или используется другой программой, удалите файл PID и перейдите к шагу 2.
 6. При завершении программы удалите файл PID.

Цикл на шаге 5 гарантирует, что, если два экземпляра запускаются одновременно, в конце будет работать только один.

Ответ 6

Имейте pid файл и при запуске выполните 'kill -0 <pid>'. Где значение, считанное из файла. Если ответ равен!= 0, тогда демон не будет жив, и вы можете его перезапустить.

Другим подходом было бы привязать к порту и обработать исключение связывания во второй попытке запуска демона. Если порт используется, выйдите из него в противном случае, продолжите запуск демона.

Ответ 7

Я считаю, что мое решение является самым простым:

(не используйте его, если условие гонки является возможным сценарием, но в любом другом случае это простое и удовлетворяющее решение)

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