9 comments

[ 2.4 ms ] story [ 12.9 ms ] thread
I have been using/administering GNU/Linux based systems for 15 years and have yet to see where the Bash built-in /dev/tcp was enabled, so any shell script I write that requires sockets I reach for netcat or socat.
I just tried it on stock Ubuntu 14.04, Linux Mint, and a CentOS box, and it worked fine.
I think you are mistaken. /dev/tcp is not visible in /dev or devtmpfs, however it most definitely works.

$ nc -l 8080 &

[1] 13694

$ echo hi >> /dev/tcp/127.0.0.1/8080

hi

[1]+ Done nc -l 8080

I just tried it on a relatively diverse set of distros. Depending on the version of netcat, if it is an ancient one on an older distribution such as say RHEL4, you have to do:

nc -l -p 8080

However, the same echo command works in all of them.

Exactly. Its been available for a while now on most distros, I even used it on some legacy AIX systems running Korn shell.

Btw, the reason why this works even if you dont see anything in /dev/tcp is because when you try to open a socket in bash using /dev/tcp it doesn't talk with the pseudo-filesystem of /dev. Bash actually intercepts the command and issues a connect() to the remote host.

Arguably not pure bash, in that it calls out to external executables. I'm pretty sure all the head/cut/tr invocations could be easily replaced by appropriate parameter expansions though, and the `read` builtin could probably supplant `dd`, so it should be doable.
Bash doesn't exist in a vacuum. It's designed to make use of and interact heavily with those external commands. An environment missing dd, head, cut, and tr is probably not going to provide a usable /dev/tcp filesystem, either.

Ultimately the point is that a Redis client is possible using just a standard Unixish userland, and sysadmins who interact with Bash all day can easily make use of redis directly and integrate it into existing scripts without installing special client libraries or writing wrappers in Perl or Python.

Sure -- but my point was merely in regard to the (mis)use of the word "pure" here. Avoiding calling out to external executables and remaining purely within the shell itself is also frequently a good way to improve performance (sometimes quite dramatically), so being aware of the difference is worthwhile.

(Also, /dev/tcp isn't a filesystem, just a simulation of one constructed purely within bash itself, so it wouldn't in fact depend on anything but the relevant networking syscalls.)

Reminds me of cronlock[0] which is a bash script that uses Redis as a global lock that you can use across multiple servers. Needing to just download a single bash script makes it easy to drop into an existing project.

[0] https://github.com/kvz/cronlock

I use Redis as an IPC lock for our applications, too - it's quite good at it, especially since you can have atomicity guarantees with a Lua script.