Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从lsof(Linux命令行)中提取字段/属性_Linux_Bash_Command Line_Flv - Fatal编程技术网

从lsof(Linux命令行)中提取字段/属性

从lsof(Linux命令行)中提取字段/属性,linux,bash,command-line,flv,Linux,Bash,Command Line,Flv,随着最近对Flash 10的迁移(或者可能是发行版的选择),我和其他许多人不再能够从/tmp复制Flash视频。但是,我在以下方面找到了解决办法: 首先,执行: lsof | grep Flash 它应该返回如下输出: plugin-co 8935 richard 16w REG 8,1 4139180 8220 /tmp/FlashXXq4KyOZ (deleted) p16471 f16 n/tmp/FlashXXq4KyOZ f17 n

随着最近对Flash 10的迁移(或者可能是发行版的选择),我和其他许多人不再能够从/tmp复制Flash视频。但是,我在以下方面找到了解决办法:

首先,执行:

lsof | grep Flash
它应该返回如下输出:

plugin-co 8935    richard   16w      REG        8,1   4139180       8220 /tmp/FlashXXq4KyOZ (deleted)
p16471
f16
n/tmp/FlashXXq4KyOZ
f17
n/tmp/FlashXXq4KyOZ
p26588
f16
n/tmp/FlashYYh3JwIW
f17
fds[pids[c]]+=${line:1}" "
注意:您可以在这里看到问题,…tmp文件释放了文件指针

但是,您可以使用cp命令抓取文件,因此:

cp /proc/#/fd/# video.flv
其中,第一个是进程ID(8935),第二个是下一个数字(16,从16w开始)

目前,这是可行的,但需要一些手动步骤。为了实现自动化,我想我可以提取PID和fd编号,并将它们动态地插入到cp命令中

我的问题是如何将适当的字段拉入变量?我知道您可以使用$1等来获取输入参数,但如何检索输出


注意:我可以使用
pidof plugin container
查找PID,但我仍然需要另一个数字(因为它告诉我要保存哪个特定的flash视频)。

以下命令将返回
/tmp
中所有文件名以“flash”开头的PID和FDs

输出将如下所示:

plugin-co 8935    richard   16w      REG        8,1   4139180       8220 /tmp/FlashXXq4KyOZ (deleted)
p16471
f16
n/tmp/FlashXXq4KyOZ
f17
n/tmp/FlashXXq4KyOZ
p26588
f16
n/tmp/FlashYYh3JwIW
f17
fds[pids[c]]+=${line:1}" "
其中字段标识符为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
在PID索引的数组中存储的字符串中累积文件描述符。对包含空格的文件名执行此操作将失败。如果有必要的话,可以解决这个问题

该行通过使用子字符串运算符从前导字段描述符字符中剥离:
${line:1}
从位置1开始,并包含字符串的其余部分,因此它会删除字符零


第二个循环只是一个演示,用于显示对数组的迭代。

避免使用lsof,因为返回路径需要太长(>30秒)。下面的.bashrc行将与vlc、mplayer或您输入的任何内容一起使用,并在毫秒内返回已删除临时文件的路径。
flashplay(){
vlc$(stat-c%N/proc/*/fd/*2>&1|awk-F[\`\']''']'/lash/{print$2}')
}

已完成的脚本:

#!/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

谢谢我最终使用了:pid=$(lsof | grep Flash | awk'{print$2}')file_num=$(lsof | grep Flash | awk'{print substr($4,1,2)}')@Richard:请将您的解决方案作为自己的答案发布,以便更好地查找。这很有趣……我很欣赏演示如何使用lsof的内置开关。不幸的是,此脚本无法工作,因为/tmp中的文件总是被删除。以前,您可以只复制/粘贴文件,但现在它已取消链接,唯一的检索方法是通过/proc。这就是为什么我必须将lsof的输出传输到grep。这允许-F开关仅打印名称(n参数)。但同样,这是一次很好的学习经历,我感谢您。@JohnSmith:您仍然可以使用
-F
选项。迭代输出,在找到“p”和“f”项时保存它们,当您找到要查找的“n”项时,您就有了所需的内容。如果在找到要查找的“n”之前找到一个新的“p”条目,请删除前一个条目并继续。顺便说一下,
lsof
发行版中包含了一些示例AWK和Perl脚本。哇,我喜欢它的速度。我将vlc更改为cp并添加了一个目的地(通常是点)。唯一的问题是它复制了/proc/pid/fd/中的所有文件,但我真的只想过滤到一个文件。有关脚本的当前形式,请参见上面的答案。