I'm trying to write a script which dynamically can update my local vhosts file.
Basically the idea is to add/remove a virtual host block dynamically.
- generate vhost block dynamically ☑️
- insert generated block into desired section of vhosts file ⚠️
- script that can remove a virtual host by ServerName
./remove-vhost example.test
from section (pending)
My vhosts
file looks something like this:
## Definition of all system wide vhosts, e.g.
<VirtualHost *:80>
DocumentRoot "/Users/sammy/workspace"
ServerName localhost
</VirtualHost>
# ...
## Virtual hosts inside this section should be added/removed
## dynamically
## GENERATED INCLUDES - DO NOT MODIFY ##
<VirtualHost *:80> # This host was generated automatically
DocumentRoot "/Users/sammy/workspace/example.com"
ServerName example.test
</VirtualHost>
# ...
## END GENERATED INCLUDES ##
I tried to figure out how to modify the vhosts file using sed
.
I'm not very used to work with sed, so any assistance is well appreciated.
I tired things like
#!/bin/bash
# ...
VHOSTS_PATH="/usr/local/etc/httpd/extra/httpd-vhosts.conf"
BEGIN_OF_CODEBLOCK="## GENERATED INCLUDES - DO NOT MODIFY ##"
END_OF_CODEBLOCK="## END GENERATED INCLUDES ##"
BLOCK_TO_ADD="
<VirtualHost *:$PORT>
DocumentRoot \"$WORKING_DIR\"
ServerName $SERVER_NAME
</VirtualHost>"
sed "/$BEGIN_OF_CODEBLOCK/ { N; s/$BEGIN_OF_CODEBLOCK/$BLOCK_TO_ADD\n&/ }" $VHOSTS_PATH
## breaks with different errors saying e.g
# unescaped newline inside substitute pattern
Who could help me solving this issue?
CodePudding user response:
Using shell variables inside sed commands has various issues.
If you have perl
available - it's a simpler option.
You export your shell variables so perl can access them through its %ENV
(environment) variable.
export BLOCK_TO_ADD BEGIN_OF_CODEBLOCK
perl -ple '$_ = "$ENV{BLOCK_TO_ADD}\n$_" if /$ENV{BEGIN_OF_CODEBLOCK}/' "$VHOSTS_PATH"
$_
is a perl variable which in this case will contain the "current line"
You can write it using the s///
command if that makes more sense to you:
perl -ple 's/$ENV{BEGIN_OF_CODEBLOCK}/$ENV{BLOCK_TO_ADD}\n$&/ if /$ENV{BEGIN_OF_CODEBLOCK}/' "$VHOSTS_PATH"
&
in sed changes to $&
in perl.
You can use perl -pi -le
to add the -i
option.
CodePudding user response:
sed
is maybe not the best tool for this. So let's use awk
instead. But as you ask for a sed
solution see at the end for a sed
-based insertion.
Insertion with awk
$ VHOSTS_PATH="/usr/local/etc/httpd/extra/httpd-vhosts.conf"
$ BEGIN_OF_CODEBLOCK="## GENERATED INCLUDES - DO NOT MODIFY ##"
$ BLOCK_TO_ADD="<VirtualHost *:$PORT>
DocumentRoot \"$WORKING_DIR\"
ServerName $SERVER_NAME
</VirtualHost>"
$ awk -vb="$BEGIN_OF_CODEBLOCK" -vi="$BLOCK_TO_ADD" '
{print} $0 == b {print i}' "$VHOSTS_PATH"
...
## GENERATED INCLUDES - DO NOT MODIFY ##
<VirtualHost *:80>
DocumentRoot "foo"
ServerName bar
</VirtualHost>
...
## END GENERATED INCLUDES ##
Deletion with awk
Note: this deletes any matching section, even if not in the ## GENERATED INCLUDES...
part.
$ VHOSTS_PATH="/usr/local/etc/httpd/extra/httpd-vhosts.conf"
$ SERVER_NAME=bar
$ awk -vs='\\<ServerName[[:space:]] '"$SERVER_NAME"'\\>' '
/^[[:space:]]*<VirtualHost/,/^[[:space:]]*<\/VirtualHost>/ {
tmp = tmp $0 "\n"}
/^[[:space:]]*<\/VirtualHost>/ && tmp {
if(tmp !~ s) printf("%s", tmp); tmp = ""; next}
!tmp {print}' "$VHOSTS_PATH"
...
## GENERATED INCLUDES - DO NOT MODIFY ##
<VirtualHost *:80> # This host was generated automatically
DocumentRoot "/Users/sammy/workspace/example.com"
ServerName example.test
</VirtualHost>
## END GENERATED INCLUDES ##
sed
-based insertion
In such cases it is sometimes easier if you store the sed
script itself in a shell variable:
$ VHOSTS_PATH="/usr/local/etc/httpd/extra/httpd-vhosts.conf"
$ BEGIN_OF_CODEBLOCK="## GENERATED INCLUDES - DO NOT MODIFY ##"
$ PORT=80
$ WORKING_DIR=foo
$ SERVER_NAME=bar
$ script='/^'"$BEGIN_OF_CODEBLOCK"'$/a \
<VirtualHost *:'"$PORT"'>\
DocumentRoot \"'"$WORKING_DIR"'\"\
ServerName '$SERVER_NAME'\
</VirtualHost>'
$ sed -e "$script" "$VHOSTS_PATH"
## Definition of all system wide vhosts, e.g.
<VirtualHost *:80>
DocumentRoot "/Users/sammy/workspace"
ServerName localhost
</VirtualHost>
# ...
## Virtual hosts inside this section should be added/removed
## dynamically
## GENERATED INCLUDES - DO NOT MODIFY ##
<VirtualHost *:80>
DocumentRoot "foo"
ServerName bar
</VirtualHost>
<VirtualHost *:80> # This host was generated automatically
DocumentRoot "/Users/sammy/workspace/example.com"
ServerName example.test
</VirtualHost>
# ...
## END GENERATED INCLUDES ##