쉘 스크립트에서 리눅스로 템플릿?


26

내가 성취하고 싶은 것은 :

1.) $ version $ path와 같은 변수를 사용하여 구성 파일을 템플릿으로 사용 (예 : Apache 구성)

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
GNU gettext의 일부이므로 모든 주요 Unix 플랫폼 (macOS X 포함)과 Microsoft Windows에서 사용할 수 있습니다.
tricasse

4

아마도 Puppet 또는 Chef 같은 구성 관리 시스템을 살펴 봐야 합니다. 이들은 쉽게 위하고 무엇을 설명 할 수있는 훨씬 더.


1
감사. 물론 Chef가 설치되어 실행 중입니다. 그러나 자체 요리 책을 작성해야 할 때 많은 오버 헤드가 추가됩니다. 나는 루비 프로그래밍 언어를 모른다. 그리고 나의 결론은 있었다. 보다 쉬운 경우를 위해 쉘 스크립트를 사용하여이 작업을 수행하는 것이 더 쉽습니다 (가능한 경우).
Markus

PuppetChef는 모두 템플릿에 ERB를 사용하는 것처럼 보이고 시작하기가 엄청나게 쉽습니다. 변수가 주어지면 템플릿 name의 문자열 <%= name %>name의 값으로 대체됩니다 . name템플릿 외부에서 정의하는 방법 은 분명히 두 시스템간에 다릅니다.
Mike Renfro

1
네 (템플릿 포함) 자체는 절대적으로 쉽습니다. 그러나 Chef를 Framework (및 요리 책 작성)로 사용하려면 많은 시간이 필요합니다. 데이터를 템플릿으로 가져 오려면 Chef가 데이터 소스의 "병합"및 기타 많은 항목을 관리하는 위치와 방법을 이해해야합니다. 나는 내 자신의 요리 책을 쓰기 시작했지만, 특별한 경우에는 쉘 스크립트가 100 배 더 빠를 것이다 ...
Markus

Chef 또는 Puppet의 인프라 스트럭처 구축이 어려울 수 있으며 재미있는 모험이 될 수있는 헤드리스 운영 방법을 알아볼 수 있습니다. Ansible은 풀 아웃 또는 푸시 모드에서 제대로 작동하므로 알아 내고 직접 스크립팅하는 것이 더 좋습니다. 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 을 사용 합니다. (비공개 프로젝트, 즉 널리 사용되지는 않습니다. 그러나 어쨌든 테스트하고 싶을 수도 있습니다)

예를 들어 csv 파일에서 / etc / network / interfaces를 생성하려면 다음과 같이하십시오.

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

템플릿 (여기에서 interfaces.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

최근에 jinja와 같은 템플릿 구문을 사용하여 bash 스크립트를 작성했습니다. 쿠키 라고 합니다. 데모는 다음과 같습니다.

쿠키 데모


이 질문에 어떻게 대답합니까?
RalfFriedl

1
@RalfFriedl 무슨 말인지 잘 모르겠습니다. 나는 뭔가를 놓친 것 같아서 질문을 다시 읽었지만 그것을 보지 못했습니다. 사실, 어떻게합니까 하지 대답 어떤 질문을 받았다 질문의 일부를? 마치이 질문에 대답 할 목적으로 쿠키를 만들었던 것과 거의 비슷합니다. 비록 제가 머리에 조금 다르게 말했을 수도 있습니다. :)
Bryan Bugyi

나는 중재자를 연기하기에는 조금 늦었지만 아마도 Ralf는 쿠키가 어떻게 질문에 대답하는지 설명 하기 위해 자선 적으로 프롬프트를 표시 했습니다. .
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

heredoc + 제어 문자를 사용하여 @FooF의 훌륭한 답변 (줄 바꿈이 주석에서 형식화되지 않음)을 확장하려면 임의의 문자 파일 이름을 허용 할 수 있습니다 .

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

이것은 널이 아닌 문자를 허용하며 3 ^D바이트가 자신의 행에서 발견 될 때만 잘립니다 (실제로는 절대). zsh는 null 종결자를 지원하기 때문에 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미리 (또는 다른 안전한 사용자) 미리하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.