Я хочу time
команду, которая состоит из двух отдельных команд с одним выводом трубопровода к другому. Например, рассмотрим два сценария ниже:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
Теперь, как я могу time
сообщить о потраченном времени foo.sh | bar.sh
(и да, я знаю, что канал здесь не имеет смысла, но это всего лишь пример)? Это работает, как и ожидалось, если я запускаю их последовательно в подоболочке без трубопровода:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
Но я не могу заставить его работать при обвязке:
$ 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
Я прочитал аналогичный вопрос ( Как запустить время на нескольких командах И записать вывод времени в файл? ), А также попробовал автономный time
исполняемый файл:
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
Это даже не работает, если я создаю третий скрипт, который запускает только канал:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
И тогда время, которое:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
Интересно, что он не выглядит так, как будто time
завершается, как только первая команда выполнена. Если я изменю bar.sh
на:
#!/bin/sh
sleep 2
seq 1 5
И time
опять же, я ожидал, что time
вывод будет напечатан раньше, seq
но это не так:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
Похоже time
, не считается время, которое потребовалось для выполнения, bar.sh
несмотря на ожидание его завершения перед печатью своего отчета 1 .
Все тесты выполнялись в системе Arch и использовали выпуск bash 4.4.12 (1). Я могу использовать bash только для проекта, частью которого он является, так что даже если zsh
или какая-то другая мощная оболочка сможет обойти его, это не будет для меня жизнеспособным решением.
Итак, как я могу получить время, которое потребовалось для запуска набора конвейерных команд? И, хотя мы на это, почему это не работает? Похоже, что time
сразу выходит, как только первая команда закончена. Зачем?
Я знаю, что могу получить индивидуальные времена с чем-то вроде этого:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
Но я все еще хотел бы знать, возможно ли рассчитать все это как одну операцию.
1 Похоже, что это не проблема с буфером, я попытался запустить сценарии с unbuffered
и, stdbuf -i0 -o0 -e0
и числа все еще печатались до time
вывода.