Вот скрипт, который симметрично шифрует/дешифрует файл с помощью двух различных симметричных шифров последовательно.
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Arguments: enc|dec filename"
exit
fi
E="gpg -o - --symmetric --cipher-algo"
D="gpg -o - --decrypt"
ERR="2>/dev/null"
if [ "$1" = "enc" ]; then
$E AES $2 | $E TWOFISH -
elif [ "$1" = "dec" ]; then
$D $2 ${ERR} | $D - ${ERR}
else
echo "Arguments: enc|dec filename"
exit
fi
Когда я запускаю, ./doublecrypt dec /tmp/test.encrypted
я получаю ошибки
usage: gpg [options] --decrypt [filename]
usage: gpg [options] --decrypt [filename]
Если я изменю линию
$D $2 ${ERR} | $D - ${ERR}
к
echo "$D $2 ${ERR} | $D - ${ERR}"
Он печатает
gpg -o - --decrypt /tmp/xenc 2>/dev/null | gpg -o - --decrypt - 2>/dev/null
Если я скопирую и вставлю это в bash, то все запустится правильно.
Так почему же не работает, если я уберу echo
и позволю скрипту bash оценить его напрямую, как в исходной форме?
Я использую Ubuntu Saucy, а моя оболочка — bash.
решение1
Короткий ответ: см.BashFAQ #50: Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!.
Длинный ответ: у вас проблемы из-за порядка, в котором оболочка анализирует различные элементы командных строк; в частности, она расширяет ссылки на переменные (например, ${ERR}
) примерно на полпути процесса — после того, как она уже разобралась с такими вещами, как кавычки, экранирования и перенаправления. В вашем случае важна часть с перенаправлениями: к тому времени, как оболочка расширяется ${ERR}
до 2>/dev/null
, она уже ищет перенаправления и не находит их, поэтому она просто рассматривает это 2>/dev/null
как аргумент команды, а затем gpg
отклоняет его как не имеющий смысла.
По сути, хранение команд (или элементов команд) в переменных — неправильный способ. Переменные предназначены для данных, а не для исполняемого кода. В этом случае вам было бы гораздо лучше использовать функции:
e() {
gpg -o - --symmetric --cipher-algo "$@"
}
d() {
gpg -o - --decrypt "$@" 2>/dev/null
}
if [ "$1" = "enc" ]; then
e AES "$2" | e TWOFISH -
elif [ "$1" = "dec" ]; then
d "$2" | d -
else
echo "Arguments: enc|dec filename"
exit
fi
Обратите внимание, что я также заключил его $2
в двойные кавычки, чтобы предотвратить передачу его значения во вторую половину процесса синтаксического анализа оболочки.
решение2
Попробуйте изменить $D $2 ${ERR} | $D - ${ERR}
на:
$( $D $2 ${ERR} | $D - ${ERR} )
Также используйте полный путь к вашей gpg
программе, например:
/usr/local/bin/gpg