捕获错误的输出在bash EXEC I / O重定向 [英] Capture output of error in bash exec I/O redirection
问题描述
我想开在bash TCP套接字,使用的/ dev / TCP /主机/端口
psuedo-的设备语法,但我需要恢复正常,如果主机/端口
端点不在听。这是容易的,如果我做的是将数据发送到套接字或从中提取数据,因为我可以只使用一次性的重定向,即:
回声'平'2 - ; >(记录)GT; /dev/tcp/127.0.0.1/8080
或者,从插座上写着:
猫2 - ; >(记录器)LT; /dev/tcp/127.0.0.1/8080
其中,记录
是标准的记录,从标准输入线写入系统日志。
的问题是,在某些情况下,我需要写入套接字的请求,并得到回一个响应。所以,我需要打开一个文件描述符与 EXEC
,但在这种情况下,攻克了-bash:连接:连接被拒绝的错误是很难的,因为我不想重定向在外壳的所有输出,这是什么 2 - ; >(记录)
在EXEC的环境中使用时一样。下面的伟大工程,如果端点是(因为庆典命中打开套接字时的错误,并将所有重定向),但呈现我的壳pretty无用的,如果它能够进行连接。
EXEC 2 - ; >(记录器)3';> /dev/tcp/127.0.0.1/8080
到目前为止,最好的解决办法,我想出了如下,在那里我打开一个文件描述符(FD 9)指向原来的错误,都重定向STDERR(FD 2)我的记录器,打开FD插座3,然后设置FD 2回原来的STDERR,并关闭我的临时STDERR别名(FD 9)。
EXEC 9个和2 2 - ; >(记录器)3';> /dev/tcp/127.0.0.1/8080 2 - ;和9 -9;&放大器; -
这似乎是很多工作的东西那么简单。有没有办法告诉我要重定向STDERR庆典而bash中运行 EXEC
命令,而不考虑重定向作为文字参数 EXEC
?
请保持你的答案/建议局限于来砸(最多来砸30年3月4日)。我知道远程登录
,的netcat
, socat
等。对于我的工作(如使用bash的问题出来)的项目的想法来自挫折产生如何慢特定工具是,这是由于它是如何代理了所有它的外壳佣工关闭外部(蟒蛇)间preters。另外,我想避免 mkfifo子
如果可能的话。
评估'EXEC 3';> /dev/tcp/127.0.0.1/8080'2 - ; >(记录仪)
或者,要好得多,因为它不破坏旧文件描述符3:
评估'EXEC {FD}<> /dev/tcp/127.0.0.1/8080'2 - ; >(记录仪)
它使用最小的自由文件描述符并给它分配于fd。
取消设置FD
EVALEXEC {FD}<> /dev/tcp/127.0.0.1/8080'2 - ; >(记录仪)如果测试$? !=最后一个命令的0#状态 - 0,如果连接成功
然后
回声无法打开连接>和2
科幻#$?只显示最后的状态。稍后,您可以检查的成功是这样的:如果测试-z$ FD
然后
回声无法打开连接>和2#过去式,因为它现在以后
其他
回应一些数据传输>&安培; $ FD
IFS =读-r just_on_line_of_response<&安培; $ FD
科幻
一旦完成,使用删除连接
EXEC {FD}>&安培; -
这将工作以及
评估EXEC $ FD>&放大器; -
但失败草草收场加上关闭你的标准输出:
EXEC $ FD>&安培; -
I want to open a TCP socket in bash, using the /dev/tcp/host/port
psuedo-device syntax, but I need to recover gracefully if the host/port
endpoint is not listening. This is easy if all I'm doing is sending data to the socket, or pulling data from it, since I can just use one-off redirection, i.e.:
echo 'ping' 2> >(logger) >/dev/tcp/127.0.0.1/8080
Or, reading from the socket:
cat 2> >(logger) </dev/tcp/127.0.0.1/8080
Where logger
is the standard logger that writes lines from stdin to syslog.
The problem is that in some cases I need to write a request to the socket and get a response back. So I need to open a file descriptor for the socket with exec
, but in this case, capturing the "-bash: connect: Connection refused" error is harder, since I don't want to redirect all output in the shell, which is what 2> >(logger)
does when used in the context of exec. The following works great if the endpoint is down (since bash hits an error when opening the socket, and resets all redirections), but renders my shell pretty useless if it is able to make the connection.
exec 2> >(logger) 3<>/dev/tcp/127.0.0.1/8080
So far, the best solution I've come up with is the following, where I open a file descriptor (fd 9) pointing to the original STDERR, redirect STDERR (fd 2) to my logger, open the socket on fd 3, then set fd 2 back to the original STDERR, and close my temporary STDERR alias (fd 9).
exec 9>&2 2> >(logger) 3<>/dev/tcp/127.0.0.1/8080 2>&9 9>&-
Which seems like a lot of work for something so simple. Is there a way to tell bash that I want to redirect STDERR while bash runs the exec
command, instead of considering the redirection as a literal argument to exec
?
Please keep your answers / suggestions limited to bash (up to bash 4.3.30). I know about telnet
, netcat
, socat
, etc. The idea for the project I'm working on (where this bash issue came up) arose from frustration at how slow a particular tool is, which is due to how it proxies all of its shell helpers off to external (python) interpreters. Also, I'd like to avoid mkfifo
if possible.
eval 'exec 3<>/dev/tcp/127.0.0.1/8080' 2> >(logger)
or, much better because it does not destroy the old file descriptor 3:
eval 'exec {fd}<>/dev/tcp/127.0.0.1/8080' 2> >(logger)
which uses the smallest free file descriptor and assigns it to 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
Once you are done, delete the connection using
exec {fd}>&-
This will work as well:
eval "exec $fd>&-"
But this fails miserably plus closes your stdout:
exec $fd>&-
这篇关于捕获错误的输出在bash EXEC I / O重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!