#linux #bash #terminal #sh
#linux #bash #терминал #sh
Вопрос:
У нас есть следующий вариант использования:
- Запустите команду (стороннюю, не контролирующую исходный код), которая запускает сервер разработки со встроенным «наблюдателем за файлами», который перекомпилирует исходные файлы и перезапускает сервер при обнаружении изменений в файлах (и публикует выходные данные в папке /dist только в самые последние секунды ~ 30-секундного процесса; папка /dist создается как последний шаг процесса публикации).
- Запустите вторичную команду «постобработки», которая должна выполняться только тогда, когда предыдущая команда успешно запустила сервер и опубликовала файлы в папке / dist (эта команда публикует некоторые дополнительные статические файлы в папке / dist, поэтому это зависит от существования папки).
При таком подходе возникает несколько проблем:
- Команда с шага 1 «крадет» терминал, что означает, что он никогда не завершается (из-за file watcher). Таким образом, выполнение двух команд последовательно не является вариантом.
- Вторая команда должна дождаться, пока терминал 1 выведет определенную строку (например, «Сервер запущен»), что означает, что папка /dist теперь готова. Только тогда это должно вступить в силу.
На данный момент мы ввели разумный режим «ожидания» в начале второго терминала, просто чтобы он ожидал, пока первая команда выполнит публикацию и папка /dist будет существовать. Проблема в том, что на более медленных компьютерах этого периода ожидания недостаточно (вторая команда начинает выполняться до того, как у первой было достаточно времени для создания папки /dist). На быстрых компьютерах первая команда завершается довольно быстро, и перед запуском второй команды требуется довольно неудобное время ожидания. Для целей разработки это очень раздражает.
Есть ли способ автоматизировать этот двухэтапный процесс?
Перефразируя:
Есть ли способ создать терминал X, запустить вторичный терминал Y и дождаться, пока терминал Y выведет определенную строку, прежде чем выполнять какое-либо действие. И предпочтительно выполнять это же действие, когда терминал Y выводит указанную строку снова и снова.
Мы предпочитаем решение для Windows, если это возможно, но Linux также является вариантом, если решение не найдено.
Комментарии:
1. Если вы ищете решение для Windows, почему вы не пометили этот вопрос как
Windows
?2. В окне Linux я должен использовать
inotifywait
команду для обнаружения создания каталога /dist .
Ответ №1:
Этот ответ предназначен для решения Linux;
Итак, часть первая: автоматический запуск двух терминалов. Нужно ли, чтобы терминалы, после того как они автоматизированы, действительно были видны кому-либо? Если нет, я бы запустил их на экранах. screen
Команда позволяет создавать виртуальные терминалы, которые можно подключать и отсоединять по мере необходимости. Чтобы автоматически запустить экран с запущенной командой, используйте
screen -S meaningful_service_name -d -m ./ ProcessA
Здесь «-S» задает название экрана на что-то понятное человеку, на что можно ссылаться позже, а «-d -m» означает запустить экран в отключенном режиме (идеально подходит для сценариев запуска) и запустить в нем следующую команду. Эти экраны будут работать в фоновом режиме (пока программы не завершатся или что-то не уничтожит их), и могут быть подключены с терминала пользователем с screen -r meaningful_service_name
Затем пользователь может отключиться, нажав Ctrl-A, а затем D. Это также позволяет вам удаленно отслеживать процессы через SSH.
—
Что приводит ко второй части: Запуск ProcessB только после вывода A на экран. Экран позволяет нам делать так называемые «скриншоты» его текущего вывода. Это сохраняется как текстовый файл, поскольку (виртуальный) терминал основан на тексте.
screen -S meaningful_service_name -p 0 -X hardcopy /some/file/location.txt
Здесь «-p» указывает, каким по сути является текущее окно (которое обычно должно быть равно нулю), а «-X» означает выполнение следующей команды. Теперь, когда у вас есть текстовый файл с выводом ProcessA, вы можете искать в нем, как в любом другом текстовом файле.
#!/bin/bash
while true; do
screen -S meaningful_service_name -p 0 -X hardcopy /some/file/location.txt
if [[ $(cat /some/file/location.txt | grep "ProcessA's Output" | wc -l) -ge 1 ]]
then
break
fi
sleep 2
done
./ ProcessB