2011-07-15 16 views
5

Semplice script qui:BASH: Migliore architettura per leggere da due ingressi flussi

a) costantemente leggere da un socket e memorizzare i valori in un array associativo
b) segue costantemente valori da stdin e rispondere t/f se esistono già nell'array associativo

a & b sono eventi casuali, non associati in alcun modo.

Il trucco è l'accesso alla matrice da entrambi i sottoprocessi (dal mettere un processo in background genera come un sottoprocesso)

sto pensando attraverso la strategia migliore, e si verificano un paio di idee, ma mi chiedo se qualcuno ha niente di meglio in mente:

1) reindirizzare l'input da presa a stdin come sottoprocesso e trattare entrambi gli ingressi in un ciclo while (dimensioni dei dati sono piccole, < 30 caratteri, quindi credo rimarranno atomico ?).
2) leggere il socket, quindi STDIN con piccoli valori di timeout (0.1?) Su read in modo da simulare l'I/O non bloccante.
3) UPDATE: scrivere i dati del socket in un file (in realtà l'altro processo lo scrive direttamente in un file), quindi ogni volta che arriva una richiesta per verificare se il valore esiste, elaborare le voci nel file, aggiungendoli all'array (usa il blocco dei file).

+0

Sembra che tu abbia l'idea giusta. C'è una ragione per farlo in bash rispetto ad un'altra lingua? – Slartibartfast

+0

Buona domanda. No, nessuna buona ragione per usare bash su un'altra lingua. Bash è semplice e piccolo, questa è l'unica ragione (e ho altri 5 altri script di bash che eseguono simili attività di autenticazione/registrazione/gestione degli utenti, quindi è bello mantenere una piattaforma uniforme) –

risposta

4

Bash non è lo strumento giusto per questo. Questo problema viene in genere risolto utilizzando le chiamate di sistema select(2) o poll(2), che consentono di attendere contemporaneamente più descrittori di file senza girare. Bash non ha un'interfaccia per nessuno di questi.

Mi consiglia di utilizzare un linguaggio di scripting come Python o Perl (qualunque cosa sei a tuo agio con, in realtà) che fornisce un'interfaccia con select o poll (ad esempio il modulo di Python select).

+0

Grazie per avermi fatto capire.Hai ragione. Dopo aver esaminato di più questo, ed essendo un ragazzo java, ho intenzione di riprendere groovy e prendere lo sforzo di fare questo compito in Groovy. È sulla mia lista dei desideri da imparare per un po '. –

2

Non so se questo è completamente pratico e abbastanza atomico nel contesto descritto, ma utilizzando un modello client/server e named pipe è possibile creare un ciclo while in grado di distinguere tra linee provenienti da un fifo o stdin .

Il server legge costantemente le linee da una presa (/tmp/to) e linee da stdin (che viene reindirizzato al server tramite /tmp/to).

Tuttavia, le righe da stdin vengono contrassegnate dal byte del (\177) come il primo byte della linea.

Quindi il ciclo while (in background) utilizza questo primo byte di linea per distinguere le linee di origine diversa.

# terminal window 1 

# server 
(
rm -f /tmp/to /tmp/from 
mkfifo /tmp/to /tmp/from 
while true; do 
    while IFS="" read -r -d $'\n' line; do 
    printf '%s\n' "${line}" 
    done </tmp/to >/tmp/from & 
    bgpid=$! 
    exec 3>/tmp/to 
    exec 4</tmp/from 
    trap "kill -TERM $bgpid; exit" 0 1 2 3 13 15 
    wait "$bgpid" 
    echo "restarting..." 
done 
) & 
serverpid=$! 

# client 
(
exec 3>/tmp/to; 
exec 4</tmp/from; 
while IFS="" read -r -d $'\n' <&4 line; do 
    if [[ "${line:0:1}" == $'\177' ]]; then 
    printf 'line from stdin: %s\n' "${line:1}" 
    else  
    printf 'line from fifo: %s\n' "$line" 
    fi 
done & 
trap "kill -TERM $"'!; exit' 1 2 3 13 15 
while IFS="" read -r -d $'\n' line; do 
    # can we make it atomic? 
    # sleep 0.5 
    # dd if=/tmp/to iflag=nonblock of=/dev/null # flush fifo 
    printf '\177%s\n' "${line}" 
done >&3 
) 
#kill -TERM $serverpid 


# terminal window 2 
echo hello > /tmp/to 
Problemi correlati