Ich hatte keine Ahnung, dass Bash so viele erweiterte Funktionen unterstützt! Ich fing an, an einem einfachen Netzwerkprogramm zu arbeiten, um zu versuchen, einige dieser Dinge, die ich fand, zu verwenden. Mein spezielles Programm ist ein grundlegender Redis-Client, der vollständig in Bash geschrieben ist. Derzeit kann ich so etwas tun:
redis_command -c "ping" redis{001..100}:{6379..6400}
Es sendet den „Ping“-Befehl an alle Instanzen (etwa 2100) und gibt die Ergebnisse zurück. Ich sende derzeit den Befehl „ping“ seriell, aber ich dachte, ich könnte mein Programm beschleunigen, indem ich die gesamte anfängliche Socket-Erstellung parallel durchführe. Ich habe mein Programm mit/ohne Optimierung getestet und festgestellt, dass meine Optimierung die Dinge tatsächlich verlangsamt hat. So sieht die Optimierung aus:
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
Normalerweise funktioniert die Funktion get_socket() alleine hervorragend. Wenn ich jemals einen Befehl an einen bestimmten Server senden muss, rufe ich get_socket() im Voraus auf und übergebe das FD an eine andere Funktion, die den Befehl tatsächlich sendet und die Antwort analysiert. Im Pre-Connect-Szenario rufe ich get_socket im Hintergrund über &auf. Da get_socket()&in einem separaten Prozess ausgeführt wird, ist der erstellte FD im aufrufenden Prozess nicht verfügbar/zugreifbar, daher ist meine Optimierung nutzlos.
Gibt es eine Möglichkeit, Sockets in Bash zu senden, oder eine andere Möglichkeit, meine Verbindungen zu parallelisieren, ohne einen separaten Prozess zu verwenden?
Akzeptierte Antwort:
Nicht mit /dev/tcp/x/y
direkt, aber Sie könnten Pipes verwenden, um mit Prozessen zu kommunizieren, die im Hintergrund gestartet werden, um die TCP-Sockets zu verbinden und Daten zu übertragen.
So etwas wie
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]}
Am Ende laufen zwei cat
trotzdem auf /dev/tcp
verzichten (was nicht immer aktiviert ist) und verwenden Sie zum Beispiel socat:
coproc hostA { socat - tcp:localhost:80; }
Oder Sie könnten die Abhängigkeit von Bash entfernen, indem Sie Named Pipes verwenden:
mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &