Остановится ли сборка после обрыва SSH на удалённом Mac? Решение для длительных задач в 2026 году
Руководство для разработчиков, которые запускают xcodebuild, тесты, Archive или загрузку приложения через SSH на удалённом Mac. Мы разделяем SSH-соединение, Shell-сеанс, процесс сборки, пользовательский вход и обработку публикации, а затем даём схему проверки после обрыва, выхода пользователя и перезапуска хоста.
Сборку на удалённом Mac после обрыва SSH нельзя считать надёжной, если она была запущена прямо в интерактивном терминале: для разовой длительной задачи используйте повторно подключаемую сессию и отдельные stdout, stderr, код завершения и каталог артефактов, а регулярные ночные сборки передавайте CI Runner или управляемому фоновому заданию. Если в процессе участвуют Simulator, Keychain или графическая авторизация, отдельно проверяйте пользовательский и графический сеанс.
Эта инструкция предназначена разработчикам на Windows или Linux, которые через SSH запускают xcodebuild, тесты, Archive или загрузку приложения на удалённом Mac. Она также пригодится небольшой команде, которой нужны ночные сборки и публикации, а также администратору, который после обрыва сети не понимает, продолжилась ли задача, завершилась с ошибкой или просто потеряла вывод.
01 Сначала определите, что именно оборвалось
Слово «обрыв SSH» описывает только сетевое соединение между локальным компьютером и удалённым Mac. Оно не отвечает на более важный вопрос: что произошло с Shell-сеансом, процессом xcodebuild, пользовательским входом и уже начатой обработкой публикации.
После потери связи возможны как минимум три результата:
- процесс завершился вместе с интерактивным сеансом;
- сборка продолжилась, но экранный вывод пропал;
- процесс остался запущен, однако завис на подписи, Simulator, доступе к Keychain или сетевом этапе.
Поэтому мигающий терминал, исчезнувшее SSH-окно или найденный процесс не являются доказательством успеха. Для команды завершённая задача должна подтверждаться кодом выхода и результатом, а для тестов — также сохранённым xcresult. В документации Apple о переменных окружения и результатах сборки Xcode отдельно описывается значение состояния завершения: его следует сохранять как машинно проверяемый признак, а не выводить из последних строк лога.
SSH включается на самом Mac через Remote Login, а формат входа и доступные пользователи зависят от системной настройки Remote Login в macOS. Однако успешный вход говорит только о доступности удалённой оболочки. Он не гарантирует, что прежняя оболочка, пользовательский контекст и процесс сборки сохранились.
02 Первый сценарий: разовая сборка в повторно подключаемой сессии
Для ручного Build, Test или Archive не требуется сразу строить полноценную систему непрерывной интеграции. Но запускать длительную команду напрямую после входа по SSH рискованно. Сначала создайте отдельный рабочий каталог, где будут находиться журнал, код результата и артефакты.
Пример ниже использует только заменяемые значения:
mkdir -p "<WORK_DIR>/logs" "<WORK_DIR>/artifacts"
cd "<PROJECT_DIR>"
xcodebuild \
-workspace "<WORKSPACE>.xcworkspace" \
-scheme "<SCHEME>" \
-configuration Release \
-destination 'generic/platform=iOS' \
archive \
-archivePath "<WORK_DIR>/artifacts/<APP>.xcarchive" \
> "<WORK_DIR>/logs/archive.stdout.log" \
2> "<WORK_DIR>/logs/archive.stderr.log"
printf '%s\n' "$?" > "<WORK_DIR>/logs/archive.exit"
Практическая проблема этого примера в том, что при аварийном завершении оболочки Shell оператор printf может не выполниться. Поэтому для повторяемой работы команда должна запускаться внутри инструмента, который переживает отключение управляющего терминала, либо через заранее подготовленный скрипт-обёртку, который гарантированно записывает состояние завершения.
Последовательность действий:
- Войдите по SSH и перейдите в каталог конкретного проекта.
- Проверьте версию Xcode, рабочий каталог, схему и доступность signing assets.
- Создайте отдельные файлы для стандартного и ошибочного вывода.
- Запустите задачу в повторно подключаемой сессии, а не в обычном интерактивном окне.
- Убедитесь, что путь
xcarchive,xcresultили другого результата уникален для этой попытки. - Намеренно закройте локальное SSH-соединение, не завершая удалённую сессию.
- Подключитесь снова и вернитесь в ту же сессию.
- После окончания проверьте код выхода, размер и содержимое артефакта, последние строки обоих логов.
- Только после этой проверки переходите к экспорту или загрузке.
Синтаксис параметров и доступные команды следует сверять с официальным справочником xcodebuild, поскольку наличие Xcode на хосте само по себе не означает, что выбранная схема и назначение доступны из командной строки.
03 Второй сценарий: разделите Archive, экспорт и публикацию
Длительный процесс нельзя считать одной неделимой командой. В типичной цепочке есть как минимум четыре самостоятельных состояния:
- компиляция и тесты;
- создание
xcarchive; exportArchiveс формированием дистрибутива;- передача файла и последующая обработка публикации.
Если сеть оборвалась во время передачи, повторный запуск всей цепочки может заново собрать проект, изменить временные файлы и усложнить расследование. Сначала найдите уже созданный архив. Apple описывает этапы Archive и экспорта подписанного продукта в Xcode, но конкретный успех в удалённой среде всё равно нужно подтверждать локальными файлами и журналами.
Для каждого этапа задайте отдельные признаки:
<WORK_DIR>/logs/archive.stdout.log
<WORK_DIR>/logs/archive.stderr.log
<WORK_DIR>/logs/archive.exit
<WORK_DIR>/logs/export.stdout.log
<WORK_DIR>/logs/export.stderr.log
<WORK_DIR>/logs/export.exit
<WORK_DIR>/logs/upload.stdout.log
<WORK_DIR>/logs/upload.stderr.log
<WORK_DIR>/logs/upload.exit
<WORK_DIR>/artifacts/<APP>.xcarchive
<WORK_DIR>/artifacts/exported/
Такой порядок позволяет принимать решение по фактам:
- есть корректный
xcarchive— не повторяйте Archive без причины; - архив есть, экспорт отсутствует — повторяйте только экспорт;
- экспорт есть, передача прервалась — сначала проверьте, был ли файл принят;
- команда загрузки завершилась успешно — это ещё не равно завершённой серверной обработке.
Последнее различие особенно важно для TestFlight и релизных операций. Документация о распространении приложения для тестирования и выпуска отделяет передачу сборки от дальнейших действий в системе публикации. После повторного входа проверяйте номер версии, номер сборки и запись о доставке, а не запускайте повторную отправку по одному лишь исчезновению терминального вывода.
Важно: не завершайте найденный процесс и не удаляйте каталог результата, пока не сохранены PID, оба лога, время последнего изменения файлов и текущий этап. Принудительная остановка может уничтожить единственное доказательство зависания; перед такой операцией зафиксируйте влияние и способ возврата.
04 Третий сценарий: ночные задачи передайте исполнителю
Повторно подключаемый терминал хорошо подходит для разового ручного Archive, но плохо масштабируется на ночные тесты, частые коммиты и регулярные релизы. В этих случаях важна не только живучесть процесса, но и предсказуемый контекст запуска: рабочий каталог, переменные окружения, учётная запись, доступ к Keychain, место хранения результата и уведомление об ошибке.
CI Runner подходит, если задачи запускаются по событию репозитория или по расписанию и должны оставлять историю попыток. launchd уместен для локального фонового задания на самом Mac, когда нужно запускать скрипт после загрузки или в определённом системном контексте. Apple описывает назначение и структуру таких заданий в документе о создании launchd jobs.
Не смешивайте эти варианты:
- повторно подключаемая сессия сохраняет ручной контекст и подходит для диагностики;
- CI Runner управляет повторяемыми заданиями, журналами попыток и триггерами;
launchdзапускает локальную работу в описанном контексте, но не решает автоматически вопросы подписи, публикации и хранения артефактов.
После настройки фонового задания сначала запускайте безопасную тестовую команду, а не настоящий релиз. Проверьте рабочий каталог, PATH, переменные подписи, права на папку логов и видимость результата от имени той учётной записи, которая будет выполнять работу. Затем протестируйте выход пользователя и перезапуск Mac. Если после загрузки процесс появился, но Keychain или Simulator недоступны, задание нельзя считать восстановленным.
Для систем с несколькими пользователями важно учитывать различие между процессом и сеансом входа. Документация о системных контекстах процессов и пользовательских сеансах объясняет, почему фоновый процесс и интерактивный графический сеанс не являются взаимозаменяемыми. Это особенно критично для подписания и тестов, использующих Simulator.
05 Четвёртый сценарий: отдельно проверьте Simulator и Keychain
Чистая командная компиляция может продолжиться после разрыва SSH, но это не доказывает работоспособность всей iOS-сборки. Симулятор, ключи подписи и операции, требующие графического разрешения, зависят от другого контекста.
Разделите диагностику на четыре контрольных задания:
- компиляция без Simulator и без обращения к секретному хранилищу;
- тесты на выбранном Simulator;
- Archive с использованием signing assets;
- экспорт и передача результата.
Для каждого задания записывайте, был ли пользователь залогинен в графическую сессию, заблокирован ли экран, кто владел процессом и откуда был запущен скрипт. Руководство по запуску тестов и интерпретации результатов Xcode полезно использовать при проверке xcresult, но оно не заменяет проверку конкретного удалённого сеанса.
Не ослабляйте разрешения Keychain и фонового запуска как первую реакцию на сбой. Сначала сохраните ошибку, определите затронутую учётную запись и проверьте, воспроизводится ли проблема только после SSH-обрыва, после выхода пользователя или после перезапуска. Если всё же требуется изменение разрешений, зафиксируйте исходное состояние, ограничьте область изменения и заранее опишите обратную операцию.
06 Пятый сценарий: проведите три испытания перед рабочим запуском
Окружение готово не тогда, когда одна сборка прошла без ошибок, а когда понятен результат типичных отказов. Выполните следующие проверки на тестовом проекте и с отдельным идентификатором результата.
Проверка A — обрыв SSH во время сборки
- [ ] Запустить Build, Test или Archive в повторно подключаемой сессии.
- [ ] Убедиться, что stdout и stderr пишутся в отдельные файлы.
- [ ] Закрыть локальное SSH-соединение, не отправляя команду завершения.
- [ ] Войти повторно и проверить состояние сессии или фонового задания.
- [ ] Сопоставить код выхода, лог и фактический
xcresultилиxcarchive. - [ ] Зафиксировать, какой этап можно продолжить без полной пересборки.
Проверка B — выход пользователя
- [ ] Запустить отдельную задачу с Simulator или подписанием.
- [ ] Зафиксировать пользователя, графический сеанс и владельца процесса.
- [ ] Выполнить выход или переключение пользователя по согласованной процедуре.
- [ ] Проверить, продолжился ли процесс и не потерял ли он доступ к Keychain.
- [ ] Сохранить ошибку и вернуть исходный контекст без расширения разрешений.
Проверка C — перезапуск Mac
- [ ] Сохранить конфигурацию задания и расположение логов.
- [ ] Перезапустить тестовый хост после остановки безопасной задачи.
- [ ] Проверить запуск SSH, CI Runner или
launchd. - [ ] Запустить проверочную сборку от имени ожидаемой учётной записи.
- [ ] Убедиться, что новый лог не смешался со старым.
- [ ] Проверить результат, подпись, Simulator и возможность отдельного этапа загрузки.
Если хотя бы одна проверка заканчивается только сообщением «процесс существует», окружение ещё не готово к ночному релизу.
07 Частые вопросы после обрыва
Продолжится ли xcodebuild после разрыва SSH?
Иногда да, но прямой запуск в интерактивном Shell нельзя считать устойчивым способом. Результат зависит от того, как создана сессия, как запущен процесс и что произошло с пользовательским контекстом. Проверяйте не терминал, а сохранённые stdout и stderr, код выхода, xcresult, xcarchive и последующий этап.
Как восстановить удалённую сборку после сбоя сети?
Не начинайте сразу новую сборку. Сначала найдите последнюю попытку, проверьте процесс, время изменения лога и наличие результата. Если архив создан, переходите к его проверке и отдельному экспорту. Если процесс завис на Simulator или Keychain, зафиксируйте контекст и причину до завершения процесса.
Как снова подключиться к выполняющейся задаче?
Повторный SSH-вход восстанавливает сетевое соединение, но не обязательно экран прежней оболочки. Вернитесь в ту же повторно подключаемую сессию либо откройте журнал фонового исполнителя. Просмотрите статус без запуска новой команды, затем дождитесь кода завершения и проверьте каталог артефактов.
Что выбрать для ночной iOS-сборки?
Для редкого ручного Archive используйте повторно подключаемую сессию. Для ночных тестов, регулярных коммитов и публикаций применяйте CI Runner или управляемое задание с журналами и понятным контекстом. Выбор определяется не только частотой, но и требованием восстановиться после перезагрузки без ручного SSH-входа.
Как автоматически восстановить сервис после перезапуска?
Опишите запуск через CI Runner или launchd, включая пользователя, рабочий каталог, переменные, пути логов и поведение при ошибке. После перезапуска проверьте не только наличие процесса, но и доступ к сертификатам, Simulator, результатам и следующему этапу публикации.
08 Сравните сценарии до выбора постоянной схемы
Ниже — не рейтинг инструментов, а границы их применения. Ручной терминал дешевле по времени настройки, но стоимость ошибки выше, если результат не сохранён и приходится повторять весь Archive.
| Сценарий | Подход | Что переживает обрыв SSH | Что нужно проверять |
|---|---|---|---|
| Разовый Build или Archive | Повторно подключаемая сессия | Сетевой разрыв при сохранении самой сессии | Логи, код выхода, xcresult, xcarchive |
| Ночная проверка по расписанию | CI Runner | Отсутствие локального терминала | Контекст пользователя, история попытки, артефакты |
| Локальный запуск после загрузки | launchd |
Выход из SSH и, при правильной настройке, перезапуск службы | Рабочий каталог, переменные, права и восстановление |
| Simulator или подпись | Runner либо управляемое задание с проверенным сеансом | Только тот отказ, который предусмотрен конфигурацией | Графический вход, Keychain, Simulator, код завершения |
| Передача готового продукта | Отдельный этап upload | Потерю интерактивного вывода | Факт принятия, версия, номер сборки и статус обработки |
Планируйте также хранение результатов. xcarchive и xcresult нельзя считать заменой журналу: первый показывает продукт архивации, второй — данные тестового запуска, а stdout и stderr объясняют, как задача к нему пришла. Разделение этих доказательств сокращает риск повторной загрузки уже принятой сборки.
| Признак после восстановления | Решение |
|---|---|
| Есть полный лог и корректный результат | Продолжить со следующего этапа |
| Есть архив, но нет экспорта | Повторить только экспорт |
| Есть экспорт, но статус передачи неизвестен | Проверить публикацию по версии и номеру сборки |
| Процесс есть, но лог не меняется | Зафиксировать состояние и расследовать блокировку |
| Нет процесса и результата | Запустить новую попытку с новым каталогом логов |
| После перезапуска стартует только оболочка | Настроить Runner или launchd и повторить приёмочный тест |
Если текущая среда не выдерживает эти проверки, причина может быть не в команде xcodebuild, а в архитектуре доступа: личный компьютер выключается, SSH-сессия не сохраняется, журналы остаются только на локальном экране или после перезагрузки нет нужного пользовательского контекста. В таком случае удалённый Mac для iOS-сборки с постоянной доступностью и root-доступом обычно практичнее, чем пытаться превратить домашнюю машину в круглосуточный сервер. Перед выбором можно сопоставить доступные варианты аренды Mac с частотой задач и необходимостью физически стабильной среды.
Итоговый выбор зависит от частоты: для редкой ручной операции оставляйте повторно подключаемую сессию, для регулярных задач — CI Runner или управляемое задание, а для Simulator и подписи добавляйте отдельную проверку пользовательского сеанса. Если существующий компьютер не может оставаться включённым, хранить полные логи и автоматически восстанавливаться после перезапуска, аренда Mac через JEXCLOUD даст более предсказуемую основу для временной или постоянной сборочной среды, чем повторный запуск публикации после каждого сетевого сбоя.
Запускайте длительные задачи на удалённом Mac с JEXCLOUD
Арендуйте удалённый Mac JEXCLOUD для сборки проектов, тестирования и других ресурсоёмких задач.
Работайте через SSH и сохраняйте контроль над процессом даже при временном обрыве локального соединения.
Арендовать сейчас