Шаблонування з Linux у сценарії оболонки?


26

що я хочу дозволити:

1.) Маючи конфігураційний файл як шаблон із змінними, такими як $ version $ path (наприклад, apache config)

2.) Маючи скрипт оболонки, який "заповнює" змінні шаблону і записує створений файл на диск.

Чи можливо це за допомогою сценарію оболонки. Я був би дуже вдячний, якщо ви можете назвати деякі команди / інструменти, я можу виконати це чи кілька хороших посилань.

Відповіді:


23

Це дуже можливо. Дуже простим способом реалізувати це було б, щоб файл шаблону насправді був сценарієм та використовував такі змінні оболонки, як

#! /bin/bash
version="1.2.3"
path="/foo/bar/baz"
cat > /tmp/destfile <<-EOF
here is some config for version $version which should
also reference this path $path
EOF

Ви навіть можете зробити цю конфігурацію в командному рядку, вказавши version=$1і path=$2, таким чином, ви можете запускати її так, як bash script /foo/bar/baz 1.2.3. Попередній -EOF спричиняє пробіл перед ігноруванням рядків, використовуйте просту, <<EOFякщо ви не хочете такої поведінки.

Ще один спосіб зробити це - використовувати пошук і замінити функціональність sed

#! /bin/bash
version="1.2.3"
path="/foo/bar/baz"
sed -e "s/VERSION/$version/g" -e "s/PATH/$path/" /path/to/templatefile > /tmp/destfile

який би замінив кожен екземпляр рядків VERSION і PATH. Якщо є інші причини, ці рядки будуть у файлі шаблону, ви можете зробити пошук і замінити VERSION або% VERSION% або щось менш імовірно, що воно буде викликане випадково.


18

Інших інструментів, крім них /bin/sh. Дано файл шаблону форми

Version: ${version}
Path: ${path}

або навіть із змішаним кодом оболонки

Version: ${version}
Path: ${path}
Cost: ${cost}\$
$(i=1; for w in one two three four; do echo Param${i}: ${w}; i=$(expr $i + 1); done)

і файл конфігурації, аналогічний оболонці, як

version="1.2.3-r42"
path="/some/place/under/the/rainbow/where/files/dance/in/happiness"
cost="42"

розширити це на просту справу

Version: 1.2.3-r42
Path: /some/place/under/the/rainbow/where/files/dance/in/happiness
Cost: 42$
Param1: one
Param2: two
Param3: three
Param4: four

Дійсно, враховуючи шлях до файлу конфігурації в змінній оболонки config_fileта шлях до файлу шаблону template_file, все, що вам потрібно зробити:

. ${config_file}
template="$(cat ${template_file})"
eval "echo \"${template}\""

Це, можливо, красивіше, ніж мати повний скрипт оболонки як файл шаблону (рішення @ mtinberg).

Повна програма наївного розширювача шаблонів:

#!/bin/sh

PROG=$(basename $0)

usage()
{
    echo "${PROG} <template-file> [ <config-file> ]"
}

expand()
{
    local template="$(cat $1)"
    eval "echo \"${template}\""
}

case $# in
    1) expand "$1";;
    2) . "$2"; expand "$1";;
    *) usage; exit 0;;
esac

Це виведе розширення на стандартний вихід; просто перенаправляйте стандартний вихід на файл або модифікуйте вище описане очевидно, щоб отримати бажаний вихідний файл.

Застереження: Розширення файлу шаблону не працюватиме, якби файл містив подвійні подвійні лапки ( "). З міркувань безпеки ми, ймовірно, повинні включати кілька очевидних перевірок правильності або, що ще краще, виконувати трансформацію уникнення оболонки, якщо файл шаблону генерується зовнішнім об'єктом.


1
Чудово все ще бачити людей активно, використовуючи сценарії оболонки, щоб робити такі цікаві речі. Мій приятель написав годинник із сценарієм оболонки. github.com/tablespoon/fun/blob/master/cli-clock І справді веселі часи.
пташенята

2
Коли я знайшов цю відповідь , коли шукає , щоб зробити це сам, я реалізував досить наївний підхід і відправив його на Github: github.com/nealian/bash-unsafe-templates
Pyrocater

9

Найпростіший спосіб зробити це просто в Linux CLI - це використання envsubstта змінні середовища.

Приклад файлу шаблону apache.tmpl:

<VirtualHost *:${PORT}>
    ServerName ${SERVER_NAME}
    ServerAlias ${SERVER_ALIAS}
    DocumentRoot "${DOCUMENT_ROOT}"
</VirtualHost>

Запустити envsubstта вивести результат у новий файл my_apache_site.conf:

export PORT="443"
export SERVER_NAME="example.com"
export SERVER_ALIAS="www.example.com"
export DOCUMENT_ROOT="/var/www/html/"
envsubst < apache.tmpl > my_apache_site.conf

Вихід:

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot "/var/www/html/"
</VirtualHost>

2
Він є частиною gettext GNU, а тому доступний на всіх основних платформах Unix (включаючи macOS X), а також Microsoft Windows.
трикассе

4

Напевно, вам слід заглянути в систему управління конфігурацією, наприклад Ляльковий або шеф-кухар . Це легко зробити те, що ви описали вище, та багато іншого.


1
Спасибі. Абсолютно, у мене встановлений і працює шеф-кухар. Але це додає багато накладних витрат, коли вам доведеться писати власні кулінарні книги. Я не знаю мови програмування рубіну, і мій висновок був такий. простіше зробити це за допомогою сценарію оболонки для легших випадків (якщо це можливо).
Маркус

Схоже, Лялька та шеф-кухар використовують ERB для шаблонів, і це смішно легко почати. З огляду на змінну name, рядок <%= name %>у шаблоні буде замінено на nameзначення 's. nameОчевидно, те, як ви визначаєтесь поза шаблоном, відрізняється між двома системами.
Майк Ренфро

1
Так, шаблонувати (з шеф-кухарем) абсолютно просто. Але використання шеф-кухаря в якості рамки (і написання кулінарних книг) вимагає багато часу. Щоб отримати дані в шаблони, вам потрібно зрозуміти, де і як шеф-кухар управляє "злиттям" джерел даних та багато іншого. Я почав писати власні кулінарні книги, але сценарій оболонки в моєму спеціальному випадку був би в 100 разів швидшим ...
Маркус

Отримати інфраструктуру для шеф-кухаря чи лялечки може неприємно, або ви можете спробувати зрозуміти, як запустити їх без голови, що це приємна пригода. Відповідник прекрасно працює в режимі витягування або виштовхування поза коробкою, так що це може призвести до кращого балансу з'ясування та створення сценаріїв самостійно. docs.ansible.com/template_module.html
пташенята

4

Якщо вам потрібні легкі та реальні шаблони, а не код оболонки, який створює нові файли, звичайним вибором є sed& awkабо perl. Ось одне посилання: http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/

Мені б я користувався справжньою мовою на зразок perl, tcl, python, ruby ​​чи іншим у цьому класі. Щось побудовано для сценаріїв. Всі вони мають гарні, прості інструменти для створення шаблонів і багато прикладів у google.


4

Я використовую shtpl для цього. (мій приватний проект, що означає, що він широко не використовується. Але, можливо, ви хочете його протестувати)

Наприклад, ви хочете генерувати інтерфейси / etc / network / інтерфейси з CSV-файлу, ви можете це зробити так:

Вміст файлу CSV (тут test.csv):

eth0;10.1.0.10;255.255.0.0;10.1.0.1
eth1;192.168.0.10; 255.255.255.0;192.168.0.1

Шаблон (тут інтерфейси.tpl):

#% IFS=';'
#% while read "Val1" "Val2" "Val3" "Val4"; do
auto $Val1 
iface $Val1 inet static
  address $Val2 
  netmask $Val3 
  gateway $Val4 

#% done < "$CSVFILE"

Команда:

$ CSVFILE=test.csv sh -c "$( shtpl interfaces.tpl )"

Результат:

auto eth0 
iface eth0 inet static
  address 10.1.0.10 
  netmask 255.255.0.0 
  gateway 10.1.0.1 

auto eth1 
iface eth1 inet static
  address 192.168.0.10 
  netmask  255.255.255.0 
  gateway 192.168.0.1

Насолоджуйтесь!


1

Я вдосконалив відповідь FooF, щоб користувачеві не потрібно було вручну скасовувати подвійні лапки:

#!/bin/bash
template="$(cat $1)"
template=$(sed 's/\([^\\]\)"/\1\\"/g; s/^"/\\"/g' <<< "$template")
eval "echo \"${template}\""

1

Нещодавно я опублікував сценарій bash, який виконує саме те, використовуючи синтаксис шаблону, подібного до jinja. Це називається cookie . Ось демонстрація:

демонстрація файлів cookie


Як це відповідає на питання?
РальфФрідл

1
@RalfFriedl Я не впевнений, що ти маєш на увазі. Я просто перечитав питання, думаючи, що, мабуть, щось пропустив, але не бачу. Насправді, як це не відповідає жодній частині запитання, яке було задано? Це майже так, як я створив печиво з єдиною метою відповісти на це запитання ... що я зробив Кіндоф, хоча я, можливо, в той час це сформулював трохи інакше. :)
Брайан Буджі

Я трохи запізнююсь, щоб грати посередника, але, можливо, Ральф просто благодійно спонукав вас пояснити, як cookie відповідає на це питання, а не намагатися незмінно означати, що ви не знаєте свого власного проекту досить добре, щоб оцінити, чи може він вирішити чиюсь проблему .
abathur

0

Я, мабуть, спізнився на цю вечірку. Однак я натрапив на ту саму проблему і вирішив створити свій власний двигун шаблонів BASH у кількох рядках коду:

Скажемо, що у вас це є file.template:

# My template
## Author
 - @NAME@ <@EMAIL@>

І цей rulesфайл:

NAME=LEOPOLDO WINSTON
EMAIL=leothewinston\@leoserver.com

Ви виконуєте цю команду:

templater rules < file.template

Ви отримуєте це:

# My template
## Author
 - LEOPOLDO WINSTON <leothewinston@leoserver.com>

Ви можете встановити його:

 bpkg install vicentebolea/bash-templater

Це сайт проекту


0

Щоб розширити чудову відповідь @ FooF (нові рядки не форматуються в коментарі), використовуючи контрольні символи heredoc +, ви можете дозволити довільні символи та назви файлів:

template() {
    # if [ "$#" -eq 0 ] ; then return; fi # or just error
    eval "cat <<$(printf '\x04\x04\x04');
$(cat $1)
"
}

Це приймає будь-який ненульовий символ і скорочується лише рано, якщо 3 ^Dбайти зустрічаються в їх власному рядку (реально ніколи). zsh навіть підтримує нульові термінатори, так printf '\x00\x00\x00'би працювало. templateнавіть працює для підступних імен файлів, таких як:

for num in `seq 10`; do
    template 'foo "$ .html' # works
done

Остерігайтеся шаблонів оболонок можуть "розширювати" довільні команди, наприклад $(launch_nukes.sh --target $(curl -sL https://freegeoip.app/csv/ | cut -d, -f 9,10)). З великою силою ...

Редагувати: якщо ви дійсно не хочете, щоб ваші файли запускали нуклеуси, просто sudo -u nobody sh(або якийсь інший безпечний користувач) заздалегідь.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.