create an array of multiple multi-line text for script to use..

Rob

Administrator
Staff member
Joined
Oct 27, 2011
Messages
915
Reaction score
1,736
Credits
1,129
So, main purpose of this is so a QA guy can run this script to update /etc/hosts on one of the qa-test VMs to ensure they're hitting the correct cluster of hosts.. I grabbed most of this from two stackexchange answers:

The /etc/hosts stuff:
https://unix.stackexchange.com/questions/60549/etc-hosts-file-refer-to-another-configuration-file

The part listing out files to use to insert:
https://askubuntu.com/questions/682095/create-bash-menu-based-on-file-list-map-files-to-numbers

Currently, the script looks in /etc/hosts.d/ and creates a list of available files to insert into /etc/hosts and replace the old content between two markers..

example of one of the hosts.d files - this one would be called 'westus-prod'
Code:
111.222.333.444     app1.domain.com     # westus-prod
111.222.333.444     app2.domain.com     # westus-prod

It works great!

However, I would instead rather have the user pick from a list of options that are contained in the script itself instead of maintaining all the different /etc/hosts.d files..

I probably just need to think harder here, i'm sure something like this would work, but i'm blanking on listing the choices and inserting them into the /etc/hosts file part.. :
Code:
westus-prod=(
111.222.333.444 app1.domain.com #westus-prod
111.222.333.444 app2.domain.com #westus-prod
);

centralus-prod=(
222.111.222.333 app1.domain.com #centralus-prod
222.111.222.333 app2.domain.com #centralus-prod
);

Here's the script
Code:
#!/bin/bash

files=( /etc/hosts.d/*)
shopt -s extglob

string="@(${files[0]}"
for((i=1;i<${#files[@]};i++))
do
    string+="|${files[$i]}"
done
string+=")"

select file in "${files[@]}" "quit"
do
    case $file in
    $string)
sudo cp /etc/hosts "/etc/hosts.bak.$(date +%Y%m%d%H%M%S)" && \
    (
        sed -n '1,/^# CUSTOM BEGIN/{/^# CUSTOM BEGIN/!p;}' /etc/hosts; \
        echo "# CUSTOM BEGIN"; \
        cat "$file"; \
        echo "# CUSTOM END"; \
        sed -n '/^# CUSTOM END/,${/^# CUSTOM END/!p;}' /etc/hosts; \
    ) | \
    sudo tee /etc/hosts.new | \
    sed -n '/^# CUSTOM BEGIN/,/^# CUSTOM END/p' && \
        sudo mv /etc/hosts.new /etc/hosts

        break;
        ;;
  
    "quit")
        exit;;
    *)
        file=""
        echo "Please choose a number from 1 to $((${#files[@]}+1))";;
    esac
done
 
Last edited:


OP
Rob

Rob

Administrator
Staff member
Joined
Oct 27, 2011
Messages
915
Reaction score
1,736
Credits
1,129
Working from the bottom up.. still would need to figure out how the user can select from a list of arrays, but this kind of works to print them out, which splits into two lines, but creates a space before the 2nd line..

I guess i could put them into a tmp file, then use sed or something to remove beginning white space?

Code:
#!/bin/bash

westus_prod=(
111.222.333.444 app1.domain.com \# westus_prod\\n
111.222.333.444 app2.domain.com \# westus_prod
);

centralus_prod=(
222.111.222.333 app1.domain.com \# centralus_prod\\n
222.111.222.333 app2.domain.com \# centralus_prod
);

( IFS=$'\n'; echo -e "${centralus_prod[@]}" )
 
Last edited:
OP
Rob

Rob

Administrator
Staff member
Joined
Oct 27, 2011
Messages
915
Reaction score
1,736
Credits
1,129
Meh - i think i'll maybe create the files at the top of the script, then display them, let the user choose, once everything is done, clean them up.

Still a fun script if someone can figure out how to choose from the arrays, update /etc/hosts a bit cleaner lol :)
 

in1t5

New Member
Joined
May 13, 2020
Messages
13
Reaction score
4
Credits
121
I'm not completely understanding what you're up to... But to chose elements from an array I've just written:

Bash:
count=0
for $i in $array; do echo $i; count=$(($count+1)); done | nl
printf "Choose the element with a number: "
read -l choice

# Check if a number
[ "$choice" -eq "$choice" 2>/dev/null ] || echo "Not a num"
# Check if admitted number
[ "$choice" -le 0 ] || [ "$choice" -gt "$count" ] || echo "Out of bound"

filter="${choice}q;d"
line=$( for $i in $array; do echo $i; done | sed $filter )

# This is the array element chosen
echo $line

Edit some stuff and give it a try ;).

I would like to understand what you want to do better in order to write a clean version in POSIX sh.
 
$100 Digital Ocean Credit
Get a free VM to test out Linux!

Linux.org Hosting Donations
Consider making a donation

Staff online


Top