FreeBSD rc.d демон аргументы отсутствуют

Вопрос или проблема

Я создаю скрипт 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"

Обратите внимание на следующие изменения:

  1. jvm_flags=(${peerbanhelper_jvm_flags}) — здесь мы преобразуем строку флагов JVM в массив. Пробелы в строке автоматически конвертируются в отдельные элементы массива.

  2. В строке command_args мы используем ${jvm_flags[@]}, чтобы добавить элементы этого массива как отдельные аргументы к команде.

Теперь, когда вы запустите сервис снова с service peerbanhelper onestart, флаги JVM должны корректно передаваться процессы daemon, и ваше приложение будет запущено как демон.

Убедитесь, что вы адаптировали путь к вашему Java приложению и его jar-файлу, чтобы избежать других возможных ошибок. Если у вас возникнут дополнительные вопросы, не стесняйтесь их задавать.

Оцените материал
Добавить комментарий

Капча загружается...