Finding lowest UID

Soldato
Joined
18 May 2010
Posts
22,893
Location
London
Was looking at a way to find out the lowest available UID.

As with lots of things I found someone else's script on line here.

I've changed the value 999 to 1 so it will find the lowest value from 1 rather than 999.

The script works, but I dont quite understand how the function is working.

As I don't have anyone else to ask I'm asking someone here if they would be so kind to comment on the function so I can understand why it works.

Thanks


----

#!/bin/bash

# return 1 if the Uid is already used, else 0
function usedUid()
{
if [ -z "$1" ]
then
return
fi
for i in ${lines[@]} ; do
if [ $i == $1 ]
then
return 1
fi
done
return 0
}

i=0

# load all the UIDs from /etc/passwd
lines=( $( cat /etc/passwd | cut -d: -f3 | sort -n ) )

testuid=1

x=1

# search for a free uid greater than 999 (default behaviour of adduser)
while [ $x -eq 1 ] ; do
testuid=$(( $testuid + 1))
usedUid $testuid
x=$?
done

# print the just found free uid
echo $testuid
 
I think what's confusing you is the inclusion of the first if-statement in the function:
Code:
if [ -z "$1 ]
    return
fi

It's redundant in my opinion, as you aren't ever going to be in a situation where the function doesn't receive an input unless you explictly remove testuid as an argument to the usedUid call (in which case the person modifying the script has no idea what they're doing).

With that, we're left with the loop:
Code:
function usedUid() {
    for i in ${lines[@]}; do
        if [ $i == $1 ]; then
            return 1;
        fi
    done
    return 0
}

The only confusion left at this point could be that usedUid doesn't appear to take any arguments. However, in Bash variables are global by default, hence why the function can see the array "lines", and we can pass an argument (hence $1). "function <NAME>" is deprecated notation now, the proper way in this example would just be useUid().

The for-loop will cycle through the array. If any variable in the array matches the argument 1 (testuid), leave the function and return 1 (failed - there is a matching value). Otherwise, it'll complete the loop and return 0 (success - there is no match, and you have your lowest UID).

The calling while-loop will then set x to this return value ($?) and will re-evaluate. As above, if x is 1, continue. If x is 0, print testuid as it is the lowest free.

Hope this helps. Not necessarily the way I'd have done it for such a short script, it's a bit fussy.

EDIT: How's the new job going?

Thanks mate!!

I left the job after 6 months. The Devops engineer there taught me enough to get a role where I am now doing 100% Linux and Devops stuff. It's mostly REHL and Puppet. No more tech support for me! :D
 
Back
Top Bottom