Вопрос или проблема
Я создаю скрипт rc.d для Java-приложения на FreeBSD, вот мой скрипт rc.d
#!/bin/sh
#
# PROVIDE: peerbanhelper
# REQUIRE: LOGIN
# KEYWORD: shutdown
. /etc/rc.subr
name="peerbanhelper"
rcvar=peerbanhelper_enable
load_rc_config $name
: ${peerbanhelper_enable:=NO}
: ${peerbanhelper_user:="root"}
: ${peerbanhelper_dir:="/usr/local/etc/peerbanhelper"}
: ${peerbanhelper_command:="/usr/local/bin/java"}
: ${peerbanhelper_classpath:="/usr/local/lib/peerbanhelper/PeerBanHelper.jar"}
: ${peerbanhelper_jvm_flags:="-Dpbh.datadir=${peerbanhelper_dir} -Xmx386M -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+ShrinkHeapInSteps -jar ${peerbanhelper_classpath}"}
command="/usr/sbin/daemon"
command_args="-f -p /var/run/${name}.pid -u ${peerbanhelper_user} ${peerbanhelper_command} ${peerbanhelper_jvm_flags}"
# это только для отладки
echo "выполнение команды: ${command} ${command_args}"
run_rc_command "$1"
И когда я пытаюсь запустить этот скрипт, я получаю:
root@freebsd:~/PeerBanHelper # service peerbanhelper onestart
выполнение команды: /usr/sbin/daemon -f -p /var/run/peerbanhelper.pid -u root /usr/local/bin/java
/usr/local/etc/rc.d/peerbanhelper: DEBUG: checkyesno: peerbanhelper_enable установлено в YES.
Запуск peerbanhelper.
/usr/local/etc/rc.d/peerbanhelper: DEBUG: run_rc_command: doit: limits -C daemon /usr/sbin/daemon -Dpbh.datadir=/usr/local/etc/peerbanhelper -Xmx386M -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+ShrinkHeapInSteps -jar /usr/local/lib/peerbanhelper/PeerBanHelper.jar -f -p /var/run/peerbanhelper.pid -u root /usr/local/bin/java
daemon: недопустимый параметр -- D
использование: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]
[-u user] [-o output_file] [-t title]
[-l syslog_facility] [-s syslog_priority]
[-T syslog_tag] [-m output_mask] [-R restart_delay_secs]
аргументы команды ...
--change-dir -c Изменить текущий каталог на корневой
--close-fds -f Установить stdin, stdout, stderr в /dev/null
--sighup -H Закрыть и повторно открыть выходной файл при SIGHUP
--syslog -S Отправить вывод в syslog
--output-file -o <file> Добавить вывод дочернего процесса в файл
--output-mask -m <mask> Что отправить в syslog/файл
1=stdout, 2=stderr, 3=оба
--child-pidfile -p <file> Записать PID дочернего процесса в файл
--supervisor-pidfile -P <file> Записать PID процесса-надсмотрщика в файл
--restart -r Перезапустить дочерний процесс, если он завершится (задержка 1 сек)
--restart-delay -R <N> Перезапустить дочерний процесс, если он завершится через N сек
--title -t <title> Установить заголовок процесса-надсмотрщика
--user -u <user> Понизить привилегии, выполнять от имени указанного пользователя
--syslog-priority -s <prio> Установить приоритет syslog
--syslog-facility -l <flty> Установить источник syslog
--syslog-tag -T <tag> Установить тег syslog
--help -h Показать эту справку
Как показывает отладочный вывод, аргументы между /usr/sbin/daemon
и ${peerbanhelper_jvm_flags}
исчезли! Есть ли что-то неправильно в моем скрипте?
Если я изменю command
на /usr/local/bin/java
, это работает. Но я хочу, чтобы это приложение работало как демон, поэтому я должен его использовать.
Ответ или решение
Ваш скрипт rc.d для запуска Java приложения содержит небольшую ошибку в передаче аргументов, которые вы хотите передать команде daemon
.
Проблема заключается в том, как вы формируете строку аргументов для command_args
. При использовании переменной command_args
в вашем скрипте, вы передаете все ключи и параметры Java виртуальной машины как одну строку, что приводит к тому, что daemon
интерпретирует их как единое целое, а не как отдельные аргументы.
Чтобы решить эту проблему, вам нужно разбить peerbanhelper_jvm_flags
на отдельные аргументы. Вы можете сделать это, используя массивы в Bash. Вот исправленная версия вашего скрипта:
#!/bin/sh
#
# PROVIDE: peerbanhelper
# REQUIRE: LOGIN
# KEYWORD: shutdown
. /etc/rc.subr
name="peerbanhelper"
rcvar=peerbanhelper_enable
load_rc_config $name
: ${peerbanhelper_enable:=NO}
: ${peerbanhelper_user:="root"}
: ${peerbanhelper_dir:="/usr/local/etc/peerbanhelper"}
: ${peerbanhelper_command:="/usr/local/bin/java"}
: ${peerbanhelper_classpath:="/usr/local/lib/peerbanhelper/PeerBanHelper.jar"}
: ${peerbanhelper_jvm_flags:="-Dpbh.datadir=${peerbanhelper_dir} -Xmx386M -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+ShrinkHeapInSteps -jar ${peerbanhelper_classpath}"}
command="/usr/sbin/daemon"
# Преобразуем флаги JVM в массив
jvm_flags=(${peerbanhelper_jvm_flags})
# Создаем аргументы для daemon, включая флаги JVM
command_args="-f -p /var/run/${name}.pid -u ${peerbanhelper_user} ${peerbanhelper_command} ${jvm_flags[@]}"
# Это только для отладки
echo "run command: ${command} ${command_args}"
run_rc_command "$1"
Обратите внимание на следующие изменения:
-
jvm_flags=(${peerbanhelper_jvm_flags})
— здесь мы преобразуем строку флагов JVM в массив. Пробелы в строке автоматически конвертируются в отдельные элементы массива. -
В строке
command_args
мы используем${jvm_flags[@]}
, чтобы добавить элементы этого массива как отдельные аргументы к команде.
Теперь, когда вы запустите сервис снова с service peerbanhelper onestart
, флаги JVM должны корректно передаваться процессы daemon
, и ваше приложение будет запущено как демон.
Убедитесь, что вы адаптировали путь к вашему Java приложению и его jar-файлу, чтобы избежать других возможных ошибок. Если у вас возникнут дополнительные вопросы, не стесняйтесь их задавать.