How can I list all vhosts in nginx
The answers so far will work, except if you have server_name
directives running over multiple lines, then it'll silently fail. They also seem to be written for human consumption (picking up extra lines like server_name_in_redirect off;
) so you can't include them in a script.
I have lots of virtual hosts, and wanted to use the output in a script (sigh), so here's something which is a lot longer, but should be robust enough for that purpose:
nginx -T | sed -r -e 's/[ \t]*$//' -e 's/^[ \t]*//' -e 's/^#.*$//' -e 's/[ \t]*#.*$//' -e '/^$/d' | \sed -e ':a;N;$!ba;s/\([^;\{\}]\)\n/\1 /g' | \grep -P 'server_name[ \t]' | grep -v '\$' | grep '\.' | \sed -r -e 's/(\S)[ \t]+(\S)/\1\n\2/g' -e 's/[\t ]//g' -e 's/;//' -e 's/server_name//' | \sort | uniq | xargs -L1
Since it's long and \
-y, I'll include a quick explanation of each line.
- Get nginx to print its entire configuration (so that we don't have to worry about which files to include) and sanitise it: remove leading and trailing space, comments (including trailing ones) and blank lines.
- Every line that doesn't end with a semi-colon or curly brace should be continued, so we replace any
\n
without a preceding;
,{
or}
with a space. This needs to use sed's weirdo:a;N;$!ba;
grab the whole file trick, and some grouping so that we can put the last character back with\1
, plus a bunch of extra backslashes for luck. - Now we can pull each
server_name
line, with some extra checks to remove nginx variables ($foo
) and only include valid domains (ie notlocalhost
and_
). - Any tabs/spaces between words get turned into carriage returns, then we remove surplus spaces (just in case), semi-colons and the
server_name
part. - Finally sort it, uniqify it and use
xargs -L1
to remove the single blank line at the top.
Note that there are some bits in here which are technically doubling up, but I like to be as clear and robust as possible. Suggestions for improvement welcome, though.