Linux.com

Feature: System Administration

A script to tell which workstations are using Samba shares

By Sergio Gonzalez Duran on October 03, 2007 (9:00:00 AM)

Share    Print    Comments   

A combination of Linux utilities can help you determine who on your network is using which of your shared filesystems at any given time, allowing you to ask those users to log off while you update the system.

One of my clients has many multiple small Visual Basic 6 and Access-based applications running directly on Linux via Samba through network shares on Windows XP clients. Whenever he needs to update the application or database, he asks the users to log off the application so he can upload the new binary application or Access file to the server. However, his mid-sized network has about 100 clients using the apps, so even if only one user is logged on, my client has to get on the phone and go extension by extension until he finds the user who is using the application, ask the user to log off, and perform the upload.

I created a script to solve this problem using a combination of lsof, netstat, gawk, grep, uniq, and other utilities. All of the applications' binaries are stored in /usr/apps, in subfolders named payroll, accounting, sales, invoice, and so on. Assuming, for example, that the client needs to know the IP addresses of all the users who are using the payroll system, you can use the lsof utility, which lists all the open files:

lsof  |  grep /usr/apps/payroll
smbd      16258  systems  cwd   DIR        8,5     4096    2191586 /usr/apps/payroll
smbd      16258  systems  27rR  REG        8,5  2449408    2191760 /usr/apps/payroll/payroll.exe
smbd      16258  systems  28u   REG        8,5 37883904    1684790 /usr/apps/payroll/dbpayroll.mdb
smbd      16258  systems  29uw  REG        8,5      256    1684290 /usr/apps/payroll/dbpayroll.ldb
smbd      19237  systems  cwd   DIR        8,5     4096    2191586 /usr/apps/payroll
smbd      19237  systems  25rR  REG        8,5  2449408    2191760 /usr/apps/payroll/payroll.exe
smbd      19237  systems  27u   REG        8,5 37883904    1684790 /usr/apps/payroll/dbpayroll.mdb
smbd      19237  systems  28uw  REG        8,5      256    1684290 /usr/apps/payroll/dbpayroll.ldb
smbd      19237  systems  29rW  REG        8,5    45056    1684863 /usr/apps/payroll/report1.rpt

The output shows that smbd (Samba) has several files open, from process IDs (PID) 16258 through 19237. You know that two users are using the payroll.exe application, for example. The last line shows that the report1.rpt file is being used. This is a typical Crystal Reports extension, so you can figure out that this application is also busy. However, this doesn't show the users, so you need to extract only the necessary information (the PID numbers) from the previous output:

lsof  |  grep /usr/apps/payroll | gawk '{ print $2 }'
16258
16258
16258
16258
19237
19237
19237
19237
19237

With gawk, you can extract the second field, but you don't need all those repetitions. Use uniq, which removes duplicate lines from a sorted listing:

lsof  |  grep /usr/apps/payroll | gawk '{ print $2 }' | uniq
16258
19237

Send the results to a temporary file:

lsof | grep /usr/apps/payroll | gawk '{ print $2 }' | uniq > tmp

Next, relate those PID numbers with a network socket using the netstat command. With the –p option, netstat shows the PID and the name of the program to which each socket belongs:

netstat -p | grep 16258
tcp        0      0 192.168.100.250:netbios-ssn   192.168.100.32:1028          ESTABLISHED 16258/smbd

The fourth column (192.168.100.250:netbios-ssn) is the server machine, and the fifth column (168.100.32:1028) is the IP address and port number of the client machine, which is what you need.

Now you can put everything together by using a script that reads the PIDs in the tmp file:

lsof | grep /usr/apps/payroll | gawk '{ print $2 }' | uniq > tmp
echo "PCs USING THE APPLICATION:"
while read row ; do
   netstat -p | grep $row | gawk '{ print $5 }' | cut -d":" -f1
done < tmp

The line netstat -p | grep $row | gawk '{ print $5 }' | cut -d":" -f1 first executes netstat, then calls grep with the variable $row, which comes from each row of the tmp file. Extract the fifth column with gawk, then with cut and the ":" delimiter, extract the first field, which is the IP address.

Give the script a name, and run chmod 700 script.sh to make it executable. When you run it, the result should look something like this:

./script.sh
PCs USING THE APPLICATION
192.168.100.32
192.168.100.78

Now you just have to tie the IP address to a user name. To do that, add to /etc/hosts lines like this:

192.168.100.32     Lindsay_Hayek
192.168.100.78     Salma_Lohan
192.168.100.145    Tom_Norton
192.168.100.193    Edward_Cruise

And add an additional grep the script to read from /etc/hosts, in the netstat line:

grep `netstat -p | grep $row | gawk '{ print $5 }' | cut -d":" -f1` /etc/hosts

Now, however, if the script finds an IP address that is not listed in /etc/hosts, it will send an error rather than simply print the IP address. We can solve that problem with an if statment. If the above instruction is correct (returns 0 through the variable $?) then the script should go on to the next row of the tmp file, while anything besides 0 means that the IP address wasn't found in /etc/hosts, so just print the IP address. You may be able to find out who it belongs to from a network administrator. The final script would look something like this:

lsof | grep /usr/apps/payroll | gawk '{ print $2 }' | uniq > tmp
echo "PCs USING THE APPLICATION:"
while read row ; do
   grep `netstat -p | grep $row | gawk '{ print $5 }' | cut -d":" -f1` /etc/hosts
   
   if [ $? -ne 0 ]; then
     netstat -p | grep $row | gawk '{ print $5 }' | cut -d":" -f1
   end if
   
done < tmp

And when run, the result would look like:

./script.sh
PCs USING THE APPLICATION
192.168.100.32    Lindsay_Hayek
192.168.100.78    Salma_Lohan
192.168.100.90

You could enhance this script. For example, instead of using payroll in the line lsof | grep /usr/apps/payroll | gawk '{ print $2 }' | uniq > tmp and then having to edit it every time you want to look for another application, you could use something like this:

lsof | grep /usr/apps/$1 | gawk '{ print $2 }' | uniq > tmp
echo "PCs USING THE APPLICATION: $1"

Here, $1 is an argument read from the command line:

./script.sh accounting
PCs USING THE APPLICATION accounting
192.168.100.145    Tom_Norton
192.168.100.178
192.168.100.193    Edward_Cruise

You could also create a menu of applications, or use Zenity to interact with the script in an X Window environment.

Sergio Gonzalez Duran is a Linux administrator, systems developer, and network security counselor who also teaches Linux courses and publishes the Spanish-oriented Linux and open source Web site linuxtotal.com.mx.

Share    Print    Comments   

Comments

on A script to tell which workstations are using Samba shares

Note: Comments are owned by the poster. We are not responsible for their content.

Suggestion

Posted by: Anonymous [ip: 81.35.199.235] on October 03, 2007 09:40 AM
You may want to add the -w option while 'grepping' /etc/hosts, so "192.168.100.3" doesn't match "192.168.100.32 Lindsay_Hayek", for example.

#

Re: Suggestion

Posted by: Anonymous [ip: unknown] on October 03, 2007 03:51 PM
It works better with -w option. Thanks

#

A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 196.209.164.35] on October 03, 2007 10:17 AM
SWAT for Samba is also brilliant for tasks like this, Identifying which user is connected to which share, quickly and easily, through a web browser .. without needing to fill up your hosts file, i flike me, your using dhcp to manage ip addresses.

Great script though ;) I can see it packaged into a cron job to automate the process :)

#

Re: A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 76.86.130.164] on October 03, 2007 11:27 AM
Or, you could just use smbstatus to tell you who's logged into what computer and which files and shares they have open.

#

Re(1): A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: unknown] on October 03, 2007 02:19 PM
That's correct, smbstatus tells youw which workstations are using samba shares even if they are not using any program from there. So it may mislead who is using what. So this is the reason because I created this script to know exactly who is using what.

#

Re(2): A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 216.136.60.243] on October 03, 2007 03:26 PM
smbstatus will tell you which files are in use as well (use smbstatus -L to just see locks). I wrote a perl script that matches the pid for the file in use back to the user. I use it all the time to see who is in certain access dbs on my samba server. I even wrote a php script to do it so you can access the info from our intranet.

#

Re(3): A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 64.6.40.50] on October 03, 2007 07:40 PM
I use the SWAT utility that is commonly available with SAMBA. All of that information is neatly presented under the configuration tab.

It also allows you to kill off the samba process which owns the locked files -- even if the windows machine has abandoned the connection. That can happen if the client dies suddenly and leaves its locks behind. Usually, if the samba process is killed, the windows client will re-create the connection, although it is wise to be careful with this, because it could leave a corrupted access database or a confused client that found a mis-matched version of a dll.

#

A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 192.168.3.70] on October 03, 2007 10:42 AM
instead of using lsof, ps and so on, try to use smbstatus, normally it tells you the pc name, username, and all open shares. Examine AWK in a little detail and you can leave grep out. I also noticed the usefulness of awk not long ago.

Greg

#

A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 75.168.87.163] on October 03, 2007 01:46 PM
Scripting is still a bit of a dark art to me (ok, not a bit, but a lot!) so your step-by-step has helped me both understand your script, and understand the tools and steps that went into it. Thank you for taking the time to well explain what is going on here!

#

A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 219.95.191.251] on October 03, 2007 03:17 PM
isn't the smbstatus has done the job ?

#

A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: unknown] on October 03, 2007 04:42 PM
You could pipe the output of the lsof command directly into the while loop running as a subprocess. That would cut out the need for the temporary file.



Eg.



echo "PCs USING THE APPLICATION:"



lsof | grep /usr/apps/payroll | gawk '{ print $2 }' | uniq | {



while read row ; do


grep `netstat -p | grep $row | gawk '{ print $5 }' | cut -d":" -f1` /etc/hosts


if [ $? -ne 0 ]; then


netstat -p | grep $row | gawk '{ print $5 }' | cut -d":" -f1


end if


done }

#

Re: A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 76.86.130.164] on October 03, 2007 07:55 PM
That's pretty cool! I didn't know you could do that.

#

smbstatus

Posted by: Anonymous [ip: 213.162.200.18] on October 04, 2007 03:13 PM
Why don't use smbstatus ???

#

Using host file to find where users are is a bad idea.

Posted by: Anonymous [ip: 211.27.180.104] on October 05, 2007 12:00 AM
smbstatus is more trustable.

/etc/hosts is better replaced with a machine lookup. nslookup followed by a lookup on who is using that machine. Since using a host file is completely useless in a dhcp network. I even have a file that does like this for nfs shares. Also for smb shares I end up just using smbstatus reason machines running thin clients. So there might be more than one user on them. Ie 1 in 200 users is not a good place to be looking.

Very big mistake thinking that only one user would be using the machine.

#

Bug in script

Posted by: Anonymous [ip: 195.145.160.206] on October 05, 2007 07:56 AM
Be careful, uniq expects its input to already sorted alphabetically! So to fix this bug, either put a sort before uniq



... | sort | uniq ...



or get rid of uniq bei using the -u option to sort:



... | sort -u



Have fun!

#

A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 82.146.251.29] on October 05, 2007 04:08 PM
Thanks for very interesting article. Keep up the good work. Regards
<a href="http://www.profesjonalna-reklama.pl" target="_blank">Pozycjonowanie</a>

#

/usr/bin/net

Posted by: Anonymous [ip: 128.223.87.50] on October 05, 2007 09:02 PM
The net command has been part of the samba suite for a while. Compare "net status shares" and "net status sessions".

#

A script to tell which workstations are using Samba shares

Posted by: Anonymous [ip: 91.148.102.51] on October 06, 2007 07:30 PM
Since you know that you want a list of files that smbd has open, using lsof -c smbd is a lot faster than using lsof.

#

do it in one line with awk, no tmp file needed

Posted by: Anonymous [ip: 172.16.176.1] on October 09, 2007 01:08 AM
lsof | grep /usr/apps/payroll | awk '{print $2}' | uniq | awk '{print "netstat -p | grep "$1}' | sh | awk '{print $5'} | awk -F: '{print $1}'


or alternatively:


lsof | awk '$0~/\/usr\/apps\/payroll/{print $0}' | awk '{print $2}' | uniq | awk '{print "netstat -p | grep "$1}' | sh | awk '{print $5'} | awk -F: '{print $1}'
[Modified by: Anonymous on October 10, 2007 04:31 AM]

#

Re: do it in one line with awk, no tmp file needed

Posted by: Anonymous [ip: unknown] on October 10, 2007 12:17 AM
awsome what you can do, I have always like one line scripts, love the feedback on this kind of articles, I learn a lot.

#

Tradución al español, spanish translation

Posted by: Anonymous [ip: 189.166.221.119] on November 06, 2007 06:36 AM

This story has been archived. Comments can no longer be posted.



 
Tableless layout Validate XHTML 1.0 Strict Validate CSS Powered by Xaraya