Golang虚拟文件

时间:2016-10-19 08:16:31

标签: hadoop go named-pipes fuse

我有一个封闭的soruce应用程序,它将文件作为输入,计算其哈希并执行其他一些我无法控制的东西。修改源或逆向工程是不可行的。

该程序旨在使用常规文件,但我需要从HDFS提供一个非常大的文件。复制文件将占用磁盘上太多的时间和空间。所以我在考虑使用FUSE,但我没有找到一个好的解决方案。我尝试使用命名管道如下:

func readFile(namenode, path string, pipe *os.File) {
    client, err := hdfs.New(namenode)
    log.Println(err, client)

    hdfsFile, err := client.Open(path)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(hdfsFile)

    // written, err := io.Copy(pipe, hdfsFile)
    bytes := make([]byte, 4096)
    for {
        read, err := hdfsFile.Read(bytes)
        log.Println(read, err)
        if err != nil {
            break
        }
        written, err := pipe.Write(bytes)
        log.Println(written, err)
    }
    err = pipe.Close()
    log.Println(err)
}

我知道上面的代码不完整,测试文件是10MB,但是在读取8次4096字节后,命名管道缓冲区变满了,另一个程序取得了所有并关闭了管道。

但是过了一会儿,正在读取管道的另一个程序关闭管道,我的管道出现故障。是否有可能创建除保险丝和管道之外的虚拟文件?

2 个答案:

答案 0 :(得分:1)

我认为你实际上对FUSE有正确的想法。如果没有上游应用程序的源代码,很难说它试图使用哪种文件语义(虽然有时候使用strace可能有助于说明正在发生的事情。也许......)。

在任何情况下,我都会看一下the Go-FUSE project,特别是the hello.go example,它会详细说明如何处理单个文件的情况。

答案 1 :(得分:1)

我理解问题是封闭源程序2需要文件名并且不接受来自 stdin 的输入?

运行程序时,可以使用标准的Unix样式管道将进程的 stdin stdout 连接在一起。命名管道可能会有问题,因此使用FUSE过于复杂。

您可以让program1输出到 stdout 。并提供具有虚拟文件名/dev/stdin的封闭源程序2,如下所示:

program1 | program2 /dev/stdin

这假设您正在使用Linux(您没有指定,但我假设是因为您正在讨论FUSE)。

如果program2关心文件名(例如需要特定的名称扩展名),您可以通过创建一个符号链接来解决这个问题,该链接具有指向/dev/stdin的所需名称并提供名称符号链接作为program2的参数:

ln -s /dev/stdin file.ext
program1 | program2 file.ext
rm -f file.ext

如果program2需要一个可以 stat 的真实文件但在这种情况下不应该是一个问题(因为从program2接受命名管道的问题已知),这一切都不会起作用

此外,如果program2期望来自 stdin 的键盘输入,这种方法将无效。