如何设置shell脚本的进程组?此外,我希望所有子进程都在同一进程组中
我期待类似于C中的setpgid().
简短的问题是,如果shell在没有tty的孤立进程组中应该怎么办?但我建议阅读这个长问题,因为它很有趣.
这是一个有趣而令人兴奋的方式,使用您最喜欢的外壳将您的笔记本电脑变成便携式空间加热器(除非您是其中一个tcsh怪人):
#include <unistd.h>
int main(void) {
if (fork() == 0) {
execl("/bin/bash", "/bin/bash", NULL);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这会导致bash将CPU固定在100%.zsh和鱼做同样的事情,而ksh和tcsh笨拙地谈论工作控制然后龙骨,这有点好,但并不多.哦,这是一个与平台无关的罪犯:OS X和Linux都受到了影响.
我的(可能是错误的)解释如下:子shell检测到它不在前台:tcgetpgrp(0) != getpgrp().因此它试图阻止自己:killpg(getpgrp(), SIGTTIN).但它的进程组是孤立的,因为它的父进程(C程序)是领导者并且死了,并且发送给孤立进程组的SIGTTIN刚刚被删除(否则什么都不能再启动它).因此,子shell不会停止,但它仍然在后台,所以它会立即再次完成.冲洗并重复.
我的问题是,命令行shell如何检测这种情况,它做什么是正确的?我的想法是shell尝试read从stdin,如果read给它EIO就退出.
谢谢你的想法!
编辑:我尝试在/ dev/tty上执行零长度读取(),并且成功,这很糟糕.为了获得EIO,我实际上必须准备从/ dev/tty读取一些数据.
编辑:我的另一个想法是kill(getpgrp(), 0).如果进程组是孤立的,那么我相信这将永远失败.但是,它也可能失败,因为我没有权限发信号通知会话负责人.
编辑:对于后来发现这个的人,我最终做的是在https://github.com/fish-shell/fish-shell/issues/422中描述的.还有,未来怎么样?
我被分配到了
编写一个C程序,打印以下标识符PID,PPID,SID,PGID,UID,EUID.
然后,作业继续问
什么代表每个标识符?
我已完成该程序,但尚未找到有关标识符的充分解释.
假设pid X是一个进程组负责人并X终止,但进程组中的其他进程仍在运行(X作为他们的pgid).Linux会阻止将值X指定为新进程的pid吗?
我问这是因为POSIX允许的失败条件setsid:
[EPERM]调用进程已经是进程组负责人,或者调用进程以外的进程的进程组ID与调用进程的进程ID匹配.
对于使用将"随机"触发的进程组(即shell)的代码,此错误似乎是一个不可恢复的条件,使其更加可恶.我认为任何旨在达到理智水平的实现都会避免重新分配X为pid,而它仍然被用作pgid,但我无法在任何地方找到它.
我想在自己的进程组中启动一个进程(或者,一旦启动就更改其组)并且:
Ctrl+Ckill命令终止组中的所有进程.注意:我试过setsid prog [args]但是进程没有响应来自终端的Ctrl + C,也没有得到新的进程组ID.
我也试图通过Perl的改变进程组setpgrp($pid, $pid)和POSIX::setpgid($pid, $pid),都无济于事.
编辑:更大的问题:
我有一个进程(单线程;让我们称之为"多产"进程P)同步启动许多子进程(一个接一个;当前一个子进程终止时它启动一个新进程).从终端,我希望能够杀死P它下面的进程树.要做到这一点,我可以简单地安排杀死组中的进程P.但是,默认行为是P在其父进程的组中.这意味着P如果我杀死了P组中的所有进程,那么父级将被杀死,除非我拥有P它的树并且它的树在他们自己的组中.
我的目的是杀死P它下面的树,但不是P父母.另外,我无法修改P代码本身.
我正在为我的CS类编写一个shell,项目的一部分涉及如果用户传入'&'字符,则在后台运行一个进程.
如果进程在前台运行,我只是execvp进程,它仍然在终端的控制之下,因为它在前台.但是,如果它是后台进程,我必须在开始执行进程后将控制权返回给我的主shell.我知道系统调用tcsetpgrp(pid_t)将进程作为参数传递给前台,但我不太明白如何使用它.
我应该叫tcsetpgrp后execvp,如果它是一个后台进程?如果是这样,我可以通过电话获取我的shell的pid getpid吗?
基本上我想要一个 bash 脚本进程在收到 后SIGINT,在退出之前终止其所有子进程。我在这里读到的内容是:
trap "kill -TERM -$$ ; exit 1" INT QUIT
Run Code Online (Sandbox Code Playgroud)
我还阅读了使用kill 0:
trap "kill -TERM 0 ; exit 1" INT QUIT
Run Code Online (Sandbox Code Playgroud)
它们之间有什么区别,它们是否满足以下要求(如果不满足,什么要求?)?:
./foo.sh &,然后,终止./foo.sh第二个进程或实例,即使在同一个 tty 中,终止第二个进程也不应终止第一个进程)。我有一个关于Linux pid事情的问题.如何在同一组中获得pids?在Linux中使用'ps'命令获取所有pid或pgid似乎很容易,但是如何获得属于同一组的pid,或者换句话说,如何获得同一个程序的pid?有人请给我一些帮助吗?谢谢!
给定一个 Linux 系统,在 Haskell GHCi 8.8.3 中,我可以使用以下命令运行 Docker 命令:
System.Process> withCreateProcess (shell "docker run -it alpine sh -c \"echo hello\""){create_group=False} $ \_ _ _ pid -> waitForProcess pid
hello
ExitSuccess
Run Code Online (Sandbox Code Playgroud)
但是,当我切换到create_group=True进程挂起时。的效果create_group是在子进程中调用set_pgidwith ,在父进程中调用with 。为什么这种变化会导致挂起?这是 Docker 中的错误吗?System.Process 中的错误?还是不幸但必要的互动?0pid
我试图修改Linux内核和我需要从获取用户ID和进程组ID task_struct和一个pid_namespace。尽管我在源代码中搜索了它们的定义,但是我找不到任何全局变量或函数(可能由于缺少代码中的注释而丢失了)来访问它们。
因为我不能使用诸如getuid()等等的用户空间函数,有没有一种方法可以在内核空间中获取它们?
process-group ×10
linux ×7
process ×5
shell ×4
c ×2
unix ×2
userid ×2
bash ×1
docker ×1
haskell ×1
job-control ×1
linux-kernel ×1
pid ×1
posix ×1
signals ×1