Saya tidak tahu bahwa Bash mendukung begitu banyak fitur canggih! Saya mulai mengerjakan program jaringan sederhana untuk mencoba dan menggunakan beberapa hal yang saya temukan ini. Program khusus saya adalah klien redis dasar yang ditulis sepenuhnya dalam Bash. Saat ini, saya dapat melakukan sesuatu seperti berikut:
redis_command -c "ping" redis{001..100}:{6379..6400}
Ini akan mengirim perintah "ping" ke semua instance (sekitar 2100) dan mengembalikan hasilnya. Saat ini saya mengirim perintah "ping" secara serial, tetapi saya pikir saya dapat mempercepat program saya dengan melakukan semua pembuatan soket awal secara paralel. Saya menguji program saya dengan/tanpa pengoptimalan, dan menyadari bahwa pengoptimalan saya sebenarnya memperlambat segalanya. Begini tampilan pengoptimalannya:
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
Biasanya, fungsi get_socket() sendiri berfungsi dengan baik. Jika saya perlu mengirim perintah ke server tertentu, saya memanggil get_socket() sebelumnya, dan meneruskan FD ke fungsi lain yang benar-benar mengirim perintah dan mem-parsing respons. Dalam skenario pra-koneksi, saya memanggil get_socket di latar belakang melalui &. Karena get_socket()&berjalan dalam proses terpisah, FD yang dibuat tidak tersedia/dapat diakses dalam proses panggilan, jadi pengoptimalan saya tidak berguna.
Apakah ada cara untuk mengirim soket di bash, atau cara lain agar saya dapat memparalelkan koneksi saya tanpa menggunakan proses terpisah?
Jawaban yang Diterima:
Tidak dengan /dev/tcp/x/y
secara langsung, tetapi Anda dapat menggunakan pipa untuk berkomunikasi dengan proses yang dimulai di latar belakang untuk menghubungkan soket TCP dan mentransfer data.
Sesuatu seperti
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]}
Saat Anda akhirnya menjalankan dua cat
tetap, Anda mungkin juga melakukannya tanpa /dev/tcp
(yang tidak selalu diaktifkan) dan gunakan misalnya socat:
coproc hostA { socat - tcp:localhost:80; }
Atau, Anda dapat menghapus ketergantungan pada bash dengan menggunakan pipa bernama:
mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &