Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision Next revisionBoth sides next revision | ||
| docs:guide-user:base-system:hotplug [2021/02/24 05:33] – [How it works] vgaetera | docs:guide-user:base-system:hotplug [2024/08/23 10:25] – Avoid duplication/duplicate execution oliv3r | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Hotplug ====== | ====== Hotplug ====== | ||
| - | Procd (the init system and process management daemon) executes scripts located in ''/ | + | Procd (the init system and process management daemon) executes scripts located in ''/ |
| It can be very useful with PPPoE connection or in an unstable network, or to use hardware buttons. | It can be very useful with PPPoE connection or in an unstable network, or to use hardware buttons. | ||
| Line 11: | Line 11: | ||
| Which is why most scripts in there use a numeric prefix. | Which is why most scripts in there use a numeric prefix. | ||
| - | ^ Directory ^ Description ^ | + | ^ Directory |
| - | | **block** | Block device events: device connected/ | + | | **block** |
| - | | **button** | Buttons: not created by default, see [[docs: | + | | **button** |
| - | | **iface** | Interface events: LAN/ | + | | **dhcp** |
| - | | **net** | Network-related events | | + | | **dsl** |
| - | | **ntp** | Time sync events: time step, time server stratum change | | + | | **firewall** |
| - | | **usb** | USB devices like 3g-modem and tty* | | + | | **iface** |
| - | | **dhcp** | DHCP-related events | | + | | **neigh** |
| - | | **neigh** | Neighbor discovery | + | | **net** |
| - | | **tftp** | TFTP-related events | + | | **ntp** |
| + | | **tftp** | TFTP-related events | ||
| + | | **tty** | ||
| + | | **usb** | ||
| + | | **usbmisc** | ||
| - | There may (should) be others, for other types of triggers: | + | See also: |
| - | * [[https:// | + | * [[https:// |
| * [[https:// | * [[https:// | ||
| + | * [[docs: | ||
| ===== Usage / Troubleshooting ===== | ===== Usage / Troubleshooting ===== | ||
| Line 46: | Line 51: | ||
| ===== Event classes / Directories ===== | ===== Event classes / Directories ===== | ||
| + | ==== net ==== | ||
| + | For scripts in **net** directory, these are the (relevant) environmental variables | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | ACTION | " | ||
| + | | DEVICENAME | configured interface names (br-lan, wlan0, phy1-ap0 | | ||
| + | | PATH | Full path | | ||
| + | | DEVPATH | full device path (for example "/ | ||
| + | | DEVTYPE | what the DEVICENAME are names of, ie. br-lan, phy1-ap0 | | ||
| + | | INTERFACE | configured interfaces as in DEVTYPE | | ||
| + | | SEQNUM | seqnum (a number) | | ||
| + | | SUBSYSTEM | always = " | ||
| + | | IFINDEX | appears to be related to the configured interfaces. See `ifconfig` | | ||
| + | |||
| ==== block ==== | ==== block ==== | ||
| For scripts in **block** directory, these are the (relevant) environmental variables | For scripts in **block** directory, these are the (relevant) environmental variables | ||
| Line 59: | Line 78: | ||
| | SEQNUM | seqnum (a number) | | | SEQNUM | seqnum (a number) | | ||
| | SUBSYSTEM | seems this is only " | | SUBSYSTEM | seems this is only " | ||
| + | |||
| + | ==== dsl ==== | ||
| + | For scripts in **dsl** directory, these are the (relevant) environment variables | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | DSL_NOTIFICATION_TYPE | '' | ||
| + | | DSL_LINE_NUMBER | '' | ||
| + | |||
| + | When DSL_NOTIFICATION_TYPE is '' | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | DSL_XTU_STATUS | '' | ||
| + | | DSL_TC_LAYER_STATUS | '' | ||
| + | | DSL_EFM_TC_CONFIG_US | '' | ||
| + | | DSL_EFM_TC_CONFIG_DS | '' | ||
| + | |||
| + | When DSL_NOTIFICATION_TYPE is '' | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | DSL_INTERFACE_STATUS | '' | ||
| + | | DSL_BONDING_STATUS | '' | ||
| + | |||
| + | When DSL_NOTIFICATION_TYPE is '' | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | DSL_DATARATE_US_BC0 | Upstream data rate in bit/s for Channel 0 | | ||
| + | | DSL_DATARATE_US_BC1 | Upstream data rate in bit/s for Channel 1 * | | ||
| + | |||
| + | When DSL_NOTIFICATION_TYPE is '' | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | DSL_DATARATE_DS_BC0 | Downstream data rate in bit/s for Channel 0 | | ||
| + | | DSL_DATARATE_DS_BC1 | Downstream data rate in bit/s for Channel 1 * | | ||
| + | |||
| + | NOTE: environment variables marked with an * are only available when channel bonding support is compiled in. | ||
| ==== iface ==== | ==== iface ==== | ||
| - | There are three main environment variables that are passed to each **iface** | + | For scripts in **iface** |
| ^ Variable name ^ Description ^ | ^ Variable name ^ Description ^ | ||
| - | | ACTION | "ifup", " | + | | ACTION | '' |
| - | | INTERFACE | Name of the logical interface which went up or down (e.g. "wan" | + | | INTERFACE | Name of the logical interface which went up or down (e.g. '' |
| - | | DEVICE | Physical | + | | DEVICE | Name of the physical |
| - | | IFUPDATE_ADDRESSES | "1" | + | |
| - | | IFUPDATE_PREFIXES | "1" | + | The meaning of most actions should be straightforward, |
| + | ^ Value ^ Description ^ | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | |||
| + | When ACTION is '' | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | IFUPDATE_ADDRESSES | '' | ||
| + | | IFUPDATE_ROUTES | '' | ||
| + | | IFUPDATE_PREFIXES | '' | ||
| + | | IFUPDATE_DATA | '' | ||
| ==== ntp ==== | ==== ntp ==== | ||
| + | Variables based on busybox ntpd: | ||
| + | |||
| ^ Variable name ^ description ^ | ^ Variable name ^ description ^ | ||
| | ACTION | step, stratum, unsync or periodic | | | ACTION | step, stratum, unsync or periodic | | ||
| | freq_drift_ppm | ntp variables | | | freq_drift_ppm | ntp variables | | ||
| - | | offset | ntp variables | + | | offset | Time adjustment done | |
| - | | stratum | ntp variables | + | | stratum | Quality (nr of servers to atomic clock) |
| | poll_interval | ntp variables | | | poll_interval | ntp variables | | ||
| - | Even without NTP sync, you will receive a " | + | Even without NTP sync, you will receive a " |
| + | |||
| + | ==== tty ==== | ||
| + | ^ Variable name ^ description ^ | ||
| + | | ACTION | add, remove, bind, unbind as above | | ||
| + | | DEVICENAME | eg " | ||
| + | | DEVNAME | only for bind/ | ||
| + | | DEVPATH | eg, "/ | ||
| + | | SEQNUM | (action number since boot for this subsystem) eg 335 | | ||
| + | | SUBSYSTEM | Specific type of device, eg, " | ||
| + | | MAJOR | eg 189 | | ||
| + | | MINOR | eg 1 | | ||
| ==== usb ==== | ==== usb ==== | ||
| ^ Variable name ^ description ^ | ^ Variable name ^ description ^ | ||
| - | | ACTION | add, remove | + | | ACTION | add, remove, |
| - | | DEVNAME | eg, " | + | |
| - | | DEVPATH | eg, "/ | + | |
| | DEVICENAME | eg " | | DEVICENAME | eg " | ||
| + | | DEVNAME | eg, " | ||
| | DEVNUM | eg 002 | | | DEVNUM | eg 002 | | ||
| - | | DRIVER | + | | DEVPATH |
| + | | DEVTYPE | eg " | ||
| | TYPE | eg 9/0/1 | | | TYPE | eg 9/0/1 | | ||
| | PRODUCT | the vendor/ | | PRODUCT | the vendor/ | ||
| - | | SEQNUM | ? eg 335 | | + | | SEQNUM | (action number since boot for this subsystem) |
| | BUSNUM | eg 001 | | | BUSNUM | eg 001 | | ||
| | MAJOR | eg 189 | | | MAJOR | eg 189 | | ||
| | MINOR | eg 1 | | | MINOR | eg 1 | | ||
| + | |||
| + | ==== usbmisc ==== | ||
| + | ^ Variable name ^ description | ||
| + | | ACTION | ||
| + | | DEVNAME | ||
| + | | DEVPATH | ||
| + | | DEVICENAME | ||
| + | | SEQNUM | ||
| + | | MAJOR | eg 189 | | ||
| + | | MINOR | eg 1 | | ||
| + | |||
| ===== Examples ===== | ===== Examples ===== | ||
| Line 106: | Line 196: | ||
| Every time an interface goes up then the if/fi statement will be executed. | Every time an interface goes up then the if/fi statement will be executed. | ||
| - | === Restart wlan on USB WiFi hotplug | + | ==== Symlink instead of rename a device ==== |
| - | Niii has posted this quick example for a USB WiFi device | + | An other script to create |
| - | To determine RTL8188SU_PRODID variable: | + | <code bash> |
| + | cat << " | ||
| + | CP210_PRODID=' | ||
| + | SYMLINK=" | ||
| - | <code bash># lsusb -v | + | set -eu |
| - | idVendor | + | |
| - | idProduct | + | |
| - | bcdDevice | + | |
| - | </ | + | |
| - | <code bash> | + | if [ "${DEVTYPE: |
| - | cat << | + | [ " |
| - | BINARY="/sbin/wifi up" | + | if [ " |
| - | RTL8188SU_PRODID="bda/8171/200" | + | if [ -L "/dev/${SYMLINK}" |
| + | logger -t hotplug | ||
| + | exit 0 | ||
| + | fi | ||
| - | if [ "${PRODUCT}" = "${RTL8188SU_PRODID}" | + | DEVICE_NAME="$(find /sys${DEVPATH:-} -maxdepth 1 -type d -iname ' |
| - | if [ "${ACTION}" = "add" ]; then | + | if [ -z "${DEVICE_NAME}" ]; then |
| - | | + | logger -t hotplug ' |
| - | fi | + | exit 0 |
| - | fi | + | fi |
| - | EOF | + | |
| - | </ | + | |
| - | === Symlink instead | + | logger -t hotplug " |
| - | An other script to create a symlink instead of renaming the device. | + | ln -s "/ |
| - | I test if DEVICE_NAME | + | logger -t hotplug " |
| + | fi | ||
| - | <code bash> | ||
| - | cat << " | ||
| - | CP210_PRODID=" | ||
| - | SYMLINK=" | ||
| - | if [ " | + | if [ " |
| - | | + | rm "/ |
| - | | + | logger -t hotplug " |
| - | if [ -z ${DEVICE_NAME} ]; then | + | fi |
| - | logger -t hotplug | + | |
| - | exit | + | |
| - | fi | + | |
| - | logger -t hotplug " | + | |
| - | ln -s / | + | |
| - | logger -t hotplug | + | |
| - | fi | + | |
| - | fi | + | |
| - | + | ||
| - | if [ " | + | |
| - | if [ " | + | |
| - | rm / | + | |
| - | logger -t hotplug " | + | |
| - | fi | + | |
| fi | fi | ||
| EOF | EOF | ||
| </ | </ | ||
| - | + | ==== Script that detects | |
| - | === Script that detects | + | |
| <code bash> | <code bash> | ||
| cat << " | cat << " | ||
| BT_PRODID=" | BT_PRODID=" | ||
| - | BT_PRODID_HOT=`echo ${PRODUCT} | cut -c 1-6` | + | BT_PRODID_HOT="${PRODUCT::6}" |
| #logger -t hotplug " | #logger -t hotplug " | ||
| Line 187: | Line 259: | ||
| </ | </ | ||
| - | === Auto start mjpg-streamer when an usb camera is plugged in === | + | ==== Auto start mjpg-streamer when an usb camera is plugged in ==== |
| <code bash> | <code bash> | ||
| cat << " | cat << " | ||
| Line 193: | Line 265: | ||
| add) | add) | ||
| # start process | # start process | ||
| - | | + | |
| ;; | ;; | ||
| remove) | remove) | ||
| # stop process | # stop process | ||
| - | | + | |
| ;; | ;; | ||
| esac | esac | ||
| Line 203: | Line 275: | ||
| </ | </ | ||
| - | === Custom automount script for xfs === | + | ==== Custom automount script for XFS ==== |
| <code bash> | <code bash> | ||
| cat << " | cat << " | ||
| Line 230: | Line 302: | ||
| </ | </ | ||
| - | ===== Coldplug | + | ==== Coldplug ==== |
| - | If you had notice | + | You may have noticed that the udev and eudev were removed in the openwrt 18.0.* release. Don' |
| You can use hotplug scripts as coldplug. | You can use hotplug scripts as coldplug. | ||
| - | Pay attention | + | Pay attention |
| - | So, just add this option to hotplug run accordinly. | + | So, just add this option to hotplug |
| In my case I used this: | In my case I used this: | ||
| <code bash> | <code bash> | ||
| + | mkdir -p / | ||
| cat << " | cat << " | ||
| # Description: | # Description: | ||
| - | if [ " | + | if [ " |
| case " | case " | ||
| 1bc7*) # Telit HE910 3g modules product id prefix | 1bc7*) # Telit HE910 3g modules product id prefix | ||
| Line 246: | Line 320: | ||
| DEVICE_TTY=" | DEVICE_TTY=" | ||
| # Module Telit HE910-* connected to minipciexpress slot MAIN | # Module Telit HE910-* connected to minipciexpress slot MAIN | ||
| - | if [ " | + | if [ " |
| ln -s / | ln -s / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| - | elif [ " | + | elif [ " |
| ln -s / | ln -s / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| # Module Telit HE910-* connected to minipciexpress slot SECONDARY | # Module Telit HE910-* connected to minipciexpress slot SECONDARY | ||
| - | elif [ " | + | elif [ " |
| ln -s / | ln -s / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| - | elif [ " | + | elif [ " |
| ln -s / | ln -s / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| Line 264: | Line 338: | ||
| fi | fi | ||
| # Action to remove the symlinks | # Action to remove the symlinks | ||
| - | if [ " | + | if [ " |
| case " | case " | ||
| 1bc7*) | 1bc7*) | ||
| # Module Telit HE910-* connected to minipciexpress slot MAIN | # Module Telit HE910-* connected to minipciexpress slot MAIN | ||
| - | if [ " | + | if [ " |
| rm / | rm / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| - | elif [ " | + | elif [ " |
| rm / | rm / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| # Module Telit HE910-* connected to minipciexpress slot SECONDARY | # Module Telit HE910-* connected to minipciexpress slot SECONDARY | ||
| - | elif [ " | + | elif [ " |
| rm / | rm / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| - | elif [ " | + | elif [ " |
| rm / | rm / | ||
| logger -t hotplug " | logger -t hotplug " | ||
| Line 288: | Line 362: | ||
| </ | </ | ||
| + | ==== Log DSL status changes ==== | ||
| + | If you have a DSL modem you can add logging of DSL status changes and connection data rates. | ||
| + | |||
| + | This can be helpful if your DSL connection is affected by Seamless Rate Adaptation (SRA) or | ||
| + | Dynamic Line Management (DLM) events; for SRA events data rate changes will be logged, while | ||
| + | for DLM events connection status changes will be logged as the modem is forced to retrain and then the new | ||
| + | data rates will be logged. | ||
| + | |||
| + | <code bash> | ||
| + | cat << " | ||
| + | case " | ||
| + | (DSL_INTERFACE_STATUS) | ||
| + | logger -p daemon.notice -t dsl-notify " | ||
| + | (DSL_DATARATE_STATUS_US) | ||
| + | logger -p daemon.notice -t dsl-notify "DSL upstream actual data rate: ${DSL_DATARATE_US_BC0}" | ||
| + | (DSL_DATARATE_STATUS_DS) | ||
| + | logger -p daemon.notice -t dsl-notify "DSL downstream actual data rate: ${DSL_DATARATE_DS_BC0}" | ||
| + | esac | ||
| + | EOF | ||
| + | </ | ||
| + | |||
| + | This script assumes that channel bonding is not compiled in to the DSL support. | ||
| + | |||
| + | ==== Utilize wireless USB adapter ==== | ||
| + | Restart Wi-Fi when plugging in a wireless USB adapter. | ||
| + | |||
| + | <code bash> | ||
| + | mkdir -p / | ||
| + | cat << " | ||
| + | if [ " | ||
| + | && [ " | ||
| + | then wifi | ||
| + | fi | ||
| + | EOF | ||
| + | </ | ||
| + | |||
| + | The above code matches the following device. | ||
| + | |||
| + | <code bash> | ||
| + | # lsusb -v | ||
| + | idVendor 0x0bda Realtek Semiconductor Corp. | ||
| + | idProduct 0x8171 RTL8188SU 802.11n WLAN Adapter | ||
| + | bcdDevice 2.00 | ||
| + | </ | ||
| + | |||
| + | ==== Get specific IP address ==== | ||
| + | Assuming your ISP provides a dynamic IP address. | ||
| + | Reconnect until you get the one matching a specific regexp. | ||
| + | Delay for 10 seconds between reconnects. | ||
| + | Set up [[docs: | ||
| + | |||
| + | <code bash> | ||
| + | mkdir -p / | ||
| + | cat << " | ||
| + | . / | ||
| + | network_flush_cache | ||
| + | network_find_wan WAN_IF | ||
| + | network_get_ipaddr WAN_ADDR " | ||
| + | if [ " | ||
| + | then exit 0 | ||
| + | fi | ||
| + | case ${WAN_ADDR} in | ||
| + | (??.???.*) exit 0 ;; | ||
| + | esac | ||
| + | sleep 10 | ||
| + | ifup ${INTERFACE} | ||
| + | EOF | ||
| + | </ | ||
| + | |||
| + | ==== Rename interfaces by MAC address ==== | ||
| + | Assuming pre-configured upstream interfaces '' | ||
| + | Set up persistent interface names by MAC address. | ||
| + | |||
| + | <code bash> | ||
| + | cat << " | ||
| + | dev_rename() { | ||
| + | local DEV_CONF=" | ||
| + | local DEV_MAC DEV_NAME DEV_ONAME | ||
| + | config_get DEV_MAC " | ||
| + | config_get DEV_NAME " | ||
| + | DEV_ONAME=" | ||
| + | $(find / | ||
| + | | sed -e " | ||
| + | | awk -F '/' | ||
| + | if [ -n " | ||
| + | && [ " | ||
| + | then ip link set " | ||
| + | fi | ||
| + | } | ||
| + | . / | ||
| + | config_load network | ||
| + | config_foreach dev_rename device | ||
| + | EOF | ||
| + | |||
| + | while read -r DEV_NAME DEV_MAC | ||
| + | do | ||
| + | uci set network.${DEV_NAME}.device=" | ||
| + | uci set network.${DEV_NAME}6.device=" | ||
| + | uci -q delete network.${DEV_NAME}_dev | ||
| + | uci set network.${DEV_NAME}_dev=" | ||
| + | uci set network.${DEV_NAME}_dev.mac=" | ||
| + | uci set network.${DEV_NAME}_dev.name=" | ||
| + | done << EOI | ||
| + | wana 11: | ||
| + | wanb aa: | ||
| + | EOI | ||
| + | uci commit network | ||
| + | service network restart | ||
| + | </ | ||
| + | |||
| + | ==== Create deterministic/ | ||
| + | Resulting links will be placed in / | ||
| + | with a name structure closely resembling links created by udev, but not fully exact. | ||
| + | |||
| + | <code bash> | ||
| + | set -o pipefail | ||
| + | [ " | ||
| + | [ " | ||
| + | [ -n " | ||
| + | |||
| + | if [ " | ||
| + | subsystem=" | ||
| + | |||
| + | [ " | ||
| + | |||
| + | replace_whitespace=" | ||
| + | manufacturer=" | ||
| + | product=" | ||
| + | serial=" | ||
| + | interface=" | ||
| + | port=" | ||
| + | |||
| + | replace_chars=" | ||
| + | id_link=$(echo " | ||
| + | path_link=$(echo " | ||
| + | |||
| + | mkdir -p / | ||
| + | ln -sf "/ | ||
| + | ln -sf "/ | ||
| + | elif [ " | ||
| + | for link in $(find /dev/serial -type l); do | ||
| + | [ -L ${link} -a " | ||
| + | done | ||
| + | fi | ||
| + | </ | ||
| + | [[https:// | ||