Файловый дескриптор 2 открыт для чтения и записи.

Файловый дескриптор 2 открыт для чтения и записи.

Это моя программа на языке C, считываемая из stderr, которую я пишу

#include <uninstd.h>
#include <stdio.h>

int main(void) {
 char buff[3];
 read(2, buff, sizeof(buff));
 printf("%s", buff");
 return 0;
}

Мой вопрос, как мне отправить stderr в него. Большинство поисковиков показывают, что в bash перенаправление

command 2> file

Но это отправит stderr в файл.

Как мне перейти к моей программе. Как pip,

command 2 "somthing here" ./myprogram

Спасибо за ответы.

решение1

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

(Примечание: в этом ответе я использую фактические номера дескрипторов файлов.С потокитакие, которые stderrна самом деле не должны соответствовать этим файловым дескрипторам, поскольку программа может изменить их, и это добавляет уровень путаницы в разговор о том, что делают потоки C. Ваша программа использует read().)

Файловый дескриптор 2 открыт для чтения и записи.

Для программ в сеансах входа, где не использовалось перенаправление в родительском процессе, файловый дескриптор 2 (стандартная ошибка) обычно является дубликатом файлового дескриптора 0 (стандартный ввод). Они оба ссылаются на один и тот же базовыйописание файла, который обычно является терминалом сеанса входа в систему (открывается и дублируется ttymonили, в старых системах, gettyв самом начале сеанса).

Если вы читаете из файлового дескриптора 2, вы получаете те же входные данные, что и при чтении из файлового дескриптора 0.

Кстати: Чтение из файлового дескриптора 2 часто выполнялось для таких вещей, как ввод пароля; до того, как /dev/ttyустройство было представлено, примерно в 1977 году. Причиной чтения из файлового дескриптора 2 было получение ввода с исходного терминала, когда файловый дескриптор 0 был перенаправлен в другое место (как, например, в середине конвейера).

Несмотря на то /dev/tty, что POSIX существует уже давно, более 40 лет, он по-прежнему требует, чтобы файловый дескриптор 2 был открыт для чтения.

Что ваша программа не делает

Чтение из выходного файла дескриптора 2 другой программы — это другое дело. Вы не можете сделать это легкосам по себе, без слияния стандартного вывода со стандартной ошибкой. Обычно это включает в себя серию 3>&1 1>&2 2>&3или что-то вроде свопов. Некоторые оболочки разрешают каналы на выходном файловом дескрипторе 2, вызывая

prog1 2| prog2

Но такие снаряды редки, и это не то, чтотвойпрограмма нужна в любом случае.

Отправка входных данных в вашу программу

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

Оболочка позволяет использовать <>оператор перенаправления, который явно открывает файл как для чтения, так и для записи. Это то, что вы используете при перенаправлении файлового дескриптора 2 вашей программы.

./myprogram 2<>filename

Помимо перенаправления оболочки, есть множество инструментов, которые позволяют манипулировать файловыми дескрипторами. Например: С цепочкой загрузки Лорана Беркоredirfdинструмент, который поставляется с execline, это перенаправление больше похоже на вашу гипотезу:

redirfd -u 2 filename ./myprogram

Также существует синтаксис оболочки в оболочках Bourne Again и Z (но не в оболочках Almquist) для предоставления «здесь документов» и «здесь строк» ​​файловому дескриптору 2. Обратите внимание, что файловый дескриптор 2 открыттолько для чтенияэтими снарядами в данном случае.

./myprogram 2<<< "here string"

решение2

stderrпредназначен для записи, а не для чтения. Иногда это деликатес dup( stdinнапример, когда все 3 входа/выхода/ошибки подключены к терминалу). Чтобы прочитать stderr другой программы, вы перенаправляете stderr этой программы на stdin другой.

например, to направляет stdoutк файлу, а stderrto ./myprograms's stdin.

command 2>&1 >a_file | ./myprogram

решение3

С помощью таких оболочек, как bashи zsh(но не просто POSIX sh), вы можете перенаправить стандартную ошибку одной программы на стандартный ввод другой программы с помощью firstprogram 2> >(second program).

Пример:

$ perl -E 'say "perl stdout"; warn "perl stderr\n"' 2> >(awk '{print "awk", $0}')
perl stdout
awk perl stderr

решение4

Чтобы оболочка настроила перенаправление ввода для stderr, вы должны использовать <, <<или <<<и префикс в виде номера дескриптора файла:

./myprog 2< somefile.txt

или

./myprog 2<<< "some text"

Хотя если вы перенаправите stderrтаким образом, программа не сможетвыходк нему, что будет означать, что вы не увидите никаких сообщений об ошибках, которые программа (или любые используемые ею библиотеки) может попытаться вывести на печать, и, кроме того, программа будет получать ошибки при попытке записать эти сообщения.

Вы можете пересмотреть, есть ли другой способ сделать то, что вы делаете. По крайней мере, рассмотрите использование, например, fd 3, если идея заключается в том, чтобы предоставить программе какой-то ввод.

Связанный контент