Примерно так:
$ cp /tmp/FlashIBmQCU video.flv
Поставив свежий пре-релиз флэш-плеера, который на днях обсуждали на хабре (у меня 64-битная система), я с удивлением обнаружил, что этот способ больше не работает, так как никакие файлы во временном каталоге не создаются. Рассудив, однако, что едва ли плеер хранит видео целиком в памяти, и куда-то он его всё-таки должен писать, я приступил к расследованию.
…То есть решил посмотреть список открытых плагином файлов. Для начала нам нужен PID процесса, в котором хостится плагин. Пользуюсь я Firefox-ом, так что искать будем просто:
$ ps x | grep firefox 9800 ? S 0:00 /bin/sh /usr/lib/firefox-3.6.9/firefox 9805 ? S 0:00 /bin/sh /usr/lib/firefox-3.6.9/run-mozilla.sh /usr/lib/firefox-3.6.9/firefox-bin 9809 ? Sl 14:58 /usr/lib/firefox-3.6.9/firefox-bin 10099 ? Sl 4:10 /usr/lib/firefox-3.6.9/plugin-container /usr/lib/mozilla/plugins/libflashplayer.so 9809 plugin 26199 pts/13 S+ 0:00 grep firefox
Как видно, Mozilla запускает плагин в отдельном процессе и его PID — 10099. Теперь список открытых файлов можно посмотреть командой
lsof
:$ lsof -p 10099 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME # поскипано 152 строки plugin-co 10099 rooslan mem REG 8,21 26048 2656 /usr/lib/gconv/gconv-modules.cache plugin-co 10099 rooslan mem REG 8,21 343 106080 /usr/lib/locale/ru_RU.utf8/LC_IDENTIFICATION plugin-co 10099 rooslan 0r CHR 1,3 3419 /dev/null plugin-co 10099 rooslan 1w FIFO 0,6 9649 pipe plugin-co 10099 rooslan 2w FIFO 0,6 9649 pipe plugin-co 10099 rooslan 3u unix 0xffff88007304a3c0 287192 socket plugin-co 10099 rooslan 4r 0000 0,7 0 32 anon_inode plugin-co 10099 rooslan 5w unix 0xffff8800c5425e40 287277 socket plugin-co 10099 rooslan 6r unix 0xffff8800c5424b00 287278 socket plugin-co 10099 rooslan 7w FIFO 0,6 287279 pipe plugin-co 10099 rooslan 8r FIFO 0,6 287279 pipe plugin-co 10099 rooslan 9w FIFO 0,6 287280 pipe plugin-co 10099 rooslan 10u FIFO 0,6 287280 pipe plugin-co 10099 rooslan 11u FIFO 0,6 287281 pipe plugin-co 10099 rooslan 12u FIFO 0,6 287281 pipe plugin-co 10099 rooslan 13u unix 0xffff88007304a100 287284 socket plugin-co 10099 rooslan 14u REG 8,24 376832 1409239 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/cert8.db plugin-co 10099 rooslan 15w REG 8,24 16384 1409240 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/key3.db plugin-co 10099 rooslan 16u REG 8,23 494641 16 /tmp/FlashXXlm7mcU (deleted) plugin-co 10099 rooslan 17u FIFO 0,6 404625 pipe plugin-co 10099 rooslan 18u FIFO 0,6 404625 pipe plugin-co 10099 rooslan 19r FIFO 0,6 404626 pipe plugin-co 10099 rooslan 20w FIFO 0,6 404626 pipe plugin-co 10099 rooslan 21r unix 0xffff880015a2b9c0 404630 socket
Всё самое интересное оказалось в конце и сразу перед глазами, но для порядка попробуем отфильтровать открытые процессом обычные (regular) файлы. Вероятно, это можно сделать встроенными средствами
lsof
, но размеры man lsof
быстро отбивают желание читать его для решения такой проходной задачи. Поэтому я предпочёл воспользоваться простым фильтром на AWK:$ lsof -p 10099 | awk '$4 ~ /^[0-9]+/ && $5 == "REG"' plugin-co 10099 rooslan 14u REG 8,24 376832 1409239 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/cert8.db plugin-co 10099 rooslan 15w REG 8,24 16384 1409240 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/key3.db plugin-co 10099 rooslan 16u REG 8,23 494641 16 /tmp/FlashXXlm7mcU (deleted)
Сразу стало понятно, куда делся наш временный файл: плагин удалил (unlink) ссылку на файл из каталога, но оставил открытым его дескриптор. Таким образом файл перестал быть виден в файловой системе, но не исчез, и окончательно удалён он будет только когда закроется последний ссылающийся на него дескриптор.
Но как нам теперь достать содержимое файла, открытого лишь одним процессом? Очень просто, с помощью файловой системы procfs. Каталог
/proc/$PID/fd
содержит символьные ссылки на все открытые процессом PID дескрипторы.$ ls -l /proc/10099/fd итого 0 lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 0 -> /dev/null l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 1 -> pipe:[9649] lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 10 -> pipe:[287280] lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 11 -> pipe:[287281] lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 12 -> pipe:[287281] lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 13 -> socket:[287284] lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 14 -> /home/rooslan/.mozilla/firefox/xxxxxxxx.default/cert8.db l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 15 -> /home/rooslan/.mozilla/firefox/xxxxxxxx.default/key3.db lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 16 -> /tmp/FlashXXpOdDuF (deleted) lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 17 -> pipe:[396658] lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 18 -> pipe:[396658] lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 19 -> pipe:[396659] l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 2 -> pipe:[9649] l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 20 -> pipe:[396659] lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 21 -> socket:[396663] lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 3 -> socket:[287192] lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 4 -> anon_inode:[eventpoll] l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 5 -> socket:[287277] lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 6 -> socket:[287278] l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 7 -> pipe:[287279] lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 8 -> pipe:[287279] l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 9 -> pipe:[287280]
(Вот, кстати, ещё один способ посмотреть открытые процессом файлы, помимо
lsof
).И, хотя readlink возвращает для некоторых из этих ссылок имена несуществующих файлов, из них можно спокойно читать (если права позволяют), чем мы и воспользуемся:
$ cp /proc/10099/fd/16 video.flv
Вот и всё. Это достаточно тривиальные вещи (многие, думаю, догадались, о чём пойдёт речь с одного лишь заголовка), но, надеюсь, для кого-то этот простой трюк окажется полезным.
Комментариев нет:
Отправить комментарий