Capturing exit status of commands
The assignment of command output to the rep
variable does not lose the exit status of the curl command; it is still available as $?
. For more details, see How can I store the return value and/or output of a command in a variable?.
Curl exit code for failed HTTP requests
Usually if a requested HTTP resource isn’t available, a web server responds with a HTML document corresponding to the relevant HTTP status code, e.g. 404. In such cases, curl accepts this document from the server and since it was successful in getting a response from the web server, it displays the error document and exits with a status of 0 for success.
I presume you’re expecting curl
to return an error code if there was a problem retrieving the HTTP resource. In scripts it’s better to have curl
exit with unsuccessful status if there was a problem retrieving the HTTP resource. For that, you need to provide the -f, --fail
option to curl, described in the curl man page as:
Fail silently (no output at all) on server errors. This is mostly done to better enable scripts etc to better deal with failed attempts. In normal cases when an HTTP server fails to deliver a document, it returns an HTML document stating so (which often also describes why and more). This flag will prevent curl from outputting that and return error 22.
This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407).
You can save the curl command’s exit status by using an extra variable, status
:
httpUrl="http://www.nnin.com"
rep=$(curl -f -v -d "UID=username&PWD=pass" "$httpUrl")
status="$?"
echo "$rep"
exit "$status"
The shell variable, httpUrl
should be double-quoted in case the URL contains characters that may be interpreted by the shell. Also, the -X POST
is not needed as the POST method is always used when data is provided with the -d
option.
(Not) printing output of curl command
There’s no need to save the output of the curl command into the rep
variable if all you do with it is print it to standard output.
Regarding the second question, “how to prevent the output from print”, you can replace the -v/--verbose
option with the -s/--silent
option (Silent mode. Don’t show progress meter or error messages).
In fact, you can simplify your script even more if its last command is the curl invocation. The exit code of the script will be the return code of the script’s last command.
httpUrl="http://www.nnin.com"
curl -f -s -d "UID=username&PWD=pass" "$httpUrl"
Single-quote vs double-quote versions
Let's define the alias using single-quotes:
$ alias d='$(date)'
Now, let's retrieve the definition of the alias:
$ alias d
alias d='$(date)'
Observe that no command substitution was yet performed.
Let's do the same, but this time with double-quotes:
$ alias d="$(date)"
$ alias d
alias d='Fri Oct 28 17:01:12 PDT 2016'
Because double-quotes are used, command substitution was performed before the alias was defined.
Single-quote version
Let's try executing the single-quote version:
$ alias d='$(date)'
$ d
bash: Fri: command not found
The single-quote version is equivalent to running:
$ $(date)
bash: Fri: command not found
In both cases, the command substitution is performed when the command is executed.
A variation
Let's consider this alias which uses command substitution and is defined using single-quotes:
$ alias e='echo $(date)'
$ e
Fri Oct 28 17:05:29 PDT 2016
$ e
Fri Oct 28 17:05:35 PDT 2016
Every time that we run this command, date
is evaluated again. With single-quotes, the command substitution is performed when the alias is executed, not when it is defined.
Best Answer
Since back-ticks are often used, it makes sense to teach this syntactic construct.
Of course,
$()
style command substitution should be emphasized as the default style (and standard conforming construct).Why are back-ticks still popular? Because they save one character in typing, and they are arguably less heavy on the eye.