Извлечь поля / атрибуты из lsof (командной строки Linux) - PullRequest
3 голосов
/ 21 февраля 2011

С недавним переходом на Flash 10 (или, возможно, это был дистрибутив), я и многие другие больше не можем копировать Flash-видео из / tmp.Однако я нашел обходной путь в следующем:

Во-первых, выполните:

lsof | grep Flash

, который должен возвращать вывод, подобный этому:

plugin-co 8935    richard   16w      REG        8,1   4139180       8220 /tmp/FlashXXq4KyOZ (deleted)

Примечание: выЗдесь можно увидеть проблему ... файл / tmp имеет освобожденный указатель файла.

Однако вы можете получить файл, используя команду cp:

cp /proc/#/fd/# video.flv

где 1-й номер - это идентификатор процесса (8935), а второй - следующий номер (16, из 16w).

В настоящее время это работает, но требует нескольких ручных шагов.Чтобы автоматизировать это, я полагаю, что я мог бы извлечь PID и номер fd и динамически вставить их в команду cp.

Мой вопрос: как мне перетащить соответствующие поля в переменные?Я знаю, что вы можете использовать $ 1 и т. Д. Для получения входных аргументов, но как вы извлекаете выходные данные?

Примечание: я мог бы использовать pidof plugin-container, чтобы найти PID, но мне все еще нужен другой номер (так как онрассказывает, какое конкретное флэш-видео сохранить).

Ответы [ 4 ]

5 голосов
/ 21 февраля 2011

Следующая команда вернет PID и FD для всех файлов в /tmp, имена файлов которых начинаются с «Flash»

lsof -F pfn /tmp/Flash*

, и результат будет выглядеть примерно так:

p16471
f16
n/tmp/FlashXXq4KyOZ
f17
n/tmp/FlashXXq4KyOZ
p26588
f16
n/tmp/FlashYYh3JwIW
f17

Где идентификаторы полей: p: PID, f: FD, n: NAME.Опция -F предназначена для упрощения анализа выходных данных lsof.

Итерирование по ним и удаление идентификаторов полей тривиально.

#!/bin/bash
c=-1
while read -r line
do
    case $line in
        f*)
            fds[pids[c]]+=${line:1}" "
            ;;
        n*)
            names[pids[c]]+=${line:1}" "
            ;;
        p*)
            pids[++c]=${line:1}
            ;;
    esac
done < <(lsof -F pfn -- /tmp/Flash*)

for ((i=0; i<=c; i++))
do
    for name in ${names[pids[i]]}
    do
        for fd in ${fds[pids[i]]}
        do
            echo "File: $name, Process ID: ${pids[i]}, File Descriptor: $fd"
        done
    done
done

Строки, подобные этой:

fds[pids[c]]+=${line:1}" "

накапливает файловые дескрипторы в строке, хранящейся в массиве, индексированном с помощью PID.Делать это для имен файлов не удастся для имен файлов, которые содержат пробелы.В случае необходимости это можно обойти.

Строка удаляется из символа дескриптора ведущего поля с помощью оператора подстроки: ${line:1} начинается с первой позиции и включает в себя оставшуюся часть строки, поэтому она сбрасывает нулевой символ.

Второй цикл - это просто демонстрация, демонстрирующая итерации по массивам.

2 голосов
/ 21 февраля 2011
var=$(lsof | awk '/Flash/{gsub(/[^0-9]/,"",$4);print $2 FS $4};exit')
set -- $var
pid=$1
number=$2
1 голос
/ 10 сентября 2012

Завершенный сценарий:

#!/bin/sh

if [ $1 ]; then
    #lsof | grep Flash | awk '{print $2}' also works for PID
    pid=$(pidof plugin-container)
    file_num=$(lsof -p $pid | grep /tmp/Flash | awk '{print substr($4,1,2)}')

    cp /proc/$pid/fd/$file_num ~/Downloads/"$1".flv
else
    echo "Please enter video name as argument."
fi
0 голосов
/ 10 июня 2011

Избегайте использования lsof, потому что это займет слишком много времени (> 30 секунд), чтобы вернуть путь.Приведенная ниже строка .bashrc будет работать с vlc, mplayer или чем-то другим, что вы вставили, и вернет путь к удаленному временному файлу в миллисекундах.flashplay () { vlc $(stat -c %N /proc/*/fd/* 2>&1|awk -F[\`\'] '/lash/{print$2}') }

...