tcpreplay后错误读取失败:0:资源暂时不可用

时间:2013-05-06 15:47:58

标签: bash

我有一个非常简单的脚本来运行。它调用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之后是否需要关闭或清理任何句柄或管道?

3 个答案:

答案 0 :(得分:8)

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

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

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

另外一个补充:或者,如果你真的需要tcpreplay来接收你的 输入你可以编写一个重置O_NONBLOCK的短程序。像这个 (复位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

答案 1 :(得分:1)

Resource temporarily unavailableEAGAIN(或EWOULDBLOCK),当没有更多数据可用时(如果不是在非阻止模式下将被阻止),它是非阻止文件描述符的错误代码。先前的命令(在这种情况下为tcpreplay)错误地使STDIN处于非阻塞模式。 Shell不会对其进行更正,并且以下过程不适用于非默认的非阻塞STDIN。

在您的脚本中,您还可以通过以下方式关闭非阻止功能:

perl -MFcntl -e 'fcntl STDIN, F_SETFL, fcntl(STDIN, F_GETFL, 0) & ~O_NONBLOCK'

答案 2 :(得分:0)

在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')'