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
  • 2
  • 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](https://www.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
Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202