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 [2019/09/13 19:51] – code optimized 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 6: | Line 6: | ||
| ===== How it works ===== | ===== How it works ===== | ||
| - | In the ''/ | + | In the ''/ |
| - | When the trigger event fires, Procd will execute all scripts in that trigger' | + | When the trigger event fires, Procd will execute all scripts in that trigger' |
| + | Which is why most scripts in there use a numeric prefix. | ||
| - | ^ Directory ^ Description ^ | + | ^ Directory |
| - | | **block** | Block device events | + | | **block** |
| - | | **button** | Buttons | + | | **button** |
| - | | **iface** | Interface events | + | | **dhcp** |
| - | | **net** | Network-related events | | + | | **dsl** |
| - | | **ntp** | Time sync events | + | | **firewall** |
| - | | **usb** | USB devices like 3g-modem and tty* | | + | | **iface** |
| + | | **neigh** | ||
| + | | **net** | ||
| + | | **ntp** | ||
| + | | **tftp** | ||
| + | | **tty** | ||
| + | | **usb** | ||
| + | | **usbmisc** | ||
| - | There may (should) be others, for other types of triggers. By looking at the source | + | See also: |
| + | * [[https://github.com/ | ||
| + | * [[https:// | ||
| + | * [[docs: | ||
| - | ===== Usage ===== | + | ===== Usage / Troubleshooting |
| - | Simply place your script(s) into the right hotplug.d | + | Simply place your script(s) into the right hotplug.d |
| - | ===== Information provided to your scripts / Troubleshooting ===== | ||
| Procd exposes a wealth of info when executes your scripts in ''/ | Procd exposes a wealth of info when executes your scripts in ''/ | ||
| - | If you want to see what environmental variables it is providing, make a script | + | If you want to see what environmental variables it is providing, make a script |
| <code bash> | <code bash> | ||
| - | env > /tmp/envs_log.log | + | cat << " |
| + | logger -t hotplug $(env) | ||
| + | EOF | ||
| </ | </ | ||
| - | and place it in the folder you want to use, then trigger the event connected to that folder, and then you can see what envs were passed by reading the ''/ | + | Then trigger the event connected to that directory, and then you can see what envs were passed by reading the output: |
| - | ==== The block folder | + | <code bash> |
| - | For scripts in **block** | + | logread -e hotplug |
| + | </ | ||
| + | |||
| + | ===== 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 ==== | ||
| + | For scripts in **block** | ||
| ^ Variable name ^ Description ^ | ^ Variable name ^ Description ^ | ||
| - | | ACTION | Either | + | | ACTION | For normal device (e.g: sda) it is either |
| | DEVICENAME | seems same as DEVNAME below | | | DEVICENAME | seems same as DEVNAME below | | ||
| | DEVNAME | Device or partition name (if I connect a drive I get a hotplug call with " | | DEVNAME | Device or partition name (if I connect a drive I get a hotplug call with " | ||
| Line 47: | Line 79: | ||
| | SUBSYSTEM | seems this is only " | | SUBSYSTEM | seems this is only " | ||
| - | ==== The iface folder | + | ==== dsl ==== |
| - | There are three main environment variables that are passed to each **iface** hotplug script: | + | For scripts in **dsl** directory, these are the (relevant) environment variables |
| ^ Variable name ^ Description ^ | ^ Variable name ^ Description ^ | ||
| - | | ACTION | Either " | + | | DSL_NOTIFICATION_TYPE | '' |
| - | | INTERFACE | Name of the interface which went up or down (e.g. "wan" | + | | DSL_LINE_NUMBER | '' |
| - | | DEVICE | Physical | + | |
| + | 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 ==== | ||
| + | For scripts in **iface** directory, these are the (relevant) environmental variables | ||
| + | |||
| + | ^ Variable name ^ Description ^ | ||
| + | | ACTION | '' | ||
| + | | INTERFACE | Name of the logical | ||
| + | | DEVICE | Name of the physical | ||
| + | |||
| + | 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 ==== | ||
| + | Variables based on busybox ntpd: | ||
| - | ==== The ntp folder ==== | ||
| ^ 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 periodic hotplug event, with stratum=16, about every 11 minutes out of the box. | + | Even without NTP sync, you will receive a "periodic" |
| - | ==== The usb folder | + | ==== tty ==== |
| ^ Variable name ^ description ^ | ^ Variable name ^ description ^ | ||
| - | | ACTION | add, remove as above | | + | | ACTION | add, remove, bind, unbind |
| - | | DEVNAME | eg, "bus/ | + | | DEVICENAME | eg " |
| - | | DEVPATH | 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 ==== | ||
| + | ^ Variable name ^ description ^ | ||
| + | | ACTION | add, remove, bind, unbind as above | | ||
| | 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 91: | 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># lsusb -v | + | |
| - | idVendor | + | |
| - | idProduct | + | |
| - | bcdDevice | + | |
| - | </ | + | |
| - | <code bash> | ||
| - | cat << " | ||
| - | BINARY="/ | ||
| - | RTL8188SU_PRODID=" | ||
| - | |||
| - | if [ " | ||
| - | if [ " | ||
| - | ${BINARY} | ||
| - | fi | ||
| - | fi | ||
| - | EOF | ||
| - | </ | ||
| - | |||
| - | === Symlink instead of rename a device === | ||
| - | An other script to create a symlink instead of renaming the device.\\ | ||
| - | I test if DEVICE_NAME is empty because when I plug usb device I retrieve two add event, and the first come before created device, so symlink fails. | ||
| <code bash> | <code bash> | ||
| cat << " | cat << " | ||
| - | CP210_PRODID="10c4/ | + | CP210_PRODID='10c4/ |
| SYMLINK=" | SYMLINK=" | ||
| - | if [ " | + | set -eu |
| - | if [ " | + | |
| - | DEVICE_NAME=$(ls / | + | |
| - | if [ -z ${DEVICE_NAME} ]; then | + | |
| - | logger -t hotplug " | + | |
| - | exit | + | |
| - | fi | + | |
| - | logger -t hotplug " | + | |
| - | ln -s / | + | |
| - | logger -t hotplug " | + | |
| - | fi | + | |
| - | fi | + | |
| - | if [ " | + | if [ " |
| - | if [ " | + | [ " |
| - | rm / | + | if [ " |
| - | logger -t hotplug " | + | if [ -L "/ |
| - | fi | + | logger -t hotplug " |
| + | exit 0 | ||
| + | fi | ||
| + | |||
| + | DEVICE_NAME=" | ||
| + | if [ -z " | ||
| + | logger -t hotplug ' | ||
| + | exit 0 | ||
| + | fi | ||
| + | |||
| + | logger -t hotplug " | ||
| + | ln -s "/ | ||
| + | logger -t hotplug " | ||
| + | fi | ||
| + | |||
| + | |||
| + | 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 170: | 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 176: | Line 265: | ||
| add) | add) | ||
| # start process | # start process | ||
| - | | + | |
| ;; | ;; | ||
| remove) | remove) | ||
| # stop process | # stop process | ||
| - | | + | |
| ;; | ;; | ||
| esac | esac | ||
| Line 186: | Line 275: | ||
| </ | </ | ||
| - | === Custom automount script for xfs === | + | ==== Custom automount script for XFS ==== |
| <code bash> | <code bash> | ||
| cat << " | cat << " | ||
| Line 213: | 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' |
| - | **Using | + | You can use hotplug scripts as coldplug. |
| - | You just need to pay atention at the ACTION | + | Pay attention |
| - | So, just add this option to hotplug run accordinly. In my case I used this: | + | So, just add this option to hotplug |
| + | |||
| + | 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 228: | 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 246: | 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 270: | 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:// | ||