@memba

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

Нужно организовать простую проверку на запуск второго экземпляра программы и по возможности заблокировать его.

Первое:
Я бы создал PID файл и вешал на него исключительную блокировку. Соответственно, если файл заблокирован, то приложение уже запущенно. Проблема: как я вижу в Go не реализован кроссплатформенный способ блокировки файла из коробки (syscall.Flock не поддерживается под Windows), писать костыль не разумно.

Второе:
Я бы установил Мьютекс. Проблема: как я вижу в Go нет поддержки именованных мьютексов и соответственно они доступны только в приделах одного процесса.

Третье:
Я бы занял какой-нибудь порт и при каждом запуске программы проверял его занятость. Проблема: Не очень хорошо забивать порт, темболее он может быть уже занят изначально. И в Go нет простого способа проверить доступность порта. Можно только к нему подключится используя net.Listen("tcp", ":8080"), проверить результат подключения и сразу отключится.
  • Вопрос задан
  • 649 просмотров
Решения вопроса 1
Третий способ самый кошерный и самый универсальный.
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
Tyranron
@Tyranron
Мне не нравится 3й вариант, так как он не решает задачу целиком. Порт, который слушать - это больше конфигурационный параметр, значит надо задумываться уже, ничего ли страшного не случится при смене порта и рестарте (обычно не должно, но раз на раз не приходится). А что, если демону и вовсе не нужно слушать какой-либо порт? Не универсальненько.

Увы, кросс-платформенного решения "из коробки" нет, да. Я когда стряпал свою поделку, то меня интересовали только *nix-like платформы, мне хватило старого хорошего PID-файла с syscall.Flock. То, что видел в других решениях, более кросс-платформенных, - люди заморачивались на platform specific код, для Windows они использовали регистрацию процесса в виде сервиса. Обернуть это дело в отдельный пакет с единым интерфейсом и platform specific компиляцией совсем не сложно в случае с Go. Для работы с сервисами Windows есть замечательный, пусть и не входящий в стандартную либу, но все же официальный пакет golang.org/x/sys/windows/svc, и костылить на чистых syscall'ах даже не нужно.
Также загляните в этот тред, там как раз про решение для Windows в виде semaphore/mutex аналогично тому, что указал Владимир Мартьянов в комментарии к Вашему вопросу и тому, что Вы указали 2м пунктом.
Ответ написан
Комментировать
index0h
@index0h
PHP, Golang. https://github.com/index0h
Пидфайл -> проверка существования процесса по pid -> если уже существует:
* да -> закрыть
* нет -> удалить пидфайл, если есть -> запустить

-----

Есть альтернативный вариант запуска: через supervisor
Ответ написан
saboteur_kiev
@saboteur_kiev
software engineer
memba:
PID файл не нужно блокировать.
Посмотрите что лежит внутри файлов /var/run
все pid файлы внутри хранят номер процесса. Поэтому файл не нужно блокировать, нужно просто проверять наличие файла, считвыать из него номер процесса и проверять существует ли такой процесс.
Если не существует - значит предыдущее выполнение программы было завершено некорректно.

Файл потому и называется PID, что в нем лежит PID ;)
Ответ написан
mututunus
@mututunus
Backend developer (Python, Golang)
Можно просто самому проверять PID файл при запуске..
Ответ написан
@RomanPyr
В Unix можно использовать unix sockets (как это делает ssh-agent), в windows named pipes. Для последнего:
https://github.com/natefinch/npipe
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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