I have two (and possibly in the future, more) USB serial devices which are identical (down to the serial number, unfortunately) – they’re actually BTC miners. Currently they end up as ttyUSBX where X is 0, 1 or 2, as there’s another unrelated USB serial device as well (which need not be worried about here).
I would like to write a udev rule which will assign them predictable names within /dev, like /dev/miner0 where the zero is an incrementing integer. I don’t care which of them ends up as which, but I do need them to be within a predictable range which won’t change.
Currently I have this:
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="miner%n"
This is pretty close, as I end up with names like I want. The only problem is, since the miners and the third device can sometimes appear in a random order, I might end up with two of miner0, miner1 and miner2, but I never know which two (without manually looking). If I add any more non-miner usb serial devices (which is a possibility), it’ll exacerbate the problem.
I had found reference to %e which looked like it did exactly what I wanted, but it doesn’t seem to exist anymore.
How might I give these devices predictable names? I’d prefer not to tie them to their location on the USB bus as well if possible.
Further information/background
It’s worth mentioning that I’m not that bothered what the names are, just that they be known and unchanging even if/when the device gets plugged into a different USB socket. I would simply forget the whole udev thing and use entries in /dev/serial/by-id, but as they have the same serial number, there’s only one of them in there!
It’s also worth mentioning that the reason for doing this is that the mining software needs to be told a list of devices to probe and find. I can just have it do all (it basically just finds all valid miners in the ttyUSB* range), but that annoys the non-miner device. So I need the names of the miners known ahead of time so I can configure it to use just those. Sadly it won’t accept a wildcard (so just telling it to use /dev/miner* seems to be out of the question), hence this problem.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This is untested in combination:
Add a udev rule to IMPORT{program}="/usr/local/sbin/unique-num /run/miner-counter 0 MINER_NUM" for your miners.
Then you could use a simple shell script, something like this somewhat tested program:
#!/bin/sh
if [ $# -ne 3 ]; then
echo "Usage: $0 data-file initial var-name" >&2
exit 1
fi
datfile="$1"
lockfile="$1.lck"
initial=$2
key="$3"
(
flock -x 9
num=$initial
if [ -e "$datfile" ]; then
read -r num < "$datfile"
fi
next=`expr $num + 1`;
echo $next > "$datfile"
echo "$key=$num"
) 9> "$lockfile"
Then you can use that udev environment variable to name your miners.
Method 2
The question already has an accepted answer, but I decided to share my variation of the solution provided by derobert.
My requirements were slightly different – in addition to providing “incrementing” index numbers to new devices – I wanted reacquire index numbers that were given up by devices that have been removed from the system.
The udev rule for setting up the environment variable would look something like this:
IMPORT{program}="/usr/local/sbin/unique-num /dev miner MINER_NUM"
In my solution, I do not use a file to keep track of the index, I simply loop over the existing symlink and find the first available index:
/usr/local/sbin/unique-num script:
#!/bin/bash
if [ $# -ne 3 ]; then
echo "Usage: $0 location prefix var-name" >&2
exit 1
fi
location="$1"
prefix="$2"
key="$3"
needindex=1
index=0
while [ $needindex -eq 1 ]
do
if [ ! -e $location/$prefix$index ]; then
needindex=0
echo "$key=$index"
else
(( index++ ))
fi
done
This will, of course, print out the var-name with the first available index, for example if these symlink already exist:
miner0 miner1 miner2
and then miner1 is detached from the system – we are left with:
miner0 miner2
Running the script will return:
MINER_NUM=1
…as this is now the first available index.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0