Гарантируйте единственный экземпляр приложения в Linux

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

33
задан Acumenus 1 March 2015 в 19:06
поделиться

10 ответов

Существует несколько общих методов включая использование семафоров. Тот, который я вижу используемый чаще всего, должен создавать "изодромный с предварением файл блокировки" на запуске, который содержит pid рабочего процесса. Если файл уже существует, когда программа запускает, откройте его и захватите pid внутри, проверьте, чтобы видеть, работает ли процесс с тем pid, если это - проверка значение cmdline в/proc / pid, чтобы видеть, является ли это экземпляр Вашей программы, если это затем завершено, иначе перезапишите файл со своим pid. Обычное название изодромного с предварением файла application_name.pid.

25
ответ дан 27 November 2019 в 17:23
поделиться

Правильной Вещью является консультативная блокировка с помощью flock(LOCK_EX); в Python это найдено в fcntl модуль .

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

, Если Вы хотите обнаружение небезопасного завершения работы, можно записать маркер (такой как PID, для традиционалистов) в файл после захвата блокировки, и затем усечь файл к 0-байтовому состоянию перед чистым завершением работы (в то время как блокировка сохранена); таким образом, если блокировка не сохранена, и файл непуст, небезопасное завершение работы обозначается.

60
ответ дан 27 November 2019 в 17:23
поделиться

Полное решение для блокировки с помощью fcntl модуль:

import fcntl
pid_file = 'program.pid'
fp = open(pid_file, 'w')
try:
    fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    # another instance is running
    sys.exit(1)
28
ответ дан 27 November 2019 в 17:23
поделиться

wxWidgets предлагает wxSingleInstanceChecker класс с этой целью: wxPython документ , или wxWidgets документ . wxWidgets документ имеет пример кода в C++, но эквивалентный Python должен быть что-то вроде этого (непротестированное):

  name = "MyApp-%s" % wx.GetUserId()
  checker = wx.SingleInstanceChecker(name)
  if checker.IsAnotherRunning():
      return False
8
ответ дан 27 November 2019 в 17:23
поделиться

Ищите модуль Python, который взаимодействует через интерфейс к семафорам SYSV на Unix. Семафоры имеют флаг SEM_UNDO, который заставит ресурсы, сохраненные процесс быть выпущенными, если процесс откажет.

Иначе как предложенный Bernard, можно использовать

import os
os.getpid()

И записать это в/var/run / application_name.pid. Когда процесс запускается, он должен проверить, перечислен ли pid в/var/run / application_name.pid в таблице PS и завершен, если это, иначе запишите ее собственный pid в/var/run / application_name.pid. В следующем var_run_pid pid, который Вы читаете из/var/run / application_name.pid

cmd = "ps -p %s -o comm=" % var_run_pid
app_name = os.popen(cmd).read().strip()
if len(app_name) > 0:
    Already running
1
ответ дан 27 November 2019 в 17:23
поделиться

набором функций, определяемых в semaphore.h - sem_open(), sem_trywait(), и т.д. - является эквивалентный POSIX, я верю.

1
ответ дан 27 November 2019 в 17:23
поделиться

Безусловно наиболее распространенный метод должен бросить файл в/var/run/, названный [приложением] .pid, который содержит только PID рабочего процесса или родительского процесса. Как альтернатива, можно создать именованный канал в том же каталоге, чтобы смочь отправить сообщения в активный процесс, например, открыть новый файл.

0
ответ дан 27 November 2019 в 17:23
поделиться

Можно ли использовать 'pidof' утилиту? Если Ваше приложение будет работать, то pidof запишет идентификатор Процесса Вашего приложения к stdout. В противном случае это распечатает новую строку (LF) и возвратит код ошибки.

Пример (от удара, для простоты):

linux# pidof myapp
8947
linux# pidof nonexistent_app

linux#
0
ответ дан 27 November 2019 в 17:23
поделиться

Если Вы создаете файл блокировки и помещаете pid в него, можно ли проверить идентификатор процесса по нему и сказать ли, отказали ли Вы, нет?

я не сделал этого лично, поэтому возьмите с, ассигнуют суммы в размере соли. :p

0
ответ дан 27 November 2019 в 17:23
поделиться

Я сделал основную платформу для выполнения этих видов приложений, когда Вы хотите смочь передать параметры командной строки последующих предпринятых экземпляров к первому. Экземпляр начнет слушать на предопределенном порте, если он, уже не найдет экземпляр слушая там. Если экземпляр уже существует, он отправляет свои параметры командной строки по сокету и выходам.

код w/объяснение

0
ответ дан 27 November 2019 в 17:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: