Existe uma maneira de exibir todos os scripts chamados de algum outro script?

6

Eu tenho um grande número de scripts que preciso modificar. Cada script provavelmente chama de 5 a 10 outros scripts, que por sua vez podem chamar vários outros scripts, e quem sabe o quão profundo é esse buraco de coelho.

Existe alguma maneira de obter uma lista de scripts chamados por um script específico?

Estou pensando em algo como:

/home/root/ $ showscripts mytargetscript

a saída seria algo como:

/home/root/mytargetscript
/home/root/asubscript
/home/root/bsubscript
...

Se eu ofendi os deuses Unix, eu ofereço minha penitência com antecedência. Eu respondo muitas perguntas no dba.se.

    
por Max Vernon 04.06.2015 / 16:39

4 respostas

5

Não há solução genérica, pois há inúmeras maneiras de um script estar usando para chamar outros scripts. Você pode fazer um grep que pode funcionar para seus scripts, mas não em geral.

Quais scripts isso chama?

$(find / -executable -name "*.sh" -print0 | shuf -z -n 1)

Se você conseguir executar esses scripts, poderá rastreá-los de duas maneiras.

set -x

fará com que o seu script imprima cada comando que ele executa na forma expandida. Você pode então verificar esses comandos para aqueles que executam scripts.

strace -ff

Overkill, mas strace fornece tudo o que um processo faz e, com a opção -ff , ele também segue o buraco do coelho até o final. Eu digo quase porque existem maneiras de contornar isso. Acompanha daemons?

Grep o strace para chamadas para open() ou exec*() e filtrar para arquivos que são scripts e você pode estar em algum lugar perto de uma imagem completa [para essa execução do script que você criou - sem contar os scripts são chamados apenas sob outras condições].

$ strace -ff ./testscript.sh |& grep 'open.*\.sh"' 
open("./testscript.sh", O_RDONLY)       = 3
[pid 24486] open("./CD-DVD Image erstellen.sh", O_RDONLY) = 3

Assim, você pode ser criativo com suas soluções, mas não espere uma que se adapte a todas as situações.

    
por 04.06.2015 / 17:04
3

Assumindo todos os scripts ao vivo no mesmo diretório, eles não têm guias ou novas linhas em seus nomes, e você tem a lista dos "interessantes" em um arquivo scripts.txt , um por linha, e também supondo que seu shell pode fazer <(...) substituições do processo:

#! /bin/sh
while read -r s; do
    fgrep -o -w -f <(fgrep -v -w "$s" scripts.txt) "$s" /dev/null | \
        sort -u | \
        tr : '\t' >>calls.txt
done <scripts.txt

Isso cria um arquivo calls.txt . O arquivo é formado por pares separados por tabulação script1 script2 , que descrevem relações " script1 calls script2 ".

Você precisa alimentar calls.txt com o seguinte script Perl:

#!/usr/bin/env perl
use v5.10;                  
use strict;                 
use warnings;               

use Graph::Directed;        

my $g = Graph::Directed->new;

while (<>) {                
    chomp;                  
    $g->add_edge( split /\t/ );
}                           

for ( sort $g->vertices ) { 
    say "$_: " . join(', ', sort $g->all_successors($_));
}

O script cria um gráfico direcionado a partir das relações de chamada e, em seguida, imprime os sucessores de todos os vértices (ou seja, scripts).

É claro que o script precisa do módulo% PerlGraph. Supondo que você tenha o script cpanm , você pode instalar o módulo necessário executando cpanm Graph .

    
por 04.06.2015 / 16:47
0

Dado um script de

$ cat the_script
ls
/bin/ls
touch ./xx.xx
ls
/bin/ls
ls
ls
  /bin/ls
ls
    /bin/ls(tabs)

Então

$ cat the_script | grep ^[[:space:]]*\t*\/

produz

/bin/ls
/bin/ls
  /bin/ls
    /bin/ls

e, portanto, mostrará essas chamadas se começarem no início das linhas (permite espaços ou tabulações)

Você também pode identificar arquivos executáveis para a "lista de arquivos para fazer isso" em vez de manter uma lista codificada com, por exemplo,

$ find -type f -perm /u=x,g=x,o=x
./test.sh
./the_script

e você pode canalizar

    
por 05.06.2015 / 00:25
0

Uma maneira possível (não testada) é a seguinte.

Resumo: você tem muitos scripts de shell, todos chamando uns aos outros. Você quer saber qual é a relação de chamada entre esses scripts.

Vamos supor que os scripts sejam invocados como programas separados, uma vez que Gilles me diz que, nesse caso, o script chamado é um processo filho do script de chamada.

Em seguida, coloque algum código em cada script, que grava informações como id do processo, id do processo pai e o nome do script em um banco de dados. Esse código pode ser comum a todos os scripts. Depois, processe as informações do banco de dados depois de executar seus scripts, para determinar o relacionamento entre os scripts.

    
por 05.06.2015 / 01:17

Tags