LINUX.ORG.RU

Bash: как поймать код возврата фонового процесса?


0

2

Народ, скажите.

А можно ли в Bash узнать код возврата фонового процесса?

Например, код:

#!/bin/sh

# Время ожидания, в секундах
waitTime=5

# Запускаемая команда
runCommand="sleep 1; exit 25"

echo "#!/bin/sh" > run.sh
echo $runCommand >> run.sh
chmod 755 run.sh

# Запускается команда в подроцессе
./run.sh &

pid=$! # PID последнего процесса
echo "Номер процесса: "$pid

# Заданное ожидание
sleep $waitTime

# Код возврата последнего процесса
errCode=$? 

echo "Err code: "$errCode

Выводит:

Номер процесса: 20045
Err code: 0

А хотелось бы:

Номер процесса: 20045
Err code: 25

Как сие можно провернуть?

★★★★★

$ help wait
wait: wait [id]
Wait for job completion and return exit status.

Waits for the process identified by ID, which may be a process ID or a
job specification, and reports its termination status. If ID is not
given, waits for all currently active child processes, and the return
status is zero. If ID is a a job specification, waits for all processes
in the job's pipeline.

Exit Status:
Returns the status of ID; fails if ID is invalid or an invalid option is
given.
AITap ★★★★★ ()
Ответ на: комментарий от AITap

Если запускаемый процесс зависнет по ин/оуту (а в моем случае он может) то wait тоже зависнет. То есть, нужно либо получить код возврата, либо прибить процесс по истечении некоторого времени.

Прибить процесс не проблема, ибо известен ПИД. А как поймать код возврата в вышеозначенных условиях?

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

wait может сообщить статус уже убитого процесса:

[19:00:44][aitap@Tarkus ~]> sleep 999h & pid=$!
[1] 10566
[19:49:48][aitap@Tarkus ~]> kill -1 10566
[1]+ Обрыв терминальной линии sleep 999h
[19:50:00][aitap@Tarkus ~]> wait 10566
[19:50:06][aitap@Tarkus ~]129>


Но это всё не нужно, поскольку есть утилита timeout:

нужно либо получить код возврата, либо прибить процесс по истечении некоторого времени.

$ timeout --help

...
Если команда завершилась по таймауту, то код завершения 124. Иначе
возвращается полученный код завершения КОМАНДЫ. Если сигнал не задан
то по таймауту посылается сигнал TERM.

AITap ★★★★★ ()
Ответ на: комментарий от AITap

возвращается полученный код завершения КОМАНДЫ

Вот тут поточнее. Что будет возвращено в случае выполнения строки команд, разделенных символом ";"? Что будет в случае команды вызова скрипта?

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Что будет возвращено в случае выполнения строки команд, разделенных символом ";"?

Под «КОМАНДОЙ» здесь понимается путь к исполняемому файлу + параметры для него. Чтобы выполнить несколько команд, нужно запустить шелл (вроде timeout 5 sh -c 'command; command; command'). Ну а exit code шелла зависит от разных параметров и чаще всего равен exit code последней команды.

AITap ★★★★★ ()
Ответ на: комментарий от AITap

Проблема все еще не решена.

Wait не работает так как описано. Пример:

$ (exit 5) &
[1] 1111

$ echo $!
1111
[1]+  Exit 5                  ( exit 5 )

$ wait 1111

^----- тут пусто а должно быть 5

С утилитой timeout вообще непонятки. Ее по каким-то причинам нет в CentOs 5.8. Так что воспользоваться ей не могу.

$ timeout
bash: timeout: команда не найдена

$ yum provides "*/timeout"
Loaded plugins: fastestmirror
epel/filelists_db                                                             | 4.8 MB     00:00     
bash-3.2-32.el5.i386 : The GNU Bourne Again shell (bash) version 3.2
Repo        : base
Matched from:
Filename    : /usr/share/doc/bash-3.2/scripts/timeout

bash-3.2-32.el5.i386 : Оболочка GNU Bourne Again shell (bash), версия 3.1.
Repo        : installed
Matched from:
Filename    : /usr/share/doc/bash-3.2/scripts/timeout
Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Wait не работает так как описано.

$ (exit 5) &
[1] 32640

$ echo $!
32640
[1]+  Exit 5                  ( exit 5 )

$ wait 32640

$ echo $?
5
Deleted ()
Ответ на: комментарий от Xintrea

$ wait 1111
^----- тут пусто а должно быть 5

Наверное, я плохо пояснил: wait возвращает exit code процесса в своём exit code:

$ (exit 5) & pid=$!
[1] 28511
$ echo $pid
28511
[1]+ Exit 5 ( exit 5 )
$ wait $pid; echo $?
5


С утилитой timeout вообще непонятки. Ее по каким-то причинам нет в CentOs 5.8. Так что воспользоваться ей не могу.

$ dpkg -S $(which timeout)
coreutils: /usr/bin/timeout
$ dpkg -l coreutils | grep ^ii
ii coreutils 8.13-3.4 i386 GNU core utilities


timeout появился в coreutils в районе версии 7.3. Есть ещё утилита timelimit с похожим функционалом.

Возможно, апплет timeout есть в busybox:

$ busybox timeout
BusyBox v1.20.2 (Debian 1:1.20.0-7) multi-call binary.

Usage: timeout [-t SECS] [-s SIG] PROG ARGS

Runs PROG. Sends SIG to it if it is not gone in SECS seconds.
Defaults: SECS: 10, SIG: TERM.

AITap ★★★★★ ()
Ответ на: комментарий от Xintrea

Если запускаемый процесс зависнет по ин/оуту (а в моем случае он может) то wait тоже зависнет.

Как вариант можно по истечении необходимого интервала времени выполнить

kill -s 0 $pid
Если код возврата 0 - значит процесс ещё работает (завис) и его можно прибить, если 1 - вызываем wait $pid для получения кода фонового процесса.

x-signal ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.