add ATA disk mapping, zpool check, netdev check, and a config file (#15)

1. Add the config file /etc/ugreen-leds.conf for environment variables used in ugreen-diskiomon (see scripts/ugreen-leds.conf)
2. Make the blinking of netdev activities, colors of different disk states / NIC link speeds configurable
3. Add the check of zpool health
4. Add the check of gateway connectivity and the link speed of network device
5. Split the systemd service to ugreen-diskiomon.service and ugreen-netdevmon@<device name>.service
6. HCTL mapping will fail in some cases (hctl mapping for SATA drives only #14), UGOS uses ATA number to map disks to slots. I changed the default mapping to ATA, which can be shown by the following scripts:
This commit is contained in:
Yuhao Zhou
2024-06-22 03:26:26 +08:00
committed by GitHub
parent 1dbc4c42ae
commit 522f93b8cf
7 changed files with 400 additions and 91 deletions

View File

@@ -149,6 +149,8 @@ To blink the `disk` LED when a block device is active, you can use the `ledtrig-
#### Start at Boot (for Debian 12)
The configure file of `ugreen-diskiomon` and `ugreen-netdevmon` is `/etc/ugreen-led.conf`. Please see `scripts/ugreen-leds.conf` for an example.
- Edit `/etc/modules-load.d/ugreen-led.conf` and add the following lines:
```
i2c-dev
@@ -163,27 +165,36 @@ ledtrig-netdev
- Copy files in the `scripts` directory:
```bash
# copy the scripts
scripts=(ugreen-diskiomon ugreen-netdevmon ugreen-probe-leds)
for f in ${scripts[@]}; do
chmod +x "scripts/$f"
cp "scripts/$f" /usr/bin
done
# copy the configuration file, you can change it if needed
cp scripts/ugreen-leds.conf /etc/ugreen-leds.conf
# copy the systemd services
cp scripts/*.service /etc/systemd/system/
systemctl daemon-reload
# change enp2s0 to the network device you want to monitor
systemctl start ugreen-ledmon@enp2s0
systemctl start ugreen-netdevmon@enp2s0
systemctl start ugreen-diskiomon
# if you confirm that everything works well,
# run the command below to make the service start at boot
systemctl enable ugreen-ledmon@enp2s0
systemctl enable ugreen-netdevmon@enp2s0
systemctl enable ugreen-diskiomon
```
## Disk Mapping
To make the disk LEDs useful, we should map the disk LEDs to correct disk slots. First of all, we should highlight that using `/dev/sdX` is never a smart idea, as it may change at every boot. In the script `ugreen-diskiomon` we provide two mapping methods: **by HCTL** and **by serial**.
To make the disk LEDs useful, we should map the disk LEDs to correct disk slots. First of all, we should highlight that using `/dev/sdX` is never a smart idea, as it may change at every boot. In the script `ugreen-diskiomon` we provide three mapping methods: **by ATA**, **by HCTL** and **by serial**.
The best mapping method is using serial numbers, but it needs to record them manually and fill the `DISK_SERIAL` array in `/etc/ugreen-leds.conf`. We use ATA mapping by default, and find that UGOS also uses a similar mapping method (see [#15](https://github.com/miskcoo/ugreen_dx4600_leds_controller/pull/15)). See the comments in `scripts/ugreen-leds.conf` for more details.
The HCTL mapping depends on how the SATA controllers are connected to the PCIe bus and the disk slots. To check the HCTL order, you can run the following command, and check the serial of your disks:
@@ -200,7 +211,7 @@ sdg 6:0:0:0 XXKH3SXX
sdh 7:0:0:0 XXJDB1XX
```
As far as we know, the mapping between HCTL and the disk serial are stable at each boot (see [#4](https://github.com/miskcoo/ugreen_dx4600_leds_controller/pull/4) and [#9](https://github.com/miskcoo/ugreen_dx4600_leds_controller/issues/9)). However, it has been reported that the exact order is model-dependent (see [#9](https://github.com/miskcoo/ugreen_dx4600_leds_controller/issues/9)). In DX4600 Pro and DXP8800 Plus, the mapping is `X:0:0:0 -> diskX`, but In the DXP6800 Pro, `0:0:0:0` and `1:0:0:0` are mapped to `disk5` and `disk6`, and `2:0:0:0` to `6:0:0:0` are mapped to `disk1` to `disk4`, so you should change the array `hctl_map` in `ugreen-diskiomon` accordingly.
As far as we know, the mapping between HCTL and the disk serial are stable at each boot (see [#4](https://github.com/miskcoo/ugreen_dx4600_leds_controller/pull/4) and [#9](https://github.com/miskcoo/ugreen_dx4600_leds_controller/issues/9)). However, it has been reported that the exact order is model-dependent (see [#9](https://github.com/miskcoo/ugreen_dx4600_leds_controller/issues/9)). In DX4600 Pro and DXP8800 Plus, the mapping is `X:0:0:0 -> diskX`, but in DXP6800 Pro, `0:0:0:0` and `1:0:0:0` are mapped to `disk5` and `disk6`, and `2:0:0:0` to `6:0:0:0` are mapped to `disk1` to `disk4`. The script will use `dmidecode` to detect the device model, but I suggest to check the mapping outputed by the script manually.
## Communication Protocols

View File

@@ -6,6 +6,8 @@ exit-ugreen-diskiomon() {
rm "/var/run/ugreen-diskiomon.lock"
fi
kill $smart_check_pid 2>/dev/null
kill $zpool_check_pid 2>/dev/null
kill $disk_online_check_pid 2>/dev/null
}
# trap exit and remove lockfile
@@ -23,42 +25,55 @@ if [[ -f /boot/config/plugins/ugreenleds-driver/settings.cfg ]]; then
source /boot/config/plugins/ugreenleds-driver/settings.cfg
fi
# load environment variables
if [[ -f /etc/ugreen-leds.conf ]]; then
source /etc/ugreen-leds.conf
fi
# led-disk mapping (see https://github.com/miskcoo/ugreen_dx4600_leds_controller/pull/4)
MAPPING_METHOD=${MAPPING_METHOD:=hctl} # hctl, serial
MAPPING_METHOD=${MAPPING_METHOD:=ata} # ata, hctl, serial
led_map=(disk1 disk2 disk3 disk4 disk5 disk6 disk7 disk8)
# hctl, $> lsblk -S -x hctl -o hctl,serial,name
# NOTE: It is reported that the order below should be adjusted for each model.
# Please check the disk mapping section in https://github.com/miskcoo/ugreen_dx4600_leds_controller/blob/master/README.md.
hctl_map=("0:0:0:0" "1:0:0:0" "2:0:0:0" "3:0:0:0" "4:0:0:0" "5:0:0:0" "6:0:0:0" "7:0:0:0")
if which dmidecode; then
# serial number, $> lsblk -S -x hctl -o hctl,serial,name
serial_map=(${DISK_SERIAL})
# ata number, $> ls /sys/block | egrep ata\d
ata_map=("ata1" "ata2" "ata3" "ata4" "ata5" "ata6" "ata7" "ata8")
if which dmidecode > /dev/null; then
product_name=$(dmidecode --string system-product-name)
case "${product_name}" in
"DXP6800 Pro")
echo "Found UGREEN DXP6800 Pro"
hctl_map=("2:0:0:0" "3:0:0:0" "4:0:0:0" "5:0:0:0" "0:0:0:0" "1:0:0:0")
;;
"DX4600 Pro")
echo "Found UGREEN DX4600 Pro"
# using the default mapping
;;
"DXP8800 Plus")
echo "Found UGREEN DXP8800 Plus"
# using the default mapping
;;
DXP6800*) # tested on DXP6800 Pro
echo "Found UGREEN DXP6800 series"
hctl_map=("2:0:0:0" "3:0:0:0" "4:0:0:0" "5:0:0:0" "0:0:0:0" "1:0:0:0")
ata_map=("ata3" "ata4" "ata5" "ata6" "ata1" "ata2")
;;
DX4600*) # tested on DX4600 Pro
echo "Found UGREEN DX4600 series"
;;
DXP4800*)
echo "Found UGREEN DXP4800 series"
;;
DXP8800*) # tested on DXP8800 Plus
echo "Found UGREEN DXP8800 series"
# using the default mapping
;;
*)
if [[ "${MAPPING_METHOD}" = "hctl" ]]; then
echo "Using the default HCTL order. Please check it maps to your disk slots correctly."
echo "If you confirm that the HCTL order is correct, or find it is different, you can submit an issue to let us know, so we can update the script."
echo "(Read the disk mapping section in https://github.com/miskcoo/ugreen_dx4600_leds_controller/blob/master/README.md for more details)"
fi
;;
if [[ "${MAPPING_METHOD}" == "hctl" || "${MAPPING_METHOD}" == "ata" ]]; then
echo -e "\033[0;31mUsing the default HCTL order. Please check it maps to your disk slots correctly."
echo -e "If you confirm that the HCTL order is correct, or find it is different, you can "
echo -e "submit an issue to let us know, so we can update the script."
echo -e "Please read the disk mapping section in the link below for more details. "
echo -e " https://github.com/miskcoo/ugreen_dx4600_leds_controller/blob/master/README.md\033[0m"
fi
;;
esac
elif [[ "${MAPPING_METHOD}" = "hctl" ]]; then
echo "installing the tool `dmidecode` is suggested; otherwise the script cannot detect your device and adjust the hctl_map"
elif [[ "${MAPPING_METHOD}" == "hctl" || "${MAPPING_METHOD}" == "ata" ]]; then
echo -e "\033[0;31minstalling the tool `dmidecode` is suggested; otherwise the script cannot detect your device and adjust the hctl/ata_map\033[0m"
fi
# serial number, $> lsblk -S -x hctl -o hctl,serial,name
serial_map=("placeholder0" "placeholder1" "placeholder2" "placeholder3" "placeholder4" "placeholder5" "placeholder6" "placeholder7")
declare -A devices
# set monitor SMART information to true by default if not running unRAID
@@ -72,31 +87,55 @@ CHECK_SMART_INTERVAL=${CHECK_SMART_INTERVAL:=360}
# refresh interval from disk leds
LED_REFRESH_INTERVAL=${LED_REFRESH_INTERVAL:=0.1}
# whether to check zpool health
CHECK_ZPOOL=${CHECK_ZPOOL:=false}
# polling rate for checking zpool health. 5 seconds by default
CHECK_ZPOOL_INTERVAL=${CHECK_ZPOOL_INTERVAL:=5}
# polling rate for checking disk online. 5 seconds by default
CHECK_DISK_ONLINE_INTERVAL=${CHECK_DISK_ONLINE_INTERVAL:=5}
COLOR_DISK_HEALTH=${COLOR_DISK_HEALTH:="255 255 255"}
COLOR_DISK_UNAVAIL=${COLOR_DISK_UNAVAIL:="255 0 0"}
COLOR_ZPOOL_FAIL=${COLOR_ZPOOL_FAIL:="255 0 0"}
COLOR_SMART_FAIL=${COLOR_SMART_FAIL:="255 0 0"}
BRIGHTNESS_DISK_LEDS=${BRIGHTNESS_DISK_LEDS:="255"}
{ lsmod | grep ledtrig_oneshot ; } || modprobe -v ledtrig_oneshot
{ lsmod | grep ledtrig_oneshot > /dev/null; } || { modprobe -v ledtrig_oneshot && sleep 2; }
sleep 2
function disk_enumerating_string() {
if [[ $MAPPING_METHOD == ata ]]; then
ls -ahl /sys/block | sed 's/\/$//' | awk '{
if (match($0, /ata[0-9]+/)) {
ata = substr($0, RSTART, RLENGTH);
if (match($0, /[^\/]+$/)) {
basename = substr($0, RSTART, RLENGTH);
print basename, ata;
}
}
}'
elif [[ $MAPPING_METHOD == hctl || $MAPPING_METHOD == serial ]]; then
lsblk -S -o name,${MAPPING_METHOD},tran | grep sata
else
echo Unsupported mapping method: ${MAPPING_METHOD}
exit 1
fi
}
echo Enumerating disks based on $MAPPING_METHOD...
declare -A dev_map
while read line
do
blk_line=($line)
if [[ $MAPPING_METHOD = hctl ]]; then
key=${blk_line[1]}
val=${blk_line[0]}
elif [[ $MAPPING_METHOD = serial ]]; then
key=${blk_line[1]}
val=${blk_line[0]}
else
echo Unsupported mapping method: ${MAPPING_METHOD}
exit 1
fi
key=${blk_line[1]}
val=${blk_line[0]}
dev_map[${key}]=${val}
echo $MAPPING_METHOD ${key} ">>" ${dev_map[${key}]}
done <<< "$(lsblk -S -o name,${MAPPING_METHOD} | tail -n +2)"
done <<< "$(disk_enumerating_string)"
# initialize LEDs
declare -A dev_to_led_map
for i in "${!led_map[@]}"; do
led=${led_map[i]}
if [[ -d /sys/class/leds/$led ]]; then
@@ -104,35 +143,116 @@ for i in "${!led_map[@]}"; do
echo 1 > /sys/class/leds/$led/invert
echo 100 > /sys/class/leds/$led/delay_on
echo 100 > /sys/class/leds/$led/delay_off
echo "255 255 255" > /sys/class/leds/$led/color
echo "$COLOR_DISK_HEALTH" > /sys/class/leds/$led/color
echo "$BRIGHTNESS_DISK_LEDS" > /sys/class/leds/$led/brightness
# find corresponding device
_tmp_str=${MAPPING_METHOD}_map[@]
_tmp_arr=(${!_tmp_str})
dev=${dev_map[${_tmp_arr[i]}]}
if [[ -f /sys/class/block/${dev}/stat ]]; then
devices[$led]=${dev}
else
# turn off the led if no disk installed on this slot
echo 0 > /sys/class/leds/$led/brightness
echo none > /sys/class/leds/$led/trigger
if [[ -v "dev_map[${_tmp_arr[i]}]" ]]; then
dev=${dev_map[${_tmp_arr[i]}]}
if [[ -f /sys/class/block/${dev}/stat ]]; then
devices[$led]=${dev}
dev_to_led_map[$dev]=$led
else
# turn off the led if no disk installed on this slot
echo 0 > /sys/class/leds/$led/brightness
echo none > /sys/class/leds/$led/trigger
fi
fi
fi
done
# construct zpool device mapping
declare -A zpool_ledmap
if [ "$CHECK_ZPOOL" = true ]; then
echo Enumerating zpool devices...
while read line
do
zpool_dev_line=($line)
zpool_dev_name=${zpool_dev_line[0]}
zpool_scsi_dev_name="unknown"
# zpool_dev_state=${zpool_dev_line[1]}
case "$zpool_dev_name" in
sd*)
# remove the trailing partition number
zpool_scsi_dev_name=$(echo $zpool_dev_name | sed 's/[0-9]*$//')
;;
dm*)
# find the underlying block device of the encrypted device
dm_slaves=($(ls /sys/block/${zpool_dev_name}/slaves))
zpool_scsi_dev_name=${dm_slaves[0]}
;;
*)
echo Unsupported zpool device type ${zpool_dev_name}.
;;
esac
# if the detected scsi device can be found in the mapping array
#echo zpool $zpool_dev_name ">>" $zpool_scsi_dev_name ">>" ${dev_to_led_map[${zpool_scsi_dev_name}]}
if [[ -v "dev_to_led_map[${zpool_scsi_dev_name}]" ]]; then
zpool_ledmap[$zpool_dev_name]=${dev_to_led_map[${zpool_scsi_dev_name}]}
echo "zpool device" $zpool_dev_name ">>" $zpool_scsi_dev_name ">> LED:"${zpool_ledmap[$zpool_dev_name]}
fi
done <<< "$(zpool status -L | egrep ^\\s*\(sd\|dm\))"
function zpool_check_loop() {
while true; do
while read line
do
zpool_dev_line=($line)
zpool_dev_name=${zpool_dev_line[0]}
zpool_dev_state=${zpool_dev_line[1]}
# TODO: do something if the pool is unhealthy?
if [[ -v "zpool_ledmap[${zpool_dev_name}]" ]]; then
led=${zpool_ledmap[$zpool_dev_name]}
if [[ "$(cat /sys/class/leds/$led/color)" != "$COLOR_DISK_HEALTH" ]]; then
continue;
fi
if [[ "${zpool_dev_state}" != "ONLINE" ]]; then
echo "$COLOR_ZPOOL_FAIL" > /sys/class/leds/$led/color
echo Disk failure detected on /dev/$dev at $(date +%Y-%m-%d' '%H:%M:%S)
fi
# ==== To recover from an error, you should restart the script ====
## case "${zpool_dev_state}" in
## ONLINE)
## # echo "$COLOR_DISK_HEALTH" > /sys/class/leds/$led/color
## ;;
## *)
## echo "255 0 0" > /sys/class/leds/$led/color
## ;;
## esac
fi
done <<< "$(zpool status -L | egrep ^\\s*\(sd\|dm\))"
sleep ${CHECK_ZPOOL_INTERVAL}s
done
}
zpool_check_loop &
zpool_check_pid=$!
fi
# check disk health if enabled
if [ "$CHECK_SMART" = true ]; then
(
while true; do
for led in "${!devices[@]}"; do
if [[ "$(cat /sys/class/leds/$led/color)" = "255 0 0" ]]; then
if [[ "$(cat /sys/class/leds/$led/color)" != "$COLOR_DISK_HEALTH" ]]; then
continue;
fi
dev=${devices[$led]}
if [[ -z $(smartctl -H /dev/${dev} | grep PASSED) ]]; then
echo "255 0 0" > /sys/class/leds/$led/color
echo "$COLOR_SMART_FAIL" > /sys/class/leds/$led/color
echo Disk failure detected on /dev/$dev at $(date +%Y-%m-%d' '%H:%M:%S)
continue
fi
@@ -143,40 +263,42 @@ if [ "$CHECK_SMART" = true ]; then
smart_check_pid=$!
fi
# check for zpool-leds.sh and set variable
if [[ -f /usr/bin/zpool-leds.sh ]]; then
ZPOOL_LEDS="bash /usr/bin/zpool-leds.sh"
else
ZPOOL_LEDS=""
fi
# check disk online status
(
while true; do
for led in "${!devices[@]}"; do
dev=${devices[$led]}
if [[ "$(cat /sys/class/leds/$led/color)" != "$COLOR_DISK_HEALTH" ]]; then
continue;
fi
if [[ ! -f /sys/class/block/${dev}/stat ]]; then
echo "$COLOR_DISK_UNAVAIL" > /sys/class/leds/$led/color 2>/dev/null
echo Disk /dev/$dev went offline at $(date +%Y-%m-%d' '%H:%M:%S)
continue
fi
done
sleep ${CHECK_DISK_ONLINE_INTERVAL}s
done
) &
disk_online_check_pid=$!
# monitor disk activities
declare -A diskio_data_rw
while true; do
for led in "${!devices[@]}"; do
dev=${devices[$led]}
diskio_old_rw="${diskio_data_rw[$led]}"
if [[ "$(cat /sys/class/leds/$led/color)" = "255 0 0" ]]; then
continue;
fi
# if $dev does not exist, diskio_new_rw="", which will be safe
diskio_new_rw="$(cat /sys/block/${devices[$led]}/stat 2>/dev/null)"
if [[ ! -f /sys/class/block/${dev}/stat ]]; then
echo "255 0 0" > /sys/class/leds/$led/color 2>/dev/null
echo Disk /dev/$dev went offline at $(date +%Y-%m-%d' '%H:%M:%S)
continue
fi
diskio_new_rw="$(cat /sys/block/${dev}/stat)"
if [ "${diskio_old_rw}" != "${diskio_new_rw}" ]; then
if [ "${diskio_data_rw[$led]}" != "${diskio_new_rw}" ]; then
echo 1 > /sys/class/leds/$led/shot
fi
diskio_data_rw[$led]=$diskio_new_rw
done
${ZPOOL_LEDS}
sleep ${LED_REFRESH_INTERVAL}s
done

View File

@@ -1,12 +0,0 @@
[Unit]
Description=UGREEN LEDs daemon for monitoring diskio / netio (of %i) and blinking corresponding LEDs
[Service]
ExecStartPre=/usr/bin/ugreen-probe-leds
ExecStartPre=/usr/bin/ugreen-netdevmon %i
ExecStart=/usr/bin/ugreen-diskiomon
StandardOutput=journal
[Install]
WantedBy=multi-user.target

99
scripts/ugreen-leds.conf Normal file
View File

@@ -0,0 +1,99 @@
# configuration file for ugreen-diskiomon and ugreen-netdevmon
# it should be put in /etc/ugreen-leds.conf
# =========== parameters of disk activities monitoring ===========
# The method of mapping disks to LEDs: ata, hctl, serial
# ata: default, also used in UGOS
# $> ls -ahl /sys/block | grep ata[0-9] --color
# * you should check whether it will change after reboot
#
# hctl: mapping by HCTL,
# $> lsblk -S -x hctl -o hctl,serial,name
# it will fail in some devices if you have USB disks inserted, but works well otherwise
# * you should check whether it will change after reboot
# ** see https://github.com/miskcoo/ugreen_dx4600_leds_controller/issues/14
#
# serial: suggested, mapping by serial
# this method requires the user to check the disks' serial numbers
# and fill the DISK_SERIAL array below (see the comments therein).
MAPPING_METHOD=ata
# The serial numbers of disks (used only when MAPPING_METHOD=serial)
# You need to record them before inserting to your NAS, and the corresponding disk slots.
# If you have 4 disks, with serial numbers: SN1 SN2 SN3 SN4,
# then the config below leads to the following mapping:
# SN1 -- disk1
# SN2 -- disk2
# SN3 -- disk3
# SN4 -- disk4
DISK_SERIAL="SN1 SN2 SN3 SN4"
# The sleep time between two disk activities checks (default: 0.1 seconds)
LED_REFRESH_INTERVAL=0.1
# brightness of disk LEDs, taking value from 1 to 255 (default: 255)
BRIGHTNESS_DISK_LEDS="255"
# color of a healthy disk (default: 255 255 255)
COLOR_DISK_HEALTH="255 255 255"
# color of an unavailable disk (default: 255 0 0)
COLOR_DISK_UNAVAIL="255 0 0"
# color of a failed zpool device (default: 255 0 0)
COLOR_ZPOOL_FAIL="255 0 0"
# color of a device with unhealthy smart info (default: 255 0 0)
COLOR_SMART_FAIL="255 0 0"
# Check the disk health by smartctl (default: true)
CHECK_SMART=true
# The sleep time between two smart checks (default: 360 seconds)
CHECK_SMART_INTERVAL=360
# Check the zpool health (default: false)
CHECK_ZPOOL=false
# The sleep time between two zpool checks (default: 5 seconds)
CHECK_ZPOOL_INTERVAL=5
# The sleep time between two disk online checks (default: 5 seconds) CHECK_DISK_ONLINE_INTERVAL=5
# =========== parameters of network activities monitoring ===========
# Blink the netdev light when sending data (default: 1)
NETDEV_BLINK_TX=1
# Blink the netdev light when receiving data (default: 1)
NETDEV_BLINK_RX=1
# A cycle of netdev blinking (default: 200 milliseconds)
NETDEV_BLINK_INTERVAL=200
# color of the netdev under the normal state (for CHECK_LINK_SPEED=false)
COLOR_NETDEV_NORMAL="255 255 255"
# The sleep time between two netdev connectivity / link speed monitoring (default: 60 seconds)
CHECK_NETDEV_INTERVAL=60
# Monitor the gateway connectivity (default: false)
CHECK_GATEWAY_CONNECTIVITY=false
# Monitor the link speed (default: false)
CHECK_LINK_SPEED=false
# brightness of the netdev LED, taking value from 1 to 255 (default: 255)
BRIGHTNESS_NETDEV_LED="255"
# color of the netdev under different link speeds (for CHECK_LINK_SPEED=true)
COLOR_NETDEV_LINK_100="255 255 255"
COLOR_NETDEV_LINK_1000="255 255 255"
COLOR_NETDEV_LINK_2500="255 255 255"
COLOR_NETDEV_LINK_10000="255 255 255"
# color of the netdev when unable to ping the gateway
COLOR_NETDEV_GATEWAY_UNREACHABLE="255 0 0"

View File

@@ -1,13 +1,91 @@
#!/usr/bin/bash
{ lsmod | grep ledtrig_netdev ; } || modprobe -v ledtrig_netdev
# function for removing lockfile
exit-ugreen-netdevmon() {
if [[ -f "/var/run/ugreen-netdevmon.lock" ]]; then
rm "/var/run/ugreen-netdevmon.lock"
fi
kill $smart_check_pid 2>/dev/null
kill $zpool_check_pid 2>/dev/null
kill $disk_online_check_pid 2>/dev/null
}
sleep 2
# trap exit and remove lockfile
trap 'exit-ugreen-netdevmon' EXIT
# check if script is already running
if [[ -f "/var/run/ugreen-netdevmon.lock" ]]; then
echo "ugreen-netdevmon already running!"
exit 1
fi
touch /var/run/ugreen-netdevmon.lock
{ lsmod | grep ledtrig_netdev > /dev/null; } || { modprobe -v ledtrig_netdev && sleep 2; }
# load environment variables
if [[ -f /etc/ugreen-leds.conf ]]; then
source /etc/ugreen-leds.conf
fi
COLOR_NETDEV_NORMAL=${COLOR_NETDEV_NORMAL:="255 255 255"}
COLOR_NETDEV_GATEWAY_UNREACHABLE=${COLOR_NETDEV_GATEWAY_UNREACHABLE:="255 0 0"}
BRIGHTNESS_NETDEV_LED=${BRIGHTNESS_NETDEV_LED:="255"}
CHECK_NETDEV_INTERVAL=${CHECK_NETDEV_INTERVAL:=60}
CHECK_GATEWAY_CONNECTIVITY=${CHECK_GATEWAY_CONNECTIVITY:=false}
CHECK_LINK_SPEED=${CHECK_LINK_SPEED:=false}
led="netdev"
netdev_name=$1
echo netdev > /sys/class/leds/$led/trigger
echo $1 > /sys/class/leds/$led/device_name
echo $netdev_name > /sys/class/leds/$led/device_name
echo 1 > /sys/class/leds/$led/link
echo 1 > /sys/class/leds/$led/tx
echo 1 > /sys/class/leds/$led/rx
echo 200 > /sys/class/leds/$led/interval
echo ${NETDEV_BLINK_TX:=1} > /sys/class/leds/$led/tx
echo ${NETDEV_BLINK_RX:=1} > /sys/class/leds/$led/rx
echo ${NETDEV_BLINK_INTERVAL:=200} > /sys/class/leds/$led/interval
echo $COLOR_NETDEV_NORMAL > /sys/class/leds/$led/color
echo $BRIGHTNESS_NETDEV_LED > /sys/class/leds/$led/brightness
function set_netdev_normal_color() {
color=$COLOR_NETDEV_NORMAL
if [[ $CHECK_LINK_SPEED == true ]]; then
case $(cat /sys/class/net/$netdev_name/speed) in
100) color=${COLOR_NETDEV_LINK_100:=$COLOR_NETDEV_NORMAL};;
1000) color=${COLOR_NETDEV_LINK_1000:=$COLOR_NETDEV_NORMAL};;
2500) color=${COLOR_NETDEV_LINK_2500:=$COLOR_NETDEV_NORMAL};;
10000) color=${COLOR_NETDEV_LINK_10000:=$COLOR_NETDEV_NORMAL};;
esac
fi
echo $color > /sys/class/leds/$led/color
}
if [[ $CHECK_GATEWAY_CONNECTIVITY == false && $CHECK_LINK_SPEED == false ]]; then
exit 0
fi
gw_conn=1
while true; do
if [[ $CHECK_GATEWAY_CONNECTIVITY == true ]]; then
gw=$(ip route | awk '/default/ { print $3 }')
if ping -q -c 1 -W 1 $gw >/dev/null; then
gw_conn=1
else
gw_conn=0
fi
fi
if [[ $gw_conn == 1 ]]; then
set_netdev_normal_color
else
echo $COLOR_NETDEV_GATEWAY_UNREACHABLE > /sys/class/leds/$led/color
fi
sleep ${CHECK_NETDEV_INTERVAL}s
done

View File

@@ -0,0 +1,11 @@
[Unit]
Description=UGREEN LEDs daemon for monitoring netio (of %i) and blinking corresponding LEDs
[Service]
ExecStartPre=/usr/bin/ugreen-probe-leds
ExecStart=/usr/bin/ugreen-netdevmon %i
StandardOutput=journal
[Install]
WantedBy=multi-user.target