[Редактировать] Я изменил свой ответ с исходного, который был несколько лет назад.
Мне нравится ответ от FooF выше:
https://stackoverflow.com/a/30872526/3538173
Тем не менее, я предпочитаю не иметь промежуточную переменную для хранения всего содержимого файла шаблона в памяти.
. "${config_file}"
eval "echo \"$(cat "${template_file}")\""
Пример
Создать файл шаблона. Давайте назовем это example.tpl
:
Hello, ${NAME}!
Today, the weather is ${WEATHER}. Enjoy!
Создайте файл конфигурации для хранения ваших переменных. Давайте назовем это good.conf
:
NAME=John
WEATHER=good
Теперь в скрипте, где вы хотите отобразить шаблон, вы можете написать это:
#!/usr/bin/env bash
template_file=example.tpl
config_file=good.conf
. "${config_file}"
eval "echo \"$(cat "${template_file}")\""
# Or store the output in a file
eval "echo \"$(cat "${template_file}")\"" > out
Вы должны увидеть этот замечательный вывод:)
Hello, John!
Today, the weather is good. Enjoy!
Осторожно с eval
Когда вы используете eval
, если файл шаблона содержит некоторые инструкции, они будут выполнены, и это может быть опасно. Например, давайте изменим example.tpl
выше с этим содержанием:
Hello, ${NAME}!
Today, the weather is ${WEATHER}. Enjoy!
I'm a hacker, hu hu! Look, fool!
$(ls /)
Теперь, если вы создадите файл шаблона, вы увидите следующее:
Hello, John!
Today, the weather is good. Enjoy!
I'm a hacker, hu hu! Look, fool!
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
Теперь отредактируйте ваш файл good.conf
, чтобы иметь этот контент:
NAME=$(ls -l /var)
WEATHER=good
и отрендерить шаблон. Вы должны увидеть что-то вроде этого:
Hello, total 8
drwxr-xr-x. 2 root root 6 Apr 11 04:59 adm
drwxr-xr-x. 5 root root 44 Sep 11 18:04 cache
drwxr-xr-x. 3 root root 34 Sep 11 18:04 db
drwxr-xr-x. 3 root root 18 Sep 11 18:04 empty
drwxr-xr-x. 2 root root 6 Apr 11 04:59 games
drwxr-xr-x. 2 root root 6 Apr 11 04:59 gopher
drwxr-xr-x. 3 root root 18 May 9 13:48 kerberos
drwxr-xr-x. 28 root root 4096 Oct 8 00:30 lib
drwxr-xr-x. 2 root root 6 Apr 11 04:59 local
lrwxrwxrwx. 1 root root 11 Sep 11 18:03 lock -> ../run/lock
drwxr-xr-x. 8 root root 4096 Oct 8 04:55 log
lrwxrwxrwx. 1 root root 10 Sep 11 18:03 mail -> spool/mail
drwxr-xr-x. 2 root root 6 Apr 11 04:59 nis
drwxr-xr-x. 2 root root 6 Apr 11 04:59 opt
drwxr-xr-x. 2 root root 6 Apr 11 04:59 preserve
lrwxrwxrwx. 1 root root 6 Sep 11 18:03 run -> ../run
drwxr-xr-x. 8 root root 87 Sep 11 18:04 spool
drwxrwxrwt. 4 root root 111 Oct 9 09:02 tmp
drwxr-xr-x. 2 root root 6 Apr 11 04:59 yp!
Today, the weather is good. Enjoy!
I'm a hacker, hu hu! Look, fool!
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
swapfile
sys
tmp
usr
var
Как вы можете видеть, внедрение команды в файле конфигурации и файле шаблона возможно, и поэтому вы должны быть особенно осторожны:
- быть уверенным в содержимом файла шаблона : проверить, что команда НЕ вводится.
- быть уверенным в содержимом файла конфигурации : убедитесь, что нет команды ввода. Если файл конфигурации исходит от кого-то другого, вам необходимо знать и доверять этому человеку перед обработкой шаблона.
Представьте, что вы sudoer без пароля, рендеринг файла шаблона может привести к разрушению вашей системы с удачным размещением rm -rf
.
Пока вы контролируете содержимое этих файлов, можно использовать этот шаблон eval
.
Если у вас есть внешний (ненадежный) входящий файл конфигурации, вы должны искать шаблонизатор, который изолирует этот тип инъекций. Например, шаблон Jinja2 довольно известен в Python.