2

I received this linux script from my professor and I was trying to understand what it does and I think I know what most of it does. However, there is one part that confuses me. What does junk do in this line:

who | while read user junk

What's its purpose? I've tried googling it but I just can't seem to find it anywhere other than referencing junk characters and from what I can tell that's a separate thing. The whole script is:

#!/bin/bash
#Run a while loop using input of user command
who | while read user junk
do
   #Get users real name from /etc/passwd file
   realname=`grep $user /etc/passwd | cut -d: -f5`
   echo "User: $realname ($user)"
   #Get user's logged in time using who command
   loggedin=`who | grep $user | awk '{print $3" "$4}'`
   echo "Logged in: $loggedin"
   #Get home directory of the user from /etc/passwd file
   homedir=`cat /etc/passwd | grep $user | cut -d":" -f6`
   echo "Home Directory is $homedir"
   #Get count of all files in user's home directory
   #including sub-directories (excluding directory count) using find command
   file_dir_count=`find $homedir -type f | wc -l`
   echo "Home directory contains $file_dir_count files"
   #Get user's processes count using ps command
   proc_count=`ps -u $user --no-headers | wc -l`
   echo "$user has $proc_count processes"
   #Display user's top 7 memory using process list in given order using top
   echo "Top 7 processes sorted by Memory Usage:"
   top -b -n 1 -u $user -o %MEM | head -14 | tail -8 | awk '!($3="")'
done
terdon
  • 242,166
Destech
  • 23
  • 3
    junk is a variable name. If you enter foo bar baz, read user junk will assign foo to user and bar baz to junk. He probably called it junk because he ignores its value, and cares only about the first word entereded by the user. As to the rest of the script -- find a better professor ;-) –  Apr 18 '20 at 16:44

1 Answers1

6

The way read is used in your script means that it will read the first word on each line in the output of who into the variable user, and the rest of the line (from the first space or tab) into the variable junk.

By default, read reads words delimited by any character in $IFS (space, tab, newline) into each of the listed variables. The last variable listed will get what is left of the data after assigning words to the previous variables.

This is a cheap way of reading only the first word on each line.

See "Understanding "IFS= read -r line"" for more details.


The script has several issues. It will, for example, give you incorrect results (and quite likely errors) if there are users with usernames that are substrings of each other, like bill and billy. It will also produce the wrong results if a user has files with filenames that contain newlines.

It also executes who again for each user, even though this information could well have been read with the initial read. It also reads /etc/passwd several times per line of output of that initial who command.

I would suggest dividing the processing up into an information gathering section (which uses a single getent passwd "$user" call to get the passwd info, and which does not use top which is primarily an interactive monitoring tool) and a separate reporting section (for output). Using whitespace (like, empty lines) would also improve readability.

Kusalananda
  • 333,661