≡ Menu

Bash Shell Generate Random Numbers

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

Tweet itFacebook itGoogle+ itPDF itFound an error/typo on this page?

{ 18 comments… add one }

  • Deluxe April 27, 2010, 11:59 pm

    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.

  • Philippe Petrinko April 28, 2010, 1:37 pm

    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]

  • Philippe Petrinko April 28, 2010, 1:39 pm

    Then if you want a random integer belonging to [0;200],
    you may use:

    echo $(( n %= 201))

  • Paul Dubuc April 30, 2010, 2:31 pm

    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=$$

  • Erik May 10, 2010, 7:06 pm

    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

  • Mark Szymanski August 27, 2010, 1:46 am

    Is there any way to do this with a custom random seed?

  • Philippe Petrinko August 27, 2010, 7:32 am

    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?

    • b April 10, 2015, 9:59 pm

      actually it’s between 100 and 299.

  • ravi July 27, 2011, 5:43 am

    really nice

  • Dago February 12, 2012, 5:47 pm

    #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)))

  • Zdendo March 20, 2012, 1:08 am

    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

  • Philippe Petrinko March 20, 2012, 9:26 am

    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

  • Satish June 4, 2012, 12:51 pm

    Hi
    that was useful, didn’t know there was more than one method to generate random number.

  • ksaver August 29, 2012, 7:20 pm

    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!

  • none February 2, 2013, 6:16 am

    in a simplest exposure:
    $((RANDOM%offsetFromLowest+Lowest))

  • Roel May 9, 2014, 3:20 am

    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

  • Roel Van de Paar November 17, 2014, 9:26 pm

    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

  • David Goodwin May 18, 2015, 1:08 pm

    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).

Leave a Comment