Script to show HTTP(S) and TLS details for a website

This may be seen as self-promotion - that's not totally wrong. But I think this may also be useful to others and (as I acknowledge in the blog post) I'm quite pleased with the resultant script. Over the past year and a half I've slowly developed a shell script that gives a concise summary of the state of TLS and HTTP(S) on a given website. It looks like this: $ tlsdetails google.ca Using OpenSSL: /usr/bin/openssl Expiry Date: Oct 27 17:27:07 2019 GMT (78 days) Issuer: Google Trust Services, CN TLS Versions: tls1_3 tls1_2 tls1_1 tls1 (tried but unavailable: ssl3 ssl2 ) HTTP Version: 2 I first started work on it after a couple embarrassing certificate expiries. It then grew to check the Issuer, TLS versions, and more recently whether or not a site supports HTTP2. (The pointer to the OpenSSL version is shown because the script will also run on Mac, and their version of 'openssl' is problematic at best. That line is of course easy to remove if you don't like it.) If you're interested, you can find the details here: https://www.gilesorr.com/blog/tls-https-details.html Any suggestions to improve the script would be most welcome. -- Giles https://www.gilesorr.com/ gilesorr@gmail.com

Looks like a handy script to have. My only real suggestion is to change the shebang to *#!/usr/bin/env bash* as it's more portable than the current one. Still not perfect, but works reliably on more systems. -jason On Sat, Aug 10, 2019 at 11:46 AM Giles Orr via talk <talk@gtalug.org> wrote:
This may be seen as self-promotion - that's not totally wrong. But I think this may also be useful to others and (as I acknowledge in the blog post) I'm quite pleased with the resultant script.
Over the past year and a half I've slowly developed a shell script that gives a concise summary of the state of TLS and HTTP(S) on a given website. It looks like this:
$ tlsdetails google.ca Using OpenSSL: /usr/bin/openssl Expiry Date: Oct 27 17:27:07 2019 GMT (78 days) Issuer: Google Trust Services, CN TLS Versions: tls1_3 tls1_2 tls1_1 tls1 (tried but unavailable: ssl3 ssl2 ) HTTP Version: 2
I first started work on it after a couple embarrassing certificate expiries. It then grew to check the Issuer, TLS versions, and more recently whether or not a site supports HTTP2.
(The pointer to the OpenSSL version is shown because the script will also run on Mac, and their version of 'openssl' is problematic at best. That line is of course easy to remove if you don't like it.)
If you're interested, you can find the details here:
https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
-- Giles https://www.gilesorr.com/ gilesorr@gmail.com --- Post to this mailing list talk@gtalug.org Unsubscribe from this mailing list https://gtalug.org/mailman/listinfo/talk

Line 130 s/-eq/=/ Otherwise, cool! Thanks! ../Dave On Aug 10, 2019, 5:32 PM -0400, Jason Shaw via talk <talk@gtalug.org>, wrote:
Looks like a handy script to have. My only real suggestion is to change the shebang to #!/usr/bin/env bash as it's more portable than the current one. Still not perfect, but works reliably on more systems.
-jason
On Sat, Aug 10, 2019 at 11:46 AM Giles Orr via talk <talk@gtalug.org> wrote:
This may be seen as self-promotion - that's not totally wrong. But I think this may also be useful to others and (as I acknowledge in the blog post) I'm quite pleased with the resultant script.
Over the past year and a half I've slowly developed a shell script that gives a concise summary of the state of TLS and HTTP(S) on a given website. It looks like this:
$ tlsdetails google.ca Using OpenSSL: /usr/bin/openssl Expiry Date: Oct 27 17:27:07 2019 GMT (78 days) Issuer: Google Trust Services, CN TLS Versions: tls1_3 tls1_2 tls1_1 tls1 (tried but unavailable: ssl3 ssl2 ) HTTP Version: 2
I first started work on it after a couple embarrassing certificate expiries. It then grew to check the Issuer, TLS versions, and more recently whether or not a site supports HTTP2.
(The pointer to the OpenSSL version is shown because the script will also run on Mac, and their version of 'openssl' is problematic at best. That line is of course easy to remove if you don't like it.)
If you're interested, you can find the details here:
https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
-- Giles https://www.gilesorr.com/ gilesorr@gmail.com --- Post to this mailing list talk@gtalug.org Unsubscribe from this mailing list https://gtalug.org/mailman/listinfo/talk
Post to this mailing list talk@gtalug.org Unsubscribe from this mailing list https://gtalug.org/mailman/listinfo/talk

Nice work, Giles! It's just a little loud on sites that don't support https: $ tls-details.sh c-raine.com Using OpenSSL: /usr/bin/openssl unable to load certificate 140536996852864:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE unable to load certificate 139639350289536:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE Expiry Date: (0 days) unable to load certificate 139787601568896:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE Issuer: TLS Versions: (tried but unavailable: tls1_3 tls1_2 tls1_1 tls1 ssl3 ssl2 ) HTTP Version: 1.1 Sites without https support still exist, despite what Google wants you to hear. This is on a host that doesn't support Let's Encrypt (ionos still want something ridiculous like $50/year for a certificate) and the inertia of moving to another host is just too much. cheers, Stewart

How does it compare with "testssl.sh" ?--William Sent from Yahoo Mail on Android On Sat, Aug 10, 2019 at 11:46 AM, Giles Orr via talk<talk@gtalug.org> wrote: This may be seen as self-promotion - that's not totally wrong. But I think this may also be useful to others and (as I acknowledge in the blog post) I'm quite pleased with the resultant script. Over the past year and a half I've slowly developed a shell script that gives a concise summary of the state of TLS and HTTP(S) on a given website. It looks like this: $ tlsdetails google.ca Using OpenSSL: /usr/bin/openssl Expiry Date: Oct 27 17:27:07 2019 GMT (78 days) Issuer: Google Trust Services, CN TLS Versions: tls1_3 tls1_2 tls1_1 tls1 (tried but unavailable: ssl3 ssl2 ) HTTP Version: 2 I first started work on it after a couple embarrassing certificate expiries. It then grew to check the Issuer, TLS versions, and more recently whether or not a site supports HTTP2. (The pointer to the OpenSSL version is shown because the script will also run on Mac, and their version of 'openssl' is problematic at best. That line is of course easy to remove if you don't like it.) If you're interested, you can find the details here: https://www.gilesorr.com/blog/tls-https-details.html Any suggestions to improve the script would be most welcome. -- Giles https://www.gilesorr.com/ gilesorr@gmail.com--- Post to this mailing list talk@gtalug.org Unsubscribe from this mailing list https://gtalug.org/mailman/listinfo/talk

On Sat, 10 Aug 2019 at 11:46, Giles Orr <gilesorr@gmail.com> wrote:
... https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
Jason: You are of course correct: '#!/usr/bin/env bash' is more portable. I don't usually bother because '#!/usr/bin/bash' works fine on every Linux I've used and on Mac, so I don't think to fix this when I make my scripts public ... Dave: "Line 130 s/-eq/=/" See, that's interesting ... First, "==" would be correct for a Bash string comparison, not "=" (which is correct for 'sh'). Second ... Arguably it's a numeric comparison (thus '-eq'), but I did put quotes around it which probably makes it string ... <sigh> Yeah, I don't know what that should be. It's worked so far ... Stewart: "It's just a little loud on sites that don't support https:" My apologies: I did think of that and test for it ... but on precisely one site where it returned silently and all was good. I tested on a site that responds on port 80, but doesn't respond at all on port 443. The site you named sends a 400 "Bugger off" response (technically "Bad Request") on port 443. Probably because you have a hosting provider who reasonably enough listens on that port whether the site has a certificate or not. I naively assumed that a site without a cert wouldn't be listening on port 443. I'll think about that. William: 'How does it compare with "testssl.sh" ?' I have no idea, I haven't used that. If you point me to it I'll take a look. -- Giles https://www.gilesorr.com/ gilesorr@gmail.com

On Sun, 11 Aug 2019, Giles Orr via talk wrote:
On Sat, 10 Aug 2019 at 11:46, Giles Orr <gilesorr@gmail.com> wrote: ...https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
Jason:
You are of course correct: '#!/usr/bin/env bash' is more portable.? I don't usually bother because '#!/usr/bin/bash' works fine on every Linux I've used and on Mac, so I don't think to fix this when I make my scripts public ...
$ ls /usr/bin/bash ls: cannot access '/usr/bin/bash': No such file or directory It is usually /bin/bash
Dave: "Line 130 s/-eq/=/"
See, that's interesting ...? First, "==" would be correct for a Bash string comparison, not "=" (which is correct for 'sh').? Second ...? Arguably it's a numeric comparison (thus '-eq'), but I did put quotes around it which probably makes it string ...? <sigh>? Yeah, I don't know what that should be.? It's worked so far ...
You said that is could return 1.1; that is not a valid number in bash. Also, you are combining two syntaxes in your function definitions. You can use either function funcname { : ## ksh style } or funcname() { : ## POSIX style } You don't need both. -- Chris F.A. Johnson <http://cfajohnson.com/> =========================== Author: =============================== Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress) Pro Bash Programming: Scripting the GNU/Linux shell (2009, Apress)

On Sun, Aug 11, 2019 at 07:58:15PM -0400, Giles Orr via talk wrote:
William: 'How does it compare with "testssl.sh" ?'
I have no idea, I haven't used that. If you point me to it I'll take a look.
We use it at work. http://testssl.sh/ I don't know how they give out different responses, but if you use browser, you get frontpage. If you use curl or wget, you get the script. -- William Park <opengeometry@yahoo.ca>

On 2019-08-11 7:58 p.m., Giles Orr via talk wrote:
The site you named sends a 400 "Bugger off" response (technically "Bad Request") on port 443.
I prefer your term to the official one. It's much more in line with Ionos' (formerly 1and1) customer support policy. Seconding the need for quotes around variables in scripts. You don't need 'em until you let others use one of your scripts. Stewart

On Sat, Aug 10, 2019 at 8:46 AM Giles Orr via talk <talk@gtalug.org> wrote:
This may be seen as self-promotion - that's not totally wrong. But I think this may also be useful to others and (as I acknowledge in the blog post) I'm quite pleased with the resultant script.
Over the past year and a half I've slowly developed a shell script that gives a concise summary of the state of TLS and HTTP(S) on a given website. It looks like this:
$ tlsdetails google.ca Using OpenSSL: /usr/bin/openssl Expiry Date: Oct 27 17:27:07 2019 GMT (78 days) Issuer: Google Trust Services, CN TLS Versions: tls1_3 tls1_2 tls1_1 tls1 (tried but unavailable: ssl3 ssl2 ) HTTP Version: 2
I first started work on it after a couple embarrassing certificate expiries. It then grew to check the Issuer, TLS versions, and more recently whether or not a site supports HTTP2.
(The pointer to the OpenSSL version is shown because the script will also run on Mac, and their version of 'openssl' is problematic at best. That line is of course easy to remove if you don't like it.)
If you're interested, you can find the details here:
https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
This is pretty cool work! My only suggestion would be to slap a license on it. Even if it is a BSD style one, it makes it very clear what you believe acceptable use to be. Thanks! Dhaval

On Sat, Aug 10, 2019 at 11:46:40AM -0400, Giles Orr via talk wrote:
If you're interested, you can find the details here:
https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
OK, here it goes...
# Put most desirable/least-likely last: for opensslbinary in /usr/local/opt/openssl@1.1/bin/openssl /usr/local/opt/opens sl/bin/openssl /usr/bin/openssl do # Every version of OpenSSL I've checked (several across multiple # OpenSSL versions and Apple's LibreSSL) respond to 'openssl version' # with '<brand> <version-no> ...' - there may or may not be stuff after # those two items (usually a build date, but not with Libre). # if [ -f "${opensslbinary}" ]
'-f' tests if it's a file. Maybe you should use '-x' which tests if it's executable.
then output="$("${opensslbinary}" version)" brand="$( echo "${output}" | awk '{ print $1 }')" version="$(echo "${output}" | awk '{ print $2 }')" if [[ "OpenSSL" == "${brand}" ]] then if [[ "${version}" == "1.1"* ]] then OPENSSL="${opensslbinary}" fi fi
You got 7 subshells here. You can reduce it to 1 subshell: read a b rest <<< $($opensslbinary version) case $a:$b in OpenSSL:1.1*) OPENSSL=$opensslbinary ;; esac
fi done
Maybe you should break out of the for-loop as soon as you find something correct. As is, OPENSSL will be the last correct one.
function help() { echo "Usage:" echo " $(basename "${0}") [-h]|<domain-name>" echo "" echo "Show HTTP(s) and certificate details." echo "Do not include the 'http(s)://' leader on the domain name." echo "" echo "-h show this help and exit"
Instead of echo'ing each and every line, you can do cat << EOF Usage: $(basename "${0}") [-h]|<domain-name> Show HTTP(s) and certificate details. Do not include the 'http(s)://' leader on the domain name. -h show this help and exit EOF
function expiry_date() { echo "${1}" | ${OPENSSL} x509 -noout -dates | grep notAfter | awk 'BEGIN { F S="=" } { print $2 }' }
You can get rid of grep, since you're already using awk. echo "$1" | ${OPENSSL} x509 -noout -dates | awk -F= '/notAfter/ {print $2}'
function days_to_expiry() { expiry_date="$(echo "${1}" | ${OPENSSL} x509 -noout -dates | grep notAfter | awk 'BEGIN { FS="=" } { print $2 }')"
You already defined expiry_date(), so why not use it here. expiry_date=$(expiry_date "$1")
if [[ "$(date --version 2>/dev/null)" == *"GNU"* ]] then # Linux (or at least GNU) expiry_epoch_seconds=$(date --date="${expiry_date}" "+%s") else # Assuming the Mac version: expiry_epoch_seconds=$(date -jf '%b %e %H:%M:%S %Y %Z' "${expiry_date}" "+%s") fi
Testing for "GNU" string can be done more simply using grep. if date --version 2>/dev/null | grep -q GNU; then ... else ... fi
function tlsversions() { successful="" failed="" for tlsversion in ssl2 ssl3 tls1 tls1_1 tls1_2 tls1_3 do success=$(echo | ${OPENSSL} s_client -connect "${1}":443 -${tlsversion}
/dev/null 2> /dev/null ; echo $?) if [ ${success} -eq 0 ] then successful="${tlsversion} ${successful}" else failed="${tlsversion} ${failed}" fi
Testing if a command succeeded or failed can be done in-line. if echo | ${OPENSSL} s_client -connect "${1}":443 -${tlsversion} &>/dev/null; then successful=... else failed=... fi Also, do you really need to send empty line to openssl? Maybe you can redirect stdin from /dev/null as well, like openssl ... </dev/null ... That will reduce 3 subshells to 0. General observation: 1. You don't need quotes in variable assignments like var="$(...)" var="$var1" 2. The following tests are the same. They both tests if var is empty. [ "$var"x = x ] [ -z "$var" ] 3. Testing if command succeeded or failed can be done in-line. if command1 | command2 | command2; then ... else ... fi 4. Case statement is usually better than if statement. eg. if [[ "$var" == glob ]]; then ... fi vs case $var in glob) ... ;; esac Note the missing quotes in case, too. You don't need it. -- William Park <opengeometry@yahoo.ca>

Well damn. That's a lot of very good suggestions. I will dispute one of them: you said (more than once I think) that I don't need to quote variables. You are technically correct ... right up until a variable value has a space in it. Then everything goes to hell in a handbasket. I use 'shellcheck' ( https://github.com/koalaman/shellcheck ) through NeoVim's Syntastic ( https://github.com/vim-syntastic/syntastic ) plugin, and it's a real nag about quoting variables. And I agree with it, having had unquoted variables explode in my face. I hope to implement and test most of the rest of your suggestions (along with the previous ones) shortly. Thanks. On Sun, 11 Aug 2019 at 23:49, William Park via talk <talk@gtalug.org> wrote:
On Sat, Aug 10, 2019 at 11:46:40AM -0400, Giles Orr via talk wrote:
If you're interested, you can find the details here:
https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
OK, here it goes...
# Put most desirable/least-likely last: for opensslbinary in /usr/local/opt/openssl@1.1/bin/openssl /usr/local/opt/opens sl/bin/openssl /usr/bin/openssl do # Every version of OpenSSL I've checked (several across multiple # OpenSSL versions and Apple's LibreSSL) respond to 'openssl version' # with '<brand> <version-no> ...' - there may or may not be stuff after # those two items (usually a build date, but not with Libre). # if [ -f "${opensslbinary}" ]
'-f' tests if it's a file. Maybe you should use '-x' which tests if it's executable.
then output="$("${opensslbinary}" version)" brand="$( echo "${output}" | awk '{ print $1 }')" version="$(echo "${output}" | awk '{ print $2 }')" if [[ "OpenSSL" == "${brand}" ]] then if [[ "${version}" == "1.1"* ]] then OPENSSL="${opensslbinary}" fi fi
You got 7 subshells here. You can reduce it to 1 subshell:
read a b rest <<< $($opensslbinary version) case $a:$b in OpenSSL:1.1*) OPENSSL=$opensslbinary ;; esac
fi done
Maybe you should break out of the for-loop as soon as you find something correct. As is, OPENSSL will be the last correct one.
function help() { echo "Usage:" echo " $(basename "${0}") [-h]|<domain-name>" echo "" echo "Show HTTP(s) and certificate details." echo "Do not include the 'http(s)://' leader on the domain name." echo "" echo "-h show this help and exit"
Instead of echo'ing each and every line, you can do
cat << EOF Usage: $(basename "${0}") [-h]|<domain-name>
Show HTTP(s) and certificate details. Do not include the 'http(s)://' leader on the domain name.
-h show this help and exit EOF
function expiry_date() { echo "${1}" | ${OPENSSL} x509 -noout -dates | grep notAfter | awk 'BEGIN { F S="=" } { print $2 }' }
You can get rid of grep, since you're already using awk.
echo "$1" | ${OPENSSL} x509 -noout -dates | awk -F= '/notAfter/ {print $2}'
function days_to_expiry() { expiry_date="$(echo "${1}" | ${OPENSSL} x509 -noout -dates | grep
notAfter |
awk 'BEGIN { FS="=" } { print $2 }')"
You already defined expiry_date(), so why not use it here.
expiry_date=$(expiry_date "$1")
if [[ "$(date --version 2>/dev/null)" == *"GNU"* ]] then # Linux (or at least GNU) expiry_epoch_seconds=$(date --date="${expiry_date}" "+%s") else # Assuming the Mac version: expiry_epoch_seconds=$(date -jf '%b %e %H:%M:%S %Y %Z'
"${expiry_date}"
"+%s") fi
Testing for "GNU" string can be done more simply using grep.
if date --version 2>/dev/null | grep -q GNU; then ... else ... fi
function tlsversions() { successful="" failed="" for tlsversion in ssl2 ssl3 tls1 tls1_1 tls1_2 tls1_3 do success=$(echo | ${OPENSSL} s_client -connect "${1}":443 -${tlsversion}
/dev/null 2> /dev/null ; echo $?) if [ ${success} -eq 0 ] then successful="${tlsversion} ${successful}" else failed="${tlsversion} ${failed}" fi
Testing if a command succeeded or failed can be done in-line.
if echo | ${OPENSSL} s_client -connect "${1}":443 -${tlsversion} &>/dev/null; then successful=... else failed=... fi
Also, do you really need to send empty line to openssl? Maybe you can redirect stdin from /dev/null as well, like
openssl ... </dev/null ...
That will reduce 3 subshells to 0.
General observation:
1. You don't need quotes in variable assignments like var="$(...)" var="$var1"
2. The following tests are the same. They both tests if var is empty. [ "$var"x = x ] [ -z "$var" ]
3. Testing if command succeeded or failed can be done in-line. if command1 | command2 | command2; then ... else ... fi
4. Case statement is usually better than if statement. eg. if [[ "$var" == glob ]]; then ... fi vs case $var in glob) ... ;; esac Note the missing quotes in case, too. You don't need it. -- William Park <opengeometry@yahoo.ca> --- Post to this mailing list talk@gtalug.org Unsubscribe from this mailing list https://gtalug.org/mailman/listinfo/talk
-- Giles https://www.gilesorr.com/ gilesorr@gmail.com

On Mon, 12 Aug 2019, Giles Orr via talk wrote:
Well damn.? That's a lot of very good suggestions.
I will dispute one of them: you said (more than once I think) that I don't need to quote variables.? You are technically correct ... right up until a variable value has a space in it.? Then everything goes to hell in a handbasket.?
Yes, always quote them. And it is not only spaces that can be a problem; several other characters are special to the shell and can cause problems. But it is not necessary to use braces unless you need more than straight expansion: echo "$var" not: echo "${var}" -- Chris F.A. Johnson <http://cfajohnson.com/> =========================== Author: =============================== Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress) Pro Bash Programming: Scripting the GNU/Linux shell (2009, Apress)

| From: William Park via talk <talk@gtalug.org> | 1. You don't need quotes in variable assignments like | var="$(...)" | var="$var1" True. Even if var1 has whitespace. But the quotes are harmless. The rule I aspire to following: Quote all shell variable references EXCEPT when they must not be quoted (rare). It's a lot easier than knowing the very odd rules applying to assignment and other special contexts. Why is assignment odd? Because, syntactically, it is a kind of word (an ASSIGNMENT_WORD according to POSIX). | 2. The following tests are the same. They both tests if var is empty. | [ "$var"x = x ] | [ -z "$var" ] I like -z Superstitiously, I would write [ "x$var" = x ] instead of [ "$var"x = x ] I would otherwise worry that if $var started with, say, -, funny things might happen. | 3. Testing if command succeeded or failed can be done in-line. | if command1 | command2 | command2; then | ... | else | ... | fi When I learned sh (long before POSIX) I think that the Bourne Shell set the exit status of a pipeline to the exit status of the first command. So I'm (needlessly) nervous about what the exit status of a pipeline is. BASH has an option to have a pipeline fail if any component fails. Seems useful (but not portable): -o pipefail Speaking of useful bash options, I always turn on these two options in my BASH scripts -e stop dead when a command returns an error in an untested context -u consider a reference to an undefined variable to be an error These catch a lot of errors that might otherwise go unnoticed. | 4. Case statement is usually better than if statement. eg. | if [[ "$var" == glob ]]; then | ... | fi | vs | case $var in | glob) ... ;; | esac | Note the missing quotes in case, too. You don't need it. I think that [[ ]] is a BASHism. I presume that it has advantages over [ ] but I don't know them. In the old days, test (AKA [ ]) wasn't built-in and so case was faster. This isn't true of modern shells.

On Sat, 10 Aug 2019 at 11:46, Giles Orr <gilesorr@gmail.com> wrote:
This may be seen as self-promotion - that's not totally wrong. But I think this may also be useful to others and (as I acknowledge in the blog post) I'm quite pleased with the resultant script.
Over the past year and a half I've slowly developed a shell script that gives a concise summary of the state of TLS and HTTP(S) on a given website. It looks like this:
$ tlsdetails google.ca Using OpenSSL: /usr/bin/openssl Expiry Date: Oct 27 17:27:07 2019 GMT (78 days) Issuer: Google Trust Services, CN TLS Versions: tls1_3 tls1_2 tls1_1 tls1 (tried but unavailable: ssl3 ssl2 ) HTTP Version: 2
I first started work on it after a couple embarrassing certificate expiries. It then grew to check the Issuer, TLS versions, and more recently whether or not a site supports HTTP2.
(The pointer to the OpenSSL version is shown because the script will also run on Mac, and their version of 'openssl' is problematic at best. That line is of course easy to remove if you don't like it.)
If you're interested, you can find the details here:
https://www.gilesorr.com/blog/tls-https-details.html
Any suggestions to improve the script would be most welcome.
Having solicited suggestions for improvement, I got more than I bargained for (but it was all good!). It took a while, but I've incorporated most of the suggestions: https://www.gilesorr.com/blog/tls-https-details2.html -- Giles https://www.gilesorr.com/ gilesorr@gmail.com

On Fri, Sep 13, 2019 at 09:22:54AM -0400, Giles Orr via talk wrote:
Having solicited suggestions for improvement, I got more than I bargained for (but it was all good!). It took a while, but I've incorporated most of the suggestions:
Hmm, minor personal irritant about variable assigment: var=$(...) is enough. You don't need to do var="$(...)" Eg. $ a="11 * 22" $ b=$(echo "$a") $ c="$(echo "$a")" $ declare -p a b c declare -- a="11 * 22" declare -- b="11 * 22" declare -- c="11 * 22" -- William Park <opengeometry@yahoo.ca>

| From: William Park via talk <talk@gtalug.org> | Hmm, minor personal irritant about variable assigment: | var=$(...) | is enough. You don't need to do | var="$(...)" I think that getting quotes right in sh is hard. I support the simplest rule that works: Always double-quote a $ thing UNLESS it must not be quoted. The case you point out may be quoted, so I would quote it.

On Sat, 14 Sep 2019, D. Hugh Redelmeier via talk wrote:
| From: William Park via talk <talk@gtalug.org>
| Hmm, minor personal irritant about variable assigment: | var=$(...) | is enough. You don't need to do | var="$(...)"
I think that getting quotes right in sh is hard. I support the simplest rule that works:
Always double-quote a $ thing UNLESS it must not be quoted.
The case you point out may be quoted, so I would quote it.
The only time an assignment needs to be quoted is when it contains literal whitespace. Using quotes on an assignment is just as silly as always using braces: echo "${var}" You don't always do it just because sometimes it is needed. -- Chris F.A. Johnson <http://cfajohnson.com/> =========================== Author: =============================== Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress) Pro Bash Programming: Scripting the GNU/Linux shell (2009, Apress)

On Sat, Sep 14, 2019 at 10:02:46AM -0400, D. Hugh Redelmeier via talk wrote:
| From: William Park via talk <talk@gtalug.org>
| Hmm, minor personal irritant about variable assigment: | var=$(...) | is enough. You don't need to do | var="$(...)"
I think that getting quotes right in sh is hard. I support the simplest rule that works:
Always double-quote a $ thing UNLESS it must not be quoted.
The case you point out may be quoted, so I would quote it.
Extra quotes distract your eyes, makes it difficult to read or spot a bug. It's like always carrying an opened umbrella (because you can), when you should do it only when it rains. -- William Park <opengeometry@yahoo.ca>

On Sun, 15 Sep 2019 at 11:01, William Park via talk <talk@gtalug.org> wrote:
On Sat, Sep 14, 2019 at 10:02:46AM -0400, D. Hugh Redelmeier via talk wrote:
| From: William Park via talk <talk@gtalug.org>
| Hmm, minor personal irritant about variable assigment: | var=$(...) | is enough. You don't need to do | var="$(...)"
I think that getting quotes right in sh is hard. I support the simplest rule that works:
Always double-quote a $ thing UNLESS it must not be quoted.
The case you point out may be quoted, so I would quote it.
Extra quotes distract your eyes, makes it difficult to read or spot a bug. It's like always carrying an opened umbrella (because you can), when you should do it only when it rains.
We covered this the first time I posted about the script - clearly there are some strongly held opinions on the subject. I'm going to state mine once. If you have a variable called "a" and another called "ab" and you type "$ab" the shell script, you'll get the contents of variable "ab" not the contents of variable "a" followed by the letter "b". So I _always_ put braces around my variable names - even though it's a pain to type and not particularly beautiful. It's syntactically correct and I won't ever get an unexpected error. My thinking is the same about quoting. filename="/var/log/apache.log" cat $filename (Never mind it's a contrived example.) That works just fine. I didn't brace or quote $filename. And - as I said last time - everything goes swimmingly right up until someone edits your file, or gives it some input such that the filename variable includes a space. And then - if you're lucky - you get a "file not found" error, but depending on your code the error may be much more obscure. Which is bad enough if you have to dig out the error, and far worse if the script is in the hands of someone who has no Bash knowledge. I choose to use the quotes and braces as a precaution against possible future problems. Some people don't, and that's fine. But what I'm doing isn't "wrong" (it's valid and safe syntax), so I don't think it's worth a lot of debate. -- Giles https://www.gilesorr.com/ gilesorr@gmail.com
participants (8)
-
Chris F.A. Johnson
-
D. Hugh Redelmeier
-
David Mason
-
Dhaval Giani
-
Giles Orr
-
Jason Shaw
-
Stewart C. Russell
-
William Park