Bashがこれほど多くの高度な機能をサポートしていることを私は知りませんでした!私は、見つけたこれらのもののいくつかを試して使用するために、単純なネットワークプログラムに取り組み始めました。私の特定のプログラムは、完全にBashで記述された基本的なredisクライアントです。現在、私は次のようなことをすることができます:
redis_command -c "ping" redis{001..100}:{6379..6400}
すべてのインスタンス(約2100)に「ping」コマンドを送信し、結果を返します。現在、「ping」コマンドをシリアルに送信していますが、最初のソケット作成をすべて並行して実行することで、プログラムを高速化できると思いました。最適化の有無にかかわらずプログラムをテストしたところ、最適化によって実際に速度が低下することがわかりました。最適化の外観は次のとおりです。
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
通常、get_socket()関数自体はうまく機能します。特定のサーバーにコマンドを送信する必要がある場合は、事前にget_socket()を呼び出し、実際にコマンドを送信して応答を解析する別の関数にFDを渡します。接続前のシナリオでは、バックグラウンドで&を介してget_socketを呼び出しています。 get_socket()&は別のプロセスで実行されるため、作成されたFDは呼び出しプロセスで使用/アクセスできないため、最適化は役に立ちません。
ソケットをbashで送信する方法、または別のプロセスを使用せずに接続を並列化できる他の方法はありますか?
承認された回答:
/dev/tcp/x/y
ではありません 直接ですが、パイプを使用して、バックグラウンドで開始されたプロセスと通信し、TCPソケットを接続してデータを転送することもできます。
のようなもの
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]}
最終的に2つのcat
を実行することになります とにかくコマンド、あなたは/dev/tcp
なしでやったほうがいいかもしれません (常に有効になっているわけではありません)そして、例えばsocatを使用します:
coproc hostA { socat - tcp:localhost:80; }
または、名前付きパイプを使用してbashへの依存を削除することもできます:
mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &