В этой инструкции я расскажу как создать приложение для последовательного запуска нескольких программ или исполняемых файлов так, чтобы после запуска это приложение не оставалось открытым (то есть не занимало место в пенил Dock).
У меня была такая задача: По запуску моего приложения нужно запустить rlm сервер и потом запустить приложение BricsCAD. При этом программа которая запускает rlm и потом (на тот момент я не разобрался как добавлять rlm в автозапуск, но сейчас я разобрался и для BricsCAD эта инструкция уже не актуальна, по крайней мере для меня).
Я нуб в использовании bash, Apple Script и Automator. Возможно решение этой проблемы банальное и я просто неправильно формулировал запрос в гугле (тогда напишите, как правильно задать вопрос при котором в поисковой выдаче будет решение описанной выше задачи)
Изначально загуглив я написал такой shell скрипт для последовательного запуска rlm и BricsCAD
#!/bin/bash
/Volumes/ShareFiles/rlm/rlm >/dev/null & /Applications/BricsCAD\ V21.app/Contents/MacOS/bricscad & sleep 0.01
exit
exit
Его можно положить в файл с расширением .command и в настройках терминала сделать так, чтобы терминал закрывал свое окно по команде exit. Как вы понимаете у такого подхода есть 2 минуса:
- Этот файл нельзя поместить в панель Dock
- Нужно менять стандартные настройки терминала (во-первых нужно не забыть изменить эту настройку в терминале иначе после запуска .command файла будет оставаться черное окно терминала, что может пугать обычных пользователей. Во-вторых кто-то реально пользуется терминалом и не хочет, что он закрывался по команде exit)
Я видел скрипт на языке Apple Script для отмотки времени и запуска одного приложения и решил свой скрипт тоже выполнять в Apple Script Editor и потом экспортировать в .app и вот какой скрипт у меня получился:
do shell script "PATH=/usr/local/bin:$PATH; /Volumes/ShareFiles/rlm/rlm >/dev/null & '/Applications/BricsCAD V21.app/Contents/MacOS/bricscad' & sleep 0.01;exit;exit"
Это решило последние 2 проблемы, но оставался один раздражающий меня нюанс - экспортированное приложение после запуска все время висело в панели Dock пока я не завершу работу BricsCAD (об этой задаче я писал в самом начале) и для решения этой проблемы я потратил больше всего времени.
В ходе поисков решения этой проблемы я наткнулся на эти 2 страницы, они были полезны, но не помогли решить проблему: https://stackoverflow.com/questions/10247721/on-writing-a-linux-shell-script-to-safely-detach-programs-from-a-terminal/ https://discussions.apple.com/thread/2179510
В ходе тестирования я пробовал такие версии своего Apple Script:
-
do shell script "PATH=/usr/local/bin:$PATH; /Volumes/ShareFiles/rlm/rlm >/dev/null & '/Applications/BricsCAD V21.app/Contents/MacOS/bricscad' & sleep 0.01 &> /dev/null &"
-
do shell script "exec /Volumes/ShareFiles/rlm/rlm &> /dev/null & '/Applications/BricsCAD V21.app/Contents/MacOS/bricscad' & sleep 0.01 &> /dev/null &"
-
do shell script "exec /Volumes/ShareFiles/rlm/rlm & exec '/Applications/BricsCAD V21.app/Contents/MacOS/bricscad' &> /dev/null &"
Потом от своего друга я узнал, что shell скрипты можно еще выполнять в приложении Automator. Я протестировал несколько вариаций своего скрипта и вот этот вариант оказался самым оптимальным:
exec /Volumes/ShareFiles/rlm/rlm &> /dev/null & '/Applications/BricsCAD V21.app/Contents/MacOS/bricscad' & sleep 0.01 &> /dev/null &
Но с Automator тоже есть нюанс - пока работает BricsCAD вверху в панели меню будет крутится шестеренка от Automator и она пропадет только после завершения BricsCAD. Это приемлемый вариант, но не совсем идеальный (из-за шестеренки вверху), поэтому я продолжил попытки решить описанную проблему с помощью Apple Script.
Я решил использовать более нативный путь и запускать BricsCAD не с помощью его бинарного файла, а с запускать его как приложение и вот что у меня получилось:
do shell script "exec /Volumes/ShareFiles/rlm/rlm &> /dev/null & open '/Applications/BricsCAD V21.app'"
И теперь это работает как надо - после запуска экспортированного приложения оно появляется в панели Dock буквально на секунду, потом исчезает и появляется иконка приложения BricsCAD. Я немного поразмыслил и решил модифицировать старый скрипт, и в ходе экспериметнов я выяснил, что если выполнять его в Apple Script не в одну строку, а в 2, то эффект будет тот же. Вот результат:
do shell script "exec /Volumes/ShareFiles/rlm/rlm &> /dev/null &"
do shell script "exec '/Applications/BricsCAD V21.app/Contents/MacOS/bricscad' &> /dev/null &"
Либо для запуска BricsCAD использовать нативную Apple Script команду. Тогда скрипт будет выглядеть так:
do shell script "exec /Volumes/ShareFiles/rlm/rlm &> /dev/null &"
tell application "'/Applications/BricsCAD V21.app" to activate
Следующим этапом у меня появилась если rlm нужен только для BricsCAD, то, наверное, лучше после завершения работы BricsCAD также завершать работу RLM. Это можно сделать вручную через приложение Activity Monitor, но естественно это не наш путь. Я нагуглил, что можно с помощью специальных утилит найти процессы rlm и убить их, а можно завершить работу rlm с помощью утилиты rlmutil. Вот тут есть пример использования - https://docs.arnoldrenderer.com/display/RLAG/Shutting+down+a+License+Server
./rlmutil rlmdown RLM
Но после ввода этой команды терминал ждет подтверждения от пользователя. Я нашел несколько способов решения этой проблемы. Можно выполнить ./rlmutil --help и посмотреть документацию по этой утилите и понять, что нужна нам команда это:
./rlmutil rlmdown RLM -q
Также это можно сделать с помощью
yes | ./rlmutil rlmdown RLM
или
echo y| ./rlmutil rlmdown RLM
Перепробовав несколько вариантов доработки своего скрипта я нашел вариантм при котором rlm будет завершаться после завершения работы BricsCAD. Вот то, что у меня получилось для Apple Script:
do shell script "exec /Volumes/ShareFiles/rlm/rlm &> /dev/null &"
do shell script "sleep 0.01 & '/Applications/BricsCAD V21.app/Contents/MacOS/bricscad' || /Volumes/ShareFiles/rlm/rlmutil rlmdown RLM -q &> /dev/null &"
Я не владею навыками работы в терминале на очень очень очень базовом уровне. Надеюсь я найду когда-нибудь время, чтобы улучшить свои знания по работе с bash. Если у вы знаете как можно улучшить представленный здесь код - я не против аргументированной критики.
Вот так я решил задачу с тем, что мне нужно создать приложение для последовательного запуска двух приложений и завершения работы первого приложения после завершения работы второго приложения.
Надеюсь это кому-то поможет.