Сообщение об ошибке
gpg: signing failed: Inappropriate ioctl for device
Также выводится как
- [GNUPG:] FAILURE sign 83918950
Git выводит это сообщение под строкой «error: gpg failed to sign the data». С `--status-fd` gpg также выдаёт `[GNUPG:] FAILURE sign 83918950` (числовой код ошибки GPG для этой ситуации).
Git commit signing with GnuPG 2 — pinentry has no terminal
Что это означает
Ключ подписи защищён парольной фразой, gpg-agent запустил терминальный pinentry, чтобы её запросить, а pinentry не смог открыть терминал. «Inappropriate ioctl for device» — это `ENOTTY` операционной системы: stdin — не TTY, а `GPG_TTY` не указывает ни на один TTY. С ключом и конфигурацией всё в порядке: не удался только запрос парольной фразы.
Почему это происходит
Переменная GPG_TTY не экспортирована
частоДокументация GnuPG требует добавить `export GPG_TTY=$(tty)` в профиль оболочки. Без этого curses-версия pinentry не знает, где выводить запрос.
Подпись из IDE или графического клиента
частоVS Code, IDE от JetBrains и графические Git-клиенты запускают git без терминала. Там не может работать pinentry, рассчитанный только на терминал (`pinentry-curses`, `pinentry-tty`).
Подпись в CI ключом, защищённым парольной фразой
иногдаВвести парольную фразу некому. Для CI нужен отдельный ключ и неинтерактивный способ передать парольную фразу.
Как исправить
- 1.
Экспортируйте GPG_TTY
Добавьте экспорт в профиль оболочки; если запущенный агент стартовал из другого терминала, обновите его командой `updatestartuptty`.
bash # ~/.bashrc or ~/.zshrc export GPG_TTY=$(tty) # if gpg-agent was started before, tell it about the current terminal gpg-connect-agent updatestartuptty /bye - 2.
Используйте графический pinentry
`pinentry-mac`, `pinentry-gnome3` или `pinentry-qt` показывают диалоговое окно, которое работает и при запуске из IDE.
bash # macOS (Homebrew): a GUI pinentry works for IDEs and GUI Git clients too brew install pinentry-mac echo "pinentry-program $(brew --prefix)/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf gpgconf --kill gpg-agent - 3.
Loopback-режим pinentry для автоматизации
С `allow-loopback-pinentry` gpg может читать парольную фразу из файла. Используйте отдельный ключ для CI, предназначенный только для подписи, и никогда не используйте личный ключ.
bash # CI: a dedicated signing key; passphrase supplied non-interactively via loopback pinentry echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf && gpgconf --kill gpg-agent cat > /usr/local/bin/gpg-ci <<'EOF' #!/bin/sh exec gpg --batch --pinentry-mode loopback --passphrase-file "$GPG_PASSPHRASE_FILE" "$@" EOF chmod +x /usr/local/bin/gpg-ci git config --global gpg.program gpg-ci
Связанные ошибки
error: gpg failed to sign the dataGit (commit -S, tag -s, commit.gpgsign) with GnuPGsign_and_send_pubkey: signing failed for RSA "/path/to/key" from agent: agent r…OpenSSH client with an SSH agent (ssh-agent, gpg-agent, 1Password, Secretive, Windows OpenSSH agent)gpg: Can't check signature: No public keyGnuPG (gpg --verify, git verify-commit / verify-tag / log --show-signature)