Да, целесообразно перенаправить весь вывод терминала из вашей программы (и всех ее дочерних процессов) после запуска вашей программы.Программы 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
.