
У меня есть скрипт оболочки bash, в котором я передаю некоторые данные примерно через 5 или 6 различных программ, а затем конечные результаты помещаю в файл с разделителями табуляции.
Затем я делаю то же самое еще раз для отдельного похожего набора данных и вывожу результаты во второй файл.
Затем оба файла вводятся в другую программу для сравнительного анализа. например, для упрощения.
Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv
AnalysisProg -i Data1res.csv Data2res.csv
У меня такой вопрос: как сделать так, чтобы шаги 1 и 2 выполнялись одновременно (например, с помощью &), но запустить шаг 3 (AnalysisProg) только после завершения обоих?
спасибо
ps AnalysisProg не будет работать на потоке или fifo.
решение1
Используйте wait
. Например:
Data1 ... > Data1Res.csv &
Data2 ... > Data2Res.csv &
wait
AnalysisProg
воля:
- запустите каналы Data1 и Data2 как фоновые задания
- подожди, пока они оба закончат
- запустить AnalysisProg.
См., например,этот вопрос.
решение2
Ответ cxw, без сомнения, является предпочтительным решением, если у вас всего 2 файла. Если 2 файла — это просто примеры, а на самом деле у вас 10000 файлов, то решение '&' не сработает, так как это перегрузит ваш сервер. Для этого вам понадобится инструмент вроде GNU Parallel:
ls Data* | parallel 'cat {} | this | that |theother | grep |sed | awk |whatever > {}res.csv
AnalysisProg -i *res.csv
Чтобы узнать больше о GNU Parallel:
- Посмотрите вступительное видео для краткого ознакомления: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
- Пройдитесь по учебнику (man parallel_tutorial). Ваша командная строка будет вам за это благодарна.
решение3
Один из способов сделать это может выглядеть примерно так:
AnalysisProg <<PREPROCESS /dev/stdin
$(
{ process1=$( pipe | line | 1 >&2 & echo $! )
process2=$( pipe | line | 2 >&2 & echo $! )
while ps -p $process1 $process2 >/dev/null; do
sleep 1
done
} 2>&1
)
#END
PREPROCESS
Таким образом, вы переводите оба конвейера в фоновый режим, но все равно ждете, пока они закончат выполнение, прежде чем объединить их вывод в stdin, который оценивается в here-документе и передается в AnalysisProg. Если вы можете использоватьwait
это даже лучше чемwhile ps
цикл, но, в зависимости от оболочки,wait
может возразить, если вы дадите ему указание подождать в процессе, которыйне является дочерним элементом текущей оболочки.
Также обратите внимание, что метод выше будет собирать вывод - так что оба процесса будут писать одновременно. Если вы вместо этого хотите их разделить или добавить один к другому, возможно, вы могли бы сделать:
AnalysisProg 3<<PREPROCESS /dev/fd/3 /dev/stderr
$(
process1=$(... >&2 ...) 2>/dev/fd/3
...
} 3>/dev/fd/3 2>/dev/stderr
)
Я уже демонстрировал эти концепции. Вероятно, лучшие демонстрации — этоздесьиздесь.
решение4
Попробуйте использовать это.
rm -f Data1Res.csv
rm -f Data2Res.csv
Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv &
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv &
while true
do
ps aux | grep -v grep | grep -i -E 'Data1Res.csv|Data2Res.csv' &> /dev/null
if [ $? -ne 0 ]
then
AnalysisProg -i Data1res.csv Data2res.csv
exit 0
fi
done