0

I have a small Perl script that is used to take user command line input, and then splitting the input into an array where each service should be its own element.

My goal is to enable single arguments, as well as several arguments using a split character where every argument is separated by a comma sign. Examples of these would be:

  • ssh
  • ssh,named,cups

My code looks as follows, it does compile without errors but the output is not the intended.

    print "Please provide the service name that you wish to analyze (Named service):\n";
    print "Several services may be provided, using a comma sign as a separator.\n";

    my $service_name_input = <>;
    chomp($service_name_input);
    my @service_list = split(/,/, $service_name_input);

    foreach my $line (@service_list)
    {
        open(my $service_input, "service @service_list status|");
    }

    foreach my $line (@service_list)
    {
        #Matches for "running".
        if ($line =~ m/(\(running\))/)
        {
            print "The service @service_list is running\n";
        }
        #Matches for "dead".
        elsif ($line =~ m/(dead)/)
        {
            print "The service @service_list is dead\n";
        }
    }

The program should output if the service is running or dead, but I only get the following error code. When manually issuing the service command, it works just fine though.

The service command supports only basic LSB actions (start, stop, restart, try-restart, reload, force-reload, status). For other actions, please try to use systemctl.

Any help regarding the steps I should take in order to achieve a working program will be much appreciated. Thank you for reading.

4
  • 1
    open(my $service_input, "service @service_list status|"); -> open(my $service_input, "service $line status|"); Commented Aug 11, 2015 at 21:45
  • It doesn't result in any errors, but I do not get any output either. I think it might have something to do with the print statement then. Commented Aug 11, 2015 at 21:49
  • 2
    You don't actually use $service_input aside from opening it. You might want to capture the output somehow. Commented Aug 11, 2015 at 21:50
  • You are correct. I will take a look at that. Commented Aug 11, 2015 at 21:52

1 Answer 1

2
foreach my $line (@service_list)
{
    open(my $service_input, "service @service_list status|");
}

This loop doesn't use $line. You're passing the whole array @service_list to the service command, i.e. you're running service ssh named cups status. This causes an error because service thinks you want to execute the named action on the ssh service. To fix that, write "service $line status |".

But there's another issue: You never do anything with $service_input either. If you want to loop over each line of each service command output, you need something more like:

foreach my $service (@service_list)
{
    open(my $service_input, '-|', 'service', $service, 'status')
        or die "$0: can't run 'service': $!\n";

    while (my $line = readline $service_input)
    {
        #Matches for "running".
        if ($line =~ m/(\(running\))/)
        {
            print "The service $service is running\n";
        }
        #Matches for "dead".
        elsif ($line =~ m/(dead)/)
        {
            print "The service $service is dead\n";
        }
    }
}

I've changed your open line to use a separate mode argument -| (which is good style in general) and the list form of process open, which avoids the shell, which is also good in general (no issues with "special characters" in $service, for example).

Sign up to request clarification or add additional context in comments.

4 Comments

With pipe opens, don't forget to check the return value of close to see if the command actually succeeded (open only returns the pid of the child, so you're really checking the success of fork).
I understand all of your changes but readline. I'm not sure what this is supposed to do.
@MajesticPixel It does just what it sounds like: reads...wait for it...lines. :) That bit of code is reading the output of your command line-by-line and storing the result in the scalar $line. See perldoc -f readline (linked for your convenience)
I tried this but somehow the variables $service_input and $service require explicit package name even though they have that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.