Shell script to get a list of specific users in Linux?

I put this together, but it sucks: (for example, magic numbers there, parsing text .. boo!)

awk -F: '{if($3 >= 1000 && $3 < 2**16-2) print $1}' /etc/passwd 

What is the right way to do this?

+7
source share
6 answers

Some Unix systems do not use /etc/passwd or do not have users that are not listed there. You should use getent passwd instead of reading /etc/passwd .

My system also has users that are disabled, and may require a longer login using the /bin/false or /usr/sbin/nologin . You probably also want to exclude them.

Here's what works for me, including the arheops awk and ansgar command, to get min and max from login.defs :

 getent passwd | \ grep -vE '(nologin|false)$' | \ awk -F: -v min=`awk '/^UID_MIN/ {print $2}' /etc/login.defs` \ -v max=`awk '/^UID_MAX/ {print $2}' /etc/login.defs` \ '{if(($3 >= min)&&($3 <= max)) print $1}' | \ sort -u 
+12
source

I'm not sure why you only make> 1000, beacuase on a redhat system it starts at 500.

For me, this awk script works fine:

 awk -F: '{if(($3 >= 500)&&($3 <65534)) print $1}' /etc/passwd 

Used only with passwords:

 awk -F: '{if(!(( $2 == "!!")||($2 == "*"))) print $1}' /etc/shadow 
+2
source

Extract the minimum and maximum user IDs from /etc/login.defs , and then select the users with the IDs between these fields from /etc/passwd :

 UID_MIN=$(awk '/^UID_MIN/ {print $2}' /etc/login.defs) UID_MAX=$(awk '/^UID_MAX/ {print $2}' /etc/login.defs) awk -F: -v min=$UID_MIN -v max=$UID_MAX '$3 >= min && $3 <= max{print $1}' /etc/passwd 
+2
source

Here's another approach that spawns only one external program, getent (suggested by @AnsgarWiechers), so both local and network passwd databases will be used. This reduces the number of forks to one for getent only. However, its portability is somewhat limited by the requirement of bash4.

 get_users () { local IFS=$' \t#' while read var val ; do case "$var" in UID_MIN) min="$val" ;; UID_MAX) max="$val" ;; esac done < /etc/login.defs declare -A users local IFS=: while read user pass uid gid gecos home shell; do if (( min <= uid && uid <= max )) && [[ ! $shell =~ '/(nologin|false)$' ]]; then users[$user]=1 fi done < <(getent passwd 2>/dev/null) echo ${!users[@]} } 
+2
source

So, are you just trying to get a list of all users from / etc / passwd? If so, I believe this would be a simpler solution:

 cut -d":" -f1 /etc/passwd 

Edit:

If you only need a list of user users (not system users), you can use one of them:

 grep -E ":[0-9]{4,6}:[0-9]{4,6}:" /etc/passwd | cut -d: -f1 

^ It is assumed that your system uses 1000 and above for UID and GID for user users

 grep /home /etc/passwd | cut -d: -f1 

^ It is assumed that each user has a home directory.

Other solutions depend on more detailed criteria and system settings.

+1
source

This simplifies @StephenOstermiller's answer, which only runs with two processes. I think this is also easier to read (assuming you are familiar with idkom awk NR==FNR ).

 getent passwd | awk 'NR==FNR { if ($1 ~ /^UID_(MIN|MAX)$/) m[$1] = $2; next } { split ($0, a, /:/); if (a[3] >= m["UID_MIN"] && a[3] <= m["UID_MAX"] && a[7] !~ /(false|nologin)$/) print a[1] }' /etc/login.defs - 

Different patterns of separation at the two inputs are a little wart; perhaps you could fix it more elegantly somehow.

+1
source

All Articles