Both of the attached scripts are from my second book, "Win32 Perl
Programming: Administrators Handbook"
(http://www.roth.net/books/handbook/). The first one, openfiles.pl, will
display all files that have been opened *remotely*. Unfortunately there
is no easy way to discover all open file handles locally (nor would you
want to since there would literally be hundreds).
The other script (closefile.pl) will force closed a given file that has
been opened remotely.
For both files, pass in "-h" for help.

dave

-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of
Thomas Berk
Sent: Wednesday, February 04, 2004 10:29 AM
To: 'Perl-Win32-Admin-Request (E-mail)'
Subject: Closing open file sessions on a server

Does anybody have an example of how to identify and close open file
locks.
I have an application that's locking a db file on a Windows 2000 server.
Users are inadvertently leaving themselves logged in over night
preventing
the file from being backed up.

I realize that there are risks in clearing these sessions from the
server
side, but I think the risk of missed backups at least warrants some
testing
(on something other than the live application db).

I've thought of using "net file" and parsing the output to produce "net
file" commands to close the sessions.  Does anybody have a better idea?

Thomas

_______________________________________________
Perl-Win32-Admin mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs


#  ----------------------------------------
#  From "Win32 Perl Programming: Administrators Handbook" by Dave Roth
#  Published by Macmillan Technical Publishing.
#  ISBN # 1-57870-215-1

use vars qw( $VERSION $PATH );
use Win32::Lanman;

$VERSION = 20000410;
%PATH = (
    max     =>  45,
    filler  =>  ' ... ',
);

Configure( \%Config, @ARGV );
if( $Config{help} )
{
    Syntax();
    exit();
}

foreach my $FileID ( @{$Config{ids}} )
{
    my( %File );
    if( Win32::Lanman::NetFileGetInfo( $Config{machine}, $FileID, \%File ) )
    {
        undef %Data;
        $Data{path}  = $File{pathname};
        $Data{user}  = $File{username};
        $Data{locks} = $File{num_locks};
        $Data{id}    = $File{id};

        if( $PATH{max} < length( $Data{path} ) )
        {
            my $PathLength = int( ( $PATH{max} - length( $PATH{filler} ) ) / 2 );
            my $FillerLength = length( $PATH{filler} );
            $Data{path} =~ 
s/^(.{$PathLength})(.*?)(.{$PathLength})$/$1$PATH{filler}$3/;
        }

        if( ! Win32::Lanman::NetFileClose( $Config{server}, $FileID ) )
        {
            my( %Temp ) = %Data;
            push( @Failed, \%Temp );
        }
        else
        {
            my( %Temp ) = %Data;
            push( @Succeeded, \%Temp );
        }
    }
    else
    {
        my %Temp = (
            id          =>  $FileID,
            pathname    =>  'File ID is not in use on this server.',
        );
        push( @Failed, \%Temp );
    }
}

if( scalar @Succeeded )
{
    print "\nThe following files were forced closed:\n";
    $~ = OUTPUT_HEADER;
    write;
    $~ = OUTPUT;

    foreach my $File ( @Succeeded )
    {
        %Data = %$File;
        write;
    }
}

if( scalar @Failed )
{
    print "\nThe following attempts to close files failed:\n";
    $~ = OUTPUT_HEADER;
    write;
    $~ = OUTPUT;

    foreach my $File ( @Failed )
    {
        %Data = %$File;
        write;
    }
}


format OUTPUT_HEADER=
@<<<<<< @<<<<< @<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
'ID', 'Locks', 'User', 'Path'
------- ------ ------------------ ---------------------------------------------
.

format OUTPUT=
@>>>>>> @>>>>> @<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$Data{id}, $Data{locks}, $Data{user}, $Data{path}
.

sub Configure
{
    my( $Config, @Args ) = @_;

    if( 0 == scalar @Args )
    {
        $Config->{help} = 1;
    }

    while( my $Arg = shift @Args )
    {
        if( $Arg =~ s#^[-/]## )
        {
            if( $Arg =~ /^m/i )
            {
                # Specified a machine
                $Config->{machine} = shift @Args;
            }
            elsif( $Arg =~ /^(\?|h|help)/i )
            {
                # Request help
                $Config->{help} = 1;
            }
            else
            {
                # An unknown switch
                $Config->{help} = 1;
            }
        }
        else
        {
            push( @{$Config->{ids}}, $Arg );
        }
    }

}

sub Syntax
{
    my( $Script ) = ( $0 =~ /([^\\\/]*?)$/ );
    my( $Line ) = "-" x length( $0 );

    print <<EOT;

$0
$Line
Force an open file on a server to close.
Version $VERSION

Syntax:
    perl $0 [-m Machine] FileID [ FileID2 [ ... ] ]
        -m..........Close files on the specified machine.
        FileID......The file ID of the open file.

EOT

}


#  ----------------------------------------
#  From "Win32 Perl Programming: Administrators Handbook" by Dave Roth
#  Published by Macmillan Technical Publishing.
#  ISBN # 1-57870-215-1

use vars qw( $VERSION %Data $PATH $USERS );
use Win32;
use Win32::Lanman;

$VERSION = 20000411;
%PATH = (
    max     =>  45,
    filler  =>  ' ... ',
);

Configure( \%Config, @ARGV );
if( $Config{help} )
{
    Syntax();
    exit();
}

$USERS = ";" . join( ";", @{$Config{users}} ) . ";";

if( ! scalar @{$Config{servers}} )
{
    push( @{$Config{servers}}, Win32::NodeName() );
}

foreach my $Server ( sort( @{$Config{servers}} ) )
{
    my @FileInfo;
    next if( lc $Server eq $PrevServer );
    $PrevServer = lc $Server;

    print "Open files on \\\\$Server:\n";
    $~ = OUTPUT_HEADER;
    write;
    $~ = OUTPUT;
    $: = "\\-_+";

    foreach my $Path ( @$Config{paths} )
    {
        my( @Info, $User );
        if( Win32::Lanman::NetFileEnum( $Server, $Path, $User, [EMAIL PROTECTED] ) )
        {
            push( @FileInfo, @Info );
        }
    }

    foreach my $File ( @FileInfo )
    {
        undef %Data;
        $Data{path}  = $File->{pathname};
        $Data{user}  = $File->{username};
        $Data{locks} = $File->{num_locks};
        $Data{id}    = $File->{id};

        if( scalar @{$Config{users}} )
        {
            next unless( $USERS =~ /;$Data{user};/i );
        }

        if( ! $Config{full} )
        {
            if( $PATH{max} < length( $Data{path} ) )
            {
                my $PathLength = int( ( $PATH{max} - length( $PATH{filler} ) ) / 2 );
                my $FillerLength = length( $PATH{filler} );
                ( $Data{path} = $File->{pathname} ) =~ 
s/^(.{$PathLength})(.*?)(.{$PathLength})$/$1$PATH{filler}$3/;
            }
        }
        write;
    }
    print "\n";
}

sub Configure
{
    my( $Config, @Args ) = @_;

    while( my $Arg = shift @Args )
    {
        if( $Arg =~ s#^[-/]## )
        {
            if( $Arg =~ /^u/i )
            {
                # Specified a user name
                push( @{$Config->{users}}, shift @Args );
            }
            elsif( $Arg =~ /^f/i )
            {
                $Config->{full} = 1;
            }
            elsif( $Arg =~ /^m/i )
            {
                # Specified a machine
                my @List;
                my $Server = shift @Args;
                $Server =~ s#^[\\/]+##;
                if( "*" eq $Server )
                {
                    my $Domain = Win32::DomainName();
                    if( Win32::Lanman::NetServerEnum( '', $Domain, SV_TYPE_SERVER, 
[EMAIL PROTECTED] ) )
                    {
                       map
                       {
                           push( @{$Config->{servers}}, $_->{name} );
                       } @List;
                    }
                }
                else
                {
                    push( @{$Config->{servers}}, $Server );
                }
            }
            elsif( $Arg =~ /^(\?|h|help)/i )
            {
                # Request help
                $Config->{help} = 1;
            }
            else
            {
                # An unknown switch
                $Config->{help} = 1;
            }
        }
        else
        {
            push( @{$Config->{paths}}, $Arg );
        }
    }
}

sub Syntax
{
    my( $Script ) = ( $0 =~ /([^\\\/]*?)$/ );
    my( $Line ) = "-" x length( $0 );

    print <<EOT;

$0
$Line
Display what files are open on a server.
Version $VERSION

Syntax:
    perl $0 [-f] [-u User] [-m Machine] Path [$Path2 [...]]
        -u..........Display only files opened by this user.
                    Use as many -u switches as needed.
        -f..........Display full path of each open file.
        -m..........Examine this machine.
                    Specify * for all machines sharing files.
                    Default is the local machine.
        Path........The path to examine local to the specified server.
                    This can be either a file or a directory path.
                    Default will be ALL files on the server.

EOT

}

format OUTPUT_HEADER=
@<<<<<< @<<<<< @<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
'ID', 'Locks', 'User', 'Path'
------- ------ ------------------ ---------------------------------------------
.

format OUTPUT =
@>>>>>> @>>>>> @<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$Data{id}, $Data{locks}, $Data{user}, $Data{path}
~                                 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                  $Data{path}
~                                 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                  $Data{path}
~                                 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                  $Data{path}
.

Reply via email to