Если вы подписываете git-коммиты YubiKey на macOS и периодически получаете «General error» от GPG — это не баг YubiKey. Это гонка процессов за PC/SC интерфейс. GPG YubiKey scdaemon ошибка macOS — один из самых раздражающих артефактов повседневной работы с аппаратными токенами. Я написал gpg-with-retry — drop-in замену GPG, которая решает проблему полностью, без ручного вмешательства.
- Причина ошибки: GPG YubiKey scdaemon ошибка macOS
- Почему стандартные советы не работают
- Как работает gpg-with-retry
- Установка за три команды
- Переменные окружения и отладка
- Практический результат: ноль сбоев на M2 Mac
- Технические детали реализации
- FAQ: вопросы о GPG YubiKey scdaemon ошибках на macOS
- Почему GPG выдаёт «General error», хотя YubiKey вставлен?
- Работает ли gpg-with-retry с SSH-аутентификацией через gpg-agent?
- Не замедлит ли preflight-проверка каждый коммит?
- С какими моделями YubiKey совместим инструмент?
- Получить gpg-with-retry
Причина ошибки: GPG YubiKey scdaemon ошибка macOS
На macOS за доступ к смарт-карте через PC/SC одновременно конкурируют три процесса:
- scdaemon (GnuPG) — держит выбранный OpenPGP-апплет
- ctkpcscd (Apple CryptoTokenKit) — периодически опрашивает карту
- ssh-pkcs11-helper (OpenSSH) — обращается к PKCS#11-интерфейсу
Когда ctkpcscd или ssh-pkcs11-helper подключается к карте, он снимает выбор OpenPGP-апплета. scdaemon об этом не знает и продолжает использовать устаревшее соединение. Следующий gpg --sign или git commit -S падает с «General error» — хотя YubiKey физически на месте.
Особенно болезненно при коммитах: git воспринимает любую ошибку GPG как окончательную, встроенного retry нет. Приходится вручную запускать gpgconf --kill scdaemon перед каждым вторым коммитом.
Почему стандартные советы не работают
- disable-ccid в scdaemon.conf — снижает частоту, но не устраняет гонку
- Алиас
pkill scdaemon— нужно запускать вручную - Git хуки — коды выхода GPG одинаковы для восстановимых и неустранимых ошибок
- Перезапуск gpg-agent — сбрасывает все кешированные PIN-коды
Как работает gpg-with-retry
gpg-with-retry — прозрачная обёртка над gpg. Указываешь его как gpg.program в git config, и он берёт на себя управление жизненным циклом scdaemon:
- Preflight check — перед первой попыткой проверяет
SCD SERIALNO - Прозрачный retry — при восстановимой ошибке убивает scdaemon, очищает PCSC-клиентов, восстанавливает соединение
- Умная классификация ошибок — «General error» → retry; «Operation cancelled» → выход; «No card» → выход
- Освобождение карты — убивает scdaemon после каждой операции
- Race-free захват stderr — FIFO вместо process substitution
Результат: git commit -S работает с первого раза, каждый раз, без ручного вмешательства.
Установка за три команды
cp gpg-with-retry ~/.local/bin/
chmod +x ~/.local/bin/gpg-with-retry
git config --global gpg.program gpg-with-retryДобавьте в ~/.gnupg/scdaemon.conf:
disable-ccid
pcsc-sharedПеременные окружения и отладка
GPG_RETRY_MAX=2— максимальное число попытокGPG_RETRY_DEBUG=1— подробный вывод в stderrGPG_BINARY=/path/to/gpg— явный путь к бинарнику GPG
При любых проблемах: GPG_RETRY_DEBUG=1 git commit -S покажет, какая ошибка была обнаружена, сработал ли retry и в каком состоянии был scdaemon.
Практический результат: ноль сбоев на M2 Mac
Я развернул gpg-with-retry для команды разработчиков с обязательной подписью коммитов через YubiKey на macOS 14 (M2). До внедрения: примерно каждый пятый git commit -S падал. После — ноль сбоев. Команда перестала думать о GPG вообще.
Это часть работы по выстраиванию безопасной инфраструктуры разработки. Помогаю командам в рамках ИТ-консалтинга и управления рисками — там, где разрыв между политикой безопасности и её реальным исполнением кроется в инструментарии разработчика.
Технические детали реализации
- FIFO вместо process substitution: GPG может завершиться до того, как process substitution прочитает весь stderr. FIFO блокирует до полного чтения.
- Классификация по паттернам ошибок: коды выхода GPG ненадёжны между версиями, скрипт сопоставляет текстовые паттерны.
- Очистка PCSC-клиентов: на некоторых версиях macOS убийства scdaemon недостаточно — ctkpcscd держит устаревший handle.
- Никаких внешних зависимостей: чистый POSIX shell, работает на любом macOS с GnuPG.
FAQ: вопросы о GPG YubiKey scdaemon ошибках на macOS
Почему GPG выдаёт «General error», хотя YubiKey вставлен?
Это проблема deselection OpenPGP-апплета через PC/SC. Когда ctkpcscd или ssh-pkcs11-helper обращается к карте, он снимает выбор апплета. scdaemon использует устаревший handle и возвращает «General error». YubiKey исправен. gpg-with-retry обнаруживает этот паттерн и автоматически восстанавливает соединение.
Работает ли gpg-with-retry с SSH-аутентификацией через gpg-agent?
Да. Обёртка перехватывает все вызовы через gpg.program: git commit -S, gpg --sign, gpg --decrypt и любые инструменты, вызывающие бинарник gpg.
Не замедлит ли preflight-проверка каждый коммит?
Только первый вызов после перезапуска scdaemon — около 100–200 мс. Последующие коммиты не имеют накладных расходов.
С какими моделями YubiKey совместим инструмент?
С любой смарт-картой, поддерживающей OpenPGP через scdaemon: YubiKey 4, YubiKey 5 (USB-A, USB-C, NFC), Nitrokey, Gnuk и аналоги. Обёртка управляет scdaemon, не общаясь с картой напрямую.
Получить gpg-with-retry
gpg-with-retry распространяется с открытым исходным кодом под лицензией MIT. Если вы настраиваете инфраструктуру подписи на YubiKey для команды или хотите проконсультироваться по безопасности DevSecOps — свяжитесь со мной.
