Действительно ли это - опечатка в разделе перенаправления руководства Bash?

Ваша карта флэш-памяти идет только для чтения, потому что драйвер отказывает. Когда драйвер отказал, любые данные, которые это могло бы чувствовать себя заставленным записать, возможно повреждены, таким образом, файловая система вынуждена в режим только для чтения избежать любого (дальнейшего) повреждения.

Драйвер отказывает, потому что он исчерпывает память: трассировка заканчивается в warn_alloc_failed, и отсутствием памяти показывают swapper/0: page allocation failure: order:2, mode:0x4020. На первый взгляд похоже, что у Вас заканчивается память, это применимо ядром. Это не вполне то же самое, столь исчерпывающее RAM, как ядро не может использовать целую RAM для себя. Разряжение памяти ядра довольно редко, все же. Вы запускаете интенсивные приложения, которые вызывают большое одновременное использование диска или сетевой трафик? У Вас есть большая сумма видеопамяти?

Если ответ да, Вы, возможно, должны переключиться на 64-разрядную установку или уменьшить Ваше использование памяти ядра.

Если ответ не (или даже если это - да), это могло бы быть ошибкой ядра. Удостоверьтесь, что Вы выполняете последнее обеспеченное распределением ядро. Это могло быть ошибкой драйвера, это инициировано поврежденной файловой системой, или поврежденное средство чтения (драйвер, как предполагается, сопротивляется к неправильным данным, но много драйверов не тестируются много с неправильно себя ведущими устройствами). Это могло также приводить RAM к сбою; сделайте тест памяти.

13
25.07.2013, 01:26
4 ответа

Дублирование является действительно важной частью здесь.

Давайте посмотрим, куда дескрипторы файлов идут в перед перенаправлением. Это обычно - текущий терминал, например:

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

Теперь, если мы звоним ls -l без перенаправления выходные сигналы и сообщения об ошибках переходят к моему терминалу под /dev/pts/1.

Если мы сначала перенаправляем STDOUT в файл (ls -l > dirlist), это похоже на это:

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

Когда мы затем перенаправляем STDERR к дубликату STDOUTдескриптор файла (ls -l > dirlist 2>&1), STDERR переходит к дубликату /home/bon/dirlist:

STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist

Если мы сначала перенаправили бы STDERR к дубликату STDOUTдескриптор файла (ls -l 2>&1):

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

и затем STDOUT в файл (ls -l 2>&1 > dirlist), мы получили бы это:

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

Здесь, STDERR все еще идет в терминал.

Вы видите, порядок в странице справочника является правильным.


Тестирование перенаправления

Теперь, можно протестировать это сами. Используя ls -l /proc/$$/fd/, Вы видите где STDOUT (с fd 1) и STDERR (с fd 2), идут для текущего процесса:

$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1

Давайте создадим маленький сценарий оболочки, который показывает, где на Ваши дескрипторы файлов указывают. Таким образом, мы всегда получаем состояние при вызове ls, включая любое перенаправление от оболочки вызова.

$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh

CtrlD Вы отправляете конец файла и так остановитесь cat команда, читающая из STDIN.)

Теперь, назовите этот сценарий с переменными комбинациями перенаправления:

$ ./lookfd.sh 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh

Вы видите, что дескрипторы файлов 1 (для STDOUT) и 2 (для STDERR) варьироваться. Для забавы Вы могли также перенаправить STDIN и посмотрите результат:

$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh

(Вопрос оставлен читателю: Где делает дескриптор файла 255 точек?;-))

23
27.01.2020, 19:52
  • 1
    +1 - превосходный ответ. Чрезвычайно правильно написанные и потрясающие примеры.Спасибо!!! о –  slm♦ 24.07.2013, 21:50
  • 2
    , который я вижу, я думаю, что мое недоразумение состояло в том, что перенаправление будет персистентным для всего после команд, так, чтобы любой STDERR для остальной части строки перешел бы к STDOUT. –  Gregg Leventhal 31.07.2013, 16:56

Нет, руководство является правильным.

Если в первой 1 точке к терминалу, и 2 также к терминалу, то:

command  2>&1   1>somewhere

перенаправление evaluatino произойдет слева направо.

Таким образом, это СНАЧАЛА оценит 2>&1, и таким образом ПЕРВАЯ копия, что fd 1 используемый для указания на (т.е., дескриптор файла the terminal, обычно/dev/tty) в fd 2.

Таким образом в той точке fd 2 теперь точки туда, где fd 1 используемый для указания на (the terminal)

И ЗАТЕМ это оценивает 1>somewhere часть, и таким образом скопирует дескриптор файла somewhere в fd 1 (таким образом в той точке, fd 1 теперь точки к somewhere, и fd 2 неподвижные точки к the terminal)

Таким образом, это действительно печатает 1 в "где-нибудь" и 2 в терминал, поскольку 2 был дублирован от 1, ПРЕЖДЕ ЧЕМ 1 был изменен.

Другой порядок:

command  1>somewhere 2>&1

сначала перенаправит fd 1 кому: somewhere, и затем скопируйте ту же самую ссылку в fd 2, таким образом, в конце 2 также точки к somewhere. Но они не "связаны" с этого времени. Каждый может все еще быть перенаправлен отдельно.

исключая:

command  1>somewhere 2>&1
exec 2>/dev/null

В конце того, fd 1 точки к somewhere, и fd 2 направлен к /dev/null

Обычные названия fd 1 STDOUT (стандартный вывод) и обычное название fd 2 STDERR (стандартная погрешность, поскольку это является наиболее часто используемым для отображения ошибок, не вмешиваясь в STDOUT),

2
27.01.2020, 19:52
  • 1
    @Michael-mrozek: спасибо за редактирование, но я настаиваю на том, чтобы говорить "копию" вместо "дубликата", поскольку "дубликат" мог привести полагать, что с этого времени оба - "то же самое", которое не верно. исключая: cmd 1>somewhere 2>&1 ; exec 2>/dev/null : после должностного лица только 2 были перенаправлены к/dev/null (1, все еще идет в "куда-нибудь"). Я действительно нуждаюсь в помощи для предложения способа сказать, "что 1 точка к" вместо "fd 1", однако..., поскольку это также сбивает с толку... –  Olivier Dulac 24.07.2013, 20:19
  • 2
    , я не уверен, что Вы имеете в виду; Вы - тот, который изменил тебя из "копии" для "копирования". Все, что я сделал, было, используют для своей выгоды и вещи формата, я не изменил слово –  Michael Mrozek♦ 24.07.2013, 20:23
  • 3
    doh... ^^ извините. И я отредактировал снова для переформулирования для создания более точным, что копируется в то, какой ^^ –  Olivier Dulac 24.07.2013, 20:26

Я думаю, что запутывающая часть здесь является недоразумением, что перенаправление stderr к stdout на самом деле соединяет эти два потока.

Совершенно разумная идея, но что происходит, когда Вы пишете 2>&1 stderr, берет пикабу в том, во что stdout пишет и пишет в само то же место. Поэтому, если Вы впоследствии говорите stdout идти запись где-то в другом месте, что это не имеет никакого эффекта на место назначения stderr, который был уже перемещен.

Я думаю, что это немного парадоксально сам, но это - то, как это работает. Настроенный, где Вы хотите записать в первый затем, говорят, что все "копируют меня". Надежда, которая разъясняется...

1
27.01.2020, 19:52

ДУБЛИРОВАНИЕ...

важен, но скорее в том смысле, что он является источником большой путаницы . Это действительно очень просто. Этот ответ - просто «радикальная» иллюстрация.

Принятый ответ хорош, но слишком длинный и подчеркивает «дублирование».

Q мудро заканчивается на:

The use of the word duplication seems a little strange to me in this context. Perhaps that is throwing me.

Я использую нотацию bash и определяю переменные «один» и «два» как дескрипторы файлов «1» и «2». (выходной )оператор перенаправления >является присваиванием =. &и $означают «значение».

Примеры man bash (с добавленным значением по умолчанию "1")

ls 1>dirlist 2>&1      # both to dirlist
ls 2>&1 1>dirlist      # 1 to dirlist, 2 stays on tty/screen 

стать:

one=dirlist  two=$one

и

two=$one   one=dirlist

И даже это не -автоматически для меня и некоторых других, я думаю. Первая строка оставляет вам $oneи $two, содержащие «dirlist». Конечно.

Вторая строка начинается с бесполезного присвоения. Оба начинаются по определению с "TTY" (немного символического )в качестве их направления ; это присваивание не изменяет никакого значения, а с переменными, как и с файловыми дескрипторами, ничего магическим образом не связывается. На переменную twoне влияют следующие one=dirlist. Конечно, нет.

Кто-то здесь (6 лет назад )предложил "указать" вместо "копировать" или "дублировать", а потом понял :, что это тоже сбивает с толку.

Эта семантика дублирования или указателя даже не нужна. Может быть, это амперсанд, который требует большего внимания. «Значение» оператора/токена/что угодно.

Если -и только если -вы ищете способ получить неожиданный номер задания на вашей консоли , то сообщение «Готово» плюс в качестве бонуса файл с именем «2 ", тогда иди:

ls 1>2& 2>/dev/null

Обычно это читается как "копировать"/"дублировать" от 1 до 2, а затем оба вместе дают null . Но идея неверна, а также синтаксис. (но нет синтаксической ошибки, это действительно)

Правильный способ планирования — перенаправить любой из двух на null, а затем перенаправить ДРУГОЙ в то же место:

ls 1>/dev/null 2>&1
# or 
ls 2>/dev/null 1>&2

(ведущую "1" можно опустить)

(ОК согл. A не слишком длинный, но слишком длинный список -или :очень хорошая визуализация, не очень хорошее объяснение)

0
27.01.2020, 19:52

Теги

Похожие вопросы