Назад | Перейти на главную страницу

Подавить сообщение 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

РЕДАКТИРОВАТЬ: Перенаправление stderr не работает

$ 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 вы должны использовать ферма. В 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 .


Первое, что выделяется как интересное (хотя и немного не связанное с этим), это то, что gpg выполняет повторяющиеся однобайтовые чтения при получении входной кодовой фразы из stdin. Иногда это явный признак неэффективного кода, но в данном случае это, вероятно, не так уж и важно:

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 до выхода (он не закрывается явно).

Рассматривая каждый из них по очереди:

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

    Это открывает файл / dev / tty как для чтения, так и для записи. Возвращаемое значение (новый дескриптор файла для дальнейшего использования) - 3.

    / dev / tty - это синоним текущего управляющего терминала. Вы можете увидеть устройство, на которое фактически ссылается этот специальный файл, запустив $ tty

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

    Это используется gpg, чтобы узнать о файле, только что открытом с файловым дескриптором 3. В фигурных скобках указано то, что возвращается (заполненная структура struct stat, где 5, 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

    Это более просто. gpg успешно записывает этот текст (некоторые из которых были сокращены в выводе strace) на терминал.


Итак - это ваш ответ ... gpg записывает это сообщение журнала непосредственно в / dev / tty (синоним управляющего терминала), поэтому вы не сможете перенаправить его так же, как для stdout или stderr.

Там является способ обойти это. Вы можете отключить управляющий терминал перед запуском gpg.

Вот короткая программа, которая делает именно это:

#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]);
}

Для выполнения вышеуказанного должна быть существующая утилита, но я не смог ее найти.

Если вам нужно было скомпилировать этот код, вызовите полученный исполняемый файл notty, тогда вы можете сделать это:

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

Это должно подавить сообщение, но сохранить ваши stdout и stderr нетронутыми. Однако неясно, что еще будет подавлено (вам нужно посмотреть исходный код gpg, чтобы узнать, что еще выводится таким образом).

--batch - это ответ, но я понятия не имею, как он выводится, даже когда stderr перенаправлен ...

Хотя ответ user30579 полезен для понимания проблемы, давайте сократим его до минимума, необходимого для фактического решения проблемы:

Просто используйте переключатель --no-tty, встроенный в GPG. например.,:

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