我有一个封闭的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字节后,命名管道缓冲区变满了,另一个程序取得了所有并关闭了管道。
但是过了一会儿,正在读取管道的另一个程序关闭管道,我的管道出现故障。是否有可能创建除保险丝和管道之外的虚拟文件?
答案 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 的键盘输入,这种方法将无效。