Сначала я запускаю команду cat > foo1
в одном сеансе и проверяю, что данные из stdin копируются в файл. Затем в другой сессии я перенаправляю вывод.
Сначала найдите PID процесса:
$ ps aux | grep cat
rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat
Теперь проверьте дескрипторы файлов, которые у него открыты:
$ ls -l /proc/6760/fd
total 3
lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1
lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5
Теперь запустите GDB:
$ gdb -p 6760 /bin/cat
GNU gdb 6.4.90-debian
[license stuff snipped]
Attaching to program: /bin/cat, process 6760
[snip other stuff that's not interesting now]
(gdb) p close(1)
$1 = 0
(gdb) p creat("/tmp/foo3", 0600)
$2 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760
Команда p
в GDB напечатает значение выражения, выражение может быть функцией для вызова, это может быть системный вызов ... Поэтому я выполняю системный вызов close()
и передаю дескриптор файла 1, затем Я выполняю системный вызов creat()
, чтобы открыть новый файл. Результат creat()
был 1, что означает, что он заменил предыдущий дескриптор файла. Если бы я хотел использовать один и тот же файл для stdout и stderr или если бы я хотел заменить дескриптор файла каким-то другим номером, то мне нужно было бы вызвать системный вызов dup2()
для достижения этого результата.
Для этого примера я решил использовать creat()
вместо open()
, потому что здесь меньше параметров. Макросы C для флагов не могут использоваться из GDB (он не использует заголовки C), поэтому я должен был бы прочитать файлы заголовков, чтобы обнаружить это - это не так сложно сделать, но это займет больше времени. Обратите внимание, что 0600 является восьмеричным разрешением для владельца, имеющего права на чтение / запись, и для группы и других, не имеющих доступа. Также будет полезно использовать 0 для этого параметра и позже запустить chmod для файла.
После этого я проверяю результат:
ls -l /proc/6760/fd/
total 3
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 <====
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5
Ввод дополнительных данных в cat
приводит к добавлению файла /tmp/foo3
.
Если вы хотите закрыть исходный сеанс, вам нужно закрыть все файловые дескрипторы для него, открыть новое устройство, которое может быть управляющим tty, а затем вызвать setsid()
.