6 ms·
if [ exec 1>/dev/null 2>/dev/null 3>/dev/tcp/localhost/4000 ] ; then This code runs `[ exec ]` (which tests if "exec" is a non-empty string, thus it returns tr
by izabera 6y ago
if [ exec 1>/dev/null 2>/dev/null 3>/dev/tcp/localhost/4000 ] ; then
This code runs `[ exec ]` (which tests if "exec" is a non-empty string, thus it returns true) and redirects its output and error to /dev/null, and fd 3 to /dev/tcp/whatever. If the socket opening fails, `[ exec ]` is not even executed, and the overall command returns nonzero. Completely equivalent to `: 3>/dev/tcp/localhost/4000`, which also returns nonzero if the socket can't be opened.
It happens to work for the intended purpose, but not for the reasons the author intended.
- kzrdude 6y agoA testament to the brokenness of making `[` a command
- dundarious 6y agoI prefer to always use the `test` command instead (it’s the exact equivalent of `[`), and never use `[[` bashisms (well, almost never).
- xyzzy_plugh 6y agoAnd here I thought I was the only one!
- kzrdude 6y agoI also do this.
- yrro 6y agoshellcheck has this to say: In exec.sh line 1: if [ exec 1>/dev/null 2>/dev/null 3>/dev/tcp/localhost/4000 ] ; then ^-- SC1009: The mentioned syntax error was in this if expression. ^-- SC1073: Couldn't parse this test expression. Fix to allow more checks. ^-- SC1014: Use 'if cmd; then ..' to check exit code, or 'if [[ $(cmd) == .. ]]' to check output. ^-- SC1072: Expected test to end here (don't wrap commands in []/[[]]). Fix any mentioned problems and try again. For more information: https://www.shellcheck.net/wiki/SC1014 -- Use 'if cmd; then ..' to check ex... https://www.shellcheck.net/wiki/SC1072 -- Expected test to end here (don't ... https://www.shellcheck.net/wiki/SC1073 -- Couldn't parse this test expressi...
- who23 6y agoHey I'm the author - I did not know about this! I suppose I should have guessed somebody made a shell script linter at some point though. Very useful!
- gricardo99 6y agoI'm not sure if the code example changed on the linked page after your comment, but I see this code: #!/bin/bash if exec 3>/dev/tcp/localhost/4000 ; then echo "server up!" else echo "server down." fi Which also confused me for similar reasons to your comment. I'm not familiar with exec, but generally non-zero return means a fail, and zero means success. So why is the "server up" for non-zero result?
- gricardo99 6y agoSure enough, I tested this, and the server up/down is reversed from what it should be: > exec 3>/dev/tcp/localhost/4000 bash: connect: Connection refused bash: /dev/tcp/localhost/4000: Connection refused > echo $? 1 But if a localhost port is listening (in another terminal window: > nc -l localhost 4000): > exec 3>/dev/tcp/localhost/4000 > echo $? 0
- dllthomas 6y agoIn the quoted code, "server up" is for a zero result - `if` is reversed from what you think it is: > if true; then echo yup; fi yup > true > echo $? 0
- gricardo99 6y agoindeed you are right. Thanks for the reply. I'm too accustomed to seeing code like: if [ $? -eq 0 ]; then echo "pass";else echo "fail";fi But without the expression '[ ... ]' shell/bash does indeed treat zero return code (success) as boolean true. For whatever reason I have not seen much (if any) bash code that simply uses: if COMMAND; then ...
- fl0wenol 6y agoYou really really should use if COMMAND logic, in the event that all you care about is zero or non-zero result. I find it easier to follow for shell control flow. It also works for shell functions.
- who23 6y agoHi I'm the author! Yes, I wrote this code quite quickly and when I originally posted this on reddit someone pointed out my mistake. The more you know, I suppose.