Colocando subshell no background vs colocando o comando no background

4

Eu tenho dois scripts bash que tentam verificar os hosts que estão ativos:

Script 1:

#!/bin/bash 
for ip in {1..254}; do
    ping -c 1 192.168.1.$ip | grep "bytes from" | cut -d" " -f 4 | cut -d ":" -f 1 &
done

Script 2:

#!/bin/bash 
for ip in {1..254}; do
    host=192.168.1.$ip
    (ping -c 1 $host > /dev/null 
    if [ "$?" = 0 ]
    then 
        echo $host
    fi) &
done

Como estou verificando um intervalo grande, gostaria de processar cada comando ping em paralelo. No entanto, meu segundo script parece não tentar tentativas de bifurcação repetidas devido a limites de recursos. Isso faz com que o segundo script tenha resultados inconsistentes, enquanto meu primeiro script fornece resultados constantes, apesar de ambos não conseguirem bifurcar às vezes. Alguém pode explicar isso para mim? Também existe alguma maneira de tentar novamente os garfos falhados?

    
por MykelXIII 01.06.2016 / 19:59

2 respostas

3

Já existe uma resposta que fornece um snippet de código aprimorado para a tarefa relacionada às perguntas do pôster original, embora ainda não tenha respondido mais diretamente à pergunta.

A questão é sobre diferenças de

  • A) Plano de fundo de um "comando" diretamente, vs
  • B) Colocar um subshell no segundo plano (ou seja, com uma tarefa semelhante)

Permite verificar essas diferenças executando 2 testes

# A) Backgrounding a command directly
sleep 2 & ps

saídas

[1] 4228
  PID TTY          TIME CMD
 4216 pts/8    00:00:00 sh
 4228 pts/8    00:00:00 sleep

enquanto

# A) backgrounding a subhell (with similar tas)
( sleep 2; ) & ps

apresenta algo como:

[1] 3252
  PID TTY          TIME CMD
 3216 pts/8    00:00:00 sh
 3252 pts/8    00:00:00 sh
 3253 pts/8    00:00:00 ps
 3254 pts/8    00:00:00 sleep

** Resultados do teste: **

Neste teste (que executa apenas um sleep 2 ) a versão do subshell realmente difere, pois usaria 2 processos filhos (isto é, dois fork() / exec operations e PID) e, portanto, mais do que o background direto de o comando.

No script 1 da questão, no entanto, o comando não era um único sleep 2s , mas sim um pipe de 4 comandos, que, se testarmos em um caso adicional

  • C) Plano de fundo de um pipe com 4 comandos

    C) Plano de fundo de um pipe com 4 comandos

    dormir 2s | dormir 2s | dormir 2s | dormir 2s & ps

produz isso

[2] 3265
  PID TTY          TIME CMD
 3216 pts/8    00:00:00 bash
 3262 pts/8    00:00:00 sleep
 3263 pts/8    00:00:00 sleep
 3264 pts/8    00:00:00 sleep
 3265 pts/8    00:00:00 sleep
 3266 pts/8    00:00:00 ps

e mostra que, de fato, o script 1 seria um aumento muito maior em termos de PIDs e fork() s.

Como uma estimativa aproximada, o script teria usado cerca de 254 * 4 ~ = 1000 PIDs e, portanto, ainda mais do que o script 2 com 254 * 2 ~ = 500 PIDs. Qualquer problema que ocorra por causa de PIDs depleção resouce parece ainda improvável, pois na maioria das caixas de linux

$ cat /proc/sys/kernel/pid_max
32768

dá 32x vezes os PIDs necessários mesmo para o caso script 1 e os processos / programas envolvidos (por exemplo, sed , ping , etc) também parecem não causar os resultados inconstantes.

Como mencionado pelo usuário @derobert, o problema real por trás da scripts falha foi que a falta do comando wait , o que significa que após o background dos comandos no loop, o final do script e, portanto, o shell causou todos os processos filhos a serem finalizados.

    
por 11.08.2016 / 17:20
2

Isso fará o que você está esperando:

#!/bin/bash
function_ping(){
    if ping -c 1 -w 5 $1 &>/dev/null; then 
        echo "UP: $1"
    else
        echo "DOWN $1" 
    fi
}
for ip in {1..254}; do
        function_ping 192.168.1.$ip &  
done
wait 

Salve como paralelismo e execute-o.

Isso ajuda você? Ele pode ser convertido em uma grande função, que pode ser usada em um loop rápido também, então você pode usar sua imaginação programando com ela.

Nota: você deve usar o bash.

    
por 01.06.2016 / 21:54