Проблема не обязательно в команде nohup
, а в &
в конце командной строки.
На справочной странице для bash
указано:
If a command is terminated by the control operator &, the shell executes the command in the background in a subshell. The shell does not wait for the command to finish, and the return status is 0.
Технически оболочка разветвляет подоболочку для выполнения команды nohup...
, а основная оболочка, выполняющая сценарий, немедленно переходит к следующей команде в сценарии. Таким образом, когда основная оболочка выполняет строку после строки nohup... &
, команда nohup может еще не завершиться :, подоболочка может находиться в процессе ее загрузки для выполнения.
И команда nohup
не обязательно завершается как таковая :, она устанавливает обработчик сигнала на игнорирование сигнала HUP, а затем пытается напрямую exec()
выполнить команду java...
. Если системный вызов exec()
успешен, то процесс, который был nohup
, преобразуется вjava
без fork()
создания нового процесса и выхода из , поэтому пока не будет никакого кода выхода для возврата.
Реальная команда nohup
вернет код выхода только в том случае, если команда java
не может быть найдена или выполнена,или если в самой команде nohup
возникла внутренняя ошибка. Если системный вызов exec()
выполнен успешно, код выхода будет доступен только тогда, когда сама команда java
завершится.
Вот почему подобные попытки не дают желаемого результата:
nohup java -jar Xyz-port-0.0.1.jar &
wait $!
if [ $? -ne 0 ]; then
echo "Error in running Java"
fi
Если nohup
не работает в фоновом режиме, wait
получит свой код выхода и позволит его проверить; но если nohup
успешно запустит java
, то команда wait
будет продолжать ждать, пока не завершится java
, поскольку и nohup
, и java
будут выполняться в одном и том же процессе один за другим.
Возможно, вы захотите сделать что-то подобное, как предложил @datUser:
STARTWAIT=20 #number of seconds to wait after starting the service
nohup java -jar Xyz-port-0.0.1.jar &
NEWPID=$!
for i in $(seq $STARTWAIT); do
# test if the process still exists
if ! kill -0 $NEWPID 2>/dev/null; then
# Process has died: get its exit code, report error, stop waiting
wait $!
EXITCODE=$?
echo "Process died after restart and reported result $EXITCODE" >&2
break
fi
sleep 1
done
if kill -0 $NEWPID; then
echo "The process was started and is still alive after $STARTWAIT seconds"
echo "so I guess it's now running correctly"
fi
Обратите внимание, что моему сценарию присуща слабость. :Если процесс nohup
ped умирает, а другой процесс получает тот же номер PID в течение одной секунды, этот сценарий не заметит, что это уже не тот же самый процесс. (Но если ваши номера PID обновляются так быстро, у вас, вероятно, есть более серьезные проблемы.)
Для оптимального решения проблемы вам потребуется сценарий для настройки некоторого механизма времени -выхода, который останавливал бы команду wait
в определенное заранее -время, а затем запускал wait()
] системный вызов отслеживаемого процесса (, который достигается командой оболочки wait
), потому что это может сделать только фактический родитель отслеживаемого процесса. Это довольно сложно реализовать в сценарии оболочки.
Я понял, что могу просто использовать tail -f
при частичной загрузке и передать его напрямую в wirehark.