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
  • 14
    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

20 Answers 20


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:

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

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

</dev/urandom tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' | 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
  • 13
    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
  • 7
    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
  • 5
    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
  • 2
    @Rup I'm not sure what's not working with your tr .. command but just quoting everything (except for the single quote) works – tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~'. – Kenny Evitt Aug 18 '16 at 19:33

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
  • 18
    +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

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

openssl rand -base64 12


openssl rand -hex 12
  • 6
    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
  • @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
  • The question was "How to generate a random string of a specific length" @DennisWilliamson, so while your comment is correct as such, it's not correct in the context of this question. – Martin Tournoij May 19 '17 at 20:31
  • @Carpetsmoker: In that case, neither is this answer. – Dennis Williamson May 19 '17 at 20:58
  • 2
    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

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 I like this approach, thanks. Allows to control both length and number of generated strings. – landroni Sep 20 '15 at 6:12
  • 3
    Achievement unlocked: Unnecessary use of cat! – user1338062 Oct 25 '16 at 9:26
  • 1
    @user1338062 An unhelpful comment. OP presumably isn't running on a PDP-10 and can afford to waste the whole circa 4KB of RAM on running cat. Lots of people have explained (again and again since the mid 1980s) why they find the bash one-liner style using cat easier to read and edit. – jwg May 16 '18 at 15:04

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

  • 1
    In what way is this different from the existing answers? Specifically, herbert's comes to mind. – Fox Apr 27 '17 at 22:40
  • 3
    @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
  • < /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

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-zA-Z]'
$ echo $RANDOM | tr '[0-9]' '[a-zA-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-zA-Z]'
  • How do you control the length of the generated string? – landroni Sep 19 '15 at 13:33
  • @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
  • @landroni yes, that's what I said, it generates numbers between 0 and 32767, so 5 digits will be the max. If you need longer ones or need to be able to specify the length, please edit your question and make that clear. – terdon Sep 19 '15 at 14:20
  • 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

@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 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 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

APG is a default software on 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.

  • 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

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.


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.


I use:

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

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

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.

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 lenght 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


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:


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.

A super easy and simple (probably more simple than you're looking for) way to achieve this would be to generate a random number in a given range, convert that number to its equivalent ASCII character, and append it to the end of a string.

Here's a basic example in Python:

import random # import random library  
passFile = open("passwords.txt", 'w') # create file passwords.txt
passNum = int(input("Number of passwords: ")) # get number of  passwords
passLength = int(input("Password length: ")) # get length of passwords  
for i in range(passNum):
    password = "" # reset password
    for i in range(passLength):
        num = random.randint(65, 122) # get random number
        while num in range(91, 97): # Don't include punctuation
            num = random.randint(65, 122)
        password += chr(num) # add character to current password 
    passFile.write(password + "\n") # add current password to file  
passFile.close() # close file

EDIT: added comments, and added code to generate multiple passwords and write them to a file


I'd like this command:

date +%s | sha256sum | base64 | head -c 12
  • 1
    I would rather use more random nanoseconds approach: date +%N Since if you generate many users and passwords in a script, the seconds might become same for many or even for all date commands, thus producing identical passwords. – John Mayor Apr 28 '17 at 12:53
  • 1
    @JohnMayor: is this approach more robust: dd if=/dev/random bs=512 count=1 ? – Eugen Konkov Apr 28 '17 at 13:48
  • 7
    This answers is highly dangerous! You generate the password(s) from a known seed which is easy to predict. I could generate all passwords generated using this method of the last years and use this list for brute forcing purposes. – Flow Jul 1 '17 at 17:20

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.

  • 2
    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
  • 1
    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 acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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