надежный код возврата фонового процесса

Давайте предположим следующий фрагмент кода bash:

foo > logfile 2>&1 & foo_pid=$! while ps -p$foo_pid do ping -c 1 localhost done wait $foo_pid if [[ $? == 0 ]] then echo "foo success" fi 

Можно ли предположить, что $? действительно содержит код возврата foo а не код возврата ping ? Если ответ на этот вопрос: «Вы не можете этого принять». то как я могу изменить этот кусок кода, чтобы убедиться, что $? всегда содержит код возврата foo ?

3 Solutions collect form web for “надежный код возврата фонового процесса”

С помощью bash вас будет эта гарантия, если вы не запустили другое фоновое задание (и остерегайтесь того, что фоновые задания могут быть запущены с помощью & а также с coproc и с заменой процесса) между foo & и wait .

POSIX требует, чтобы оболочка запоминала статус выхода не менее 25 заданий после их исчезновения , но bash помнит намного больше.

Теперь, если вы это сделаете:

 foo & pid=$! ... bar & wait "$pid" 

У вас нет гарантии, что bar не будет присвоен тот же pid, что и foo (если foo закончил с помощью bar времени), так что, хотя это маловероятно, wait "$pid" может дать вам статус выхода из bar .

Вы можете воспроизвести его с помощью:

 bash -c '(exit 12; foo) & pid=$! while : bar & [ "$pid" != "$!" ]; do :;done wait "$pid"; echo "$?"' 

который (в конце концов) даст вам 0 вместо 12 .

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

 { foo_pid=$! while ps -p "$foo_pid" do ping -c 1 localhost done bar & ... read <&3 ret if [ "$ret" = 0 ]; then echo foo was sucessful. fi } 3< <(foo > logfile 2>&1; echo "$?") 

Да, вы можете рассчитывать на wait "$!" для получения статуса фоновой работы. При запуске в качестве сценария bash автоматически не собирает завершенные фоновые задания. Таким образом, если вы запустите wait , он соберет задание во время wait .

Вы можете проверить это с помощью простого скрипта:

 #!/bin/bash sh -c 'sleep 1; exit 22' & sleep 5 echo "FG: $?" wait %1 echo "BG: $?" 

Что будет выводить:

 FG: 0 BG: 22 

Я считаю, что ваше предположение верно. Вот выдержка из man bash относительно ожидания фоновых процессов.

Если n указывает несуществующий процесс или задание, статус возврата равен 127. В противном случае статус возврата – это статус выхода для последнего процесса или ожидаемого задания.

Так что, возможно, вам стоит проверить на 127

Есть аналогичный вопрос с совершенно другим ответом, чем может помочь.

Сценарий Bash ждет процессов и получает код возврата

изменить 1

Вдохновленный комментариями и ответами @ Стефана, я расширил его сценарий. Я могу начать около 34 фоновых процессов, прежде чем он начнет расшатываться.

tback

 $ cat tback plist=() elist=() slist=([1]=12 [2]=15 [3]=17 [4]=19 [5]=21 [6]=23) count=30 #start background tasksto monitor for i in 1 2 3 4 do #echo pid $i ${plist[$i]} ${slist[$i]} (echo $BASHPID-${slist[$i]} running; exit ${slist[$i]}) & plist[$i]=$! done echo starting $count background echos to test history for i in `eval echo {1..$count}` do echo -n "." & elist[$i]=$! done # wait for each background echo to complete for i in `eval echo {1..$count}` do wait ${elist[$i]} echo -n $? done echo "" # Now wait for each monitored process and check return status with expected failed=0 for i in 1 2 3 4 do wait ${plist[$i]} rv=$? echo " pid ${plist[$i]} returns $rv should be ${slist[$i]}" if [[ $rv != ${slist[$i]} ]] then failed=1 fi done wait echo "Complete $failed" if [[ $failed = "1" ]] then echo Failed else echo Success fi exit $failed $ 

на моей системе производит

 $ bash tback 14553-12 running 14554-15 running 14555-17 running starting 30 background echos to test history 14556-19 running ..............................000000000000000000000000000000 pid 14553 returns 12 should be 12 pid 14554 returns 15 should be 15 pid 14555 returns 17 should be 17 pid 14556 returns 19 should be 19 Complete 0 Success 
  • Удалить определенное слово в переменной
  • Доступ к экранам назад и вперед через скрипт bash
  • Сценарий оболочки Linux для перезагрузки нескольких Linux-машин
  • трубопровод с недетерминированным выходом
  • Найдите конкретную вложенность имен каталогов, например ... / project / dir1 / dir2
  • Поиск файлов, содержащих символы, отличные от ASCII
  • Как остановить фоновый процесс, запущенный в том же скрипте, без выхода из сценария?
  • Как написать скрипт для автоматической компиляции и установки всех модулей Moksha?
  • Как создать столько переменных, сколько необходимо из сценария оболочки (bash)?
  • * .tar.gz резервное копирование
  • Как подключиться к Tar с помощью BASH?
  • Interesting Posts

    Добавить файлы в Centos Live CD

    Будут ли скопированы файлы, созданные в исходном каталоге после запуска `cp`?

    перечислить принадлежащий ему файл / каталоги и изменить его разрешения

    Как использовать команду grep для поиска всех URL-адресов в файле базы данных, кроме гиперссылок и http://www.example.com, и сохранить их в другом файле

    Где положить команду `setxkbmap` в Xfce?

    Автоматизация установки гостевых дополнений VirtualBox через командную строку

    Очень медленное автозаполнение в Linux для Windows

    OpenBox привязка мыши для перетаскивания окна к краю экрана

    Добавьте текст с эхом, но начните с новой строки, если файл не пуст

    Отказоустойчивая система Wifi-LTE, усиливает интерфейсы WiFi и LTE для использования одного и того же IP-адреса

    Цитирование через строки в нескольких файлах (bash)

    Я не могу удалить файл даже после изменения права собственности и разрешений

    Удаление инструкции по установке Debian

    Анализ текстового файла с помощью awk

    Сделать Trickle получить правильную $ PATH

    Linux и Unix - лучшая ОС в мире.