- Linux, отключить /dev /fd0 (гибкий диск)
- 3 ответа
- Linux на Дискете.
- 🇧🇼 Как использовать fd для быстрого поиска файлов в Linux и macOS
- Установка fd на Linux
- Ubuntu
- Debian
- Fedora
- Arch Linux
- Gentoo Linux
- macOS
- Использование fd в Linux
- Выполнение команды по результатам
- Файл дескриптор в Linux с примерами
- Тузик
- Файл дескриптор
- Redirect и Pipe
- Программируем уже запущенный процесс
- Немного усложним задачу
Linux, отключить /dev /fd0 (гибкий диск)
Возможно ли, чтобы ядро Linux полностью игнорировало контроллер гибких дисков? У меня нет диска, но, очевидно, моя материнская плата содержит контроллер. Я бы хотел отключить узел устройства /dev/fd0 каким-то образом, чтобы избежать Thunar и других инструментов, обнаруживающих его и исследующих.
3 ответа
В Ubuntu в качестве модуля загружается драйвер floppy . Вы можете занести в черный список этот модуль, чтобы он не загружался:
Сразу же после перезагрузки драйвер флоппи-дисковода должен быть отправлен навсегда.
Наличие или отсутствие флоппи-дисковода — это то, что настроено в BIOS системы. Вы должны вручную сообщить BIOS, какой тип флоппи у вас есть, и он, в свою очередь, сообщает ОС. Это связано с тем, что аппаратное обеспечение фактически не может быть обнаружено автоматически.
Итак, вам нужно зайти в свой BIOS и сказать, что у вас нет дискеты.
Я столкнулся с этой проблемой даже с помощью V & gt ;! Host = Windows Server 2012 Essentials. Гость = Linux Mint 14. Аппаратное обеспечение = HP Proliant ML350, без флоппи-дисковода. Проблема не возникла ни у кого из других гостей.
VMware WS 9. Определите Linux Mint как Ubuntu 64. Удалите виртуальную флоппи-дисковод перед установкой из ISO.
Сообщенная ошибка = Error mounting system managed device /dev/fd0. Command line . /media/flopp0 exited with non-zero . /dev/fd0 is not a valid block device.
/dev/fd0 пытался монтировать в fstab . /dev/fd0 . /media/floppy и /media/floppy существуют. Удалено /dev/fd0 из fstab . Удалите каталоги floppy и floppy0 (с —- +: = 10 =: + —-, конечно).
Перезагрузка — та же ошибка sudo и /dev/fd0 были воссозданы.
Используется команда выше. Rebooted. Нет ошибки.
Источник
Linux на Дискете.
1.Предисловие.
2. Права и отказ от обязательств.
3. О чем мужик шумит.
4. Минимальные требования.
5. К барьеру.
5.1 Файловая система.
6. Что на диске твоем.
7. Как быть дальше.
8. Обработка напильником.
9. Автор.
10. Литература.
1.Предисловие.
В первую очередь хочется сказать, что на отработку данного материала я лично потратил уйму времени. Этот материал представляет собой краткую информацию о создании специализированных загрузочных дисков. А не тех, которые вы можете сделать выполнением команды
mkbootdisk -device /dev/fd0 2.4.21
или с помощью утилиты rawrite из под Windows или MS-DOS.
2. Права и отказ от обязательств.
Вся содержащаяся в этом тексте информация предназначеная для Linux и Intel платформ, но так же может быть использована и для других процессоров. Все написанное здесь написано лишь с целью оказаться полезной информацией, но не является непосредственной инструкцией к действию.
3. О чем мужик шумит.
Загрузочным диском в данном конкретном случае я хочу назвать «полноценную Linux — систему в миниатюре», т.е мы будем говорить о загрузочном диске самодостаточном для самостоятельного старта и работы. Наверное, вы уже встречали такие Linux — системы. Например, мне первое, что попало в руки это дискета на 3,5″ с помощью которой поднимался роутер (freesco), все ПО для запуска и конфигурирования было на нем, и было самодостаточным. Честно говоря никода бы не полез в эти дебри, если бы не старое ядро. Я не буду здесь говорить о типах загрузочных дисков, все это в полной мере вы можете прочитать в Boot Disk-How-To.
4. Минимальные требования.
Для работы нам потребуется флопповод (/dev/fd0 хотя бы).
Поддержка петлевого интерфейса ядром. Проверить наличие поддержки можно набрав команду
Нам понадобятся исходники ядра и четкое представление о том, что должен делать диск, а так же положительный опыт сборки ядра.
5. К барьеру.
Я никого не хочу пугать, но если ваша рабочая Linux — система живет как минимум на 600 Мб (приблизительный размер RedHat 7.2 в режиме разработчика без X-oв). То здесь нам придется немного попотеть, что бы запихнуть все, что нам понадобится как минимум на 1400 Кб. Почувствуйте разницу.
И так без чего никак не обойтись:
1.минимальный набор каталогов: /bin; /proc; /lib; /dev; /etc; /usr; /tmp;
2.минимальный набор утилит: mv; cp; ls; sh и прочих
3. минимальный набор конфигурационных файлов: rc; inittab; fstab и прочих
4. /dev/hd*; /dev/tt*; /dev/fd0 и прочие
5.1 Файловая система.
Сформировать файловую систему для загрузочного диска можно двумя способами:
1.Используя RAM — диск, если ваша базовое ядро поддерживает RAM — диски.Поддерживается по умолчанию линейкой 2.4.хх.
2.Используя петлевое устройство (loopback device), если ваше базовое ядро поддерживает loopback devices.
Поддержка RAM — дисков понадобится нам и для работы нашего загрузочного диска. Так как я не прибегал к первому способу формирования файловой системы, то как следствие мы будем действовать по второму.
Для начала сформируем файл заполненный 0, в котором мы будем создавать файловую систему нашего загрузочного диска.
#dd if=/dev/zero of=/tmp/fsfile bs=1k count=4000
Таким образом, мы получим файл размером 4096 Кб, этого нам будет вполне достаточно для корня файловой системы, но об этом позже.
Теперь мы его отформатируем. Есть несколько вариантом mke2fs, mkfs.ext3, mkfs.xfs и mkfs.raiserfs. Здесь выбор за вами я пользовался mke2fs преследуя только свои интересы.
#mke2fs -m 0 -N 2000 /tmp/fsfile
По правилам использования этих и других опций читайте # man mke2fs и прочии маны.
#mkdir /mnt/rootfs
#mount -o loop /tmp/filefs /mnt/rootfs
6. Что на диске твоем.
Поймите меня правильно, но я не стану сейчас описывать в какой директории, что у вас лежит или, что должно лежать это займет несколько страниц и полностью отвлечет от темы. Подробности все в том же Boot-Disk-How-To.
Создаем каталоги /bin; /sbin; /dev; /var; /usr; /proc; /etc; /lib; /mnt;на нашей файловой системе.
#cp -dpR /dev/fd0* /mnt/rootfs/dev/
#cp -dpR /dev/ram? /mnt/rootfs/dev/
#cp -dpR /dev/tty6 /mnt/rootfs/dev/
#cp -dpR /dev/hd[a-c]* /mnt/rootfs/dev/
Ну и все иные устройства, поддержка которых необходима, но не перестарайтесь.
На самом деле можно и не копировать все эти устройства, а можно заставить rc скрипт выполнять mknod для необходимых устройств. Но не забудьте, что console; mem; kmem; null; ram0 должны быть обязательно.
Заполняем /etc
Здесь все согласно ваших намерений, могу только указать то, что необходимо на 100%
1.rc
2.inittab
3.fstab
На самом деле здесь большое поле для исследовательской деятельности и все остальное, что вы внесете сюда зависит только от вашей задачи.
Самый простой rc
#!/bin/sh
/bin/mount -av
/bin/hostname Diskotech
/bin/sh
Самый простой fstab
/dev/ram0 / ext2 defaults 1 1
/proc /proc proc defaults 0 0
Самый простой inittab
id:2:initdefault
si::sysinit:/etc/rc
1: 2345: respawn: /sbin/getty 9600 /dev/tty1
2: 23: respawn: /sbin/getty 9600 /dev/tty2
Заполняем /bin
Тут Начинается самое веселое, столько всего, а места на диске практически и нет, без паники! Все лечится! Берем пакет busybox, собираем у себя и читаем мануал. В зависимости от версии «полной коробочки» у вас будут различное и ее наполнение.
# cp -R /bin/busybox /mnt/rootfs/bin/
И создаем все возможные софтлинки.
Заполняем /lib
Ну тут все совсем просто
#ldd /sbin/mke2fs
libext2fs.so.2 => /lib/libext2fs.so.2 (0x40025000)
libcom_err.so.2 => /lib/libcom_err.so.2 (0x4003c000)
libe2p.so.2 => /lib/libe2p.so.2 (0x4003e000)
libuuid.so.1 => /lib/libuuid.so.1 (0x40043000)
libc.so.6 => /lib/libc.so.6 (0x40046000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000
С помощью команды ldd мы выясним все необходимые нам библиотеки и скопируем их в
/mnt/rootfs/lib используя ключ -R дабы софтлинки были скопированы без нарушений.
Заполняем /lib/modules
В этом нам поможет modules.conf или lsmod кому, что нравится. Самое главное не забыть модулей файловой системы с которой придется работать если она отлична от файловой системы загрузочного диска. Не забудте vfat.o мне это стоило больших неприятностей, когда заказчик не смог примонтировать саму дискету. Что лежит у меня? Дрова CD_ROM. Дрова мультипортовки, и прочее.
7. Как быть дальше.
Если формирование корневого каталога закончено самое время начать волноваться посильнее. Все дело в том, что теперь могут начаться проблемы. Но об этом позже.
#umount /mnt/rootfs
#gzip -v9 /tmp/fsfile
И так образ нашей корневой файловой системы готов. В сжатом виде составляет, что-то вроде 650 Kb. Переходим к следующему этапу, формированию самого диска.
8. Обработка напильником.
Что ж переходим к этапу формирования ядра. Первоначально дабы не озадачиваться персональной сборкой ядра. Предлагаю самое простое это просто выполнить
#cd /usr/src/linux
#make bzImage
И посмотреть какого размера получится ядро. Если те же 650-800 Kb, то вполне приемлемый размер. Если ядро всетаки большое, то придется потратить часок другой на удаление лихних компонентов. Хочу напомнить, что ядро должно поддерживать в обязательном порядке RAM- диски, размер RAM диска по умолчанию 4096 байт, можно и больше в описываемом случае в этом нет необходимости. Так же в ядро должна быть вкомпилированная поддержка корневой файловой системы.
Теперь маленькая хитрость, что бы не выполнять десяток операций по созданию загрузочных записей на диске, выполним всего одну
#mkbootdisk -device /dev/fd0 2.4.21
тем самым сформируем шаблон загрузочной дискеты размером 1,44 Mb, если этого размера изначально не хватает, то сформируем дискетку побольше
#mkbootdisk -device /dev/fd0u1680 2.4.21
По крайней мере мне такого размера хватало за глаза.
Теперь монтируем нашу дискету и заполним ее необходимой информацией. То есть скопируем на нее образ корневой файловой системы
#cp /tmp/fsfile.gz /mnt/floppy
Запускаем любимый текстовый редактор, правим файл syslinux.cfg и пишем что-то вроде приведенного ниже текста.
default update
vga=4
prompt 1
display boot.msg
timeout 100
label update
kernel bzImage
append initrd=fsfile.gz rw root=/dev/ram
Вот собственно и все. Наш корневой загрузочный диск готов.
9. Автор.
Andrew E. Kuznetsoff aka Разгильдяй на обкуренной кошке.
10. Литература.
Источник
🇧🇼 Как использовать fd для быстрого поиска файлов в Linux и macOS
fd – более простая альтернатива команде find.
Она использует усеченный синтаксис и сокращенную структуру команд, чтобы ваши набранные команды были короткими и точными.
Однако это отсутствие многословия, которое упрощает ввод fd, усложняет понимание.
fd также выполняет сопоставление с шаблоном быстрее, чем команды поиска по умолчанию.
Узнайте, как использовать fd в Linux и macOS.
Установка fd на Linux
fd не поставляется во многих системах по умолчанию.
Вам нужно будет использовать предпочитаемый менеджер пакетов для загрузки и установки приложения, а затем вы сможете запустить его из терминала.
Ubuntu
Он будет поставляться на Ubuntu Disco Dingo 19.04, но в противном случае вам придется скачать и установить его.
Для Ubuntu и других дистрибутивов Linux на основе Debian вы должны выполнить следующие команды для загрузки и установки программы.
Если вам нужна 32-битная версия или другая сборка, загрузите ее со страницы релизов GitHub для fd.
Debian
На Debian Buster или новее вы можете установить fd из официального репозитория, поддерживаемого Debian.
Fedora
На Fedora 28, fd может быть установлен из официальных версий пакета.
Arch Linux
Аналогично, пользователи Arch могут получить fd из официальных репозиториев:
Gentoo Linux
Пользователи Gentoo могут использовать следующую команду для загрузки fd ebuild:
macOS
Если вы используете macOS, установите Homebrew, затем используйте команду ниже для установки fd:
Использование fd в Linux
Команды fd имеют базовую структуру шаблона fd по сравнению с find. -наименование «шаблон».
Чтобы найти файл по его имени, используйте следующую команду:
Этот поиск выполняется в предустановленном рабочем каталоге, включая подкаталоги.
Для поиска в определенном каталоге, укажите его после поискового запроса:
Выполнение команды по результатам
Как и find, fd имеет функциональность, которая передает найденные файлы другой команде для выполнения.
Где используется find . -iname pattern -exec command ,команда, fd использует флаг -x:
Эта команда отправит все zip-файлы в каталоге команде unzip.
Вы можете использовать следующие символы в «фразе» команды execute для передачи информации определенным образом.
Источник
Файл дескриптор в Linux с примерами
Однажды, на одном интервью меня спросили, что ты будешь делать, если обнаружишь неработающий сервис из-за того, что на диске закончилось место?
Конечно же я ответил, что посмотрю, чем занято это место и если возможно, то почищу место.
Тогда интервьюер спросил, а что если на разделе нет свободного места, но и файлов, которые бы занимали все место, ты тоже не видишь?
На это я сказал, что всегда можно посмотреть открытые файл дескрипторы, например командой lsof и понять какое приложение заняло все доступное место, а дальше можно действовать по обстоятельствам, в зависимости от того, нужны ли данные.
Интервьюер прервал меня на последнем слове, дополнив свой вопрос: «Предположим, что данные нам не нужны, это просто дебаг лог, но приложение не работает из-за того, что не может записать дебаг»?
«окей», — ответил я, «мы можем выключить дебаг в конфиге приложения и перезапустить его».
Интервьюер возразил: «Нет, приложение мы перезапустить не можем, у нас в памяти все еще хранятся важные данные, а к самому сервису подключены важные клиенты, которых мы не можем заставлять переподключаться заново».
«ну хорошо», сказал я, «если мы не можем перезапускать приложение и данные нам не важны, то мы можем просто очистить этот открытый файл через файл дескриптор, даже если мы его не видим в команде ls на файловой системе».
Интервьюер остался доволен, а я нет.
Тогда я подумал, почему человек, проверяющий мои знания, не копает глубже? А что, если данные все-таки важны? Что если мы не можем перезапускать процесс, и при этом этот процесс пишет на файловую систему в раздел, на котором нет свободного места? Что если мы не можем потерять не только уже записанные данные, но и те данные, что этот процесс пишет или пытается записать?
Тузик
В начале моей карьеры я пытался создать небольшое приложение, в котором нужно было хранить информацию о пользователях. И тогда я думал, а как мне сопоставить пользователя к его данным. Есть, например, у меня Иванов Иван Иваныч, и есть у него какие-то данные, но как их подружить? Я могу указать напрямую, что собака по имени «Тузик» принадлежит этому самому Ивану. Но что, если он сменит имя и вместо Ивана станет, например, Олей? Тогда получится, что наша Оля Ивановна Иванова больше не будет иметь собаки, а наш Тузик все еще будет принадлежать несуществующему Ивану. Решить эту проблему помогла база данных, которая каждому пользователю давала уникальный идентификатор (ID), и мой Тузик привязывался к этому ID, который, по сути, был просто порядковым номером. Таким образом хозяин у тузика был с ID под номером 2, и на какой-то момент времени под этим ID был Иван, а потом под этим же ID стала Оля. Проблема человечества и животноводства была практически решена.
Файл дескриптор
Проблема файла и программы, работающей с этим файлом, примерно такая же как нашей собаки и человека. Предположим я открыл файл под именем ivan.txt и начал в него записывать слово tuzik, но успел записать только первую букву «t» в файл, и этот файл был кем-то переименован, например в olya.txt. Но файл остался тем же самым, и я все еще хочу записать в него своего тузика. Каждый раз при открытии файла системным вызовом open в любом языке программирования я получаю уникальный ID, который указывает мне на файл, этот ID и есть файл дескриптор. И совершенно не важно, что и кто делает с этим файлом дальше, его могут удалить, его могут переименовать, ему могут поменять владельца или забрать права на чтение и запись, я все равно буду иметь к нему доступ, потому что на момент открытия файла у меня были права для его чтения и/или записи и я успел начать с ним работать, а значит должен продолжать это делать.
В Linux библиотека libc открывает для каждого запущенного приложения(процесса) 3 файл дескриптора, с номерами 0,1,2. Больше информации вы можете найти по ссылкам man stdio и man stdout
- Файл дескриптор 0 называется STDIN и ассоциируется с вводом данных у приложения
- Файл дескриптор 1 называется STDOUT и используется приложениями для вывода данных, например командами print
- Файл дескриптор 2 называется STDERR и используется приложениями для вывода данных, сообщающих об ошибке
Если в вашей программе вы откроете какой-либо файл на чтение или запись, то скорее всего вы получите первый свободный ID и это будет номер 3.
Список файл дескрипторов можно посмотреть у любого процесса, если вы знаете его PID.
Например, откроем консоль с bash и посмотрим PID нашего процесса
Во второй консоли запустим
Файл дескриптор с номером 255 можете смело игнорировать в рамках данной статьи, он был открыт для своих нужд уже самим bash, а не прилинкованной библиотекой.
Сейчас все 3 файл дескриптора связаны с устройством псевдотерминала /dev/pts, но мы все равно можем ими манипулировать, например запустим во второй консоли
И в первой консоли мы увидим
Redirect и Pipe
Вы можете легко переопределить эти 3 файл дескриптора в любом процессе, в том числе и в bash, например через трубу(pipe), соединяющую два процесса, смотрим
Вы можете сами запустить эту команду с strace -f и увидеть, что происходит внутри, но я вкратце расскажу.
Наш родительский процесс bash с PID 15771 парсит нашу команду и понимает сколько именно команд мы хотим запустить, в нашем случае их две: cat и sleep. Bash знает что ему нужно создать два дочерних процесса, и объединить их одной трубой. Итого bash потребуется 2 дочерних процесса и один pipe.
Перед созданием дочерних процессов bash запускает системный вызов pipe и получает новые файл дескрипторы на временный буфер pipe, но этот буфер никак пока не связывает наши два дочерних процесса.
Для родительского процесса это выглядит так будто pipe уже есть, а дочерних процессов еще нет:
Затем с помощью системного вызова clone bash создает два дочерних процесса, и наши три процесса будут выглядеть так:
Не забываем, что clone клонирует процесс вместе со всеми файл дескрипторами, поэтому в родительском процессе и в дочерних они будут одинаковые. Задача родительского процесса с PID 15771 следить за дочерними процессами, поэтому он просто ждет ответ от дочерних.
Следовательно pipe ему не нужен, и он закрывает файл дескрипторы с номерами 3 и 4.
В первом дочернем процессе bash с PID 9004, системным вызовом dup2, меняет наш STDOUT файл дескриптор с номером 1 на файл дескриптор указывающий на pipe, в нашем случае это номер 3. Таким образом все, что первый дочерний процесс с PID 9004 будет писать в STDOUT, будет автоматически попадать в буфер pipe.
Во втором дочернем процессе с PID 9005 bash меняет с помощью dup2 файл дескриптор STDIN с номером 0. Теперь все, что будет читать наш второй bash с PID 9005, будет читать из pipe.
После этого в дочерних процессах так же закрываются файл дескрипторы с номерами 3 и 4, так как они более не используются.
Файл дескриптор 255 я намеренно игнорирую, он использует для внутренних нужд самого bash и в дочерних процессах будет также закрыт.
Далее в первом дочернем процессе с PID 9004 bash запускает с помощью системного вызова exec исполняемый файл, который мы указали в командной строке, в нашем случае это /usr/bin/cat.
Во втором дочернем процессе с PID 9005 bash запускает второй исполняемый файл, который мы указали, в нашем случае это /usr/bin/sleep.
Системный вызов exec не закрывает файл дескрипторы, если они не были открыты с флагом O_CLOEXEC во время выполнения вызова open. В нашем случае после запуска исполняемых файлов все текущие файл дескрипторы сохранятся.
Проверяем в консоли:
Как видите уникальный номер нашего pipe у нас в обоих процессах совпадает. Таким образом у нас есть связь между двумя разными процессами с одним родителем.
Для тех, кто не знаком с системными вызовами, которые использует bash, крайне рекомендую запустить команды через strace и посмотреть, что происходит внутри, например, так:
Вернемся к нашей проблеме с нехваткой места на диске и попыткой сохранить данные без перезапуска процесса. Напишем небольшую программу, которая будет записывать на диск примерно 1 мегабайт в секунду. При этом если по какой-либо причине мы не смогли записать данные на диск, мы будем просто игнорировать это и пытаться записать данные вновь через секунду. В примере я использую Python, вы можете использовать любой другой язык программирования.
Запустим программу и посмотрим на файл дескрипторы
Как видим у нас есть наши 3 стандартные файл дескрипторы и еще один, который мы открыли. Проверим размер файла:
данные пишутся, пробуем поменять права на файл:
Видим, что данные все еще пишутся, хотя наш пользователь не имеет права писать в файл. Попробуем его удалить:
Куда пишутся данные? И пишутся ли вообще? Проверяем:
Да, наш файл дескриптор все еще существует, и мы можем работать с этим файл дескриптором как с нашим старым файлом, мы можем его читать, очищать и копировать.
Смотрим на размер файла:
Размер файла 19923457. Пробуем очистить файл:
Как видим размер файла только увеличивается и наш транкейт не сработал. Обратимся к документации по системному вызову open. Если при открытии файла мы используем флаг O_APPEND, то при каждой записи операционная система проверяет размер файла и пишет данные в самый конец файла, причем делает это атомарно. Это позволяет нескольким тредам или процессам писать в один и тот же файл. Но в нашем коде мы не используем этот флаг. Мы можем увидеть другой размер файла в lsof после транкейт только если откроем файл для дозаписи, а значит в нашем коде вместо
мы должны поставить
Проверяем с «w» флагом
Программируем уже запущенный процесс
Часто программисты при создании и тестировании программы используют дебагеры (например GDB) или различные уровни логирования в приложении. Linux предоставляет возможность фактически писать и менять уже запущенную программу, например менять значения переменных, устанавливать breakpoint и тд и тп.
Возвращаясь к оригинальному вопросу с нехваткой места на диске для записи файла, попробуем сэмулировать проблему.
Создадим файл для нашего раздела, который мы подмонтируем как отдельный диск:
Создадим файловую систему:
Подмонтируем файловую систему:
Создаем директорию с нашим владельцем:
Откроем файл только на запись в нашей программе:
Ждем несколько секунд
Итак, мы получили проблему, описанную в начале этой статьи. Свободного места 0, занятого 100%.
Мы помним, что по условиям задачи мы пытаемся записать очень важные данные, которые нельзя потерять. И при этом нам нужно починить сервис без перезапуска процесса.
Допустим, у нас все же есть место на диске, но в другом разделе, например в /home.
Попробуем «перепрограммировать на лету» наш код.
Смотрим PID нашего процесса, который съел все место на диске:
Подключаемся к процессу через gdb
Смотрим открытые файл дескрипторы:
Смотрим информацию о файл дескрипторе с номером 3, который нас интересует
Помня о том, какой системный вызов делает Python (смотрите выше, где мы запускали strace и находили вызов open), обрабатывая наш код для открытия файла, мы делаем то же самое самостоятельно от имени нашего процесса, но биты O_WRONLY|O_CREAT|O_TRUNC нам нужно заменить на числовое значение. Для этого открываем исходники ядра, например тут и смотрим какие флаги за что отвечают
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
Объединяем все значения в одно, получаем 00001101
Запускаем наш вызов из gdb
Итак мы получили новый файл дескриптор с номером 4 и новый открытый файл на другом разделе, проверяем:
Мы помним пример с pipe — как bash меняет файл дескрипторы, и уже выучили системный вызов dup2.
Пробуем подменить один файл дескриптор другим
Закрываем файл дескриптор 4, так как нам он не нужен:
И выходим из gdb
Проверяем новый файл:
Как видим, данные пишутся в новый файл, проверяем старый:
Данные не потеряны, приложение работает, логи пишутся в новое место.
Немного усложним задачу
Представим, что данные нам важны, но места на диске у нас нет ни в одном из разделов и подключить диск мы не можем.
Что мы можем сделать, так это перенаправить куда-то наши данные, например в pipe, а данные из pipe в свою очередь перенаправить в сеть через какую-либо программу, например netcat.
Мы можем создать именованный pipe командой mkfifo. Она создаст псевдофайл на файловой системе, даже если на ней нет свободного места.
Перезапускаем приложение, и проверяем:
Места на диске нет, но мы успешно создаем там именованный pipe:
Теперь нам надо как-то завернуть все данные, что попадают в этот pipe на другой сервер через сеть, для этого подойдет все тот же netcat.
На сервере remote-server.example.com запускаем
На нашем проблемном сервере запускаем в отдельном терминале
Теперь все данные, которые попадут в pipe автоматически попадут на stdin в netcat, который их отправит в сеть на порт 7777.
Все что нам осталось сделать это начать писать наши данные в этот именованный pipe.
У нас уже есть запущенное приложение:
Из всех флагов нам нужен только O_WRONLY так как файл уже существует и очищать нам его не нужно
Проверяем удаленный сервер remote-server.example.com
Данные идут, проверяем проблемный сервер
Данные сохранились, проблема решена.
Пользуясь случаем, передаю привет коллегам из компании Degiro.
Слушайте подкасты Радио-Т.
В качестве домашнего задания предлагаю подумать, что будет в файл дескрипторах процесса cat и sleep если запустить такую команду:
Источник