用其协同进程/子进程替换当前进程


10

我有一个程序P,期望接收“你好”并输出“为什么?” 在提供功能之前。其他不知道通常与“ 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


您需要zsh解决方案还是bash可接受的解决方案?
roaima

1
我会用失望bash的解决方案,是不适用的zsh,但肯定会接受吗☺
迈克尔

是否知道还会有其他程序运行此脚本?它是一个有限列表,还是可以是任何数字?显然,另一个程序需要知道这一点才能调用它。
Lizardx 2015年

我典型的用法是with ssh及其选项ProxyCommand
迈克尔

1
cat通常不会缓冲。如果您的系统上有,请尝试cat -u
斯特凡Chazelas

Answers:


1

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

无法直接执行此操作(至少在外壳中;dup2可以想象在进程内部,调用可能起作用)。您将需要拼接流。即:

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

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

除非P检查了它所连接的输入/输出流并据此决定要进行缓冲,否则这不会引起额外的缓冲(至少使用GNU cat)。例如,如果C标准库连接到文件,则将在stdout/ 上启用缓冲stderr,但仅在它们连接到终端时才执行行缓冲。


-1

可以使用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!

例如,这与使用相同dd ibs=1。我对此不满意。在某种程度上,coproc具有自己的缓冲,而我要使用的就是它。
迈克尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.