C дескриптор терминала перенаправления - PullRequest
0 голосов
/ 27 октября 2018

Можно ли перенаправить все, что написано в терминале, в процесс?

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

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Да, целесообразно перенаправить весь вывод терминала из вашей программы (и всех ее дочерних процессов) после запуска вашей программы.Программы Unix обычно пишут в терминал, записывая в стандартный вывод (stdout).Стандартный вывод всегда для файлового дескриптора номер 1 (константа C STDOUT_FILENO) для всех процессов.Вы можете использовать системный вызов dup2(), чтобы заменить любой номер дескриптора файла другим дескриптором файла.

Таким образом, вы можете, например, создать канал, используя int fds[2]; pipe(fds);.Тогда fds[1] будет номером дескриптора файла, который вы можете использовать для записи в канал.Если вы сделаете dup2(fds[1], STDOUT_FILENO);, то стандартный вывод также запишет в канал.(Вы можете close(fds[1]); впоследствии, поскольку вам, вероятно, это не нужно, теперь вы можете вместо этого использовать стандартный вывод.)

Вы также можете открыть файл для записи с помощью fd = open("filename", O_WRONLY);, а затем dup2(fd, STDOUT_FILENO);, чтобы всезапись в stdout входит в ваш файл.

Обратите внимание, что вам нужно перенаправить stdout в самом начале вашей программы, прежде чем делать что-либо, что может записать в stdout.


Приведенный выше трюксделать стандартный вывод на ваш канал вместо терминала.Если вы хотите, чтобы вывод шел в терминал, , а также получал копию вывода в файле потока, это более сложно, но это также можно сделать.Вам нужно создать внутренний канал, затем dup2(that_pipe, STDOUT_FILENO);, чтобы stdout записывал в этот канал.Затем вам нужно прочитать из этого канала (вероятно, используя poll(), затем read()) и записать все, что вы получили, в 1) терминал и 2) в другой канал или файл, который выходит за пределы вашей программы.Поэтому вам нужно две трубы , если вы хотите скопировать вывод.

Команда tee делает это (копировать стандартный вывод в файлы) из оболочки.


Этот dup2() подход не является пуленепробиваемым, поскольку терминал Unix (даже при использовании эмулятора терминала с графическим интерфейсом вместо аппаратной консоли) является устройством в /dev.Вы можете набрать tty в оболочке или использовать ttyname(STDOUT_FILENO) в C, чтобы увидеть, какой файл в /dev соответствует терминалу, в который записывает стандартный вывод.В принципе, любая программа (под той же учетной записью пользователя) может открыть терминальное устройство, используя это имя файла, и записать в него, не запрашивая разрешения у какой-либо другой программы.Вы можете легко попробовать это из оболочки, используя программу write:

echo hello world | write $(whoami) /dev/ttys123

, где /dev/ttys123 - это все, что вы получили, набрав tty в другом окне терминала (имя выглядит немного по-разному в разных операционных системах, например, Linux и MacOS).В этом другом окне вы должны увидеть hello world.

0 голосов
/ 27 октября 2018

От дочернего процесса нет. Вы должны установить это в родительском preocess и распространить его вниз на детей (за исключением какого-то сумасшедшего хака).

Из оболочки можно перенаправить.

exec >file

Это перенаправит стандартный вывод на file и будет применяться ко всем будущим командам, выполняемым в оболочке. Вы можете превратить это в функцию, если хотите.

...