从 Nginx conf 中提取服务器的块和值

use*_*472 5 awk text-processing nginx

我们如何使用 AWK 提取 nginx 服务器块?输入

server { # php/fastcgi
listen       80;
server_name  domain1.com www.domain1.com;
access_log   logs/domain1.access.log  main;
root         html;

location ~ \.php$ {
  fastcgi_pass   127.0.0.1:1025;
}
}
server { # simple reverse-proxy
listen       80;
server_name  domain2.com www.domain2.com;
access_log   logs/domain2.access.log  main;

# serve static files
location ~ ^/(images|javascript|js|css|flash|media|static)/  {
  root    /var/www/virtual/big.server.com/htdocs;
  expires 30d;
}

# pass requests for dynamic content to rails/turbogears/zope, et al
location / {
  proxy_pass      http://127.0.0.1:8080;
}
}
Run Code Online (Sandbox Code Playgroud)

我们如何匹配所需的值并为每个 server{} 块打印一行?

例如

我需要获取listen|root|server_name 的值。所需的输出是

80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
Run Code Online (Sandbox Code Playgroud)

ter*_*don 5

由于每行可以有多个以空格分隔的值,因此使用起来awk有点棘手。这在 awk 中是绝对可能的,但使用 Perl 之类的东西更简单:

$ perl -lne '
    if(/(^| )server / || eof){ 
        print join " ",@ll if $ll[0]; 
        @ll=(); 
    }
    /^(listen|root|server_name)\s+(\S[^;]+)/ && push @ll,$2' file 
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
Run Code Online (Sandbox Code Playgroud)

-lne手段“逐行读取输入文件中的行(-n),剥离后换行和一个换行添加到每个print呼叫(-l)和运行由下式给出的脚本-e每行”。

编码:

  • if(/(^| )server / || eof){ : 如果当前行包含server由空格包围或在行首的单词,则此部分将运行。

  • print join " ",@ll if $ll[0]; : 如果当前数组中存储了任何内容@ll(因此,如果$ll[0]定义了数组的第一个元素 , ),则打印以空格连接的数组内容。

  • @ll=(); : 清空数组,以便我们可以获取下一个服务器的信息。

  • /^(listen|root|server_name)\s+(\S[^;]+)/ && push @ll,$2': 如果这一行以关键字之一开头,然后有一个或多个空白字符,则找到第一个非空白字符和尽可能多的非;字符,直到行尾并添加它(括号将捕获模式所以“这个”现在是$2) 到阵列@ll进行打印。


这是在 awk 中执行此操作的(丑陋)方式:

$ awk '
    (/ server\s*\{/){ 
        if(out){
            print out
        }
        out=""
    } 
    ($1=="listen" || $1=="root" || $1=="server_name"){
        gsub(";",""); 
        $1=""; 
        gsub(/^ */,""); 
        out ? out=out" "$0 : out=$0
    }
    END{print out}' file 
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
Run Code Online (Sandbox Code Playgroud)