74
read /dev/urandom 3

The above is not working..How can I read random bytes from /dev/urandom in bash?

7 Answers 7

65
random="$(dd if=/dev/urandom bs=3 count=1)"

if specifies the input file, bs the block size (3 bytes), and count the number of blocks (1 * 3 = 3 total bytes)

9
  • 1
    @Flimzy,how does $() work?
    – linux
    Jun 23, 2011 at 6:07
  • 2
    It treats the output of a command like a variable. Note: That's a bashism. If you're not using bash, you may need to use `` instead. `` is more universal, but I think $() is easier to read.
    – Flimzy
    Jun 23, 2011 at 6:08
  • 1
    @Flimzy,It treats the output of a command like a variable.,you actually mean as string,right?
    – linux
    Jun 23, 2011 at 6:14
  • 2
    A variable can be a string... or a number. It treats it as a variable... then depending on context, it's treated like a string, or a number.
    – Flimzy
    Jun 23, 2011 at 6:27
  • 1
    $() is pretty universal, not bash-specific. BTW, be careful you don't run into limitations on what characters the shell can store in variables -- for example, the version of bash I tested with leaves out nulls (\x00) from the string. Jun 23, 2011 at 13:13
70
head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9~!@#$%^&*_-' | fold -w 3 | head -n 1

(If you want literal dash characters, the dash character must go at the end of the string as done above, as opposed to *-_).

And to explain what gets done due to the above set of commands:

  1. head -c 500 /dev/urandom: Obtain the first 500 characters (bytes) from /dev/urandom.
  2. tr -dc 'a-zA-Z0-9~!@#$%^&*_-': Remove all but the characters specified in 'a-zA-Z0-9~!@#$%^&*_-' from the output of the first command.
  3. fold -w 3: Format the output of the second command such that it has 3 characters per line.
  4. head -n 1: Display the first line of the result of the third command on stdout.
7
  • 1
    He's looking for 3 bytes...
    – Chris S
    Feb 21, 2013 at 16:56
  • 1
    3 plus exact pattern
    – ADM
    Feb 21, 2013 at 17:05
  • 4
    Great! There are also the char class names ([:graph|print|etc:]) available for the tr func, and it could be further simplified by replacing the fold -w 3 | head -n 1 by a head -c 3 if the new line char is not needed at the end.
    – Zimmi
    Dec 14, 2014 at 22:39
  • 6
    If the system's default encoding is multibyte (e.g. UTF-8) then tr will fail with an Illegal byte sequence error. To fix that, use the "C" encoding; change the command to: head -c 500 /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9~!@#$%^&*_-' | fold -w 3 | head -n 1
    – devstuff
    Nov 10, 2015 at 17:06
  • 2
    What is the purpose of grabbing 500 bytes at the beginning? Don't you obtain the same result with: cat /dev/urandom | tr -dc 'a-zA-Z0-9~!@#$%^&*_-' | fold -w 3 | head -n 1
    – philraj
    Aug 9, 2019 at 15:49
44

Please check man od.

You can use, for example

od -vAn -N4 -tu4 < /dev/urandom

to generate unsigned decimal 4 bytes random numbers.

2
  • 2
    Ekrem, welcome to SF. I don't normally much favour new answers to long-accepted questions, but this is genuinely different from all previous answers, and has some real advantages - nice! +1 from me, and I hope you stay around SF and contribute like this for some time to come.
    – MadHatter
    Sep 1, 2015 at 8:00
  • I really like this way of generating random strings, it's much more efficient.
    – Jaakko
    Apr 20, 2020 at 11:06
27

Here's one that creates base64 strings, note that even though they are limited to base64 strings, the padding is removed from them, so you can't decode them, you probably won't need it anyway.

 cat /dev/urandom | base64 | head -c 5

Replace 5 with the number of chars you'd like.

If you however need to decode them for some reason, move base64 to the end of the pipe. It will then collect 5 chars from urandom and base64 encode it with the right padding, but the final string may be longer than what you wanted due to padding.

cat /dev/urandom | head -c 5 | base64
6
  • This is not exactly what the question was asking for. Your answer might still be useful, but the question doesn't have enough context to say for sure.
    – kasperd
    Jan 4, 2015 at 10:23
  • 2
    @kasperd The question asks (in the title) how to read N random characters from /dev/urandom but in the body it asks for reading bytes. I agree there is an inconsistency. I came to this question from Google for reading characters and I think that it may help the future visitors as an option. Jan 4, 2015 at 14:31
  • 1
    Using cat will read far more than a given amount N chars, and can deplete the entropy. Not useful answer.
    – DrBeco
    Mar 20, 2017 at 18:52
  • 1
    While Dr Beco is correct that this is an abuse of cat since both base64 and head can take a filename as an argument, in this case it works and shouldn't deplete the entropy. See stackoverflow.com/questions/10031344/…
    – J.Money
    Mar 20, 2017 at 22:34
  • 4
    Hey! its yet another useless use of cat. $ head -c 5 /dev/urandom | base64 produces exactly the same output. Oct 2, 2017 at 23:42
15

The easiest solution would be as simple as:

$ head -cN /dev/urandom
2
  • 2
    What does this add to the answers already given?
    – MadHatter
    Sep 1, 2015 at 8:03
  • 10
    simpler invocation Jun 27, 2016 at 19:08
11

Try this: dd if=/dev/urandom bs=1 count=3

If you want to put the result in $variable:

variable=`dd if=/dev/urandom bs=1 count=3`

Do note that it'll probably not be printable.

1
  • Can the command also be uses in order to read 3 random bytes of binary data as well? Apr 26, 2018 at 21:32
1

The following command generates random characters

</dev/urandom tr -dc 'A-Za-z0-9!"#$%&\(\)*+,./: ;<=>?@\[\]^_`{|}~-' | head -c 15  ; echo

from all the ASCII Printable characters and only takes 15 head characters (or any number that you specifies) from it.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .