Diferenças entre palavra reservada e comando 'time' no shell embutido, função, pipeline e lista de comandos?

0

No Manual de Referência do Bash,

The use of time as a reserved word permits the timing of shell builtins, shell functions, and pipelines. An external time command cannot time these easily.

  1. Você poderia explicar por que a citação diz isso?

    É por causa da diferença entre uma palavra reservada e uma comando, não apenas limitado ao caso de time ? Por exemplo, como é que o shell bash parse ou interprete-os diferentemente?

    Ou isso é limitado apenas ao caso de time ?

  2. Nos exemplos a seguir,

    por que o time externo funciona em um shell embutido e um pipeline, enquanto a citação diz que "não pode tempo estes facilmente"?

    Externa time em um shell embutido :

    $ /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
    

    Externa time em um 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
    
  3. No exemplo a seguir, por que o time externo em um shell função falhar? O que significa sua saída de erro?

    $ 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. Parece que a cotação não se aplica apenas a sincronizações de shell, funções de shell e pipelines, mas também para cronometrar um grupo de comandos :

    $ 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 '}'
    

    Por que o shell diz "bash: erro de sintaxe próximo a token inesperado } "no caso do comando /usr/bin/time ?

por Tim 15.03.2016 / 00:04

2 respostas

2

Em bash , time é uma palavra reservada , então o shell pode analisá-lo do jeito que quiser e aplicar regras para ele.

Aqui está o código que mostra como a linha bash parse começa com time palavra reservada :

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 */
}

Você vê, time pode ser seguido pela maioria dos outros bash palavras reservadas.

No caso de comando externo, a regra normal foi aplicada, { foi considerado entrada de /usr/bin/time . } sozinho é um token inválido e bash aumenta o erro.

Em:

/usr/bin/time echo hello

external time não chamou o shell embutido echo , mas o comando echo externo.

Um strace verifica que:

$ 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 +++
....

Aqui, time externo procura sua variável PATH para encontrar o comando executável. Isso também explica no caso de usar uma função, você tem Nenhum arquivo ou diretório porque não existe um comando chamado mytest em seu PATH .

    
por 15.03.2016 / 03:46
2

Em 2. você pode ver que a saída está errada, especialmente para o segundo caso: /usr/bin/time vezes o primeiro comando do pipeline (10 s). Em seguida, a saída do comando /usr/bin/time sleep 10 é canalizada para sleep 5 . É o shell que divide sua linha de comando desta forma: para isso, /usr/bin/time é como qualquer outro comando.

Em 3. as funções do shell são internas ao processo do shell: /usr/bin/time é invocado com o argumento mytest , procura este comando no caminho e não encontra nada. /usr/bin/time é invocado pelo shell, mas não faz parte dele.

    
por 15.03.2016 / 10:41