我想知道我的程序是从命令行执行,还是通过system()
调用或脚本执行。
我最初考虑过获取父ID(getppid()
),并查找/proc/#pppid
目录,检查exe
链接或cmdline
文件的内容。如果是/ bin / bash,或/ bin / csh,或/ bin / sh,我会知道它是从命令行运行的。
问题是不正确,因为独立脚本也会告诉我/bin/bash
。
即使它有效,它可能是非常具体的Linux版本方法,并可能在将来停止工作。
有更好的方法吗?
感谢您提出任何建议或指出某些方向。
答案 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'