How To Generate Random Numbers In Linux/Bash Shell?

Sarath Pillai's picture
Generating Random Numbers

It is generally hard and complex ( well I cannot say that it is impossible ) to generate a real random number using a modern day computer. You might be thinking why is that?. It is because computer cannot just do anything random to be precise. If it did something really random, then we cannot call it a computer (A computer should only do a predefined set of tasks with complete predictability.)

 

Being said that, it is possible to introduce a certain level of randomness programmatically. These numbers, although appear random, they are generally called as Pseudo Random Numbers(Because these numbers are generated using mathematical operations, and are not really random).

 

However, there are techniques to generate a real true random number using a computer. These real random numbers are actually not generated by the computer itself. They are generated depending upon some external events. The best example can be the random movement of a users mouse on the computer screen(different positions of the mouse on the screen can be considered as a good source to generate a random number). Noise generated in the atmosphere are a good source of randomness. These can be fed to a computer using some external hardware, to generate random numbers.

 

Random numbers are used in computing for different purposes. One good example is for creating a strong encryption key (the key needs to be as random as possible, so that predictability is less. The degree of predictability is often referred to as entropy in cryptography). Another use case can be to use a temporary number to represent something inside a program for a short period.

 

In this article we will not be discussing real and true random numbers, as that is outside the scope of this article. We will be discussing some methods that we can use inside scripts and small programs to generate random numbers.

 

Using Bash Inbuilt function to Generate Random Numbers:

 

This is not the best method available. But it is for sure the easiest method available to generate a random number in bash shell. Bash has a built in function which is accessible using a variable called RANDOM. Getting a random number is as simple as invoking that variable. Each time you invoke it, you will get a random number in the range of 0 to 32767.  It is limited to 32767, because RANDOM will only give you a 16 bit integer. Maximum you can go in 16 bit is 32767. Each time you invoke RANDOM variable in bash, you will get an integer in that range (shown below.)

 

root@localhost:~# echo $RANDOM
9535
root@localhost:~# echo $RANDOM
7950
root@localhost:~# echo $RANDOM
28426
root@localhost:~# echo $RANDOM
13670
root@localhost:~# echo $RANDOM
31479
root@localhost:~# echo $RANDOM
16235
root@localhost:~# echo $RANDOM
14345

 

Please keep the fact in mind that this method is not at all suited for any security related requirements. As the numbers generated are easily predictable. You can use several techniques with RANDOM variable to grab a bit more longer number(several examples are shown below).

 

root@localhost:~# echo $RANDOM$RANDOM
700226432
root@localhost:~# echo $RANDOM$RANDOM
2763530556

 

If you want you can lower the limit from 32767 to a lower number like 200 as shown below.

 

root@jenkins:~# ANOTHER_RANDOM=$(( $RANDOM % 200 + 1 ))
root@jenkins:~# echo $ANOTHER_RANDOM
194
root@jenkins:~# ANOTHER_RANDOM=$(( $RANDOM % 200 + 1 ))
root@jenkins:~# echo $ANOTHER_RANDOM
113

 

As shown above, you need to re-initialize the variable for the above to work. Else the value will get hardcorded inside the variable. So plan accordingly in the script (using a function is ideal).

 

Using /dev/random to generate random Numbers:

 

Linux kernel provides a random number generator. We can use this kernel feature to to create a random number. This feature is exposed to the user using a special file called /dev/random.

But how does kernel generate a random number?. A computer generates several subtle noises internally(basically environmental noise generated by computers, which cannot be easily predicted). Couple of things that kernel observes to generate randomness are "interval between keystrokes on keyboard", "time gap between CPU interrupts" etc. These things are very hard for an external person to guess, as these are specific to your computer environment. These random bits collected by the kernel from system noise is then stored in a pool called entropy pool. So basically when you access bits from /dev/random, you are actually accessing random bits collected by the kernel in the entropy pool.

If the entropy pool does not have enough random data to provide, you might encounter intermittent delay while accessing /dev/random. A workaround for this delay is to use /dev/urandom instead of /dev/random. But technically /dev/random is more random compared to /dev/urandom. Accessing /dev/random to gather random data is the best method possible without having any other external source of randomness other than your computer.

 

The best tool available in all linux distributions to access /dev/random is dd command. Remember the fact that the output generated by dd command from /dev/random file will be binary.

 

# dd if=/dev/random count=1
?E$??0+1 records in
0+1 records out
7 bytes (7 B) copied, 4.0658e-05 s, 172 kB/s

 

 

dd command is quite straight forward. The option if specifies input file to read bytes from. The option count=1 indicates the fact that we only need one byte of data from /dev/random file. And finally those strange looking values in the output above are binary data read from entropy pool (/dev/random). 

We do not need dd specific information shown in the output above, so lets use the linux standard mechanism and redirect it to black hole using dd if=/dev/random count=1 2>/dev/null. Still the gibbrish binary data is not that useful for us. Because we need a random number, and not a binary value. We need to convert that binary to integer, for which we will be using another command called od.  See the entire command below that will give a good random number by combining all of these

 

[root@ip-10-55-3-249 ~]# dd if=/dev/random count=1 2>/dev/null | od -t u4 | awk '{print $2}' | head -1
991641864
[root@ip-10-55-3-249 ~]# dd if=/dev/random count=1 2>/dev/null | od -t u4 | awk '{print $2}' | head -1
4145171965
[root@ip-10-55-3-249 ~]# dd if=/dev/random count=1 2>/dev/null | od -t u4 | awk '{print $2}' | head -1
969523131

 

Not satisfied with the length of the random number generated above? Want a much more bigger random number? Or a small random number?. All that is possible by simply changing u4 to u2, u3 and u8. Try it out (see below).

 

root@localhost:~# dd if=/dev/random count=1 2>/dev/null | od -t u8 | awk '{print $2}' | head -1
19132691377836

 

 

If /dev/random is taking much longer, simply change it to /dev/urandom.

 

root@localhost:~# dd if=/dev/urandom count=1 2>/dev/null | od -t u8 | awk '{print $2}' | head -1
13649141904838558922

 

Using awk to generate Random Number:

Awk is a powerful tool available in Linux. It has an internal random number generator. It has the capability to generate a random number between 0 and 1. Yes it is floating point.

 

awk 'BEGIN{ srand(); print rand() }'

 

 

The above will generate a random number between 0 and 1. The number might repeat if you try it fast back to back. To solve the problem, you can actually provide our own random seed value. Lets use something that we already learned here. Lets use the RANDOM variable of bash as a seed value to awk.

 

root@jenkins:~# awk -v s=$RANDOM 'BEGIN{ srand(s); print int(1000000000000 * rand()) }'
405677268470
root@jenkins:~# awk -v s=$RANDOM 'BEGIN{ srand(s); print int(1000000000000 * rand()) }'
624237668991

 

 

We have first configured a variable named s which has the RANDOM number value, and then that is fed as seed to srand. The random number generated by RANDOM (ie: s variable) acts as a starting point for generating a random number. The above shown one liner will create a random number less than 1000000000000.

 

Another relatively lesser used tool is shuf. You can use shuf command as shown below to generate a random number in the range you like.

 

root@localhost:~# shuf -i 1000-1000000000 -n 1
236133356

 

If you do not trust any of these, you can also try using a Perl or Python one liner. A perl method is shown below.

 

perl -e 'print int(rand(1000000000000-100000)) + 100000'
663125101011

 

 

The above will produce a random number between 100000 and 1000000000000. You can include that line in your bash shell script as well, and assign the output to a variable to use the random number. Similarly a python based method is shown below.

 

root@localhost:~# python -S -c "import random; print random.randrange(10000,100000000)"
16452640
root@localhost:~# python -S -c "import random; print random.randrange(10000,100000000)"
1764075
Rate this article: 
No votes yet

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Type the characters you see in this picture. (verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.