禁止GPG“从文件描述符0读取密码”消息

简单地说,我怎样才能使GPG不打印那条消息呢? 以下是我正在使用的命令:

echo "test input" > test.in echo "test" | gpg -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in echo "test" | gpg -q -d --passphrase-fd 0 test.enc > test.out 

并运行它:

 $ echo "test input" > test.in $ echo "test" | gpg -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in Reading passphrase from file descriptor 0 $ echo "test" | gpg -q -d --passphrase-fd 0 test.enc > test.out Reading passphrase from file descriptor 0 

编辑:redirectstderr似乎不工作

 $ echo "test" | gpg -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in 2> /dev/null Reading passphrase from file descriptor 0 

看看发生了什么的一种方法是跟踪涉及的系统调用。 实用程序根据平台而有所不同。 在Solaris上,你可以使用truss 。 在Linux上(如我的例子),你会使用strace 。


跟踪,我们改变使用的命令:

echo "test" | gpg -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in 2> /dev/null

至:

echo "test" | strace gpg -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in 2>trace_output.txt echo "test" | strace gpg -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in 2>trace_output.txt


第一件有趣的事情(如果有点不相关的话)是当gpg从stdin中input密码短语时,重复单字节读取。 这有时是代码效率低下的迹象 – 但在这种情况下,这可能不是什么大问题:

 read(0, "t", 1) = 1 read(0, "e", 1) = 1 read(0, "s", 1) = 1 read(0, "t", 1) = 1 read(0, "\n", 1) = 1 

有关日志消息输出的更多相关内容全部在这里:

 open("/dev/tty", O_RDWR) = 3 fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(5, 0), ...}) = 0 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 opost isig icanon echo ...}) = 0 write(3, "Reading passphrase from file des"..., 45) = 45 write(3, "\10\10\10 \n", 7) = 7 

这就是我们所听到的有关文件描述符3的所有信息,直到退出(没有明确closures)。

依次看这些:

  • open("/dev/tty", O_RDWR) = 3

    这是打开文件/ dev / tty,读取和写入。 返回值(一个新的文件描述符供以后使用)是3。

    / dev / tty是当前控制terminal的同义词 。 你可以通过运行$ tty来查看这个特殊文件所引用的设备

  • fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(5, 0), ...}) = 0

    这个被gpg用来找出刚刚用文件描述符3打开的文件。大括号内的东西是返回的东西(一个填充的结构统计,用5,0表示这是一个特别特殊的文件 )。

  • ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 opost isig icanon echo ...}) = 0

    这是在输出之前操纵控制terminal的属性。

  • write(3, "Reading passphrase from file des"..., 45) = 45

    write(3, "\10\10\10 \n", 7) = 7

    这些更直接。 gpg成功地将该文本(其中一些在strace输出中缩写)写入terminal。


所以 – 这是你的答案.. gpg直接写这个日志消息到/ dev / tty(控制terminal的同义词),所以你将无法以stdout或stderr的方式redirect它。

有一种解决方法。 在执行gpg之前,您可以断开控制terminal。

这是一个简短的程序,只是这样做的:

 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> int main(int argc, char* argv[]) { int rc, fd; if (argc != 2) { fprintf(stderr, "Provide command line arg to execute after TIOCNOTTY\n"); return EXIT_FAILURE; } fd = open("/dev/tty", O_RDWR); if (fd < 0) { fprintf(stderr, "Failed to open controlling terminal: %s\n", strerror(errno)); return EXIT_FAILURE; } rc = ioctl(fd, TIOCNOTTY); if (rc == -1) { fprintf(stderr, "Failed TIOCNOTTY ioctrl: %s\b", strerror(errno)); return EXIT_FAILURE; } return system(argv[1]); } 

应该有一个现有的工具来做到这一点,但我找不到一个。

如果您要编译该代码,请致电生成的可执行文件,然后您可以执行此操作:

echo "test" | notty "gpg -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in"

这应该抑制消息,但保持你的stdout和stderr完好无损。 目前还不清楚还有什么会被压制的(你需要看看gpg的源代码,看看还有什么是以这种方式输出的)。

--batch是答案,但我不知道它是如何输出,即使当stderr被redirect…

虽然user30579的答案对于理解问题非常有用,但我们可以将其修改为实际解决问题所需的最小值:

只需使用内置于GPG的–no-tty开关即可。 例如,:

 echo "test" | gpg --no-tty -q -c --passphrase-fd 0 --output test.enc --yes --force-mdc test.in