解决alpine容器下udhcpc renew卡死的问题
之前有个macvlan的容器,每次启动后要手动在容器内运行udhcpc,从DHCP获取动态IP。 为了方便加了一个supervisord,容器启动自动跑udhcpc -f以及容器本身的程序。改了后发现容器启动一段时间后就会断网,排查日志发现udhcpc刚启动时会去获取IP,然后renew 1次后,就没再renew记录了。
问题排查
udhcpc进程有supervisord守护,用ps aux查看udhcpc进程是在正常跑的,但发现有个脚本一直不退出

脚本是udhcpc每次成功获取IP后运行的,用来配置网卡、路由、resolv解析等等。用pstree看看子进程在跑什么

发现是grep不退出,于是查看script文件看看是怎么跑的grep

原因分析
renew函数里有两个地方,没有输入文件流给grep,预设grep就会从stdin流读取,所以这里一直卡着。 由于supervisor跑udhcpc -f(foreground mode),stdin输入流是绑着的,所以导致grep一直在等待,而之前udhcp是跑在daemon mode,fork出来时stdin流是解绑的,grep尝试读取stdin会收到EOF直接退出,继续往下运行脚本。
所以解释了为什么之前手动跑udhcpc没问题而用supervisord + udhcpc -f会卡住。另外grep只在renew()存在,第一次获取IP后是运行bound(),也解释了为什么刚启动时获取IP没问题,到后面renew就出问题
解决方法
udhcpc -f 换成 /bin/sh -c "udhcpc -f < /dev/null"
把stdin流重定向到/dev/null
成功解决