GNU/Linux >> Tutoriales Linux >  >> Linux

En Bash, ¿puedo abrir sockets de forma asíncrona y usarlos más tarde?

¡No tenía idea de que Bash admitiera tantas funciones avanzadas! Empecé a trabajar en un programa de red simple para probar y usar algunas de estas cosas que encontré. Mi programa particular es un cliente redis básico escrito completamente en Bash. Actualmente, puedo hacer algo como lo siguiente:

redis_command -c "ping" redis{001..100}:{6379..6400}

Enviará el comando "ping" a todas las instancias (alrededor de 2100) y devolverá los resultados. Actualmente estoy enviando el comando "ping" en serie, pero pensé que podría acelerar mi programa haciendo toda la creación del socket inicial en paralelo. Probé mi programa con/sin la optimización y me di cuenta de que mi optimización en realidad ralentizaba las cosas. Así es como se ve la optimización:

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

Normalmente, la función get_socket() por sí sola funciona muy bien. Si alguna vez necesito enviar un comando a un servidor en particular, llamo a get_socket() con anticipación y paso el FD a otra función que realmente envía el comando y analiza la respuesta. En el escenario previo a la conexión, llamo a get_socket en segundo plano a través de &. Dado que get_socket()&se ejecuta en un proceso separado, el FD creado no está disponible/accesible en el proceso de llamada, por lo que mi optimización es inútil.

¿Hay alguna forma de enviar sockets en bash, o alguna otra forma en la que pueda paralelizar mis conexiones sin usar un proceso separado?

Respuesta aceptada:

No con /dev/tcp/x/y directamente, pero podría usar canalizaciones para comunicarse con procesos que se inician en segundo plano para conectar los sockets TCP y transferir datos.

Algo como

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]}

Como terminas ejecutando dos cat comandos de todos modos, también podría prescindir de /dev/tcp (que no siempre está habilitado) y use, por ejemplo, socat:

coproc hostA { socat - tcp:localhost:80; }

O bien, puede eliminar la dependencia de bash mediante el uso de canalizaciones con nombre:

mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &

Linux
  1. Cómo guardar comandos de Linux y usarlos bajo demanda

  2. Linux:almacenado en archivos /dev/pts y ¿podemos abrirlos?

  3. ¿Por qué se debe evitar eval en Bash y qué debo usar en su lugar?

  4. Intentando usar bash en Windows y no tengo un mensaje de distribuciones instaladas

  5. ¿Cómo puedo usar comodines de estilo ms-dos con ls y mv?

Comprender las rutas de los archivos y cómo usarlas en Linux

Cómo crear roles de Ansible y usarlos en Playbook

Cómo usar bash if -z y if -n para probar cadenas en Linux

¿Puedo usar Calibre para ordenar y escuchar audiolibros?

Esquemas de color en Vim:cómo cambiarlos y usarlos

Bash Scripting Part6 - Crear y usar funciones de Bash