Как заставить массовые bash-скрипты запускаться один за другим - PullRequest
1 голос
/ 17 октября 2019

У меня есть 2 процесса, которые мне нужно запустить один за другим для большого количества файлов.

for file in ` basename -a /path/to/some/data-*`; do

        #Manages the number of jobs and cores
        SCRIPTNAME=/path_to_my/script.sh
        NCORES=90
        while [ $(ps -ef | grep -v grep | grep $SCRIPTNAME | wc -l) -ge $NCORES ]; do
            sleep 1m
        done
        echo "${SCRIPTNAME} ${file}"
        bash $SCRIPTNAME $file &
done

После того, как все эти файлы будут выполнены, я бы хотел запустить другой файл впохожим образом, но я не могу просто добавить еще один цикл for после этого, потому что он запустится до завершения других. Как запустить следующий цикл for после того, как из первого цикла больше не будет запущено ни одного процесса?

Ответы [ 2 ]

2 голосов
/ 17 октября 2019

Я бы посоветовал вам взглянуть на snakemake .

. Первоначально это было сделано для случая, когда необходимо анализировать большой набор биологических образцов параллельно, когда некоторые шаги зависят отпредыдущие шаги. Таким образом, если ваш inputfile1 уже завершил шаг 1, snakemake уже запустил step2 для inputfile 1, даже если шаг 1 для inputfile2 все еще может выполняться. В зависимости от того, сколько входных файлов и сколько вычислительных ресурсов у вас есть, этот подход может сэкономить вам драгоценное время.

В противном случае, если snakemake не вариант, я бы выбрал подход Erans.

Иливозможно, ваш первый сценарий добавит строку в файл-пустышку в качестве самой последней команды и будет выполнять цикл while, проверяющий каждые 30 секунд (или более), содержит ли этот файл то же количество строк, что и ваши входные данные, перед тем как он начнет второй запуск. Таким образом, он также не запустится, если один из ваших первых сценариев потерпит неудачу.

Это может выглядеть примерно так:

tot=$(ls /path/to/some/data-* | wc -l)
while sleep 30; do
    lines=$(wc -l dummie.txt)
    if [ "$tot" == "$lines"]; then
        echo -e "All jobs from first script finished! You can now start second script"
    fi
done

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

1 голос
/ 17 октября 2019

bash $SCRIPTNAME $file & возвращает идентификатор процесса фонового процесса. Соберите все идентификаторы и используйте команду wait, чтобы удерживать ее, пока все не будет сделано.

...