需要脚本将 STDIN 和 STDOUT 重定向到命名管道

需要脚本将 STDIN 和 STDOUT 重定向到命名管道

我有一个应用程序,它启动一个身份验证助手(我的脚本)并使用 STDIN/STDOUT 进行通信。

我想将该脚本的 STDIN 和 STDOUT 重定向到两个命名管道,以便与另一个程序进行交互。

例如:

SCRIPT_STDIN > 管道1
SCRIPT_STDOUT < 管道2

以下是我想要完成的流程:

[应用]-> 启动辅助脚本,写入辅助 STDIN,从辅助 STDOUT 读取(例如:STDIN:用户名,密码;STDOUT:LOGIN_OK)
[辅助脚本]-> 读取 STDIN(来自应用程序的数据),转发到 PIPE1;从 PIPE2 读取,并将其写回到 STDOUT 上的应用程序
[其他流程]-> 从 PIPE1 输入读取、处理并将结果返回给 PIPE2

cat 命令几乎可以完成我想要的操作。如果有一个选项可以将 STDIN 复制到 STDERR,我可以使用命令让 cat 执行此操作(假设虚构的选项 -e 回显到 STDERR 而不是 STDOUT):

cat -e PIPE2 2>PIPE1 (从 PIPE2 读取并将其写入 STDOUT,复制输入,通常转到 STDERR 到 PIPE1)

答案1

下面是一个最终能实现我想要的功能的脚本。它读取 STDIN 并将其输出到 PIPE1,并从 PIPE2 中读取并将其输出到 STDOUT。

#!/bin/ksh
exec 3>../pipes/PIPE1
exec 4<../pipes/PIPE2
{ cat; } <&4 >&1 &
{ cat; } <&0 >&3
wait

这样做的目的是将辅助应用程序的输入/输出重定向到可由第三方应用程序处理的两个管道(这是一个典型的身份验证助手)。

答案2

我后来发现,我之前的答案并不是一个理想的解决方案。它有三个缺点:第一,当 stdin 关闭时它不会关闭(stdin 上的 eof)。第二,cat(以及 tee 等其他实用程序)在关闭它正在写入的管道的读取端时有一些奇怪的特性(如果您关闭并重新打开此脚本正在写入的管道的读取端,它将开始缓冲所有数据,并且只有当该进程停止时才会刷新它,这对我来说显然是一个问题)。第三,在这种情况下,后台进程可能会被孤立。

处理完这些问题后,我编写的新脚本可以解决上述所有三个问题。希望它能对某些人有所帮助。

#!/bin/ksh

#
# USAGE
# helper <path_to_CLIENT_TO_SERVER_pipe> <path_to_SERVER_TO_CLIENT_pipe>
#

CS=$1
SC=$2

exec 3>&0

trap 'exit;' CHLD

{
while read LINE; do             #STDIN -> CS
   print $LINE >>$CS;
done;
} <&3 &

while true; do                  #SC -> STDOUT
        read IN <$SC;
        retCode=$?
        if [[ $retCode -eq 0 ]]; then
                print $IN;
        else
                sleep 1;
        fi
done

在这种情况下,我们只有一个后台进程,即读取 stdin 的进程。如果 stdin 关闭,它将退出,我们会捕获该情况并退出前台脚本。前台脚本永远不需要退出,因为它正在从管道读取数据,无论管道另一端发生什么,它都应该始终这样做。使用 read 虽然效率较低,但当正在读取/写入给定管道的外部进程启动或关闭时,不会遇到缓冲问题。此脚本仅在 stdin 关闭时存在。

相关内容