$! não funciona na linha de comando

0

Estou executando o abaixo diretamente no prompt da linha de comando do bash :

$ PIDS= ;while read name; do (cd $name; npm install) & echo started install; PIDS+=($!); done < <(\ls); for pid in ${PIDS[@]}; do wait $pid; done;

E eu entendo isso:

-bash: !: event not found

Eu assumo que o símbolo ! está sendo usado para fazer a substituição do histórico de comandos em vez de ver "$!" como uma variável primeiro.

Como obtenho o pid do último processo em segundo plano se estiver sendo executado diretamente na linha de comando do bash?

    
por Alexander Bird 15.08.2017 / 14:53

2 respostas

4

Eu não consegui reproduzir seu problema com bash 4.3 e 4.4, portanto, aqui está uma resposta genérica.

Seu problema é acionado pelo ! em PIDS+=($!) , ! sendo o início da substituição do histórico (que é ativado por padrão com um shell interativo).

Desabilite a substituição do histórico com set +H ou cite o ! (não desejável aqui por causa do $ precedente) ou adicione um espaço após ! . O manual do bash lê:

! Start a history substitution, except when followed by a blank, newline, carriage return, = or ( (when the extglob shell option is enabled using the shopt builtin)

Sua linha de comando se tornaria:

PIDS=()
while read name; do
    (cd "$name"; npm install) &
    echo started install
    PIDS+=( $! )
done < <(\ls)
wait "${PIDS[@]}"

Notas:

  • Você não está limitado a uma linha de código aqui
  • Eu adicionei aspas adequadas às variáveis
  • Você pode esperar vários PIDs de uma só vez; Eu consertei isso
por 15.08.2017 / 16:03
1

Do registro de alterações do bash :

This document details the changes between this version, bash-4.2-alpha, and the previous version, bash-4.1-release. (…)

3. New Features in Bash (…)

u. History expansion no longer expands the $! variable expansion.

Para lidar com versões mais antigas do bash, altere PIDS+=($!) para PIDS+=($! ) . O espaço extra garante que o bash nunca pense que esse ! inicia uma referência de histórico.

    
por 17.08.2017 / 02:11