Using /dev/random, /dev/urandom to generate random data
You can use od
to get numbers out of /dev/random
and /dev/urandom
.
For example,
2 byte unsigned decimal integers,
$ od -vAn -N2 -tu2 < /dev/urandom
24352
1 byte signed decimal integer,
$ od -vAn -N1 -td1 < /dev/urandom
-78
4 byte unsigned decimal integers,
$ od -vAn -N4 -tu4 < /dev/urandom
3394619386
man od
for more information on od
.
Some shells (e.g. bash(1)
) have a $RANDOM
"variable" that gives random numbers.
Shelling out to od
is slow. Using the built-in bash function is 100s of times faster. Would you like a 60-bit random integer? Do this:
((RND=((RANDOM<<15|RANDOM)<<15|RANDOM)<<15|RANDOM))
That will give you a random number in the range of 0 to 1,152,921,504,606,846,975. You can scale that down with a modulo division to whatever range you want.
Here's a practical example. Let's say, I want to read one random sector from my hard disk, for example, to wake up the disk from a standby state. I can do this:
#!/bin/bash
DEV=/dev/sda # Let's say that this is the device we want to spin up.
# Get the device geometry...
read -d- SIZE64 BS <<<$(blockdev --getsize64 --getbsz $DEV)
((SECTORS=SIZE64/BS)) # The total number of $BS-sized sectors on that device.
((RND=(RANDOM<<15|RANDOM)<<15|RANDOM)) # Generate a 45-bit random number.
((SECT=RND%SECTORS)) # The random sector that we will now read...
dd if=$DEV of=/dev/null bs=$BS skip=$SECT count=1 >/dev/null 2>&1
Done.
(Note: In this example I decided that a 45-bit random integer would be more than enough, and also, a tiny little bit faster than using 60 bits.)
Update:
To give some quantitative backup for the above speed claim:
~# time for i in {1..10000} ;do RND=$(od -An -N7 -tu8 /dev/urandom) ;done
real 0m45.647s
user 0m17.540s
sys 0m28.807s
~# time for i in {1..10000} ;do ((RND=((RANDOM<<15|RANDOM)<<15|RANDOM)<<15|RANDOM)) ;done
real 0m0.112s
user 0m0.105s
sys 0m0.007s