Interromper a expansão da linha de comandos da shell

4

Aviso: NÃO tente os comandos listados nesta pergunta sem saber suas implicações.

Desculpe se esta é uma duplicata. Estou surpreso em saber que um comando tão simples como

echo $(yes)

congela o meu computador (na verdade, ele fica muito atrasado em relação ao computador, em vez de congelar, mas o atraso é ruim o suficiente para fazer alguém pensar que congelou). Digitar Ctrl C ou Ctrl Z logo depois de digitar este comando não parece me ajudar a recuperar desse comando digitado incorretamente .

Por outro lado

ls /*/../*/../*/../*/../*/

é uma vulnerabilidade bem conhecida que também deixa o computador com o melhor desempenho e trava o computador com o pior.

Note que estes comandos são bem diferentes das conhecidas garfos.

A minha pergunta é: Existe uma maneira de interromper tais comandos que constroem uma enorme quantidade de opções de linha de comando da shell imediatamente depois de começar a executá-las no shell?

Meu entendimento é que, como a expansão do shell é feita antes que o comando seja executado, a maneira usual de interromper um comando não funciona porque o comando nem está sendo executado quando o atraso acontece, mas também quero confirmar que meu entendimento é correto, e estou extremamente interessado em aprender qualquer maneira de cancelar a expansão do shell antes de usar muita memória.

Não estou procurando como o kernel funciona com pouca memória. Eu também não estou procurando por SysRq overkills que podem ser úteis quando o sistema já está muito lento. Nem estou procurando abordagens preventivas como impor um ulimit na memória. Eu estou procurando uma maneira que possa efetivamente cancelar um enorme processo de expansão de shell dentro do próprio shell antes que fique atrasado no sistema. Não sei se é possível. Se for impossível como comentado, por favor, deixe também uma resposta indicando que, de preferência com explicações.

Eu escolhi não incluir nenhuma informação específica do sistema na pergunta original porque quero uma resposta geral, mas, caso isso seja importante, aqui estão as informações sobre o meu sistema: Ubuntu 16.04.4 LTS with gnome-terminal and bash 4.3.48(1) , executando um sistema x86_64 . Nenhuma máquina virtual envolvida.

    
por Weijun Zhou 13.03.2018 / 04:23

1 resposta

1

A partir de GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu) e não estou usando uma VM:

echo $(yes) 

existe o shell e não congela o sistema, e:

ls /*/../*/../*/../*/../*/

retorna

bash: /bin/ls: Argument list too long

Mas, como regra, quando você lida com algo que pode obter todos os recursos de um sistema é melhor definir limites antes de executá-los, se você sabe que um processo pode ser um processador, você pode iniciá-lo com cpulimit ou execute renice .

Se você quiser limitar os processos que já foram iniciados, você terá que fazer um por um pelo PID, mas você pode ter um script em lote para fazer isso como o abaixo:

#!/bin/bash
LIMIT_PIDS=$(pgrep tesseract)   # PIDs in queue replace tesseract with your name
echo $LIMIT_PIDS
for i in $LIMIT_PIDS
do
    cpulimit -p $i -l 10 -z &   # to 10 percent processes
done

No meu caso pypdfocr lança o ganancioso tesseract .

Além disso, em alguns casos, sua CPU é muito boa. Basta usar um renice assim:

watch -n5 'pidof tesseract | xargs -L1 sudo renice +19'
    
por 06.08.2018 / 05:30