Проблема с кодом выхода команды nohup в unix

Debido a que .es un comodín regex, grep '..'coincide con cada línea que tiene al menos dos caracteres:

$ echo "$gene" | grep '..'
     gene            89..1483
                     /gene="non-structural protein"
                     /gene="non-structural protein"
                     /gene="non-structural protein"
                     /gene="non-structural protein"
                     /gene="non-structural protein"
                     /gene="non-structural protein"
                     /gene="non-structural protein"
     gene            complement(1987..2763)
                     /gene="nucleocapsid protein"
                     /gene="nucleocapsid protein"

En las expresiones regulares, .es verdaderamente comodín :coincidirá no solo con cualquier letra o número, sino también con cualquier puntuación, espacio en blanco, tabulación o cualquier otro carácter.

Para hacer coincidir solo períodos, use-F:

$ echo "$gene" | grep -F '..'
     gene            89..1483
     gene            complement(1987..2763)

-Fes la abreviatura de --fixed-stringsy le dice a grepque trate el patrón como una cadena fija, no como una expresión regular.

Alternativamente, uno puede escapar de los puntos para que solo coincidan (hat tip:Nick):

$ echo "$gene" | grep '\.\.'
     gene            89..1483
     gene            complement(1987..2763)

O bien podemos obligar a grepa tratar los períodos como períodos literales colocándolos dentro de clases de caracteres (hat tip:dave _thompson):

$ echo "$gene" | grep '[.][.]'
     gene            89..1483
     gene            complement(1987..2763)

Sin embargo, si no necesita expresiones regulares, use -Fporque hace que grepel procesamiento sea mucho más rápido.

1
15.03.2019, 21:49
3 ответа

Что-то вроде этого позволит более надежно зафиксировать код выхода вашего процесса.:

родитель.sh

...
java -jar Xyz-port-0.0.1.jar > /dev/null & #optionally discard stdout of java
child=$!
wait $child
exit_status=$?
if [[ "$exit_status" -ne 0 ]]; then
    # handle error
else
    #handle success
fi

Подождите

Обратите внимание, что вызов waitбудет заблокирован на неопределенный срок, поэтому, если вам нужно установить произвольное ограничение на количество времени, которое вы даете команде java, вы можете заменить вызов waitциклом. и некоторые ручные проверки ps, чтобы убедиться, что процесс все еще выполняется. Это позволит вам установить сторожевой таймер и вызвать всех из пула, если процесс зависнет.

Нохуп

Если вам нужно запустить процесс java и обработать его код выхода, не находясь в активном сеансе терминала, вызовите родительский сценарий (выше )с кодом nohup, а не кодом java. Родительский сценарий может быть nohupотредактирован и будет работать в фоновом режиме без управляющего терминала, надежно выполняя отправку электронной почты или очистку.

1
27.01.2020, 23:22

Фоновое задание всегда запущено успешно:

$ sntaoehu &
[1] 33566
$ bash: sntaoehu: command not found
[1]+  Exit 127                sntaoehu
$ echo $?
0

Вы не можете запустить свою Java-программу в фоновом режиме и определить, хорошо она прошла или нет, пока не завершится выполнение команды nohup. Команда nohupзавершится, если она не сможет найти или запустить javaили всякий раз, когда завершится программа Java. Это не nohup, который запускает вашу программу в фоновом режиме. Это просто заставляет вашу программу игнорировать любой сигнал HUPи будет зависать до тех пор, пока ваша программа не завершится, а затем возвращает статус выхода программы вызывающей оболочке.

Чтобы отправить электронное письмо, если задание запущено не удалось , вы можете выполнить

(
    nohup java -jar Xyz-port-0.0.1.jar
    status=$?
    if [ "$status" -eq 126 ] || [ "$status" -eq 127 ]; then
        # something wrong in launching java
        echo 'nohup failed to run java'
        printf 'nohup exit status is %s\n' "$status"
    elif [ "$status" -ne 0 ]; then
        # the java code returned an error
        echo 'java returned an error'
        printf 'java exit status is %s\n' "$status"
    else
        # everything went well and java exited ok
        echo 'java exited safely'
    fi | mail -s 'java job status report' me@example.com
) &

echo 'started background job'

То есть, запустите фоновую подоболочку, в которой вы запускаете свою программу, затем проверьте, возвращает ли nohup126 или 127. Он сделает это, если команда javaне может быть найдена или не может быть запущена.

2
27.01.2020, 23:22

Проблема не обязательно в команде 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

Обратите внимание, что моему сценарию присуща слабость. :Если процесс nohupped умирает, а другой процесс получает тот же номер PID в течение одной секунды, этот сценарий не заметит, что это уже не тот же самый процесс. (Но если ваши номера PID обновляются так быстро, у вас, вероятно, есть более серьезные проблемы.)

Для оптимального решения проблемы вам потребуется сценарий для настройки некоторого механизма времени -выхода, который останавливал бы команду waitв определенное заранее -время, а затем запускал wait()] системный вызов отслеживаемого процесса (, который достигается командой оболочки wait), потому что это может сделать только фактический родитель отслеживаемого процесса. Это довольно сложно реализовать в сценарии оболочки.

0
27.01.2020, 23:22

Теги

Похожие вопросы