GNU/Linux >> Linux Esercitazione >  >> Linux

In Bash, posso aprire i socket in modo asincrono e usarli in seguito?

Non avevo idea che Bash supportasse così tante funzionalità avanzate! Ho iniziato a lavorare su un semplice programma di rete per provare a utilizzare alcune di queste cose che ho trovato. Il mio programma particolare è un client redis di base scritto completamente in Bash. Attualmente, posso fare qualcosa di simile a quanto segue:

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

Invierà il comando "ping" a tutte le istanze (circa 2100) e restituirà i risultati. Attualmente sto inviando il comando "ping" in serie, ma ho pensato di poter velocizzare il mio programma eseguendo tutta la creazione iniziale del socket in parallelo. Ho testato il mio programma con/senza l'ottimizzazione e mi sono reso conto che la mia ottimizzazione in realtà ha rallentato le cose. Ecco come appare l'ottimizzazione:

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 funzione get_socket() da sola funziona benissimo. Se ho bisogno di inviare un comando a un determinato server, chiamo get_socket() in anticipo e passo l'FD a un'altra funzione che effettivamente invia il comando e analizza la risposta. Nello scenario di preconnessione, chiamo get_socket in background tramite &. Poiché get_socket()&viene eseguito in un processo separato, l'FD creato non è disponibile/accessibile nel processo di chiamata, quindi la mia ottimizzazione è inutile.

C'è un modo per inviare socket in bash o un altro modo per parallelizzare le mie connessioni senza utilizzare un processo separato?

Risposta accettata:

Non con /dev/tcp/x/y direttamente, ma potresti usare le pipe per comunicare con i processi avviati in background per connettere i socket TCP e trasferire i dati.

Qualcosa come

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

Quando finisci per eseguire due cat comunque, potresti anche fare a meno di /dev/tcp (che non è sempre abilitato) e utilizzare ad esempio socat:

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

Oppure puoi rimuovere la dipendenza da bash usando named pipe:

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

Linux
  1. Come utilizzare il comando di spegnimento di Linux, riavvii pianificati e immediati

  2. Linux:archiviato nei file /dev/pts e possiamo aprirli?

  3. Usa grep per trovare il contenuto nei file e spostarli se corrispondono

  4. Come posso usare i comandi con alias con xargs?

  5. Cercando di usare bash su Windows e non ho ricevuto messaggi di distribuzioni installate

Comprendere i percorsi dei file e come usarli in Linux

Come creare ruoli Ansible e usarli in Playbook

Come usare bash if -z e if -n per testare le stringhe in Linux

Posso usare Calibre per ordinare e ascoltare audiolibri?

Schemi di colori in Vim:come cambiarli e usarli

Bash Scripting Part6 – Crea e usa le funzioni Bash