4

我有一个非常简单的脚本要运行。它调用 tcpreplay 然后要求用户输入一些东西。然后读取将失败,读取:读取错误:0:资源暂时不可用。

这是代码

#!/bin/bash

tcpreplay -ieth4 SMTP.pcap

echo TEST
read HANDLE
echo $HANDLE

输出是

[root@vse1 quick_test]# ./test.sh 
sending out eth4 
processing file: SMTP.pcap
Actual: 28 packets (4380 bytes) sent in 0.53 seconds.       Rated: 8264.2 bps, 0.06 Mbps, 52.83 pps
Statistics for network device: eth4
        Attempted packets:         28
        Successful packets:        28
        Failed packets:            0
        Retried packets (ENOBUFS): 0
        Retried packets (EAGAIN):  0
TEST
./test.sh: line 6: read: read error: 0: Resource temporarily unavailable

[root@vse1 quick_test]#

我想知道在运行 tcpreplay 后是否需要关闭或清理任何句柄或管道?

4

3 回答 3

8

显然 tcpreplay 在标准输入上设置了 O_NONBLOCK ,然后不删除它。我会说这是 tcpreplay 中的一个错误。要解决这个问题,您可以使用从 /dev/null 重定向的标准输入运行 tcpreplay。像这样:

tcpreplay -i eth4 SMTP.pcap </dev/null

另外:请注意,此 tcpreplay 行为仅会破坏非交互式 shell。

另一个补充:或者,如果您真的需要 tcpreplay 来接收您的输入,您可以编写一个重置 O_NONBLOCK 的短程序。像这个(reset-nonblock.c):

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int
main()
{
    if (fcntl(STDIN_FILENO, F_SETFL,
              fcntl(STDIN_FILENO, F_GETFL) & ~O_NONBLOCK) < 0) {
        perror(NULL);
        return 1;
    }
    return 0;
}

使用“make reset-nonblock”进行制作,然后将其放入您的 PATH 并像这样使用:

tcpreplay -i eth4 SMTP.pcap
reset-nonblock
于 2013-05-06T16:16:47.670 回答
2

虽然 C 解决方案有效,但您可以使用 Python 从命令行在一行中关闭非阻塞输入。就个人而言,我将其别名为“setblocking”,因为它相当方便。

$ python3 -c $'import os\nos.set_blocking(0, True)'

你也可以让 Python 打印之前的状态,这样它只能暂时改变:

$ o=$(python3 -c $'import os\nprint(os.get_blocking(0))\nos.set_blocking(0, True)')
$ somecommandthatreadsstdin
$ python3 -c $'import os\nos.set_blocking(0, '$o')'
于 2019-02-07T20:33:56.633 回答
1

Resource temporarily unavailableis EAGAIN(or EWOULDBLOCK) 这是当没有更多数据可用时非阻塞文件描述符的错误代码(如果不在非阻塞模式下将阻塞)。上一个命令(在本例中为 tcpreplay)错误地将 STDIN 置于非阻塞模式。shell 不会更正它,并且以下过程不适用于非默认非阻塞 STDIN。

在您的脚本中,您还可以使用以下命令关闭非阻塞:

perl -MFcntl -e 'fcntl STDIN, F_SETFL, fcntl(STDIN, F_GETFL, 0) & ~O_NONBLOCK'
于 2019-12-19T19:38:58.937 回答