무작위 데이터를 생성하려면 /dev/random, /dev/urandom을 사용하십시오.

무작위 데이터를 생성하려면 /dev/random, /dev/urandom을 사용하십시오.

/dev/random명령줄에서 (또는)을 사용하는 방법을 찾고 있습니다 . 특히, 이와 같은 스트림을 사용하여 난수 스트림(한 줄에 하나의 숫자)을 작성하는 /dev/urandom방법을 알고 싶습니다 .stdinstdout

나는 기계 아키텍처에서 기본적으로 지원하는 모든 숫자 유형의 난수에 관심이 있습니다. 예를 들어, 64비트 아키텍처의 경우 여기에는 64비트 부호 있는 정수와 부호 없는 정수 및 64비트 부동 소수점이 포함됩니다. 범위에 관한 한 다양한 숫자 유형의 최대 범위는 괜찮습니다.

Perl, Python 등과 같은 범용 인터프리터를 사용하여 이 모든 작업을 수행하는 방법을 알고 있지만 셸에서 "더 간단한" 도구를 사용하여 이 모든 작업을 수행하는 방법을 알고 싶습니다. (그리고 "더 쉽다"는 것은 "매우 작은 Unix 설치에서도 사용할 수 있을 가능성이 더 높다"는 의미입니다.)

기본적으로 이 문제는 명령줄에서 이진 데이터를 문자열 표현으로 변환하는 문제를 줄여줍니다. (예를 들어 다음은 작동하지 않습니다: printf '%f\n' $(head -c8 /dev/random).)

쉘 독립적 답변을 찾고 있습니다. 게다가 이 질문에서는 /dev/random와 의 차이가 /dev/urandom중요하지 않습니다. 결과의 의미가 다를 수 있더라도 한 쪽에서 작동하는 모든 절차가 다른 쪽에서도 작동할 것으로 기대합니다.


아래에 표시된 기능을 생성하기 위해 EightBitTony의 답변을 적용했습니다 toints.

사용 예:

% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422

논평:

  1. hexdump대신 od내가 원하는 방식으로 출력 형식을 지정하는 더 쉬운 방법을 제공하기 때문에 이를 사용합니다 .
  2. 하지만 짜증나게도 hexdump64비트 정수는 지원되지 않습니다(wtf???).
  3. 기능에 대한 인터페이스는 개선이 필요하지만(예: 인터페이스 -n5도 수용해야 함 -n 5), 쉘 프로그래밍 기술이 부족하기 때문에 이것이 제가 신속하게 구성할 수 있는 최선입니다. (항상 그렇듯이 의견이나 개선 사항을 환영합니다.)

이 연습에서 가장 놀랐던 점은딱딱한쉘에서 프로그램을 작성하세요.기본숫자 콘텐츠(예: 16진수 부동 소수점 값 읽기 또는 최대 기본 부동 소수점 값 가져오기)...


_tonums () {
  local FUNCTION_NAME=$1 BYTES=$2 CODE=$3
  shift 3

  local USAGE="Usage: $FUNCTION_NAME [-n <INTEGER>] [FILE...]"
  local -a PREFIX

  case $1 in
    ( -n ) if (( $# > 1 ))
           then
               PREFIX=( head -c $(( $2 * $BYTES )) )
               shift 2
           else
               echo $USAGE >&2
               return 1
           fi ;;
    ( -* ) echo $USAGE >&2
           return 1 ;;
    (  * ) PREFIX=( cat ) ;;
  esac

  local FORMAT=$( printf '"%%%s\\n"' $CODE )
  $PREFIX "$@" | hexdump -ve $FORMAT
}

toints () {
  _tonums toints 4 d "$@"
}

touints () {
  _tonums touints 4 u "$@"
}

tofloats () {
  _tonums tofloats 8 g "$@"
}

toprobs () {
  _tonums toprobs 4 u "$@" | perl -lpe '$_/=4294967295'
}

답변1

od을 사용하여 번호를 얻을 수 있습니다 ./dev/random/dev/urandom

예를 들어,

2바이트 부호 없는 10진수 정수,

$ od -vAn -N2 -tu2 < /dev/urandom
24352

1바이트 부호 있는 10진수 정수,

$ od -vAn -N1 -td1 < /dev/urandom
-78

4바이트 부호 없는 10진수 정수,

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

man od더 많은 정보를 알고 싶다면 od.

답변2

일부 쉘(예: bash(1)) 에는 $RANDOM난수를 제공하는 "변수"가 있습니다.

답변3

Bash 내장 명령을 사용하는 것이 od.

((RND=((RANDOM<<15|RANDOM)<<15|RANDOM)<<15|RANDOM))

그러면 0에서 1,152,921,504,606,846,975 사이의 임의의 숫자가 제공됩니다. 모듈식 분할을 통해 원하는 범위로 좁힐 수 있습니다.

실제적인 예로, 디스크를 대기 모드에서 깨우기 위해 하드 드라이브에서 임의의 섹터를 읽는다고 가정해 보겠습니다. 나는 이것을 할 수 있다:

#!/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

완벽한.

(참고: 이 예에서는 45비트 임의 정수이면 충분하고 60비트 임의 정수보다 조금 더 빠르다고 생각합니다.)


고쳐 쓰다:

위의 속도 주장에 대한 정량적 뒷받침을 제공하려면 다음을 수행하십시오.


~# 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

답변4

버전 5.1 또는 5.2부터 bash에는 $SRANDOM32비트 난수를 제공하는 "변수"가 있습니다.

관련 정보