使用 bash 脚本从模板创建新文件
我必须创建非常相似的conf 文件和init.d
。这些文件允许在我的服务器上部署新的 HTTP 服务。这些文件是相同的,只有一些参数从一个文件更改为另一个文件(listen_port
、域和服务器上的路径)。
由于这些文件中的任何错误都会导致服务功能障碍,我想创建这些文件使用 bash 脚本的文件。
例如:
generate_new_http_service.sh 8282 subdomain.domain.example /home/myapp/rootOfHTTPService
我正在寻找一种可以与 bash 一起使用的模板模块。该模板模块将使用一些通用的 conf
和 init.d
脚本来创建新的脚本。
我可以使用 python 模板引擎吗?
I have to create conf files and init.d
which are very similar. These files permit to deploy new HTTP service on my servers. These files are the same and only some parameters change from one file to another (listen_port
, domain, and path on server.)
As any error in these files leads to dysfunction of service I would like to create these files using a bash script.
For example:
generate_new_http_service.sh 8282 subdomain.domain.example /home/myapp/rootOfHTTPService
I am looking for a kind of templating module that I could use with bash. This templating module would use some generic conf
and init.d
scripts to create new ones.
Could I could use python templating engine?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
您可以使用定界符来做到这一点。例如
generate.sh
:输出:
或将其保存到文件:
You can do this using a heredoc. e.g.
generate.sh
:Output:
or save it to a file:
bash 的模板模块?使用 sed,卢克!以下是数百万种可能方法之一的示例:
Template module for bash? Use
sed
, Luke! Here is an example of one of millions of possible ways of doing this:您可以直接在 bash 中执行此操作,甚至不需要 sed。编写这样的脚本:
然后像这样调用它:
you can do this directly in bash, you do not even need sed. Write a script like that:
then call it like so:
对于简单的文件生成,基本上这样做
就足够了。
这里的
${config_file}
包含 shell 可解析格式的配置变量,而${template_file}
是模板文件,看起来像 shell here 文档。第一行在文件${config_file}
中进行源代码,第二行将文件${template_file}
的内容放入 shell 变量template_str
中>。最后,在第三行中,我们构建 shell 命令echo "${template_str}"
(其中双引号表达式"${template_str}"
被展开)并对其求值。有关这两个文件的内容示例,请参阅 https://serverfault.com/a/699377/120756。
模板文件中的内容存在限制,或者需要执行 shell 转义。此外,如果模板文件是外部生成的,那么出于安全原因,您需要考虑在执行之前实施适当的过滤,这样当有人注入著名的
$(rm -rf /)< 时,您就不会丢失文件。 /code> 在模板文件中。
For simple file generation, basically doing
would suffice.
Here
${config_file}
contains the configuration variables in shell parseable format, and${template_file}
is the template file that looks like shell here document. The first line sources in the file${config_file}
, the second line puts the contents of the file${template_file}
into the shell variabletemplate_str
. Finally in the third line we build the shell commandecho "${template_str}"
(where the double quoted expression"${template_str}"
is expanded) and evaluate it.For an example of the contents of those two files, please refer to https://serverfault.com/a/699377/120756.
There are limitations what you can have in the template file or you need to perform shell escaping. Also if the template file is externally produced, then for security reasons you need to consider implementing a proper filtering prior to execution so that you will not for example lose your files when somebody injects the famous
$(rm -rf /)
in the template file.这是我最终采取的解决这个问题的方法。我发现它比上述一些方法更灵活,并且它避免了一些引号问题。
fill.sh:
模板:
配置:
结果:
充满重要内容的模板
Here's the approach that I ended up taking to solve this problem. I found it a little more flexible than some of the above approaches, and it avoids some of the issues with quotes.
fill.sh:
template:
config:
result:
Template full of important stuff
[编辑]我改变了几年前的原始答案。
我喜欢上面 FooF 的答案:
但是
,我不希望有一个中间变量来存储内存中模板文件的全部内容。
示例
创建模板文件。我们将其命名为
example.tpl
:创建一个配置文件来存储变量。让我们称之为
good.conf
:现在,在要渲染模板的脚本中,您可以这样写:
您应该看到这个精彩的输出:)
注意
eval
当你使用
eval
时,如果模板文件包含一些指令,它们就会被执行,这可能是危险的。例如,让我们使用以下内容更改上面的example.tpl
:现在,如果您渲染模板文件,您将看到以下内容:
现在将文件
good.conf
编辑为有这个内容:并渲染模板。您应该看到类似这样的内容:
如您所见,配置文件和模板文件中的命令注入是可能的,这就是为什么您必须格外小心:
想象一下,您是一个无密码 sudoer,呈现模板文件可能会导致使用适当的 rm -rf 破坏您的系统。
只要您控制这些文件的内容,就可以使用此
eval
模板。如果您有外部(不受信任的)传入配置文件,您应该寻找模板引擎,它将隔离此类注入。例如,Jinja2 模板在 Python 中非常有名。
[Edit] I changed my answer from the original one, that was years ago.
I like the answer from FooF above:
https://stackoverflow.com/a/30872526/3538173
Yet, I prefer not to have an intermediary variable to store the whole content of the template file in memory.
Example
Create a template file. Let's call it
example.tpl
:Create a configuration file to store your variables. Let's call it
good.conf
:Now, in the script where you want to render the template, you can write this:
You should see this wonderful output :)
Caution with
eval
When you use
eval
, if the template file contains some instructions, they will be executed, and it can be dangerous. For example, let's change theexample.tpl
above with this content:Now, if you render your template file, you will see this:
Now edit your file
good.conf
to have this content:and render the template. You should see something like this:
As you can see, command injection in the configuration file and the template file is possible, and that's why you have to be extra careful:
Imagine that you are a password-less sudoer, rendering the template file could result in ruining your system with a well-placed
rm -rf
.As long as you control the content of these files, it is fine to use this
eval
templating.If you have an external (untrusted) incoming configuration file, you should look for templating engine, that will isolate these kind of injection. For example, Jinja2 templating is quite famous in Python.
我最终使用了可供我使用的 envsubst 。它在大多数 Linux 系统上都可以通过 gettext 包广泛使用。我使用它是因为它将负责有选择地替换变量,并且我不必像 eval 那样在模板中转义它们。这是一个例子。
I ended up using envsubst which was available for me. It is widely available on most Linux systems in the gettext package. I used this because it will take care of selectively replacing variables and I don't have to escape them in the template as with e.g. eval. Here is an example.
您可以使用 python class
string.Template
或
这里
$X
是模板中的占位符,{"X":"A"}
是占位符到值的映射。在 python 代码中,我们从文件中读取模板文本,从中创建模板,然后用命令行参数替换占位符。或者,如果您的计算机上安装了 Ruby,您也可以使用 Ruby 的 ERB。
这里
<%= ENV['X'] %>
是一个占位符。ENV['X']
从环境变量中读取值。X=A
将环境变量设置为所需的值。You can use python class
string.Template
or
Here
$X
is a placeholder in the template and{"X":"A"}
is a mapping of the placeholder to a value. In the python code we read the template text from the file, create a template from it, then substitute the placeholder with the command line argument.Alternatively you can use Ruby's ERB, if Ruby is installed on your machine.
Here
<%= ENV['X'] %>
is a placeholder.ENV['X']
reads the value from the environment variable.X=A
sets the environment variable to the desired value.使用
perl
编写的优雅而简短的解决方案我使用
perl
将变量替换为其值:输出:
I love you, World!你太棒了
。my_template.txt
可以包含以$
为前缀的变量。Elegant and short solution in one line with
perl
I use
perl
to replace variables with their values:The output:
I love you, World! You are wonderful
.my_template.txt
can contain variables prefixed with$
.使用bash从模板生成bash脚本
这个问题需要
在模板文件
sample.tpl.sh
中严格分离变量数据(脚本头)和常量代码(脚本体),我只有一个模板变量#%TEMPLATE_CONSTANTS
大多数环境都缺少固定字符串编辑器,因此我使用
grep
和dd
创建了自己的“fsed”,以仅替换第一个匹配项#%TEMPLATE_CONSTANTS
相关
use bash to generate bash script from template
this problem calls for a strict separation of variable data (script header) and constant code (script body)
in the template file
sample.tpl.sh
, i have only one template variable#%TEMPLATE_CONSTANTS
most environments lack a fixed-string-editor, so i made my own "fsed" with
grep
anddd
, to replace only the first match of#%TEMPLATE_CONSTANTS
related
我建议 shtpl,一个 shell 模板系统:
https://github.com/dontsueme/shtpl
它有一个非常简单的语法,万无一失,并且只需要标准的 *nix 工具。
I suggest shtpl, a shell templating system:
https://github.com/dontsueme/shtpl
It has a very simple syntax, is foolproof and does only need standard *nix tools.
快速而优雅的解决方案,安全地支持完整的 shell 脚本。
tmpl.sh
https: //gitlab.com/risserlabs/community/cinch/-/blob/main/src/tmpl.sh
只需在您想要模板化的任何文件上运行以下命令即可。
file.txt.tmpl
输出将类似于以下内容。
如果您想编写模板文件,只需将输出重定向到新文件即可。
您可以通过设置
OPEN
和CLOSE
来更改开始和结束字符。file.txt.tmpl
Quick and elegant solution that safely supports full shell scripting.
tmpl.sh
https://gitlab.com/risserlabs/community/cinch/-/blob/main/src/tmpl.sh
Simply run the following on any file you want to template.
file.txt.tmpl
The output would be something like the following.
If you want to write the templated file, simply redirect the output to a new file.
You can change the open and close characters by setting
OPEN
andCLOSE
.file.txt.tmpl