Bashがそれほど多くの高度な機能をサポートするとは予想しませんでした!私は私が見つけたものを試してみるために単純なWebプログラムを開発し始めました。私の特定のプログラムは、完全に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でソケット経由で送信する方法はありますか?それとも別のプロセスを使用せずに接続を並列化する別の方法がありますか?
答え1
直接使用することはできませんが、/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.0\r\n\r' >&${hostA[1]}
cat <&${hostA[0]}
とにかく、両方のコマンドを実行したら使用しないでください(常にアクティブではない)、socatを使用することをお勧めしますcat
。/dev/tcp
coproc hostA { socat - tcp:localhost:80; }
あるいは、名前付きパイプを使用してbashへの依存関係を削除することもできます。
mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &