Запустите команду bash после завершения процесса

Запустите команду bash после завершения процесса

У меня есть два скрипта, которые используют GPU и обучают модели ML. Я хочу запустить их перед сном, чтобы они работали ночью, и я ожидаю увидеть какие-то результаты утром.

Но поскольку память графического процессора ограничена, я хочу запускать их последовательно, а не параллельно.

Я могу сделать это с помощью python train_v1.py && python train_v2.py; но, скажем, я начал обучать train_v1. Тем временем, поскольку обучение занимает много времени, я начал и закончил реализацию второго скрипта, train_v2.py, и хочу запустить его автоматически, когда python train_v1.pyон будет завершен.

Как мне этого добиться? Спасибо.

решение1

Вот подход, который не подразумевает цикл и проверку того, активен ли еще другой процесс, или вызов train_v1.pyспособом, отличным от того, который вы обычно делаете:

$ python train_v1.py
^Z
[1]+  Stopped                 python train_v1.py
$ % && python train_v2.py

Это ^Zя нажимаю Ctrl+ Z, когда процесс засыпает, train_v1.pyпосылая ему SIGTSTPсигнал. Затем я говорю оболочке разбудить его с помощью %, используя его как команду, к которой я могу добавить && python train_v2.pyв конце. Это заставляет его вести себя так же, как если бы вы сделали это python train_v1.py && python train_v2.pyс самого начала.

Вместо %, вы также можете использовать fg. Это то же самое. Если вы хотите узнать больше об этих типах функций оболочки, вы можете прочитать о них враздел «УПРАВЛЕНИЕ ЗАДАНИЯМИ» на странице руководства bash.

EDIT: Как продолжать добавлять в очередь

Как отметил jamesdlin в комментарии, если вы попытаетесь продолжить шаблон, train_v3.pyнапример, добавить до начала v2, вы обнаружите, что не сможете:

$ % && python train_v2.py
^Z
[1]+  Stopped                 python train_v1.py

train_v1.pyОстанавливается только потому train_v2.py, что не был запущен, а остановить/приостановить/перевести в спящий режим то, что еще не запущено, невозможно.

$ % && python train_v3.py

приведет к тому же результату, что и

python train_v1.py && python train_v3.py

поскольку %соответствует последнему приостановленному процессу. Вместо того, чтобы пытаться добавлять v3так, следует использовать историю:

$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py

Можно выполнить расширение истории, как указано выше, или вызвать последнюю команду с помощью сочетания клавиш (например, up) и добавить v3 в конец.

$ % && python train_v2.py && python train_v3.py

Это то, что можно повторять, чтобы добавить что-то еще в конвейер.

$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py
^Z
[1]+  Stopped                 python train_v1.py
$ !! && python train_v4.py
% && python train_v2.py && python train_v3.py && python train_v4.py

решение2

Если вы уже запустили python train_v1.py, вы, возможно, могли бы использовать pgrepопрос этого процесса до тех пор, пока он не исчезнет, ​​а затем запустить второй скрипт Python:

while pgrep -u "$USER" -fx 'python train_v1.py' >/dev/null
do
    # sleep for a minute
    sleep 60
done
python train_v2.py

Используя -fand, -xвы сопоставляете точную командную строку, которая использовалась для запуска первого скрипта Python. В некоторых системах pgrepреализует -qопцию, которая делает его тихим (как и grep -q), что означает, что перенаправление на /dev/nullне понадобится.

Эта -uопция ограничивает соответствие тем командам, которые запускаете вы (а не ваш друг или другой человек в той же системе).

Если вы еще не приступили к первому скрипту:

Как упоминалось в комментариях, вы можете просто запустить второй скрипт сразу после первого. Тот факт, что второй скрипт не существует или еще не готов к запуску, не имеет значения (при условии, что он готов к запуску, когда первый скрипт завершится):

python train_v1.py; python train_v2.py

Если сделать это таким образом, второй скрипт запустится независимо от статуса выхода первого скрипта. Использование &&вместо ;, как вы показываете в вопросе, также будет работать, но потребует успешного завершения первого скрипта для запуска второго скрипта.

решение3

Вы можете запустить первый скрипт с помощью

python train_v1.py; touch finished

Затем просто создайте цикл, который регулярно проверяет, finishedсуществует ли:

while [ ! -f finished ] ; do     
    sleep 5
done
python train_v2.py
rm finished

решение4

Если вам не нужно знать статус завершения первого скрипта, то я рекомендую что-то вродечто написал Кусалананда.

Если вам действительно нужно знать статус выхода (в данном случае вы его, вероятно, не знаете, но кто-то другой может поискать решение, которое это делает), то это сложнее. Я написалнебольшая утилита Linuxpwaitкоторый позволяет дождаться завершения процесса и узнать его статус выхода.

Связанный контент