Como você interrompe uma expansão de shell bash?

3

Eu conheço alguns métodos para parar o processo. Quando eu digito:

echo {1..999999} > filename.txt 

Não consigo parar de funcionar. Eu posso parar outros processos com Ctrl + C | Ctrl + D | Ctrl + \ e etc. Mas nenhum deles parece estar trabalhando com esse comando.

Alguns caras me disseram para simplesmente fechar este terminal. Além disso, abra um novo terminal para matar todos os processos do terminal, mas não quero fazer isso dessa maneira. No servidor eu não terei a chance de abrir um novo terminal, eu acho.

Posso abrir uma nova sessão de terminal no modo de texto?

    
por rzaaeeff 14.03.2015 / 21:36

2 respostas

4

A razão pela qual não é possível interromper isso com Ctrl - c etc ... é que o shell não está executando nenhum comando nesse ponto. Ele está ocupado expandindo {1..999999} para calcular quais serão os argumentos da linha de comando quando chegar ao ponto de executar o comando.

Enquanto comandos externos respondem a sinais de terminação como SIGINT (que é emitido por padrão quando você pressiona Ctrl - c ), os próprios shells os ignoram. Se não, então, quando você pressionou Ctrl - c , então, além de matar qualquer comando que estivesse em execução, você também mataria o próprio shell! (Isso não é bem verdade por causa do tty job control e dos grupos de processos de primeiro plano e segundo plano, mas perto o suficiente para o propósito dessa explicação.)

Se você precisar interrompê-lo, infelizmente não há nada que você possa fazer além de matar o próprio shell. Matar o próprio shell fará com que sua sessão termine. Nesse sentido, é em grande parte equivalente a fechar a janela do terminal ou encerrar a conexão SSH.

    
por 15.03.2015 / 03:48
3

Se você quiser uma alternativa que possa ser interrompida com ctrl + c , o seguinte funciona no bash:

i=1; while [ $i -le 999999 ]; do echo $((i++)) >> filename.txt; done

Certifique-se de usar o símbolo de redirecionamento 1 >> para anexar ao arquivo em vez de sobrescrevê-lo.

Além disso, pareço ser capaz de pará-lo com ctrl + c ao executar o comando dentro de um subshell usando parênteses ( echo {1..999999} > numero.txt ) Observe que o arquivo de saída nunca é criado pelas razões que Celada explicou.

Veja os Subshells - Guia avançado de script de script

Para suportar ainda mais a resposta da Celada, abaixo está a ordem em que o esquema fork-and-exec do shell bash opera. Você pode ver que o comando não é executado até que as expansões de shell sejam executadas; nenhum fork ainda é criado. No comando echo {1..999999} > filename.txt , o shell pai é o processo no qual a expansão do shell está sendo executada. ctrl + c , obviamente, não mata o shell pai.

De Guia do Bash para iniciantes  1.4.1.1. Sintaxe da Shell

If input is not commented, the shell reads it and divides it into words and operators, employing quoting rules to define the meaning of each character of input. Then these words and operators are translated into commands and other constructs, which return an exit status available for inspection or processing. The above fork-and-exec scheme is only applied after the shell has analyzed input in the following way:

  • The shell reads its input from a file, from a string or from the user's terminal.

  • Input is broken up into words and operators, obeying the quoting rules, see Chapter 3. These tokens are separated by metacharacters. Alias expansion is performed.

  • The shell parses (analyzes and substitutes) the tokens into simple and compound commands.

  • Bash performs various shell expansions, breaking the expanded tokens into lists of filenames and commands and arguments.

  • Redirection is performed if necessary, redirection operators and their operands are removed from the argument list.

  • Commands are executed.

  • Optionally the shell waits for the command to complete and collects its exit status.

De Guia do Bash para iniciantes 3.4.1. Geral

After the command has been split into tokens (see Section 1.4.1.1), these tokens or words are expanded or resolved. There are eight kinds of expansion performed, which we will discuss in the next sections, in the order that they are expanded.

A expansão de chave é a primeira entre a ordem de expansões realizadas.

Parando uma expansão de shell

Você pode realmente parar uma expansão do shell enviando kill -SIGSTOP <pid> para o pid do shell. echo $$ dará o pid do shell atual ou você pode tentar pgrep -l bash e tentar determinar qual shell está executando a expansão.

A expansão pode ser retomada de onde parou com kill -SIGCONT <pid> .

Eu não sei de nenhuma maneira de matar a expansão além de matar o shell pai ou deixá-lo terminar. Para mim, isso é um bom argumento para executar expansões em um subshell.

    
por 15.03.2015 / 04:28