In the Bash Reference Manual,
The use of
time
as a reserved word permits the timing of shell builtins, shell functions, and pipelines. An externaltime
command cannot time these easily.
Could you explain why the quote says that?
Is this because of the difference between a reserved word and a command, not just limited to the case of
time
? For example, how does the bash shell parse or interpret them differently?Or is this only limited to the case of
time
?In the following examples,
why does the external
time
work on a shell builtin, and a pipeline, while the quote say it "cannot time these easily"?External
time
on a shell builtin:$ /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
External
time
on a pipeline:$ /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
In the following example, why does the external
time
on a shell function fail? What does its error output mean?$ 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
It seems that the quote does not just apply to timing shell builtins, shell functions, and pipelines, but also to timing a group of commands:
$ 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 `}'
Why does the shell say "bash: syntax error near unexpected token
}
" in the case for command/usr/bin/time
?
-
3Possible duplicate of Differences between keyword, reserved word, and builtin?user79743– user797432016年03月15日 07:20:10 +00:00Commented Mar 15, 2016 at 7:20
-
1Not a duplicate.Tim– Tim2016年03月15日 08:02:06 +00:00Commented Mar 15, 2016 at 8:02
2 Answers 2
In bash
, time
is a reserved word, so the shell can parse it the own way and apply rules for it.
Here is the code show how bash
parse line start with time
reserved word:
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 */
}
You see, time
can be followed by most others bash
reserved words.
In case of external command, the normal rule was applied, {
was considered input of /usr/bin/time
. }
alone is invalid token, and bash
raise the error.
In:
/usr/bin/time echo hello
external time
did not call the shell builtin echo
but the external echo
command.
A strace
verifies that:
$ 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 +++
....
Here external time
lookup your PATH
variable to find the command executable. That also explain in case of using a function, you got No such file or directory becasue there's no command named mytest
in your PATH
.
-
"time is a reverse word". really?user79743– user797432016年03月15日 07:15:14 +00:00Commented Mar 15, 2016 at 7:15
-
@BinaryZebra: And also, feel free to make the editing next time. Thanks.cuonglm– cuonglm2016年03月15日 07:55:03 +00:00Commented Mar 15, 2016 at 7:55
-
Thanks. Cuonglm. I just added some details to my questions.Tim– Tim2016年03月15日 08:09:20 +00:00Commented Mar 15, 2016 at 8:09
-
thanks. "In case of external command, the normal rule was applied", what is the "normal rule"? Why is
{
considered input of/usr/bin/time
, and}
alone invalid token,?Tim– Tim2016年03月16日 00:50:17 +00:00Commented Mar 16, 2016 at 0:50 -
I tried to find it in POSIX specifications, but can't find any.Tim– Tim2016年03月16日 01:46:47 +00:00Commented Mar 16, 2016 at 1:46
In 2. you can see the output is wrong, especially for the second case: /usr/bin/time
times the first command of the pipeline (10 s). Then the /usr/bin/time sleep 10
command output is piped into sleep 5
. It is the shell that breaks down your command-line this way: for it, /usr/bin/time
is just like any other command.
In 3. shell functions are internal to the shell process: /usr/bin/time
is invoked with argument mytest
, it searches this command in the path, and finds nothing. /usr/bin/time
is invoked by the shell but is not part of it.