LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   duplicate UID in /etc/passwd - change with shell script (https://www.linuxquestions.org/questions/linux-newbie-8/duplicate-uid-in-etc-passwd-change-with-shell-script-4175439126/)

hugataga 11-28-2012 07:32 AM

duplicate UID in /etc/passwd - change with shell script
 
Hello, I need to read /etc/passwd and check for duplicate UIDs for different users. If found, assign them the next free UID above 1000.

can somebody help me ?

A sample from my /etc/passwd file:
Code:

hugataga:x:1000:1000:hugataga,,,:/home/hugataga:/bin/bash
proftpd:x:107:65534::/var/run/proftpd:/bin/false
ftp:x:108:65534::/srv/ftp:/bin/false
petri:x:1000:1000:petri,,,:/home/petri:/bin/bash

The user hugataga and petri have the same UID 1000. i would like to change the UID for the user petri to the next not used 1001. Is there a way to do that with a bash script ?

I have the script to find the next free UID:
Code:

#! /bin/bash

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=999

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

but i have no idea how to change the uid with a script. It is possible to change it manually with nano, but not for a passwd file with 600 entries.

linosaurusroot 11-28-2012 08:10 AM

Sounds like you want "usermod" to make the change - then if you aren't aiming for top efficiency just have a block of code repeated until there are no more changes to make.

Changing owners of home directories and all that would be a further step.

David the H. 11-28-2012 08:27 AM

Code:

awk -F: -v OFS=: '{ $3=$4=($3+a[$3]++) }1' <( sort -t : -k3n /etc/passwd )

First, the input needs to be sorted, so I used a bash process substitution to dynamically create the sorted "file".

awk's -F and -v options set the input and output field separators to ":".

$3=$4=() changes fields 3 and 4 (I'm assuming that gid needs to be incremented too) to the new value calculated inside the parentheses.

$3+a[$3]++ adds the current value of the array entry "a[$3]" to the value of field three, then post-increments the array value by one ("a[$3]++"). This means that the first time you encounter a given value in field 3, a[$3] will be zero, and one higher for every time encountered after that.

The final "1" at the end is a shortcut trick for printing the current line after the modifications have been made. awk only outputs to stdout, so you'll have to save it to a temp file and replace it after that.

Edit: Note however that this is just a quick and brain-dead solution. As it stands it only increments the uid number by one and doesn't do any testing against subsequent conflicts.


All times are GMT -5. The time now is 07:15 AM.