ip netns monitor 在脚本中不起作用

ip netns monitor 在脚本中不起作用

我正在尝试使用ip netns monitor脚本来响应新网络命名空间的创建,例如:

ip netns monitor | while read ACTION NETNS; do
 echo 'handling it!'
done

但是,我从未看到ip netns monitor此用例中的任何输出。进一步的实验表明,ip netns monitor如果它被重定向或通过管道传输,我从未看到任何输出。

这是一个可以得到预期结果的简单示例:

$ ip netns monitor &
$ touch /var/run/netns/dummy ; sleep 2 ; rm /var/run/netns/dummy
add dummy
delete dummy

下面是另一个使用示例,它产生了输出:

$ ip netns monitor >/tmp/ip-netns-monitor.log 2>&1 &
$ ip netns monitor | cat &
$ touch /var/run/netns/dummy ; sleep 2 ; rm /var/run/netns/dummy
$ cat /tmp/ip-netns-monitor.log
# no results

ip我已经追溯到这个监视器的实现 版本:http://git.kernel.org/cgit/linux/kernel/git/shemminger/iproute2.git/tree/ip/ipnetns.c?id=3c61c01a666d9f4dbb871305ab6791e19ede7d4a#n462

我没有在源代码中看到任何明显的东西会导致行为根据 STDOUT 指向的位置而改变 - 但我对这一切还很陌生。

我应该使用什么方法ip netns monitor才能让它在脚本中工作?还是我应该在某处提出错误?

如果这确实有问题,我可以尝试其他解决方法inotifywait

我的系统:

$ ip -Version
ip utility, iproute2-ss131122
$ lsb_release --description
Description:    Ubuntu 14.04.2 LTS
$ uname -rvm
3.13.0-45-generic #74-Ubuntu SMP Tue Jan 13 19:36:28 UTC 2015 x86_64

更新

我已经运行了交互式和重定向两种变体,strace结果如下。

方法:

while true; do touch /var/run/netns/dummy ; sleep 2; rm /var/run/netns/dummy; sleep 2; done &
strace -ivy ip netns monitor
strace -ivy ip netns monitor | cat

除了一些地址和句柄之外,strace 显示两者的初始化相同。它们不同的地方是在第一次从 inotify 读取之后。

交互式(即没有| cat)产生:

[00007ffe9274c767] inotify_init()       = 4
[00007ffe9274c737] inotify_add_watch(4<anon_inode:inotify>, "/var/run/netns", IN_CREATE|IN_DELETE) = 1
[00007ffe9273d3a0] read(4<anon_inode:inotify>, "\1\0\0\0\0\1\0\0\0\0\0\0\20\0\0\0dummy\0\0\0\0\0\0\0\0\0\0\0", 4096) = 32
[00007ffe9273cd84] fstat(1</dev/pts/0>, {st_dev=makedev(0, 12), st_ino=3, st_mode=S_IFCHR|0600, st_nlink=1, st_uid=1000, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(136, 0), st_atime=2015/04/05-20:55:28, st_mtime=2015/04/05-20:55:36, st_ctime=2015/04/05-04:17:42}) = 0
[00007ffe9274655a] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffe92e3a000
[00007ffe9273d400] write(1</dev/pts/0>, "add dummy\n", 10add dummy) = 10
[00007ffe9273d3a0] read(4<anon_inode:inotify>, "\1\0\0\0\0\2\0\0\0\0\0\0\20\0\0\0dummy\0\0\0\0\0\0\0\0\0\0\0", 4096) = 32
[00007ffe9273d400] write(1</dev/pts/0>, "delete dummy\n", 13delete dummy) = 13

重定向(即使用| cat)产生:

[00007f607d90e767] inotify_init()       = 4
[00007f607d90e737] inotify_add_watch(4<anon_inode:inotify>, "/var/run/netns", IN_CREATE|IN_DELETE) = 1
[00007f607d8ff3a0] read(4<anon_inode:inotify>, "\1\0\0\0\0\2\0\0\0\0\0\0\20\0\0\0dummy\0\0\0\0\0\0\0\0\0\0\0", 4096) = 32
[00007f607d8fed84] fstat(1<pipe:[154785]>, {st_dev=makedev(0, 8), st_ino=154785, st_mode=S_IFIFO|0600, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=0, st_size=0, st_atime=2015/04/05-21:04:54, st_mtime=2015/04/05-21:04:54, st_ctime=2015/04/05-21:04:54}) = 0
[00007f607d90855a] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f607dffc000
[00007f607d8ff3a0] read(4<anon_inode:inotify>, "\1\0\0\0\0\1\0\0\0\0\0\0\20\0\0\0dummy\0\0\0\0\0\0\0\0\0\0\0", 4096) = 32
[00007f607d8ff3a0] read(4<anon_inode:inotify>, "\1\0\0\0\0\2\0\0\0\0\0\0\20\0\0\0dummy\0\0\0\0\0\0\0\0\0\0\0", 4096) = 32

因此,重定向时fstat会产生不同的结果(符合预期),但从write未被调用。结果read表明通知按预期发送。并且ip netns monitor必须高兴没有错误,因为它一直在循环。

答案1

我猜这可能是你遇到了管道上的 stdout 缓冲为 4K 的问题。请参阅https://unix.stackexchange.com/a/25378了解一些修复方法。要确认这是您的特定问题,请尝试将虚拟文件的名称更改为更大的名称,或多次调用 touch/rm,以生成足够的输出以达到默认缓冲区大小。

相关内容