跳到主要内容
ecdsa.com
Git commit signing with GnuPG 2Git

错误信息

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。密钥和配置都没有问题;失败的只是密码短语提示。

原因

修复方法

  1. 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. 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. 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

相关错误

浏览完整的签名错误库