“上传”管道就像上传普通文件一样

“上传”管道就像上传普通文件一样

假设我想将文件打包并压缩,以便上传到 Google Drive 或其他地方,但无需保存中间压缩包(例如,由于磁盘空间不足和/或磁盘是只读的)。借助命名文件描述符和命令替换,这听起来很容易,对吧?

exec {foo}< <(tar -c -z $SOME_DIRECTORY)
ln -L -s /dev/fd/${foo} ~/foo # "-L" may or may not be necessary here

遗憾的是,这似乎不起作用。当我尝试将此“文件”上传到 Google Drive 时(我还没有在其他地方测试过),它抱怨找不到该文件。所以我继续尝试查看出了什么问题。

$ ls -H -l /dev/fd # "-H" because "/dev/fd" itself is a symbolic link
lrwx------ 1 dlam dlam 64 Oct 16 12:53 0 -> /dev/pts/0
lrwx------ 1 dlam dlam 64 Oct 16 12:53 1 -> /dev/pts/0
lr-x------ 1 dlam dlam 64 Oct 16 12:53 10 -> pipe:[1334334] # In bold red
lrwx------ 1 dlam dlam 64 Oct 16 12:53 2 -> /dev/pts/0
lr-x------ 1 dlam dlam 64 Oct 16 12:53 3 -> /proc/16635/fd

看起来文件描述符10(当然是进程的描述符)链接到某种管道描述符或句柄,而不是实际的管道文件(ls显示为红色,好像表示链接断开)。使用-L而不是-Hls确实可以正确地取消引用它并报告正确的文件类型。

$ ls -L -l /dev/fd
total 0
crw--w---- 1 dlam tty  136, 0 Oct 16 12:58 0
crw--w---- 1 dlam tty  136, 0 Oct 16 12:58 1
prw------- 1 dlam dlam      0 Oct 16 12:52 10 # Correctly reported as a pipe
crw--w---- 1 dlam tty  136, 0 Oct 16 12:58 2
dr-x------ 2 dlam dlam      0 Oct 16 12:58 3

但是,尝试cat直接或通过符号链接确实会成功,因此肯定没有丢失或损坏。我的猜测是,某些东西正在逐字读取文件描述符链接,因此试图找到一个逐字命名为的文件pipe:[1334334],这可能是为什么甚至ls在没有开关的情况下认为它是一个断开的链接-L。无论如何,我该怎么做才能让它像读取要上传到 Google Drive 或其他地方的常规文件一样读取它?

更新

因此我尝试使用命名管道来mkfifo代替。

mkfifo foo
tar -c -z $SOME_DIRECTORY > foo &

但这也不太管用。在这种情况下,Google Drive 会抱怨它无法读取,但再次执行cat后,它又可以正常工作。

答案1

根据您下面的评论进行更新。

所以……你似乎想这样做。获取一个进程,将该进程连接stdout到 Firefox,并让 Firefox 在文件上传过程中将其作为文件的内容进行流式传输。你正在尝试使用管道/fifo 代替文件。

我认为这行不通,因为 Firefox 需要知道文件的大小,以便生成标Content-Length:头 - 这会告诉接收系统有多少数据即将到来。服务器可以配置为仅接收未知大小的数据,但这通常被认为是一个安全问题(这样很容易耗尽服务器资源)并且可能未在服务器端启用。因此,如果不对其进行修补,可能无法让 Firefox 采用 fifo 而不是文件。

如果您可以获取上传 URL 并找出上传页面的需求(例如 cookie 等),并且它不需要 Javascript,那么curl如果服务器端采用没有Content-Length:标头的 HTTP POST,您可能可以进行某些操作。


任何具有文件描述符的东西都只能从本地进程访问;无论是文件、fifo、设备节点等。

您可以在文件系统上创建这些文件,但实际上写入文件系统的物理内容实际上是特殊代码,这些代码会使本地操作系统在读取/写入时表现不同。尝试将这些“特殊文件”的实际内容发送到另一个系统(尤其是您无法控制的系统)并期望该系统表现得与您的系统一样,这将失败。

如果您想将它们连接到另一个系统,您必须使用本地连接到该文件描述符的本地程序,然后使用 TCP/IP 堆栈等向世界各地发送/接收数据。

相关内容