我想使用/dev/tcp/host/port
psuedo - device syntax在bash中打开TCP套接字,但如果host/port
端点没有侦听,我需要优雅地恢复。如果我正在做的就是将数据发送到套接字或从中提取数据,这很容易,因为我只能使用一次性重定向,即:
echo 'ping' 2> >(logger) >/dev/tcp/127.0.0.1/8080
或者,从插座中读取:
cat 2> >(logger) </dev/tcp/127.0.0.1/8080
其中logger
是将stdin中的行写入syslog的标准logger。
问题是在某些情况下我需要向套接字写一个请求并获得响应。所以我需要用exec
打开套接字的文件描述符,但在这种情况下,捕获“-bash:connect:Connection refused”错误更难,因为我不想重定向所有输出shell,这是2> >(logger)
在exec上下文中使用时的作用。如果端点关闭,则以下工作很有效(因为bash在打开套接字时遇到错误,并重置所有重定向),但如果能够建立连接,则渲染我的shell非常无用。
exec 2> >(logger) 3<>/dev/tcp/127.0.0.1/8080
到目前为止,我提出的最佳解决方案如下,我打开一个指向原始STDERR的文件描述符(fd 9),将STDERR(fd 2)重定向到我的记录器,打开fd上的套接字3,然后将fd 2设置回原来的STDERR,并关闭我的临时STDERR别名(fd 9)。
exec 9>&2 2> >(logger) 3<>/dev/tcp/127.0.0.1/8080 2>&9 9>&-
对于这么简单的事情来说,这似乎是很多工作。有没有办法告诉bash我想在bash运行exec
命令时重定向STDERR,而不是将重定向视为exec
的文字参数?
请保留您的答案/建议仅限于bash (最高为bash 4.3.30)。我知道telnet
,netcat
,socat
等等。我正在努力的project(这个bash问题出现的地方)的想法源于对慢一个特定的tool,这是由于它如何将所有shell助手代理到外部(python)解释器。另外,如果可能的话,我想避免使用mkfifo
。
答案 0 :(得分:1)
eval 'exec 3<>/dev/tcp/127.0.0.1/8080' 2> >(logger)
或更好,因为它不会破坏旧的文件描述符3:
eval 'exec {fd}<>/dev/tcp/127.0.0.1/8080' 2> >(logger)
使用最小的空闲文件描述符并将其分配给fd。
unset fd
eval 'exec {fd}<>/dev/tcp/127.0.0.1/8080' 2> >(logger)
if test $? != 0 # status of the last command - 0 if the connection succeeded
then
echo cannot open connection >&2
fi
# $? shows the last status only. Later you can check success this way:
if test -z "$fd"
then
echo could not open connection >&2 # past tense because it's later now
else
echo some data to transmit >&$fd
IFS= read -r just_on_line_of_response <&$fd
fi
完成后,使用
删除连接exec {fd}>&-
这也可行:
eval "exec $fd>&-"
但是这个失败了,加上关闭你的标准:
exec $fd>&-