今天遇到一个很奇葩的问题,udhcpc获取到了,但是ifconfig命令查看时却没有生效。下面来看下是怎么回事。
udhcpc是集成在busybox里面的,所以在编译busybox的时候加入dhcp的选项就可以了。
如果没有udhcpc的执行文件,可以手动连接一个:ln -s /bin/busybox /sbin/udhcpc。
1、命令执行打印
# udhcpc -b -i eth0
udhcpc: started, v1.31.1
udhcpc: sending discover
udhcpc: sending select for 172.30.15.20
udhcpc: lease of 172.30.15.20 obtained, lease time 691200
从上面打印可以明显得出结论,我们是获取到了ip地址的172.30.15.20,ip地址为。来看下ifconfig命令打印。
# udhcpc -b -i eth0
udhcpc: started, v1.31.1
udhcpc: sending discover
udhcpc: sending select for 172.30.15.20
udhcpc: lease of 172.30.15.20 obtained, lease time 691200
#
# ifconfig
eth0 Link encap:Ethernet HWaddr 02:31:A2:6D:75:BF
inet addr:172.30.15.67 Bcast:172.30.255.255 Mask:255.255.0.0
inet6 addr: fe80::31:a2ff:fe6d:75bf/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1451 errors:0 dropped:27 overruns:0 frame:0
TX packets:24 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:624135 (609.5 KiB) TX bytes:3879 (3.7 KiB)
Interrupt:41
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
上面ifconfig命令打印出来的eth0网卡IP地址却不是172.30.15.20。说明我们虽然获取到了ip地址但是没有设置进去。
2、解决方案
通过搜索博客知道是:udhcpc命令只能去获取到ip,但是不能设置。设置过程是(default.script)脚本来完成的。这个脚本默认位置在/usr/share/udhcpc/default.script。
参考博客:https://blog.csdn.net/sddsighhz/article/details/46005629
来看下我的这个路径:
# ls -l /usr/share/
total 0
drwxr-xr-x 4 root root 0 Jul 13 2020 alsa
发现并没有这个脚本文件。应该是被系统裁剪掉了。下面尝试补充这个脚本,发现这个路径是只读路径。没办法添加到默认路径中去,只有/tmp/路径是可读可写的,想办法让udhcpc命令去执行这个路径下的(default.script)脚本文件。
3、udhcpc命令
从下面可以看到 -s 传参可以指定这个脚本文件路径,到此我们就可以解决这个问题了。
# udhcpc -h
udhcpc: option requires an argument -- 'h'
BusyBox v1.31.1 (2020-07-13 19:33:08 CST) multi-call binary.
Usage: udhcpc [-fbqRB] [-a[MSEC]] [-t N] [-T SEC] [-A SEC/-n]
[-i IFACE] [-s PROG] [-p PIDFILE]
[-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]...
-i IFACE Interface to use (default eth0)
-s PROG Run PROG at DHCP events (default /usr/share/udhcpc/default.script)
-p FILE Create pidfile
-B Request broadcast replies
-t N Send up to N discover packets (default 3)
-T SEC Pause between packets (default 3)
-A SEC Wait if lease is not obtained (default 20)
-b Background if lease is not obtained
-n Exit if lease is not obtained
-q Exit after obtaining lease
-R Release IP on exit
-f Run in foreground
-S Log to syslog too
-a[MSEC] Validate offered address with ARP ping
-r IP Request this IP address
-o Don't request any options (unless -O is given)
-O OPT Request option OPT from server (cumulative)
-x OPT:VAL Include option OPT in sent packets (cumulative)
Examples of string, numeric, and hex byte opts:
-x hostname:bbox - option 12
-x lease:3600 - option 51 (lease time)
-x 0x3d:0100BEEFC0FFEE - option 61 (client id)
-x 14:'"dumpfile"' - option 14 (shell-quoted)
-F NAME Ask server to update DNS mapping for NAME
-V VENDOR Vendor identifier (default 'udhcp VERSION')
-C Don't send MAC as client identifier
Signals:
USR1 Renew lease
USR2 Release lease
4、解决方案
方案1:
1、在/usr/share/udhcpc/默认路径直接添加default.script文件
2、执行udhcpc命令(如:udhcpc -b -i eth0)
方案2:
1、在/tmp/路径下添加default.script文件
2、执行udhcpc命令,但是要带 -s 传参脚本路径(如:udhcpc -b -s /tmp/default.script -i eth0)
如:busybox udhcpc -b -q -t 1 -i eth0 -s /etc/simple.script -p /var/run/udhcpc.pid &
方案1:/usr/share/udhcpc/路径是只读文件,需要编译文件系统时就要编译进去。但是用起来比较方便,所有程序直接都能共用。
方案2:/tmp/是可读可写文件,不需要编译时就生成。但是掉电就没有了,每次都需要应用程序去写一次,并且不能共用。
所以按需采用。
5、脚本
default.script脚本如下:
#!/bin/sh
# udhcpc script edited by Tim Riker <Tim@Rikers.org>
[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
RESOLV_CONF="/etc/resolv.conf"
[ -e $RESOLV_CONF ] || touch $RESOLV_CONF
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
[ -n "$subnet" ] && NETMASK="netmask $subnet"
# Handle stateful DHCPv6 like DHCPv4
[ -n "$ipv6" ] && ip="$ipv6/128"
if [ -z "${IF_WAIT_DELAY}" ]; then
IF_WAIT_DELAY=10
fi
wait_for_ipv6_default_route() {
printf "Waiting for IPv6 default route to appear"
while [ $IF_WAIT_DELAY -gt 0 ]; do
if [ -z "$(ip -6 route list | grep default)" ]; then
printf "\n"
return
fi
sleep 1
printf "."
: $((IF_WAIT_DELAY -= 1))
done
printf " timeout!\n"
}
case "$1" in
deconfig)
/sbin/ifconfig $interface up
/sbin/ifconfig $interface 0.0.0.0
# drop info from this interface
# resolv.conf may be a symlink to /tmp/, so take care
TMPFILE=$(mktemp)
grep -vE "# $interface\$" $RESOLV_CONF > $TMPFILE
cat $TMPFILE > $RESOLV_CONF
rm -f $TMPFILE
if [ -x /usr/sbin/avahi-autoipd ]; then
/usr/sbin/avahi-autoipd -k $interface
fi
;;
leasefail|nak)
if [ -x /usr/sbin/avahi-autoipd ]; then
/usr/sbin/avahi-autoipd -wD $interface --no-chroot
fi
;;
renew|bound)
if [ -x /usr/sbin/avahi-autoipd ]; then
/usr/sbin/avahi-autoipd -k $interface
fi
/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
if [ -n "$ipv6" ] ; then
wait_for_ipv6_default_route
fi
if [ -n "$router" ] ; then
echo "deleting routers"
while route del default gw 0.0.0.0 dev $interface 2> /dev/null; do
:
done
for i in $router ; do
route add default gw $i dev $interface
done
fi
# drop info from this interface
# resolv.conf may be a symlink to /tmp/, so take care
TMPFILE=$(mktemp)
grep -vE "# $interface\$" $RESOLV_CONF > $TMPFILE
cat $TMPFILE > $RESOLV_CONF
rm -f $TMPFILE
# prefer rfc3397 domain search list (option 119) if available
if [ -n "$search" ]; then
search_list=$search
elif [ -n "$domain" ]; then
search_list=$domain
fi
[ -n "$search_list" ] &&
echo "search $search_list # $interface" >> $RESOLV_CONF
for i in $dns ; do
echo adding dns $i
echo "nameserver $i # $interface" >> $RESOLV_CONF
done
;;
esac
HOOK_DIR="$0.d"
for hook in "${HOOK_DIR}/"*; do
[ -f "${hook}" -a -x "${hook}" ] || continue
"${hook}" "${@}"
done
exit 0
再来一个
#!/bin/sh
# udhcpc script edited by Tim Riker <Tim@Rikers.org>
RESOLV_CONF="/etc/resolv.conf"
[ -n "$1" ] || { echo "Error: should be called from udhcpc"; exit 1; }
NETMASK=""
[ -n "$subnet" ] && NETMASK="netmask $subnet"
BROADCAST="broadcast +"
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
case "$1" in
deconfig)
echo "Setting IP address 0.0.0.0 on $interface"
busybox ifconfig $interface 0.0.0.0
;;
renew|bound)
echo "Setting IP address $ip on $interface"
busybox ifconfig $interface $ip $NETMASK $BROADCAST
if [ -n "$router" ] ; then
echo "Deleting routers"
while busybox route del default gw 0.0.0.0 dev $interface ; do
:
done
metric=0
for i in $router ; do
echo "Adding router $i"
busybox route add default gw $i dev $interface metric $metric
: $(( metric += 1 ))
done
fi
echo "Recreating $RESOLV_CONF"
# If the file is a symlink somewhere (like /etc/resolv.conf
# pointing to /run/resolv.conf), make sure things work.
realconf=$(readlink -f "$RESOLV_CONF" 2>/dev/null || echo "$RESOLV_CONF")
tmpfile="$realconf-$$"
> "$tmpfile"
[ -n "$domain" ] && echo "search $domain" >> "$tmpfile"
for i in $dns ; do
echo " Adding DNS server $i"
echo "nameserver $i" >> "$tmpfile"
done
busybox mv "$tmpfile" "$realconf"
;;
esac
exit 0
总结
这个问题的原因是,udhcpc命令只能获取ip,设置ip是靠default.script脚本来完成的。
解决步骤:
1、创建default.script脚本
2、添加default.script脚本的权限为0755(这个很重要)
3、执行udhcpc命令(udhcpc -b -s /tmp/default.script -i eth0)
正常打印:
# udhcpc -b -s /tmp/default.script -i eth0
udhcpc: started, v1.31.1
udhcpc: sending discover
udhcpc: sending select for 172.30.15.20
udhcpc: lease of 172.30.15.20 obtained, lease time 691200
deleting routers
adding dns 202.96.134.133
adding dns 202.96.128.166