Something I learned recently and I thought was amazing - you can create sockets straight from your shell! Well, assuming you use bash or zsh - from some surface level digging, I couldn’t find anything for fish.
Here’s how it works:
Bash supports tcp and udp connections out of the box, and does so with an imaginary device in
$ echo "text!" > /dev/$PROTO/$HOST/$PORT
And you’ll create a connection to
$PROTO can be
udp. If the connection can’t be made, writing to/reading the file will fail.
Along with being easy to access from the terminal, it’s very handy for scripts, especially if you don’t have
telnet. For example, if a local build of a web app runs on port 8000, you can check if it’s running with:1
#!/bin/bash if exec 3>/dev/tcp/localhost/8000 ; then echo "server up!" else echo "server down." fi
And then use that information somewhere else.
If you’re unfamiliar,
exec without any arguments is used to redirect file descriptors and files. By associating fd 3 with
/dev/tcp/localhost/4000, it attempts to create a file there and thus a connection. We use
> to open the socket for writing, although we don’t need to write anything in this case.
<> we can open a file for reading and writing, and use it to create a super simple curl:
#!/bin/bash exec 3<>/dev/tcp/"$1"/80 echo -e "GET / HTTP/1.1\n" >&3 cat <&3
$ ./simplecurl www.google.com HTTP/1.1 200 OK Date: Thu, 03 Dec 2020 00:57:30 GMT Expires: -1 .... <google website>
I’m sure you can see the power of being able to open sockets with bash alone. Go play around with it!
zsh has an external module you can load in order to use it’s socket capabilities. It doesn’t support udp like bash, but it’s more powerful in a few ways!
To load the module, put the following in your
.zshrc or run it in your shell:
$ zmodload zsh/net/tcp
We now have access to the zsh networking builtin -
ztcp allows creating connections, like bash, but also allows listening for connections.
Straight from the zsh docs, we can create a connection between two machines with
# host machine: ztcp -l 7128 lfd=$REPLY ztcp -a $lfd talkfd=$REPLY # client machine ztcp HOST 7128 talkfd=$REPLY
$REPLY variable here is a file descriptor returned by the last
ztcp command, referring to the socket/connection it just created.
talkfd on both machines is a file descriptor for talking to the other:
# host machine echo -e "hello!" >&$talkfd # client machine read -r line <&$talkfd; print -r - $line > hello!
Again, there’s a lot more you can do, especially with the ability to listen for connections.
Hope this was as interesting to you as it was to me!
Thanks to u/barubary for pointing out why the previous version of this code was wrong! ↩