Czy istnieje sposób wyświetlania wszystkich skryptów wywoływanych z innego skryptu?

6

Mam dużą liczbę skryptów, które muszę zmodyfikować. Każdy skrypt prawdopodobnie wywołuje od 5 do 10 innych skryptów, które z kolei mogą wywoływać kilka innych skryptów i kto wie, jak głęboko biegnie ta królicza nora.

Czy jest jakiś sposób na uzyskanie listy skryptów wywoływanych przez określony skrypt?

Myślę o czymś takim:

/home/root/ $ showscripts mytargetscript

wynik byłby mniej więcej taki:

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

Jeśli obraziłem bogów uniksowych, z góry oferuję swoją pokutę. Odpowiadam na wiele pytań na dba.se.

Max Vernon
źródło
2
Czy potrafisz uruchomić skrypty? Czy potrafisz je prześledzić za pomocą np. trussWywołań execsystemowych?
Colin 't Hart
2
Bogowie uniksowi są zadowoleni. Na razie.
mikeserv

Odpowiedzi:

5

Nie ma ogólnego rozwiązania, ponieważ istnieje niezliczona ilość sposobów, za pomocą których skrypt może wywoływać inne skrypty. Możesz zrobić coś, grepco może działać dla twoich skryptów, ale ogólnie nie.

Jakie skrypty to wywołuje?

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

Jeśli jesteś w stanie uruchomić te skrypty, możesz je prześledzić na dwa sposoby.

set -x

sprawi, że skrypt wydrukuje każde wykonane polecenie w rozszerzonej formie. Następnie możesz sprawdzić te polecenia pod kątem tych, które uruchamiają skrypty.

strace -ff

Przesada, ale stracedaje ci wszystko, co robi proces, a dzięki -ffopcji podąża za króliczą dziurą prawie do końca. Mówię prawie dlatego, że istnieją sposoby na obejście tego. Czy podąża za demonami?

Grep stracedla wywołań open()lub exec*()filtruj je w poszukiwaniu plików, które są skryptami, a możesz być gdzieś w pobliżu pełnego obrazu [dla tego jednego uruchomienia skryptu, który wykonałeś - nie licząc skryptów, które są wywoływane tylko w innych warunkach].

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

Możesz więc być kreatywny ze swoimi rozwiązaniami, po prostu nie oczekuj takiego, który pasuje do każdej sytuacji.

frostschutz
źródło
Proszę zobaczyć „ogólne” rozwiązanie w mojej odpowiedzi.
lcd047
@ lcd047 Widziałem twoją odpowiedź, dlatego nie podałem grepprzykładu. Ale grepnie znajduje żadnych prócz najbardziej prymitywnych wywołań (które mogą być wszystkim, co jest tu potrzebne, ale kto wie) i istnieje możliwość fałszywych dopasowań.
frostschutz
Jeśli skrypty nie zostaną celowo zaciemnione, nie powinno być fałszywych negatywów. Rzeczywiście istnieje możliwość uzyskania wyników fałszywie dodatnich, w sytuacjach takich jak # this script is commented out i echo "havea nice script".
lcd047
Nie jest to zaciemnianie, jeśli skrypt wykonuje skrypt w hookach / *. Sh. Skrypty wywołują takie skrypty przez cały czas. I to miałem na myśli, mówiąc „brak ogólnego rozwiązania”. Jest tylko tyle, ile możesz zrobić z grepem, nie wiedząc nic o danym skrypcie.
frostschutz
Hmm, prawda, to też jest dość powszechne.
lcd047
3

Asusming wszystkie skrypty żyją w tym samym katalogu, nie mają w nazwach tabulatorów ani znaków nowej linii, a lista „interesujących” skryptów znajduje się w pliku scripts.txt, po jednym w wierszu, a także przy założeniu, że powłoka może dokonywać <(...)podstawień procesów:

#! /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

To buduje plik calls.txt. Plik składa się z par oddzielonych tabulatorami script1 script2, które opisują relacje „ script1wywołania script2”.

Musisz nakarmić calls.txtnastępujący skrypt Perla:

#!/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($_));
}

Skrypt buduje ukierunkowany wykres na podstawie relacji wywołania, a następnie drukuje następców dla wszystkich wierzchołków (tj. Skryptów).

Oczywiście skrypt wymaga modułu Perl Graph. Zakładając, że masz cpanmskrypt, możesz zainstalować wymagany moduł, uruchamiając go cpanm Graph.

lcd047
źródło
1
Nie wierzę, że to rekurencyjnie się obniża?
Colin 't Hart
1
@ Colin'tHart Racja, nie ma. Ale możesz wywnioskować z niego odpowiedź za pomocą modułu Pel Graph :: Directed. Zmienię swoją odpowiedź.
lcd047
niestety nasze skrypty się nie kończą .sh. w ogóle nie mają rozszerzenia. :-(
Max Vernon
@ MaxVernon Cóż, masz jakiś sposób, aby uzyskać listę nazw skryptów w pliku po scripts.txtjednym w wierszu, prawda?
lcd047
1
@ Colin'tHart Zaktualizowano.
lcd047
0

Biorąc pod uwagę scenariusz

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

Następnie

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

produkuje

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

i dlatego pokażą te połączenia, jeśli zaczynają się na początku linii (dopuszcza spacje lub tabulatory)

Można również zidentyfikować pliki wykonywalne dla „listy plików, dla których można to zrobić” zamiast utrzymywać listę zakodowaną przy pomocy np.

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

i możesz fajkować

Michael Durrant
źródło
0

Jeden z możliwych sposobów (niesprawdzony) jest następujący.

Podsumowanie: masz wiele skryptów powłoki, wszystkie wywołują się nawzajem. Chcesz wiedzieć, jaka jest relacja wywołująca między tymi skryptami.

Załóżmy, że wszystkie skrypty są wywoływane jako osobne programy, ponieważ Gilles mówi mi, że w takim przypadku wywoływany skrypt jest procesem potomnym wywołującego skryptu.

Następnie umieść kod w każdym skrypcie, który zapisuje takie informacje, jak identyfikator procesu, identyfikator procesu nadrzędnego i nazwa skryptu do bazy danych. Ten kod może być wspólny dla wszystkich skryptów. Następnie przetwarzaj informacje bazy danych po uruchomieniu skryptu (ów), aby ustalić relację wywoływania między skryptami.

Faheem Mitha
źródło