LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 08-28-2012, 02:19 PM   #1
djs515
LQ Newbie
 
Registered: Aug 2012
Posts: 5

Rep: Reputation: 0
Unhappy Help Me - how to use the who command with awk and array.


Hi, I am new to the forum and I hope someone can help me. I had to create a script to kill users off the system with exception of MIS user group. I have most of it but, I can not fiqure out how to use the who command with awk and an array as the user names.

Here is what I have so far:
### create file with all users in the "mis" group
/usr/bin/getent group mis | /usr/bin/awk -F: '{print $4 }' > killtest.txt

### Do for the number of users in the group
for i in `seq 1 $(awk -F, '{ total = total + NF }; END {print total}' killtest.txt)`; do
awk -v I=$i -F, '{print $I }' killtest.txt >>killtest.dat
done

users=($(awk '{print $1}' killtest.dat))
echo ${users[*]}

who -u | awk -v users="$users" '{ if ($1!="root" && $1!=users[*]) print $1 $6 }' > killthem.dat

My problem is the who command how do I get the list of users not to be included in my list. This should print the username and the process id.

exp output:
name19998
name23455
name23354

By the way I am doing this in Bash.

Thank you

Last edited by djs515; 08-28-2012 at 03:09 PM.
 
Old 08-28-2012, 04:57 PM   #2
rigor
Member
 
Registered: Sep 2003
Location: 19th moon ................. ................Planet Covid ................Another Galaxy;............. ................Not Yours
Posts: 705

Rep: Reputation: Disabled
Hi djs515!

I'm not quite sure how you're using the group and passwd "databases" on your system.

If I were going to use a mix of bash and awk, I might do something like the following to get a list of users in a particular group. Given what might be a difference in the way getent works on our systems, what I'm about to illustrate is put together to be run as root, and just access the text files directly. You can interpret it to apply it in the context of however your getent works. Since I don't necessarily have an mis group, I'll just use the users group, so I can have actually run the code and make sure it works on my system.

Code:
group_id=`egrep '^users:' /etc/group | cut -d: -f3-3`

group_users_list=`awk -F: ' /^[^:]+:[^:]+:[^:]+:100:/ { print $1 } ' < /etc/passwd`
To me, the number of times you've used awk in your bash script, makes me wonder if it might be better if more of the code were written in awk directly. So I might finish out the rest of the script mostly in awk. In which case, the result would be this:

Code:
group_id=`egrep '^users:' /etc/group | cut -d: -f3-3`

awk -F: '

    BEGIN {
            # Who command for awk to run.
            who_command="who -u"
          }

    # Use user name as index of associate array, value of array element is not important.
    /^[^:]+:[^:]+:[^:]+:100:/  {  group_users_list[ $1 ]=1  }

    END  {
            # Have awk run "who -u" command in a shell, and pipe output into awk variable.
            while (  who_command  |  getline  who_output_line  )
            {
                split(  who_output_line ,  who_line_fields ,  /[ \t]+/  ) ;
                
                # Make use of "in" operator to check if user name is an index of associate array.
                if (  (  who_line_fields[1]  !=  "root" )  &&  ! ( who_line_fields[1]  in group_users_list )  )
                    print who_line_fields[1]  " "  who_line_fields[7]
            }

        }

' <  /etc/passwd  >  killthem.dat
HTH.

Last edited by rigor; 08-29-2012 at 04:09 PM.
 
Old 08-29-2012, 08:54 AM   #3
djs515
LQ Newbie
 
Registered: Aug 2012
Posts: 5

Original Poster
Rep: Reputation: 0
Question Thanks for the reply but confused

I am confused why you are using the /etc/passwd in the awk command?
Also, the statement:
group_id=`egrep '^users:' /etc/group | cut -d: -f3-3’ #-- Does not work for me I do not have /etc/group on my system

The command I am using works great:
group_id=($(/usr/bin/getent group killemall | /usr/bin/awk -F: '{print $4 }')) #-- This returns all the users in the mis group comma , delimited. name1,name2,name3

I don’t see where you use this array group_id in the awk?

What I am trying to do is create a file with all the users who are currently logged on and not include the users in the MIS group which now = group_id.
My end results will be the username and process id.

I am able to do this without an array for one name but I can’t figure out how to do it for a list of names.
This is the script I have to kill off all users except for root and me and works great:
me=$(logname)
who -u | awk -v me="$me" '{ if ($1!="root" && $1!=me) print "/usr/bin/sudo kill -9 " $6 }' > /bin/kill.dat
chmod 744 /bin/kill.dat
/bin/kill.dat

Hope you can help. Thank you
 
Old 08-29-2012, 03:46 PM   #4
rigor
Member
 
Registered: Sep 2003
Location: 19th moon ................. ................Planet Covid ................Another Galaxy;............. ................Not Yours
Posts: 705

Rep: Reputation: Disabled
I am very sorry. I misinterpreted a variety of things about your question.

I think I understand much better now.

On the Linux system I am using, I was able to take a bash array of users and get it into an awk array of users like this:

Code:
( echo ${users[*]} ; who -u ) | awk  '
    ( NR == 1 ) { for ( field_num=1 ; field_num <= NF ;  field_num++ ) { users[ $field_num ] = 1 ; } }
    ( NR > 1 )  { if ( ($1!="root") &&   ! ( $1  in users )  ) print $1 $7 }
' > killthem.dat
The echo command output is the first line of input to awk, with the output of the who command on the following lines.

The awk "in" operator checks for a match amongst the indexes of the array, not the values of the elements. So the value of the array element isn't meaningful in this case. Each user name is used as an index of an array element; I just set the value of the array element to a arbitrary constant, to create the array element.

On my system the output of "who -u" looks like this:

Code:
user     pts/6        Aug 15 18:39 19:13       20226
so I found that I needed to output field number 7 rather than 6. I also found I needed to make a slight change to the code to avoid duplicate user names:

Code:
### Do for the number of users in the group
# since users will be appended to killtest.dat first make sure the file is empty
> killtest.dat
for i in `seq 1 $(awk -F, '{ total = total + NF }; END {print total}' killtest.txt)`; do
awk -v I=$i -F, '{print $I }' killtest.txt >>killtest.dat
done

Last edited by rigor; 08-29-2012 at 04:06 PM.
 
1 members found this post helpful.
Old 08-29-2012, 04:13 PM   #5
djs515
LQ Newbie
 
Registered: Aug 2012
Posts: 5

Original Poster
Rep: Reputation: 0
Still confused

Now I get a syntax error near unexpected token 'done'
This is what I have now:

### create file with all users in the "mis" group
/usr/bin/getent group killemall | /usr/bin/awk -F: '{print $4 }' > killtest.txt

### Get total number of users
numofusers=$(awk -F, '{ total = total + NF }; END {print total}' killtest.txt)

who -u | awk '{ if ($1!="root" && $1!=(for i in $numofusers; do; awk -v I=$i -F, '{print $I } ; done) print $1 $6 }' > killthem.dat

I must be missing something, I feel like we are so close. hope u can help, I need this before month-end.
Thank you so much for all your replys it is really appreciated
 
Old 08-29-2012, 04:26 PM   #6
djs515
LQ Newbie
 
Registered: Aug 2012
Posts: 5

Original Poster
Rep: Reputation: 0
Tried this too

I also tried this but it didn't exclude the names in the killtest.txt which has the names of the users to exclude form the who list in killthem.dat

chmod 744 killtest.dat
rm killtest.dat

### create file with all users in the "killemall" group
/usr/bin/getent group killemall | /usr/bin/awk -F: '{print $4 }' > killtest.txt

### Do for the number of users in the group
# since users will be appended to killtest.dat first make sure the file is empty
for i in `seq 1 $(awk -F, '{ total = total + NF }; END {print total}' killtest.txt)`; do
awk -v I=$i -F, '{print $I }' killtest.txt >>killtest.dat
done

( echo ${users[*]} ; who -u ) | awk '
( NR == 1 ) { for ( field_num=1 ; field_num <= NF ; field_num++ ) { users[ $field_num ] = 1 ; } }
( NR > 1 ) { if ( ($1!="root") && ! ( $1 in users ) ) print $1 $6 }' > killthem.dat

I hope you can see what I am doing wrong. Thank again!!!

Last edited by djs515; 08-30-2012 at 07:48 AM.
 
Old 08-29-2012, 05:59 PM   #7
rigor
Member
 
Registered: Sep 2003
Location: 19th moon ................. ................Planet Covid ................Another Galaxy;............. ................Not Yours
Posts: 705

Rep: Reputation: Disabled
djs515, in your most recent message, I don't see the code that creates the bash array. Did you remove your code that creates the bash array?

Code:
users=($(awk '{print $1}' killtest.dat))
You still need to create the bash array so that you can input it to the awk program.

Also, I would suggest that you always refer to files in the same way. That is, if you need to include the full path for a file such as /home/dsantore/killtest.txt then you should always use the full path for the file, to make absolutely sure you are using the same file. You probably shouldn't use /home/dsantore/killtest.txt in one place, and just killtest.txt in another place.

Last edited by rigor; 08-29-2012 at 06:04 PM.
 
Old 08-29-2012, 06:03 PM   #8
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,360

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
Try setting the top of the script to
Code:
#!/bin/bash
set -xv
The latter shows you what the parser is doing
 
Old 08-30-2012, 10:10 AM   #9
djs515
LQ Newbie
 
Registered: Aug 2012
Posts: 5

Original Poster
Rep: Reputation: 0
Smile Fantastic – Thank you so much

Got it Thanks you so much, I am so happy I joined this forum. You are all so smart. A SPECIAL THANKS TO KAKAKA!!!

I am going to post what I have that works in case anybody else needs to do this. This code will kill off all users except users in a specified group on the system. I needed to do this for month end. To kill off all user except the users in the MIS group.

# KILLEMALL - Kill off all users on the system except users in MIS group
#
chmod 744 /bin/groupusers.dat
rm /bin/groupusers.dat

### Create a file with all users in the "mis" group -- Change to what ever group you want to exclude
/usr/bin/getent group mis | /usr/bin/awk -F: '{print $4 }' > /bin/groupusers.txt

### Do for the number of users in the group
for i in `seq 1 $(awk -F, '{ total = total + NF }; END {print total}' /bin/groupusers.txt)`; do
awk -v I=$i -F, '{print $I }' /bin/groupusers.txt >>/bin/groupusers.dat
done

### Move users to exclude from kill in to an array which will be used as an index for awk
users=($(awk '{print $1}' /bin/groupusers.dat))

( echo ${users[*]} ; who -u ) | awk '
( NR == 1 ) { for ( field_num=1 ; field_num <= NF ; field_num++ ) { users[ $field_num ] = 1 ; } }
( NR > 1 ) { if ( ($1!="root") && ! ( $1 in users ) ) print "/usr/bin/sudo kill -9 " $6 }' > /bin/kill.dat

chmod 744 /bin/kill.dat
/bin/kill.dat
exit

If you want to see the user name just add $1 in the print of the awk. Just remember to take it out other wise it will error out.

Thanks again!!!!

Last edited by djs515; 08-30-2012 at 03:31 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
awk array grob115 Programming 3 10-25-2011 09:19 PM
how to use array in awk rpd2207 Linux - Newbie 3 10-17-2011 07:30 PM
[SOLVED] printing array in awk ghantauke Linux - Newbie 3 11-24-2010 09:16 AM
bash: use file as input into array, parse out other variables from array using awk beeblequix Linux - General 2 11-20-2009 10:07 AM
shell command using awk fields inside awk one71 Programming 6 06-26-2008 04:11 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 02:12 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration