in reply to Timing out ``?

alarm will do what you need -- the link has a good example. Not to be combined with sleep.

Alternatively, you can put an explicit timeout on the ssh call: @list = `ssh machine -o ConnectTimeout=$timeout "ls path"`; However, in this scenario, you won't know if the connection timed out or not.

Side note: I don't think @list = `ssh machine "ls path"`; does what you think it does; maybe you mean @list = split /\n/, `ssh machine "ls path"`;?


#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Replies are listed 'Best First'.
Re^2: Timing out ``?
by mbethke (Hermit) on Jun 06, 2012 at 23:15 UTC
    Side note: I don't think @list = `ssh machine "ls path"`; does what you think it does; maybe you mean @list = split /\n/, `ssh machine "ls path"`;?

    Yes it does:

    In scalar context, it comes back as a single (potentially multi-line) string, or undef if the command failed. In list context, returns a list of lines (however you've defined lines with $/ or $INPUT_RECORD_SEPARATOR), or an empty list if the command failed.
    perlop

    So while the OP's way is safe, you'd even have to check for undef before splitting to avoid warnings on failure---which will even be fairly frequent in his use case.

      Except that all of your list entries will have trailing newlines (see perl -e '@list = `ls`; print $list[0] =~ /\n/ ? "yes\n" : "no\n"') which can cause funny errors depending on how you use the list. I would actually consider a warning on failure to be a good thing in this case, although the emitted warning would be unfortunately ambiguous. But this is all fairly subjective, particularly without seeing how the list gets used.

      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re^2: Timing out ``?
by thomas895 (Deacon) on Jun 06, 2012 at 22:09 UTC

    To give a concrete example of that:

    use warnings; my @list = (); eval { local $SIG{ALRM} = sub { die "SSH timed out" }; alarm 5; #If after 5 seconds nothing happens, then call SIGALRM @list = `ssh machine "ls path"`; alarm 0; #Reset }; if( $@ ) { warn "I could not do that: $@"; } else { do_something_with( @list ); }

    Update: After being corrected, I have changed the code to make it work

    ~Thomas~
    confess( "I offer no guarantees on my code." );
      No. As the docs say,
      If you want to use alarm to time out a system call you need to use an eval/die pair.
      Your code will emit a warning, but will continue to hang until the backticks return.

      Update: Parent's code has been corrected.

      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      This is exactly what I was looking for. I've done similar things in C, just wasn't sure how to handle it in Perl.

      Thanks,

      Sean.