Подавить сообщение 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
3 ответа
Один из способов увидеть, что происходит, - это отслеживать системные вызовы. Утилиты для этого различаются в зависимости от платформы. На 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. В фигурных скобках указано, что возвращено (заполненная структура 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