在Perl脚本中如何确定调用当前脚本的父进程shell类型
解决方案
核心思路是直接读取Perl进程的父进程信息,拿到直接启动脚本的上层进程可执行路径,完全不受SHELL环境变量默认值、多层嵌套启动shell的影响。
方法1:跨平台通用实现(推荐)
使用Perl的Proc::ProcessTable模块读取系统进程表,无外部命令依赖,兼容Linux、macOS、BSD等多类Unix系统:
- 先安装对应模块:
- CPAN安装命令:
cpanm Proc::ProcessTable - Debian/Ubuntu 系统安装:
apt install libproc-processtable-perl - RHEL/CentOS/Fedora 系统安装:
dnf install perl-Proc-ProcessTable
- CPAN安装命令:
- 脚本实现代码:
use Proc::ProcessTable; # 构建进程表映射 my $pt = Proc::ProcessTable->new(); my %proc_map = map { $_->pid => $_ } @{$pt->table}; # 取当前Perl进程的父进程ID my $parent_pid = getppid(); my $parent_proc = $proc_map{$parent_pid}; # 提取调用shell路径,兼容登录态shell前缀带-的场景(比如-bash、-tcsh) my $caller_shell = $parent_proc->exec; if ((split /\//, $caller_shell)[-1] ne (split /\//, $parent_proc->cmndexec)[-1]) { $caller_shell = (split /-/, $parent_proc->cmndexec)[-1]; } # 拿到$caller_shell后直接传给你的module调用逻辑即可 print "调用脚本的shell为:$caller_shell\n";
方法2:Linux专属无依赖实现
如果不想额外安装模块,Linux平台可以直接读取/proc文件系统获取进程信息:
my $parent_pid = getppid(); # 读取父进程可执行路径 my $caller_shell = readlink "/proc/$parent_pid/exe"; # 兼容登录态shell的-前缀场景 open my $cmd_fh, '<', "/proc/$parent_pid/cmdline" or die $!; my $cmdline = do { local $/; <$cmd_fh> }; close $cmd_fh; my @cmd_args = split /\0/, $cmdline; if ($cmd_args[0] =~ /^-(\w+)$/) { $caller_shell = $1; } print "调用脚本的shell为:$caller_shell\n";
兜底逻辑补充
如果出现脚本不是从shell启动(比如从桌面快捷方式、其他应用直接调用)的异常场景,可以加判断逻辑,回退到读取$ENV{SHELL}作为默认值使用即可。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

