>> In previous messages:
>
>     system('systemctl', '--quiet', [...] , @start_units) == 0
>       or die("Could not execute systemctl: $!");
>
>     Could not execute systemctl:  at /usr/bin/deb-systemd-invoke line 148.

  See the ":" followed by two spaces?  Unlike systemctl, well-behaved
  programs set "errno" when they puke, and that setting is turned into
  a more-or-less useful error message like "Permission denied".
  "$!" would have held that message.

  I would try removing "'--quiet'," from the system() call -- maybe
  systemctl didn't get something it needed in the argument list.

  I'd also use the full path ('/usr/bin/systemctl' or whatever) because
  otherwise you're trusting $PATH to be set correctly.

>> On Sat 12 Oct 2024 at 14:10:20 (-0400), Thomas Schmitt wrote:

> Well, if perl is not more awkward than i believe anyways, then the
> message is emitted if the run of program systemctl fails.  The reasons
> for such a failure are manifold, from botched installation to lack of
> disk space...

  Exactly right, and we shouldn't have to guess.

> I imagine a pressured perl programmer who has to invent a
> comprehensive error message and thinks "Let them look up the code
> on their own".  So the users get shown the script name and the line
> number.

  I avoid using system() because it's bitten me in the ass before; any
  metacharacters in any argument cause the whole thing to be passed to a
  shell, which can result in all sorts of entertainment.  If I ever have
  to use it in a perl script, I make a safe wrapper.  I've attached a
  small example.

-- 
Karl Vogel                      I don't speak for anyone but myself

Manhunt Underway After Lubed-Up Diddy Slips Out From Between Prison Bars
                                            --Babylon Bee, 20 Sep 2024
Perl script cleverly called "tst":

  1  #!/usr/bin/perl
  2  #<tst: try a wrapper around system().
  3
  4  use Modern::Perl;
  5  use subs qw/safesys/;
  6
  7  my @instance_args = ('i1', 'i2');
  8  my $action        = 'do-something';
  9  my @start_units   = ('st1', 'st2', 'st3');
 10
 11  print "Calling safesys, should work...\n";
 12  safesys('/bin/ls', '-lF', "$0");
 13
 14  print "\n...calling safesys again...\n";
 15  safesys('systemctl', '--quiet', @instance_args, $action, @start_units);
 16
 17  print "...should not get here\n";
 18  exit(0);
 19
 20  # -------------------------------------------------------------------
 21  # safesys: run a command using system, view any unexpected results.
 22  sub safesys {
 23      unless (system(@_) == 0) {
 24          my ($package, $filename, $line) = caller;
 25
 26          printf "  PACKAGE: %s\n     FILE: %s\n     LINE: %d\n",
 27              $package, $filename, $line;
 28
 29          print "system() failed with arguments:\n  ";
 30          print "[$_] " foreach @_;
 31          print "\n";
 32
 33          if ($? == -1) {
 34              print "failed to execute: $!\n";
 35          }
 36          elsif ($? & 127) {
 37              printf "child died with signal %d, %s coredump\n",
 38                ($? & 127), ($? & 128) ? 'with' : 'without';
 39          }
 40          else {
 41              printf "child exited with value %d\n", $? >> 8;
 42          }
 43
 44          exit($?);
 45      }
 46  }

When I run it, the first call succeeds in passing its own name to "ls".

I don't have systemctl installed on my machine, so the second call fails
at line 23.  I use "caller" to see where the problem actually occurred
(line 15) and what args were passed to systemctl:

    me% ./tst
    Calling safesys, should work...
    -rwxr-xr-x  1 vogelke  mis  1242 Oct 12 21:37 ./tst*

    ...calling safesys again...
    Can't exec "systemctl": No such file or directory at ./tst line 23.
      PACKAGE: main
         FILE: ./tst
         LINE: 15
    system() failed with arguments:
      [systemctl] [--quiet] [i1] [i2] [do-something] [st1] [st2] [st3]
    failed to execute: No such file or directory

As you can see, the script never makes it to line 17.

Reply via email to