HalNineThousand has asked for the wisdom of the Perl Monks concerning the following question:

I have a master Perl script that will run a number of slave Perl scripts, but while debugging, I may be running some of the slave scripts from the console.

Is there any way a Perl script can tell if it was run from within another script through the system() command (or using backtick quotes) instead of being run from the command line (or vice versa)?

Replies are listed 'Best First'.
Re: How Was My Script Run?
by JavaFan (Canon) on Mar 15, 2011 at 07:22 UTC
    Assuming you aren't mucking around with pseudo terminals when calling your slave programs, you could just check whether STDIN is a terminal:
    if (-t STDIN) { # Ran from the command line }
    This is a fairly standard way to check whether a program is run interactively (from the command-line) or not.

    An alternative way is to inspect the parent process. getppid returns the process ID of the parent, and from there you can work your way up.

    But I'd go the "check whether STDIN is a terminal" way.

Re: How Was My Script Run?
by cdarke (Prior) on Mar 15, 2011 at 09:21 UTC
    In principle, get your parent process id. (getppid) then interrogate that. On UNIX you can use Proc::ProcessTable or walk the /proc directory tree.
    Example for Linux:
    use warnings; use strict; my $ppid = getppid(); open (my $cmdfh, '<', "/proc/$ppid/cmdline") or die "Unable to open pp +id cmdline: $!"; my $cmdline = <$cmdfh>; close $cmdfh; if ($cmdline =~ /bash|ksh|csh/) { print "Started by a shell\n"; } elsif ($cmdline =~ /perl/) { print "Perl is the daddy\n"; } else { print "I was created by: $cmdline\n"; }
    On Windows it is not so easy. For some reason getppid is not implemented although there are Win32 API calls which will give details of the parent process based around CreateToolhelp32Snapshot() API.
      You can always do like
      $ENV{I_AM_THE_PARENT_PROCESS_ALL_MY_KIDS} = "LOVE ME"; fork ...
      Even cpan/cpanplus does this

        When I try using:

        if (-t STDIN) { $stdflag = 1; }
        I get the same result, whether I run my program from bash or if it's a spinoff from my Perl program, launched by system() or within backticks. I have no idea why, but that simply is not working on my system.

        When I use getppid() and get the command line from the /proc file system it works every time.

        What's important to me is that I have something that works so I don't have to set flags or be sure a parameter is passed on the command line. I can't use fork() to start the new process unless I make some significant changes in combining modules or USEing mods I don't want to on small daemon programs.

        But, as a point of interest, does anyone know why "-t STDIN" would still return a true when run from system() or with backticks?

        Thank you, everyone, for all the help!

      Slightly more general is to use the ps command. Unfortunately details vary on different varieties of Unix:

      68$ cat /tmp/p.pl; perl /tmp/p.pl my $ppid= getppid(); my $job = `ps -o "cmd" -p $ppid`; print $job # ----- CMD /bin/ksh

      As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Re: How Was My Script Run?
by Anonymous Monk on Mar 15, 2011 at 06:52 UTC
    Sure
    set FROMCOMMANDLINE=myslave.pl perl myslave.pl --fromcommandline
    export FROMCOMMANDLINE=myslave.pl perl myslave.pl --fromcommandline

      So I'd have to do it by using a parameter as a flag? Is that the only way, or is there any way for a script to tell, such as by looking at input or output or something else that I wouldn't specify in a parameter?

        So I'd have to do it by using a parameter as a flag? Is that the only way, or is there any way for a script to tell, such as by looking at input or output or something else that I wouldn't specify in a parameter?

        Parameters are delicious, learn to love them :)