GNU/Linux >> Znalost Linux >  >> Linux

Mohu v Bash asynchronně otevřít zásuvky a použít je později?

Netušil jsem, že Bash podporuje tolik pokročilých funkcí! Začal jsem pracovat na jednoduchém síťovém programu, abych vyzkoušel a použil některé z těchto věcí, které jsem našel. Můj konkrétní program je základní klient redis napsaný kompletně v Bash. V současné době mohu udělat něco jako následující:

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

Odešle příkaz „ping“ všem instancím (asi 2100) a vrátí výsledky. V současné době odesílám příkaz „ping“ sériově, ale myslel jsem, že bych mohl urychlit svůj program tím, že bych všechny počáteční vytváření soketu provedl paralelně. Testoval jsem svůj program s/bez optimalizace a uvědomil jsem si, že moje optimalizace ve skutečnosti věci zpomalila. Optimalizace vypadá takto:

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

Normálně funguje funkce get_socket() sama o sobě skvěle. Pokud někdy potřebuji odeslat příkaz na konkrétní server, zavolám předem get_socket() a předám FD jiné funkci, která příkaz skutečně odešle a analyzuje odpověď. Ve scénáři předběžného připojení volám get_socket na pozadí přes &. Vzhledem k tomu, že get_socket()&běží v samostatném procesu, vytvořený FD není dostupný/přístupný v procesu volání, takže moje optimalizace je k ničemu.

Existuje nějaký způsob, jak odeslat sokety v bash, nebo nějaký jiný způsob, jak mohu paralelizovat svá připojení bez použití samostatného procesu?

Přijatá odpověď:

Ne s /dev/tcp/x/y přímo, ale můžete použít roury ke komunikaci s procesy, které jsou spuštěny na pozadí pro připojení TCP soketů a přenos dat.

Něco jako

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

Jak skončíte spuštěním dvou cat příkazů se stejně můžete obejít bez /dev/tcp (což není vždy povoleno) a použijte například socat:

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

Nebo můžete závislost na bash odstranit pomocí pojmenovaných kanálů:

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

Linux
  1. Jak používat Linux Shutdown Command, restartování plánované a okamžité

  2. Linux – uložené v souborech /dev/pts a můžeme je otevřít?

  3. Pomocí grep vyhledejte obsah v souborech a přesuňte je, pokud se shodují

  1. Proč by se měl v Bash vyhnout eval a co bych měl místo toho použít?

  2. Při pokusu o použití bash v systému Windows se neobjevila žádná zpráva o instalaci distribuce

  3. Kdy použít Bash a kdy Perl/Python/Ruby?

  1. Jak mohu používat aliasované příkazy s xargs?

  2. jak mohu vyhledat soubory a zazipovat je do jednoho souboru zip

  3. Jak mohu v Bash používat společně příkazy watch a jobs?