Use this script to find a Raspberry Pi on your network

Identify a specific Raspberry Pi in your cluster with a script that triggers an LED to flash.
149 readers like this.
Raspberries with pi symbol overlay

Dwight Sipler on Flickr

We've all been there. "I'm going to get this Raspberry Pi to try out. They look kinda cool." And then, like tribbles on an Enterprise, suddenly you have Kubernetes clusters and NFS servers and Tor proxies. Maybe even a hotel booking system!

Pis cover the desk. They spill out onto the floor. Carrier boards for Raspberry Pi compute modules installed into lunchboxes litter the shelves.

…or maybe that's just me?

I'll bet if you have one Raspberry Pi, you've got at least two others, though, and gosh darn it, they all look the same.

This was the situation I found myself in recently while testing a network filesystem (NFS) server I set up on one of my Raspberry Pis. I needed to plug in a USB hard drive, but … to which one? Ol' Lingonberry Pi was the chosen host, and I was SSH'd into her, but which actual, physical RPi was she? There was no way of knowing…

Or was there?

Raspberry Pis stacked up in cluster cases

So, so many Raspberry Pis. Which one is Lingonberry? (Chris Collins, CC BY-SA 4.0)

At a previous job, I sometimes worked on servers in our data centers, and some of them had a neat feature: an ID button on the front of the server that, when pressed, started an LED flashing on the front and back of the server. If I needed to deal with the other side of the server, I could press the ID button, then walk allllll the way around to the other side of the rack, and easily find the right server.

I needed something like this to find Lingonberry.

There aren't any buttons on the Pis, but there are LEDs, and after a quick Google search, I learned that one of them is controllable. Cue maniacal laughter.

There are three important bits to know. First, the LED path: on Raspberry Pis, at least those running Ubuntu 20.04, the front (and user-controllable) LED is found at /sys/class/leds/led0. If you navigate to it, you'll find it is a symlink to a directory that has a number of files in it. The two important files are trigger and brightness.

The trigger file controls what lights up the LED. If you cat that file, you will find a list:

none usb-gadget usb-host rc-feedback rfkill-any 
rfkill-none kbd-scrolllock kbd-numlock kbd-capslock 
kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock 
kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock
kbd-ctrlrlock timer oneshot disk-activity disk-read
disk-write ide-disk mtd nand-disk heartbeat backlight
gpio cpu cpu0 cpu1 cpu2 cpu3 default-on input panic
mmc1 [mmc0] bluetooth-power rfkill0 
unimac-mdio--19:01:link unimac-mdio--19:01:1Gbps 
unimac-mdio--19:01:100Mbps unimac-mdio--19:01:10Mbps

The item in brackets indicates what triggers the LED; in the example above, it's [mmc0]—the disk activity for when the SD card plugged into the Raspberry Pi. The trigger file isn't a normal file, though. Rather than editing it directly, you change the trigger by echoing one of the triggers into the file.

To identify Lingonberry, I needed to temporarily disable the [mmc0] trigger, so I could make the LED work how I wanted it to work. In the script, I disabled all the triggers by echoing "none" into the trigger file:

# You must be root to do this
$ echo none >trigger

$ cat trigger
[none] usb-gadget usb-host rc-feedback rfkill-any rfkill-none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer oneshot disk-activity disk-read disk-write ide-disk mtd nand-disk heartbeat backlight gpio cpu cpu0 cpu1 cpu2 cpu3 default-on input panic mmc1 mmc0 bluetooth-power rfkill0 unimac-mdio--19:01:link unimac-mdio--19:01:1Gbps unimac-mdio--19:01:100Mbps unimac-mdio--19:01:10Mbps

In the contents of the trigger file above, you can see [none] is now the selected trigger. Now the LED is off and not flashing.

Next up is the brightness file. You can control whether the LED is on (1) or off (0) by echoing either 0 or 1 into the file. Alternating 1 and 0 will make the LED blink, and doing it with a one-second sleep in the middle produces a regular on/off blink unlike any of the activity that would otherwise trigger the LED. This is perfect for identifying the Raspberry Pi.

Finally, if you do not set the trigger file back to a trigger, it remains off. That's not what you want most of the time—it's better to see the disk activity. This means you have to make sure that any script you write will reset the trigger when it's finished or interrupted. That calls for a signal trap. A trap will capture the SIGINT or SIGTERM (or other) signals and execute some code before quitting. This way, if the script is interrupted—say if you press CTRL+C to stop it—it can still reset the trigger.

With this newfound knowledge, I was able to bang out a script (available under the MIT License) pretty quickly and toss it onto my Raspberry Pis:

#!/bin/bash

set -o errexit
set -o nounset

trap quit INT TERM

COUNT=0

if ! [ $(id -u) = 0 ]; then
   echo "Must be run as root."
   exit 1
fi

LED="/sys/class/leds/led0"

if [[ ! -d $LED ]]
then
  echo "Could not find an LED at ${LED}"
  echo "Perhaps try '/sys/class/leds/ACT'?"
  exit 1
fi

function quit() {
  echo mmc0 >"${LED}/trigger"
}

echo -n "Blinking Raspberry Pi's LED - press CTRL-C to quit"

echo none >"${LED}/trigger"

while true
do
  let "COUNT=COUNT+1"
  if [[ $COUNT -lt 30 ]]
  then
    echo 1 >"${LED}/brightness"
    sleep 1
    echo 0 >"${LED}/brightness"
    sleep 1
  else
    quit
    break
  fi
done

This script checks that the LED control directory exists, disables the [mmc0] trigger, and then starts a loop blinking the LED on and off every second. It also includes a trap to catch INT and TERM signals and resets the trigger. I copied this script onto all my Raspberry Pis, and any time I need to identify one of them, I just run it. It worked perfectly to identify Ol' Lingonberry, so I could set up the disks for the NFS server, and I've used it a number of times since then.

One thing to note—the path to the LED might be different in other distributions. There are also other LEDs in the /sys/class/leds directory, but they are not controllable by the user; they are hooked into different bits of the firmware of the Raspberry Pi.

Do you have any cool Raspberry Pi tricks? Let me know in the comments! I'm always interested in learning what other people do with their infestation of Pis!

What to read next
Chris Collins
Chris Collins is an SRE at Red Hat and an OpenSource.com Correspondent with a passion for automation, container orchestration and the ecosystems around them, and likes to recreate enterprise-grade technology at home for fun.

4 Comments

Nice script! I have 10 (or so) and will be using it.

Hi, love the script but I can't get it to work on Raspberry Pi OS. I get an error at line 17 and 24...not sure what I did wrong but I copied and pasted the script from the webpage directly.

Her are the errors:
./blink.sh: 17: ./blink.sh: [[: not found
./blink.sh: 24: ./blink.sh: Syntax error: "(" unexpected

Since I'm not very good at scripting, it could be something stupid. Don't hesitate to point out. ;-)

Thanks
P.

The "[[" is a Bash construct, and the script is trying to run using the old Bourse shell ("/bin/sh").

Change the first line of the script to
#!/bin/bash

In reply to by Pierre Rochefort (not verified)

Thanks Simon, I was copying and pasting from my own test script when I wrote the article, and must have must have missed that! I'll get the article updated.

In reply to by Simon Reap (not verified)

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.