OpenWRT嵌入式Linux故障排除一例

跟大数据没关系,只是帮朋友忙排了个错记录一下。

以前关系很不错的同事,目前在企业级wifi领域创业,采购了我们的大数据服务,正在给他做平台的搭建和调试。然后这几天他这个CEO在调试路由器的时候遇到一些问题,在搞大数据的同时捎带手解决了一下他这个问题。

OpenWRT,嵌入式Linux,主要用在MIPS或ARM设备上。路由器和wifi设备很多会采用这个系统,特点是轻巧。

Coova-Chilli,在openwrt下的接入访问控制器,提供认证网关,可以使用radius或http来做接入计费等工作。

正常的话,在启动chilli以后,会启动四个tun虚拟隧道网卡,而故障是偶发性的,不定期的会有两个IP地址一样的tun设备。比如是这样

 

tun1 10.1.0.1

tun2 10.2.0.1

tun3 10.3.0.1

tun4 10.4.0.1

正常的情况下是应该只有tun0-3的设备,但是每次启动都会多出一两个tun,而且还不固定,有时候是tun0-1 IP地址一样,有时候tun2-3 IP地址一样。而且OpenWRT默认是不记录syslog的。很难排查。其实可以从logread里面读取syslog,但是syslog里其实没记录 任何东西。

那哥们以前也是写代码的,苦熬了三个通宵没找到问题在哪,在chilli启动脚本里面设置了各种记log,wait,sleep,都没用。下午 过去讨论完当前大数据平台的需求就没事了,然后我闲的蛋疼就给他看了一下那个脚本,chilli脚本应该没有太多的问题,然后他是按照官方部署文档搭建 的。一开始也没看出问题在哪。chilli脚本默认是放在/etc/init.d目录下的。按说不会有问题,后来快感来了,他告诉我他写了一个命令在 rc.local做启动,我看了一下rc.local里面,他写了一个启动脚本放到了/root下面。vi 那个在/root下的启动脚本,里面写了一个/etc/init.d/chilli restart。我就问他这是干嘛用的,他说wrt官方让这样写,说这样写保险。我尝试注销掉restart行,重启10遍,tun隧道都毫无问题。20 分钟搞定。

问题分析

chilli原始脚本如下

#! /bin/sh    
### BEGIN INIT INFO    
# Provides:          chilli    
# Required-Start:    $remote_fs $syslog $network    
# Required-Stop:     $remote_fs $syslog $network    
# Default-Start:     2 3 4 5    
# Default-Stop:      0 1 6    
# Short-Description: Start CoovaChilli daemon at boot time    
# Description:       Enable CoovaChilli service provided by daemon.    
### END INIT INFO    
PATH=/sbin:/bin:/usr/sbin:/usr/bin    
DAEMON=/usr/sbin/chilli    
NAME=chilli    
DESC=chilli    
START_CHILLI=0    
if [ -f /etc/default/chilli ] ; then    
. /etc/default/chilli    
fi    
if [ "$START_CHILLI" != "1" ] ; then    
echo "Chilli default off. Look at /etc/default/chilli"    
exit 0    
fi    
test -f $DAEMON || exit 0    
. /etc/chilli/functions    
MULTI=$(ls /etc/chilli/*/chilli.conf 2>/dev/null)    
[ -z "$DHCPIF" ] && [ -n "$MULTI" ] && {    
for c in $MULTI;     
do    
  echo "Found configuration $c"    
  DHCPIF=$(basename $(echo $c|sed 's#/chilli.conf##'))    
  export DHCPIF    
  echo "Running DHCPIF=$DHCPIF $0 $*"    
  sh $0 $*    
done    
exit    
}    
if [ -n "$DHCPIF" ]; then    
CONFIG=/etc/chilli/$DHCPIF/chilli.conf    
else    
CONFIG=/etc/chilli.conf    
fi    
[ -f $CONFIG ] || {    
echo "$CONFIG Not found"    
exit 0    
}    
check_required    
RETVAL=0    
prog="chilli"    
case "$1" in    
start)    
  echo -n "Starting $DESC: "    
  /sbin/modprobe tun >/dev/null 2>&1    
  echo 1 > /proc/sys/net/ipv4/ip_forward    
  writeconfig    
  radiusconfig    
  test ${HS_ADMINTERVAL:-0} -gt 0 && {	    
(crontab -l 2>&- | grep -v $0    
    echo "*/$HS_ADMINTERVAL * * * * $0 radconfig"    
    ) | crontab - 2>&-    
  }    
  ifconfig $HS_LANIF 0.0.0.0    
  start-stop-daemon --start --quiet --pidfile /var/run/$NAME.$HS_LANIF.pid \    
    --exec $DAEMON -- -c $CONFIG    
  RETVAL=$?    
  echo "$NAME."    
  ;;    
checkrunning)    
  check=`start-stop-daemon --start --exec $DAEMON --test`    
  if [ x"$check" != x"$DAEMON already running." ] ; then    
$0 start    
  fi    
  ;;    
radconfig)    
  [ -e $MAIN_CONF ] || writeconfig    
  radiusconfig    
  ;;    
restart)    
  $0 stop    
  sleep 1    
  $0 start    
  RETVAL=$?    
  ;;    
stop)    
  echo -n "Stopping $DESC: "    
  crontab -l 2>&- | grep -v $0 | crontab -    
  start-stop-daemon --oknodo --stop --quiet --pidfile /var/run/$NAME.$HS_LANIF.pid \    
  --exec $DAEMON    
  echo "$NAME."    
  ;;    
reload)    
  echo "Reloading $DESC."    
  start-stop-daemon --stop --signal 1 --quiet --pidfile \    
  /var/run/$NAME.$HS_LANIF.pid --exec $DAEMON    
  ;;    
condrestart)    
  check=`start-stop-daemon --start --exec $DAEMON --test`    
  if [ x"$check" != x"$DAEMON already running." ] ; then    
$0 restart    
RETVAL=$?    
  fi    
  ;;    
status)    
  status chilli    
  RETVAL=$?    
  ;;    
*)    
  N=/etc/init.d/$NAME    
  echo "Usage: $N {start|stop|restart|condrestart|status|reload|radconfig}" >&2    
  exit 1    
  ;;    
esac    
exit 0

问题在于,他在调试的时候,在for c in $MULTI循环里面,为了保证每个子进程都启动成功,加了一个wait,后面在建立tun通道的时候为了调试又加了几个sleep。照着官方文档,他又 加了个restart到rc.local里面,这样问题就来了,/etc/init.d里面是自动执行chilli start命令的,而加上了wait和sleep。init.d的启动脚本会等待,而这时候Linux在不同的tty又启动了rc.local里面的 chilli restart命令,于是两个或三个相同的tun IP地址就会共同存在。

反正问题解决了,鉴于他为这种破事熬了三个通宵,我就可以以先知的口吻教育这个亲自调试程序的CEO:“尽信书不如无书”。开源系统的官方文档往往滞后,可能新版本早就解决了需要restart的问题,但是文档没有及时更新,导致这种问题的发生。

总结,了解各种系统的工作原理是多么重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入式Linux程序框架可以帮助开发人员快速开发嵌入式Linux应用程序,提高开发效率和质量。以下是一个简单的嵌入式Linux程序框架: 1. 硬件驱动层 硬件驱动层是整个嵌入式系统的基础,它负责管理硬件资源,包括处理器、内存、外设等。这一层的开发需要根据具体的硬件平台进行,通常需要使用C语言和汇编语言进行开发。 2. 操作系统层 操作系统层负责管理系统资源,包括进程、线程、内存、文件系统等。在嵌入式Linux系统中,常用的操作系统包括BusyBox、Buildroot、OpenWrt等。这一层的开发需要掌握Linux内核和系统编程的知识。 3. 应用程序层 应用程序层是用户直接使用的程序,包括应用程序、脚本、库等。这一层的开发需要掌握各种编程语言,如C、C++、Python、Shell等。 4. 调试和测试层 调试和测试层用于调试和测试嵌入式系统。这一层通常包括调试工具、测试工具和日志记录工具等。常用的调试和测试工具包括GDB、Valgrind、strace等。 5. 系统管理层 系统管理层负责管理整个嵌入式系统,包括配置管理、升级管理、安全管理等。这一层的开发需要掌握系统管理和网络安全的知识。 以上是一个简单的嵌入式Linux程序框架,它可以帮助开发人员快速开发嵌入式Linux应用程序,并提高开发效率和质量。当然,具体的开发框架还需要根据具体的应用场景进行设计和开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值