2012-06-18 6 views
10

Sto scrivendo uno script nella shell in cui un comando è in esecuzione e richiede 2 minuti. ogni volta. Inoltre, non c'è nulla che possiamo fare con questo. Ma se voglio eseguire questo comando 100 volte nello script, il tempo totale sarebbe 200min. e questo creerà un grosso problema. Nessuno vuole aspettare per 200 minuti. Quello che voglio è eseguire tutti i 100 comandi in modo parallelo in modo che l'uscita arrivi in ​​2 minuti o che possa essere un po 'più di tempo, ma non prendere 200 minuti.Elaborazione o threading parallelo nello script Shell

sarà apprezzato, se qualsiasi organismo può aiutarmi in questo modo in qualsiasi modo.

+0

[Che cosa hai provato] (http://mattgemmell.com/2008/12/08/what-have-you-tried/)? – ghoti

+0

Inoltre, quale shell stai usando? tcsh? zsh? pd-ksh? pesce? – Graham

risposta

10

... eseguire tutti i 100 comandi in parallelo in modo che la produzione verrà in 2min

Questo è possibile solo se si dispone di 200 processori sul vostro sistema.

Non esiste alcuna utilità/comando in shell per eseguire comandi in parallelo. Che cosa si può fare è eseguire il vostro comando in background:

for ((i=0;i<200;i++)) 
do 
    MyCommand & 
done 

Con & (sfondo), ogni esecuzione è prevista al più presto possibile. Ma questo non garantisce che il tuo codice verrà eseguito in meno di 200 minuti. Dipende da quanti processori ci sono sul tuo sistema.

Se si dispone di un solo processore e ogni esecuzione del comando (che richiede 2 minuti) sta eseguendo un calcolo per 2 minuti, quindi il processore sta facendo del lavoro, il che significa che non ci sono cicli sprecati. In questo caso, eseguire i comandi in parallelo non è di aiuto perché, c'è solo un processore che non è gratuito. Quindi, i processi aspetteranno solo il loro turno per essere eseguiti.

Se si dispone di più processori, il metodo precedente (per ciclo) potrebbe aiutare a ridurre il tempo di esecuzione totale.

+1

Se lo script è legato all'IO, non sono necessari 200 processori. In effetti, è possibile ottenere un sostanziale aumento di velocità con un solo processore. –

+0

@WilliamPursell Proprio così. Ma in realtà dipende da ciò che il comando sta facendo per quel * 2 minuti *. –

4

Come ha detto @KingsIndian, è possibile eseguire attività in background, che consentono di eseguirle in parallelo. Al di là di questo, si può anche tenere traccia di loro per ID del processo:

#!/bin/bash 

# Function to be backgrounded 
track() { 
    sleep $1 
    printf "\nFinished: %d\n" "$1" 
} 

start=$(date '+%s') 

rand3="$(jot -s\ -r 3 5 10)" 

# If you don't have `jot` (*BSD/OSX), substitute your own numbers here. 
#rand3="5 8 10" 

echo "Random numbers: $rand3" 

# Make an associative array in which you'll record pids. 
declare -A pids 

# Background an instance of the track() function for each number, record the pid. 
for n in $rand3; do 
    track $n & 
    pid=$! 
    echo "Backgrounded: $n (pid=$pid)" 
    pids[$pid]=$n 
done 

# Watch your stable of backgrounded processes. 
# If a pid goes away, remove it from the array. 
while [ -n "${pids[*]}" ]; do 
    sleep 1 
    for pid in "${!pids[@]}"; do 
    if ! ps "$pid" >/dev/null; then 
     unset pids[$pid] 
     echo "unset: $pid" 
    fi 
    done 
    if [ -z "${!pids[*]}" ]; then 
    break 
    fi 
    printf "\rStill waiting for: %s ... " "${pids[*]}" 
done 

printf "\r%-25s \n" "Done." 
printf "Total runtime: %d seconds\n" "$((`date '+%s'` - $start))" 

Si dovrebbe anche dare un'occhiata alla documentazione di Bash su coprocesses.

13

GNU Parallel è ciò che si desidera, a meno che non si voglia reinventare la ruota. Qui ci sono alcuni più dettagliata examples, ma il corto di esso:

ls | parallel gzip # gzip all files in a directory 
Problemi correlati