Como faço para procurar um arquivo por um padrão e, em seguida, extrair parte do padrão ou fornecer um padrão se o padrão não existir?

1

Estou tentando escrever um script que pesquisa uma lista pré-criada de processos em execução em várias máquinas. Estou procurando especificamente o rsyslogd em execução nesses dispositivos e tentando descobrir qual arquivo de configuração eles estão usando (se não estiver usando o padrão /etc/rsyslog.conf).

Neste momento, estou pesquisando com êxito as máquinas com esse loop:

for root_file in $TARGET_DIR/RESULTS*/ps_results; do
    grep rsyslogd $root_file | awk '{s = ""; for (i = 15; i <= NF; i++) s = s $i " "; print s}'
done

E ele retornará uma lista como

# get_configs $TARGET_DIR/
/usr/sbin/rsyslogd -n
/sbin/rsyslogd -i /var/run/syslogd.pid -c 5
/usr/sbin/rsyslogd -n -f /usr/syslog.conf
...

Mas o que eu quero é uma lista que mostre o endereço IP da máquina que está sendo verificada (que está no * do RESULTS * do script como está) seguido apenas pelo caminho para o arquivo de configuração, como então:

# get_configs $TARGET_DIR/
172.16.10.1     /etc/syslog.conf
172.16.10.2     /etc/syslog.conf
172.17.5.245    /usr/syslog.conf
... 

Eu estarei pegando esta lista e analisando os arquivos e encontrando quaisquer arquivos de configuração adicionais que eles possam linkar com a diretiva $IncludeConfig , mas eu tenho que limpar minha lista de arquivos primeiro.

O bloco mental que estou atingindo está testando a opção -f após o rsyslogd. Como o rsyslogd não requer o -f e ele é executado com o /etc/rsyslog.conf padrão, como eu manipulo o teste para a opção e extrai o caminho seguindo-o ou fornecendo um padrão?

Eu considerei usar sed ou cut para isolar '-f / path / to / file' e retornar /etc/rsyslog.conf em um resultado vazio, mas não estou conseguindo realizar isso.

    
por BigDamnHero 15.09.2018 / 21:05

2 respostas

2

Suponha que tenhamos os seguintes arquivos de entrada

$ grep . */ps_results
RESULTS-172.16.10.1/ps_results:/usr/sbin/rsyslogd -n
RESULTS-172.16.10.2/ps_results:/sbin/rsyslogd -i /var/run/syslogd.pid -c 5
RESULTS-172.17.5.245/ps_results:/usr/sbin/rsyslogd -n -f /usr/syslog.conf
$

Então, quanto a

$ awk '/rsyslogd/{gsub("^.*RESULTS-","",FILENAME);gsub("/ps_results","",FILENAME);b="/etc/rsyslog.conf";for(a=0;a++<NF;){if($a=="-f"){b=$(a+1)}};printf "%-15s%s\n",FILENAME,b}' RESULTS*/ps_results
172.16.10.1     /etc/rsyslog.conf
172.16.10.2     /etc/rsyslog.conf
172.17.5.245    /usr/syslog.conf
$

O mesmo código, anotado + formatado:

awk '/rsyslogd/ {
   # strip everything up to (and including) RESULTS- from the filename
   gsub("^.*RESULTS-","",FILENAME)
   # strip the /ps_results from the filename
   gsub("/ps_results","",FILENAME)
   # set the default rsyslog conf file
   b="/etc/rsyslog.conf"
   # look for a -f parameter: if found, grab conf file
   for(a=0;a++<NF;){
     if($a=="-f") {
       b=$(a+1)
     }
   }
   # print the ip addr and conf file
   printf "%-15s%s\n",FILENAME,b
}' RESULTS*/ps_results
    
por 15.09.2018 / 21:36
1

Você pode estender seu awk existente como este (este é um exemplo auto-contido):

awk '{ s=$0; 
       if (match($s, / -f [^ ]+/)) { 
         print substr($s, RSTART+4, RLENGTH-4) 
       } 
       else 
          print "/etc/syslog.conf" 
     }' < input

Isso pergunta se a string $s contém a expressão regular "(space) -f (space) (um ou mais caracteres não espaciais)"; em caso afirmativo, imprima a substring correspondente à expressão regular, compensada por 4 caracteres (e correspondentemente encurtada por 4 caracteres), para considerar o (espaço) -f (espaço). Se $s não não contiver a expressão regular acima, imprima o caminho padrão syslog.conf.

O código acima iria no final do seu script awk existente, substituindo a parte print s (e, claro, não reatribuindo s=$0 - que está lá apenas, então eu tinha dados para trabalhar).

    
por 15.09.2018 / 21:18