如何在 Linux 上使用时间命令

想知道一个进程运行了多长时间以及更多? Linux time
命令返回时间统计信息,让您深入了解程序使用的资源。
时间有很多亲人
有许多 Linux 发行版和不同的类 Unix 操作系统。其中每一个都有一个默认的命令外壳。现代 Linux 发行版中最常见的默认 shell 是 bash shell。但还有许多其他的,例如 Z shell (zsh) 和 Korn shell (ksh)。
所有这些 shell 都包含它们自己的 time
命令,作为内置命令或保留字。当您在终端窗口中键入 time
时,shell 将执行其内部命令,而不是使用作为 Linux 发行版的一部分提供的 GNU time
二进制文件。
我们想使用 time
的 GNU 版本,因为它有更多的选项并且更灵活。
哪个时间运行?
您可以使用 type
命令检查将运行哪个版本。 type
会让您知道 shell 是否会使用其内部例程自行处理您的指令,或者将其传递给 GNU 二进制文件。
在终端窗口中输入单词 type
、一个空格,然后输入单词 time
,然后按 Enter。
type time

我们可以看到在 bash shell 中 time
是一个保留字。这意味着 Bash 将默认使用其内部 time
例程。
type time

在 Z shell (zsh) 中,time
是保留字,因此默认情况下将使用内部 shell 例程。
type time

在 Korn shell 中,time
是一个关键字。将使用内部例程代替 GNU time
命令。
运行 GNU 时间命令
如果您的 Linux 系统上的 shell 有一个内部 time
例程,如果您希望使用 GNU time
二进制文件,则需要明确说明。您必须:
- 提供二进制文件的完整路径,例如
/usr/bin/time
。运行which time
命令来查找此路径。 - 使用
命令时间
。 - 使用像
\time
这样的反斜杠。

which time
命令为我们提供了二进制文件的路径。
我们可以通过使用 /usr/bin/time
作为启动 GNU 二进制文件的命令来对此进行测试。这样可行。我们从 time
命令得到一个响应,告诉我们我们没有提供任何命令行参数来让它工作。
输入 command time
也可以,我们从 time
获得相同的使用信息。 command
命令告诉 shell 忽略下一个命令,以便它在 shell 之外进行处理。
在命令名称前使用 \
字符与在命令名称前使用 command
相同。
确保您使用的是 GNU time
二进制文件的最简单方法是使用反斜杠选项。
time
\time

time
调用时间的 shell 版本。 \time
使用time
二进制。
使用时间命令
让我们为一些程序计时。我们使用了两个名为 loop1
和 loop2
的程序。它们是从 loop1.c 和 loop2.c 创建的。除了展示一种编码效率低下的影响外,它们没有做任何有用的事情。
这是 loop1.c。在两个嵌套循环中需要字符串的长度。长度是预先获得的,在两个嵌套循环之外。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int main (int argc, char* argv[])
{
int i, j, len, count=0;
char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek";
// get length of string once, outside of loops
len = strlen( szString );
for (j=0; j<500000; j++) {
for (i=0; i < len; i++ ) {
if (szString[i] == '-')
count++;
}
}
printf("Counted %d hyphens\n", count);
exit (0);
} // end of main
这是 loop2.c。对于外循环的每个循环,都会一次又一次地获取字符串的长度。这种低效率应该在时间上表现出来。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int main (int argc, char* argv[])
{
int i, j, count=0;
char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek";
for (j=0; j<500000; j++) {
// getting length of string every
// time the loops trigger
for (i=0; i < strlen(szString); i++ ) {
if (szString[i] == '-')
count++;
}
}
printf("Counted %d hyphens\n", count);
exit (0);
} // end of main
让我们启动 loop1
程序并使用 time
来衡量它的性能。
\time ./loop1

现在让我们对 loop2
做同样的事情。
\time ./loop2

这给了我们两组结果,但它们的格式非常丑陋。我们稍后可以做一些事情,但让我们从结果中挑选一些信息。
程序运行时有两种执行模式,它们在这两种模式之间来回切换。这些称为用户模式和内核模式。
简而言之,用户模式下的进程不能直接访问其自身分配之外的硬件或引用内存。为了访问这些资源,进程必须向内核发出请求。如果内核批准请求,则进程进入内核模式执行,直到满足要求。然后该过程切换回用户模式执行。
loop1
的结果告诉我们,loop1
在用户模式下花费了 0.09 秒。它要么在内核模式下花费了零时间,要么在内核模式下的时间值太低而无法在向下舍入后注册。总耗时为 0.1 秒。 loop1
在其总耗用时间内平均获得 89% 的 CPU 时间。
低效的 loop2
程序的执行时间是原来的三倍。其总耗时为 0.3 秒。用户模式下的处理时间持续时间为 0.29 秒。没有为内核模式注册。 loop2
在其运行期间平均获得 96% 的 CPU 时间。
格式化输出
您可以使用格式字符串自定义 time
的输出。格式字符串可以包含文本和格式说明符。格式说明符列表可以在 time
的手册页中找到。每个格式说明符代表一条信息。
打印字符串时,格式说明符将替换为它们代表的实际值。例如,CPU 百分比的格式说明符是字母 P
。要向 time
表明格式说明符不仅仅是一个常规字母,请向其添加一个百分号,例如 %P
。让我们在示例中使用它。
-f
(格式字符串)选项用于告诉time
,后面是格式字符串。
我们的格式字符串将打印字符“程序:”和程序名称(以及您传递给程序的任何命令行参数)。 %C
格式说明符代表“正在计时的命令的名称和命令行参数”。 \n
导致输出移动到下一行。
有很多格式说明符并且它们区分大小写,因此请确保您在自己执行此操作时正确输入它们。
接下来,我们将打印字符“Total time:”,后跟本次程序运行的总运行时间值(由 %E
表示)。
我们使用 \n
来换行。然后我们将打印字符“User Mode (s)”,后跟在用户模式下花费的 CPU 时间值,由 %U
表示。
我们使用 \n
来换行。这次我们准备的是内核时间值。我们打印字符“Kernel Mode (s)”,后跟在内核模式下花费的 CPU 时间的格式说明符,即 %S
。
最后,我们将打印字符“\n
CPU:”,为我们提供一个新行和该数据值的标题。 %P
格式说明符将给出定时进程使用的 CPU 时间的平均百分比。
整个格式字符串用引号括起来。如果我们对值的对齐很挑剔,我们可以包含一些 \t
字符来在输出中放置制表符。
\time -f "Program: %C\nTotal time: %E\nUser Mode (s) %U\nKernel Mode (s) %S\nCPU: %P" ./loop1

将输出发送到文件
要记录您进行的测试的时间,您可以将 time
的输出发送到文件。为此,请使用 -o
(输出)选项。程序的输出仍将显示在终端窗口中。只有 time
的输出被重定向到文件。
我们可以重新运行测试并将输出保存到 test_results.txt
文件中,如下所示:
\time -o test_results.txt -f "Program: %C\nTotal time: %E\nUser Mode (s) %U\nKernel Mode (s) %S\nCPU: %P" ./loop1
cat test_results.txt

loop1
程序输出显示在终端窗口中,time
的结果转到 test_results.txt
文件。
如果要在同一文件中捕获下一组结果,则必须使用 -a
(追加)选项,如下所示:
\time -o test_results.txt -a -f "Program: %C\nTotal time: %E\nUser Mode (s) %U\nKernel Mode (s) %S\nCPU: %P" ./loop2
cat test_results.txt

现在应该很清楚为什么我们使用 %C
格式说明符将程序名称包含在格式字符串的输出中。
我们没时间了
time
命令可能最适合程序员和开发人员用于微调他们的代码,对于任何想要在每次启动程序时更多地了解引擎盖下发生的事情的人也很有用。
Linux Commands | ||
Files | tar · pv · cat · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · type · rename · zip · unzip · mount · umount · install · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · convert · rclone · shred · srm · scp · gzip · chattr · cut · find · umask · wc | |
Processes | alias · screen · top · nice · renice · progress · strace · systemd · tmux · chsh · history · at · batch · free · which · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · timeout · wall · yes · kill · sleep · sudo · su · time · groupadd · usermod · groups · lshw · shutdown · reboot · halt · poweroff · passwd · lscpu · crontab · date · bg · fg · pidof · nohup · pmap | |
Networking | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw · arping · firewalld |
RELATED: Best Linux Laptops for Developers and Enthusiasts