Bash-скрипт работает в бесконечном цикле. Почему?

Этот сценарий инициализации должен запустить службу, используя nohup с параметром «start». Все остальные параметры должны передаваться как есть. (Перезапуск предусмотрен для удобства.)

#!/bin/sh
# Foo Startup Script

LOGFILE="/var/log/foo/foo.log"
WORKDIR="/usr/local/foo"

nohup() {
        nohup $WORKDIR/bin/foo $@ >> $LOGFILE  2>&1 &
}
other() {
        $WORKDIR/bin/foo $@
}

case "$1" in
  start)
        nohup $@
        ;;
  restart)
        other stop
        nohup start
        ;;
  *)
        other $@
        exit
esac

При «старте» сценарий запускается в бесконечный цикл с nohup, разветвляющим все больше и больше процессов (он же форк-бомба), но почему? (Выходные данные не записываются в файл журнала.)


person Matthias Ronge    schedule 12.02.2013    source источник
comment
Мне кажется, что каждый раз, когда вы вызываете nohup(), первое, что он делает, это вызывает nohup() (похоже, вы переопределили его). Попробуйте вызвать его как-то иначе и посмотрите, есть ли у вас та же проблема.   -  person TyrantWave    schedule 12.02.2013
comment
да, назовите свою функцию no_hup или как-то иначе, чем nohup   -  person Oerd    schedule 12.02.2013
comment
Или запустите /bin/nohup. Кроме того, все параметры $@ должны быть заключены в кавычки "$@", иначе они обрабатываются так же, как $*.   -  person Barmar    schedule 12.02.2013
comment
Спасибо, теперь это работает. :)   -  person Matthias Ronge    schedule 12.02.2013
comment
С другой стороны, это не должно быть форк-бомбой... Один процесс создает только ОДИН процесс в фоновом режиме. для форк-бомбы он должен создавать несколько фоновых копий самого себя...   -  person anishsane    schedule 12.02.2013


Ответы (2)


Скорее всего:

nohup() {
        nohup $WORKDIR/bin/foo $@ >> $LOGFILE  2>&1 &
}

Ваша функция nohup вызывает сама себя. Самое простое решение — дать функции другое имя.

Если вы хотите быть необычным, вы можете попробовать либо предварительно вычислить полный путь к двоичному файлу nohup, либо использовать встроенную версию оболочки (если она существует):

builtin nohup --help || native_nohup="$(which nohup)"
nohup() {
        if test -z "$native_nohup"; then
                builtin nohup $WORKDIR/bin/foo $@ >> $LOGFILE  2>&1 &
        else
                $native_nohup $WORKDIR/bin/foo $@ >> $LOGFILE  2>&1 &
        fi
}

но я действительно не вижу в этом необходимости или пользы. Гораздо проще просто переименовать функцию.

person David Z    schedule 12.02.2013

person    schedule
comment
по-другому: nohup() { command nohup ........ ; } (таким образом, если найти первую команду nohup, которую она может найти в PATH, не обязательно расположенную в /usr/bin в зависимости от дистрибутива) (и поставить завершающий ; перед закрытием }, как это необходимо в более новом bash ) - person Olivier Dulac; 12.02.2013
comment
@OlivierDulac, +1 за команду nohup. Вам нужна конечная точка с запятой только в том случае, если закрывающая фигурная скобка находится на той же строке: новая строка (и амперсанд) также является терминатором команды. - person glenn jackman; 12.02.2013
comment
@glennjackman: +1 за единственную потребность ';' если закрыть фигурную скобку в той же строке... не могу поверить, что я не знал/нащупал это раньше ^^ - person Olivier Dulac; 13.02.2013