Ответ 1
Он определяется TCP. Он может быть уменьшен на основе каждого сокета с помощью кода приложения.
NB Тайм-аут вступает в силу только при отсутствии ответа. Если есть отказ в подключении, ошибка возникает немедленно.
В приведенной ниже команде я разрешаю файл /dev/tcp/10.10.10.1/80
как для чтения, так и записи и связывать его с файловым дескриптором 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
Это автоматически пытается выполнить трехстороннее рукопожатие TCP. Если 10.10.10.1 недоступен, как в примере выше, тогда connect
системный вызов пытается подключиться в течение 75 секунд. Является ли этот 75-й тайм-аут определяемым bash
? Или эта система по умолчанию? И последнее, но не менее важное: есть ли способ уменьшить это значение таймаута?
Он определяется TCP. Он может быть уменьшен на основе каждого сокета с помощью кода приложения.
NB Тайм-аут вступает в силу только при отсутствии ответа. Если есть отказ в подключении, ошибка возникает немедленно.
/dev/tcp/
Да, вы можете изменить время ожидания по умолчанию для TCP-соединения на любом языке программирования.
Но bash не является язык программирования!
Вы можете посмотреть исходный код (см. Bash Домашняя страница), вы можете найти файл lib/sh/netopen.c
, в котором вы могли бы прочитать в функции _netopen4
:
s = socket(AF_INET, (typ == 't') ? SOCK_STREAM : SOCK_DGRAM, 0);
Вы можете внимательно прочитать этот файл, не считая таймаута соединения.
Без исправления источников bash невозможно изменить время ожидания соединения с помощью bash script.
Существует небольшой пример HTTP-клиента, написанного в чистом bash, но используя netcat
:
#!/bin/bash
tmpfile=$(mktemp -p $HOME .netbash-XXXXXX)
exec 7> >(nc -w 3 -q 0 stackoverflow.com 80 >$tmpfile)
exec 6<$tmpfile
rm $tmpfile
printf >&7 "GET %s HTTP/1.0\r\nHost: stackoverflow.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<&-
Это может сделать:
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=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly
TITLE:
bash - How to decrease TCP connect() system call timeout? - Stack Overflow
Некоторые объяснения:
Сначала мы создаем временный файл (в секретном каталоге по соображениям безопасности), связываем и удаляем его.
$ tmpfile=$(mktemp -p $HOME .netbash-XXXXXX)
$ exec 7> >(nc -w 3 -q 0 stackoverflow.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>&-
Это невозможно в Bash без изменения источника, как уже упоминалось, хотя это обходное решение с помощью команды timeout
, например:
$ timeout 1 bash -c "</dev/tcp/stackoverflow.com/80" && echo Port open. || echo Port closed.
Port open.
$ timeout 1 bash -c "</dev/tcp/stackoverflow.com/81" && echo Port open. || echo Port closed.
Port closed.
Используя этот синтаксис, команда timeout
убьет процесс по истечении заданного времени.
Подробнее см. timeout --help
.