如何找出执行Perl脚本的脚本,程序或shell?

时间:2011-12-16 19:00:12

标签: perl shell powershell

我如何确定哪些脚本,程序或shell执行了我的Perl脚本?

示例:如果从shell(针对每种类型的shell自定义)执行,我可能希望具有人类可读输出,如果从另一个perl脚本调用脚本,则可能需要不同类型的输出,如果从a执行,则可能需要机器可读格式程序,如持续集成服务器。

动机:我有一个工具可以根据shell执行它来改变输出。我通常将此行为作为脚本的选项实现,但此工具的设计不允许选项。其他shell具有指示正在运行的shell的环境变量。我正在开发一个支持Powershell的补丁,它没有这样的特殊变量。

编辑:其中许多答案恰好是特定于Linux的。不幸的是,Powershell适用于Windows。在这种情况下,getppid$ENV{SHELL}变量以及对ps的炮轰将无济于事。该脚本需要跨平台运行。

5 个答案:

答案 0 :(得分:5)

您使用getppid()。在child.pl

中获取此代码段
my $ppid = getppid();
system("ps --no-headers $ppid");

如果从命令行运行它,system将显示bash或类似(以及其他内容)。在另一个脚本中使用system("perl child.pl");执行它,例如parent.pl,您会看到perl parent.pl执行了它。

仅使用参数捕获进程的名称(感谢ikegami提供正确的ps语法):

my $ppid = getppid();
my $ps = `ps --no-headers -o cmd $ppid`;
chomp $ps;

编辑:此方法的替代方法可能是创建指向您脚本的软链接,使不同的上下文使用不同的链接来访问您的脚本并检查$0以构建逻辑这一点。

答案 1 :(得分:3)

我建议采用不同的方法来实现目标。而不是猜测上下文,使其更明确。每个用例都是完全独立的,因此有三个不同的接口。

  1. 可以在Perl程序中调用的函数。这可能会返回Perl数据结构。这比解析脚本输出更容易,更快速,更可靠。它也可以作为脚本的基础。

  2. 为当前shell输出的脚本。它可以查看$ENV{SHELL}以发现正在运行的shell。对于奖励积分,请提供明确覆盖的开关。

  3. 可以在非Perl程序中调用的脚本,例如持续集成服务器,并发出机器可读输出。 XML和/或JSON或其他。

  4. 2和3只是用于格式化来自1的数据的薄包装。

    每个都是根据其特定需求量身定制的。每个都可以没有启发式工作。每个都比试图猜测上下文和用户想要的东西简单得多。

    如果您不能将2和3分开,请让持续集成服务器设置一个环境变量并查找它。

答案 2 :(得分:1)

根据您的环境,您可以从环境变量中获取它。请考虑以下代码:

/usr/bin/perl -MData::Dumper -e 'print Dumper(\%ENV);' | grep sh

在我的Ubuntu系统上,它让我:

'SHELL' => '/bin/bash',

所以我想这就是说我从一个bash shell运行perl。如果你使用别的东西,SHELL变量可能会给你一个提示。

但是让我们说你知道你在使用bash,但perl是从子shell运行的。然后尝试:

/bin/sh -c "/usr/bin/perl -MData::Dumper -e 'print Dumper(\%ENV);'" | grep sh

你会发现:

      '_' => '/bin/sh',
      'SHELL' => '/bin/bash',

所以shell仍然是bash,但bash有一个变量$_,它还显示正在执行的shell或脚本的绝对文件名,这也可能提供一个有价值的提示。同样地,对于其他环境,很可能会在perl %ENV哈希中留下线索,这些线索应该为您提供有价值的提示。

答案 3 :(得分:1)

这是在Windows XP上使用PowerShell v2.0,所以请耐心等待。

cmd.exe shell中,我得到:

PSModulePath=C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\

而在PowerShell控制台窗口中,我得到:

PSModulePath=E:\Home\user\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsP owerShell\v1.0\Modules\

其中E:\Home\user是我的“我的文档”文件夹所在的位置。因此,一种启发式方法可能是检查PSModulePath是否包含用户相关路径。

此外,在控制台窗口中,我得到:

!::=::\

在环境中。从PowerShell ISE,我得到:

!::=::\
!C:=C:\Documents and Settings\user

答案 4 :(得分:1)

如果您正在运行PowerShell 2.0或更高版本(最有可能),则可以通过检查环境变量%psmodulepath%将shell推断为父进程。默认情况下,它指向%windir%\system32\windowspowershell\v1.0\modules下的系统模块;如果您从cmd.exe检查变量,就会看到这一点。

但是,当PowerShell启动时,它会将用户的默认模块搜索路径添加到此环境变量中,该变量类似于:%userprofile%\documents\windowspowershell\modules。这是由子进程继承的。因此,您的逻辑是测试%psmodulepath%是否以%userprofile%开头以检测powershell 2.0或更高版本。这在PowerShell 1.0中不起作用,因为它不支持模块。