Вы можете узнать, что использует ваша любимая оболочка, strace(1)
используя ее.
В одном терминале:
echo $$
В другом терминале:
strace -o /tmp/shell -f -p [PID from the first shell]
Снова в первом терминале:
ls > files.txt
Во втором терминале, ^C
ваша команда strace(1)
, а затем отредактируйте выходной файл /tmp/shell
, чтобы увидеть, какие системные вызовы он сделал для перенаправления.
freopen(3)
манипулирует стандартными указателями C IO FILE*
. Все это будет отброшено на другой стороне вызова execve(2)
, поскольку оно поддерживается в пользовательской памяти . Вы можете использовать этот после вызова execve(2)
, но это было бы неудобно использовать в общем.
popen(3)
открывает однонаправленный pipe(7)
. Это полезно, но крайне ограниченно - вы получаете стандартный дескриптор вывода или стандартный дескриптор ввода. Это потерпит неудачу для чего-то вроде ls | grep foo | sort
, где и вход, и выход должны быть перенаправлены. Так что это плохой выбор.
dup2(2)
будет управлять файловыми дескрипторами - ресурсом, реализованным в ядре - поэтому он будет сохраняться при execve(2)
вызовах и , вы можете установить столько файловых дескрипторов, сколько вам нужно, что неплохо для ls > /tmp/output 2> /tmp/error
или для обработки обоих входов и выход: ls | sort | uniq
.
Есть еще один механизм: pty(7)
обработка. Функции forkpty(3)
, openpty(3)
могут управлять новым псевдо-терминальным устройством, созданным специально для работы с другой программой. Расширенное программирование в среде Unix, 2-е издание содержит очень хороший пример pty
в своем исходном коде, хотя, если у вас возникли проблемы с пониманием, почему это было бы полезно, взгляните на script(1)
program - создает новый псевдотерминал и использует его для записи всех входных и выходных данных программ и сохраняет их в файле для последующего воспроизведения или документирования. Вы также можете использовать его для сценария действий в интерактивных программах, аналогично expect(1)
.