114 lines
3.0 KiB
Bash
114 lines
3.0 KiB
Bash
#!/bin/sh
|
|
# bee-network.sh — bring up all physical network interfaces via DHCP
|
|
# Unattended: starts later in boot, runs quietly, and gives up after a bounded timeout.
|
|
|
|
LOG_PREFIX="bee-network"
|
|
DHCP_TIMEOUT_SECS=300
|
|
|
|
log() { echo "[$LOG_PREFIX] $*"; }
|
|
|
|
list_interfaces() {
|
|
ip -o link show \
|
|
| awk -F': ' '{print $2}' \
|
|
| grep -v '^lo$' \
|
|
| grep -vE '^(docker|virbr|veth|tun|tap|br-|bond|dummy)' \
|
|
| sort
|
|
}
|
|
|
|
# Give udev a short chance to expose late NICs before the first scan.
|
|
if command -v udevadm >/dev/null 2>&1; then
|
|
udevadm settle --timeout=5 >/dev/null 2>&1 || log "WARN: udevadm settle timed out"
|
|
fi
|
|
|
|
start_dhcp() {
|
|
iface="$1"
|
|
if ! ip link set "$iface" up; then
|
|
log "WARN: could not bring up $iface"
|
|
return 1
|
|
fi
|
|
|
|
carrier=$(cat "/sys/class/net/$iface/carrier" 2>/dev/null || true)
|
|
if [ "$carrier" = "1" ]; then
|
|
log "carrier detected on $iface"
|
|
else
|
|
log "carrier not detected on $iface"
|
|
fi
|
|
|
|
dhclient -r "$iface" >/dev/null 2>&1 || true
|
|
|
|
if timeout "${DHCP_TIMEOUT_SECS}" dhclient -4 -q -1 "$iface" >/dev/null 2>&1; then
|
|
addr="$(ip -4 -o addr show dev "$iface" scope global 2>/dev/null | awk '{print $4}' | head -1)"
|
|
if [ -n "$addr" ]; then
|
|
log "DHCP lease acquired on $iface ($addr)"
|
|
else
|
|
log "DHCP lease acquired on $iface"
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
rc=$?
|
|
case "$rc" in
|
|
124)
|
|
log "DHCP timed out on $iface after ${DHCP_TIMEOUT_SECS}s"
|
|
;;
|
|
*)
|
|
log "DHCP failed on $iface (exit $rc)"
|
|
;;
|
|
esac
|
|
dhclient -r "$iface" >/dev/null 2>&1 || true
|
|
return 1
|
|
}
|
|
|
|
started_ifaces=""
|
|
started_count=0
|
|
scan_pass=1
|
|
pids=""
|
|
pid_ifaces=""
|
|
|
|
# Some server NICs appear a bit later after module/firmware init. Do a small
|
|
# bounded rescan window without turning network bring-up into a boot blocker.
|
|
while [ "$scan_pass" -le 3 ]; do
|
|
interfaces=$(list_interfaces)
|
|
|
|
if [ -n "$interfaces" ]; then
|
|
for iface in $interfaces; do
|
|
case " $started_ifaces " in
|
|
*" $iface "*) continue ;;
|
|
esac
|
|
|
|
log "starting DHCP on $iface (timeout ${DHCP_TIMEOUT_SECS}s)"
|
|
start_dhcp "$iface" &
|
|
pid="$!"
|
|
pids="$pids $pid"
|
|
pid_ifaces="$pid_ifaces $pid:$iface"
|
|
|
|
started_ifaces="$started_ifaces $iface"
|
|
started_count=$((started_count + 1))
|
|
done
|
|
fi
|
|
|
|
if [ "$scan_pass" -ge 3 ]; then
|
|
break
|
|
fi
|
|
scan_pass=$((scan_pass + 1))
|
|
sleep 2
|
|
done
|
|
|
|
if [ "$started_count" -eq 0 ]; then
|
|
log "no physical interfaces found"
|
|
exit 0
|
|
fi
|
|
|
|
success_count=0
|
|
for pid_iface in $pid_ifaces; do
|
|
pid="${pid_iface%%:*}"
|
|
iface="${pid_iface#*:}"
|
|
if wait "$pid"; then
|
|
success_count=$((success_count + 1))
|
|
else
|
|
log "DHCP did not complete successfully on $iface"
|
|
fi
|
|
done
|
|
|
|
log "done (interfaces scanned: $started_count, leases acquired: $success_count)"
|