最近换了系统, git commit 在gpg签名的时候出错了:

gpg: signing failed: Inappropriate ioctl for device

原因是 gpg 在当前终端无法弹出密码输入页面。

解决办法:

export GPG_TTY=$(tty)

重新执行,发现会弹出一个密码输入界面。

参考:https://www.jianshu.com/p/2ed292ae2365

但是老灯觉得这不是解决办法,因为在此之前,我从来没遇到过这个问题。产生这个问题是有原因的。

于是再去看了一下Arch的文档,果然,有说明“Invalid IPC response and Inappropriate ioctl for device” 这个问题。虽然报错语句不一样,但是其实是一个问题。

https://wiki.archlinux.org/title/GnuPG#Invalid_IPC_response_and_Inappropriate_ioctl_for_device

The default pinentry program is /usr/bin/pinentry-gtk-2. If gtk2 is unavailable, pinentry falls back to /usr/bin/pinentry-curses and causes signing to fail:

gpg: signing failed: Inappropriate ioctl for device gpg: [stdin]: clear-sign failed: Inappropriate ioctl for device You need to set the GPG_TTY environment variable for the pinentry programs /usr/bin/pinentry-tty and /usr/bin/pinentry-curses.

$ export GPG_TTY=$(tty)

如果我们看一下 /usr/bin/pinentry 这个shell脚本, 内容如下:

#!/bin/sh

# user-defined pre-exec hook
test -r "${XDG_CONFIG_HOME:-$HOME/.config}"/pinentry/preexec &&
    . "${XDG_CONFIG_HOME:-$HOME/.config}"/pinentry/preexec

# site-defined pre-exec hook
test -r /etc/pinentry/preexec &&
    . /etc/pinentry/preexec

test -e /usr/lib/libgtk-x11-2.0.so.0 &&
    exec /usr/bin/pinentry-gtk-2 "[email protected]"

exec /usr/bin/pinentry-curses "[email protected]"

然后我们看看 /etc/pinentry/preexec 的内容,发现 /usr/bin/pinentry-gnome3/usr/bin/pinentry-qt 其实在我当前系统上都是存在的,所以,最简单的办法,其实我们注释掉pinentry-gnome3 那一行,或qt那一行都OK.

这样就没有必要再fallback 到 pinentry-gtk-2 或 pinentry-curses 了

#!/hint/sh

# Define additional functionality for pinentry. For example
#test -e /usr/lib/libgcr-base-3.so.1 && exec /usr/bin/pinentry-gnome3 "[email protected]"
#test -e /usr/lib/libQt5Widgets.so.5 && exec /usr/bin/pinentry-qt     "[email protected]"

根据 Arch 文档, “gpg-agent is mostly used as daemon to request and cache the password for the keychain. ”, 我们使用ssh的时候,有ssh-agent 或类似 gnome seahorse 之类的工具充当agent, 那么 gpg 其实也有 agent的,这个 agent 一定是属于当前用户的,如果遇到问题,不防检查一下它是不是正确运行状态,当然,老灯这次遇到的并不是这个问题, gpg-agent 运行正常:

   ~ 
❯ systemctl --user status gpg-agent.socket
● gpg-agent.socket - GnuPG cryptographic agent and passphrase cache
     Loaded: loaded (/usr/lib/systemd/user/gpg-agent.socket; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2021-05-05 09:54:33 CST; 12h ago
   Triggers: ● gpg-agent.service
       Docs: man:gpg-agent(1)
     Listen: /run/user/1000/gnupg/S.gpg-agent (Stream)
     CGroup: /user.slice/user-1000.slice/[email protected]/app.slice/gpg-agent.socket

May 05 09:54:33 wudeng systemd[1297]: Listening on GnuPG cryptographic agent and passphrase cache.