I would like to generate a random string (e.g. passwords, user names, etc.). It should be possible to specify the needed length (e.g. 13 chars).

What tools can I use?

(For security and privacy reasons, it is preferable that strings are generated off-line, as opposed to online on a website.)

  • 1
    There are already good answers are at AskUbuntu. (I use apg personally.) – Sparhawk Sep 20 '15 at 13:07
  • 1
    @Sparhawk The AskUbuntu question/answers are more about listing tools. Please consider adding an answer here exhibiting how to use apg to generate a random string. – landroni Sep 20 '15 at 15:51
  • 1
    Be cautious about using random number generation on computers. Some are much less random than they appear, but telling the difference between 'good' and 'bad' random number generation is quite hard. – Sobrique Sep 21 '15 at 11:15
  • @Sobrique Excellent point about pseudo-random number generators (e.g. /dev/urandom). Would be nice to have some answers using true random number generators, based on e.g. random.org. – landroni Sep 21 '15 at 11:23
  • 53
    Joke answer: To generate a truly random string, place a new user in front of Emacs (or Vim) and ask them to exit. ;) – Wildcard Oct 30 '16 at 4:51

22 Answers 22


My favorite way to do it is by using /dev/urandom together with tr to delete unwanted characters. For instance, to get only digits and letters:

tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo ''

Alternatively, to include more characters from the OWASP password special characters list:

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

If you have some problems with tr complaining about the input, try adding LC_ALL=C like this:

LC_ALL=C tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 13 ; echo
  • 25
    Or do this: head /dev/urandom | tr -dc A-Za-z0-9 | head -c10 - This way is more accurate. You get 10 characters that are capitals, lowers, or digits – Brandin Sep 19 '15 at 8:47
  • 14
    The first head command might be problematic. It will output the first 10 lines from /dev/urandom, which means it will stop once it has seen the 10th newline. So the length of the output send to the tr command is random. It is possible that there will be less than 13 characters in the output from tr. I haven't computed the probability of this happening, the calculations are a bit tricky. – kasperd Sep 19 '15 at 22:40
  • 7
    Better do it like this: <dev/urandom tr -dc "$charset" | head -c "$length" – PSkocik Sep 20 '15 at 13:06
  • 3
    +1 Here's a quick attempt to include the other characters from the OWASP password special characters page, escaped for bash command line: tr -dc A-Za-z0-9\!\"#$\&\'\(\)\*+,-./\:\\\\\;\<=\>\?@[]^_`{\|}~ – Rup Jul 28 '16 at 10:26
  • 6
    +1 for the LC_ALL=C workaround. In my case head /dev/urandom | LC_ALL=C tr -dc A-Za-z0-9 | head -c 13) fixed the OSX tr problem just in place. – Camilo Sampedro Sep 28 '18 at 10:14

I am using the openssl command, the swiss army knife of cryptography.

openssl rand -base64 12


openssl rand -hex 12
  • 17
    rand -hex will limit the output to just 16 characters, rather than the 90+ on my keyboard. base64 is better because it's 64 characters, but it's not random (e.g. there are predictable padding patterns, and perhaps some characters appear more often than others). – Martin Tournoij Aug 27 '16 at 17:37
  • 2
    @Carpetsmoker: Note that the example openssl rand -base64 12 produces 16 characters of output (because 256 values are mapped to 64). And the hex example produces 24 characters. There's no loss in the case of the hex since it's a simple 1:2 mapping, but there might be a little in the base64 case since padding is used. The radix does not affect the randomness, it's the way one is mapped to another that does. (and the total bit count is much more important). – Dennis Williamson May 19 '17 at 20:29
  • 8
    This answer deserves more upvotes. urandom, pwgen, gpw, etc may or may not be available on your system; also in different environments, a policy that works on one may not work on another. It would be a pretty dysfunctional setup to not have openssl. Even better: openssl rand -base64 32 | tr -d /=+ | cut -c -16 That'll give you 32 char minus non-alphanum's and trimmed to 16 char length. Makes it easy to deal with as an admin. Users only have alphanums (which they tend to appreciate). The length is long enough that the removal of special chars don't overly impact the entropy. Golden. – zentechinc Sep 5 '17 at 16:34
  • 5
    Note that according to its manual, the openssl rand command is still a pseudo-random generator, therefore not cryptographically secure. This suited my needs, but may not suit the need of all applications, e.g. initializing IV as mentioned in another comment. – spikyjt Feb 25 '20 at 15:09
  • 3
    Note that the manual says openssl rand is a cryptographically secure pseudo random number generator (CSPRNG). – ZoFreX Mar 22 at 9:51

To generate a random password you can use pwgen:

pwgen generates random, meaningless but pronounceable passwords. These passwords contain either only lowercase letters, or upper and lower case mixed, or digits thrown in. Uppercase letters and digits are placed in a way that eases remembering their position when memorizing only the word.

Generate 7 passwords of length 13:

geek@liv-inspiron:~$ pwgen 13 7
Eu7Teadiphaec giepahl3Oyaiy iecoo9Aetaib4 phaiChae6Eivi athoo3igee8Co
Iphu4ufeDeelo aesoYi2lie9he 

As mentioned in the comments, you can avoid reducing entropy by using the -s argument (i.e. generate more secure, completely random but hard to remember passwords):

geek@liv-inspiron:~$ pwgen -s 13 7
eAfycrPlM4cYv 4MRXmZmyIVNBp D8y71iqjG7Zq7 FQRHcserl4R8O yRCUtPtV3dsqV
0vJpp2h0OrgF1 QTp7MKtJyTrjz 

To generate random user names you can use gpw:

This package generates pronounceable passwords. It uses the statistics of three-letter combinations (trigraphs) taken from whatever dictionaries you feed it.

Generate 7 passwords (user names) of length 13:

geek@liv-inspiron:~$ gpw 7 13
  • 28
    +1 for not reinventing the wheel. If you don't want the reduced entropy of the "pronounceable" constraint, simply use pwgen -s. – Nate Eldredge Sep 19 '15 at 16:21
  • 3
    Too bad pwgen is not included as part of standard bash release. – Craig Hicks Jun 6 '20 at 16:56

Here is how, I do it. It generates 10 characters random string. You can optimize it by replacing the "fold", with other string processing tools.

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 10 | head -n 1
  • 1
    +1 This answer is POSIXly correct, minus the use of /dev/urandom of course – Harold Fischer Feb 26 '19 at 3:17
  • Note that you also add a newline at the end. To fix that, and optimize by replacing fold -w 10 | head -n 1 with head -c10 – elomage Apr 7 at 7:17
  • I've been using this for years however in macOS Big Sur it breaks with "Input error" – hyperknot Apr 23 at 0:19

Inspired by Pablo Repetto I ended up with this easy to remember solution:

shuf -zer -n20  {A..Z} {a..z} {0..9}

-z avoids multi line output

-e echo the result

-r allow any character to appear multiple times

-n20 random string with a length of 20 characters

{A..Z} {a..z} {0..9} allowed char classes

shuf is part of the linux coreutils and widely available or at least been ported.

  • 2
    One problem here is "-z" because it doesn't "avoids multi line output" but appends a \0 instead of a newline to each string. Test it by appending "| od -xc". You can remove the zero chearacters with tr: shuf -zer -n20 {A..Z} {a..z} {0..9} | tr -d '\0' – Skeeve Jun 16 '20 at 5:37
  • To run this in fish shell, use bash -c 'shuf -zer -n20 {A..Z} {a..z} {0..9}' – baldrs Sep 1 '20 at 13:29

To generate password with the highest entropy possible with standard Linux tools that are built into every distribution I use:

< /dev/urandom tr -cd "[:print:]" | head -c 32; echo

This outputs all of the ASCII printable characters - from 32 (space) to 126 (tilde, ~). The password length can be controlled with the head's -c flag. There are also other possible character sets in tr (to not include the space, just characters 33-126, use [:graph:]).

  • 2
    In what way is this different from the existing answers? Specifically, herbert's comes to mind. – Fox Apr 27 '17 at 22:40
  • 5
    @Fox His solution uses hardcoded list of characters, which is not an encouraged programming practice because of code readability, compactness and cleanliness. Also some of the special printable ASCII characters could be interpreted by bash, not to mention the most obvious drawback of his one liner - if maximum entropy is desired, can one be sure that all of the available characters are included in the list? And that there are no duplicates which could possibly alter the tr's behaviour? His answer should be replaced by mine since you asked :) – drws Apr 29 '17 at 13:37
  • 2
    Many if not most web sites have restrictions on the characters that can be in a password, so hard-coding '[:print:]' doesn't feel any better to me than hard-coding the OWASP password special character list. I feel that almost every answer here could be improved by using a variable, but that is such a minor change that I'd only suggest an edit – Fox Apr 29 '17 at 13:54
  • 3
    < /dev/urandom tr -cd '[:graph:]'| tr -d '\\' | head -c 32; echo if you dont want ` characters in generated string. ` because is an escape character in many languages causes problems – mzzzzb Mar 8 '18 at 14:36
  • 2
    @RyanKrage :graph: already excludes space, so a better solution than :print:. – Dani_l Feb 16 '20 at 10:14

Depending on the level of randomness you want, you could simply go with bash's (also zsh and ksh, possibly others) builtin $RANDOM variable:

$ echo $RANDOM | tr '[0-9]' '[a-z]'
$ echo $RANDOM | tr '[0-9]' '[a-z]'

The methods reading directly from /dev/urandom are far simpler, but for the sake of completion, you could also use $RANDOM:

echo $(for((i=1;i<=13;i++)); do printf '%s' "${RANDOM:0:1}"; done) | tr '[0-9]' '[a-z]'

Important: this solution will only produce random strings using the first 10 letters of the alphabet. Whether or not that is enough for you depends on what you need this for.

  • How do you control the length of the generated string? – landroni Sep 19 '15 at 13:33
  • 1
    @landroni I don't think you can short of using a loop until you get the right length. $RANDOM will print a number between 0 and 32767. – terdon Sep 19 '15 at 13:36
  • I've tried running the command some 20 times, and I can never get anything longer than 4-5 chars... – landroni Sep 19 '15 at 13:38
  • 2
    @landroni thanks, I've added a way to specify length but it's not very good. I'd just use something like rand=$(head -c 100 /dev/urandom | tr -dc A-Za-z0-9 | head -c13) instead. – terdon Sep 19 '15 at 16:12
  • 1
    @SkippyleGrandGourou very good point. I added this to the answer, thanks. – terdon May 8 '19 at 11:30

Use xxd command to specify length (via -l) which both works in Linux and OS. https://www.howtoforge.com/linux-xxd-command/

xxd -l16 -ps /dev/urandom

APG is included by default on some Linux distributions.

To generate passwords from size 5 to 10 in subsets Special, Numeric, Capital and Lower, the command is:

apg -MSNCL -m 5 -x 10

And returns


As said by @landroni in comment.

  • 1
    Here are the options to generate random 14 letter passwords containing lots of special characters: apg -a1 -m14 – neuhaus Nov 11 '17 at 19:10

@Brandin explained in a comment to another answer how to get at most 100 bytes from /dev/urandom using head -c 100. Another way to do this is with dd:

tr -dc A-Za-z0-9 < /dev/urandom | dd bs=100 count=1 2>/dev/null

The 2>/dev/null at the end of the dd command is to suppress the "... records in / ... records out" output.

I'm not aware of any substantial advantages/disadvantages between these two methods.

I had an issue with both methods of tr complaining about the input. I thought this was because it didn't like receiving binary input, and hence suggested first filtering /dev/random with iconv -c -t US. However, Gilles suggested a different diagnosis and solution, which works for me:

LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | dd bs=100 count=1 2>/dev/null
  • For some reason the iconv solution maxes one CPU core and doesn't yield an output (I waited some 10s before killing it)... – landroni Sep 19 '15 at 9:38
  • On my Ubuntu 14.04 system iconv is provided by libc-bin 2.19. I'm not sure if it's the same iconv... – landroni Sep 19 '15 at 13:36
  • tr supports binary input. However a range like A-Z may be influenced by locale settings. Try LC_ALL=C tr … – Gilles 'SO- stop being evil' Sep 19 '15 at 20:27
  • 1
    @Gilles According to the POSIX spec it doesn't "support binary input". Only GNU tr does because it doesn't support multibyte at all (e.g. last time I checked it changing case was implemented by simply setting the sixth bit of every byte). Other systems (e.g. BSD) do support multibyte and this will fail there since the chance that a random input stream is also a valid multibyte stream is very small in most encodings. GNU may add multibyte support at any given moment, at which point this will fail. Of course, setting LC_ALL=C will fix that. – Martin Tournoij Aug 27 '16 at 17:33
  • @Carpetsmoker POSIX does require tr to process binary input (in the C locale). (Well, ok, it only says explicitly that null bytes are to be supported, it doesn't say that non-empty files not ending with a newline character are to be supported, but in practice that's always the case as well.) – Gilles 'SO- stop being evil' Aug 27 '16 at 17:57

You can use one of md5 tools that has precisely this purpose. In the case of creating a completely random password you can use the md5pass. It is a very simple tool to use and very helpful, since you can use "normal text" together with a "salt" to jump-bit construction of the same password that you can recover afterwards, or alternatively you may want to get a completely random password all the time. The general usage is:

md5pass [password] [salt]

where password is a chosen word that will be used for the construction of the random string and salt is the jump in bytes to be used. Like this:

md5pass word


This will create a "a random sequence" password for you to use. If you use no salt, then you may not be able to recreate this same string afterwards.

However if you use a salt like this:

md5pass word 512


then you can create a sequence which you can recover if you use the word in conjunction with the same salt (or jump) if it was originally defined.

  • When a salt is being used, this sounds similar to the PasswordMaker approach... – landroni Sep 26 '15 at 8:20
  • -Yes May sound similar to one maker password, but the difference is that it is not a commercial program or anything, because the set of md5 tools, "md5pass, md5sum, md5sum.textutils" dealt with here are concerned and are available the system at no cost some !!! – Joke Sr. OK Sep 26 '15 at 13:17
  • I actually had in mind PasswordMaker, which is also open-source and non-commercial. – landroni Sep 26 '15 at 16:43
  • If you don't have (or like) md5pass, a very similar idea also works with openssl: openssl passwd <BLABLA>, where <BLABLA> is an arbitrary string. This command just generates a hash of that string using the crypt algorithm by default. Old-fashioned, no high security, but for quick-and-dirty applications (like temporary accounts) may be acceptable. – Laryx Decidua Jan 29 at 16:24

I use:

base64 < /dev/urandom | tr -d 'O0Il1+/' | head -c 44; printf '\n'

This gives me 57 possible characters. The string can be copy-pasted (removed + and ``) or printed and retyped as the difficult to distinguish characters (I1lO0) have been removed.

  • 44 characters gives me: log2(5744) > 256.64 bits of entropy
  • 22 characters gives me: log2(5722) > 128.32 bits of entropy

I like this because:

  • the command is simple to type and memorable
  • it uses standard system tools - no extra binaries
  • doesn't "waste" much randomness (uses 89% of the random bits it receives vs ~24% for solutions directly piping to tr)
  • 22 and 44 characters pair quite nicely (just above even) common power of two breakpoints
  • the output can be easily selected and pasted or printed and retyped with minimal human error rates
  • shorter than hex encoded (32 and 64 instead of 22 and 44) solutions such as md5sum/sha1sum, etc.

Credit to https://unix.stackexchange.com/a/230676/9583 and especially the comments for my initial inspiration.

  • If you need numbers/special characters - typically there will be a number, if not you can safely append 1 without reducing entropy (while generating a new one to get one w/a number does reduce entropy). You can also safely append a ! without reducing entropy. Neither scheme increases entropy worth anything either, but could bring the generated string into compliance with older password requirements. – Iiridayn Oct 17 '18 at 21:28
  • 1
    And it works on macOS! – Micah Henning May 2 '20 at 2:56

These two commands generate random passwords and passphrases, respectively.

shuf --random-source=/dev/urandom --repeat --head-count=20 file_with_characters | tr --delete '\n'

shuf --random-source=/dev/urandom --repeat --head-count=7 file_with_words | tr '\n' ' '

The password generator requires a file_with_characters containing all the characters you want the password to use, one character per line, and exactly one time each. The file must not contain blank lines, and lines must be newline-terminated.

The passphrase generator requires a file_with_words containing all the words you want the passphrase to use, one word per line, and exactly one time each. The file must not contain blank lines, and lines must be newline-terminated.

The --head-count option specifies the length of the password--in characters--or passphrase--in words.


I've found that piping /dev/urandom to tr on macOS didn't work. Here's another way:

for i in `seq 1 $n`; do
    char=${set:$RANDOM % ${#set}:1}
echo $rand

I would like to contribute my usual command to generate a password

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -13

To configure the length of the password, change the number in the cut command to the length that you require, for example, 24 character

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -24

Don't want confusing 0 or O, 1 or l? Filter it out with another tr

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' | tr -d '0O1l'|cut -c -24

I personally never prefer special character in password, that is why I only choose [:alnum:] for my password generator


The Unix philosophy of "many small tools that do one thing well" serves you very well in this case.

  • /dev/urandom is a stream of random "bytes" (which include non-printable characters)
  • base64 encodes byte data into [A-Za-z0-9/+] (which is entirely printable)
  • dd copies input to output applying modifiers given as arguments (which can include block size and block count)


base64     < /dev/urandom | dd bs=1k count=1


base64 -w0 < /dev/urandom | dd bs=1k count=1


  • If you need a subset of the characters, you can insert a modifier in the pipe.
    • Ex: tr -d '[A-Z/+]' to get rid of capital letters and + and /
  • You can set the bs (block size) to whatever length you need.
  • On Linux, base64 wraps to 76 columns by default and must be reset with -w0 unless you want that.

My way for a very secure password (where 16 is the pw length):

cat /dev/urandom | tr -cd [:graph:]|head -c 16

Example result:


Or alternatively, to generate multiple passwords:

cat /dev/urandom | tr -cd [:graph:]|fold -w 16|head -6

Example result:


Little less secure (smaller character set):

cat /dev/urandom |base64 -w 0|fold -w 16|head -6

Example result:


I maintain secpwgen in Alpine Linux & keep the sources on my Github.

It can produce random strings or diceware phrases:

musl64 [~]$ secpwgen
USAGE: secpwgen <-p[e] | -A[adhsy] | -r | -s[e]> N

PASSPHRASE of N words from Diceware dictionary
  -p    generate passphrase
  -pe   generate enhanced (with symbols) passphrase

SKEY PASSWORD of N words from S/Key dictionary
  -s    generate passphrase
  -se   generate enhanced (with symbols) passphrase

ASCII RANDOM of N elements (at least one option MUST be present)
  -A    Each letter adds the following random elements in output:
    a    alphanumeric characters
    d    decimal digits
    h    hexadecimal digits
    s    special characters
    y    3-4 letter syllables

  -r    output BASE64 encoded string of N random BITS
  -k    output koremutake encoding of N random BITS

To generate a 13 character random string you would use:

musl64 [~]$ secpwgen -Aas 13
WK5#*V<]M3<CU ;ENTROPY=67.21 bits
INFO: destroying random number generator.
INFO: zeroing memory.

musl64 [~]$ secpwgen -Aa 13
INFO: destroying random number generator.
INFO: zeroing memory.

For users to remember a password use the diceware phrases:

musl64 [~]$ secpwgen -p 5
wq seen list n8 kerr  ;ENTROPY=65.00 bits
INFO: destroying random number generator.
INFO: zeroing memory.

I personally like:

musl64 [~]$ secpwgen -r 512
h62lL7G4gwh3/j9c7YteQvVXoqJrQKKPWVR3Lt7az36DcfWZWtUgBT19iwmJBwP4UahNzPe7qYD7OcklUFpCzQ== ;ENTROPY=512.00 bits
INFO: destroying random number generator.
INFO: zeroing memory.

None of the answers so far are truly cross-OS.

The main flaws are represented by the locale definition (MacOS case) and tr being unable to recognize intervals of characters (Solaris case).

You should try shlibs. It's fresh and truly cross-OS. The code to get a random string is shlibs str005 (./shlibs str005).

Get a random string of 50 chars, include puntuation, exclude numbers:

shlibs str005 50 -p -xd

To use the highest voted answer on MacOS, you can use

LC_CTYPE=C tr -dc A-Za-z0-9 < /dev/urandom | head -c 32

where LC_CTYPE=C will limit the charset of tr, and 32 is the length.


pwgen, as everyone else has said, for passwords.

A diceware cli for usernames, and passwords if you want, for something a little more recollection friendly; I use the pip package diceware, which is fine for my needs. I am sure there are at least 100 more, of which 74% are written in nodejs, because, uh.. well that's what they do. Whichever you do decide upon, I would prioritize built-in upcase/downcase, because you will have those contraints at some point, and performing either of those is annoyingly long in posix shell.



I go, to http://passwordsgenerator.net/ it allows generating strings of random characters up to 2048 characters, selecting upper case, lower case, digits 0 to 9, punctuation marks, or any combination.

  • 3
    I've clarified the question to make it explicit that off-line generated strings are preferable. Generating a password directly on a website, especially if the connection is not HTTPS (as in your answer), is not secure. – landroni Sep 26 '15 at 7:09
  • 3
    Getting a random password from the internet is spectacularly stupid & naive. Someone now knows a password you are using for some service or site and unique personal details about you (IP address, browser/environment info). This site can now cross-reference the info with other data collected about you. For example, you once posted to a mailing list, your IP address is in the mail’s header, so we now have a password, name, and an email address... You are really trusting random strangers with your passwords here. – Martin Tournoij Aug 27 '16 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.