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)
-F
es la abreviatura de --fixed-strings
y le dice a grep
que 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 grep
a 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 -F
porque hace que grep
el procesamiento sea mucho más rápido.
Что-то вроде этого позволит более надежно зафиксировать код выхода вашего процесса.:
...
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
отредактирован и будет работать в фоновом режиме без управляющего терминала, надежно выполняя отправку электронной почты или очистку.
Фоновое задание всегда запущено успешно:
$ 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'
То есть, запустите фоновую подоболочку, в которой вы запускаете свою программу, затем проверьте, возвращает ли nohup
126 или 127. Он сделает это, если команда java
не может быть найдена или не может быть запущена.
Проблема не обязательно в команде 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
), потому что это может сделать только фактический родитель отслеживаемого процесса. Это довольно сложно реализовать в сценарии оболочки.