Shell Script'inde Linux ile Baş Etmek?


26

tamamlamak istediğim şey:

1.) $ config $ path (örneğin apache config) gibi değişkenler içeren bir config dosyasına şablon olarak sahip olmak.

2.) Şablon değişkenlerini "dolduracak" bir kabuk betiğine sahip olmak ve oluşturulan dosyayı diske yazar.

Bu bir kabuk betiği ile mümkün mü. Bazı komutları / araçları adlandırabilirseniz, bunu ya da bazı iyi linkleri başarabilirsem çok teşekkür ederim.

Yanıtlar:


23

Bu çok mümkün. Bunu uygulamanın çok basit bir yolu, şablon dosyasının aslında script olması ve kabuk değişkenleri kullanmasıdır.

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

Bunu belirterek komut satırında bile yapılandırılabilir hale getirebilir version=$1ve path=$2böylece çalıştırabilirsiniz bash script /foo/bar/baz 1.2.3. -EOF satırlar yok sayılır önce boşlukları neden önce düz kullanmak <<EOFo davranışı istemiyorsanız.

Bunu yapmanın başka bir yolu da sed'i aramak ve işlevini kullanmaktır.

#! /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 ve PATH dizelerinin her örneğinin yerini alacak. Bu dizelerin şablon dosyasında bulunmasının başka nedenleri varsa, aramanızı yapabilir ve bunun yerine VERSION veya% VERSION% veya yanlışlıkla tetiklenmesi daha düşük bir şey olabilir.


18

Dışında hiçbir araç gerekmez /bin/sh. Formun bir şablon dosyası verildi

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

hatta dahil karışık kabuk kodu ile

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)

ve gibi kabuk ayrıştırılabilir bir yapılandırma dosyası

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

bu genişletmek için basit bir mesele

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

Nitekim, kabuk değişkenindeki yapılandırma dosyasının config_fileyolu ve içindeki şablon dosyasının yolu göz önüne alındığında, template_fileyapmanız gereken tek şey:

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

Bu belki de şablon dosyası olarak tam kabuk betiğine sahip olmaktan daha güzel (@ mtinberg'in çözümü).

Eksiksiz naif şablon genişletici programı:

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

Bu, genişlemeyi standart çıktıya çıkaracaktır; sadece standart çıktıyı bir dosyaya yönlendirmek veya istenen çıktı dosyasını üretmek için yukarıdakileri açık bir şekilde değiştirmek.

Uyarılar: Dosya çıkmamış çift tırnak işareti ( ") içeriyorsa şablon dosyası genişletme çalışmaz . Güvenlik nedeniyle, eğer şablon dosyası dış varlık tarafından oluşturulmuşsa, bazı açık akıl sağlığı kontrolleri içermeli ya da daha da iyisi, kabuk kaçış dönüşümünü gerçekleştirmeliyiz.


1
Böyle eğlenceli şeyler yapmak için hala kabuk komut dosyalarını kullanan kişileri görmek harika. Bir arkadaşım kabuk senaryosunda bir saat yazdı. github.com/tablespoon/fun/blob/master/cli-clock Gerçekten eğlenceli zamanlar.
piliçler

2
Bunu yaparken kendime bakarken bu cevabı bulduğumda, oldukça naif bir yaklaşım kullandım ve onu Github'da
Pyrocater

9

Bunu basitçe Linux CLI'da yapmanın en kolay yolu, kullanmak envsubstve Ortam Değişkenleri kullanmaktır .

Örnek şablon dosyası apache.tmpl:

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

Çalıştır envsubstve sonucu yeni dosyaya ver 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

Çıktı:

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

2
GNU gettext'in bir parçasıdır ve bu nedenle tüm Windows Unix platformlarında (macOS X dahil) ve Microsoft Windows'ta kullanılabilir.
Tricasse

4

Muhtemelen Kukla veya Şef gibi bir konfigürasyon yönetim sistemine bakmalısınız . Bunlar yukarıda ve daha fazlasını açıkladığınız şeyi kolayca yapabilir .


1
Teşekkürler. Kesinlikle, şef yüklü ve çalışıyor. Ancak kendi yemek kitaplarınızı yazmak zorunda kaldığınızda çok fazla yük ekler. Ruby programlama dilini bilmiyorum ve benim sonucumdu. Bunu kolay vakalar için bir kabuk betiğiyle yapmak daha kolaydır (mümkünse).
Markus

Puppet ve Chef'in her ikisi de şablonlar için ERB kullanıyor gibi görünüyor ve başlaması çok kolay. Bir değişken verildiğinde name, <%= name %>bir şablondaki dize name'nin değeri ile değiştirilir . nameŞablonun dışında nasıl tanımladığınız açıkça iki sistem arasında farklılık gösterir.
Mike Renfro

1
Evet baştan (Aşçı ile) kendisi kesinlikle kolaydır. Ancak şefi Framework olarak kullanmak (ve yemek kitaplarını yazmak) çok zaman gerektirir. Verileri şablonlara dahil etmek için, Chef'in veri kaynaklarının ve bir sürü başka şeyin "birleştirilmesini" nerede ve nasıl yönettiğini anlamanız gerekir. Kendi yemek kitaplarımı yazmaya başladım, ancak bir kabuk senaryosu benim özel durumumda 100 kat daha hızlı olurdu ...
Markus

Altyapıyı Şef ya da Kukla için almak bir acı olabilir ya da onları nasıl başa çıkacağını bulmaya çalışabilirsiniz ki bu eğlenceli bir maceradır. Ansible, kutudan çekme veya basma modunda iyi çalışır, bu sayede daha iyi bir şekilde denemek ve komut dosyası yazmak sizin elinizdedir. docs.ansible.com/template_module.html
civciv

4

Yeni dosyalar üreten kabuk kodu yerine hafif ve gerçek şablonlar istiyorsanız, genel seçimler sed& awkveya perl. İşte bir link: http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/

Ben, perl, tcl, python, ruby ​​ya da o sınıftaki başka bir şey gibi gerçek bir dil kullanırdım. Komut dosyası oluşturmak için yapılmış bir şey. Hepsinde iyi, basit şablonlama araçları ve google'da tonlarca örnek var.


4

Bunun için shtpl kullanıyorum . (benim özel proje, yani, yaygın olarak kullanılmıyor. Ama belki de yine de test etmek istiyorsunuz)

Örneğin, bir csv dosyasından bir / etc / network / interfaces oluşturmak istiyorsanız, bunu yapabilirsiniz:

CSV dosyası içeriği (burada 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

Şablon (burada interfaces.tpl):

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

#% done < "$CSVFILE"

Komut:

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

Sonuç:

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

Keyfini çıkarın!


1

FooF'un cevabını, kullanıcının çift tırnak işaretini elle kaldırmasına gerek kalmaması için geliştirdim:

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

1

Kısa bir süre önce sadece bir jinja benzeri şablon sözdizimi kullanarak bunu gerçekleştiren bir bash betiği yayımladı. Buna kurabiye denir . İşte bir demo:

çerez demosu


Bu soruya nasıl cevap veriyor?
RalfFriedl

1
@RalfFriedl Ne demek istediğinden emin değilim. Sadece bir şeyi özlemiş olduğumu düşünerek soruyu yeniden okudum, ama göremiyorum. Aslında, bu nasıl yok değil cevap herhangi istendi sorunun parçası? Neredeyse tek başıma kafamda biraz farklı ifade etmiş olmama rağmen, yaptığım bu soruyu cevaplamak için bir çerez yaptım. :)
Bryan Bugyi,

Ben biraz geç arabulucu oynamak için, ama belki Ralf sadece charitably sen isteyen edildi açıklamak çerez yerine birisinin sorununu çözebilir olmadığını uncharitably yeterince iyi yargıç için kendi projesini bilmediğimi ima etmeye çalışmak yerine, konunun ne denli .
abathur

0

Muhtemelen bu partiye geç kaldım. Bununla birlikte, aynı sorunla karşılaştım ve kendi BASH şablon motorumu birkaç kod satırında oluşturmayı seçtim:

Şunlara sahip olduğunuzu söyleyelim file.template:

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

Ve bu rulesdosya:

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

Bu komutu siz yürütün:

templater rules < file.template

Bunu aldın:

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

Tarafından kurabilirsiniz:

 bpkg install vicentebolea/bash-templater

Burası proje sitesi


0

@ FooF'un büyük cevabını genişletmek için (yeni satırlar yorumda formatlanmadı), heredoc + kontrol karakterlerini kullanarak, rastgele karakterlere ve dosya adlarına izin verebilirsiniz :

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

Bu, boş olmayan herhangi bir karakteri kabul eder ve yalnızca ^Dkendi satırlarında 3 baytla karşılaşılırsa (gerçekçi olarak asla) kesilir . zsh boş sonlandırıcıları bile destekliyor, bu yüzden printf '\x00\x00\x00'işe yarayacaktı. templategibi hain dosya isimleri için bile çalışır:

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

Dikkat edin, kabuk şablonları isteğe bağlı komutları "genişletebilir" $(launch_nukes.sh --target $(curl -sL https://freegeoip.app/csv/ | cut -d, -f 9,10)). Büyük güçle…

Düzenleme: dosyalarınızın size yalnızca nükleer bomba atmasını istemiyorsanız, sudo -u nobody shönceden ( sadece başka bir güvenli kullanıcı).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.