Próbowałem znaleźć odpowiedź na to pytanie, ale jak dotąd nie miałem szczęścia:
Mam skrypt, który uruchamia inne skrypty, a wiele innych skryptów zawiera „set -x”, co powoduje, że wypisują każde wykonane polecenie. Chciałbym się tego pozbyć, ale zachowuję informacje, jeśli którykolwiek ze skryptów wyśle komunikat o błędzie do stderr.
Więc nie mogę po prostu pisać ./script 2>/dev/null
Ponadto nie mam uprawnień do edytowania tych innych skryptów, więc nie mogę ręcznie zmienić opcji set.
Myślałem o zarejestrowaniu wszystkiego, od stderr do osobnego pliku i odfiltrowaniu poleceń śledzenia, ale może istnieje prostszy sposób?
./script 2>some_file
Odpowiedzi:
W wersji
bash
4.1 i nowszej możesz to zrobić(działa również, gdy
bash
zostanie wywołany jakosh
).Zasadniczo mówimy,
bash
aby wyświetlać danextrace
wyjściowe na deskryptorze pliku 7 zamiast wartości domyślnej 2 i przekierować ten deskryptor pliku na/dev/null
. Numer fd jest dowolny. Użyj fd powyżej 2, który nie jest inaczej używany w twoim skrypcie. Jeśli powłoka, w której wpisujesz to polecenie, tobash
lubyash
, możesz nawet użyć liczby powyżej 9 (chociaż możesz napotkać problemy, jeśli deskryptor pliku jest używany wewnętrznie przez powłokę).Jeśli powłoka, z której wywołujesz ten
bash
skryptzsh
, to możesz także:aby zmienna była automatycznie przypisywana pierwszej wolnej wartości fd powyżej 9.
W starszych wersjach
bash
inną opcją, jeślixtrace
zostanie włączony za pomocąset -x
(w przeciwieństwie do#! /bin/bash -x
lubset -o xtrace
) byłoby przedefiniowanieset
jako wyeksportowanej funkcji, która nic nie robi po przekazaniu-x
(choć to zepsułoby skrypt, jeśli on (lub innybash
skrypt, który wywołuje) służyset
do ustawiania parametrów pozycyjnych).Lubić:
Inną opcją jest dodanie pułapki DEBUG do
$BASH_ENV
pliku, który działaset +x
przed każdym poleceniem.To nie zadziała, gdy
set -x
zostanie wykonane w podpowłoce.Jak powiedział @ilkkachu, pod warunkiem, że masz uprawnienia do zapisu w dowolnym folderze w systemie plików, powinieneś być przynajmniej w stanie wykonać kopię skryptu i edytować go.
Jeśli nie ma gdzie napisać kopii skryptu, lub jeśli nie jest wygodne tworzenie i edytowanie nowej kopii za każdym razem, gdy pojawi się aktualizacja oryginalnego skryptu, nadal możesz zrobić:
To (i podejście do kopiowania) może nie działać poprawnie, jeśli skrypt robi coś wymyślnego
$0
lub specjalne zmienne, takie jak$BASH_SOURCE
(np. Szukanie plików, które są względne względem położenia samego skryptu), więc może być konieczne wykonanie dalszej edycji, takiej jak zastąp$0
ścieżką skryptu ...źródło
{BASH_XTRACEFD}>
Sztuczka działa wbash
4.1 lub nowszy, jak również.ksh93
albobash
że zmienna nie jest przekazywana w środowisku polecenia (porównaj<shell> -c 'export fd; printenv fd {fd}> /dev/null'
wzsh
,bash
iksh93
). Możesz sprawić, by działał wksh93
/bash
wykonując go w dwóch krokach lub ewentualnie używająceval
, ale dlabash
, miałoby to skutki uboczne, gdyby włączona była opcja xtrace.Ponieważ oni skrypty, to mógłby zrobić ich kopie i edytować te.
Poza tym filtrowanie danych wyjściowych wydaje się proste, możesz jawnie ustawić
PS4
coś bardziej niezwykłego niż pojedynczy plus, aby ułatwić filtrowanie:(oczywiście, że to załamie się na stdout i stdin, ale dodawanie stderr w Bash robi się trochę owłosione, więc zignoruję to)
źródło
PS4="%%%%" bash script.sh 2> >(grep -ve '^%%%%')
.bash
ma problemy, ponieważgrep
jest uruchamiane asynchronicznie (bash nie czeka na to, więc może (i często robi) dane wyjściowe po uruchomieniu następnego polecenia w skrypcie).