OSX의 / dev / urandom에서 tr을 읽을 수없는 이유는 무엇입니까? 임의의 키를 만들 것을 제안했습니다. tr -dc

동료는 다음 명령을 통해 임의의 키를 만들 것을 제안했습니다.

tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs

그것은 나에게 오류를 주었다 :

tr : 잘못된 바이트 시퀀스

/dev/urandom시스템에 없는 것이 걱정 됩니다. 이 파일을 설치하는 방법을 찾기 위해 인터넷 검색을 시도했지만 비어 있습니다. 나는 노력 locate urandom하고 또한 비어 있었다. (실제로 man 페이지를 찾았지만 도움이되지 않습니다)

urandomMac OSX 시스템에서 어떻게 사용할 수 있습니까? (사자)



답변

오류 메시지에 따르면 / dev / urandom이 문제라고 생각하지 않습니다. 그렇다면 “파일 또는 디렉토리가 없습니다”와 같은 오류가 발생합니다.

귀하가 얻은 오류 메시지를 검색하여 문제와 관련이있는 것 같습니다 : http://nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte-sequence

기본적으로 tr명령 앞에 다음을 추가하여 로케일을 지정하십시오 LC_CTYPE=C.

LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs


답변

귀하의 tr시도는 UTF-8 인코딩 텍스트로 입력을 해석합니다. 따라서 유효한 UTF-8이 아닌 첫 번째 바이트 시퀀스를 불평하고 중단합니다. 접두어를 tr사용 LC_ALL=C하거나 LC_CTYPE=C해당 변수를 환경으로 내 보내면 tr로컬 문자 세트에 대한 아이디어가 C 표준으로 변경됩니다. 즉, 모든 것이 불투명 한 바이트 시퀀스입니다.

그건 그렇고, \)-+당신의 명령 의 순서 는 의도적 인 것입니까? 여기에는 *이미 포함했지만 -의도 한대로 포함되지 않습니다 . 대신 다음 중 하나를 작성하는 것이 좋습니다.

LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()\-+=' < /dev/urandom
LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)\\-+= < /dev/urandom


답변

다른 사람들이 지적했듯이, 당신의 문제는 /dev/urandom빠진 것이 아니라 오히려 trOS X에서 어떻게 작동 하는지 perl입니다 tr.

perl -pe 'binmode(STDIN, ":bytes"); tr/A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+=//dc;' < /dev/urandom | head -c 32; echo

이것은 OS X, Redhat 및 Ubuntu에서 이식 가능하다는 이점이 있습니다.

(또한 출력 끝에서 개행을 얻기 위해 xargswitch를 대체 하는로 파이프를 제거했습니다 echo.)


답변

첫째, 당신은 포함하려는 않았다 -또는 *유효한 문자 목록에? 행의 매개 변수 tr시퀀스가 포함 )-+되는 바이트 범위로 시작 “을 의미 )하고 끝나는 +사실이다를 )*+.

둘째, 커널의 엔트로피 풀에서 많은 킬로바이트를 읽지 않고 (전체 풀을 안전하지 않은 것으로 표시하여 안전한 엔트로피가 필요한 다른 프로세스에 영향을 미침), 필요한만큼만 읽기를 고려 head -c...하십시오. 첫 번째 단계로 사용, 원하지 않는 문자를 버리지 말고 번역하십시오.

이 문제의이 특정 버전은 76 개의 다른 기호를 사용한다는 점에서 약간 특이합니다. 대부분 영숫자를 원하므로 64 기호만으로도 만족한다면 base64유틸리티 를 사용 하면 엔트로피 풀의 소비가 최소화됩니다 (24는 32의 6/8 임).

head -c24 < /dev/random | base64


답변

로케일의 문자 인코딩 (로 알 수 있음 locale charmap)은 문자 당 멀티 바이트입니다.

오늘날 가장 일반적인 것은 문자가 1-4 바이트 이상 인코딩 될 수있는 UTF-8입니다. 모든 바이트 시퀀스가 ​​UTF-8에서 유효한 문자를 형성하는 것은 아닙니다. UTF-8의 모든 비 ASCII 문자는 2 개의 가장 높은 비트 세트가있는 1 바이트로 시작하여 가장 높은 (그러나 2 번째가 아닌) 비트 세트가 따르는 바이트 수를 알려줍니다.

/dev/urandom임의의 바이트 스트림을 포함합니다. tr문자를 음역하므로 해당 바이트를 문자로 디코딩해야합니다. 범위의 ASCII 문자는 모두 UTF-8로 한 문자로 인코딩되지만 tr여전히 모든 문자를 디코딩해야합니다. 예를 들어 A0x41 바이트 이외의 일부 문자 (에 대한 코드)를 포함하는 다른 멀티 바이트 인코딩이 있습니다 A.

임의의 바이트 스트림이 유효하지 않은 시퀀스를 포함하도록 바인드되기 때문에 (예를 들어, ASCII가 아닌 문자는 0xc1보다 큰 바이트로 시작해야하기 때문에 0x80 바이트 자체는 UTF-8에서 유효하지 않습니다 (0xc0 및 0xc1은 UTF- 8 자)))이므로 tr오류가 발생하면 오류와 함께 반환됩니다.

여기서 원하는 것은 문자 당 1 바이트를 갖는 인코딩에서 바이트 스트림을 문자로 간주하는 것입니다. AZ가 가정하고 ABCDEFGHIJKLMNOPQRSTUVWXYZ를 의미하고 Ý, 와 같은 것은 아니라는 것을 의미 Ê하므로) 범위의 모든 문자가 휴대용 문자 세트의 일부이므로 시스템에서 지원되는 모든 문자 세트에서 동일하게 인코딩되므로 선택하는 것이 중요하지 않습니다 .

이를 위해, 당신은 설정 한 것 LC_CTYPE사용하고 무엇을 같은 것들을되는 캐릭터 세트 결정하는 하나 현지화 변수 blank, alpha문자 클래스가 포함되어 있습니다. 그러나 AZ 범위의 정의를 위해 LC_COLLATE변수 (문자열 순서를 결정 하는 변수) 도 설정해야 합니다.

C일명 POSIX로케일은 하나의 보장 문자임을 단일 바이트이고 AZ는 ABCDEFGHIJKLMNOPQRSTUVWXYZ입니다. 당신은 할 수 있습니다 :

 LC_CTYPE=C LC_COLLATE=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'

(여기에서 -를 끝으로 이동하면 그렇지 않은 경우 )-+와 같은 범위로 사용됩니다 A-Z)

그러나 노트는 것을 LC_ALL변수는 다른 모든 무시 LC_*LANG변수를. 따라서 LC_ALL달리 정의되어 있으면 위의 효과가 없습니다. 대신 간단하게 할 수 있습니다 :

 LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'

이는 오류 메시지의 언어와 같은 다른 요소에 영향을 미치지 만 LC_CTYPE 변경은 이미 오류 메시지의 문제 일 수 있습니다 (예 : C 로케일의 문자 세트로 러시아어 또는 일본어 오류 메시지를 표현할 방법이 없음).


답변

man 페이지 에 따르면 / dev / random은 아마도 당신의 필요에 충분할 것입니다. 아마도 애플은 불필요하기 때문에 / dev / urandom 생성을 중단했을까요?


답변