bounty将在4天后过期。回答此问题可获得+100声望奖励。zwol希望引起更多人关注此问题。
在可移植shell中,* 不 * 使用命名管道,启动一个后台进程,并让该进程的stdin成为在父shell中的文件描述符3(或其他大于2的数字)上打开的管道,这是可能的吗?另一种说法是,我想在可移植shell中做popen("some-program", "w")
在C中做的事情。
具体来说,执行以下代码段的操作,但不使用mkfifo
:
mkfifo fifo
some-program < fifo &
exec 3> fifo
rm fifo
注意:“bash”标签主要是为了可见性而添加的。我理解这是可能的using the "coprocess" extension in bash, ksh, or zsh;我正在寻找一种在 * 只有 * XPG Issue 6 (POSIX.1-2001) Shell and Utilities工具可用的环境中工作的技术。此外,使用命名管道(最明显的是通过mkfifo
)的答案将不会被接受,需要root
特权的答案也不会被接受。
不鼓励使用以下任何一种答案,但我会听到一个论点,即没有其中一种或多种答案是不可能做到的:
- 创建机器语言可执行文件的任何内容(例如
c99
) - 主要用于交互式使用的任何内容(例如
vi
) - 不属于第6版“Base”规范的任何内容,或在第6版或任何后续版本的POSIX中过时的任何内容(例如
uucp
)
我也会听到一个答案,这个答案会令人信服地证明,在上述限制范围内,这是不可能的。
(Why没有命名管道?因为它们的行为与普通管道不太一样,特别是在旧的、有缺陷的操作系统中,“只使用#!/bin/bash
“不是一个选项。此外,在文件系统中暴露管道,无论多么短暂,都意味着不能完全排除一些不相关的进程打开管道的可能性。)
3条答案
按热度按时间rlcwz9us1#
它必须是背景的 * 本身 * 吗?您能容忍不同的父进程吗?
使用环境变量来检测脚本的第二次调用可能会更可靠地作为单独的脚本重新实现。WARNING 行是您需要关注命令注入(CWE-78)的未来修订版本的地方。
进程的祖先将如下所示:
它们都在同一个进程组中,可能是从交互式环境(
-bash
?)中派生出来的。ylamdve62#
我不知道问题是什么,但是
popen("some-program", "w")
只向some-program
的stdin提供数据,所以可以用|
(用于运行//中的命令)和{ }
(用于对多个命令的文件描述符进行分组)来模拟它。pw136qt23#
提供创建管道的唯一标准shell特性是
|
操作符。如果我们假设没有使用扩展,那么规范说明(多命令)管道在子 shell 环境中执行。这样的环境不能修改父 shell 以使管道的写入端的文件描述符在那里可用,所以我们能做的最接近的事情就是让它在管道的写入端的{ compound-command }
范围内可用。现在,虽然它可以被重定向,但异步命令的初始标准输入是(相当于)
/dev/null
,因此只将some-command &
放在管道的读取端是行不通的,但我们可以在some-command
周围放置另一个复合命令,以便为从管道复制标准输入文件描述符提供一个位置。例如:这些搭配起来效果很好。例如:
输出:
不是吹笛?
吹笛!
如果您关心
4>&0
重定向和将/dev/null
重定向到异步进程的标准输入的相对顺序,那么多一点复合命令声明就可以使这一点变得明确: