Чому tr не можна читати з / dev / urandom на OSX?


35

Колега запропонував створити випадковий ключ за допомогою наступної команди:

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

Це дало мені помилку:

tr: Незаконна послідовність байтів

Мене хвилює те, що я не маю /dev/urandomсвоєї системи. Я спробував googling, щоб зрозуміти, як встановити цей файл, але я з'явився порожнім. Я спробував locate urandomі теж підійшов порожнім. (ну насправді, він знайшов сторінку man, але це не допомагає)

Як зробити urandomдоступними для моєї системи Mac OSX? (Лев)


3
Цікаве використання xargs
sendmoreinfo

Відповіді:


49

На основі повідомлення про помилку, яке ви отримуєте, я не думаю, що проблема / 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

Дякую, що справді зробив трюк. Будь-яка ідея, чому я не можу знайти urandomабо random? Це спеціальні магічні "файли", які не існують у фактичній файловій системі? (Також я запропонував редагувати, щоб допомогти пом'якшити гниття зв’язків)
Кірк Волл

1
Я вважаю, locateщо не шукає безпосередньо вашу файлову систему, а шукає ваш запит за допомогою попередньо вбудованої бази даних. Ця база даних, швидше за все, налаштована на ігнорування / dev / та інші «спеціальні» файлові системи.
lk-

досить справедливо, але я не бачу цього, коли дивлюсь прямо /dev. Піди розберися. Але ще раз дякую за допомогу.
Кірк Волл

1
не працює на 10,9; все ще не вдається з тим самим повідомленням про помилку. LC_ALL=Cробить трюк тхо.
Ерік Аллик

1
Будь ласка, змініть це посилання на nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte-sequence, оскільки в даний час воно вказує на останню сторінку блогу, що не містить trінформації.
Єроен Вірт Плюймерс

11

Ваші 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

6

Як зазначали інші, ваша проблема полягає не в тому, що /dev/urandomвона відсутня, а в тому, як trпрацює OS X. Замість того, щоб возитися з varialnment varialbes, використовуйте perlзамість tr:

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

Це має перевагу в тому, що він переноситься через OS X, Redhat та Ubuntu.

(Я також зняв трубу xargs, замінюючи відьму echo, щоб отримати новий рядок в кінці виходу.)


Рано чи пізно я очікую, що Perl зробить binmode ":utf8"стандарт, і тоді ваш рішення Perl матиме ту саму проблему, що trі.
Марк

Вирішував стурбованість Марка, додавши binmode (STDIN, ": байти") до зразка коду.
Трентон

2

По-перше, чи ви мали намір включити -чи *до списку дійсних символів? Параметр для trвключає послідовність)-+ що означає "діапазон байтів, починаючи з )і закінчуючи +, що є насправді )*+.

По-друге, замість того, щоб читати багато кілобайт з пулу ентропії ядра (і таким чином позначати весь пул як небезпечний, що вплине на будь-які інші процеси, які потребують безпечної ентропії), розгляньте читання лише стільки бітів, скільки вам потрібно: використовувати head -c...як перший крок, а потім перекладати, а не відкидати небажані символи.

Ця конкретна версія проблеми є дещо незвичною, оскільки використовується 76 різних символів; більшість просто хочуть буквено-цифрових знаків, тож якщо вас задовольнить лише 64 символи, то використання цієї base64утиліти зведе до мінімуму споживання пулу ентропії (зауважте, що 24 - це 6/8 з 32):

head -c24 < /dev/random | base64

1

Кодування символів вашої мови (про яке ви можете розповісти locale charmap ) є багатобайтовим на кожний символ.

Найпоширенішим на сьогоднішній день є UTF-8, де символи можуть кодуватися більше від 1 до 4 байтів. Не всі послідовності байтів утворюють дійсні символи в UTF-8. Кожен символ, що не є ASCII в UTF-8, починається з одного байта, який має два найвищі біти, і повідомляє, скільки байтів з найвищим (але не другим найвищим) набором бітів слідує.

/dev/urandomмістить випадковий потік байтів. trтранслітерація символів, тому йому потрібно розшифрувати ці байти як символи. Ці символи ASCII у вашому діапазоні всі закодовані в одному символі в UTF-8, але trвсе ж потрібно декодувати всі символи. Наприклад, є інші багатобайтові кодування, де деякі символи, крім Aмістять байт 0x41 (код дляA ).

Оскільки цей випадковий потік байтів повинен містити недійсні послідовності (наприклад, байт 0x80 сам по собі недійсний у UTF-8, оскільки символ, який не є ASCII, повинен починатися з байта, що перевищує 0xc1 (0xc0 і 0xc1 не містять UTF- 8 символів)), тому trповертається з помилкою, коли це відбувається.

Що ви хочете тут, це вважати цей потік байтів як символи в кодуванні, який має один байт на символ. Що б ви не вибрали, це не важливо, оскільки всі ці символи у вашому діапазоні (якщо припустити, AZ, ви мали на увазі ABCDEFGHIJKLMNOPQRSTUVWXYZ, а не подібні речі Ý, Ê) є частиною портативного набору символів, тому кодуйте однаково у всіх шаблонах, що підтримуються у вашій системі.

Для цього, потрібно встановити LC_CTYPEзмінну локалізації , яка є той , який вирішує , який набір символів використовується і то , що такі речі , як blank, alphaсимвольні класи містять. Але для визначення діапазону AZ ви також хочете встановитиLC_COLLATE змінну (ту, яка вирішує впорядкування рядків).

CАка POSIXлокаль одне , що гарантує символи в поодинокі байти і AZ є АБВГДЕЖЗІКЛМНОПРСТУФХЧШЕЮЯ. Ви можете зробити:

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


0

Згідно з довідковою сторінкою , / dev / random напевно буде достатньо для ваших потреб. Можливо, Apple перестала створювати / dev / urandom, оскільки це непотрібно?


У мене немає /dev/randomжодного.
Кірк Волл

MacOSX повинен мати / dev / random та / dev / urandom. Можливо, Apple більше не включає ці спеціальні файли? А може, це лише там, якщо встановити XCode?
jsbillings

1
FWIW, обидва пристрої присутні на моїй робочій станції Lion, що модернізується до Mountain Lion. Я вважаю, що він був присутній і на Леві. Вузли також різні (13,0 проти 13,1)
мрб
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.