Chcę timepolecenia składającego się z dwóch oddzielnych poleceń z jednym wyjściem potokowym do drugiego. Weźmy na przykład dwa poniższe skrypty:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
Jak mogę timezgłosić czas foo.sh | bar.sh(i tak, wiem, że fajka nie ma tutaj sensu, ale to tylko przykład)? Działa zgodnie z oczekiwaniami, jeśli uruchamiam je sekwencyjnie w podpowłoce bez instalacji:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
Ale nie mogę go uruchomić podczas instalacji:
$ time ( foo.sh | bar.sh )
real 0m4.009s
user 0m0.007s
sys 0m0.003s
$ time ( { foo.sh | bar.sh; } )
real 0m4.008s
user 0m0.007s
sys 0m0.000s
$ time sh -c "foo.sh | bar.sh "
real 0m4.006s
user 0m0.000s
sys 0m0.000s
Przeczytałem podobne pytanie ( Jak uruchomić czas na wielu poleceniach ORAZ zapisać czas wyjściowy do pliku? ), A także wypróbowałem samodzielny timeplik wykonywalny:
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
To nawet nie działa, jeśli utworzę trzeci skrypt, który uruchamia tylko potok:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
A potem czas, że:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
Co ciekawe, nie wydaje się, że timekończy się natychmiast po wykonaniu pierwszego polecenia. Jeśli zmienię bar.shna:
#!/bin/sh
sleep 2
seq 1 5
I timeznowu spodziewałem się, że timewydruk zostanie wydrukowany przed, seqale nie jest to:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
Wygląda na to, timeże nie liczy czasu wykonania bar.shpomimo oczekiwania na zakończenie przed wydrukowaniem raportu 1 .
Wszystkie testy zostały uruchomione w systemie Arch i przy użyciu wersji bash 4.4.12 (1). Mogę użyć bash tylko do projektu, który jest częścią tego, więc nawet jeśli zshjakaś inna potężna powłoka może go obejść, nie będzie to dla mnie realnym rozwiązaniem.
Jak mogę uzyskać czas potrzebny na uruchomienie zestawu potoków? A skoro już to robimy, dlaczego to nie działa? Wygląda na to, że timenatychmiast kończy działanie, gdy tylko zakończy się pierwsze polecenie. Czemu?
Wiem, że mogę uzyskać indywidualne czasy za pomocą czegoś takiego:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
Ale nadal chciałbym wiedzieć, czy jest możliwe, aby całość czasu zaplanować jako pojedynczą operację.
1 To nie wydaje się być problemem z buforem, próbowałem uruchomić skrypty z, unbuffereda stdbuf -i0 -o0 -e0liczby były nadal drukowane przed timewyjściem.