How to set up a udev rule for ETH "link down"/"link up"? - linux

I like to switch on a green LED(connected through GPIOs), when eth0 is connected. When disconnected I like to switch the green LED of and a red one on.
Thought that udev is maybe the right place for it. I created the simple demo rule:
KERNEL=="eth0", SUBSYSTEM=="net", ACTION=="add", RUN+="/sbin/set_BSPleds eth0 on"
This rule should call a script when the eth0 is added. It was never executed.
After I was looking to the udev monitor by entering "udevadm monitor -k -u" at the shell. There were no events coming when I unplug/plug the lan cable.
root#sama5d3xek:/etc/udev/rules.d# udevadm monitor -k -uh0
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
root#sama5d3xek:/etc/udev/rules.d#
Seems that there are no uevents for eth0. The ethernet driver is provided my ATMEL. I am building a custom Linux by the help of Yocto.
My question is, how to get the "link down"/"link up" events to udev?
If it does not works with udev, what alternative way is the best?

As others have already mentioned, it seems one can't use udev for this.
Ubuntu: wait for network link up and execute a bash command suggests
inotifywait -e modify /sys/class/net/eth0/carrier; echo 'Change detected'
(Currently, / is on nfs for my box, so I can't really say if it will work.)
In other posts, there are some concerns about using the inotify API on /sys: inotify_add_watch fails on /sys/class/net/eth0/operstate .
I think the Right Way(TM) do do this would be to use the netlink(7) API, preferably through a daemon such as netplugd.
Hope that helps :)

Ethernet devices are devices, but connections are not.
You could trace connection through /dev/xconsole, dmesg or /var/log/kern.log.
Sample, using rsyslog:
You could (as root):
echo ':msg, contains, "Link is" |/run/netlink' >/etc/rsyslog.d/netlinkstate.conf
mkfifo /run/netlink
chgrp user /run/netlink
chmod 640 /run/netlink
service rsyslog force-reload
Then, logged as user, simply:
read line < /run/netlink
will wait for input from fifo, then hold until something happen.
state=${line#*Link is } eventtime=${line%% $HOSTNAME*}
echo $eventtime $state
2016-11-21T17:40:50.956181+01:00 Down
or
echo $eventtime $state
2016-11-21T17:40:50.956181+01:00 Up 100 Mbps Full Duplex, Flow Control: Rx/Tx
echo $eventtime ${state%% *}
2016-11-21T17:40:50.956181+01:00 Up
Under bash, you could use timeout for emptying fifo and read only last entry:
while read -t .01 entry </run/netlink;do line="$entry";done
state=${line#*Link is }
eventtime=${line%% $HOSTNAME*}
shortstate=${state%% *}
Nota: I've used /run to store fifo. This could be not the better place as this won't exist on next reboot.

Related

Detect IP-Address change on an interface

I would like to trigger a service when a change of an ip address on a specific interface occurs. Is there a target for this or some other method I am not aware of to achieve this using systemd on Linux (Kernel 3.19)?
The service would be used to send a SIGNAL to a defined process. The Linux is running on an embedded system.
Thanks!
Because you use Systemd you might already use systemd-networkd for managing your devices instead of relying on 3rd party code.
You could use the structured journal output to get the last 2 ADDRESS field of the current BOOD_ID.(sadly, there is no notification mechanism for address changes in systemd-networkd):
→ sudo journalctl -F ADDRESS -u systemd-networkd -n 2
192.168.178.29
So, if there is only one line output, there was no address change.
There is an solution in other question of StackOverflow. Just here:
Detecting a change of IP address in Linux
I like this code, it's easy, you onli need a cron job with frecuency as you need (I made a little change):
#!/bin/bash
OLD_IP=`cat ip.txt`
NEW_IP=`/sbin/ifconfig | awk -F "[: ]+'{ print $4}'`
if [ $NEW_IP != OLD_IP ]; then
YOU_COMMAND <commands>
echo $NEW_IP > ip.txt
fi
exit 0

Detect if an ethernet port is unplugged

I want to trap the event of unplugging an ethernet port on a Linux Ubuntu 14.04.
I want to create a script that detect whenever an ethernet port is unplugged and write it to a log.
Which is the best way to trap such an event
Just put an executable script inside /etc/network/if-post-down.d.
#!/bin/bash
set -e
if [[ "$IFACE" == "wlan0" ]]; then
logger "The wlan0 interface is down!"
# Do whatever you want here.
fi
Make sure to chmod +x it, also.
Read more about these events/scripts here on the Ubuntu Wiki.

Force unmount of usb drive by closing open applications programatically [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 7 years ago.
Improve this question
When I unplug the AC adapter from my laptop I want all USB drives to automatically unmount. If applications are open that block the device, they should be killed. Once everything is killed and unmount a signal tone could be plaid to indicate that it's now safe to unplug it.
The use case is to quickly grab and go your laptop without having to fumble with the ui to get all drives disconnected but avoid unclean unmounts.
Any hints on how to start would be fantastic, thanks you!
ANSWER
For a full copy&paste script see my answer below.
If your USB devices mount to /mount/media do:
kill -9 $(lsof -t $(mount | grep "/mount/media" | cut -d " " -f 1)) # Exit processes blocking umount cleanly
kill $(lsof -t $(mount | grep "/mount/media" | cut -d " " -f 1)) # Force kill remaining open processes
umount $(mount | grep "/mount/media" | cut -d " " -f 1) # Unmount USB drives
Be careful with this since if you don't have blocking applications open lsof will return all pids and you will kill your running OS. See the copy&paste script below for a working implementation that handles this case.
Then call this script whenever the AC adapter is unplugged by adding this line to /etc/udev/rules.d
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="0" , RUN+="/path/to/script/shown/above"
The answer below by Nuetrino shows how to detect the AC unplug event, this answer: How do I find out which process is preventing a umount? shows how to list and kill all processes blocking the device from unmounting (I had more success with lsof than fuser -c which sometimes didn't list any processes even though umount was still being blocked)
Details
Use udevadm monitor to log the event, e.g.
KERNEL[20154.545075] change /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP0 (power_supply)
then use udevadm info -a -p with the event to get the attributes
udevadm info -a -p /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP0
looking at device '/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP0':
KERNEL=="ADP0"
SUBSYSTEM=="power_supply"
DRIVER==""
ATTR{online}=="0"
ATTR{type}=="Mains"
Now you can set up the udev rules with the attributes you like as answered below.
You can define udev rules to do it.
Just put your rule in /etc/udev/rules.d
Here is a example from me which i use to control brightness when i remove the AC adapter.
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="0" , RUN+="/usr/local/bin/bright_unplug"
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="1" , RUN+="/usr/local/bin/bright_replug
I run my custom script 'bright_replug' and 'bright_unplug' when I recieve kernel uvent.
You can use udevadm monitor to
monitor will print the received events for: UDEV - the event which
udev sends out after rule processing KERNEL - the kernel uevent
You can use udevadm info to match more attributes
Step by step solution
1.
Create this script e.g. in /home/user/uall.sh and replace mount_root with the folder where your distribution mounts usb drives, e.g. /media/user
#!/bin/bash
mount_root=/run/media/user
echo "Try unmounting.."
umount $(ls -d -1 $mount_root/*) # Unmount USB drives
mounted=$(ls -d -1 $mount_root/*) # Probe if there are still applications blocking
if ! [ -z "$mounted" ]
then
echo "Found blocked devices: $mounted, killing.."
kill -9 $(lsof -t $mounted) # Exit processes blocking umount cleanly
kill $(lsof -t $mounted) # Force kill remaining open processes
echo "Unmounting.."
umount $(ls -d -1 $mount_root/*) # Unmount USB drives
mounted=$(ls -d -1 $mount_root/*) # Probe if there are still applications blocking
fi
if [ -z "$mounted" ]
then
echo "Success!"
echo "All USB devices umount."
paplay /usr/share/sounds/speech-dispatcher/test.wav
else
echo "Error!"
echo "Tried it all but couldn't umount all USB devices."
echo "These devices are still mounted:"
echo "$mounted"
fi
2.
Create a udev wrapper script (call it /home/user/uall-udev-wrapper) that executes uall.sh as your username:
#!/bin/bash
runuser -l <user> -c '/home/user/uall.sh > /home/user/uall.log'
3.
Create the file /etc/udev/rules.d/99-usb-unmount.rules with the content
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="0" , RUN+="/home/user/uall-udev-wrapper"
4.
Reboot or run sudo udevadm control --reload-rules && udevadm trigger to load the new udev rule
Optional. Add an alias uall=/home/user/uall.sh to your ~/.bashrc to access the script easily from your terminal and use your Desktop environment to configure a hotkey to quickly unmount all usb drives
Caveats
1.
When udev runs the script mount will not display gvfsd-fuse mount points, neither will cat /proc/mounts or cat /etc/mtab not even if using the runuser -l <user> wrapper. Instead I'm using now ls -d -1 $mount_root/* which only returns the devices mounted by the current user specified in $mount_root, on a multi user system devices mounted by a different user will not be unmounted by this script.
2.
When udev runs the script I do not get audio from paplay or spd-say.
Any input on these caveats would be greatly appreciated.

Write a bash script that executes a command when a USB device is plugged in/removed [duplicate]

Is there a Bash script and/or daemon that I can write that will detect a specific USB drive and then sync that drive with a directory?
For future reference, here's how to run a bash script upon detection of a USB drive.
Connect your device and run lsusb to retrieve the device's info. You should see something similar to this:
$ lsusb
Bus 002 Device 039: ID 0bc2:2100 Seagate RSS LLC
In this case, the vendor ID of the device is 0bc2 and the product ID is 2100.
Now you can create your UDEV rule using a text editor of your choice.
$sudo vi /etc/udev/rules.d/85-my_usb_device_rule.rules
And add this:
ACTION=="add", SUBSYSTEM=="usb", SYSFS{idVendor}=="0bc2",
SYSFS{idProduct}=="2100", RUN+="/home/myhome/my_script"
/home/myhome/my_script is the path to your script which it would do whatever you want.
To make sure the detection script will execute right away, run this command to reload the UDEV rules:
$sudo udevadm control --reload-rules
This was tested on Fedora 14.
I didn't do it myself, but you can try udev rules like this:
# Hitachi SimpleDrive mini, model HTS545050B9A300 (500 GB USB HDD)
SUBSYSTEM=="block", ATTR{size}=="976768002", ATTRS{product}=="SimpleDrive mini", ATTRS{serial}=="2512009121920487", ACTION=="add", RUN+="/lib/udev/local.usb.hdd.sh add $devpath"
Place it in /etc/udev/rules.d/90-local.rules or similar place, certainly dependable on your OS.
Here is an example python deamon that you could use for the listening part, then copying the files to your directory shouldn't be a problem.
There are excellent answers here already but depending on your use case, it could be as simple as
[ -d /run/media/$USER/USB_STICK ] && do_stuff
USB_STICK here is the label of the usb stick.

Detecting USB Thumb Drive when Ready in Linux Shell Script

I am a Windows admin and dev, I do not generally work with Linux so forgive me if this is in some way obvious.
I have a not so good Linux box, some older version of Open SUSE, and I have a script that unmounts the USB thumb drive, formats it, and then waits for the device to become ready again before it runs a script that does a copy/MD5 checksum verification on the source and destination file to ensure the copy was valid. The problem is that on one box the USB thumb drive does not become ready after the format in a consistent way. It takes anywhere from 1 to 2+ minutes before I can access the drive via /media/LABELNAME.
The direct path is /dev/sdb but, of course, I cannot access it directly via this path to copy the files. Here is my shell script as it stands:
#!/bin/bash
set -e
echo "Starting LABELNAME.\n\nUnmounting /dev/sdb/"
umount /dev/sdb
echo "Formatting /dev/sdb/"
mkfs.vfat -I -F32 -n "LABELNAME" /dev/sdb
echo "Waiting on remount..."
sleep 30
echo "Format complete. Running make master."
perl /home/labelname_master.20120830.pl
Any suggestions? How might I wait for the drive to become ready and detect it? I have seen Detecting and Writing to a USB Key / Thumb DriveAutomatically but quite frankly I don't even know what that answer means.
It seems that you have some automatic mounting service running which detects the flash disk and mounts the partition. However, you already know what the partition is, so I recommend that you simply mount the disk in your script, choosing a suitable mount point yourself.
mkfs.vfat -I -F32 -n "LABELNAME" /dev/sdb
echo "Format complete, remounting"
mount /dev/sdb $mountpoint #<-- you would choose $mountpoint
echo "Running make master."
perl /home/labelname_master.20120830.pl

Resources