-   Linux - Newbie (
-   -   Shell script to increment IP variables into ranges using /29 /28 /26 etc? (

joecam1673 04-28-2011 01:45 PM

Shell script to increment IP variables into ranges using /29 /28 /26 etc?
So, I've been a member of this forum for a while and, as the header pointed out when I logged in today, I've never actually asked a questions. Usually I just scrape through the forums and google until I find someone who has already asked the question I have and piece together my own answers but I can't seem to make that happen this time so here goes...

I am trying to write a shell script that I thought would be relatively simple but isn't really coming together.

What I need is a script that adds an IP in what I assume would be to variables based on the "read -e" input and then a third variable thats the subnet shorthand (/29 or whatever also from read -e). Once thats in I'd like to use what I assume would be a while loop to not only increment the last octet of the IP but also run the command to add that IP to a vps the number of usable IP's in the subnet. So increment the last octet 5 times and run the command 5 times so I can just add a first IP and give its range. Doable? Any help or suggestions or even just pointing me toward a pertinent tut/tuts would be much appreciated.

Thanks for readin'

16pide 04-28-2011 03:38 PM

could you maybe give us something easier to read.
For example you might give us how the script would run:

Input your network address:
Here are the possible addresses:
etc ...

and if that's the script you want, then maybe this URL is useful:

grail 04-28-2011 10:54 PM

As per previous post, if you supply examples of your inputs and outputs it makes it much easier to assist.

The idea sounds fairly trivial (based on current information), so here is a link to help with learning scripting.

joecam1673 05-01-2011 10:55 AM

Basically I'm looking for this on a superficial level;

Please enter the name of the container to add IPs:ctxxxx
Please enter the first usable IP in the range:
Please enter the subnet:/29

Then it would use the vzctl set ctxxxx --ipadd --save (5 times, incrementing that last octet each time.)

Thanks for responding. I'll read over your links. They are much appreciated.


joecam1673 08-18-2011 06:42 PM

Here's what I came up with. Seems pretty dirty so if anyone has any best practice tips or whatever to help clean it up I'd welcome them gladly. Virtuozzo doesn't have a shell command to add IP ranges to VPS's so if anyone else uses it, here ya go. :)




echo -n "Please enter container name(ie ctxxxxx): "
read CT
echo -n "Please enter first IP in range: "
read IP
echo -n "Please enter subnet(ie /29): "

OCT1=$(echo $IP | cut -d "." -f1)
OCT2=$(echo $IP | cut -d "." -f2)
OCT3=$(echo $IP | cut -d "." -f3)
OCT4=$(echo $IP | cut -d "." -f4)

if [ "$SUBNET" == "/29" ]
                END=$(($OCT4 + 4))
        for IPFULL in `seq $OCT4 $END`
                vzctl set $CT --ipadd $OCT1.$OCT2.$OCT3.$IPFULL --save
elif [ "$SUBNET" == "/28" ]
                END=$(($OCT4 + 12))
        for IPFULL in `seq $OCT4 $END`
                vzctl set $CT --ipadd $OCT1.$OCT2.$OCT3.$IPFULL --save

grail 08-21-2011 07:57 AM

Initial suggestions are as follows:

1. You do not seem to check any of the user input

2. Are you never allowing more than 2 subnets? If we assume more, you can remove the ifs altogether:

(( END = OCT4 + ( 2 ** (32 - ${SUBNET#/} ))))
for (( IPFULL = OCT4; IPFULL <= END; IPFULL++ ))

3. The above leads me to question how you were calculating the END??

4. An alternative to your echo and cut routine:

set - ${IP//./ }
The above allows you to now refer to each segment using the positional parameter numbers, ie OCT1 = $1 (This of course assumes that IP has been checked and is a correct address format)

5. You can also use bash builtin substitution:

vzctl set $CT --ipadd ${IP%$4}$IPFULL --save
This assumes previous step has been provided

Hope some of this helps.

joecam1673 02-16-2013 08:43 PM

I know it's been ages since I originally posted this but I did find your response very helpfull. Thanks for the advise.

dariusrickard 02-17-2013 12:41 AM

nice thread. thanks for sharing that information. it was very informative.

David the H. 02-17-2013 04:40 PM

Here's a simpler way to chop up the address string:


$ address=

$ IFS='./' read -ra ipnums <<<"$address"

$ printf '%s\n' "${ipnums[@]}"

Now you have an array with five numbers in it. You could alternately supply five named variables, of course, for portability or better clarity.

string manipulations in bash

joecam1673 02-17-2013 07:11 PM

Good point. If you're going to change the field separator, this would be simpler still.

echo "${IP[@]}"

grail 02-18-2013 02:29 AM

Actually, whilst simpler you have missed the subnet option at the end which is after '/' hence your last array element would be something like:

echo ${IP[3]]

joecam1673 02-19-2013 06:15 AM

ohh, touche

David the H. 02-24-2013 04:41 PM

I would still maintain that using read is the cleaner option, since you don't have to modify IFS globally. It's generally a good idea to avoid doing that, since it usually means you also have to remember to change it back afterwards, and forgetting to do so can lead to unpleasant and difficult to diagnose side-effects.

It's also probably slightly faster, as only a single command is executed. Finally, as I mentioned, you can replace the array with individual variables, if it suits the script flow better.


IFS='./' read -r oct1 oct2 oct3 oct4 subnet <<<"$address"

All times are GMT -5. The time now is 11:03 AM.