测试我的程序是否从bash / ksh / csh命令行执行

时间:2014-06-20 16:45:33

标签: c linux

我想知道我的程序是从命令行执行,还是通过system()调用或脚本执行。

我最初考虑过获取父ID(getppid()),并查找/proc/#pppid目录,检查exe链接或cmdline文件的内容。如果是/ bin / bash,或/ bin / csh,或/ bin / sh,我会知道它是从命令行运行的。

问题是不正确,因为独立脚本也会告诉我/bin/bash。 即使它有效,它可能是非常具体的Linux版本方法,并可能在将来停止工作。

有更好的方法吗?

感谢您提出任何建议或指出某些方向。

3 个答案:

答案 0 :(得分:1)

自1980年以来编写的大多数shell都支持作业控制,这是通过为一个命令管道中的每个进程分配一个进程组来实现的。进程组由setpgrp()设置,它将进程的pgrp设置为其pid。

pgrp是在forks中继承的。

因此,如果你的shell是一个相对现代的shell,由交互式shell启动的程序将具有getpid() == getpgrp(),以及该进程分叉的任何其他进程(例如,如果它是shell脚本或者是它会调用system()getpid() != getpgrp()

这是一个测试程序,它在bash下的行为(在ksh93和tcsh下也会表现相同):

pp.c

#include <unistd.h>
#include <stdio.h>

main()
{
    printf("pid=%d pgrp=%d\n", (int)getpid(), (int)getpgrp());
}


$ ./pp
pid=3164 pgrp=3164
$ ./pp &
[1] 3165
$ pid=3165 pgrp=3165

在管道中,最左边的命令是进程组负责人。 (这没有记录,但是bash,ksh93和tcsh都是这样做的。)

$ ls|./pp
pid=3179 pgrp=3178
$ ./pp|cat
pid=3180 pgrp=3180

使用system()调用的程序将与其父代具有相同的pgrp:

pps.c

#include <stdlib.h>

main()
{
    system("./pp");
}


$ ./pps
pid=4610 pgrp=4608

在shell脚本中,shell是进程组负责人,由它调用的任何命令都将继承pgrp:

pp.sh

#!/bin/sh
./pp


$ ./pp.sh
pid=4501 pgrp=4500

但是如果shell脚本exec是一个程序,那么pid就不会改变,并且所执行的程序将成为一个进程组的领导者,所以你可能不想这样做。 / p>

ppe.sh

#!/bin/sh
exec ./pp


$ ./ppe.sh
pid=4504 pgrp=4504

在不太可能的情况下,用户关闭作业控制,每个命令将具有与shell相同的pgrp:

$ set +m
$ ./pp
pid=4521 pgrp=2990
$ ./pp
pid=4522 pgrp=2990

答案 1 :(得分:0)

脚本完成后你可以拦截来自PID的信号并检查&#34; kill&#34;为了它。

答案 2 :(得分:0)

不确定是否能解决您的问题,但环境变量可以为您提供良好的提示。例如:

 $ set | grep "^_="
 _=
 $ bash -c "set" | grep "^_="
 _=/bin/bash
 $ sh -c "set" | grep "^_="
 _='/bin/sh'