
Я только что обновился с Mavericks до Yosemite и теперь curl
не вижу имен хостов обратной связи.
Настройте простой http-сервер для тестирования:
$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
Теперь я могу попасть на localhost:8000 в Chrome. Я даже могу wget его. Но в curl происходит следующее:
$ curl localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused
Однако это работает:
$ curl 127.0.0.1:8000
Я читаюэтот ответ о настройках прокси wget, но это не помогло, потому что это работает:
$ wget --proxy=off localhost:8000
Это действительно раздражает, поскольку в моем файле указано несколько разных имен хостов loopback, /etc/hosts
поэтому я могу разрабатывать приложения локально, и я привык отлаживать их с помощью curl.
Я попробовал версию curl, которая идет в комплекте с OSX:
$ curl --version
curl 7.37.1 (x86_64-apple-darwin14.0) libcurl/7.37.1 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IPv6 Largefile NTLM NTLM_WB SSL libz
$ curl localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused
$ curl 127.0.0.1 # works
И я попробовал скомпилировать curl с помощью brew:
$ /usr/local/Cellar/curl/7.38.0/bin/curl --version
curl 7.38.0 (x86_64-apple-darwin14.0.0) libcurl/7.38.0 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: IPv6 Largefile NTLM NTLM_WB SSL libz
$ /usr/local/Cellar/curl/7.38.0/bin/curl localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused
$ /usr/local/Cellar/curl/7.38.0/bin/curl 127.0.0.1:8000 # works
решение1
Я только что заставил его работать, закомментировав одну из строк IPv6 loopback в моем файле /etc/hosts:
#fe80::1%lo0 localhost
Теперь все мои петлевые имена хостов работают, а не только localhost. Интересно, что с этим?
решение2
Альтернатива(не требует sudo или изменения /etc/hosts
)- всегда используйте ipv4, пока curl не станет умнее.
$ echo '--ipv4' >> ~/.curlrc
(тогда все будет работать так, как нужно)
решение3
Прежде всего, 0.0.0.0
это специальный адрес, означающий «любой адрес IPv4».
Сокет может быть привязан к протоколу IPv4 или IPv6. Если сокет привязан к 0.0.0.0
, это означает, что он будет слушать любой IPv4, пытающийся подключиться к нему, и будет представлен следующим образом:
$ nc -l 0.0.0.0 8085
$ lsof -i4 -Pnl | grep 8085
nc 23994 [xxx] 3u IPv4 [xxx] 0t0 TCP *:8085 (LISTEN)
Знак *
эквивалентен 0.0.0.0
IPv4.
Для IPv6:
$ nc -l :: 8085
$ lsof -i6 -Pnl | grep 8085
nc 24145 [xxx] 3u IPv6 [xxx] 0t0 TCP *:8085 (LISTEN)
Знак *
эквивалентен ::
IPv6,как в официальной спецификации.
Причина в том, что он curl
пытается разрешить случайную localhost
запись в /etc/hosts
, и, как упомянул @NickRetallack, эта запись выбирается при curl
разрешении localhost
в режиме по умолчанию (предположительно IPv6 или IPv4, в зависимости от того, что разрешается первым).
Принудительное включение --ipv4
режима, как предложил @CharlesHebdough, приведет к curl
разрешению (при условии, что нет других записей IPv4 для in ).localhost
127.0.0.1
localhost
/etc/hosts
Каждая реализация будет решать localhost
проблему по своему усмотрению, поэтому при использовании разных инструментов у вас был непостоянный успех.
Чтобы быть максимально точным, используйте 127.0.0.1
вместо localhost, но это привяжет вас к IPv4. localhost
дает вам гибкость для работы как с протоколами IPv6, так и с IPv4, однако в некоторых реализациях у вас могут возникнуть проблемы, как в этой конкретной версии curl
.