2

I'm trying to use ip netns monitor in a script to react to the creation of new network namespaces, eg:

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

However I never see any output from ip netns monitor in this use case. Further experimenting reveals I never see any output from ip netns monitor if it is redirected or piped.

Here is a simple example of what does give the expected result:

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

And here is another example of a usage that produces zero output:

$ 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

I have tracked my version of ip back to this implementation of monitor: http://git.kernel.org/cgit/linux/kernel/git/shemminger/iproute2.git/tree/ip/ipnetns.c?id=3c61c01a666d9f4dbb871305ab6791e19ede7d4a#n462

I don't see anything obvious in the source that would cause behaviour to change based on where STDOUT is pointed - but I'm still new to all this.

Is there some way I should be using ip netns monitor so that it works in a script? Or should I be raising a bug somewhere?

If this is truly broken I can try a workaround with inotifywait instead.

My system:

$ 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

Update

I have run both interactive and redirected variants with strace and the results follow.

Method:

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

Aside from some addresses and handles, strace shows the same initialisation for both. Where they vary is following the first read from inotify.

Interactive (ie without | cat) produces:

[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

Redirected (ie with | cat) produces:

[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

So, when redirected fstat has different results (expectedly) but write is never called. The results of read show that the notifications are coming through as expected. And ip netns monitor must be happy there is no error because it keeps looping.

1

1 Answer 1

3

I'm taking a guess that this is possibly you hitting an issue where stdout on a pipe buffers at 4K. See https://unix.stackexchange.com/a/25378 for some ideas on fixing it. To confirm this is your specific issue, try changing the name of your dummy file to something much larger, or call touch/rm multiple times, to generate enough output to hit the default buffer size.

2
  • Bingo! Longer file names, more events, and it eventually yields output when redirected. Cannot believe I haven't encountered this before. Using stdbuf --output=L ip netns monitor | cat solves it. Thanks. Apr 5, 2015 at 22:15
  • I learned somthing today! ;-) Thanks! (Upvoted!)
    – Fabby
    Apr 10, 2015 at 19:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .