我正在尝试使用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,以生成足够的输出以达到默认缓冲区大小。