在bash中的函数,它从/ dev / random生成随机字符

时间:2015-08-01 19:37:47

标签: bash random

在我的.bashrc文件中,我添加了行$sentence = userinput; @words = split(/ /, $sentence); for ($i = 0; $i < @words.length; $i ++){ $words[$i] =~ s/\W//g; @characters = split(//, $words[$i]); #print $words[$i] . "\n"; $wordlength = length($words[$i]); for ($j = 0; $j < @characters.length; $j ++){ $char = $characters[$j]; for ($x = 0; $x < $wordlength; $x++){ $char++; if ($char eq "aa"){ $char = "a"; } elsif ($char eq "AA"){ $char = "A"; } } print $char; if ($x = 0){ $output[$i] = $char; } else { $output[$i] = join ($char); } } print $output[$i]; } ,这样当我在终端中键入psswd() { LC_ALL=C tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/urandom | head -c "$1";echo ;}时,它会返回一个包含n个随机字符的字符串。我想实现相同但使用/ dev / random而不是/ dev / urandom。但是当我用/ random替换/ urandom时,调用psswd什么都不做(1小时后甚至不能输出一个随机字符),就像它被冻结一样。我不知道为什么会这样,我知道这不是没有足够熵的问题。原因是命令psswd n返回一个随机数。

请注意,如果我在重新启动后输入它,则最后一个命令几乎立即返回一个随机数。但是如果我用/ random调用了psswd n,那么该命令会在大约15秒后返回一个随机数。所以对/ random的调用似乎对/ dev / random有一些影响,即使在调用函数psswd时它没有产生输出。

总的来说,我想知道如何创建一个使用/ dev / random来生成n个字符的随机字符串的函数。

2 个答案:

答案 0 :(得分:1)

这是因为当libc不是终端时,tr将缓冲tr的输出。在GNU / Linux上,它是4096字节。这意味着head必须在/dev/random看到前几个字节之前产生4096字节的输出,即使它只是要求例如8.

由于您只保留256个值中的78个,因此在获取密码之前,4096*256/78必须平均生成/dev/random = 13443个字节的随机输出。

我的系统上的

13443*26/20,从空池开始,需要26秒才能生成20个字节。这意味着这些字节需要tr = 17475秒,或者差不多5个小时才能生成密码。

此时它会打印密码,但是head需要另一个缓冲区来实现(8+1)*256/78不再需要,所以在命令之前还需要5个小时退出。

如果禁用缓冲,则只需要生成stdbuf -o0 = 29个字节,这只需要约38秒。在GNU / Linux上,您可以使用$ time { LC_ALL=C stdbuf -o0 tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/random | head -c 8; echo; } 9D^MKbT) real 0m36.172s user 0m0.000s sys 0m0.010s

执行此操作
{{1}}

答案 1 :(得分:0)

  

...当我用/urandom替换/random时,调用psswd什么都不做......

发生这种情况。 As Wikipedia explains

  

在类Unix操作系统中,/dev/random是一个特殊文件,用作阻塞伪随机数生成器....

  与/dev/random对应的是/dev/urandom(“无限制”/ 非阻止随机来源[强调添加]

“阻止”意味着当它认为已经耗尽熵时,它会停止产生数字。例如,在我的系统上,管道中的第一个命令产生以下内容:

$ LC_ALL=C tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/random  
~Sk(+!h

然后,它挂起,大​​概是在等待更多熵时。

此问题将进一步讨论here,其中有人认为/dev/urandomgood enough

加快速度

tr似乎缓冲了其输出,从而延迟了字符的出现。解决方法是使用stdbuf,对我而言,这会带来显着的加速:

LC_ALL=C stdbuf -o0 tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/random