How do I create or generate random numbers (sequence of numbers that lack any pattern), under Bash shell?
The bash shell offers $RANDOM variable (it also works with ksh). From the bash man page:
Each time this is referenced, a random integer between 0 and 32767 is generated. The sequence of random numbers may be initialized by assigning a value to RANDOM. If RANDOM is unset, it loses its special properties, even if it is subsequently reset.
To view $RANDOM, enter:
$ echo $RANDOM
Sample outputs:
11799
You can use the bash loop as follows to test random numbers:
for i in {1..5}; do echo $RANDOM; done |
Sample outputs:
32340 18591 32100 15165 19743
You can store it to a variable as follows:
#!/bin/bash n=$RANDOM echo "My move: trying $n..." |
You can have a random integer number within a certain range as follows:
n=$RANDOM # display a random integer <= 200 echo $(( r %= 200 )) # display random number between 100 and 200. echo $((RANDOM%200+100)) |
Here is a sample shell script to find out random TCP port:
#!/bin/bash # Set a trap to detect spam bots at port 80 # Find out random unused TCP port findRandomTcpPort(){ port=$(( 100+( $(od -An -N2 -i /dev/random) )%(1023+1) )) while : do (echo >/dev/tcp/localhost/$port) &>/dev/null && port=$(( 100+( $(od -An -N2 -i /dev/random) )%(1023+1) )) || break done echo "$port" } p=$(findRandomTcpPort) echo "Setting Honeypot @ port 80 and real Apache server at port $p..." # setHoneypot 80 # setApache $p |
Another shell script to setup a random wallpaper. You can call this one from your crontab:
#!/bin/bash # get images files=(/nas/download/share/fun/images/wallpapers/*.png) # find out random one n=${#files[@]} wallpaper="${files[RANDOM % n]}" # Kde3 command (may not work with kde4) # dcop kdesktop KBackgroundIface setWallpaper "$wallpaper" 5 # Gnome command gconftool-2 --type string --set /desktop/gnome/background/picture_filename "$wallpaper" |
Using /dev/urandom or /dev/random
The character special files /dev/random and /dev/urandom provide an interface to the kernel’s random number generator. You can use /dev/urandom as follows:
$ od -vAn -N4 -tu4 < /dev/urandom
Sample outputs:
2494028411
You can use /dev/random as follows:
$ od -An -N2 -i /dev/random
Sample outputs:
62362
Recommended readings:
See the following man pages:
man 4 random
man bash
man od



19 comment
Thanks for the tips. Two mistake though:
– ‘echo $(( r %= 200 ))’ should be ‘echo $(( n %= 200 ))’
– ‘echo $((RANDOM%200+100))’ return a number between 100 and 300, not 100 and 200 as commented above.
The example involving 200 is not a uniform distribution. The mapping function used is f(x) = x module 200. This input, x, is a uniform distribution. The output f(x) is not because the the size of the domain is a power of 2 and the size of the range is 200. if f(x) were random, the size of the domain would be a multiple of the size of the range. A power of 2 is never a multiple of 200. The following would be random: while (set I to $RANDOM) {if i < 200 then {echo $i; break;} }.
Nice topic.
Precision:
echo $(( n %= 200 ))
Will return an integer strictly less than 200.
I think that If you want to include 200, you could use:
echo $(( n %= 200 + 1))
But then, [n] will never be zero, it will belong to [1;200]
Then if you want a random integer belonging to [0;200],
you may use:
echo $(( n %= 201))
Like the man page excerpt above says, you can initialize the sequence by assigning an arbitrary number to RANDOM before using it. If you don’t want the same ‘random’ sequence each time you run the script, you should seed RANDOM by assigning an arbitrary number before using it. The process ID works well:
RANDOM=$$
OpenSSL can also be used as a source of random numbers, and is a good idea if the numbers are going to be used for cryptographic key generation or nonces. The generator used by OpenSSL uses a FIPS 140 approved algorithm and has been widely tested and reviewed.
OpenSSL on Unix systems will leverage available entropy from the OS RNG as part of it’s seed/start process.
Here are some sample commands – quoted from the “OpenSSL Command-line HOWTO”:
# write 128 random bytes of base64-encoded data to stdout
openssl rand -base64 128
# write 1024 bytes of binary random data to a file
openssl rand -out random-data.bin 1024
Cheers, Erik
ArtofInfoSec.com
Is there any way to do this with a custom random seed?
vivek,
There is a bug here:
# display random number between 100 and 200.
echo $((RANDOM%200+100))
This will display random number between 100 and 300 (not 200)
If you want to display random number between 100 and 200, use:
echo $((RANDOM%100+100))
Would you modify yor code above?
actually it’s between 100 and 299.
really nice
#Bug in ‘display random number between 100 and 200.’
echo $((RANDOM%200+100))
#For determine the random number between x and y is:
echo $((x + RANDOM%(y-x+1)))
Works good:
echo $(( RANDOM% ($maximal – $minimal) + $minimal ))
example: maximal=10 minimal=5 try it ;)
Or if you want numbers between 5 – 10, you can do this:
echo $(( RANDOM% 5 + 5 ))
5 – minimum, maximum is +5 bigger
Hi Vivek,
You may be overwhelmed or overloaded,
but you will also find that this page does not meet your quality standard.
1) As Dago said:
#To get random integer number between x and y, x and y beeing included as in [x;y] notation, use:
echo $((x + RANDOM%(y-x+1)))
2) Typo
There is still a typo here: echo $(( r %= 200 ))
Should be: echo $(( n %= 200 ))
3) Misunderstanding
Why do you use “%=” where “%” will be appropriate ?
That is: echo $(( n %= 200 ))
Should be: echo $(( n % 200 ))
KUTGW, I really appreciate your site – as usual, great work.
— Philippe
Hi
that was useful, didn’t know there was more than one method to generate random number.
Nice and instructive post!
I was looking for a way to seed the $RANDOM-ness in bash, and I found this can be done by setting the $RANDOM variable:
$ RANDOM=1
$ echo $RANDOM
16807
$ echo $RANDOM
15089
$ RANDOM=1
$ echo $RANDOM
16807
$ echo $RANDOM
15089
May be a good way for seeding randomness would be using time:
$ RANDOM=$(date +%s)
Thanks a lot!
in a simplest exposure:
$((RANDOM%offsetFromLowest+Lowest))
Nanosecond semi-random number generator
date +’%N’
Can also be used as $RANDOM shuffler:
RANDOM=$(date +’%N’)
$ RANDOM=$(date +’%N’)
$ echo $RANDOM
13967
$ RANDOM=$(date +’%N’)
$ echo $RANDOM
27211
Random entropy pool init with subsequent selection of some text to echo. ‘+’ should never hit (%3 + 1 == 1 to 3). Output will be 1,2 or 3.
RANDOM=`date +%s%N | cut -b14-19`;
case $[$RANDOM % 3 + 1] in 1) echo ‘1’;; 2) echo ‘2’;; 3) echo ‘3’;; *) echo ‘+’;; esac
I find ‘shuf’ to be a good solution. You can specify the range and how many numbers you want back, as well as a random source to make it repeatable when testing.
Example:
RANDOM=$(shuf -i 1-1000 -n 1)
although it’s probably as good as using ‘od’.
Using $RANDOM works, but technically won’t give you a very even distribution (as it’s between 0 and 32767 before you % 100 it or whatever).