1

I am trying to create a small script for creating simple, all-default Apache virtual host files (it should be used any time I establish a new web application).

This script prompts me for the domain.tld of the web application and also for its database credentials, in verified read operations:

read -p "Have you created db credentials already?" yn
case $yn in
    [Yy]* ) break;;
    [Nn]* ) exit;;
    * ) echo "Please create db credentials and then comeback;";;
esac

read -p "Please enter the domain of your web application:" domain_1 && echo
read -p "Please enter the domain of your web application again:" domain_2 && echo
if [ "$domain_1" != "$domain_2" ]; then echo "Values unmatched. Please try again." && exit 2; fi

read -sp "Please enter the app DB root password:" dbrootp_1 && echo
read -sp "Please enter the app DB root password again:" dbrootp_2 && echo
if [ "$dbrootp_1" != "$dbrootp_2" ]; then echo "Values unmatched. Please try again." && exit 2; fi

read -sp "Please enter the app DB user password:" dbuserp_1 && echo
read -sp "Please enter the app DB user password again:" dbuserp_2 && echo
if [ "$dbuserp_1" != "$dbuserp_2" ]; then echo "Values unmatched. Please try again." && exit 2; fi

Why I do it with Bash

As for now I would prefer Bash automation over Ansible automation because Ansible has a steep learning curve and its docs (as well as some printed book I bought about it) where not clear or useful for me in learning how to use it). I also prefer not to use Docker images and then change them after-build.

My problem

The entire Bash script (which I haven't brought here in its fullness) is a bit longer and the above "heavy" chuck of text makes it significantly longer - yet it is mostly a cosmetic issue.

My question

Is there an alternative for the verified read operations? A utility that both prompts twice and compares in one go?

Related: The need for $1 and $2 for comparison with an here-string

3
+50

How about a shell function? Like

function read_n_verify  {
    read -p "$2: " TMP1
    read -p "$2 again: " TMP2
    [ "$TMP1" != "$TMP2" ] &&
    { echo "Values unmatched. Please try again."; return 2; }
    read "$1" <<< "$TMP1"
}
read_n_verify domain "Please enter the domain of your web application" 
read_n_verify dbrootp "Please enter the app DB root password" 
read_n_verify dbuserp "Please enter the app DB user password"

Then do your desired action/s with $domain, $dbrootp, $dbuserp.

$1 is used to transport the variable name for the later read from the "here string", which in turn is used as it's easier here than a (could be used as well) "here document".

$2 contains the prompt (free) text, used last to allow for (sort of) "unlimited" text length.

Upper case TMP and [ ... ] && "sugar-syntax" (whatever this might be) are used by personal preference.

if - then - fi could be used as well and would eliminate the need for the braces that collect several commands into one single command to be executed as the && branch.

  • Passwords with trailing spaces and backslashes may be improperly read here. – Kusalananda Nov 25 '18 at 8:55
  • I think I miss just one more thing, if we read TMP1 and TMP2, into $2 how come there isn't a "clash" here and both still exist to be later checked by the if-then? – JohnDoea Jan 1 at 9:13
  • @Kusalananda this is a good point, thank you for pointing it out. – JohnDoea Jan 1 at 9:14
  • @JohnDoea Nothing is read into $2. The thing in $2 is used as part of the prompt. The variable whose name is in $1 is given the value of $TMP1 in the last read (which would be better written printf -v "$1" '%s' "$TMP1"). Also note that the positional parameters are local to the function and separate from the positional parameters in the main script. There is no clash between them. – Kusalananda Jan 1 at 10:23
1

I would do it like this:

#!/bin/bash
while [[ $string != 'string' ]] || [[ $string == '' ]] 
do
    read -p "Please enter the domain of your web application: " string
    echo "Please enter the domain of your web application: "
done 
Command 1
Command 2

Less typing.

Of course you would need a section like this for all of your questions.

Other than the way you have it and the way I have it, not really any more options.

  • Hi Michael. Why is there an echo after the read -p? Also, would you use while for command 1 and 2 and 3? I misunderstand the code. – JohnDoea Dec 17 '18 at 22:25
  • It outputs the string prompting the user without the newline before reading. @JohnDoea Those two commands would be the commands your passing the var's too, so no while loop. – Michael Prokopec Dec 18 '18 at 1:21
  • It is verifying that you typed it correctly. Comparing the read string with the response to the echo. If they don't mach the while loop continues till they do match. Once they match the next commands execute. And the variable string is retained to be used in the latter commands. – Michael Prokopec Dec 18 '18 at 1:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.