How can I list all vhosts in nginx

2020-05-25 03:51发布

Is there a command that will list all vhosts or servers running under nginx on CentOS? I would like to pipe the results to a text file for reporting purposes.

I'm looking for something similar to this command that I use for Apache:

apachectl -S 2>&1 | grep 'port 80'

7条回答
一纸荒年 Trace。
2楼-- · 2020-05-25 04:34

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.

  1. 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.
  2. 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.
  3. Now we can pull each server_name line, with some extra checks to remove nginx variables ($foo) and only include valid domains (ie not localhost and _).
  4. 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.
  5. 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.

查看更多
做个烂人
3楼-- · 2020-05-25 04:42

@anthony-briggs is correct to point out that most other answers given here won't work if your server_name ... ; declarations are spread out across multiple lines.

However, if you can afford the luxury of having a perl interpreter at your disposal, you can shorten his solution to this oneliner:

nginx -T | perl -ln0777e '$,=$\; s/^\s*#.*\n//mg; print grep !$u{$_}++ && !m/^_$/, map m/(\S+)/g, m/\bserver_name\s++(.*?)\s*;/sg'

In chunks:

perl -l -n -0777 -e

-l : Make the print command terminate its output with a newline;

It also causes trailing newlines to be stripped from each input record as its read, but that doesn't bother us because we:

-n -0777 : Slurp all input into $_ in one go (one record);

-e : Simply executes the next argument as Perl source;


$, = $\ ;

Make the print command also output a newline between each of its arguments;


s/^\s*#.*\n//mg ;

Remove all comments;

Disregarding leading whitespace, comments are assumed to start and run through to the end of a line ( . does not match a newline here);


m/\bserver_name\s++(.*?)\s*;/sg

Produce everything between all server_name ... ; declarations (. does match newlines here);


... which are all map-ped to:

map m/(\S+)/g, 

... that will leave only the consecutive non-whitespace chunks;


... which are then grep-ped for uniqueness and not being the special "_" server name,

grep !$u{$_}++ && !m/^_$/, 

... and print-ed (unsorted).

查看更多
迷人小祖宗
4楼-- · 2020-05-25 04:48

You can list the domains one line at a time using the following

nginx_domains(){
    domains=`find /etc/nginx/ -type f -name "*.conf" -print0 | xargs -0 egrep '^(\s|\t)*server_name' | sed -r 's/(.*server_name\s*|;)//g'`
    for domain in $domains; do 
       echo $domain; 
    done
}
查看更多
家丑人穷心不美
5楼-- · 2020-05-25 04:49

Update: Thanks to @Putnik for pointing out an easier way (but I prefer only listing sites-enabled):

grep server_name /etc/nginx/sites-enabled/* -RiI

Old Post:

Try something like this:

find /etc/nginx/sites-enabled/ -type f -print0 | xargs -0 egrep '^(\s|\t)*server_name'

Hope that helps!

查看更多
地球回转人心会变
6楼-- · 2020-05-25 04:49

grep server_name /etc/nginx/* -RiI

Imho much faster to type than @Haubix's answer. Add |grep -v "#" optionally

查看更多
smile是对你的礼貌
7楼-- · 2020-05-25 04:52

Beside all the other great solution, if you just need a simple list of all names one per line, like:

example.com
my.example.com
etc.com

Parse the config. Get all lines with server_name. Remove server_name. Finally put one domain per line.

sudo nginx -T | grep "server_name " | sed 's/.*server_name \(.*\);/\1/' | sed 's/ /\n/'
查看更多
登录 后发表回答