Non avevo idea che Bash supportasse così tante funzionalità avanzate! Ho iniziato a lavorare su un semplice programma di rete per provare a utilizzare alcune di queste cose che ho trovato. Il mio programma particolare è un client redis di base scritto completamente in Bash. Attualmente, posso fare qualcosa di simile a quanto segue:
redis_command -c "ping" redis{001..100}:{6379..6400}
Invierà il comando "ping" a tutte le istanze (circa 2100) e restituirà i risultati. Attualmente sto inviando il comando "ping" in serie, ma ho pensato di poter velocizzare il mio programma eseguendo tutta la creazione iniziale del socket in parallelo. Ho testato il mio programma con/senza l'ottimizzazione e mi sono reso conto che la mia ottimizzazione in realtà ha rallentato le cose. Ecco come appare l'ottimizzazione:
declare -A SOCKETS
function get_socket {
# args: <hostname> <port>
# returns: the socket number, or failure return code
# verify args
if [[ -z "${1}" ]]; then
return 1
fi
if [[ -z "${2}" ]]; then
return 1
fi
local HOSTPORT="${1}:${2}"
if [[ -z ${SOCKETS[${HOSTPORT}]} ]]; then
exec {fd}<>/dev/tcp/${1}/${2}
SOCKETS[${HOSTPORT}]=${fd}
RES=${fd}
else
RES="${SOCKETS[${HOSTPORT}]}"
fi
}
if [[ ${PRECONNECT} -eq 1 ]]; then
echo -n "Pre-connecting to ${#HOSTS[@]} instances... " >&2
for HOST in ${HOSTS[@]}; do
get_socket "${HOST%%:*}" "${HOST##*:}" &
PIDS+=($!)
done
# make sure all of our async connections finished before starting
# TODO, check for errors
for PID in ${PIDS[@]}; do
wait ${PID}
done
echo "done" >&2
fi
Normalmente, la funzione get_socket() da sola funziona benissimo. Se ho bisogno di inviare un comando a un determinato server, chiamo get_socket() in anticipo e passo l'FD a un'altra funzione che effettivamente invia il comando e analizza la risposta. Nello scenario di preconnessione, chiamo get_socket in background tramite &. Poiché get_socket()&viene eseguito in un processo separato, l'FD creato non è disponibile/accessibile nel processo di chiamata, quindi la mia ottimizzazione è inutile.
C'è un modo per inviare socket in bash o un altro modo per parallelizzare le mie connessioni senza utilizzare un processo separato?
Risposta accettata:
Non con /dev/tcp/x/y
direttamente, ma potresti usare le pipe per comunicare con i processi avviati in background per connettere i socket TCP e trasferire i dati.
Qualcosa come
coproc hostA {
exec {fd}<> /dev/tcp/127.0.0.1/80
cat <&$fd & cat >&$fd
}
# same for hostB...
echo -e 'HEAD / HTTP/1.0rnr' >&${hostA[1]}
cat <&${hostA[0]}
Quando finisci per eseguire due cat
comunque, potresti anche fare a meno di /dev/tcp
(che non è sempre abilitato) e utilizzare ad esempio socat:
coproc hostA { socat - tcp:localhost:80; }
Oppure puoi rimuovere la dipendenza da bash usando named pipe:
mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &