Results 1 to 9 of 9

Thread: unix shell

  1. #1
    Join Date
    Apr 2004
    Posts
    3

    Talking Unanswered: unix shell

    i require a utility that identifies all users currently logged into the system. It should create a file called logfile which contains a list of usernames together with a count of how many login sessions they are currently running, for example

    coc9io : 1
    hbh8jd : 3
    dg7hy : 1
    root : 4

    it should also print to a standard output message to the form

    Total User: hbh8jd (3 sessions)

    for each user with more than 2 current login sessions.

    if possible can you you use comments so that i understand the code better

    thanks very much

    james bell

  2. #2
    Join Date
    Jan 2004
    Location
    Bordeaux, France
    Posts
    320
    a possible way to do the work : who + awk
    Jean-Pierre.

  3. #3
    Join Date
    Mar 2004
    Posts
    3
    Try ...

    echo ' ' >> logfile
    date >> logfile
    for name in `who | cut -f1 -d' ' | sort -u`
    do
    name_count=`who | grep -c ${name}`
    if [ ${name_count} -gt 2 ]
    then
    echo ${name}':'${name_count} >> logfile
    echo 'Total User:'${name}' ('${name_count}' sessions)'
    fi
    done

    This is done in sh. The only problem that I can see, and don't quite know how to correct would be if you have someone with a name like jon and then a jones, as jon would be counted as jones as well.

    As for the commands who gives you a list of each person's sessions. Since their name is the first column in who, when you cut the response, you only want the first column (-f1), and it is delimited with a space (-d' '). The sort -u makes sure that you only get the one instance for each person. Without it, you would get something like:

    jones:3
    jones:3
    jones:3

    Not what you want, I'm sure. After you have your list of users, you need to count each one. So, re do the who command, and pipe it through grep -c (line count). Compare that against what you want (you said more than 2 entries, so I did the -gt 2), and echo out what you want to see.

    Oh, and the logfile. I didn't know if you wanted it to be a running logfile, or what, so I made it so that it puts a blank line, and then the date, and the the list of users. Handy if you are wanting to track when folk are on the most or whatever. If this isn't what you want, then I would drop the date command, and change the echo above the for loop to

    echo > logfile

    > will cause the file to be re-created, while >> causes the file to be appended to.

    Hope this helps.

    Hobbletoe

    Edit: Forgot the logfile ... changed a few other things.
    Last edited by Hobbletoe; 04-02-04 at 12:30.

  4. #4
    Join Date
    Jan 2004
    Location
    Bordeaux, France
    Posts
    320
    A possible solution with who + awk

    Code:
    who | \
    awk '
    # Memorize each user and increment login count 
    {
       login[$1]++;
    }
    # All logged users have been memorized, display result
    END {
       # Initialize log file name if not set
       if (LOGFILE == "")
          LOGFILE = "who.log";
       # For each memorized user log and display result
       for (user in login) {
          logcnt = login[user];
          print user ": " logcnt > LOGFILE;
          if (logcnt > 2)
             printf("Total User: %s (%d sessions)\n", user, logcnt);
       }
    }
    ' LOGFILE=/path/to/logfile
    Jean-Pierre.

  5. #5
    Join Date
    Apr 2004
    Posts
    3

    Red face A possible solution with who + awk

    just says Permission denied

    not sure why i copied and pasted in

  6. #6
    Join Date
    Jun 2002
    Location
    UK
    Posts
    525
    This is done in sh. The only problem that I can see, and don't quite know how to correct would be if you have someone with a name like jon and then a jones, as jon would be counted as jones as well.
    Use 'grep -wc' ?

    Another method would be to use who + cut + uniq +awk...
    Code:
    who | cut -f1 -d' ' | uniq -c | awk '$1>1{print "Total User: "$2" ("$1" sessions)"}{print $2" : "$1 > "logfile"}'
    The above is untested as I don't have access to a Unix box at the minute, so I hope it works. Personally, I prefer JP's pure awk solution but this might be a little easier to get your head round to start with!

    You can break the pipeline down to see how this works if you want...

    who
    who | cut -f1 -d' '
    who | cut -f1 -d' ' | uniq -c

  7. #7
    Join Date
    Jan 2004
    Location
    Bordeaux, France
    Posts
    320
    Originally posted (private message) by james bell
    hi mate figured it out

    chomd 755

    but when i ran the script this came up

    dave.sh: awk^J # Memorize each user and increment login count^J{^J login[$1]++;^J}^J # All logged users have been memorized, display result^JEND {^J # Initialize log file name if not set^J if (LOGFILE == "")^J LOGFILE = "who.log";^J # For each memorized user log and display result^J for (user in login) {^J logcnt = login[user];^J print user ": " logcnt > LOGFILE;^J if (logcnt > 2)^J printf("Total User: %s (%d sessions)\n", user, logcnt);^J }^J}^J: not found
    hapy:/home/cb3dwa % dave.sh: awk^J # Memorize each user and increment login count^J{^J login[$1]++;^J}^J # All logged users have been memorized, display result^JEND {^J # Initialize log file name if not set^J if (LOGFILE == "")^J LOGFILE = "who.log"^Z^Z
    hapy:/home/cb3dwa % dave.sh
    dave.sh: awk^J # Memorize each user and increment login count^J{^J login[$1]++;^J}^J # All logged users have been memorized, display result^JEND {^J # Initialize log file name if not set^J if (LOGFILE == "")^J LOGFILE = "who.log";^J # For each memorized user log and display result^J for (user in login) {^J logcnt = login[user];^J print user ": " logcnt > LOGFILE;^J if (logcnt > 2)^J printf("Total User: %s (%d sessions)\n", user, logcnt);^J }^J}^J: not found


    any thoughts?
    Shell considers that the command name is formed by awk + awk script, this can happen if the quote is misplaced, for example : who | 'awk
    Verify and mofify your script :
    Code:
    who | awk '
    # Memorize each user and increment login count 
    {
       login[$1]++;
    . . . . .
    Jean-Pierre.

  8. #8
    Join Date
    Apr 2004
    Posts
    3

    Question

    hi m8 this code works fine

    who | cut -f1 -d' ' | uniq -c | awk '$1>1{print "Total User: "$2" ("$1" sessions)"}{print $2" : "$1 > "logfile"}'

    only trouble is i do not understand the $1 and $2

    where do they come from and what do they do ?

    thanks david w

  9. #9
    Join Date
    Jan 2004
    Location
    Bordeaux, France
    Posts
    320
    Within awk program, $n stands for field n of record read from input file.
    The output of the 'uniq -c' command in in the form :
    number_of_records record
    So, in the awk program, $1 is number_of_records and $2 is record (in fact user).

    I think that you need to add a sort command in the pipe :
    Code:
    who | cut -f1 -d' ' | sort | uniq -c | \
    awk '$1>1{print "Total User: "$2" ("$1" sessions)"}{print $2" : "$1 > "logfile"}'
    Jean-Pierre.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •