in reply to Re^2: using online translation engines with perl
in thread using online translation engines with perl

Thx for your response, alexander, I rewrote the function to reflect $sftp->error as a first best way to get useful error info from Net::SFTP::Foreign. As I started to test the new create directory, I did discover that having a plain file as the directory one wants to create causes an error, but I have played enough with this race condition that I don't want to play anymore. I'm reminded of John van Neumann's adage: "Don't play bad logic games."

I also made a first attempt at handling the error. One is left to ponder how an sftp method call to mkdir might fail and what a person with perl can do about it. It's common for the wireless to give out, as the laptop roams with me at tortoise speed. It's a hard thing to try to induce at a critical moment against the swiftness of machine instructions.

I'm going to revert to an architecture where I deal with the consequences of the mkdir as the critical path. I tried to write a code to remove the file, and wanted to try to do some other things if I lose my sftp connection. It's a big mess. I also tried to limit processes to reasonable amounts of time, but I haven't figured out how to handle $SIG{ALRM} yet, as none of these processes terminates. I'm gonna put abridged output and then source between readmore tags and pull out a couple issues.

First I fire up ssh to see what the next directory will be for this project. The highest existing directory is 1.hound5, so I know that my script is going to want to create a directory 1.hound6 . Instead, I create a plain text file:

(uiserver):u61210220:~/pmimage$ ls >1.hound6 (uiserver):u61210220:~/pmimage$ stat 1.hound6 File: ‘1.hound6’ Size: 1151 Blocks: 8 IO Block: 4096 regular file Device: 9405h/37893d Inode: 1021987444 Links: 1 Access: (0604/-rw----r--) Uid: (6042724/u61210220) Gid: ( 600/ftpu +sers) Access: 2018-11-22 00:23:27.844353135 -0500 Modify: 2018-11-22 00:23:27.844353135 -0500 Change: 2018-11-22 00:23:27.844353135 -0500 Birth: -

This is the output from the part of the script that uses sftp transfer:

Put file to server(y/n)?: y server dir is perlmonks return1 is Directory perlmonks already exists! path3 is /home/bob/2.scripts/pages/1.hound/template_stuff/1.hound1.css image dir is pmimage return2 is Directory pmimage already exists! Remove file(y/n)?: y you got 35 seconds for process 16757 return3 is 1 1.hound1.pl,16750 -w ./1.hound1.pl |-1.hound1.pl,16757 -w ./1.hound1.pl |-pstree,16758 -Apal 16750 `-ssh,16751 -p 22 -o NumberOfPasswordPrompts=1 -o PreferredAuthentic +ations=keyboard-interactive,password -l u61210220 home349337426.1and1 +-data.host -s sftp process 16757 executed here 16757 terminated ^C $

Here are the subroutines responsible for this part of the script (remember, I said these were a wreck):

sub createDir { use 5.011; use Net::SFTP::Foreign; my ( $dirName, $sftp ) = @_; if ( $sftp->test_e($dirName) ) { if ( !$sftp->test_d($dirName) ) { print "Remove file(y/n)?: "; my $prompt1 = <STDIN>; chomp $prompt1; if ( $prompt1 eq ( "y" | "Y" ) ) { my $start = time; if ( fork() == 0 ) { # arm the alarm clock alarm(35); say "you got 35 seconds for process $$"; # create a child process my $return3 = $sftp->remove($dirName); say "return3 is remove file return: $return3"; createDir( $dirName, $sftp ); say "process $$ executed here"; exit(0); } system("pstree -Apal $$"); while ( ( my $pid = wait() ) != -1 ) { say "$pid terminated"; } say time - $start, " seconds elapsed instead of a year"; } #end if that tests !$sftp->test_d($dirName) next brace } if ( $sftp->test_d($dirName) ) { return "Directory $dirName already exists!"; } else { say "Can't create $dirName because there's a file in the way!"; handleDirCreateError( @_, $sftp->error() ); } } my $success = $sftp->mkdir($dirName) or handleDirCreateError( @_, $sftp->error() ); return $success; } sub handleDirCreateError { use 5.011; use Net::SFTP::Foreign; my ( $dirName, $sftp, $error ) = @_; say "parameter array is @_"; if ( fork() == 0 ) { # arm the alarm clock alarm(10); say "alarm set for ten in process $$ and pinging google"; # create a child process my $trial = system("ping www.google.com"); say "trial is $trial"; exit(0); } print "Bounce wireless(y/n)?: "; my $prompt1 = <STDIN>; chomp $prompt1; if ( $prompt1 eq ( "y" | "Y" ) ) { if ( fork() == 0 ) { # arm the alarm clock alarm(35); say "alarm set for 35 in process $$ and restarting network"; # create a child process my $trial2 = system("sudo service network-manager restart"); say "trial2 is $trial2"; sleep 30; say "sleeping 30"; exit(0); } } print "Do you think you're ready now(y/n)?: "; my $prompt2 = <STDIN>; chomp $prompt2; if ( $prompt2 eq ( "y" | "Y" ) ) { my $return2 = createDir( $dirName, $sftp ); say "return2 is $return2"; } else { say "$error was too much this time: ceasing execution"; die; } return "execution shouldn't get here"; }

At the end, I do get my directory, but program execution has not continued so as to populate it.

(uiserver):u61210220:~/pmimage/1.hound6$ pwd /kunden/homepages/9/d349337426/htdocs/pmimage/1.hound6 (uiserver):u61210220:~/pmimage/1.hound6$

Let me just ask: do people ping anymore, or is that an old-fashioned way to see if one has internet connectivity? For example, I pinged perlmonks and got no answer, and had my terminal tied up. Might a person use curl instead?

What would I have to add for any of those alarms to terminate the process in which they are set?

Thanks all for comments

Replies are listed 'Best First'.
Re^4: using online translation engines with perl (ping)
by hippo (Archbishop) on Nov 22, 2018 at 09:21 UTC
    Let me just ask: do people ping anymore, or is that an old-fashioned way to see if one has internet connectivity?

    I still use ping for this as it gives more useful diagnostics than many other methods and it doesn't fail due to certificate failures, etc.

    For example, I pinged perlmonks and got no answer, and had my terminal tied up.

    You need to know how to use the tool of your choice. If you just run something like you have as

    my $trial = system("ping www.google.com");

    how do you expect it ever to finish? Using some of the options restricts the action to a finite process:

    $ ping -nc1 perlmonks.org PING perlmonks.org (209.197.123.153) 56(84) bytes of data. 64 bytes from 209.197.123.153: icmp_seq=1 ttl=57 time=90.1 ms --- perlmonks.org ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 90.195/90.195/90.195/0.000 ms $

    Response received, data displayed, no tying up the terminal forever. Alternatively, see Net::Ping.

      I was unable to replicate your results.

      $ ping -ncl perlmonks.org ping: bad number of packets to transmit. $ ping -ncl www.perlmonks.org ping: bad number of packets to transmit. $

      I found the c option to be relevant to what I'm shooting for now. I don't mean to be dismissive about the others, but I hardly understood them. In man ping, these are desribed as follows:

      -n Numeric output only. No attempt will be made to lookup +symbolic names for host addresses. -c count Stop after sending count ECHO_REQUEST packets. With +deadline option, ping waits for count ECHO_REPLY packets, until t +he time&#8208; out expires. -l preload If preload is specified, ping sends that many packets n +ot wait&#8208; ing for reply. Only the super-user may select preload m +ore than 3.

      I went with different options to see how it would dovetail with forked processes. I'll have more about ping at the end of this post, but I wanted to post the functions that would house it first, with the logic driven by an initial sftp->mkdir method call. First, I ssh to my site and put a plain file where I know the script is going to want to ask for a new directory:

      (uiserver):u61210220:~/pmimage$ pwd >1.pitty2 (uiserver):u61210220:~/pmimage$ cat 1.pitty2 /kunden/homepages/9/d349337426/htdocs/pmimage (uiserver):u61210220:~/pmimage$

      Then I run my normal html template with the new functions. Output then source:

      Put file to server(y/n)?: y server dir is perlmonks parameter array is perlmonks Net::SFTP::Foreign=HASH(0x55825b47bcc8) C +ouldn't create remote directory: Failure error is Couldn't create remote directory: Failure
      sub createDir { use 5.011; use Net::SFTP::Foreign; my ( $dirName, $sftp ) = @_; my $success = $sftp->mkdir($dirName) or handleDirCreateError( @_, $sftp->error ); return $success; } sub handleDirCreateError { use 5.011; use Net::SFTP::Foreign; use Net::SFTP::Foreign::Constants qw(:error); my ( $dirName, $sftp, $error ) = @_; say "parameter array is @_"; say "error is $error"; return $error; }

      The error's description is less than complete.

      I'm trying to get the functionality described in https://metacpan.org/pod/Net::SFTP::Foreign::Constants but seem to be missing something, as my error message looks a lot different than the ones in that module. One hopes to catch salva's eye, but it's improbable this deep in my own shit.

      Q1) How do I employ the constants in that module for this case?

      I've folded together elementary forking and pinging, and I really don't get what I've unearthed. This is the source:

      $ cat 6.fork.pl #!/usr/bin/perl -w use 5.011; my $start = time; if (fork() == 0) { # arm the alarm clock alarm(10); # create a child process that sleeps system("ping www.google.com >5.fork.txt"); exit(0); } say "relevant processes with pstree command:"; system("pstree -Apal $$"); while((my $pid = wait()) != -1) { say "$pid terminated" } system("cat 5.fork.txt"); say time-$start, " ? <-ten seconds elapsed from forked process" __END__ $

      This was the first trial:

      This was as I expected it. The icmp_seq= went from 1 to 10. I expected the same output if run again and was wrong:

      The icmp_seq= values go up to 152, and there is twice as much output. The third trial had these values all over the map:

      Q2) What does icmp_seq=608 mean in this context?

      Q3) With 30 seconds of pinging google, how much data was sent? How much of this type of activity can a person do without it being interpreted as an attack?

      What really threw me for a loop is when I walked away from my laptop, came back later to it and find:

      $ ping: sendmsg: Network is unreachable ping: sendmsg: Network is unreachable ping: sendmsg: Network is unreachable ...

      They descended like ghosts, long after the programs were supposedly done executing, and twice.

      After a couple of days of making mistakes, this seems like a good ping command to test whether one has internet connectivity:

      $ ping -c 3 www.google.com PING www.google.com(sea15s12-in-x04.1e100.net (2607:f8b0:400a:809::200 +4)) 56 data bytes 64 bytes from sea15s12-in-x04.1e100.net (2607:f8b0:400a:809::2004): ic +mp_seq=1 ttl=54 time=17.0 ms 64 bytes from sea15s12-in-x04.1e100.net (2607:f8b0:400a:809::2004): ic +mp_seq=2 ttl=54 time=21.1 ms 64 bytes from sea15s12-in-x04.1e100.net (2607:f8b0:400a:809::2004): ic +mp_seq=3 ttl=54 time=19.0 ms --- www.google.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 17.096/19.092/21.126/1.649 ms

      Q4) What could you regex for to decide that this were a success?

      Finally, I didn't want to post before taking a whirl with hippo's suggestion of Net::Ping. Here's the source:

      #!/usr/bin/perl -w use 5.011; use Net::Ping; my $start = time; if ( fork() == 0 ) { # arm the alarm clock alarm(5); my @sites = qw/www.google.com www.merrillpjensen.com www.perlmonks.o +rg/; for my $host (@sites) { my $p = Net::Ping->new(); print "$host is alive.\n" if $p->ping($host); $p->close(); } exit(0); } say "relevant processes with pstree command:"; system("pstree -Apal $$"); while ( ( my $pid = wait() ) != -1 ) { say "$pid terminated"; } #system("cat 7.fork.txt"); say time - $start, " ? seconds elapsed from forked process" __END__

      The unimpressive output is:

      relevant processes with pstree command: 7.fork.pl,27579 -w ./7.fork.pl |-7.fork.pl,27580 -w ./7.fork.pl `-pstree,27581 -Apal 27579 27580 terminated 5 ? seconds elapsed from forked process

      The intent is to loop over a few sites and see if pinging is successful. I wonder what makes a site pingable like google, and how we might handle a ping sent to our own sites.

      Anyways, long post, arrrggh...

      Thank you for your comments,

        It's not clear to me why you are using fork here but that certainly seems to be the root of your troubles. The doc for alarm says:

        If you want to use "alarm" to time out a system call you need to use an "eval"/"die" pair.

        ... but you haven't done that in 6.fork.pl and therefore the ping processes are not reaped which is presumably why you see high icmp_seq counts on subsequent runs. Why use alarm at all instead of ping's built-in timeout?

        Here are 2 examples with neither fork nor alarm. First, using system to execute the ping command:

        #!/usr/bin/env perl use strict; use warnings; for my $dest ('www.google.com', 'www.perlmonks.org', 'microsoft.com', +'foo.bar') { system ("ping -nqc1 -w 3 -W 3 $dest > /tmp/ping.log") and print "### $dest is unreachable\n"; }

        and now the same with Net::Ping:

        #!/usr/bin/env perl use strict; use warnings; use Net::Ping; my $pinger = Net::Ping->new ('icmp', 3); for my $dest ('www.google.com', 'www.perlmonks.org', 'microsoft.com', +'foo.bar') { $pinger->ping ($dest) or print "### $dest is unreachable\n"; } $pinger->close;

        Note that in both cases, microsoft.com is unreachable because it doesn't respond to pings and foo.bar is unreachable because it doesn't exist. The magic number 3 is the timeout to enforce in each case. As per the documentation the second script must be run as root to use ICMP pings.

        I'll reply in detail later but wanted to clear up this one point now in case it helps.

        I was unable to replicate your results.
        $ ping -ncl perlmonks.org

        That's because you've transcribed it instead of copy-and-paste. I haven't used the -l option, I've passed a 1 (the digit one) to the -c option. Of course "l" is a bad number of packets to transmit because it isn't a number. HTH.