将当前进程替换为其协进程/子进程

将当前进程替换为其协进程/子进程

我有一个程序P期望接收“Hello”并输出“Why?”在提供功能之前。其他程序使用此功能,这些程序不知道以“Hello”开始对话是常见的礼貌行为。因此,我想编写一个包装器,P其工作方式如下(zsh 语法):

coproc P
print -p Hello  # Send Hello to P
read -pr line   # Read what P has to say
[[ "$line" = "Why?" ]] && Replace current process with the coprocess.
echo Could not get P's attention.

在部分(如)中使用cat或会导致不必要的缓冲。我有什么选择?ddReplace...cat <&p &; exec cat >&p

答案1

你所说的问题并不是真正的更换过程,但替换现有流程的溪流。目标是与进程进行一些交互,然后将其输入/输出移交给另一对连接的流。

没有办法直接执行此操作(至少在 shell 中;在进程内部,调用dup2可能会起作用)。您将需要拼接流。 IE:

( echo Hello ; cat ) | P | ( read ; cat )

在你的例子中使用coprocas 也可以。请注意,该命令将文件描述符保存到数组中,稍后您可以将它们用于重定向。

这不应该导致额外的缓冲(至少对于 GNU cat),除非 P 检查它所连接的输入/输出流并据此做出缓冲决定。例如,如果连接到文件, C 标准库将在stdout/上启用缓冲,但仅在连接到终端时才执行行缓冲。stderr

答案2

能够使用 perl 测试以下代码以避免缓冲,尝试这是否适合您

P 的示例版本

$ cat /tmp/P
#!/bin/bash
read input
if [[ $input = "Hello" ]]
then
    echo "Why?"
else
    exit 1
fi
echo "Got Hello from client, working ..."
sleep 10
echo "Need to read some input"
read x
echo "Got: $x"

包装程序

$ cat /tmp/wrapper 
#!/usr/bin/zsh
coproc /tmp/P
print -p Hello  # Send Hello to P
read -pr line   # Read what P has to say
if [[ "$line" = "Why?" ]]; then
    perl -e '$|=1;print $_ while(<>);' <& p &
    perl -e '$|=1;print $_ while(<>);' >& p
else
    echo "Could not get P's attention."
fi

测试运行

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!

相关内容