I am attempting to use Bash in order to run a form of an install process. During this process, a configuration file is copied and certain values are replaced inside of it. Such a config can be found below:
我试图使用Bash来运行一个安装过程的形式。在此过程中,将复制配置文件,并在其中替换某些值。这样的配置可以在下面找到:
server {
listen 80;
root ${INSTALLPATH};
server_name ${SITEURL};
client_max_body_size 20m;
client_body_timeout 120s;
location / {
try_files /public/router.php =404;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass ${PHPSERV};
fastcgi_index router.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location /assets {
try_files /app/$uri =404;
}
}
#Enables HTTPS access
#This requires you to install certificates and is not enabled by default
#If you wish to enable HTTPS, uncomment (remove the #s) from the below lines
#And change the ssl_certificate and ssl_certificate_key to point to the correct
#certificates.
#server {
# listen 443;
# root ${INSTALLPATH};
# server_name ${SITEURL};
#
# ssl on;
# ssl_certificate /etc/nginx/ssl/site.crt;
# ssl_certificate_key /etc/nginx/ssl/site.key;
#
# location / {
# try_files /public/router.php =404;
# fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# fastcgi_pass ${PHPSERV};
# fastcgi_index router.php;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include /etc/nginx/fastcgi_params;
# }
#
# location /assets {
# try_files /app/$uri =404;
# }
#
#}
I have been finding that most examples stem off the use of eval, and I have tried using that to do this replacement, however it appears that the file here does not properly expand, and bash tries to execute some stuff and can't.
我发现大多数例子都是使用eval,我尝试使用它来替换它,但是看起来这里的文件没有正确扩展,而bash试图执行一些东西而不能。
Currently, I have this
目前,我有这个
INSTALLPATH="/var/www/html/mycustomsite/"
PHPSERV="127.0.0.1:9000"
SITEURL="example.com"
while read -r line; do
eval echo -e "${line}"
done < template
However, this does not properly replace the values that are declared, nor does it generate the file correctly. It loses for example any line that starts with # and tries to execute others (along with losing some spacing).
但是,这不能正确替换声明的值,也不能正确生成文件。它失去了例如以#开头并试图执行其他行的任何行(以及丢失一些间距)。
What would be the correct way to do this, using just Bash and commands available on most Linux systems?
使用Bash和大多数Linux系统上可用的命令,这样做的正确方法是什么?
1 个解决方案
#1
4
Security tips
This don't take care of security issues! Using eval
is evil!
这不关心安全问题!使用eval是邪恶的!
The compatible answer is not better!
兼容的答案并不是更好!
Of course, you have to be confident about the content of your template!!
当然,您必须对模板的内容充满信心!
If else, try using sed! (see my last answer)
如果不是,请尝试使用sed! (见我的上一个答案)
Quick way bash only!:
Under bash you can simply:
在bash下你可以简单地:
eval "INSTALLPATH='/somepath/somewhere' SITEURL='example.com' PHPSERV='127.0.0.1:9000'; echo \"$(<template)\""
or
要么
eval "INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
echo \"$(<template)\""
As you're using eval
, you could store your resulting config file into one variable:
当您使用eval时,您可以将生成的配置文件存储到一个变量中:
eval "INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
cfgBody=\"$(<template)\""
Then
然后
echo "$cfgBody"
and/or
和/或
echo "$cfgBody" >/cfgpath/cfgfile
Doing this into a loop
tmplBody="$(<template)"
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
[ "$CFGFILE" ] && eval "echo \"$tmplBody\"" >"$CFGFILE"
done <<<"
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
"
Note: On second line, there are escaped spaces (prepanded with a backshash \
and quotes '
. The backslash tell read
to not split the variable, and the quotes have to be added into the resulting /tmp/file2
.
注意:在第二行,有转义空格(预装了后缀\和引号'。反斜杠告诉读取不拆分变量,并且引号必须添加到生成的/ tmp / file2中。
Soft way (compatible answer)
Under posix shell, you may do this way:
在posix shell下,你可以这样做:
#!/bin/sh
(
cat <<eohead
#!/bin/sh
INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
cat <<eof
eohead
cat template
echo eof
) | /bin/sh
This don't require bash, was tested under dash and busybox.
这不需要bash,在dash和busybox下测试。
bash Without eval !
sedcmd=''
for var in INSTALLPATH SITEURL PHPSERV;do
printf -v sc 's/${%s}/%s/;' $var "${!var//\//\\/}"
sedcmd+="$sc"
done
sed -e "$sedcmd" <template
Could work into a loop:
可以进入一个循环:
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
if [ "$CFGFILE" ] ;then
sedcmd=''
for var in INSTALLPATH SITEURL PHPSERV;do
printf -v sc 's/${%s}/%s/;' $var "${!var//\//\\/}"
sedcmd+="$sc"
done
sed -e "$sedcmd" <template >"$CFGFILE"
fi
done <<<"
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
"
Compatible answer, using sed
This could work without so called bashisms, into a loop:
这可以在没有所谓的bashisms的情况下工作,进入一个循环:
#!/bin/sh
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
sedcmd="s|\\\${INSTALLPATH}|${INSTALLPATH}|;"
sedcmd="${sedcmd}s|\\\${SITEURL}|${SITEURL}|;"
sedcmd="${sedcmd}s|\\\${PHPSERV}|${PHPSERV}|;"
sed -e "$sedcmd" template >"$CFGFILE"
done <<eof
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
eof
Comparing outputs:
比较输出:
diff -u99 /tmp/file{1,2}
--- /tmp/file1 2015-05-31 11:02:03.407463963 +0200
+++ /tmp/file2 2015-05-31 11:02:03.407463963 +0200
@@ -1,22 +1,22 @@
server {
listen 80;
- root /somepath/somewhere;
- server_name example.com;
+ root '/some other path/elsewhere';
+ server_name sample2.com;
client_max_body_size 20m;
client_body_timeout 120s;
location / {
try_files /public/router.php =404;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
- fastcgi_pass 127.0.0.1:9000;
+ fastcgi_pass 127.0.0.1:9001;
fastcgi_index router.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location /assets {
try_files /app/$uri =404;
}
}
#1
4
Security tips
This don't take care of security issues! Using eval
is evil!
这不关心安全问题!使用eval是邪恶的!
The compatible answer is not better!
兼容的答案并不是更好!
Of course, you have to be confident about the content of your template!!
当然,您必须对模板的内容充满信心!
If else, try using sed! (see my last answer)
如果不是,请尝试使用sed! (见我的上一个答案)
Quick way bash only!:
Under bash you can simply:
在bash下你可以简单地:
eval "INSTALLPATH='/somepath/somewhere' SITEURL='example.com' PHPSERV='127.0.0.1:9000'; echo \"$(<template)\""
or
要么
eval "INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
echo \"$(<template)\""
As you're using eval
, you could store your resulting config file into one variable:
当您使用eval时,您可以将生成的配置文件存储到一个变量中:
eval "INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
cfgBody=\"$(<template)\""
Then
然后
echo "$cfgBody"
and/or
和/或
echo "$cfgBody" >/cfgpath/cfgfile
Doing this into a loop
tmplBody="$(<template)"
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
[ "$CFGFILE" ] && eval "echo \"$tmplBody\"" >"$CFGFILE"
done <<<"
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
"
Note: On second line, there are escaped spaces (prepanded with a backshash \
and quotes '
. The backslash tell read
to not split the variable, and the quotes have to be added into the resulting /tmp/file2
.
注意:在第二行,有转义空格(预装了后缀\和引号'。反斜杠告诉读取不拆分变量,并且引号必须添加到生成的/ tmp / file2中。
Soft way (compatible answer)
Under posix shell, you may do this way:
在posix shell下,你可以这样做:
#!/bin/sh
(
cat <<eohead
#!/bin/sh
INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
cat <<eof
eohead
cat template
echo eof
) | /bin/sh
This don't require bash, was tested under dash and busybox.
这不需要bash,在dash和busybox下测试。
bash Without eval !
sedcmd=''
for var in INSTALLPATH SITEURL PHPSERV;do
printf -v sc 's/${%s}/%s/;' $var "${!var//\//\\/}"
sedcmd+="$sc"
done
sed -e "$sedcmd" <template
Could work into a loop:
可以进入一个循环:
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
if [ "$CFGFILE" ] ;then
sedcmd=''
for var in INSTALLPATH SITEURL PHPSERV;do
printf -v sc 's/${%s}/%s/;' $var "${!var//\//\\/}"
sedcmd+="$sc"
done
sed -e "$sedcmd" <template >"$CFGFILE"
fi
done <<<"
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
"
Compatible answer, using sed
This could work without so called bashisms, into a loop:
这可以在没有所谓的bashisms的情况下工作,进入一个循环:
#!/bin/sh
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
sedcmd="s|\\\${INSTALLPATH}|${INSTALLPATH}|;"
sedcmd="${sedcmd}s|\\\${SITEURL}|${SITEURL}|;"
sedcmd="${sedcmd}s|\\\${PHPSERV}|${PHPSERV}|;"
sed -e "$sedcmd" template >"$CFGFILE"
done <<eof
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
eof
Comparing outputs:
比较输出:
diff -u99 /tmp/file{1,2}
--- /tmp/file1 2015-05-31 11:02:03.407463963 +0200
+++ /tmp/file2 2015-05-31 11:02:03.407463963 +0200
@@ -1,22 +1,22 @@
server {
listen 80;
- root /somepath/somewhere;
- server_name example.com;
+ root '/some other path/elsewhere';
+ server_name sample2.com;
client_max_body_size 20m;
client_body_timeout 120s;
location / {
try_files /public/router.php =404;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
- fastcgi_pass 127.0.0.1:9000;
+ fastcgi_pass 127.0.0.1:9001;
fastcgi_index router.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location /assets {
try_files /app/$uri =404;
}
}