Je ne savais pas que Bash supportait autant de fonctionnalités avancées ! J'ai commencé à travailler sur un programme réseau simple pour essayer d'utiliser certaines de ces choses que j'ai trouvées. Mon programme particulier est un client redis de base entièrement écrit en Bash. Actuellement, je peux faire quelque chose comme ceci :
redis_command -c "ping" redis{001..100}:{6379..6400}
Il enverra la commande "ping" à toutes les instances (environ 2100) et renverra les résultats. J'envoie actuellement la commande "ping" en série, mais je pensais pouvoir accélérer mon programme en effectuant toute la création initiale du socket en parallèle. J'ai testé mon programme avec/sans l'optimisation, et j'ai réalisé que mon optimisation ralentissait en fait les choses. Voici à quoi ressemble l'optimisation :
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
Normalement, la fonction get_socket() seule fonctionne très bien. Si jamais j'ai besoin d'envoyer une commande à un serveur particulier, j'appelle get_socket() à l'avance et je transmets le FD à une autre fonction qui envoie réellement la commande et analyse la réponse. Dans le scénario de pré-connexion, j'appelle get_socket en arrière-plan via &. Étant donné que get_socket()&s'exécute dans un processus séparé, le FD créé n'est pas disponible/accessible dans le processus d'appel, donc mon optimisation est inutile.
Existe-t-il un moyen d'envoyer des sockets dans bash ou une autre manière de paralléliser mes connexions sans utiliser de processus séparé ?
Réponse acceptée :
Pas avec /dev/tcp/x/y
directement, mais vous pouvez utiliser des canaux pour communiquer avec des processus démarrés en arrière-plan pour connecter les sockets TCP et transférer des données.
Quelque chose comme
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]}
Lorsque vous finissez par exécuter deux cat
de toute façon, autant se passer de /dev/tcp
(qui n'est pas toujours activé) et utilisez par exemple socat :
coproc hostA { socat - tcp:localhost:80; }
Ou, vous pouvez supprimer la dépendance à bash en utilisant des canaux nommés :
mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &