Bash

為什麼內置時間在管道中不起作用?

  • January 17, 2016

我有以下範例腳本:

#!/usr/bin/env bash
sleep 5
printf "times cmd: "
times
printf "pipeline: "
times | ( read user sys; echo $user; )
printf "head: "
times | head -n1
printf "times cmd again: "
times

具有以下輸出:

$ ./test.sh 
times cmd: 0m0.003s 0m0.005s
0m0.001s 0m0.001s
pipeline: 0m0.000s
head: 0m0.000s 0m0.000s
times cmd again: 0m0.003s 0m0.006s
0m0.003s 0m0.004s

問題是,為什麼times命令在與管道一起使用時會重置時間?有沒有辦法避免它以解析值?

在管道中,所有命令都在子 shell 中執行。times報告外殼及其子外殼所花費的時間,但不報告其父外殼所花費的時間。

您可以嘗試替換程序:

times > >( head -n1 )
times > >( read user sys ; echo $user )

這是我們正在談論的外殼的問題。

在這個外殼上,我得到:

$ times
0m9.805s 0m3.372s
39m29.072s 0m15.537s

因為它已經執行了一段時間。

但是,子 shell 將報告零:

$ ( times )
0m0.000s 0m0.000s
0m0.000s 0m0.000s

並且,由於管道在其每個部分的子外殼中執行:

$  sleep 10 | times
0m0.000s 0m0.000s
0m0.000s 0m0.000s

如果您執行上面的命令,您應該會times立即看到輸出(因為它不依賴於管道)並且 shell 提示符會在 10 秒後返回。

解決方法?

留在“這個”外殼中:

$ times > >(read user sys; echo "$user") 

那麼,為什麼需要時間?可以time或更強大的功能/usr/bin/time為您工作嗎?

使用時間:

$ TIMEFORMAT="%R;%U;%S"; time { sleep 1; }
1.001;0.000;0.000
$ TIMEFORMAT="%U"; time { sleep 1; }         #### If you only want user.
0.000

將幾個過程括在大括號中:

$ time { wc /etc/hosts; sleep 2; }
21 115 327 /etc/hosts

real    0m2.003s
user    0m0.000s
sys     0m0.000s

使用更強大的外部time(遺憾的是它只適用於外部執行檔):

$ /usr/bin/time wc /etc/hosts
21 115 327 /etc/hosts
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata 534maxresident)k
0inputs+0outputs (0major+109minor)pagefaults 0swaps

引用自:https://unix.stackexchange.com/questions/255919