Shell Commands (Getting PID and Timing Them)

Discussion in 'Perl Misc' started by Hal Vaughan, Apr 5, 2005.

  1. Hal Vaughan

    Hal Vaughan Guest

    There may be a better way to do what I want to do, so I'm open to
    suggestions.

    I want to run a shell command to record sound, and kill it after x seconds.
    If I were writing a Bash script, I'd run the command in the background, get
    the PID, use a sleep statement, then kill the first command after the sleep
    statement. In Perl I know how to fork and get a PID, and I know how to use
    `command` to get a commands output, but I can't find a way to run a command
    from Perl and get the PID so I can kill it when I want.

    Is there a way to get the PID? (I'd rather not use a 2nd script in bash to
    do it.)

    If there's another way to execute a shell command from Perl, then after x
    seconds kill it, I'm open to it.

    Thanks!

    Hal
    Hal Vaughan, Apr 5, 2005
    #1
    1. Advertising

  2. Hal Vaughan

    Guest

    Hal Vaughan <> wrote:
    > I want to run a shell command to record sound, and kill it after x seconds.
    > If I were writing a Bash script, I'd run the command in the background, get
    > the PID, use a sleep statement, then kill the first command after the sleep
    > statement. In Perl I know how to fork and get a PID, and I know how to use
    > `command` to get a commands output, but I can't find a way to run a command
    > from Perl and get the PID so I can kill it when I want.


    > Is there a way to get the PID? (I'd rather not use a 2nd script in bash to
    > do it.)


    > If there's another way to execute a shell command from Perl, then after x
    > seconds kill it, I'm open to it.


    Something like...

    my $pid = open (PIPE, "-|") || exec("/what/ever");

    # Read from PIPE, have a cup of coffee, sleep

    my $kesult = kill 9, $pid;

    Axel
    , Apr 5, 2005
    #2
    1. Advertising

  3. Hal Vaughan

    Joe Smith Guest

    Hal Vaughan wrote:
    > In Perl I know how to fork and get a PID, and I know how to use
    > `command` to get a commands output, but I can't find a way to run a command
    > from Perl and get the PID so I can kill it when I want.


    my $child_pid = fork();
    die unless defined $child_pid;
    if ($child_pid) { # Parent
    sleep $sleep_time;
    kill 2,$child_pid;
    } else { # Child
    exec "command </dev/null >/dev/null 2>&1";
    die "Could not run 'command'";
    }
    -Joe
    Joe Smith, Apr 5, 2005
    #3
  4. Hal Vaughan

    Hal Vaughan Guest

    Joe Smith wrote:

    > Hal Vaughan wrote:
    >> In Perl I know how to fork and get a PID, and I know how to use
    >> `command` to get a commands output, but I can't find a way to run a
    >> command from Perl and get the PID so I can kill it when I want.

    >
    > my $child_pid = fork();
    > die unless defined $child_pid;
    > if ($child_pid) { # Parent
    > sleep $sleep_time;
    > kill 2,$child_pid;
    > } else { # Child
    > exec "command </dev/null >/dev/null 2>&1";
    > die "Could not run 'command'";
    > }
    > -Joe


    Thanks, but that gives me the PID of the forked process. I want to run a
    BASH command from Perl, and get the PID of the BASH command. The child_pid
    is not the same as the bash command.

    Hal
    Hal Vaughan, Apr 5, 2005
    #4
  5. Hal Vaughan

    Hal Vaughan Guest

    wrote:

    > Hal Vaughan <> wrote:
    >> I want to run a shell command to record sound, and kill it after x
    >> seconds. If I were writing a Bash script, I'd run the command in the
    >> background, get the PID, use a sleep statement, then kill the first
    >> command after the sleep
    >> statement. In Perl I know how to fork and get a PID, and I know how to
    >> use `command` to get a commands output, but I can't find a way to run a
    >> command from Perl and get the PID so I can kill it when I want.

    >
    >> Is there a way to get the PID? (I'd rather not use a 2nd script in bash
    >> to do it.)

    >
    >> If there's another way to execute a shell command from Perl, then after x
    >> seconds kill it, I'm open to it.

    >
    > Something like...
    >
    > my $pid = open (PIPE, "-|") || exec("/what/ever");
    >
    > # Read from PIPE, have a cup of coffee, sleep
    >
    > my $kesult = kill 9, $pid;
    >
    > Axel


    I could use a bit of help understanding this. When the pipe is opened, and
    with the "||", it will exec the program, but still continue with the rest
    of the Perl program, with the pipe still open? (I'm just trying to make
    sure I see what's going on here.)

    Hal
    Hal Vaughan, Apr 5, 2005
    #5
  6. Hal Vaughan

    Guest

    Hal Vaughan <> wrote:
    > wrote:


    >>> Is there a way to get the PID? (I'd rather not use a 2nd script in bash
    >>> to do it.)


    >>> If there's another way to execute a shell command from Perl, then after x
    >>> seconds kill it, I'm open to it.


    >> Something like...
    >>
    >> my $pid = open (PIPE, "-|") || exec("/what/ever");
    >>
    >> # Read from PIPE, have a cup of coffee, sleep
    >>
    >> my $kesult = kill 9, $pid;


    > I could use a bit of help understanding this. When the pipe is opened, and
    > with the "||", it will exec the program, but still continue with the rest
    > of the Perl program, with the pipe still open? (I'm just trying to make
    > sure I see what's going on here.)


    Yes. The pipe would be open for reading in this case. A simple
    example... assuming we have the shell script hello.sh:

    #!/bin/sh
    echo Hello from a shell script

    and the Perl script:

    #!/usr/bin/perl

    use warnings;
    use strict;

    my $pid = open (PIPE, "-|") || exec("./hello.sh");
    while (<PIPE>) {
    print "Received: ", $_;
    }
    close (PIPE);
    __END__

    The Perl script will fork a child which exec's hello.sh and then reads
    the output from the childs which will be:

    Received: Hello from a shell script

    and the closes the PIPE and kills the child (although the child should
    be dead by this time). Of course you may well want to do checks on the
    status returned by the close statement to see if there was an abnormal
    termination.

    Axel
    , Apr 5, 2005
    #6
  7. Hal Vaughan

    Anno Siegel Guest

    Hal Vaughan <> wrote in comp.lang.perl.misc:
    > Joe Smith wrote:
    >
    > > Hal Vaughan wrote:
    > >> In Perl I know how to fork and get a PID, and I know how to use
    > >> `command` to get a commands output, but I can't find a way to run a
    > >> command from Perl and get the PID so I can kill it when I want.

    > >
    > > my $child_pid = fork();
    > > die unless defined $child_pid;
    > > if ($child_pid) { # Parent
    > > sleep $sleep_time;
    > > kill 2,$child_pid;
    > > } else { # Child
    > > exec "command </dev/null >/dev/null 2>&1";
    > > die "Could not run 'command'";
    > > }
    > > -Joe

    >
    > Thanks, but that gives me the PID of the forked process. I want to run a
    > BASH command from Perl, and get the PID of the BASH command. The child_pid
    > is not the same as the bash command.


    Have you tried the code? Have you read "perldoc -f exec"? What is a
    BASH-command?

    Anno
    Anno Siegel, Apr 5, 2005
    #7
  8. Hal Vaughan <> wrote:
    > Joe Smith wrote:
    >> Hal Vaughan wrote:
    >>> In Perl I know how to fork and get a PID, and I know how to use
    >>> `command` to get a commands output, but I can't find a way to run a
    >>> command from Perl and get the PID so I can kill it when I want.

    >>
    >> my $child_pid = fork();
    >> die unless defined $child_pid;
    >> if ($child_pid) { # Parent
    >> sleep $sleep_time;
    >> kill 2,$child_pid;
    >> } else { # Child
    >> exec "command </dev/null >/dev/null 2>&1";
    >> die "Could not run 'command'";
    >> }
    >> -Joe

    >
    > Thanks, but that gives me the PID of the forked process.



    Which is the process that you want to time-out.


    > I want to run a
    > BASH command from Perl, and get the PID of the BASH command.



    You got it (if /bin/sh is bash on your system. If not then
    replace "command" above with "/bin/bash").


    > The child_pid
    > is not the same as the bash command.



    Yes it is.

    Why do you think they are different?


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Apr 5, 2005
    #8
  9. Hal Vaughan

    Hal Vaughan Guest

    Anno Siegel wrote:

    > Hal Vaughan <> wrote in comp.lang.perl.misc:
    >> Joe Smith wrote:
    >>
    >> > Hal Vaughan wrote:
    >> >> In Perl I know how to fork and get a PID, and I know how to use
    >> >> `command` to get a commands output, but I can't find a way to run a
    >> >> command from Perl and get the PID so I can kill it when I want.
    >> >
    >> > my $child_pid = fork();
    >> > die unless defined $child_pid;
    >> > if ($child_pid) { # Parent
    >> > sleep $sleep_time;
    >> > kill 2,$child_pid;
    >> > } else { # Child
    >> > exec "command </dev/null >/dev/null 2>&1";
    >> > die "Could not run 'command'";
    >> > }
    >> > -Joe

    >>
    >> Thanks, but that gives me the PID of the forked process. I want to run a
    >> BASH command from Perl, and get the PID of the BASH command. The
    >> child_pid is not the same as the bash command.

    >
    > Have you tried the code? Have you read "perldoc -f exec"? What is a
    > BASH-command?
    >
    > Anno


    Tried it with typos. It works now. I saw the other suggested solution and
    tried it first. Unfortunately, at later than 3 am, I didn't follow this
    example (with the forking) as well as I should have, and misunderstood what
    it was doing and what I was looking at.

    Funny how things make better sense after a few hours of sleep...

    Hal
    Hal Vaughan, Apr 5, 2005
    #9
  10. Hal Vaughan

    Joe Smith Guest

    Hal Vaughan wrote:
    > wrote:
    >>my $pid = open (PIPE, "-|") || exec("/what/ever");
    >> ...
    >>my $kesult = kill 9, $pid;

    >
    > I could use a bit of help understanding this. When the pipe is opened, and
    > with the "||", it will exec the program, but still continue with the rest
    > of the Perl program, with the pipe still open?


    No, exec() and "continue with the rest of the program" are mutually
    exclusive. The exec() function causes your computer to stop
    executing the perl program and execute the other program instead.
    A single process won't do both, but a parent process and a child
    process can.

    *) open(PIPE,"-|") does an implicit fork() to create a child process
    and creates a pipe.

    *) In the parent process: Set file handle PIPE to read from the
    child process. Return the pid of the child (which is nonzero).

    *) In the parent process: The statement evaluates to
    (a value which is true) || exec();
    which means that the exec() part is not executed. Perl continues
    with the next statement.

    *) In the child process: TConnect the pipe to STDOUT.
    The open() function returns false in the child.

    *) In the child process: The statement evaluates to
    (a value which is false) || exec();
    which means the exec() function will be invoked. If the
    exec() is successful, the rest of the perl program will not
    be executed.

    The key to understanding how open(FH,'-|') works is to first
    understand how fork() returns two different values.

    -Joe
    Joe Smith, Apr 6, 2005
    #10
  11. wrote:

    > my $pid = open (PIPE, "-|") || exec("/what/ever");


    Why not just do it in one step?

    my $pid = open (PIPE, '-|', '/what/ever')
    or die "Whatever failed: $!";
    Brian McCauley, Apr 6, 2005
    #11
  12. Tad McClellan wrote:

    > Hal Vaughan <> wrote:
    >
    >>Joe Smith wrote:
    >>
    >>>Hal Vaughan wrote:
    >>>
    >>>>In Perl I know how to fork and get a PID, and I know how to use
    >>>>`command` to get a commands output, but I can't find a way to run a
    >>>>command from Perl and get the PID so I can kill it when I want.
    >>>
    >>> my $child_pid = fork();
    >>> die unless defined $child_pid;
    >>> if ($child_pid) { # Parent
    >>> sleep $sleep_time;
    >>> kill 2,$child_pid;
    >>> } else { # Child
    >>> exec "command </dev/null >/dev/null 2>&1";
    >>> die "Could not run 'command'";
    >>> }
    >>>-Joe

    >>
    >>Thanks, but that gives me the PID of the forked process.

    >
    >
    >
    > Which is the process that you want to time-out.
    >
    >
    >
    >>I want to run a
    >>BASH command from Perl, and get the PID of the BASH command.


    > You got it (if /bin/sh is bash on your system. If not then
    > replace "command" above with "/bin/bash").


    That would be:

    exec "/bin/bash </dev/null >/dev/null 2>&1";

    Er no, that would run bash instead of command, not run command under bash.

    To force the command line to be processed by /bin/bash rather than /bin/sh:

    exec '/bin/bash', '-c', 'command </dev/null >/dev/null 2>&1';
    Brian McCauley, Apr 6, 2005
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Anonieko

    HttpHandlers - Learn Them. Use Them.

    Anonieko, Jun 15, 2006, in forum: ASP .Net
    Replies:
    5
    Views:
    513
    tdavisjr
    Jun 16, 2006
  2. Ben Pfaff

    Re: man pages for C commands (GCC commands)

    Ben Pfaff, Jun 24, 2003, in forum: C Programming
    Replies:
    4
    Views:
    3,965
    Thomas Stegen
    Jun 28, 2003
  3. Tim Stanka
    Replies:
    1
    Views:
    789
    Jeff Epler
    Aug 2, 2004
  4. why the lucky stiff
    Replies:
    5
    Views:
    140
    why the lucky stiff
    Sep 22, 2004
  5. Mirco Wahab
    Replies:
    1
    Views:
    203
Loading...

Share This Page