Join the discussion

Write your take first — we'll ask for email only when you're ready to publish.

  • Hacker News
  • A few years ago I had to do this for a SpringBoot health check from a Docker container:

    FROM openjdk:11-jre-slim HEALTHCHECK --start-period=10s --timeout=3s --retries=5 \ CMD perl -e "use IO::Socket; $sock = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => 'localhost', PeerPort => '8888') or die $@; $sock->autoflush(1); print $sock 'GET /actuator/health HTTP/1.1' . chr(0x0a) . chr(0x0d) . 'Host: localhost:8888' . chr(0x0a) . chr(0x0d) . 'Connection: close' . chr(0x0a) . chr(0x0d) . chr(0x0a) . chr(0x0d); while (my $line = $sock->getline ) { if ($line =~ /UP/) {exit;} }; close $sock; exit 1;"

  • Note that this didn't work historically on Debian, and presumably Debian-derived distros, where the virtual file TCP access was disabled by default. The position was reversed (and the capability enabled) in 2009, AFAIU. There's discussion and links in Bug #146464:

    <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=146464#37>

    As others have mentioned, there are numerous other ways to directly access network features using shell tools, including curl (noted in TFA's title), wget, the HEAD and GET commands (from Perl), netcat (nc), socat, telnet, and I'm quite sure others.

  • I ran into this while checking connectivity between containers on an internal Docker network where the image had neither curl nor wget.

    The main surprise was that Bash has /dev/tcp which lets you do the equivalent of an HTTP request with a bit of shell magic, for instance:

      exec 3<>/dev/tcp/service/8642
      printf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3
      cat <&3
    
    
    Where `service` is just the hostname of whatever you’re talking to and 8642 is the port you are trying to talk HTTP to.

    Pretty cool!

  • > This is a bash feature, not POSIX. dash (Debian’s /bin/sh) and zsh don’t have it, so a #!/bin/sh script can’t use it. Call bash directly.

    Zsh has its own zsh/net/tcp and zsh/zftp modules.

    https://zsh.sourceforge.io/Doc/Release/TCP-Function-System.h...

    https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-...

    https://zsh.sourceforge.io/Doc/Release/Zftp-Function-System....

  • > As it turns out, bash can speak HTTP by itself.

    No, it can not. Bash lets you open TCP sockets.

    What you are doing here is trying to speak HTTP yourself, which is fine for testing and debugging, and hella cool for fun to do by hand, but you will shoot yourself in the foot if you try to use this pseudo http client unattended in reality. This toy code does not parse HTTP properly and will break.

    You could of course write a full http/1.1 client in bash, you can even do a full http server in pure bash: https://github.com/bahamas10/bash-web-server

    For less insane, non-bash shells there is always nc which is usually probably the wiser choice.

  • In Plan 9 you did have a real (synthetic) /net, and could do that and more from any program. You could even mount /net from another machine via 9P protocol and have an instant VPN...

    9front lets you play with that on Linux.

    Some Plan 9 like /net things are visible in Go libraries... (Rob Pike legacy)

  • Neat, works against example.com

      exec 3<>/dev/tcp/example.com/80
      printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' >&3
      cat <&3
    
    Outputs:

      HTTP/1.1 200 OK
      Date: Tue, 16 Jun 2026 17:37:45 GMT
      Content-Type: text/html
      ...
    
    I always end up on example.com for this kind of thing because there are so few domains these days that don't enforce https!
  • As a kid in the late 90s my mind was blown when I realized I could telnet to port 80, 25, or 110 and interact with the servers manually.

    Simple get: GET / HTTP/1.1 Content-Type: text/html User-Agent: l33t hax0rs lol X-Funny-Monkey: farts

    For sending a mail message on port 25: HELO mail-from: whoever@whatever.com mail-to: sysadmin@yaya.com <other headers> <blank line> Body of the message yay. <two blank lines to end>

    POP3 was so long ago I forgot but you could list the mailboxes then get individual messages and so on.

    This revelation was the beginning of "there is no magic" for me. The realization that every part of the computer was built by human beings and was at some level understandable if one undertook the effort.

    Perhaps most people in the future won't bother. They'll just let agents do it all. I'm sure that will leave some interesting holes in various systems for people willing to actually learn how they work without the filter of a model (or its safety rails).

Explore Birbla archives