![需要脚本将 STDIN 和 STDOUT 重定向到命名管道](https://linux22.com/image/526178/%E9%9C%80%E8%A6%81%E8%84%9A%E6%9C%AC%E5%B0%86%20STDIN%20%E5%92%8C%20STDOUT%20%E9%87%8D%E5%AE%9A%E5%90%91%E5%88%B0%E5%91%BD%E5%90%8D%E7%AE%A1%E9%81%93.png)
我有一个应用程序,它启动一个身份验证助手(我的脚本)并使用 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 关闭时存在。