Запуск команды всякий раз, когда Mac загружается с launchctl / plist

5

Мне нужно выполнить nohup nice synergys -f --config ~/bin/conf/synergy.conf &команду всякий раз, когда компьютер загружается.

Как написано в этом посте , я придумал следующий код plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>synergy</string>
    <key>ProgramArguments</key>
    <array>
        <string>nohup nice /usr/bin/synergys -f --config /Users/USER/bin/conf/synergy.conf &</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>LaunchOnlyOnce</key>
    <true/>
</dict>
</plist>

И запустил эту команду.

launchctl load ./synergy.plist 

Тем не менее, я получил это сообщение об ошибке.

launchctl: no plist was returned for: ./synergy.plist
launchctl: no plist was returned for: ./synergy.plist
nothing found to load

Что не так с моим списком? Или моя команда launchctrl неверна в настройках?

prosseek
источник

Ответы:

12

Непосредственная проблема заключается в том, что ваш файл .plist неправильно отформатирован - содержимое <string>...</string>должно быть закодировано с помощью HTML-сущностей, т.е. &должно быть закодировано как &amp;(примечание: вы можете проверить формат файлов .plist с помощью plutil -lint filename.plist). Но есть некоторые другие изменения, которые необходимо внести ...

Запуск программ с помощью launchd отличается от запуска их из оболочки. Самое большое отличие состоит в том, что из оболочки вы хотите, чтобы программа уходила в фоновый режим и запускалась независимо от оболочки, поэтому вы переносите ее nohup ... &. С launchd, на самом деле лучше для программы оставаться на «переднем плане», так что launchd может следить за этим.

Кроме того, элементы ProgramArguments не будут анализироваться оболочкой, поэтому перечисление команды и ее аргументов с пробелами между ними не работает - сделать каждый аргумент отдельным элементом массива.

Вот мой удар по синергии .plist. Я не проверял это, поэтому может потребоваться небольшая настройка для правильной работы (см. Примечания ниже):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>local.synergy</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/synergys</string>
        <string>-f</string>
        <string>--config</string>
        <string>/Users/USER/bin/conf/synergy.conf</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>Nice</key>
    <integer>10</integer>
    <key>KeepAlive</key>
    <false/>
    <key>AbandonProcessGroup</key>
    <true/>
</dict>
</plist>

Последние два ключа описывают, как должен запускаться launchd, если / когда программа synergys завершает работу. По умолчанию он убивает все сохранившиеся подпроцессы и запускает новый экземпляр; эти две клавиши подавляют обе части, которые могут быть или не быть тем, что вы хотите. Кроме того, одна вещь, которая не делает этого с вашей версией nohup, это перенаправление stdin и stdout на nohup.out (на случай, если терминал отключится); вместо этого IIRC launchd регистрирует вещи, которые им отправляют. Если synergys используется для отправки вывода, вы можете добавить что-то вроде этого в .plist:

    <key>StandardOutPath</key>
    <string>/dev/null</string>
    <key>StandardErrorPath</key>
    <string>/dev/null</string>

Кроме того, как сказал mankoff, вы должны поместить это в ~ / Library / LaunchAgents, чтобы он автоматически загружался при каждом входе в систему. О, и вам, вероятно, следует добавить local.префикс к имени файла (как я сделал с меткой), чтобы соответствовать к соглашению об обратном именовании DNS.

Гордон Дэвиссон
источник
1
О боже, спасибо за это: plutil -lint filename.plist
Джон Хиннеган,
Отличный совет для плутиля, очень удобно
vdubgeek
Для чего нужен ключ Niceи целое число 10?
hobbes3
Также есть причина, почему вы не используете, а <key>Program</key><string>/usr/bin/synergys</string>затем передать остальные аргументы как <key>ProgramArguments</key><array><string>Argument_1</string><string>Argument_2</string></array>?
hobbes3
1
@ hobbes3: Niceзначение запускает программу с пониженным приоритетом, что эквивалентно команде nice в оригинале. Причина, по которой я не использовал <key>Program</key>это избыточность (и лень): вы должны были бы указать /usr/bin/synergysкак Program и также как первый элемент ProgramArguments.
Гордон Дэвиссон