Linux 我的父进程在哪里发送它';什么是标准?
我试图使标题简洁明了,但想不出一种方法来完全概括这个问题。我想做的是:在运行perl脚本时,我想知道除了“我自己”之外,是否还有其他进程连接到同一个STDERR流(在当前tty中或可能附加/重定向到同一个STDERR文件),如果是,我的目标是能够区分我的STDERR错误/警告/详细消息与其他并发运行程序中的任何消息之间的区别。当我检测到这种可能性时,我想在打印到STDERR的所有消息前加上我的脚本名,以便用户知道消息来自哪个进程(或者至少哪些进程来自我编写的脚本)。目前,我不关心我如何实现这一点,也不关心解决方案是否封装了所有的可能性——现在让我们称之为概念证明,它为一个体面的默认行为捕获了合理数量的用例。我正试图通过系统调用来实现这一点 我想说明两种情况:来自同级进程的消息在一系列管道命令中并发运行,来自其他子进程的消息由同一父脚本串行运行。我不打算尝试在同一个STDERR流上使用句柄来处理后台进程的情况,但是如果这些进程被捕获,那将是一个额外的好处 我相信我对第一种情况有很好的把握:兄弟进程。我可以使用Linux 我的父进程在哪里发送它';什么是标准?,linux,perl,shell,parent,lsof,Linux,Perl,Shell,Parent,Lsof,我试图使标题简洁明了,但想不出一种方法来完全概括这个问题。我想做的是:在运行perl脚本时,我想知道除了“我自己”之外,是否还有其他进程连接到同一个STDERR流(在当前tty中或可能附加/重定向到同一个STDERR文件),如果是,我的目标是能够区分我的STDERR错误/警告/详细消息与其他并发运行程序中的任何消息之间的区别。当我检测到这种可能性时,我想在打印到STDERR的所有消息前加上我的脚本名,以便用户知道消息来自哪个进程(或者至少哪些进程来自我编写的脚本)。目前,我不关心我如何实现这一点
pgrep-P$ppid
获得任何同级进程的所有PID。兄弟进程的简单存在足以保证在我的消息前面加上脚本名,但我甚至可以更进一步,使用lsof来确定它们的stderr是否与我的stderr流相同——例如,它们是否在后台运行,并且它们的stderr是否与我的TTY流相同(由文件描述符“2”推断)。我甚至可以检查我是否是一系列带有perl的-p或-t函数的管道命令的一部分(尽管我不想在文件被重定向到使用“”的位置或被重定向到使用“”的位置时预加前缀,因此单靠-p或-t是不起作用的)。无论如何,我对如何处理并发运行的同级进程感到满意
我还没有充分理解的场景是由父脚本控制的连续运行进程。我的想法是尝试并合理猜测父进程是交互式shell还是脚本
我试着阅读lsof,想知道是否有办法做到这一点。我猜测,来自交互式shell/终端的任何错误都不会被打印到与我的脚本相同的STDERR流中,但显然是这样,所以我不能简单地查看是否有任何输出将从父级发送到我的tty,以区分这两种情况
我创建了一个用于在不同环境中进行测试的单行程序:
perl -e '$ppid=getppid();print("lsof -p $ppid:\n",`lsof -p $ppid`)'
我在两个上下文中运行它:一个直接在命令行上运行,另一个在shell脚本中运行。在父级PID上运行lsof的唯一区别是,在命令行上运行时,有5个到tty的读/写连接,在shell脚本中运行时,有3个到tty的连接和一个只读连接读取shell脚本。在任何情况下,文件描述符都不是0、1或2
交互式shell:
...
tcsh 87854 me 15u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 16u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 17u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 18u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 19u CHR 16,2 0t3625 13083 /dev/ttys002
内部shell脚本:
tcsh 89384 me 16r REG 1,3 363 19758500 /whatever/tmpdelete2.tcsh
tcsh 89384 me 17u CHR 16,2 0t4721 13083 /dev/ttys002
tcsh 89384 me 18u CHR 16,2 0t4721 13083 /dev/ttys002
tcsh 89384 me 19u CHR 16,2 0t4721 13083 /dev/ttys002
所以我的问题是:这里是否有足够的信息来合理地推断父进程是否是交互式shell?
我可以从父进程对文件的常规只读读取中合理推断父进程不是交互式终端会话吗?或者我可以从存在5个到tty的读/写连接推断父进程是交互式shell吗
为了稍微测试一下这个想法,我试着在我的一行代码上面放一个sleep 1
,看看在长时间的脚本执行过程中,脚本的读取是否会在某个时候从lsof输出中消失。我还试着在运行shell脚本时重定向脚本的进出
在我的用例中,我可以分辨出不同之处,但我不确定其他shell的行为。我真正关心的是shell脚本。我想不出任何合理的场景,有人从其他任何内部调用perl脚本…查看其他进程的stderr是不够的。他们可以将其他东西重定向到同样的tty。人们经常做各种不合理的事情。我认为这项工作通常不太可能,也可能不是一个好主意。你说的“其他事情”是什么意思?如果你指的是不属于父进程的后台进程,那么我将通过pgrep将它们视为兄弟进程并预先编写我的脚本,或者我不会看到它们,因为我在脚本中运行,在这种情况下,我将预先编写-所以这不重要。不确定还有什么可能-除非我在子shell中-这可能是一个问题,但这是f功能并不是很关键——只要它表现得相当好,我就会感到满意。所以,除非是在地下室,还有什么会出错?(严肃的问题——不是一个非常无知的修辞问题。))我的意思是,他们可以向tty打开任何其他fd。你不能假设只有stderr会去那里。更不用说任何其他可以访问tty的进程都可以随机写入它(尽管显然您不能期望处理它)。是的,tty可以有非标准输出,但我只关心w/错误,这可以很容易地与其他输出区分开来。如果一个进程将错误发送到其他地方,我不会担心它(这是他们有问题的设计决策,即他们的问题)。此外,使用pgrep的第1个场景只是一个问题,它用于捕获交互式shell中的并发进程,所以不应该弹出这样的窗口