bash - Cómo disminuir el tiempo de espera de la llamada al sistema TCP connect()?
connection-timeout (3)
Está determinado por TCP. Se puede disminuir por socket por código de la aplicación.
NB El tiempo de espera solo tiene efecto si no hay respuesta. Si hay un rechazo de conexión, el error ocurre inmediatamente.
En el siguiente comando, /dev/tcp/10.10.10.1/80
archivo /dev/tcp/10.10.10.1/80
para leer y escribir y lo asocio con el descriptor de archivo 3:
$ time exec 3<>/dev/tcp/10.10.10.1/80
bash: connect: Operation timed out
bash: /dev/tcp/10.10.10.1/80: Operation timed out
real 1m15.151s
user 0m0.000s
sys 0m0.000s
Esto automáticamente intenta realizar un protocolo de enlace de tres vías TCP. Si 10.10.10.1 no es alcanzable como en el ejemplo anterior, entonces la llamada al sistema de connect
intenta conectarse durante 75 segundos. ¿Es este tiempo de espera de 75 segundos determinado por bash
? ¿O es este sistema por defecto? Por último, pero no menos importante, ¿hay alguna forma de disminuir este valor de tiempo de espera?
No: no hay forma de cambiar el tiempo de espera utilizando /dev/tcp/
Sí, podría cambiar el tiempo de espera predeterminado para la conexión TCP en cualquier lenguaje de programación.
¡Pero, bash no es un lenguaje de programación!
Puede echar un vistazo al código fuente (ver: Bash Homepage ), puede encontrar el archivo lib/sh/netopen.c
donde podría leer en la función _netopen4
:
s = socket(AF_INET, (typ == ''t'') ? SOCK_STREAM : SOCK_DGRAM, 0);
Puede leer este archivo con cuidado, no hay consideración de tiempo de espera de conexión.
Sin parchear fuentes de bash, no hay forma de cambiar el tiempo de espera de conexión mediante un script bash.
Cliente HTTP simple usando netcat (casi puro bash)
Hay un pequeño ejemplo de cliente HTTP escrito en pure bash, pero usando netcat
:
#!/bin/bash
tmpfile=$(mktemp -p $HOME .netbash-XXXXXX)
exec 7> >(nc -w 3 -q 0 .com 80 >$tmpfile)
exec 6<$tmpfile
rm $tmpfile
printf >&7 "GET %s HTTP/1.0/r/nHost: .com/r/n/r/n" /
/questions/24317341/how-to-decrease-tcp-connect-system-call-timeout
timeout=100;
while ! read -t .001 -u 6 status ; do read -t .001 foo;done
echo STATUS: $status
[ "$status" ] && [ -z "${status//HTTP*200 OK*}" ] || exit 1
echo HEADER:
while read -u 6 -a head && [ "${head//$''/r''}" ]; do
printf "%-20s : %s/n" ${head%:} "${head[*]:1}"
done
echo TITLE:
sed ''/<title>/s/<[^>]*>//gp;d'' <&6
exec 7>&-
exec 6<&-
Esto podría representar:
STATUS: HTTP/1.1 200 OK
HEADER:
Cache-Control : private
Content-Type : text/html; charset=utf-8
X-Frame-Options : SAMEORIGIN
X-Request-Guid : 46d55dc9-f7fe-425f-a560-fc49d885a5e5
Content-Length : 91642
Accept-Ranges : bytes
Date : Wed, 19 Oct 2016 13:24:35 GMT
Via : 1.1 varnish
Age : 0
Connection : close
X-Served-By : cache-fra1243-FRA
X-Cache : MISS
X-Cache-Hits : 0
X-Timer : S1476883475.343528,VS0,VE100
X-DNS-Prefetch-Control : off
Set-Cookie : prov=ff1129e3-7de5-9375-58ee-5f739eb73449; domain=..com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly
TITLE:
bash - How to decrease TCP connect() system call timeout? - Stack Overflow
Algunas explicaciones
Creamos primero un archivo temporal (en el directorio privado por razones de seguridad), vinculamos y eliminamos antes de usarlos.
$ tmpfile=$(mktemp -p $HOME .netbash-XXXXXX)
$ exec 7> >(nc -w 3 -q 0 .com 80 >$tmpfile)
$ exec 6<$tmpfile
$ rm $tmpfile
$ ls $tmpfile
ls: cannot access /home/user/.netbash-rKvpZW: No such file or directory
$ ls -l /proc/self/fd
lrwx------ 1 user user 64 Oct 19 15:20 0 -> /dev/pts/1
lrwx------ 1 user user 64 Oct 19 15:20 1 -> /dev/pts/1
lrwx------ 1 user user 64 Oct 19 15:20 2 -> /dev/pts/1
lr-x------ 1 user user 64 Oct 19 15:20 3 -> /proc/30237/fd
lr-x------ 1 user user 64 Oct 19 15:20 6 -> /home/user/.netbash-rKvpZW (deleted)
l-wx------ 1 user user 64 Oct 19 15:20 7 -> pipe:[2097453]
$ echo GET / HTTP/1.0$''/r/n/r'' >&7
$ read -u 6 foo
$ echo $foo
HTTP/1.1 500 Domain Not Found
$ exec 7>&-
$ exec 6>&-
No es posible en Bash sin modificar la fuente como ya se mencionó, aunque aquí está la solución mediante el uso del comando de timeout
, por ejemplo:
$ timeout 1 bash -c "</dev/tcp/.com/80" && echo Port open. || echo Port closed.
Port open.
$ timeout 1 bash -c "</dev/tcp/.com/81" && echo Port open. || echo Port closed.
Port closed.
Usando esta sintaxis, el comando de timeout
matará el proceso después del tiempo dado.
Ver: timeout --help
para más opciones.