Hotplug

Procd (ініціалізаційна система та демон керування процесами) виконує скрипти, розміщені в каталозі /etc/hotplug.d, коли відбуваються певні події — наприклад, коли інтерфейс підключається або відключається, коли виявлено новий накопичувач, або коли натиснута кнопка.

Це може бути дуже корисним для PPPoE-з’єднання, в умовах нестабільної мережі або для використання апаратних кнопок.

Ця функціональність емулює або розширює можливості, які раніше реалізовувалися за допомогою застарілого пакету Hotplug2.

У каталозі /etc/hotplug.d ви знайдете підкаталоги block, iface, net та ntp.

Коли виникає тригерна подія, Procd виконує всі скрипти в відповідному каталозі цієї події, у алфавітному порядку. Саме тому більшість скриптів мають числовий префікс.

Каталог Опис
block Події з блочними пристроями: пристрій підключено/відключено
button Події кнопок: за замовчуванням не створюється, див. /etc/rc.button
dhcp Події, пов’язані з DHCP
dsl Події модему DSL
firewall Події, пов’язані з фаєрволом
iface Події інтерфейсів: підключення/відключення LAN/WAN тощо
neigh Виявлення сусідів (Neighbor Discovery)
net Події, пов’язані з мережею
ntp Події синхронізації часу: зміна часу, зміна рівня stratum NTP сервера
tftp Події, пов’язані з TFTP
tty Події з TTY-пристроями, включно з модемами WWAN, що напряму вказують на інтерфейс TTY
usb USB-пристрої, наприклад, 3G-модеми та tty*
usbmisc Спеціальні USB-периферійні пристрої, такі як принтери (у цьому підсистемі доступно менше змінних)

Див. також:

Кнопки, звукові пристрої, послідовні та USB-послідовні адаптери

DHCP, NDP, TFTP

Скрипти клієнта DHCP

Просто розмістіть ваші скрипти в потрібному підкаталозі hotplug.d. Якщо каталогу не існує — створіть його.

Procd передає велику кількість інформації до скриптів у /etc/hotplug.d, зазвичай у вигляді змінних середовища.

Якщо ви хочете побачити, які саме змінні передаються, створіть такий скрипт:

 cat << "EOF" > /etc/hotplug.d/iface/00-logger logger -t hotplug $(env) EOF 

Потім виконайте подію, пов’язану з цим каталогом, і перегляньте змінні середовища через:

 logread -e hotplug 

Для скриптів у каталозі net, доступні такі (релевантні) змінні середовища:

Назва змінної Опис
ACTION Значення “add” або “remove” (додавання або видалення пристрою)
DEVICENAME Імена налаштованих інтерфейсів (наприклад, br-lan, wlan0, phy1-ap0)
PATH Повний шлях
DEVPATH Повний шлях до пристрою (наприклад, “/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host7/target7:0:0/7:0:0:0/block/sdc/sdc1”)
DEVTYPE Тип пристрою, до якого належить DEVICENAME (наприклад, br-lan, phy1-ap0)
INTERFACE Налаштовані інтерфейси, подібно до DEVTYPE
SEQNUM Порядковий номер події (ціле число)
SUBSYSTEM Завжди дорівнює “net”
IFINDEX Індекс інтерфейсу, можна переглянути через ifconfig

Для скриптів у каталозі block, доступні такі (релевантні) змінні середовища:

Назва змінної Опис
ACTION Для звичайного пристрою (наприклад, sda) значення буде “add” або “remove”. Може бути “change” для зашифрованого пристрою (dm-crypt, наприклад, dm-0)
DEVICENAME Як правило, те саме, що і DEVNAME
DEVNAME Назва пристрою або розділу (наприклад, підключення накопичувача викликає події з sda і потім з sda1)
DEVPATH Повний шлях до пристрою (наприклад, “/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host7/target7:0:0/7:0:0:0/block/sdc/sdc1”)
DEVTYPE Тип імені пристрою, наприклад, “partition” для розділу або “disk” при видаленні
MAJOR Основний номер пристрою
MINOR Додатковий номер пристрою
SEQNUM Порядковий номер події (число)
SUBSYSTEM Завжди дорівнює “block”

Для скриптів у каталозі dsl доступні наступні (релевантні) змінні середовища:

Назва змінної Опис
DSL_NOTIFICATION_TYPE DSL_STATUS, DSL_INTERFACE_STATUS, DSL_DATARATE_STATUS_US, DSL_DATARATE_STATUS_DS
DSL_LINE_NUMBER 0, 1 *

Коли DSL_NOTIFICATION_TYPE дорівнює DSL_STATUS, встановлюються наступні змінні:

Назва змінної Опис
DSL_XTU_STATUS ADSL, VDSL
DSL_TC_LAYER_STATUS ATM, EFM
DSL_EFM_TC_CONFIG_US NORMAL, PRE_EMPTION, UNKNOWN
DSL_EFM_TC_CONFIG_DS NORMAL, UNKNOWN

Коли DSL_NOTIFICATION_TYPE дорівнює DSL_INTERFACE_STATUS:

Назва змінної Опис
DSL_INTERFACE_STATUS DOWN, READY, HANDSHAKE, TRAINING, UP
DSL_BONDING_STATUS INACTIVE, ACTIVE *

Коли DSL_NOTIFICATION_TYPE дорівнює DSL_DATARATE_STATUS_US:

Назва змінної Опис
DSL_DATARATE_US_BC0 Швидкість висхідної передачі в біт/с для каналу 0
DSL_DATARATE_US_BC1 Швидкість висхідної передачі в біт/с для каналу 1 *

Коли DSL_NOTIFICATION_TYPE дорівнює DSL_DATARATE_STATUS_DS:

Назва змінної Опис
DSL_DATARATE_DS_BC0 Швидкість низхідної передачі в біт/с для каналу 0
DSL_DATARATE_DS_BC1 Швидкість низхідної передачі в біт/с для каналу 1 *

Примітка: Змінні, позначені зірочкою (*), доступні лише якщо підтримка агрегації каналів (channel bonding) скомпільована у систему.

Для скриптів у каталозі iface доступні наступні змінні середовища:

Назва змінної Опис
ACTION ifdown, ifup, ifup-failed, ifupdate, free, reload, iflink, create
INTERFACE Назва логічного інтерфейсу, який піднято або опущено (наприклад, wan, lan)
DEVICE Назва фізичного пристрою, який змінив стан (наприклад, eth0, br-lan, pppoe-wan)

Менш очевидні значення ACTION:

Значення Опис
ifup-failed Подія ifdown сталася під час спроби підняти інтерфейс
free Інтерфейс видалено (зворотне до create)
iflink Інтерфейс повідомив про наявність носія (carrier)

Якщо ACTION — це ifupdate, можуть бути встановлені такі змінні:

Назва змінної Опис
IFUPDATE_ADDRESSES 1, якщо змінилася IP-адреса
IFUPDATE_ROUTES 1, якщо змінився маршрут
IFUPDATE_PREFIXES 1, якщо змінився префікс
IFUPDATE_DATA 1, якщо виконано ubus call network.interface.$INTERFACE set_data ... або подібне

Змінні на основі busybox ntpd:

Назва змінної Опис
ACTION step, stratum, unsync, periodic
freq_drift_ppm Зсув частоти
offset Корекція часу
stratum Рівень якості часу (відстань до атомного годинника)
poll_interval Інтервал опитування

Навіть без синхронізації з NTP ви будете отримувати подію periodic з stratum=16 приблизно кожні 11 хвилин.

Назва змінної Опис
ACTION add, remove, bind, unbind
DEVICENAME Наприклад, ttyUSB2
DEVNAME Тільки для bind/unbind, напр. ttyUSB2
DEVPATH Шлях до пристрою, напр. /devices/platform/ahb/.../ttyUSB2
SEQNUM Номер події з моменту запуску системи
SUBSYSTEM Тип пристрою, напр. usb-serial
MAJOR Основний номер пристрою
MINOR Додатковий номер пристрою
Назва змінної Опис
ACTION add, remove, bind, unbind
DEVICENAME Напр., 1-1
DEVNAME Напр., bus/usb/001/002
DEVNUM Напр., 002
DEVPATH Напр., /devices/platform/ehci-platform/usb1/1-1
DEVTYPE Тип пристрою, напр., usb_device
TYPE Класифікація пристрою, напр., 9/0/1
PRODUCT Коди виробника/пристрою/версії, напр. 424/2640/0 (див. lsusb)
SEQNUM Номер події з моменту запуску
BUSNUM Номер шини USB, напр., 001
MAJOR Основний номер пристрою
MINOR Додатковий номер пристрою
Назва змінної Опис
ACTION add, remove
DEVNAME Напр., bus/usb/001/002
DEVPATH Напр., /devices/platform/ehci-platform/usb1/1-1
DEVICENAME Напр., 1-1
SEQNUM Номер події з моменту запуску
MAJOR Основний номер пристрою
MINOR Додатковий номер пристрою
cat << "EOF" > /etc/hotplug.d/iface/99-my-action
[ "${ACTION}" = "ifup" ] && {
    logger -t hotplug "Device: ${DEVICE} / Action: ${ACTION}"
}
EOF

Щоразу, коли інтерфейс піднімається, буде виконано блок if.

Ще один скрипт, який створює символічне посилання (symlink) замість перейменування пристрою:

cat << "EOF" > /etc/hotplug.d/usb/20-cp210x
CP210_PRODID='10c4/ea60/100'
SYMLINK="my_link"
 
set -eu
 
if [ "${DEVTYPE:-}" = 'usb_interface' ] && \
   [ "${PRODUCT:-}" = "${CP210_PRODID}" ]; then
  if [ "${ACTION:-}" = 'bind' ]; then
    if [ -L "/dev/${SYMLINK}" ]; then
      logger -t hotplug "Symlink '/dev/${SYMLINK}' already exists"
      exit 0
    fi
 
    DEVICE_NAME="$(find /sys${DEVPATH:-} -maxdepth 1 -type d -iname 'ttyUSB*' -exec basename {} \;)"
    if [ -z "${DEVICE_NAME}" ]; then
      logger -t hotplug 'Warning: DEVICE_NAME is empty'
      exit 0
    fi
 
    logger -t hotplug "Device name of cp210 is '${DEVICE_NAME}'"
    ln -s "/dev/${DEVICE_NAME}" "/dev/${SYMLINK}"
    logger -t hotplug "Symlink from '/dev/${DEVICE_NAME}' to '/dev/${SYMLINK}' created"
  fi
 
 
  if [ "${ACTION:-}" = 'unbind' ]; then
    rm "/dev/${SYMLINK}"
    logger -t hotplug "Symlink '/dev/${SYMLINK}' removed"
  fi
fi
EOF

Аналогічно, також можливо запускати ser2net для надання доступу до послідовного порту віддалено через мережу.

cat << "EOF" > /etc/hotplug.d/usb/20-cp210x-ser2net
CP210_PRODID='10c4/ea60/100'
SER2NET_PID='/var/run/ser2net.pid'
SER2NET_PORT=18888
SER2NET_BAUDRATE=115200
SER2NET_FLOWRATE='software'
SER2NET_RADIO='znp'
SER2NET_OPTS="${SER2NET_BAUDRATE} NONE 1STOPBIT 8DATABITS -RTSCTS -LOCAL NOBREAK"
 
set -eu
 
if [ "${DEVTYPE:-}" = 'usb_interface' ] && \
   [ "${PRODUCT:-}" = "${CP210_PRODID}" ]; then
        if [ "${ACTION:-}" = 'bind' ]; then
                if [ -s "${SER2NET_PID}" ]; then
                        logger -t hotplug "Warning: ser2net already running as pid: $(cat "${SER2NET_PID}") via ${SER2NET_PID}"
                        exit 0
                fi
 
                DEVICE_NAME="$(find "/sys${DEVPATH:-}" -maxdepth 1 -type d -iname 'ttyUSB*' -exec basename {} \;)"
                if [ -z "${DEVICE_NAME}" ]; then
                        logger -t hotplug 'Warning: DEVICE_NAME is empty'
                        exit 0
                fi
                logger -t hotplug "Device name of cp210 is '${DEVICE_NAME}'"
 
                ser2net -C "${SER2NET_PORT}:raw:100:/dev/${DEVICE_NAME}:${SER2NET_OPTS}" -P "${SER2NET_PID}"
                if [ -d '/etc/avahi/services' ]; then
                        {
                                printf '<service-group>\n\n'
                                printf '  <name replace-wildcards="yes">%%h</name>\n\n'
                                printf '  <service>\n'
                                printf '    <type>_ser2net_zigbee-gateway._tcp</type>\n'
                                printf '    <port>%d</port>\n' "${SER2NET_PORT}"
                                printf '    <txt-record>baudrate=%d</txt-record>\n' "${SER2NET_BAUDRATE:-115200}"
                                printf '    <txt-record>flow-control=%s</txt-record>\n' "${SER2NET_FLOWRATE:-software}"
                                printf '    <txt-record>radio=%s</txt-record>\n' "${SER2NET_RADIO:-znp}"
                                printf '  </service>\n\n'
                                printf '</service-group>\n'
                        } > '/etc/avahi/services/ser2net.service'
                fi
 
                logger -t hotplug "Started ser2net on '/dev/${DEVICE_NAME}'"
        fi
 
        if [ "${ACTION:-}" = 'unbind' ]; then
                logger -t hotplug "Attempting to stop ser2net with pid: $(cat "${SER2NET_PID}")"
                kill -3 "$(cat "${SER2NET_PID}")"
                if [ -s '/etc/avahi/services/ser2net.service' ]; then
                        rm '/etc/avahi/services/ser2net.service'
                fi
                if [ ! -s "${SER2NET_PID}" ]; then
                        logger -t hotplug 'Failed'
                        exit 0
                fi
        fi
fi
EOF
Примітка: Наведений вище приклад також демонструє інтеграцію з Avahi, що забезпечує автоматичне виявлення послідовного порту в мережі. У цьому прикладі до послідовного порту підключено Zigbee-пристрій.
cat << "EOF" > /etc/hotplug.d/usb/20-bt_test
BT_PRODID="a12/1/"
BT_PRODID_HOT="${PRODUCT::6}"
 
#logger -t hotplug "PRODUCT ID is ${BT_PRODID_HOT}"
 
if [ "${BT_PRODID_HOT}" = "${BT_PRODID}" ]; then
    if [ "${ACTION}" = "add" ]; then
        logger -t hotplug "bluetooth device has been plugged in!"
        if [ "${BSBTID_NEW}" = "${BSBTID_OLD}" ]; then
            logger -t hotplug "bluetooth device hasn't changed"
        else
            logger -t hotplug "bluetooth device has changed"
        fi
    fi
    if [ "${ACTION}" = "remove" ]; then
        logger -t hotplug "bluetooth device has been removed!"
    fi
else
    logger -t hotplug "USB device is not bluetooth"
fi
EOF
cat << "EOF" > /etc/hotplug.d/usb/20-mjpg_start
case "${ACTION}" in
    add)
            # start process
        service mjpg-streamer start
            ;;
    remove)
            # stop process
        service mjpg-streamer stop
            ;;
esac
EOF
cat << "EOF" > /etc/hotplug.d/block/xfs_automount
# if a new block device is connected
if [ "${ACTION}" = "add" ]; then
    # getting device UUID
    detected_uuid="$(xfs_admin -u /dev/${DEVICENAME} | awk '{print $3}')"
    # deciding mountpoint for known UUID
    mountpoint=""
    case "${detected_uuid}" in
        6a5d7c5c-c9d0-41cc-8f19-78d97f839c05)
            mountpoint="/path/to/first/mountpoint"
            ;;
        02880b1f-0c67-46b6-9b05-5535680ccc89)
            mountpoint="/path/to/second/mountpoint"
            ;;
    esac
 
    # if we have a known UUID we have a mountpoint so we can mount it
    if [ "${mountpoint}" != "" ]; then
        mount /dev/${DEVICENAME} ${mountpoint}
    fi
fi
# unmounting happens automatically at device disconnection anyway so no logic for that
EOF

Ви могли помітити, що udev та eudev були видалені у випуску OpenWrt 18.0.*. Не хвилюйтеся — все ще можна змусити все працювати.

Замість них можна використовувати скрипти hotplug як coldplug. Зверніть увагу на змінну оточення ACTION: при завантаженні системи виконуються дії типу bind. Тому просто додайте цю перевірку у ваш скрипт hotplug і він спрацює належним чином.

У моєму випадку я використав таке:

mkdir -p /etc/hotplug.d/usb
cat << "EOF" > /etc/hotplug.d/usb/22-symlinks
# Description: Action executed on boot (bind) and with the system on the fly
if [ "${ACTION}" = "bind" ]; then
  case "${PRODUCT}" in
    1bc7*) # Telit HE910 3g modules product id prefix
      DEVICE_NAME="$(ls /sys/${DEVPATH} | grep tty)"
      DEVICE_TTY="$(ls /sys/${DEVPATH}/tty/)"
      # Module Telit HE910-* connected to minipciexpress slot MAIN
      if [ "${DEVICENAME}" = "1-1.3:1.0" ]; then
        ln -s /dev/${DEVICE_TTY} /dev/ttyMODULO1_DIAL
        logger -t hotplug "Symlink from /dev/${DEVICE_TTY} to /dev/ttyMODULO1_DIAL created"
      elif [ "${DEVICENAME}" = "1-1.3:1.6" ]; then
        ln -s /dev/${DEVICE_TTY} /dev/ttyMODULO1_DATA
        logger -t hotplug "Symlink from /dev/${DEVICE_TTY} to /dev/ttyMODULO1_DATA created"
      # Module Telit HE910-* connected to minipciexpress slot SECONDARY
      elif [ "${DEVICENAME}" = "1-1.2:1.0" ]; then
        ln -s /dev/${DEVICE_TTY} /dev/ttyMODULO2_DIAL
        logger -t hotplug "Symlink from /dev/${DEVICE_TTY} to /dev/ttyMODULO2_DIAL created"
      elif [ "${DEVICENAME}" = "1-1.2:1.6" ]; then
        ln -s /dev/${DEVICE_TTY} /dev/ttyMODULO2_DATA
        logger -t hotplug "Symlink from /dev/${DEVICE_TTY} to /dev/ttyMODULO2_DATA created"
      fi
    ;;
  esac
fi
# Action to remove the symlinks
if [ "${ACTION}" = "remove" ]; then
  case "${PRODUCT}" in
    1bc7*)  # Telit HE910 3g modules product id prefix
     # Module Telit HE910-* connected to minipciexpress slot MAIN
      if [ "${DEVICENAME}" = "1-1.3:1.0" ]; then
        rm /dev/ttyMODULO1_DIAL
        logger -t hotplug "Symlink /dev/ttyMODULO1_DIAL removed"
      elif [ "${DEVICENAME}" = "1-1.3:1.6" ]; then
        rm /dev/ttyMODULO1_DATA
        logger -t hotplug "Symlink /dev/ttyMODULO1_DATA removed"
      # Module Telit HE910-* connected to minipciexpress slot SECONDARY
      elif [ "${DEVICENAME}" = "1-1.2:1.0" ]; then
        rm /dev/ttyMODULO2_DIAL
        logger -t hotplug "Symlink /dev/ttyMODULO2_DIAL removed"
      elif [ "${DEVICENAME}" = "1-1.2:1.6" ]; then
        rm /dev/ttyMODULO2_DATA
        logger -t hotplug "Symlink /dev/ttyMODULO2_DATA removed"
      fi
    ;;
  esac
fi
EOF

Якщо у вас є DSL-модем, ви можете увімкнути журналювання змін статусу DSL та швидкостей передачі даних.

Це може бути корисним, якщо на ваш DSL-зв’язок впливають події Seamless Rate Adaptation (SRA) або Dynamic Line Management (DLM); у разі подій SRA будуть фіксуватись зміни швидкості передачі даних, а у випадку подій DLM — зміни статусу з’єднання, оскільки модем змушений перетренуватися, після чого будуть зафіксовані нові швидкості передачі даних.

cat << "EOF" > /etc/hotplug.d/dsl/20-dsl_status
case "${DSL_NOTIFICATION_TYPE}" in
(DSL_INTERFACE_STATUS)
  logger -p daemon.notice -t dsl-notify "${DSL_XTU_STATUS} link status: ${DSL_INTERFACE_STATUS}" ;;
(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

Цей скрипт передбачає, що підтримка об'єднання каналів (channel bonding) не скомпільована в DSL-модулі.

Перезапуск Wi-Fi при підключенні бездротового USB-адаптера.

mkdir -p /etc/hotplug.d/usb
cat << "EOF" > /etc/hotplug.d/usb/20-rtl8188su
if [ "${PRODUCT}" = "bda/8171/200" ] \
&& [ "${ACTION}" = "add" ]
then wifi
fi
EOF

“Наведений вище код спрацьовує для такого пристрою.

# lsusb -v
  idVendor  0x0bda Realtek Semiconductor Corp.
  idProduct 0x8171 RTL8188SU 802.11n WLAN Adapter
  bcdDevice 2.00

Припускається, що ваш провайдер надає динамічну IP-адресу. Повторюйте підключення, доки не отримаєте адресу, що відповідає певному регулярному виразу.

Перед кожною новою спробою зробіть паузу 10 секунд.

Налаштуйте додаткову обробку подій hotplug, щоб запускати цей скрипт після підключення WAN-інтерфейсу.

mkdir -p /etc/hotplug.d/online
cat << "EOF" > /etc/hotplug.d/online/10-wan-ipaddr
. /lib/functions/network.sh
network_flush_cache
network_find_wan WAN_IF
network_get_ipaddr WAN_ADDR "${WAN_IF}"
if [ "${WAN_IF}" != "${INTERFACE}" ]
then exit 0
fi
case ${WAN_ADDR} in
(??.???.*) exit 0 ;;
esac
sleep 10
ifup ${INTERFACE}
EOF

Припускається, що заздалегідь налаштовані інтерфейси — wana та wanb.

Для встановлення постійних (детермінованих) імен мережевих інтерфейсів на основі MAC-адреси, виконайте наступні дії.

cat << "EOF" > /etc/hotplug.d/iface/00-dev-rename
dev_rename() {
local DEV_CONF="${1}"
local DEV_MAC DEV_NAME DEV_ONAME
config_get DEV_MAC "${DEV_CONF}" mac
config_get DEV_NAME "${DEV_CONF}" name
DEV_ONAME="$(grep -l -e "${DEV_MAC}" \
$(find /sys/class/net/*/device/uevent \
| sed -e "s|/device/uevent$|/address|") \
| awk -F '/' '{print $5}')"
if [ -n "${DEV_MAC}" ] \
&& [ "${DEV_ONAME}" != "${DEV_NAME}" ]
then ip link set "${DEV_ONAME}" name "${DEV_NAME}"
fi
}
. /lib/functions.sh
config_load network
config_foreach dev_rename device
EOF
 
while read -r DEV_NAME DEV_MAC
do
uci set network.${DEV_NAME}.device="${DEV_NAME}"
uci set network.${DEV_NAME}6.device="${DEV_NAME}"
uci -q delete network.${DEV_NAME}_dev
uci set network.${DEV_NAME}_dev="device"
uci set network.${DEV_NAME}_dev.mac="${DEV_MAC}"
uci set network.${DEV_NAME}_dev.name="${DEV_NAME}"
done << EOI
wana 11:22:33:44:55:66
wanb aa:bb:cc:dd:ee:ff
EOI
uci commit network
service network restart

Результат: символічні посилання будуть створені в каталогах /dev/serial/by-id та /dev/serial/by-path.

Імена посилань матимуть структуру, яка максимально подібна до тієї, яку створює udev у більшості дистрибутивів Linux, але не є повністю ідентичною.

set -o pipefail
[ "${ACTION}" = "bind" -o "${ACTION}" = "unbind" ] || exit 0
[ "${SUBSYSTEM}" = "usb-serial" ] || exit 0
[ -n "${DEVICENAME}" -a -n "${DEVPATH}" ] || exit 1
 
if [ "${ACTION}" = "bind" ]; then
        subsystem="$(basename $(readlink /sys${DEVPATH}/../subsystem))"
 
        [ "$subsystem" = "usb" ] || exit 0
 
        replace_whitespace="s/^[ \t]*|[ \t]*$//g; s/[ \t]+/_/g"
        manufacturer="$(cat /sys${DEVPATH}/../../manufacturer | sed -E "${replace_whitespace}")" || manufacturer="$(cat /sys${DEVPATH}/../../idVendor)"
        product="$(cat /sys${DEVPATH}/../../product | sed -E "${replace_whitespace}")" || product="$(cat /sys${DEVPATH}/../../idProduct)"
        serial="$(cat /sys${DEVPATH}/../../serial | sed -E "${replace_whitespace}")"
        interface="$(cat /sys${DEVPATH}/../bInterfaceNumber)"
        port="$(cat /sys${DEVPATH}/port_number)"
 
        replace_chars="s/[^0-9A-Za-z#+.:=@-]/_/g"
        id_link=$(echo "${subsystem}"-"${manufacturer}"_"${product}${serial:+_}${serial}"-if"${interface}${port:+-port}${port}" | sed "${replace_chars}")
        path_link=$(echo "${DEVPATH}${port:+-port}${port}" | sed "s%/devices/%%; s%/${DEVICENAME}%%g; ${replace_chars}")
 
        mkdir -p /dev/serial/by-id /dev/serial/by-path
        ln -sf "/dev/${DEVICENAME}" "/dev/serial/by-id/${id_link}"
        ln -sf "/dev/${DEVICENAME}" "/dev/serial/by-path/${path_link}"
elif [ "${ACTION}" = "unbind" ]; then
        for link in $(find /dev/serial -type l); do
                [ -L ${link} -a "$(readlink ${link})" = "/dev/$DEVICENAME" ] && rm ${link}
        done
fi

(Source)

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2025/05/30 14:45
  • by vazaz