Szablonowanie w systemie Linux w skrypcie powłoki?


26

co chcę osiągnąć to:

1.) Posiadanie pliku konfiguracyjnego jako szablonu ze zmiennymi takimi jak $ version $ path (na przykład config apache)

2.) Posiadanie skryptu powłoki, który „wypełnia” zmienne szablonu i zapisuje wygenerowany plik na dysku.

Czy jest to możliwe dzięki skryptowi powłoki. Byłbym bardzo wdzięczny, jeśli potrafisz wymienić niektóre polecenia / narzędzia, które mogę wykonać, lub dobre linki.

Odpowiedzi:


23

To bardzo możliwe. Bardzo prostym sposobem na wdrożenie tego byłoby, aby plik szablonu był faktycznie skryptem i używał zmiennych powłoki, takich jak

#! /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

Możesz nawet skonfigurować to w wierszu poleceń, określając version=$1i path=$2, abyś mógł go uruchomić w podobny sposób bash script /foo/bar/baz 1.2.3. -Przed EOF powoduje spacje przed linie są ignorowane używać zwykłego <<EOFjeśli nie chcesz tego zachowania.

Innym sposobem na to byłoby skorzystanie z funkcji wyszukiwania i zamiany 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

który zastąpiłby każde wystąpienie ciągów VERSION i PATH. Jeśli istnieją inne powody, dla których te ciągi znajdują się w pliku szablonu, możesz wyszukać i zastąpić VERSION lub% VERSION% lub coś, co prawdopodobnie zostanie przypadkowo uruchomione.


18

Nie są potrzebne żadne narzędzia inne niż /bin/sh. Biorąc pod uwagę plik szablonu formularza

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

lub nawet z dołączonym mieszanym kodem powłoki

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)

i parsowalny plik konfiguracyjny powłoki jak

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

łatwo jest to rozszerzyć

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

Rzeczywiście, biorąc pod uwagę ścieżkę do pliku konfiguracyjnego w zmiennej powłoki config_filei ścieżkę do pliku szablonu w template_file, wszystko, co musisz zrobić, to:

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

Jest to chyba ładniejsze niż posiadanie pełnego skryptu powłoki jako pliku szablonu (rozwiązanie @ mtinberg).

Kompletny naiwny program ekspandera szablonów:

#!/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

Spowoduje to wygenerowanie rozszerzenia do standardowego wyjścia; wystarczy przekierować standardowe wyjście do pliku lub zmodyfikować powyższe w oczywisty sposób, aby uzyskać pożądany plik wyjściowy.

Ostrzeżenia: Rozszerzenie pliku szablonu nie działałoby, gdyby plik zawierał nieoznaczone podwójne cudzysłowy ( "). Ze względów bezpieczeństwa prawdopodobnie powinniśmy uwzględnić pewne oczywiste kontrole poczytalności, a nawet lepiej wykonać transformację ucieczki powłoki, jeśli plik szablonu jest generowany przez jednostkę zewnętrzną.


1
Wspaniale jest nadal widzieć ludzi aktywnie korzystających ze skryptów powłoki do robienia takich zabawnych rzeczy. Mój kumpel napisał zegar w skrypcie powłoki. github.com/tablespoon/fun/blob/master/cli-clock Rzeczywiście czas zabawy.
— pisklęta

2
Kiedy znalazłem tę odpowiedź, gdy chciałem to zrobić sam, wdrożyłem
— Pyrocater

9

Najłatwiejszym sposobem, aby to zrobić po prostu w systemie Linux CLI, jest użycie envsubstzmiennych środowiskowych.

Przykładowy plik szablonu apache.tmpl:

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

Biegać envsubst i wyślij wynik do nowego pliku 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

Wydajność:

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

2
Jest częścią GNU gettext i dlatego jest dostępna na wszystkich głównych platformach Unix (w tym macOS X), a także w Microsoft Windows.
— tricasse

4

Prawdopodobnie powinieneś zajrzeć do systemu zarządzania konfiguracją, takiego jak Puppet lub Chef . Mogą z łatwością zrobić to, co opisano powyżej i wiele więcej.


1
dzięki. Oczywiście mam zainstalowanego i uruchomionego szefa kuchni. Ale to dodaje dużo kosztów ogólnych, gdy trzeba pisać własne książki kucharskie. Nie znam języka programowania ruby ​​i mój wniosek był taki. łatwiej jest to zrobić za pomocą skryptu powłoki dla łatwiejszych przypadków (jeśli to możliwe).
— Markus,

Wygląda na to, że zarówno Puppet, jak i Chef używają ERB do tworzenia szablonów, a od samego początku jest to niezwykle łatwe. Biorąc pod uwagę zmienną name, ciąg <%= name %>w szablonie zostanie zastąpiony namewartością. nameOczywiście sposób definiowania poza szablonem różni się między dwoma systemami.
— Mike Renfro,

1
Tak, samo szablonowanie (z szefem kuchni) jest absolutnie łatwe. Ale używanie szefa kuchni jako frameworka (i pisanie książek kucharskich) wymaga dużo czasu. Aby wprowadzić dane do szablonów, musisz zrozumieć, gdzie i jak Chef zarządza „łączeniem” źródeł danych i wielu innych rzeczy. Zacząłem pisać własne książki kucharskie, ale skrypt powłoki w moim przypadku byłby 100 razy szybszy ...
— Markus

Uruchomienie infrastruktury dla szefa kuchni lub marionetki może być uciążliwe lub możesz spróbować wymyślić, jak je uruchomić bez głowy, co jest zabawną przygodą. Ansible działa dobrze w trybie ciągnięcia lub wypychania po wyjęciu z pudełka, dzięki czemu może znaleźć lepszą równowagę między jego rozszyfrowaniem i samodzielnym skryptowaniem. docs.ansible.com/template_module.html
— pisklęta

4

Jeśli chcesz mieć lekkie i rzeczywiste szablony zamiast kodu powłoki, który generuje nowe pliki, zwykle wybierane są sed& awklub perl. Oto jeden link: http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/

Ja użyłbym prawdziwego języka, takiego jak perl, tcl, python, ruby ​​lub coś innego w tej klasie. Coś zbudowanego do pisania skryptów. Wszystkie mają dobre, proste narzędzia do tworzenia szablonów i mnóstwo przykładów w google.


4

Używam shtpl za to. (mój prywatny projekt, co oznacza, że ​​nie jest powszechnie używany. Ale może i tak chcesz go przetestować)

Na przykład, chcesz wygenerować / etc / network / interfejsy z pliku csv, możesz to zrobić w następujący sposób:

Zawartość pliku CSV (tutaj 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

Szablon (tutaj interfaces.tpl):

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

#% done < "$CSVFILE"

Dowództwo:

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

Wynik:

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

Cieszyć się!


1

Poprawiłem odpowiedź FooF, aby użytkownik nie musiał ręcznie usuwać cudzysłowów ręcznie:

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

1

Niedawno opublikowałem skrypt bash, który osiąga właśnie to przy użyciu składni szablonu podobnej do jinja. To się nazywa ciasteczko . Oto demo:

demo ciasteczka


Jak to odpowiada na pytanie?
— RalfFriedl

1
@RalfFriedl Nie jestem pewien, co masz na myśli. Właśnie ponownie przeczytałem pytanie, myśląc, że musiałem coś przeoczyć, ale nie widzę tego. W rzeczywistości, w jaki sposób nie odpowiada to na żadną część zadanego pytania? To prawie tak, jakbym zbudował plik cookie wyłącznie w celu udzielenia odpowiedzi na to pytanie ... co zrobiłem, chociaż mogłem wtedy sformułować to nieco inaczej w mojej głowie. :)
— Bryan Bugyi

Jestem trochę spóźniony, aby zagrać w mediatora, ale być może Ralf po prostu uprzejmie poprosił cię o wyjaśnienie, w jaki sposób cookie odpowiada na pytanie, zamiast próbować sugerować, że nie znasz wystarczająco swojego projektu, aby ocenić, czy może rozwiązać czyjś problem .
— abathur

0

Prawdopodobnie spóźniłem się na to przyjęcie. Jednak natknąłem się na ten sam problem i zdecydowałem się na stworzenie własnego silnika szablonów BASH w kilku wierszach kodu:

Powiedzmy, że masz to file.template:

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

A ten rulesplik:

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

Wykonujesz to polecenie:

templater rules < file.template

Dostajesz to:

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

Możesz go zainstalować:

 bpkg install vicentebolea/bash-templater

To jest strona projektu


0

Aby rozwinąć świetną odpowiedź @ FooF (nowe wiersze nie zostały sformatowane w komentarzu), używając znaków kontrolnych heredoc +, możesz zezwolić na dowolne znaki i nazwy plików:

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

Akceptuje to dowolny znak inny niż null i obcina się tylko wcześnie, jeśli ^Dnapotkane zostaną 3 bajty na jego własnej linii (realistycznie nigdy). Zsh obsługuje nawet terminatory zerowe, więc printf '\x00\x00\x00'działałoby. templatedziała nawet w przypadku zdradliwych nazw plików, takich jak:

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

Uwaga szablony powłoki mogą „rozszerzać” dowolne polecenia, np $(launch_nukes.sh --target $(curl -sL https://freegeoip.app/csv/ | cut -d, -f 9,10)). Z wielką mocą…

Edycja: jeśli naprawdę nie chcesz, aby Twoje pliki uruchamiały w Tobie nukes, po prostu sudo -u nobody sh(lub inny bezpieczny użytkownik) wcześniej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.