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

Я не вижу простого способа сделать это в ударе, но конечно можно повредить проблему в несколько шагов как вырезание префикса, запоминание расширения и затем замена нескольких экземпляров расширения с единственным.

for file in blue*+(.png); do tmp="${file#blue}"; extension="${file##*.}"; echo "$file" "${tmp/%+(.$extension)/}.$extension";done

если Вы довольны результатами, просто введите...

^echo^mv

и все волшебство произойдет.:)

11
20.09.2017, 12:59
4 ответа

Будет ли более эффективная обработка замены, особенно если не нужно сохранять файлы ВыходA и ВыходB и заботиться только о Результате ? Будет ли это особенно экономить время, потому что при медленном вводе/выводе на диск сохранение файлов OutputA и OutputB может быть шагом ограничения скорости?

combine  <(somethingElse InputA)  <(somethingElse InputB)  >  Result

Замена процесса позволяет поместить команду внутрь <(...здесь...) вместо сохранения вывода в файл, а затем прочитать из него как входной сигнал на шаге "Комбинировать".

Если память является ограничением, и размер outputA и outputB больше, чем может храниться в памяти, будет ли она сбрасывать со счетов всю цель?

Будет ли combine дожидаться завершения обоих процессов, прежде чем они начнут выполняться?

.
3
27.01.2020, 19:57

В вашем примере команда comb будет запущена сразу после выхода подоболочки (и при условии, что последний фоновый процесс был запущен без ошибок). Подоболочка выйдет сразу после запуска заданий, поскольку нет команды wait .

Если вы хотите выполнить команду на основе возвращаемого значения двух или более одновременных фоновых процессов, я не вижу другого способа, кроме использования временных файлов для возвращаемых значений. Это связано с тем, что wait может возвращать только возвращаемое значение одного из процессов, которых он ожидает. Кроме того, поскольку фоновые процессы должны запускаться в подоболочках, чтобы вообще получить возвращаемые значения, они не могут быть сохранены в переменных. Вы можете сделать:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

tmp1=$(mktemp)
tmp2=$(mktemp)

( somethingElse InputA >OutputA; echo $? >"$tmp1" ) &
proc1=$!

( somethingElse InputB >OutputB; echo $? >"$tmp2" ) &
proc2=$!

wait "$proc1" "$proc2"

read ret1 <"$tmp1"
read ret2 <"$tmp2"
[ "$ret1" = 0 && "ret2" = 0 ] && combine OutputA OutputB >Result

rm "$tmp1" "$tmp2"

Если вас не интересуют возвращаемые значения, вы можете просто запустить задания в обычном режиме и использовать wait :

something InputA >IrrelevantA &
something InputB >IrrelevantB &

somethingElse InputA >OutputA &
proc1=$!

somethingElse InputB >OutputB &
proc2=$!

wait "$proc1" "$proc2"
combine OutputA OutputB >Result
13
27.01.2020, 19:57

Я на самом деле демонстрирую, как именно такие вещи можно сделать, в другом ответе здесь . Этот ответ был на вопрос об обеспечении поддержки 2 журналов фоновым процессом, поэтому я продемонстрировал это с помощью 10.

Demo Script

cat <<-\DEMO >|${s=/tmp/script} 
printf 'tty is %s\nparent pid is %s\npid is pid=%s\n' \
     "$(tty)" "$PPID" "$$"
exec 1>&2 ; nums=$(seq 0 9)
rm ${files=$(printf "/tmp/file%s\n" $nums)}
for n in $nums ; do { for f in $files ; do
    echo "Line $n" >>"$f" ; done
sleep 1 ; } ; done
#END
DEMO

Run Demo

s=/tmp/script ;chmod +x $s ;info="$(($s &)2>&- &)"
echo "$info" ; pid="${info##*=}" ; echo
while ps -p $pid >/dev/null ; do sleep 3 ; done
for f in /tmp/file[0-9] ; do
    printf 'path : %s\tline count : %s\n' \
        $f $(<$f wc -l)
done

Вывод:

tty is not a tty
parent pid is 1
pid is 12123

path : /tmp/file0    line count : 10
path : /tmp/file1    line count : 10
path : /tmp/file2    line count : 10
path : /tmp/file3    line count : 10
path : /tmp/file4    line count : 10
path : /tmp/file5    line count : 10
path : /tmp/file6    line count : 10
path : /tmp/file7    line count : 10
path : /tmp/file8    line count : 10
path : /tmp/file9    line count : 10

Выше показано. Он создает и запускает сценарий с именем / tmp / script , chmod как исполняемый файл и запускает его в & background из и фоновый (подоболочка) .

Сценарий rms / tmp / file0-9 10 файлов и отображает строку каждую секунду во все 10 из них. Я захватываю некоторую $ info из отвергнутого процесса и представляю ее через $ (подстановка команд). Хотя ps все еще сообщает о записанном мной $ pid , я знаю, что он все еще работает, поэтому я сплю. Когда он завершается, строки во всех 10 файлах считаются с wc.

После того, как вы вызываете процесс таким образом, вы можете свободно закрыть его исходный родительский процесс, и он продолжит работу - от него фактически отказались. Это также означает, что вы не можете использовать обычную команду wait , но ожидание возврата ps должно быть более надежным в любом случае.

Я думаю, что стоит упомянуть, что процесс фактически изначально вызывается в $ (подстановка команд) и printfs me the $ info Я хочу, чтобы Я могу эффективно это контролировать.Но как только он сбрасывает свой терминальный вывод с помощью exec 1> & 2 (который закрыт в той же подоболочке с 2> & - ), процесс уходит, и у меня ждать его на другом конце. Это лучшее из обоих миров, особенно если вы используете его для обработки входных каналов, пока вы можете сосредоточиться на всех перенаправлениях и лидерах процессов.

Все остальное здесь просто для демонстрации. Все, что вам нужно для запуска этого сценария, - это верхний сценарий и:

info="$(($script_path &)2>&- &)"    

ПРИМЕЧАНИЕ: Он выводит на терминал только то, что я хотел продемонстрировать. Как отмечено в $ PPID, этот процесс запрещен терминалом и является прямым потомком $ PID 1.

Если вы хотите запустить два из них одновременно и ждать их, вы должны могли просто передать ps оба своих pid-идентификатора и подождать.

0
27.01.2020, 19:57

Вы можете использовать команду wait:

(echo starting & sleep 10 & wait) && echo done

Вы видите, что строка "start" происходит сразу, а "done" ждет 10 секунд.

2
27.01.2020, 19:57

Теги

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