FAQ
I'm writing a scripts that check the TTL of the ping and found the OS.
According the TTL - the script should let me know which OS it is :
Linux/ Windows or Unix (Hash table)

I'm getting an error on the line where I should use the TTL variable -
and take the right value from the hash (%list) :Use of uninitialized
value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
, <HANDLE> line 3.

Any idea ?


#! C:\Perl\bin\perl -w
use strict;
use warnings;

my %list = (60,"linux",61,"linux",62,"linux",63,"linux",64,"linux",
65,"linux",125,"Windows",126,"Windows",127,"Windows",128,"Windows",
250,"Unix",251,"Unix",252,"Unix",253,"Unix",254,"Unix",255,"Unix",
256,"Unix",257,"Unix",258,"Unix",259,"Unix",260,"Unix");
my $path = "hosts.txt" ;
my $machine_IP ;
my $cmd ;

# read machines hosts names List from the txt file c:1.txt and take
the TTL data to th e variable: $line
open (MACHINES,$path) or die "Couldn't open file for writing";
while ($machine_IP = <MACHINES>)
{
chomp($machine_IP) ;
my $line ;
$cmd = "ping $machine_IP";
open(HANDLE,"$cmd|");
while ($line = <HANDLE>)
{
if("$line" =~ "TTL=")
{
$line =~ s/.*TTL=//;
print "TTL = $line\n";
print $list{"$line"} ;
# print "Machine $machine_IP is $list{$line}" ;
last; }
}
}
close HANDLE;
close MACHINES;

Search Discussions

  • Shlomi Fish at Jan 20, 2011 at 5:12 pm
    Hi Eyal,
    On Thursday 20 Jan 2011 15:38:00 Eyal B. wrote:
    I'm writing a scripts that check the TTL of the ping and found the OS.
    According the TTL - the script should let me know which OS it is :
    Linux/ Windows or Unix (Hash table)

    I'm getting an error on the line where I should use the TTL variable -
    and take the right value from the hash (%list) :Use of uninitialized
    value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
    , <HANDLE> line 3.

    Any idea ?
    First of all, you should use a CPAN module for Ping (maybe
    http://search.cpan.org/dist/Net-Ping/ ). Otherwise, here are some comments on
    your code.
    #! C:\Perl\bin\perl -w
    use strict;
    use warnings;
    You shouldn't specify -w in the sha-bang. "use warnings;" (which you also
    have) is better.
    my %list = (60,"linux",61,"linux",62,"linux",63,"linux",64,"linux",
    65,"linux",125,"Windows",126,"Windows",127,"Windows",128,"Windows",
    250,"Unix",251,"Unix",252,"Unix",253,"Unix",254,"Unix",255,"Unix",
    256,"Unix",257,"Unix",258,"Unix",259,"Unix",260,"Unix");
    It's not a list -it's a hash. And you should use the fat comma ("=>"), and use
    some indentation.
    my $path = "hosts.txt" ;
    my $machine_IP ;
    my $cmd ;
    Don't predeclare the variables. Declare them when needed.
    # read machines hosts names List from the txt file c:1.txt and take
    the TTL data to th e variable: $line
    open (MACHINES,$path) or die "Couldn't open file for writing";
    Use three args open and don't use bareword file handles.
    while ($machine_IP = <MACHINES>)
    {
    chomp($machine_IP) ;
    my $line ;
    $cmd = "ping $machine_IP";
    open(HANDLE,"$cmd|");
    You should use three-args open, lexical filehandles and "or die". Furthermore,
    use $cmd is not needed here as you can interpolate directly from $cmd.
    while ($line = <HANDLE>)
    {
    if("$line" =~ "TTL=")
    No need for wrapping $line in double quotes here as $line is a string.
    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{"$line"} ;
    You can do all that in one regex match.

    if (my ($ttl) = $line =~ m{TTL=(\d+)})
    # print "Machine $machine_IP is $list{$line}" ;
    last; }
    }
    }
    close HANDLE;
    close MACHINES;
    For more information see:

    http://perl-begin.org/tutorials/bad-elements/

    Regards,

    Shlomi Fish

    --
    -----------------------------------------------------------------
    Shlomi Fish http://www.shlomifish.org/
    Escape from GNU Autohell - http://www.shlomifish.org/open-
    source/anti/autohell/

    Chuck Norris can make the statement "This statement is false" a true one.

    Please reply to list if it's a mailing list post - http://shlom.in/reply .
  • Eyal B. at Jan 20, 2011 at 9:26 pm
    Tried to implement your recommendations .... step by step .....

    #! C:\Perl\bin\perl
    use strict;
    use warnings;

    my %list = (60=>"linux",61=>"linux",62=>"linux",63=>"linux",
    64=>"linux",65=>"linux",125=>"Windows",126=>"Windows",127=>"Windows",
    128=>"Windows",250=>"Unix",251=>"Unix",252=>"Unix",253=>"Unix",
    254=>"Unix",255=>"Unix", 256=>"Unix",257=>"Unix",258=>"Unix",
    259=>"Unix",260=>"Unix");

    my $path = "hosts.txt" ;
    # open (MACHINES,$path) or die "Couldn't open file for writing";
    open my $input_fh, "<", $path
    or die "Could not open '$path' - $!";

    # Shlomi, you wrote : "Use three args open and don't use bareword file
    handles..."

    # I'm asking : Trying to implement that (Though, didn't understand
    what is "bareword")....where do I indicate the MACHINES handle ?

    my $machine_IP ;
    while ($machine_IP = <MACHINES>)
    {
    chomp($machine_IP) ;
    my $line ;
    my $cmd ;
    $cmd = "ping $machine_IP";
    open(HANDLE,"$cmd|");

    # Shlomi, you wrote : You should use three-args open, lexical
    filehandles and "or die".
    # I'm asking : Can you pls show me how should I write that ?
    # Furthermore, use $cmd is not needed here as you can interpolate
    directly from $cmd.
    # I didn't understand what that means.

    while ($line = <HANDLE>)
    {
    if("$line" =~ "TTL=")

    # No need for wrapping $line in double quotes here as $line is a
    string.
    # as mentioned above


    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{$line} ;
    last; }
    # You can do all that in one regex match.
    # I didn't reach so far ... Is that

    # if (my ($ttl) = $line =~ m{TTL=(\d+)})

    # print "Machine $machine_IP is
    $list{$line}" ;


    }
    }
    close HANDLE;
    close MACHINES;

    # Without make the changes about the File Handle -
    I still got the error : Use of uninitialized value within %list in
    print at C:\system\Perl\OS-recognize\os-rec5.1_.pl line 35, <HANDLE>
    line 4.

    Thanks, Shlomi,

    Eyal.
  • Shlomi Fish at Jan 21, 2011 at 9:39 am
    Hi Eyal,

    I should note that your plain text message is mal-formatted. It's not clear
    which parts were said by me, and which parts were said by you. Next time,
    please configure your mailer (GMail.com?) to format the message as plaintext
    and to use proper "> " quoting as needed by netiquette rules.
    On Friday 21 Jan 2011 10:00:06 אייל ב. wrote:
    Hi Shlomi
    I tried to put this answer on the Google group, but didn't succeed. (Sent
    it but it didn't published)
    It's not a Google group - it's a @perl.org-hosted mailing list. I don't know
    why it wasn't published, but you can try E-mail postmaster@perl.org about it.
    I'm CCing the list in any case.
    I hope this is OK I'm sending it right here.
    I guess. I'm CCing the list.
    BTW, I read your story and very likes that. It's good and very brave to
    share your self with others.
    Which story?
    Looks like you are really dealing with your life.

    Back to Perl :
    Tried to implement your recommendations .... step by step .....

    #! C:\Perl\bin\perl
    use strict;
    use warnings;

    my %list =
    (60=>"linux",61=>"linux",62=>"linux",63=>"linux",64=>"linux",65=>"linux",12
    5=>"Windows",126=>"Windows",127=>"Windows",128=>"Windows",250=>"Unix",251=>
    "Unix",252=>"Unix",253=>"Unix",254=>"Unix",255=>"Unix",
    256=>"Unix",257=>"Unix",258=>"Unix",259=>"Unix",260=>"Unix");
    Like I said you should reformat that. And since you have a lot of duplicacy
    you can use something like:

    my %ttls_to_os =
    (
    Linux => [60..65],
    Windows => [125 .. 128],
    Unix => [250 .. 260],
    );

    And then construct a TTL->OS mapping using
    http://perldoc.perl.org/functions/map.html .
    my $path = "hosts.txt" ;
    # open (MACHINES,$path) or die "Couldn't open file for writing";
    open my $input_fh, "<", $path
    or die "Could not open '$path' - $!";

    # Shlomi, you wrote : "Use three args open and don't use bareword file
    handles..."

    # I'm asking : Trying to implement that (Though, didn't understand what is
    "bareword")....where do I indicate the MACHINES handle ?
    A bareword is something like «MACHINES», i.e: starting with an uppercase
    letter and without a "$" sigil in front. And you can do:

    [code]
    open my $machines_fh, '<', $path
    or die "Could not open '$path' - $!";
    [/code]

    And then use the «$machines_fh» file handle instead of «MACHINES».
    my $machine_IP ;
    while ($machine_IP = <MACHINES>)
    {
    This should be written as:

    [code]
    while (my $machine_ip = <$machines_fh>)
    [/code]
    chomp($machine_IP) ;
    my $line ;
    my $cmd ;
    $cmd = "ping $machine_IP";
    open(HANDLE,"$cmd|");

    # Shlomi, you wrote : You should use three-args open, lexical filehandles
    and "or die".
    # I'm asking : Can you pls show me how should I write that ?
    You can do:

    [code]
    open my $handle, "ping $machine_IP|"
    or die "Could not open the ping process - $!";
    [/code]

    In this case, a three args open using '-|' won't work because it's not
    implemented in Windows yet.
    # Furthermore, use $cmd is not needed here as you can interpolate directly
    from $cmd.
    # I didn't understand what that means.
    See above.
    while ($line = <HANDLE>)
    {
    if("$line" =~ "TTL=")

    # No need for wrapping $line in double quotes here as $line is a string.
    # as mentioned above



    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{$line} ;
    last; }
    # You can do all that in one regex match.
    # I didn't reach so far ... Is that

    # if (my ($ttl) = $line =~ m{TTL=(\d+)})
    Yes, it's that.
    # print "Machine $machine_IP is $list{$line}" ;


    }
    }
    close HANDLE;
    close MACHINES;

    # Without make the changes about the File Handle -
    I still got the error : Use of uninitialized value within %list in print at
    C:\system\Perl\OS-recognize\os-rec5.1_.pl line 35, <HANDLE> line 4.
    Maybe you have a missing TTL from your hash. Try using a debugger:

    http://perl-begin.org/topics/debugging/

    Regards,

    Shlomi Fish

    --
    -----------------------------------------------------------------
    Shlomi Fish http://www.shlomifish.org/
    Apple Inc. is Evil - http://www.shlomifish.org/open-source/anti/apple/

    Chuck Norris can make the statement "This statement is false" a true one.

    Please reply to list if it's a mailing list post - http://shlom.in/reply .
  • Shlomi Fish at Jan 24, 2011 at 9:05 am
    Hi Eyal,
    On Friday 21 Jan 2011 15:55:58 אייל ב. wrote:
    Hi Shlomi, Again.
    I'm sorry for keep sending you mails (It's because my answers to the
    to the group still doesn't work and I sent a complaint to
    postmaster@perl.org)

    I hope now when I use a plain text message, it will be more understandable.
    (BTW, now it will use the ">" ? I really not have much experience in
    netiquette rules)
    See:

    * http://en.wikipedia.org/wiki/Posting_style

    * http://www.caliburn.nl/topposting.html

    [snipped personal stuff]
    Back to Perl, and to my script.
    Because there are many things to understand, I want to focus on my
    major problem why, following the variable I took from the Regular Ex.:
    $list.
    I don't know why this is working : print $list{125} ;
    But this ain't working : print $list{$line} ; while there is 125 on the
    %line. What can be the difference. (I tried chomp) ?
    I tried to debug, I still can't understand why it's doesn't work !
    What does x $line and x \%list say inside the debugger.
    (BTW, I understood the bareword issue, and implement it , according to
    your recommendations. Got a new errors :
    Global symbol "$machine_IP" requires explicit package name at
    C:\system\Perl\OS- recognize\os-rec5.01_.pl line 14.
    Global symbol "$machine_IP" requires explicit package name at
    C:\system\Perl\OS- recognize\os-rec5.01_.pl line 15.
    Global symbol "$handle" requires explicit package name at
    C:\system\Perl\OS-reco gnize\os-rec5.01_.pl line 32.
    That means you have not declared your variables. Read the thread here:

    http://www.nntp.perl.org/group/perl.beginners/2007/07/msg93172.html
    Execution of C:\system\Perl\OS-recognize\os-rec5.01_.pl aborted due .....

    Here is the new code:

    [code]

    #! C:\Perl\bin\perl
    use strict;
    use warnings;

    my %list =
    (60=>"linux",61=>"linux",62=>"linux",63=>"linux",64=>"linux",65=>"linux",
    125=>"Windows",126=>"Windows",127=>"Windows",128=>"Windows",
    250=>"Unix",251=>"Unix",252=>"Unix",253=>"Unix",254=>"Unix",255=>"Unix",
    256=>"Unix",257=>"Unix",258=>"Unix",259=>"Unix",260=>"Unix");

    my $path = "c:/system/Perl/hosts.txt" ;
    # read an IP List from the txt file c:/system/Perl/BSO2.txt and take
    the TTL data to the variable: $line
    open my $machines_fh, '<', $path
    or die "Could not open '$path' - $!";
    while (my $machine_ip = <$machines_fh>) {
    Well, the indentation here is wrong, so it's hard to read. This seems like an
    artefact of an indentation preserving mode while pasting without a special
    reservation for preserving indentation.

    Regards,

    Shlomi Fish

    --
    -----------------------------------------------------------------
    Shlomi Fish http://www.shlomifish.org/
    Optimising Code for Speed - http://shlom.in/optimise

    Chuck Norris can make the statement "This statement is false" a true one.

    Please reply to list if it's a mailing list post - http://shlom.in/reply .
  • Erez Schatz at Jan 21, 2011 at 5:50 am

    On 20 January 2011 15:38, Eyal B. wrote:
    I'm writing a scripts that check the TTL of the ping and found the OS.
    According the TTL - the script should let me know which OS it is :
    Linux/ Windows or Unix (Hash table)

    I'm getting an error on the line where I should use the TTL variable -
    and take the right value from the hash (%list) :Use of uninitialized
    value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
    , <HANDLE> line 3.

    Any idea ?
    if("$line" =~ "TTL=")
    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{"$line"} ;
    # print "Machine $machine_IP is $list{$line}" ;
    last;                                   }
    Assuming a specific line is made of nothing but TTL=, then $line =~
    s/.*TTL=//; will erase the line, leaving you with an empty
    (uninitialized) $line variable.

    A way to debug this will be to include a print $line just before the
    substitution, so you could find what is happening in each stage of the
    iteration.

    --
    Erez

    La perfection soit atteinte non quand il n'ya plus rien à ajouter,
    mais quand il n'ya plus rien à retrancher.
  • Eyal B. at Jan 21, 2011 at 10:49 am

    On Jan 21, 7:50 am, moonb...@gmail.com (Erez Schatz) wrote:
    On 20 January 2011 15:38, Eyal B. wrote:


    I'm writing a scripts that check the TTL of the ping and found the OS.
    According the TTL - the script should let me know which OS it is :
    Linux/ Windows or Unix (Hash table)
    I'm getting an error on the line where I should use the TTL variable -
    and take the right value from the hash (%list) :Use of uninitialized
    value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
    , <HANDLE> line 3.
    Any idea ?
    if("$line" =~ "TTL=")
    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{"$line"} ;
    # print "Machine $machine_IP is $list{$line}" ;
    last;                                   }
    Assuming a specific line is made of nothing but TTL=, then $line =~
    s/.*TTL=//; will erase the line, leaving you with an empty
    (uninitialized) $line variable.

    A way to debug this will be to include a print $line just before the
    substitution, so you could find what is happening in each stage of the
    iteration.

    --
    Erez

    La perfection soit atteinte non quand il n'ya plus rien à ajouter,
    mais quand il n'ya plus rien à retrancher.
    Hi Erez
    print "TTL = $line\n"; Does give me the right value ! (I.e TTL = 125)
    Also print $list{125} ; return the right value
    But this is not working : print $list{$line} ;
    What can happen for the variable ?
  • Rob Dixon at Jan 21, 2011 at 2:29 pm

    On 21/01/2011 05:50, Erez Schatz wrote:
    On 20 January 2011 15:38, Eyal B.wrote:
    I'm getting an error on the line where I should use the TTL variable -
    and take the right value from the hash (%list) :Use of uninitialized
    value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
    ,<HANDLE> line 3.

    Any idea ?
    if("$line" =~ "TTL=")
    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{"$line"} ;
    # print "Machine $machine_IP is $list{$line}" ;
    last; }
    Assuming a specific line is made of nothing but TTL=, then $line =~
    s/.*TTL=//; will erase the line, leaving you with an empty
    (uninitialized) $line variable.
    No it won't, it will leave $line containing a null (zero-length) string.
    There is no way to change a string value to uninitialized (undef) by
    deleting characters from it.

    - Rob
  • Eyal B. at Jan 21, 2011 at 9:43 pm

    On Jan 21, 4:30 pm, rob.di...@gmx.com (Rob Dixon) wrote:
    On 21/01/2011 05:50, Erez Schatz wrote:


    On 20 January 2011 15:38, Eyal B.wrote:
    I'm getting an error on the line where I should use the TTL variable -
    and take the right value from the hash (%list) :Use of uninitialized
    value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
    ,<HANDLE>  line 3.
    Any idea ?
    if("$line" =~ "TTL=")
    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{"$line"} ;
    # print "Machine $machine_IP is $list{$line}" ;
    last;                                   }
    Assuming a specific line is made of nothing but TTL=, then $line =~
    s/.*TTL=//; will erase the line, leaving you with an empty
    (uninitialized) $line variable.
    No it won't, it will leave $line containing a null (zero-length) string.
    There is no way to change a string value to uninitialized (undef) by
    deleting characters from it.

    - Rob
    ok. So why on print "TTL = $line\n"; I do get TTL = 125, if it's
    undefined ?
    Thanks, Rob, for your answer.....
  • Eyal B. at Jan 24, 2011 at 8:29 am
    On Jan 21, 11:42 pm, ewinst...@gmail.com ("Eyal B.") wrote:
    On Jan 21, 4:30 pm, rob.di...@gmx.com (Rob Dixon) wrote:


    On 21/01/2011 05:50, Erez Schatz wrote:

    On 20 January 2011 15:38, Eyal B.wrote:
    I'm getting an error on the line where I should use the TTL variable -
    and take the right value from the hash (%list) :Use of uninitialized
    value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
    ,<HANDLE>  line 3.
    Any idea ?
    if("$line" =~ "TTL=")
    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{"$line"} ;
    # print "Machine $machine_IP is $list{$line}" ;
    last;                                   }
    I found the issue, and resolve it
    This regex clean unnecessary, extra digits: $line =~/.*TTL=\s*(\S+)\s*$/;
    Assuming a specific line is made of nothing but TTL=, then $line =~
    s/.*TTL=//; will erase the line, leaving you with an empty
    (uninitialized) $line variable.
    No it won't, it will leave $line containing a null (zero-length) string.
    There is no way to change a string value to uninitialized (undef) by
    deleting characters from it.
    - Rob
    ok. So why on print "TTL = $line\n"; I do get TTL = 125, if it's
    undefined ?
    Thanks, Rob, for your answer.....
  • Eyal B. at Jan 22, 2011 at 6:32 pm
    If so, how print "TTL = $line\n" does give me the right value ! (I
    get TTL = 125 if ping to Windows machine.

    Thanks, for your answers.
    On Jan 21, 4:30 pm, rob.di...@gmx.com (Rob Dixon) wrote:
    On 21/01/2011 05:50, Erez Schatz wrote:


    On 20 January 2011 15:38, Eyal B.wrote:
    I'm getting an error on the line where I should use the TTL variable -
    and take the right value from the hash (%list) :Use of uninitialized
    value in print at D:\system\perl\os-rec\os-rec5_.pl line 24
    ,<HANDLE>  line 3.
    Any idea ?
    if("$line" =~ "TTL=")
    {
    $line =~ s/.*TTL=//;
    print "TTL = $line\n";
    print $list{"$line"} ;
    # print "Machine $machine_IP is $list{$line}" ;
    last;                                   }
    Assuming a specific line is made of nothing but TTL=, then $line =~
    s/.*TTL=//; will erase the line, leaving you with an empty
    (uninitialized) $line variable.
    No it won't, it will leave $line containing a null (zero-length) string.
    There is no way to change a string value to uninitialized (undef) by
    deleting characters from it.

    - Rob
  • אייל ב. at Jan 22, 2011 at 6:46 pm
    Guys
    You claim : s/.*TTL=//; will erase the line, leaving with an empty
    (uninitialized) $line variable.
    I want to ask :
    If so, how print "TTL = $line\n" does give me the right value !
    If it will leave $line containing a null (zero-length or undef) string
    - how can I print it ?
    (I get TTL = 125 if ping to Windows machine)


    2011/1/21 Abuse Desk <abuse@perl.org>:
    On Jan 21, 2011, at 2:53, אייל ב. wrote:

    Google Groups might not be sending us the mail -- try posting directly to the list by emailing beginners@perl.org.

    - ask
    Hi
    I'm sending a reply using the : http://groups.google.com/group/perl.beginners/browse_thread/thread/45594cc9ea0ae4b5/0e6e248cab1d1e62#0e6e248cab1d1e62

    Reply with my questions to the answers I got.
    But nothing is published.


    Thanks

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedJan 20, '11 at 1:38p
activeJan 24, '11 at 9:05a
posts12
users4
websiteperl.org

People

Translate

site design / logo © 2022 Grokbase