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에서 소켓을 통해 보낼 수 있는 방법이 있나요? 아니면 별도의 프로세스를 사용하지 않고 연결을 병렬화할 수 있는 다른 방법이 있나요?
답변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 &