错误信息
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 的文档要求在 shell 配置文件中加入 `export GPG_TTY=$(tty)`。没有这一行,curses 版 pinentry 就不知道该在哪里绘制提示。
从 IDE 或图形界面客户端签名
常见VS Code、JetBrains IDE 和图形界面 Git 客户端在没有终端的情况下运行 git。只能在终端中使用的 pinentry(`pinentry-curses`、`pinentry-tty`)在这些环境里无法工作。
在 CI 中用受密码短语保护的密钥签名
偶见没有人可以输入密码短语。CI 需要一把专用密钥,以及一种以非交互方式提供密码短语的途径。
修复方法
- 1.
导出 GPG_TTY
把它加入 shell 配置文件;如果正在运行的 gpg-agent 是从另一个终端启动的,用 `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)