shell内置、函数、管道和命令列表上的保留字和命令“time”之间的区别?

shell内置、函数、管道和命令列表上的保留字和命令“time”之间的区别?

在 Bash 参考手册中,

使用time作为保留字允许计时shell 内置函数,外壳函数, 和管道。外部 time命令无法轻松地对这些进行计时。

  1. 您能解释一下为什么引用这样说吗?

    这是因为保留字和命令之间的差异,而不仅仅限于 的情况time吗?例如,bash shell 如何以不同的方式解析或解释它们?

    或者这仅限于以下情况time

  2. 在以下示例中,

    为什么外部time在内置 shell 和管道上工作,而引用说它“无法轻松地对这些进行计时”?

    外部time开启一个内置的 shell:

    $ /usr/bin/time echo hello
    hello
    0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 1676maxresident)k
    0inputs+0outputs (0major+78minor)pagefaults 0swaps
    

    外部time开启一条管道:

    $ /usr/bin/time sleep 10 | sleep 5
    0.00user 0.00system 0:10.00elapsed 0%CPU (0avgtext+0avgdata 1776maxresident)k
    0inputs+0outputs (0major+79minor)pagefaults 0swaps
    
  3. 在下面的例子中,为什么外部timeon一个外壳函数失败?它的错误输出是什么意思?

    $ function mytest () { sleep 10; }
    
    $ /usr/bin/time mytest
    /usr/bin/time: cannot run mytest: No such file or directory
    Command exited with non-zero status 127
    0.00user 0.00system 0:00.03elapsed 0%CPU (0avgtext+0avgdata 1252maxresident)k
    32inputs+0outputs (0major+30minor)pagefaults 0swaps
    
  4. 看来这句话不仅仅适用于计时 shell 内置函数、shell 函数和管道,还要讲究时机一组命令:

    $ time { echo hello; sleep 3; echo tim; }
    hello
    tim
    
    real    0m3.002s
    user    0m0.000s
    sys 0m0.000s
    
    
    $ /usr/bin/time { echo hello; sleep 3; echo tim; }
    bash: syntax error near unexpected token `}'
    

    为什么 shell }在命令的情况下会显示“bash:意外标记附近的语法错误” /usr/bin/time

答案1

bashtime是一个保留字,因此 shell 可以以自己的方式解析它并为其应用规则。

这是代码显示如何bash解析以time保留字开头的行:

static int
time_command_acceptable ()
{
#if defined (COMMAND_TIMING)
  int i;

  if (posixly_correct && shell_compatibility_level > 41)
    {
      /* Quick check of the rest of the line to find the next token.  If it
     begins with a `-', Posix says to not return `time' as the token.
     This was interp 267. */
      i = shell_input_line_index;
      while (i < shell_input_line_len && (shell_input_line[i] == ' ' || shell_input_line[i] == '\t'))
        i++;
      if (shell_input_line[i] == '-')
    return 0;
    }

  switch (last_read_token)
    {
    case 0:
    case ';':
    case '\n':
    case AND_AND:
    case OR_OR:
    case '&':
    case WHILE:
    case DO:
    case UNTIL:
    case IF:
    case THEN:
    case ELIF:
    case ELSE:
    case '{':       /* } */
    case '(':       /* )( */
    case ')':       /* only valid in case statement */
    case BANG:      /* ! time pipeline */
    case TIME:      /* time time pipeline */
    case TIMEOPT:   /* time -p time pipeline */
    case TIMEIGN:   /* time -p -- ... */
      return 1;
    default:
      return 0;
    }
#else
  return 0;
#endif /* COMMAND_TIMING */
}

你看,time后面可以跟大多数其他bash保留字。

如果是外部命令,则应用正常规则,{被视为 的输入/usr/bin/time}单独是无效令牌,并bash引发错误。


在:

/usr/bin/time echo hello

externaltime没有调用 shell 内置命令echo,而是调用外部echo命令。

Astrace验证:

$ strace -fe execve /usr/bin/time echo 1
execve("/usr/bin/time", ["/usr/bin/time", "echo", "1"], [/* 64 vars */]) = 0
Process 25161 attached
....
[pid 25161] execve("/usr/bin/echo", ["echo", "1"], [/* 64 vars */]) = -1 ENOENT (No such file or directory)
[pid 25161] execve("/bin/echo", ["echo", "1"], [/* 64 vars */]) = 0
1
[pid 25161] +++ exited with 0 +++
....

在这里外部time查找您的PATH变量以查找可执行命令。这也解释了在使用函数的情况下,你得到了没有这样的文件或目录因为mytest你的PATH.

答案2

在2.中,您可以看到输出是错误的,特别是对于第二种情况:/usr/bin/time乘以管道的第一个命令(10秒)。然后/usr/bin/time sleep 10命令输出通过管道传输到sleep 5. shell 以这种方式分解你的命令行:对于它来说,/usr/bin/time就像任何其他命令一样。

3. shell 函数是 shell 进程的内部函数:/usr/bin/time使用参数调用mytest,它在路径中搜索该命令,但什么也没找到。/usr/bin/time由 shell 调用,但不是 shell 的一部分。

相关内容