Pull to refresh

Comments 35

Он поддерживает start/stop/status?
Нет, я имею ввиду поддержку именно в вашем коде. Это важно. То, что делается через системы инициализации, это обычно обертки на mydaemon start/stop/status
Один на «is», другой на «was».
Благодарю, исправил
Если я вас правильно понял и вы имеете ввиду service <daemon> {start|stop|status}, то обычно это реализуется с помощью init.d скрипта и механизмов вроде start-stop-daemon, и моя библиотека не поддерживает этого в чистом виде.
Извините, промахнулся, это ответ на коментарий habrahabr.ru/post/187668/#comment_6523268
При беглом просомтре не увидел дропа привелегий.
сори не заметил. =)
Это можно легко реализовать, после вызова Reborn(), примерно так:
if syscall.Getuid() == 0 {
    if err := syscall.Setgid(GID); err != nil {
        log.Println(err)
    } else {
        if err := syscall.Setuid(UID); err != nil {
            log.Println(err)
        }
    }
}
Любопытно… Какую задачу вы решали?
Мы взяли за правило запускать все критичные приложения, либо monit'ом либо с помощью systemd. Это даёт возможность без проблем контролировать состояние приложения и спокойно рестартануть его, если с ним возникнут проблемы. При таком подходе потребности в штатном механизме демонов на Go ни разу не возникло…
Upstart для хипстеров :-)
Ну, тогда вы тоже скоро познакомитесь с systemd… Думаю не пожалеете… )
хм. когда выбирал — под дебиан еще не было порта, надо посмотреть
В wheezy уже есть… Был опрос, больше половины разработчиков Debian положительно вызказалось в отношении systemd. Так что вопрос времени.
Благодарю, хороший вопрос.
В статье я не упоминал механизмы мониторинга и перезапуска демона в случае сбоя. Да, для этой задачи надо использовать инструменты вроде monit или fscd во FreeBSD.
А задачи разные, на тот момент я писал сервер для gsm трекера. И использовать systemd или подобные решения я не мог, так как требования диктует заказчик, он бы не обрадовался дополнительным зависимостям и экспериментами на боевом сервере. Если я точно знал, что написав демона, System V init скрипт и скрипт инсталляции, и они прекрасно заработают на любом дистрибутиве (с небольшой корректировкой скриптов и перекомпиляцией демона, при необходимости), то не факт, что заказчик захочет или сможет настроить systemd.
К тому же, хотя это и парадокс, доступ к своему серверу мне давать никто не собирался (хотя мои скрипты и ПО они на нем запускали без вопросов). Да и иногда требуют поддержки нескольких дистрибутивов, например недавно нужно было написать сервис, который бы работал на Debian и FreeBSD. Насколько мне известно не существует порта systemd для FreeBSD, поправьте если это не так.
Да и по моему скромному мнению, киллер фича systemd — скорость загрузки, что в первую очередь важно для десктопных систем, а не для серверов, которые работают без перезагрузки по нескольку месяцев.
Для десктопов эта «киллер фича» тоже не сдалась, когда есть suspend и hibernate.
По большому счёту не суть важно что используется для запуска приложения. Это никак не влияет на код. Во FreeBSD мы cобственно используем monit. Можно использовать банальный nohup или screen/tmux, если иногда нужно видеть вывод… Способов много. Для наших задач нормальная конкуррентность Gо важней и востребованней, чем нормальная демонизация… Ваш пример примечателен тем, что показывает, что Go достаточно сильный язык для того, чтобы делать вещи для которых он изначально не предназначался. За это спасибо…

Что же касается systemd, то скорость загрузки — конечно не последняя киллерфича, но и вовсе не первая… У него много прелестей, хотя мне олдскульному юниксоиду он по началу тоже сильно не понравился. Слишком много функционала во одном флаконе. Но тем не менее он свою работу делает и делает её качественно. За это мы его и ценим…
А что вы пишете на Go?
Сетевые сервисы и сложную обработку данных хранящихся в mongodb…
Посылаю вам лучи зависти.
Зачем мне ваши лучи зависти? Лучше пишите код на Go… )))
Тут вокруг за это не платят :(
Технически, Google как раз позиционирует Go как системный язык (к вопросу «делать вещи для которых он изначально не предназначался»). Поэтому я даже немного удивился, что в языке, заточенном под написание многопоточных (ок, пусть много-гороутинных ;) ) демонов возникли такие проблемы собственно с демонизацией. Скорее всего, этот момент просто упустили при проектировке, возможно исправят в какой-то версии языка, если девелоперам Go указать на эту проблему.
Нет, не упустили. Либо демонизация, либо конкурентность. Одновременно это нормально работать не может. Точнее это можно заставить работать при каких-то конкретных условиях как в данной статье. fork'и не совместимы с идеологией принятой в Go.
Честно говоря, не понимаю, чем демонизация мешает конкурентности и наоборот.
В гугле ведь (да и не только) все конкурентные сервисы только в виде демонов и работают, поди.

fork() изначально и не задумывался как средство обеспечения конкурентности при обработке запросов, другое дело, что он худо-бедно удовлетворяет потребность в этом. Но как ни крути — без fork-а ОС не обойтись, и то, что на платформе Go есть проблемы с fork() — это конкретный недосмотр (отнюдь не умаляю преимуществ Go, сам обожаю этот язык).
Вы просто не очень хорошо понимаете разницу между форком и процессом…
Если совсем грубо, то разница в том, что процесс создает собственный контекст и имеет возможность изменять контекст родителя, а форк клонирует контекст родителя и все изменения в контексте форка никак не отражаются на родителе.

Проблема в том, что процессы не являются частью контекста родителя и при создании форка склонироваться по понятным причинам не могут. И если процессы изменяют контекст родителя, который перед этим сделал форк, то форк никогда об этом не узнает, и взаимодействовать с процессами запущенными ранее форк не сможет. Из этого следует целый ряд эффектов и проблем, которые способны превратить написание многопоточных, конкурентных приложений в настоящий ад, рядом с которым асинхронное программирование это детский лепет. Это как раз то, чего пытались избежать cоздавая язык Go.
Прошу прощения, но то, что Вы написали выше, не соответствует действительности.
Во первых, fork() — это операция, а процесс — примитив (обьект, сущность) ОС — сравнивать их и искать разницу просто не корректно.
Во вторых, никакой процесс не имеет возможности повлиять напрямую на контекст родителя — для связи процессов можно использовать только IPC.

Если вы под «процесс» имеете ввиду «тред» — то так и пишите, будет понятно о чем дискуссия.

Исходная проблема возникла откуда — из того факта, что до фактически запуска кода программы платформа Go запустила (неявно) goroutine по обработке сигналов. Если бы не эта особенность, то и этой статьи не было бы за ненадобностью.
Если вы под «процесс» имеете ввиду «тред» — то так и пишите, будет понятно о чем дискуссия.

Если вы не поняли где я взял слово процессы, то http://golang.org/doc/faq#csp… Тут речь идет о программировании, если вы заметили. Ваше понимание терминов имеет отношение скорее к администрированию…

Исходная проблема возникла откуда — из того факта, что до фактически запуска кода программы платформа Go запустила (неявно) goroutine по обработке сигналов. Если бы не эта особенность, то и этой статьи не было бы за ненадобностью.

И? Заканчивайте мысль… Почему запущенный goroutine мешает сделать fork()?

Никакой дискуссии нет. Я просто по-доброму попытался объяснить вам почему fork() не может работать в рамках концепции CSP принятой в Go. Сам я в своё время с этим вопросом в полной мере разобрался далеко не сразу… Но вы же похоже восприняли это как оскорбление и обвинение в некомпетентности…
По ссылке http://golang.org/doc/faq#csp слово «process» встречается только в названии модели конкурентного исполнения кода
One of the most successful models for providing high-level linguistic support for concurrency comes from Hoare's Communicating Sequential Processes, or CSP

В платформе Go используется термин goroutine. Общепринятое значения термина «процесс» в программировании я Вам не буду обьяснять за отсутствием необходимости (искренне надеюсь на это).

fork() может работать на платформе Go и работает успешно, за исключением того, что goroutine-ы не могут быть перезапущены в потомке, если они заблокированы в другом треде в родителе. Технически, для шедулера Go нет проблемы перезапустить треды для горутин и возобновить в них исполнение запущеных горутин, за исключением случая, упомянутого выше. Если бы os/signal не требовал бы горутины для своей работы, либо давал возможность перезапустить её явно, то все было бы в порядке.
Как раз Google ушёл от использования в своём коде fork'ов. С ними немало проблем.

Это собственно и отразилось в отстутствии форков в языке Go. С ходу, к сожалению, не смог найти ссылку… Об этом было толи в faq то ли в группе golang-nuts.

fork'и это довольно специфичная для unix/posix вещь и ничего в них жизненно необходимого для операционной системы нет. В родном API Windows их например нет, и не похоже, чтобы windows плохо себя чувствовала из-за этого. И тем более нет проблемы c fork'ами в Go. Они там, по большому счету не нужны… Для того, чтобы отвязать проложение от консоли и дать возможность выполняться в системе без активного терминала, как я уже говорил, есть масса способов.
Просьба, поправьте форматирование статьи.
Only those users with full accounts are able to leave comments. Log in, please.