0

I need a bash script to select 2 random nameservers from a list. This is what I have that is not working - I get an error on the line "$(($RANDOM % ${SIZE}))" and I can't figure out why.

NAMESERVERS="x.x.x.x x.x.x.x x.x.x.x x.x.x.x"
SIZE=${#NAMESERVERS[@]}
# select 2 random entries
NS_IDX=$(($RANDOM % ${SIZE}))
NS_IDX2=${NS_IDX1}
while [ "${NS_IDX1}" == "${NS_IDX2}" ]
do
   NS_IDX2=$(($RANDOM % ${IDX_RANGE}))
done
NS_IP1=${NAMESERVERS[${NX_IDX1}]}
NS_IP2=${NAMESERVERS[${NX_IDX2}]}

Then I echo NS_IP1 and NS_IP2 to /etc/resolv.conf

kathyl
  • 3
  • 1
    I think the line NS_IDX=$(($RANDOM % ${SIZE})) is ok, $SIZE has a value and it isn't zero, but in the line NS_IDX2=$(($RANDOM % ${IDX_RANGE})), $IDX_RANGE is null, this gives an error (maybe it has a value at that point). If you want NAMESERVERS as an array, declare it as NAMESERVERS=(x.x.x.x x.x.x.x x.x.x.x x.x.x.x). The while command is missing a closing ], maybe a typo? – Paulo Aug 08 '23 at 14:00
  • "I get an error on the line" can you add the info about the error? What does the error say? – Luuk Aug 08 '23 at 14:14
  • ${NX_IDX1} and ${NX_IDX2} are only used on the last two lines of your script? – Luuk Aug 08 '23 at 14:23
  • @paulo - yes the missing ] in the while statement is a typo, sorry.

    For the error, the message is "7: arithmetic expression: expecting primary: "%81[@]"

    I wonder if part of the problem is that the IP addresses are not being interpreted as IPs, but one character at a time.

    Yes, i echo those ip's out to /etc/resolv.conf. I could echo them out using "${NAMESERVERS[${NS_IDX1}]} "

    – kathyl Aug 08 '23 at 14:32
  • Can you use [edit] to correct that typo ? – Luuk Aug 08 '23 at 15:28
  • If you want to use $RANDOM then you need a shell that supports it. A proper shebang is advised, e.g. #!/bin/bash -. Unless you are sourcing the script in Bash in order to use the variables after the script finishes; if so, then the lack of shebang is fine. – Kamil Maciorowski Aug 08 '23 at 17:28
  • Yes, I' using #! /bin/bash at the beginning of my script. – kathyl Aug 08 '23 at 18:09
  • @kathyl Are you running the script with the sh command? If so, that overrides the shebang and runs it in plain sh, which probably doesn't have $RANDOM. Also, the assignment to NAMESERVERS is not creating an array, just a plain string with spaces; use NAMESERVERS=(x.x.x.x x.x.x.x x.x.x.x x.x.x.x) instead (the parentheses are what tells bash to make an array). I'd also recommend running your script through shellcheck.net as a sanity-check. Finally, it's safest to use lower- or mixed-case variable names, to avoid conflicts with the many special all-caps vars. – Gordon Davisson Aug 09 '23 at 19:23

1 Answers1

2

If you can use GNU shuf then a simple method is this:

#!/bin/sh -
<<EOF shuf -n 2
nameserver 8.8.8.8
nameserver 4.4.4.4
nameserver 1.1.1.1
nameserver 1.0.0.1
nameserver 9.9.9.9
nameserver 208.67.222.222
EOF

I embedded an example list of nameservers in the shell code as a here document. If you want to separate code from data, save the list as nameservers and then:

<nameservers shuf -n 2

xor

shuf -n 2 nameservers

Each of the above commands is so simple, that a person familiar with shuf may even prefer typing it on demand instead of creating a script.

Redirect the output to /etc/resolv.conf if this is what you want. Use this trick with tee if you need sudo. Example:

# WARNING! This will overwrite your resolv.conf
<nameservers shuf -n 2 | sudo tee /etc/resolv.conf