Оказалось, что установка DBMail под Mac OS X — задачка не из тривиальных! Пришлось накропать по крайней мере строк пятьдесят всяко-разного кода! В частности, это было связано с тем, что в коде DBMail‘а сброс привилегий до пользователя, указанного в /opt/local/etc/dbmail.conf, производился раньше, чем открывался доступ к shm (Shared Memory) Отсюда и проблемы с невозможностью открыть сокет и разделяемую память при работе под пользователем, отличного от root‘а. Что же до версий 2.0.x и 2.2.x, то их установить оказалось настолько непросто, что и браться за это не стал. Одни жёсткие требования к версии xmlto чего стоили! Короче, читайте, кому интересно.-)
Настройка DBMail под Mac OS X
Предисловие, как всегда
Как это ни странно, но настройка DBMail‘а порой превращается не в саму простую из задач, какую может себе поставить системный администратор. Быть может дело в том, что пока инструментарий установки и настройки DBMail пока не очень совершенен. Не даром, некоторые дистрибутивы Linux, да и Macports пока не включили в свой состав этот довольно часто используемый программный продукт. Он и впрямь удобен: возможность хранить почту в БД, использовать всю мощность языка SQL при сортировке, поиске и фильтрации — это довольно большое достоинство во многих случаях. Особенно, последнее свойство будет удобно при создании какого-нибудь корпоративного интерфейса для почтового обмена.
Однако, определённая скудность документации и определённый ряд неудобств, возникащих при установке и настройке DBMail часто отвращают администраторов от попытки его использования. Особенно неприятная картина возникает под Mac OS X:
Во-первых, версии, младше 2.3.x вообще ставиться под этой операционкой не хотят, находя тому массу отговорок и неувязок.
Во-вторых, невозможно уговорить инсталлятор (./configure) устанавливать исполняемые файлы, куда-нибудь, кроме /bin или /sbin. Про /opt/local/bin или /opt/local/sbin мы и слышать не хотим. Даже несмотря на тщательнейшим образом втыкаемые аргументы, типа —prefix=/opt/local/, —exec-prefix=/opt/local и так далее. Вполне вменяемо «подхватываются» аргументы —with-logdir=${LOGDIR}, —sysconfdir=${SYSCONFDIR}, а с префиксом дела плохи. Куда бинарники влепили, туда влепили, как паспорт — на вечную носку. Куда-там, системная безопасность…
Представляю себе, до какой степени должны раздражать делателей портов, портежей, пакаджей, инсталляционных пакетов (и т.д.) такие вот мелкие «неувязочки». Даром ли, видел на каком-то сайте предложение приобрести соответствующий порт за $10. Это, конечно, не дорого, но покупать что-то для открытого ПО… не спортивно! Хотя, признаюсь… соблазн сэкономить время был. Увы мне — десять долларов в наличии были, но ссылка никуда не вела. Порт оказался «дутым»! Значит, придётся всё делать ручками, ручками…
Думаю, версии ниже 2.3 отметаются, как неприличные. Во-первых, в 2.3.x «прикрепы» (аттачи) хранятся отдельно. Во-вторых, судя по отдельным отзывам, с MySQL эта ветка работает лучше и стабильнее. В-третьих (ох уж мне это «в-третьих»!) — ветви 2.0.x и 2.2.x для своей установки, скажем требуют совершенно определённой версии xmlto и asciidoc. Сие, милостивые государи, ужасно и для моей (несоменно нежной) админской души, соершенно непереносимо!
Шаг за шагом…
…перед сборкой обработать напильником © народная инструкция
Итак, дабы не ввергнуться в искушение диавольское и несомненно, посрамить нечистого, следует избегая беззрассудной траты вечности, начать с ветви 2.3.x (на сей день доступна последняя версия этой ветви dbmail-2.3.1.tar.gz). Для начала просмотрим что и как здесь можно настраивать (листинг ./configure —help):
`configure' configures dbmail dbmail@dbmail.org to adapt to many kinds of systems. Usage: ./configure [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print `checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for `--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or `..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [/usr/local] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, `make install' will install all the files in `/usr/local/bin', `/usr/local/lib' etc. You can specify an installation prefix other than `/usr/local' using `--prefix', for instance `--prefix=$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/dbmail] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-shared[=PKGS] build shared libraries [default=no] --enable-static[=PKGS] build static libraries [default=no] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-logdir use logdir for logfiles --with-mysql use MySQL as database. Uses mysql_config for finding includes and libraries --with-pgsql use PostgreSQL as database. Uses pg_config for finding includes and libraries --with-sqlite use SQLite3 as database. Uses pkg-config for finding includes and libraries --with-ingres use Ingres as database. Specify the II_SYSTEM location --with-ldap=PATH path to LDAP base directory (e.g. /usr/local or /usr) --with-sieve=PATH path to libSieve base directory (e.g. /usr/local or /usr) --with-gc=PREFIX libgc PREFIX --with-check=PATH prefix where check is installed default=auto --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-tags[=TAGS] include additional configurations [automatic] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> LIBS libraries to pass to the linker, e.g. -l<library> CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations.
Надо сказать, что со всеми тремя заявленными БД-серверами (С сервером БД Ingres пока так и не познакомился) работает вполне нормально. Этот факт я проверил бегло, наскоро, но в сети отрицательных отзывов не нашёл. Да и с драйверами MySQL, PostgreSQL, SQLite, всё прекрасно собралось и с серверами вменяемо общалось (да да, вот именно: жадность — не порок, а мутировавшая запасливость)
Ну и ещё одна дань жадности — —with-sieve=/opt/local. В конце-концов — это шанс изучить язык фильтрации e-mail-сообщений sieve… правда, обойдётся это в дополнительную строчку в командной строке: sudo port install libsieve. Ну и ещё придётся нам поставить xmlto + asciidoc, чтобы документация по проекту собралась. Процедура та же: sudo port install ….
Итак, предварительно распаковав файлы в директорию, создал себе следующий инициализирующий скрипт:
#!/bin/sh # PREFIX=/opt/local PREFIX=/opt/local/bin LOGDIR=/var/log LOCALSTATEDIR=/opt/local/var/run SYSCONFDIR=/opt/local/etc DATAROOTDIR=/opt/local/lib/ PATH=${PATH}:/opt/local/lib/mysql5/bin/:/opt/local/lib/postgresql83/bin/ ./configure --datarootdir=${DATAROOTDIR} --localstatedir=${LOCALSTATEDIR} --sysconfdir=${SYSCONFDIR} --prefix=${PREFIX} --exec-prefix=${EPREFIX} --with-logdir=${LOGDIR} --with-mysql --with-pgsql --with-sqlite --with-ldap --enable-shared --with-sieve=/opt/local
Итак, запустим этот конфигурационный скрипт:
./myinstall.sh This is 's GNU configure script. checking for a BSD-compatible install... /opt/local/bin/ginstall -c checking whether build environment is sane... yeschecking for gawk... gawk checking whether make sets $(MAKE)... yeschecking whether to enable maintainer-specific portions of Makefiles... nochecking for mysql_config... /opt/local/lib/mysql5/bin//mysql_config checking MySQL headers... -I/opt/local/include/mysql5/mysql checking MySQL libraries... -L/opt/local/lib -L/opt/local/lib/mysql5/mysql -lmysqlclient -L/opt/local/lib -lz -lm -L/opt/local/lib -lssl -lcrypto checking for pg_config... /opt/local/lib/postgresql83/bin//pg_config checking PostgreSQL headers... -I/opt/local/include/postgresql83 checking PostgreSQL libraries... -L/opt/local/lib/postgresql83 -lpq checking for pkg-config... /opt/local/bin/pkg-config checking SQLite3 headers... -I/opt/local/include checking SQLite libraries... -L/opt/local/lib -lsqlite3 -lpthread checking for style of include used by make... GNU checking for gcc... gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yeschecking whether we are cross compiling... nochecking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yeschecking whether gcc accepts -g... yeschecking for gcc option to accept ISO C89... none needed checking dependency style of gcc... gcc3 checking for LDAP headers... checking for LDAP libraries... -lldap checking for library containing ldap_initialize... -lldap checking for libSieve headers... -I/opt/local/include checking for libSieve libraries... -L/opt/local/lib -lsieve checking for pkg-config... /opt/local/bin/pkg-config checking GLib headers... -I/opt/local/include/glib-2.0 -I/opt/local/lib/glib-2.0/include -I/opt/local/include checking Glib libraries... -L/opt/local/lib -lglib-2.0 -lintl -liconv checking for pkg-config... /opt/local/bin/pkg-config checking GMime headers... -I/opt/local/include/gmime-2.0 -I/opt/local/include/glib-2.0 -I/opt/local/lib/glib-2.0/include -I/opt/local/include checking GMime libraries... -L/opt/local/lib -lgmime-2.0 -lz -lgobject-2.0 -lglib-2.0 -lintl -liconv checking how to run the C preprocessor... gcc -E checking for grep that handles long lines and -e... /usr/bin/grep checking for egrep... /usr/bin/grep -E checking for ANSI C header files... yeschecking for sys/types.h... yeschecking for sys/stat.h... yeschecking for stdlib.h... yeschecking for string.h... yeschecking for memory.h... yeschecking for strings.h... yeschecking for inttypes.h... yeschecking for stdint.h... yeschecking for unistd.h... yeschecking for --with-gc... nochecking getopt.h usability... yeschecking getopt.h presence... yeschecking for getopt.h... yeschecking for getopt_long_only... yeschecking whether optreset is declared... yeschecking for connect... yeschecking for res_search... yeschecking for dn_expand... yeschecking for dns_lookup... nochecking for gcc... (cached) gcc checking whether we are using the GNU C compiler... (cached) yeschecking whether gcc accepts -g... (cached) yeschecking for gcc option to accept ISO C89... (cached) none needed checking dependency style of gcc... (cached) gcc3 checking maximum warning verbosity option... -W -Wall -Wpointer-arith -Wstrict-prototypes for C checking for an ANSI C-conforming const... yeschecking for inline... inline checking whether byte ordering is bigendian... nochecking endian.h usability... nochecking endian.h presence... nochecking for endian.h... nochecking crypt.h usability... nochecking crypt.h presence... nochecking for crypt.h... nochecking for crypt in -lcrypt... nochecking build system type... i386-apple-darwin8.11.1 checking host system type... i386-apple-darwin8.11.1 checking for a sed that does not truncate output... /usr/bin/sed checking for ld used by gcc... /usr/bin/ld checking if the linker (/usr/bin/ld) is GNU ld... nochecking for /usr/bin/ld option to reload object files... -r checking for BSD-compatible nm... /usr/bin/nm -p checking whether ln -s works... yeschecking how to recognise dependent libraries... pass_all checking dlfcn.h usability... yeschecking dlfcn.h presence... yeschecking for dlfcn.h... yeschecking for g++... g++ checking whether we are using the GNU C++ compiler... yeschecking whether g++ accepts -g... yeschecking dependency style of g++... gcc3 checking how to run the C++ preprocessor... g++ -E checking for g77... nochecking for xlf... nochecking for f77... nochecking for frt... nochecking for pgf77... nochecking for cf77... nochecking for fort77... nochecking for fl32... nochecking for af77... nochecking for xlf90... nochecking for f90... nochecking for pgf90... nochecking for pghpf... nochecking for epcf90... nochecking for gfortran... nochecking for g95... nochecking for xlf95... nochecking for f95... nochecking for fort... nochecking for ifort... nochecking for ifc... nochecking for efc... nochecking for pgf95... nochecking for lf95... nochecking for ftn... nochecking whether we are using the GNU Fortran 77 compiler... nochecking whether accepts -g... nochecking the maximum length of command line arguments... 196608 checking command to parse /usr/bin/nm -p output from gcc object... ok checking for objdir... .libs checking for ar... ar checking for ranlib... ranlib checking for strip... strip checking if gcc supports -fno-rtti -fno-exceptions... nochecking for gcc option to produce PIC... -fno-common checking if gcc PIC flag -fno-common works... yeschecking if gcc static flag -static works... nochecking if gcc supports -c -o file.o... yeschecking whether the gcc linker (/usr/bin/ld) supports shared libraries... yeschecking dynamic linker characteristics... darwin8.11.1 dyld checking how to hardcode library paths into programs... immediate checking whether stripping libraries is possible... yeschecking if libtool supports shared libraries... yeschecking whether to build shared libraries... yeschecking whether to build static libraries... noconfigure: creating libtool appending configuration tag "CXX" to libtool checking for ld used by g++... /usr/bin/ld checking if the linker (/usr/bin/ld) is GNU ld... nochecking whether the g++ linker (/usr/bin/ld) supports shared libraries... yeschecking for g++ option to produce PIC... -fno-common checking if g++ PIC flag -fno-common works... yeschecking if g++ static flag -static works... nochecking if g++ supports -c -o file.o... yeschecking whether the g++ linker (/usr/bin/ld) supports shared libraries... yeschecking dynamic linker characteristics... darwin8.11.1 dyld checking how to hardcode library paths into programs... immediate appending configuration tag "F77" to libtool configure: creating ./config.status config.status: creating src/.h config.status: creating Makefile config.status: creating src/Makefile config.status: creating src/modules/Makefile config.status: creating man/Makefile config.status: creating test/Makefile config.status: creating config.h config.status: executing depfiles commands DM_LOGDIR: /var/log DM_CONFDIR: /opt/local/etc DM_STATEDIR: /opt/local/var/run USE_DM_GETOPT: 1 CFLAGS: -g -O2 -I/opt/local/include/glib-2.0 -I/opt/local/lib/glib-2.0/include -I/opt/local/include -I/opt/local/include/gmime-2.0 -I/opt/local/include/glib-2.0 -I/opt/local/lib/glib-2.0/include -I/opt/local/include -W -Wall -Wpointer-arith -Wstrict-prototypes GLIB: -L/opt/local/lib -lglib-2.0 -lintl -liconv GMIME: -L/opt/local/lib -lgmime-2.0 -lz -lgobject-2.0 -lglib-2.0 -lintl -liconv MYSQL: -L/opt/local/lib -L/opt/local/lib/mysql5/mysql -lmysqlclient -L/opt/local/lib -lz -lm -L/opt/local/lib -lssl -lcrypto PGSQL: -L/opt/local/lib/postgresql83 -lpq SQLITE: -L/opt/local/lib -lsqlite3 -lpthread INGRES: SIEVE: -I/opt/local/include-L/opt/local/lib -lsieve LDAP: -lldap SHARED: yesSTATIC: noCHECK: noSOCKETS:
Здесь настораживает одна вещь: поле SOCKET — пустое. Впрочем, далее по тексту, читатель узнает, что здесь-то и обнаружится одна маленькая проблемка.
Также, позже выяснилось, —prefix и —exec-prefix силы никакой не возымели. Увы… —sysconfigdir — прекрасно отработала. Так, что после инсталляции царит полный, с позволения сказать, раскардаш: исполняемые файлы (-export, -lmtpd, -sievecmd, -timsieved, -users, -imapd, -pop3d, -smtp, -top, -util) обитают в /sbin, а все настройки и библиотеки, в /opt/local/[etc/][lib/] (где им, с точки зрения номарльного BSD-шника и положено обитать).
Однако, попытка собрать дистрибутив командой вроде sudo make install потерпит почти наверняка полный провал:
server.c: In function 'create_unix_socket': server.c:417: error: 'AF_LOCAL' undeclared (first use in this function) server.c:417: error: (Each undeclared identifier is reported only once server.c:417: error: for each function it appears in.) server.c: In function 'create_inet_socket': server.c:461: warning: implicit declaration of function 'inet_aton' make[3]: *** [lib_la-server.lo] Error 1 make[2]: *** [all-recursive] Error 1 make[1]: *** [all-recursive] Error 1 make: *** [all] Error 2
Что уж руководило «аффтарами» при использовании AF_LOCAL даже и не знаю. Быть может, приверженность, к заветам бессмертного Уильяма Стевенса? Не иначе… дело, однако, более, чем поправимое: надо прописать в начале файла <_src_dir>/src/server.c (всего-то!) #define AF_LOCAL AF_UNIX Что характерно, рецепт, предложенный авторами DBMail, в данной ситуации не помог, хотя в /usr/include/sys/socket.h написано следующее:
#ifndef _POSIX_C_SOURCE #define AF_LOCAL AF_UNIX /* backward compatibility */ #endif /* !_POSIX_C_SOURCE */
Итак, sudo make install. (Не знаю, как Вас, почтеннейшие граждане Публика, а последняя пара предупреждений меня малость покоробила:
serverpool.c:365: warning: passing argument 1 of 'strncpy' discards qualifiers from pointer target type serverpool.c:367: warning: passing argument 1 of 'strncpy' discards qualifiers from pointer target type
— надо будет на досуге с ними разобраться)
После радующей душу команды make install, так и тянет кинуть пальцы на клавиатуру и бойко отстучать: sudo dbmail-imap (нет, ну чем демоны (и прочие покровители unix‘a) не шутят, а вдруг запустится?!) Ну может получится, а может и нет. Можно словить и такую странную ошибку, связанную с невозможностью доступа к разделяемой памяти. На это великий Paul J. Stevens справедливо отмечает, что нефиг запускать процесс из под суперпользователя. (Уж не родственник ли… ну того, великого и неповторимого?) Чтож замечание вполне справедливое. Ещё замечу, что установочный скрипт нифига нужных директорий не создал:
/opt/local/var/run/dbmail
/var/log/dbmail
отсутствуют как класс! Значит, mkdir /opt/local/var/run/dbmail && mkdir /var/log/dbmail и chown …… стоп, а кому chown, собственно? Непонятно! Придётся добавить пользователя и группу dbmail:dbmail, а то… небезопасно как-то. Да.
Вот тут-то и подстерегает нас безапеляционная подкрадуха в лице утилиты dscl (видела я, знаете ли котов без улыбок, но улыбка без кота… © Льюис Кэрол) Мануал по этой утилите не то, чтобы невнятен, он просто не для простых людей писан. Даже не для админов (видимо, сказываются издержки коммерциализации UniX, а может я такой малосообразительный…) Посему, настоятельно рекомендую почитать статью «Open Directory and the dscl Tool» с сайта developer.apple.com, або «Command Line, Make Mac Work»
Неплохо бы сразу соорудить скриптик для сооружения uid и gid. Обратите внимание на то, что PrimaryGroupID Вы, почтеннейшие граждане Публика, создаёте сами! И он должен присутствовать, как в uid, так и в gid, иначе группа при переназначении пользователя демона в момента запуска, не будет найдена!
#!/bin/sh # (© yevstigneyevda@mail.ru) # PrimaryGroupID выбран, честно сказать от "балды". Ну, скажем, # у PostgreSQL -- 503, а у нас будет 703. PrimaryGroupID=703 dscl / -delete /Users/dbmail dscl / -delete /Groups/dbmail dscl / -create /Groups/dbmail PrimaryGroupID 703 dscl / -append /Groups/dbmail RealName dbmail dscl / -create /Users/dbmail UniqueID 703 dscl / -append /Users/dbmail PrimaryGroupID 703 dscl / -append /Users/dbmail RealName dbmail dscl / -read /Users/dbmail dscl / -read /Groups/dbmail
Почти порядок. Осталось сообразить конфигурационный файл и инициировать базы данных, как это указанно в штатной инструкции к настоящему приложению:
# mysqladmin5 create dbmail -u root -p # mysql -u root -p $ GRANT ALL ON dbmail.* to dbmail@localhost identified by '<pass>'; $ exit
Почтеннейшие граждане Публика, обратите внимание на вот это mysqladmin5 — это, если угодно, одна из «национальных» особенностей MacPorts. Впрочем, не так уж это и страшно. Просто руки не сразу привыкают после привычного mysql, набирать mysql5. Ну да ничего, ко-всему привыкнуть можно… однако, кажется я отвлёкся.
Теперь мы торжественно подхватываем штатные таблицы из дистрибутива (они обитают в <dbmail_src_dir>/sql/mysql/… (или что Вы там у себя поставили?)
# mysql -u root -p dbmail <dbmail_src_dir>/sql/mysql/create_tables.mysql
И всё-таки оно настраивается!
16:00. Война с Англией. © распорядок дня Б. Мюнхгаузена.
Думаете всё, да? О нет, веселье только началось: теперь начнём разборки с dbmail.conf. Согласно заданным параметрам, обитать он должен в /opt/local/etc/dbmail.conf.
# sudo cp <dbmail_src_dir>/dbmail.conf /opt/local/etc/
# sudo vim /opt/local/etc/dbmail.conf
(ну или какой-там редактор Вы предпочитаете в это время суток?)
# (c) 2000-2006 IC&S, The Netherlands # (сурдоперевод - © yevstigneyevda@mail.ru) # Конфигурационный файл DBMAIL [DBMAIL] # # Настройки БД # # # Общий драйвер БД. Поддерживаемые драйвера: mysql, pgsql, sqlite. # driver = mysql # # Драйвера БД авторизации. Поддерживаемые драйвера sql, ldap. # authdriver = sql # Хост БД. Установите localhost, если сервер БД находится # на том же компьютере, что и dbmail и вы хотите использовать # сокет для подлючения # host = localhost # Если вы хотите использовать TCP/IP для подключения к БД, # и ваш Сервер БД отвечает по нестандартному порту (стандартный # порт MySQL -- 3306, PostgreSQL -- 5432, SQLite... SQLite, вообще # не сервер, а процесс, взаимодейстующий непосредствено с клиентом # и порта ему не положено. # sqlport = 3306 # # эта настройка, когда подключение к серверу БД локальное, # через файл сокета. Например, /var/run/mysql.sock и т.д. # sqlsocket = /opt/local/var/run/mysql5/mysqld.sock # # логин пользователя БД. # user = dbmail # # пароль пользователя БД. # pass = MyPassword # # название БД. # db = dbmail # # Префиксы таблиц БД. По умолчанию префикс dbmail_ не определён! # table_prefix = dbmail_ # # кодировка должна соответствовать кодировке БД/таблицы # encoding = utf8 # # что делать с сообщениями с неизвестной кодировкой, если таковые # встретятся. Т.е. определить кодировку по умолчанию, как iso8859-1 или utf-8... # default_msg_encoding = utf8 # # почтовый адрес постмастера -- для перенаправления отброшенных # сообщений. # # #postmaster = DBMAIL-MAILER # # Sendmail executable for forwards, replies, notifies, vacations. # You may use pipes (|) in this command, for example: # dos2unix|/usr/sbin/sendmail works well with Qmail. # You may use quotes (") for executables with unusual names. # # местонахождение исполняемого файла для перенаправления, ответов, # уведомлений, реализации механизма «отпускных сообщений» (т.е. на сообщение приходит ответ «уехал, вернусь не скоро, приеду — отвечу — »<a href="http://wiki.cs.huji.ac.il/wiki/Mail_Vacation_Messages" class="out" target="_blank">Mail Vacation Mechanizm</a>) и т.д. # Вы можете использовать pipe (|) в команде, например: # dos2unix|/usr/sbin/sendmail (при работе с <a href="http://www.qmail.org" class="out" target="_blank">QMail</a> # sendmail = /usr/sbin/sendmail # # # Слеующие строки позволяют переопределить service-specific разделы # # # Отладочный режим ( тот самый загадочный «debug level», возникающий # при какой-нибудь неопределимой ошибке) По умолчанию стоит 2 -- (сообщения, ошибки # фатальные ошибки) # TRACE_SYSLOG = 3 # # Уровень трассировки перенаправялемый в stderr. По умолчанию - 0 # (только фатальные ошибки) # TRACE_STDERR = 1 # # root-права используются для открытия порта, затем # они сбрасываются до определённых ниже пользователя/группы # # # # EFFECTIVE_USER = dbmail EFFECTIVE_GROUP = dbmail # # IP-адрес сервиса, с которым надо связыаться. # Используйте * для определения всех локальных интерфейсов. # Используйте 127.0.0.1 для того, чтобы определить только localhost # Множественные значения разделяйте пробелами ( ) или запятыми (,) # BINDIP = * # # номер запускаемого дочернего процесса по умолчанию # NCHILDREN = 2 # # Максимально допустимое число дочерних процессов # MAXCHILDREN = 10 # # Число всегда доступных неиспользованных процессов # MINSPARECHILDREN = 2 # # Максимальное число неиспользованных активных дочерних процессов # MAXSPARECHILDREN = 4 # # Дочерний процесс будет перезапущен после обработки данного количества подключений # MAXCONNECTS = 10000 # # Дочерний процесс будет перезапущен после данного количества ошибочных подключений # MAX_ERRORS = 500 # # Допустимое время ожидания после выключения подключения # TIMEOUT = 300 # # Допустимое время ожидания после того как подключение будет выключено, если вы всё ещё залогинились # login_timeout = 60 # # Если "да", то разрешает IP-адрес в DNS-имя при залогинивании # RESOLVE_IP = no # Файл журнала для stdout-сообщений # logfile = /var/log/dbmail/dbmail.log # # файл журнала для stderr-сообщений # errorlog = /var/log/dbmail/dbmail.err # # директория для сохранения PID (Process ID) файлов # pid_directory = /opt/local/var/run/dbmail # # папка для сохранения файлов состояний демонов # state_directory = /opt/local/var/run/dbmail # # место, где сохранены библиотеки (лучше будет их прикомпилировать статически) # library_directory = /opt/local/lib/dbmail [SMTP] # Фактически, здесь по умолчанию ничего нет... [LMTP] # # Порт привязки # PORT = 24 [POP] # # Порт привязки # PORT = 110 # # Если да, то SMTP разрешён доступ с указанных IP подключающихся по POP3 # Эта опция необходима для расширения возможностей конфигурирования ваших MTA # (Mail Transfer Agent) # POP_BEFORE_SMTP = no[IMAP] # # Соответственно, порт привязки # PORT = 143 # # Для нормальной работы IMAP предпочтительно выделить таймаут побольше, чем для остальных сервисов # TIMEOUT = 4000 # # # Если этот параметр определён, как "yes", то будет разрешёт SMTP доступ # со стороны IP адресов, подключающихся по IMAP. # Эта настройка необходима для дополнительных настроек MTA. # IMAP_BEFORE_SMTP = no # период ожидания в секундах при проверке почтового ящика (по умолчанию -- 30 секунд) # # idle_timeout = 30 # # Поддержка возможности переопределить значения по умолчанию # # capability = IMAP4 IMAP4rev1 AUTH=LOGIN ACL NAMESPACE CHILDREN SORT QUOTA THREAD=ORDEREDSUBJECT UNSELECT IDLE # # Посылать статус отправки почтового ящика '*.STATUS' (MESSAGES x RECENT x UNSEEN x NEXTUID x) # для всех отправляемых сообщений в течение времени ожидания (по умолчанию - 'no') # ЗАМЕЧАНИЕ: эта настройка экспериментальная # # idle_status = yes[SIEVE] # # Порт привязки # PORT = 2000 [LDAP] PORT = 389 VERSION = 3 HOSTNAME = ldap BASE_DN = ou=People,dc=mydomain,dc=com # # Если вы включили поддержку библиотеки LDAP (ldap_initialize()) вы можете # использовать альтернативный LDAP-сервер, примерно таким способом: # # URI = ldap://127.0.0.1:389 # URI = ldapi://%2fvar%2frun%2fopenldap%2fldapi/ # # Оставьте это поле пустым, если хотите сделать привязку анонимной # или можете заполнить это поле так: cn=admin, dc=mydomain, dc=com # BIND_DN = # # Оставьте эти поля пустыми, если хотите сделать привязку анонимной # BIND_PW = SCOPE = SubTree USER_OBJECTCLASS = top,account,dbmailUser FORW_OBJECTCLASS = top,account,dbmailForwardingAddress CN_STRING = uid FIELD_PASSWD = userPassword FIELD_UID = uid FIELD_NID = uidNumber MIN_NID = 10000 MAX_NID = 15000 FIELD_CID = gidNumber MIN_CID = 10000 MAX_CID = 15000 FIELD_MAIL = mail FIELD_QUOTA = mailQuota FIELD_FWDTARGET = mailForwardingAddress [DELIVERY] # # Запуск Sieve-скриптов при получении сообщения # SIEVE = yes # Если используем формат 'user+mailbox@domain' для отправки в почтовый ящик # SUBADDRESS = yes # Включить или выключить отпускное Sieve-расширение (Sieve Vacation extension) # SIEVE_VACATION = yes # Вклюить или выключить Sieve-расширение уведомление # SIEVE_NOTIFY = yes # Включить или выключить дополнительную отладку Sieve-скриптов # SIEVE_DEBUG = no # Использовать таблицу автоуведомлений для отправки почтовых уведомлений # AUTO_NOTIFY = no # Использовать таблицу автоответов для дальнейшей переправки сообщений # AUTO_REPLY = no # По умолчанию "NEW MAIL NOTIFICATION" # #AUTO_NOTIFY_SUBJECT = # # По умолчанию отправить POSTMASTER'у из раздела DBMAIL # #AUTO_NOTIFY_SENDER = # # Если вы установите значение 'yes', dbmail будет проверять # дублированные сообщения в соответствующих почтовых ящиках # в течение отправки сообщения. Проверка осуществляется по # Message ID Header. # suppress_duplicates = noend of configuration file
Думаю, особое внимание здесь надо обратить на расположение mysqld.sock — /opt/local/var/run/mysql5/mysqld.sock. Остальное, вполне тривиально.
Вообще говоря, ещё до попыток запуска демона dbmail-imapd, надо было бы подумать об установке базы данных. У меня стоит MySQL, чего и Вам, почтеннейшие граждане Публика, желаю. Посему и идём в директорию <DBMail-2.3.1_src>/sql/mysql, берём файл create_tables.mysql и «напускаем» на него mysql5:
$ mysqladmin5 create dbmail $ mysql5 dbmail < [DBMail-2.3.1_src]/sql/mysql/create_tables.mysql
Про Mac OS X‘овскую «пятёрочку» (ну или «четвёрочку», неожиданно возникающую после имени команд, наинающихся на mysql) не забыли? Хорошо. Кстати, не забудьте, что если сервер «живёт» на другом хосте или доступ за семью паролями, то надо модифицировать вызовы комманд до mysql<…>5 —user <user> —host -p. Во-избежание.
Теперь можно честно подумать о добавлении пользователей системы:
$ dbmail-users -a admin@localhost -p $ dbmail-users -c admin@localhost -g 1
(вторая команда делает пользователя admin@localhost — суперпользователем)
Как это пишется порой в мелодраматических романах, хотел бы я сказать, что история эта продолжится хорошо, но увы. Добавлять пользователей, несомненно было бы удобнее при помощи NetVulture Cunsulting (NVC) Toolbox. Ну, там надо (будте бдительны!) было скачать два архива: собственно, сам ToolBox и nvc — модуль для работы с БД. Но, увы, для DBMail-2.3.1 эти пакеты не подходят. Так, что командная строка и утилита dbmail-user, почтеннейшие граждане Публика, вам в помощь.
От сохи и от root’а
Держивал ли ты соху? умеешь ли пахать? © В. И. Даль. «Толковый словарь живого великорусского языка»
А теперь о грустном. В нашем с Вами случае мы вынуждены писать user=root, group=wheel. Нарушение безопасности — вопиющее. Однако, почти без вариантов: попытайся мы запустить всё своё хозяйство из под пользователя dbmail, сразу получим ответ:
Dec 28 16:03:51 denis-yevstigney dbmail-imapd[389]: FATAL:[server] server.c,create_inet_socket(+470): Fatal error, could not bind to [*:143] Permission denied
Очевидно, что пользователю dbmail просто недостаточно прав для «бинденья» (связывания) сокета.
Если же мы запустим, скажем dbmail-imapd из под «root», то получим сообщение другого рода:
Dec 28 22:45:16 denis-yevstigney dbmail-imapd[16561]: FATAL:[server] serverpool.c, scoreboard_new(+92): shmget failed [nospace left on device]
На самом деле, сообщение крайне неприятное, потому что увеличение объёма shm (Shared Memory — Разделяемой Памяти) может неприятным образом сказаться на производительности системы. Неприятным и почти мистическим, потому что, скажем, 120 мегабайт вряд-ли сделают погоду при восьми гигабайтах оперативной памяти.
Итак, нарастить разделяемую память несложно (почти также, как и во FreeBSD):
$sudo /Applications/vim70/gvim /etc/rc
(ну или кто у Вас там ходит в любимых редакторах? Во всяком случае, редактировать надо именно /etc/rc — другие файлы просто не дадут желаемого эффекта.)
Ищем строчки, связанные с shm и изменяем значения на примерно такие: sysctl -w kern.sysv.shmmax=167772160 kern.sysv.shmmin=1 kern.sysv.shmmni=64 kern.sysv .shmseg=16 kern.sysv.shmall=65536. Теперь можно перезагрузиться: всё равно изменения, даже если мы их передадим напрямую из командной строки эффекта без перезагрузки иметь не будут. Ведь это же параметры, передаваемые ядру Mac OS X при загрузке.
После перезагрузки можем проверить, изменились ли параметры системы, связанные с shm:
$ sudo sysctl -a | grep shm Password: kern.exec: unknown type returned kern.sysv.shmmax: 167772160 kern.sysv.shmmin: 1 kern.sysv.shmmni: 64 kern.sysv.shmseg: 16 kern.sysv.shmall: 65536
Есть! Ура! Сработало! (Кстати, эти параметры будут полезными и для работы PostgreSQL–сервера. Ведь он тоже использует разделяемую память для связи между процессами!) Подробнее о любимой всеми FreeBSD-шниками команде sysctl
и настройках shm, можете посмотреть в статье «Shared Memory Configuration», ну и, конечно же в любимом народе man sysctl.
Ещё раз попытаемся запустить sudo /sbin/dbmail-imapd -v и…
Dec 28 10:41:42 denis-yevstigney dbmail-imapd[416]: FATAL:[server] serverpool.c,scoreboard_new(+98): scoreboard init failed [Permission denied]
Слушайте, а Вы точно поменяли пользователя в конфигурационном файле на root‘a? А группу на wheel‘a? Точно ну-ну…
Есть, заработало (если, конечно, добавлены пользователи, как это описано ниже)
Космический крейсер своими руками? Это просто!
Да просыпется файловая система Windows™ на головы программистов Linux, не учивших стандарты ©Мегахакерское проклятие.
Но, вообще-то говоря, «заработало» — это с бааальшой натяжкой. Во-первых, как говорится, «от root‘a» (почти что «от винта!»), а во-вторых, с использованием shm, применение которой в Mac OS X, категорически не рекомендовано. О чём весьма убедительно сообщается в Technical Note TN2071. Там настоятельно рекомендуется использовать вместо getshm(), mmap(). В коде DBMail разделяемый ресурс используется именно, как место хранения структуры Scoreboard_t. Это неудобно, так как mmap() отображает в память файлы.
Во-вторых, использование как getshm(), так и mmap()с точки зрения безопасности весьма «червиво последствиями». В принципе, лучше, но сложнее всего использовать многопоточную модель для программирования связи между отдельными процессами (вот хорошо бы мост построить да мужиков бы на нём с семечками поставить) Хорошо, конечно Apache: у него какую хочешь модель включаешь — хоть IPC во всех его прелестях, хоть мультипоточность.
О многопоточной модели Mac OS X подробно можно почитать в статьях Carbon Multiprocess Service, «Multithreaded Cocoa Programs», «Porting Multithreaded Application from win32 to Mac OS X». Понятно, что Posix Threads Library (pthread) будет как-то более переносимой… (читать «PTHREADs Programming Guide».) Ооох… опять меня в дебри понесло. Как-минимум, было бы не плохо. А ещё Macport соответствующий сделать. Ну да ладно, раскатал губень…
В третьих, есть догадка, что DBMail переключается на пользователя, указанного в конфигурационном файле до того, как открывает сокет и отводит место в разделяемой памяти (В отличие, скажем, от PostgreSQL.) Отсюда и проблемы. Надо бы этот момент разъяснить будет. Во-всяком случае, все беды (в DBMail v 2.3.1) происходят в файле <DBMail-2.3.1_src>/src/serverpool.c, в группе функций scoreboard_/new/lock_get/lock_new/setup…. А «срыв кода» происходит непосредственно в ф-ии scoreboard_new:
void scoreboard_new(serverConfig_t * conf) { int serr; if ((shmid = shmget(IPC_PRIVATE, (sizeof(child_state_t) * HARD_MAX_CHILDREN), /* 0644 | IPC_CREAT */IPC_CREAT | IPC_EXCL)) == -1) { serr = errno; TRACE(TRACE_FATAL, "shmget failed [%s]", strerror(serr)); } scoreboard = shmat(shmid, (void *) 0, 0); serr=errno; if (scoreboard == (Scoreboard_t *) (-1)) { TRACE(TRACE_FATAL, "scoreboard init failed [%s] (size = %d)", strerror(serr), sizeof(child_state_t) * HARD_MAX_CHILDREN); scoreboard_delete(); } scoreboard_lock_new(); scoreboard->conf = conf; scoreboard_setup(); scoreboard_conf_check(); /* Make sure that we clean up our shared memory segments when we exit * normally (i.e. not by kill -9, if you do that, you get to clean this * up yourself!) * */ atexit(scoreboard_delete); }
Чтож, проверим догадку о слишком раннем вызове функции (т.е., пользователь, указанный в dbmail.conf устанавливается раньше, чем открыт доступ к разлеяемой памяти. Итак, для смены пользователя, вызывается функция drop_privileges (char *newuser, char *newgroup) в файле [DBMail-2.3.1_src]/src/dm_misc.c:
int drop_privileges(char *newuser, char *newgroup) { /* will drop running program's priviledges to newuser and newgroup */ struct passwd *pwd; struct group *grp; grp = getgrnam(newgroup); if (grp == NULL) { TRACE(TRACE_ERROR, "could not find group %s ", newgroup); return -1; } pwd = getpwnam(newuser); if (pwd == NULL) { TRACE(TRACE_ERROR, "could not find user %s ", newuser); return -1; } if (setgid(grp->gr_gid) != 0) { TRACE(TRACE_ERROR, "could not set gid to %s ", newgroup); return -1; } if (setuid(pwd->pw_uid) != 0) { TRACE(TRACE_ERROR, "could not set uid to %s ", newuser); return -1; } return 0; }
Функция StartServer(serverConfig_t *conf), в свою очередь вызывает scoreboard_new(serverConfig_t *config) (для открытия в памяти разделяемого ресурса) в файле [DBMail-2.3.1_src]/src/server.c. Осталось найти, кто вызывает функцию StartServer(). Ага, вот оно: функция server_run(serverConfig_t * conf), 254-й строки файла [DBMail-2.3.1_src]/src/server.c. А именно:
case 0: /* child process */ if (drop_privileges(conf->serverUser, conf->serverGroup) < 0) { mainStop = 1; TRACE(TRACE_ERROR,"unable to drop privileges"); return 0; } isChildProcess = 1; result = StartServer(conf); TRACE(TRACE_INFO, "server done, restart = [%d]", result); exit(result); break;
Ну так и есть! В Linux‘е (и даже быть может, во FreeBSD с невысоким предустановелнным уровнем сетевой безопасности) такой номер проходит, а здесь — нет. Бо Mac OS X.
Ну чтож, попробуем поменять местами вызовы StartServer(…) и drop_privileges (char * newuser, char *newgroup):
case 0: /* child process */ /* (© yevstigneyevda@mail.ru) */ isChildProcess = 1; result = StartServer(conf); TRACE(TRACE_INFO, "server done, restart = [%d]", result); if (drop_privileges(conf->serverUser, conf->serverGroup) < 0) { mainStop = 1; TRACE(TRACE_ERROR,"unable to drop privileges"); return 0; } exit(result); break;
Пересоберём DBMail-2.3.1 и установим в файле /opt/local/etc/dbmail.conf снова пользователя и группу в dbmail:
user = dbmail group = dbmail
Понятно, что запускаем демона «штатно», т.е. «от root‘а»:
$ sudo dbmail-imapd -v -n
Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+262): server will create [2] children Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+275): children will make max. [10000] connections Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+288): timeout [4000] seconds Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+300): login_timeout [60] seconds Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+305): no value for SOCKET in config file Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+308): socket [] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+320): binding to PORT [143] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+341): binding to IP [*] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+348): no value for BACKLOG in config file. Using default value [16] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+362): not resolving client IP Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+376): Disabling IMAP-before-SMTP Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+388): effective user shall be [dbmail] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+400): effective group shall be [dbmail] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+412): will maintain minimum of [2] spare children in reserve Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+424): will maintain maximum of [4] spare children in reserve Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverparent] serverparent.c,LoadServerConfig(+436): will allow maximum of [10] children Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[db] dbmodule.c,db_load_driver(+59): library_directory is [/opt/local/lib/dbmail] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[db] dbmodule.c,db_load_driver(+72): looking for mysql as /opt/local/lib/dbmail/libmysql.so Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[sql] dbmysql.c,db_query(+297): query [SET NAMES utf8] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[sql] dbmysql.c,db_query(+297): query [SHOW VARIABLES LIKE 'collation_%'] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[sql] dbmysql.c,db_mysql_check_collations(+127): does [collation_database:utf8_general_ci] match [collation_connection:utf8_general_ci]? Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[auth] authmodule.c,auth_load_driver(+51): library_directory is [/opt/local/lib/dbmail] Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[auth] authmodule.c,auth_load_driver(+64): looking for auth_sql as /opt/local/lib/dbmail/libauth_sql.so Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[serverchild] serverchild.c,manage_start_cli_server(+446): client info init complete, calling client handler * OK dbmail imap (protocol version 4r1) server dbmail@dbmail.org ready to run Jan 20 20:30:04 denis-yevstigney dbmail-imapd[15229]: Debug:[imapsession] dbmail-imapsession.c,dbmail_imap_session_printf(+1647): RESPONSE: [* OK dbmail imap (protocol version 4r1) server dbmail@dbmail.org ready to run ]
Урааа! Зарработало! Правда, патчик писать пока не буду. Хотите — правьте сами.
«Демонизация» процесса
Кругло точно © искажённая надпись «Круглосуточно» на по-всей видимости, круглосуточном ларьке
Теперь надо настроить автозапуск демона. Управляет этим процессом управляет утилита daemondo из пакета MacPorts. Эта утилита была встроена в него, начиная с версии 1.6. К ней пока нет соответствующего мануала, зато весьма подробный help:
$ daemondo --help daemondo, version 1.1 usage: daemondo [-hv] [--version] --start-cmd prog args... ; [--stop-cmd prog arg... ;] [--restart-cmd prog arg... ;] [--restart-wakeup] [--restart-netchange] daemondo is a wrapper program that runs daemons. It starts the specified daemon on launch, stops it when given SIGTERM, and restarts it on SIGHUP. It can also watch for transitions in system state, such as a change in network availability or system power state, and restart the daemon on such an event. daemondo works well as an adapter between darwin 8's launchd, and daemons that are normally started via traditional rc.d style scripts or parameters. Parameters: -h, --help Provide this help. -v Increase verbosity. --verbosity=n Set verbosity to n. -V, --version Display program version information. -l, --label=desc Label used to describe the daemon. -s, --start-cmd args... ; Required: command that will start the daemon. -k, --stop-cmd args... ; Command that will stop the daemon. -r, --restart-cmd args... ; Command that will restart the daemon. --pid=none|exec|fileauto|fileclean Whether to use/how to treat pid file. --pidfile= A pidfile from which to scavenge the target pid. --restart-wakeup Restart daemon on wake from sleep. --restart-netchange Restart daemon on a network change. --restart-config regex... ; SC patterns on which to restart the daemon. --restart-dist-notify names... ; Distributed Notification Center notifications on which to restart the daemon. --restart-darwin-notify names... ; Darwin Notification Center notifications on which to restart the daemon. --restart-config regex... ; SC patterns on which to restart the daemon. daemondo responds to SIGHUP by restarting the daemon, and to SIGTERM by stopping it. daemondo exits on receipt of SIGTERM, or when it detects that the daemon process has died. The arguments start-cmd, stop-cmd, restart-cmd, restart-config, restart-dist-notify, and restart-darwin-notify, if present, must each be followed by arguments terminated by a ';'. You may need to escape or quote the ';' to protect it from special handling by your shell. daemondo runs in one of two modes: (1) If no stop-cmd is given, daemondo executes start-cmd asyncronously, and tracks the process id; that process id is used to signal the daemon for later stop and/or restart. (2) If stop-cmd is given, then both start-cmd and stop-cmd are issued syncronously, and are assumed to do all the work of controlling the daemon. In such cases there is no process id to track. In either mode, restart-cmd, if present, is used to restart the daemon. If in mode 1, restart-cmd must not disrupt the process id. If restart-cmd is not provided, the daemon is restarted via a stop/start sequence. The argument restart-config specifies a set of regex patterns corresponding to system configuration keys, on notification of change for which the daemon will be restarted The arguments restart-dist-notify and restart-darwin-notify specify a set of notification names from the distributed and darwin notification centers, respectively, on receipt of which the daemon will be restarted. The argument restart-wakeup will cause the daemon to be restarted when the computer wakes from sleep. The argument restart-netchange will cause the daemon to be restarted when the network configuration changes. This is a shortcut for the more verbose --restart-darwin-notify com.apple.system.config.network_change. In mode 1 only, daemondo will exit when it detects that the daemon being monitored has exited.
Впрочем, в подробном чтении этого документа нет необходимости. Достаточно просто скопировать какой-нибудь из *.wrapper-файлов и изменить его в соответствии с нашими требованиями.
Создадим директорию /opt/local/etc/LaunchDaemons/dbmail:
$ sudo mkdir /opt/local/etc/LaunchDaemons/dbmail
К примеру, возьмём за образец файл /opt/local/etc/LaunchDaemons/org.macports.apache2, скопируем его в директорию /opt/local/etc/LaunchDaemons/dbmail/dbmail.wrapper и приведём его в надлежащий вид:
#!/bin/sh # # daemondo support script (© yevstigneyevda@mail.ru) # # # Init # prefix=/opt/local # # Start # Start() { /sbin/dbmail-imapd > /dev/null } # # Stop # Stop() { if [ -r /opt/local/var/run/dbmail.pid ] then read PID `echo /opt/local/var/run/dbmail.pid` kill -TERM ${PID} fi } # # Restart # Restart() { Stop Start } # # Run # Run() { case $1 in start ) Start ;; stop ) Stop ;; restart) Restart ;; * ) echo "$0: unknown argument: $1";; esac } Run $1
Теперь настала очередь файла /opt/local/etc/LaunchDaemons/dbmail/dbmail.plist. Это XML файл. Опять же, можно взять за основу какой-нибудь *.plist файл и изменить его. Получим примерно следующее:
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!-- (© yevstigneyevda@mail.ru) --> <plist version="1.0"> <dict> <key>Debug</key> <false/> <key>Label</key> <string>dbmail</string> <key>OnDemand</key> <false/> <key>ProgramArguments</key> <array> <string>/opt/local/bin/daemondo</string> <string>--label=dbmail</string> <string>--start-cmd</string> <string>/opt/local/etc/LaunchDaemons/dbmail/dbmail.wrapper</string> <string>start</string> <string>;</string> <string>--stop-cmd</string> <string>/opt/local/etc/LaunchDaemons/dbmail/dbmail.wrapper</string> <string>stop</string> <string>;</string> <string>--restart-cmd</string> <string>/opt/local/etc/LaunchDaemons/dbmail/dbmail.wrapper</string> <string>restart</string> <string>;</string> <string>--pid=none</string> </array> <key>RunAtLoad</key> <false/> </dict> </plist>
Нетрудно проверить себя:
$ sudo /opt/local/etc/LaunchDaemon/dbmail/dbmail.wrapper start
Если в логе /var/log/dbmail/dbmail.err не видим ничего интересного, значит затея удалась. Порядок!
Копируем /opt/local/etc/LaunchDaemon/dbmail/dbmail.plist в /Library/LaunchDaemon/dbmail.plist и добавляем его в автозапуск при помощи команды
$ sudo launchctl load -w /Library/LaunchDaemons/dbmail.plist
После перезагрузки проверим себя:
ps ax | grep dbmail 33 ?? Ss 0:00.02 /opt/local/bin/daemondo --label=dbmail --start-cmd /opt/lo 362 p1 S+ 0:00.00 grep dbmail
Право слово, сердце радуется! Как ни странно, но это — всё. Пааачтеннейшие граждане Публика, всем радоваться!