Bezpośrednie wyjście z polecenia do pliku zawierającego oryginalne polecenie ORAZ drukowanie w terminalu

8

Podczas uruchamiania niektórych testów muszę uruchomić szereg poleceń. Byłoby to dla mnie niezwykle przydatne i zaoszczędzić dużo czasu, gdyby istniał sposób na wykonanie tych wszystkich czynności:

  • Uruchom polecenie, które muszę uruchomić
  • Przekieruj wszystkie dane wyjściowe polecenia do określonego pliku
  • Dołącz oryginalne polecenie do określonego pliku
  • Wydrukuj dane wyjściowe z oryginalnego polecenia w terminalu

Ludzie zasugerowali użycie tee dla mnie, który świetnie wykonuje drukowanie na terminalu, a także wysyłanie do pliku, ale nie zawiera oryginalnego polecenia. Chciałbym skończyć z plikiem, w którym pierwszy wiersz to polecenie, które uruchomiłem, a poniżej to wynik polecenia.

Ktoś to zasugerował:

echo "ls -l" | xargs -I{} bash -c "echo >> output.file; eval {} >> output.file"

Ale to nie drukuje danych wyjściowych w terminalu ani nie dołącza oryginalnej komendy do pliku.

Byłbym wdzięczny za wszelkie pomysły.

Shaneoh
źródło
2
Prawie duplikat askubuntu.com/q/688498/295286 .
Sergiy Kolodyazhnyy
Nie znalazłem tego w moich poszukiwaniach - niezupełnie tak samo, ale prawdopodobnie doprowadziłbym mnie do odpowiedzi.
shaneoh
tak, i dlatego powiedziałem prawie duplikat. Ale szczerze mówiąc, moim zdaniem, możesz wziąć prawie każde rozwiązanie stamtąd i skorzystać z niego z orurowaniem tee.
Sergiy Kolodyazhnyy

Odpowiedzi:

14

Właśnie tego teeszukasz.

ls -l | tee outfile

wypisuje wyjście ls -lna stdout (tj. terminal) i jednocześnie zapisuje je w pliku outfile. Ale : Nie zapisuje nazwy polecenia ani do standardowego, ani do pliku. Aby to osiągnąć, wystarczy echouruchomić nazwę polecenia przed uruchomieniem polecenia i potokować oba wyjścia do tee:

( echo "ls -l" && ls -l ) | tee outfile

Uciążliwe jest pisanie, więc dlaczego nie zdefiniować funkcji?

both(){ ( echo "$@" && "$@" ) | tee outfile ;}

Potem możesz po prostu biec

both ls -l

aby uzyskać pożądany wynik. Umieść funkcję w swoim, ~/.bashrcaby była zdefiniowana w każdym nowym terminalu.

Jeśli chcesz móc określić plik wyjściowy jako pierwszy argument jak w

both output ls -l

zamiast tego zrób to:

both(){ ( echo "${@:2}" && "${@:2}" ) | tee "$1" ;}

Jeśli nie chcesz, aby plik wyjściowy został zastąpiony, ale raczej do niego dołączyć, dodaj -aopcję do tee.

deser
źródło
9

Możesz skorzystać z scriptpolecenia, które utworzy plik maszynopisu wszystkiego wydrukowanego na twoim terminalu. Tworzy rozwidlone muszle i będzie rejestrować wszystko, dopóki ta muszla nie zostanie opuszczona.

$ script my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
Script done on Tue 28 Nov 2017 09:46:27 AM UTC

Jeśli cat my_outputotrzymam ten sam wynik:

$ cat my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
exit

Script done on Tue 28 Nov 2017 09:46:27 AM UTC
AJefferiss
źródło
6

Możesz użyć funkcji debugowania powłoki razem z tee:

( set -x; command1 args...; command2 args ) 2>&1 | tee output.log
  • ( ... )uruchamia podpowłokę, która pozwala „zbierać” strumienie wyjściowe wszystkich poleceń wykonanych w podpowłoce. Zawiera także efekt setpolecenia poniżej dla tej podpowłoki.

  • set -xwłącza xopcję powłoki, która drukuje wszystkie polecenia uruchamiane przez powłokę do standardowego strumienia błędów przed ich uruchomieniem.

  • 2>&1 przekierowuje strumień 2 (błąd standardowy) do strumienia 1 (standardowe wyjście).

  • | przekierowuje standardowy strumień wyjściowy lewego polecenia do standardowego strumienia wejściowego prawego polecenia.

  • tee FILEkopiuje standardowy strumień wejściowy do pliku FILEi na standardowe wyjście.

Jeśli sekwencja poleceń znajduje się już w pliku skryptu, bardziej sensowne byłoby uruchomienie go w następujący sposób:

bash -x /path/to/script args... 2>&1 | tee output.log
David Foerster
źródło