问题很简单:我发现有可能很有用打开(和关闭)我需要的每个时刻某个正在运行的程序的输出。更准确地说,我希望能够自由地将它们的标准输出(和错误)从当前 shell 重定向到另一个 shell、重定向/dev/null
到文件或返回到原始 shell。
我寻找一些直接(且安全)的东西,利用我所知道的事实提前我将打开和关闭输出。我也发表一个答案。
下面是我的第一次尝试。假设我在 35 号外壳工作。
$ who am I # the command line to ask where am I
myuser pts/35 ... # The answer
我的尝试从指向该终端的符号链接开始
ln -s /dev/pts/35 MyOutput # The command to link
这个想法是启动程序并将重定向设置为该链接
./Execute_program > MyOutput
它有效,它将输出重定向到我的终端,但是当我发出更改链接的命令时,
ln -sf /dev/null MyOutput
链接发生变化,但重定向不会改变我多么希望。它不会因正在运行的进程而改变。如果我以相同的方式启动一个新程序,重定向将遵循链接的新规定。
如果我再次开始并将输出链接设置/dev/null
为按预期抑制,但当我再次更改链接时,重定向不会更改。
如果我做一个链接到一个链接,我会得到相同的结果。使用hard link
不会改变情况。
可悲的是shell 在启动时扩展命令行。
是否有可能以类似的方式完成这项工作,或者我是否可以找到如何与链接已更改的进程(或 PPID 进程)进行通信?
笔记:
这是“如何重定向正在运行的进程的输出?”系列的一个问题,但它并不是从这一点开始的“Ops 我启动了程序,但忘记重定向输出。现在我想这样做”,但从相反的角度来看:“我如何启动一个程序,其明确的目标是在稍后阶段将输出重定向到其他地方?”。
当不可能(或不方便)修改程序的源代码时,我打算使用这样的过程。
我读可以disown
处理、使用screen
并从一个屏幕传输到另一个屏幕...或者使用调试器来拦截进程...所有这些解决方案都可以通过大量的经验和努力来发挥作用,但其中一些解决方案也呈现一定比例的风险。
答案1
我通过mkfifo
创建一个命名管道找到了一个解决方案,或者先进先出。
就像创建符号链接一样简单,并且可以使用 shell 允许的所有重定向。
mkfifo MyOutput
ls -l
给出
0 prw-r--r-- 1 My_username My_username 0 May 11 17:45 MyOut|
我可以通过重定向到该链接来启动该程序
./Execute_program > MyOutput & cat MyOutput
并且输出开始在终端上流动。
如果我按ctrl+c我会中断流程,但不会中断正在运行的进程(我必须使用类似kill pid
或 的东西kill %1
来执行此操作)。
当第二次我会问先进先出要在终端上转储(再次使用cat MyOutput
),它将开始转储该时刻的输出。
注意和警告:
- 直到我不会要求
FIFOs
它的转储将保存所有输出。
正如我第一次问的那样,它会冲走全部。 - 我可以重定向(或附加)到另一个文件
cat MyOutput >> NewRealFile
cat MyOutput
我也可以从另一个终端使用!- 警告:如果我要求 2 个不同的程序(或实例)将输出重定向到相同的
FIFOs
通量将被合并(没有先验区分该行来自哪个程序的方法)。 - 警告:如果我询问两次或多次(可能来自不同的终端),它将为每个请求提供一行,将输出拆分给请求者。也许有一个安全的解决方法......
答案2
如果我正确理解你的问题:
script 1>>~/out.fifo 2>>~/error.fifo
然后要监视你可以执行以下操作:
watch cat ~/out.fifo
您可以使用真实文件而不是 Fifos
script 1>/tmp/$0-out 2>/tmp/$0-error
然后 tail -f 它们,当您再次运行脚本时它们将被替换。
我更喜欢第二种方法,或者只使用多路复用器(即屏幕或本周流行的转世)
screen -t "name" bash -c 'script'
然后
screen -r
“监视”并按 ctrl+ad 分离。
如果您想在运行后查看输出,请确保在脚本末尾暂停。
答案3
如果我是你,我只是将输出重定向到一个文件,然后当我想查看输出时尾部该文件...如果你认为输出会相当长,你可能想限制该文件的大小,或者如果您认为输出会相当快,则将文件写入内存而不是磁盘上,但如何做这些事情是另一个问题。