这是我的循环程序,在后台运行并等待命令。
#include <iostream>
using namespace std;
char buffer[256];
int main(int argc, char *argv[])
{
while(true){
fgets(buffer, 255, stdin);
buffer[255] = 0;
if(buffer[0] != '\0'){
cout << buffer;
buffer[0] = '\0';
}
}
return 0;
}
我运行它:
myLoop &
现在,我如何通过管道向该进程发送命令?
答案1
我想这对于“真正的”管道来说是不可能的。
相反,您可以使用 FIFO(命名管道,请参阅 参考资料man mkfifo
)或(更优雅但更复杂)Unix 套接字 (AF_UNIX)。
./background-proc </path/to/fifo &
cat >/path/to/fifo
# typing commands into cat
我不是开发人员,所以我与套接字的唯一关系是socat
。但这可能有助于作为一个开始。
您需要一个与您的程序通信的“服务器”。这样的管道将在后台启动:
socat UNIX-LISTEN:/tmp/sockettest,fork STDOUT | sed 's/./&_/g'
这sed
只是为了测试。
然后你开始一项或多项
socat STDIN UNIX-CONNECT:/tmp/sockettest
如果您有一个为后台程序生成命令的程序,那么您也可以在此处使用管道:
cmd_prog | socat STDIN UNIX-CONNECT:/tmp/sockettest
fork
与 FIFO 相比的优点是(使用服务器端的选项)您可以断开并重新连接客户端。使用 FIFO,您需要一些技巧来保持接收端运行:
while true; do cat /path/to/fifo; done | background_prog
答案2
如果您想在后台启动命令并有一个文件描述符通过管道向其发送数据。
使用zsh
或bash
,您可以使用重定向到进程替换。
exec 3> >(cmd)
然后发送输出:
echo something >&3
并用 告诉文件结束符exec 3>&-
。
继续使用zsh
和bash
,您还可以执行以下操作:
{ coproc cmd >&3 3>&-; } >&3
这是cmd
作为一个协进程启动的,它用两个管道启动进程,一个用于输入,一个用于输出,但这里因为我们只需要一个用于输入,所以我们将cmd
的 stdout 恢复为 shell 其余部分的标准输出。
发送输出:
echo something >&p # with zsh
echo something >&"${COPROC[1]}" # with bash
通过yash
,您可以使用进程重定向:
exec 3>(cmd)
使用任何类似 Bourne 的 shell,您始终可以执行以下操作:
{ {
echo something >&3
echo whatever
...
} 3>&1 >&4 4>&- | cmd; } 4>&1
cmd
这与在后台启动并运行将其输出发送到的命令并不完全相同,cmd
因为这些命令在子 shell 中运行,并且对于交互式 shell,cmd
也在前台(例如受 Ctrl+C 影响),但除了也就是说,它在功能上基本上是等效的。
答案3
通常,在进程启动后,您无法更改进程打开的文件以及它们从进程外部指向的位置。调试接口和工具也有例外,例如雷普蒂可以以有限的方式做到这一点。
当你开始你的程序时
myLoop &
它的标准输入已连接到您的终端(因为您没有将其重定向到其他任何地方),并且不会更改为管道。
也可以看看如何将终端附加到分离的进程?