Как я могу запросить парольную фразу из сценария bash?

Я получаю это сообщение об ошибке: problem with the agent: Inappropriate ioctl for device.

#!/bin/bash

fname="/home/user/elist.txt"
while IFS= read -r file
do
    tar czf "$file".tar.gz "$file"
    gpg --passphrase-fd 0 --no-symkey-cache --symmetric --cipher-algo AES256 "$file".tar.gz
done < "$fname"
0
John Doe 7 Мар 2021 в 21:31
Я не могу воспроизвести сообщение об ошибке, которое вы показываете, но я вижу несколько проблем: 1) --passphrase-fd 0 означает чтение парольной фразы из файла "$fname" - это предназначено? Или вы пытаетесь прочитать его в интерактивном режиме из командной строки? 2) man gpg утверждает, что, начиная с версии 2.0, --passphrase-fd действует только в том случае, если также указана опция --batch (и, по-видимому, начиная с версии 2.1, --pinentry-mode loopback также требуется ).
 – 
fra-san
7 Мар 2021 в 22:03
Я хотел бы показать подсказку для пароля.
 – 
John Doe
7 Мар 2021 в 22:32

1 ответ

Учитывая --passphrase-fd 0, gpg пытается прочитать фразу-пароль из файла "$fname", потому что внутри цикла while именно на него перенаправляется файловый дескриптор 0 от.
У вас есть несколько вариантов заставить его работать:

  • Заключите весь цикл в фигурные скобки, дублируйте стандартный ввод в новый файловый дескриптор и используйте его в качестве аргумента --passphrase-fd:

    fname="/home/user/elist.txt"
    {
      while IFS= read -r file
      do
          tar czf "$file".tar.gz -- "$file"
          gpg --passphrase-fd 3 --no-symkey-cache --symmetric --batch \
            --cipher-algo AES256 --pinentry-mode loopback -- "$file".tar.gz
      done < "$fname"
    } 3<&0
    
  • Явно откройте новый дескриптор файла для elist.txt и перенаправьте стандартный ввод read из него (вместо перенаправления всего цикла):

    exec 3<"/home/user/elist.txt"
    while <&3 IFS= read -r file
    do
        tar czf "$file".tar.gz -- "$file"
        gpg --passphrase-fd 0 --no-symkey-cache --symmetric --batch \
          --cipher-algo AES256 --pinentry-mode loopback -- "$file".tar.gz
    done
    exec 3<&-
    
  • Явно откройте новый файловый дескриптор для /dev/tty и используйте его вместо 0 в качестве аргумента для параметра --passphrase-fd (это нормально, если ваш скрипт запускается в интерактивном режиме с терминала; это может не работает должным образом, если парольная фраза должна исходить от чего-то другого):

    fname="/home/user/elist.txt"
    exec 3</dev/tty
    while IFS= read -r file
    do
        tar czf "$file".tar.gz -- "$file"
        gpg --passphrase-fd 3 --no-symkey-cache --symmetric --batch \
          --cipher-algo AES256 --pinentry-mode loopback -- "$file".tar.gz
    done < "$fname"
    exec 3<&-
    

    В качестве более краткой альтернативы вы можете перенаправить стандартный ввод из /dev/tty только для gpg, используя 0</dev/tty gpg --passphrase-fd 0 ..., избегая необходимости в командах exec.

  • Предполагая, что у вас есть правильно настроенный gpg-agent (например, в некоторых дистрибутивах Linux агент представляет собой активируемую сокетом службу systemd, которая использует pinentry для взаимодействия с пользователем и работает из коробки как в виртуальных терминалах и в графических сеансах) просто избегайте использования --passphrase-fd:

    fname="/home/user/elist.txt"
    while IFS= read -r file
    do
        tar czf "$file".tar.gz -- "$file"
        gpg --no-symkey-cache --symmetric \
          --cipher-algo AES256 -- "$file".tar.gz
    done < "$fname"
    

Обратите внимание, что я добавил --batch и --pinentry-mode loopback в командную строку gpg, где используется --passphrase-fd, потому что, цитируя руководство,

... начиная с версии 2.0 эта парольная фраза используется только в том случае, если также была указана опция --batch. Начиная с версии 2.1, --pinentry-mode также необходимо установить на loopback.

4
fra-san 8 Мар 2021 в 12:34