Confファイルとinit.d
を作成する必要がありますが、これらは非常に似ています。これらのファイルにより、サーバーに新しいhttpサービスをデプロイできます。これらのファイルは同じで、一部のパラメーターのみがファイル間で変更されます(listen_port
、ドメイン、サーバー上のパス...)。
これらのファイルにエラーがあるとサービスが誤動作するため、bashスクリプトを使用してこれらのファイルを作成したいと思います。
例えば:
generate_new_http_service.sh 8282 subdomain.domain.com /home/myapp/rootOfHTTPService
Bashで使用できるテンプレートモジュールを探しています。このテンプレートモジュールは、いくつかの汎用confおよびinit.dスクリプトを使用して新しいスクリプトを作成します。
そのためのヒントはありますか?そうでない場合は、pythonテンプレートエンジンを使用できます。
これは、ヒアドキュメントを使用して行うことができます。例えば.
generate.sh:
#!/bin/sh
#define parameters which are passed in.
PORT=$1
DOMAIN=$2
#define the template.
cat << EOF
This is my template.
Port is $PORT
Domain is $DOMAIN
EOF
出力:
$ generate.sh 8080 domain.com
This is my template.
Port is 8080
Domain is domain.com
またはファイルに保存します:
$ generate.sh 8080 domain.com > result
Bashのテンプレートモジュールですか? sed
、ルークを使用してください!これは、何百万通りの方法のうちの1つの例です。
$ cat template.txt
#!/bin/sh
echo Hello, I am a server running from %DIR% and listening for connection at %Host% on port %PORT% and my configuration file is %DIR%/server.conf
$ cat create.sh
#!/bin/sh
sed -e "s;%PORT%;$1;g" -e "s;%Host%;$2;g" -e "s;%DIR%;$3;g" template.txt > script.sh
$ bash ./create.sh 1986 example.com /tmp
$ bash ./script.sh
Hello, I am a server running from /tmp and listening for connection at example.com on port 1986 and my configuration file is /tmp/server.conf
$
これをbashで直接行うことができ、sedも必要ありません。そのようなスクリプトを作成します。
#!/bin/bash
cat <<END
this is a template
with $foo
and $bar
END
次のように呼び出します:
foo=FOO bar=BAR ./template
単純なファイル生成の場合、基本的には
. "${config_file}"
template_str=$(cat "${template_file}")
eval "echo \"${template_str}\""
十分でしょう。
ここに ${config_file}
には、シェルで解析可能な形式の構成変数が含まれ、${template_file}
は、シェルヒアドキュメントのようなテンプレートファイルです。ファイルの最初の行ソース${config_file}
、2行目はファイルの内容${template_file}
シェル変数template_str
。最後の3行目では、シェルコマンドecho "${template_str}"
(二重引用符で囲まれた式"${template_str}"
が展開されます)、評価します。
これらの2つのファイルの内容の例については、 https://serverfault.com/a/699377/120756 を参照してください。
テンプレートファイルに含めることができる制限や、シェルのエスケープを実行する必要がある制限があります。また、テンプレートファイルが外部で作成される場合、セキュリティ上の理由から、実行前に適切なフィルタリングの実装を検討する必要があります。たとえば、誰かがテンプレートファイルに有名な$(rm -rf /)
を挿入したときにファイルを失うことはありません。
この問題を解決するために私が取ったアプローチは次のとおりです。上記のアプローチのいくつかよりも少し柔軟性があり、引用の問題のいくつかを回避できます。
fill.sh:
#!/usr/bin/env sh
config="$1"
template="$2"
destination="$3"
cp "$template" "$destination"
while read line; do
setting="$( echo "$line" | cut -d '=' -f 1 )"
value="$( echo "$line" | cut -d '=' -f 2- )"
sed -i -e "s;%${setting}%;${value};g" "$destination"
done < "$config"
テンプレート:
Template full of important %THINGS%
"Note that quoted %FIELDS% are handled correctly"
If I need %NEWLINES% then I can add them as well.
config:
THINGS=stuff
FIELDS="values work too!"
NEWLINES="those\\nnifty\\nlinebreaks"
結果:重要なものでいっぱいのテンプレート
"Note that quoted "values work too!" are handled correctly"
If I need those
nifty
linebreaks then I can add them as well.
[編集]数年前の元の回答から変更しました。
上記のFooFからの回答が好きです: https://stackoverflow.com/a/30872526/353817
それでも、テンプレートファイルのコンテンツ全体をメモリに保存するための中間変数を持たないことを好みます。
. "${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 templatingはPythonで非常に有名です。
Perl
を使用した1行の簡潔で短いソリューションPerl
を使用して、変数をその値に置き換えます。
export world=World beautiful=wonderful
echo 'I love you, $world! You are $beautiful.' >my_template.txt
Perl -pe 's|\$([A-Za-z_]+)|$ENV{$1}|g' my_template.txt
出力: I love you, World! You are wonderful
。
my_template.txt
には、接頭辞として$
。
python class string.Template
$ echo 'before $X after' > template.txt
$ python -c 'import string; print(string.Template(open("template.txt").read()).substitute({"X":"A"}))'
before A after
または
$ python -c 'import string, sys; print(string.Template(open("template.txt").read()).substitute({"X":sys.argv[1]}))' "A"
ここに $X
はテンプレートのプレースホルダーであり、{"X":"A"}
は、プレースホルダーから値へのマッピングです。 pythonコードで、ファイルからテンプレートテキストを読み取り、そこからテンプレートを作成し、プレースホルダーをコマンドライン引数に置き換えます。
または、Rubyがマシンにインストールされている場合、RubyのERBを使用できます。
$ echo "before <%= ENV['X'] %> after" > template.txt
$ X=A erb template.txt
before A after
ここに <%= ENV['X'] %>
はプレースホルダーです。 ENV['X']
は、環境変数から値を読み取ります。 X=A
は、環境変数を目的の値に設定します。
私は最近、ジンジャのようなテンプレート構文を使用してまさにそれを達成するbashプロジェクトを公開しました。 cookie と呼ばれます。デモは次のとおりです。