QProcess 附加到从脚本运行的可执行文件
Posted
技术标签:
【中文标题】QProcess 附加到从脚本运行的可执行文件【英文标题】:QProcess attach to executable ran from script 【发布时间】:2021-07-26 17:36:19 【问题描述】:我正在使用 QtCreator,我正在尝试创建一个运行 bash 脚本的 QProcess。在该脚本内部,执行一些其他命令后,将运行一个可执行文件。
当我监控 QProcess 时,我认为当脚本完成时,即使从该脚本启动的可执行文件仍在运行,QProcess 也会显示为已停止。
有没有办法解决这个问题?以某种方式附加到从该脚本启动的可执行文件?
我正在执行的命令是:
xterm -T "Window Title" -geometry 120x24+0+20 -e \
bash -c 'sudo -E ./executable -s 2>&1 | tee -i log_file.log' &
...并且我希望我的父进程检测 ./executable
何时完成 - 而不在发生这种情况时强制 xterm 立即退出。
【问题讨论】:
不显示细节很难说。最简单的修复(并且可以说是最好的)是将您的脚本修改为exec
,无论它启动什么进程,以便该进程接管脚本预先存在的PID。这也是许多初始化系统跟踪服务可执行文件的首选方式。
谢谢,查尔斯!你能澄清一下我该怎么做吗?在 bash 脚本中,以下命令执行可执行文件。如何将其编辑为“执行”? xterm -T "窗口标题" -geometry 120x24+0+20 -e bash -c 'sudo -E ./executable -s 2>&1 | tee -i log_file.log' &
经过一番研究,似乎这就是 xterm 命令末尾的 & 的用途?所以我不确定那是什么问题。
&
与 exec
完全相反。 exec
会告诉 shell 在同一个进程中运行某些东西。 &
告诉 shell 产生一个子进程。
如果你想保持进程树尽可能浅,一个替代方案可能看起来像:exec xterm -T "Window Title" -geometry 120x24+0+20 -e bash -c 'exec > >(exec tee -i log_file.log) 2>&1; exec sudo -E ./executable -s'
【参考方案1】:
第 1 部分:检测 xterm
何时退出
这与“第 2 部分”不同,因为它不会让您的 ./executable
一次性完成,而您的 xterm 在不同的稍后时间完成。后者见下文“第 2 部分”。
最后的&
告诉shell 不要等待xterm
进程(在“后台”运行它)。不过,在这种情况下,您希望 shell 等待——但我们可以做得更好,让 shell 完全不碍事。
第 1 步:只需取出末尾的 &
。
这将使进程显示为正在运行,直到 xterm
退出 - 尽管要实现这一点,作为 xterm 的父进程的 bash
的副本也将运行。
xterm -T "Window Title" -geometry 120x24+0+20 -e \
bash -c 'sudo -E ./executable -s 2>&1 | tee -i log_file.log'
第 2 步:将 bash 的父进程副本替换为 xterm进程本身
这是通过exec
关键字完成的;当您运行exec someprogram
时,shell 将在内存中替换为someprogram
的副本(与默认行为相反,运行someprogram
时将程序作为子进程启动,但除非您使用&
,否则shell 会等待该子进程在继续之前退出)。
这不仅节省了一点内存,而且还意味着您发送的信号将直接发送到xterm
进程,而不是发送到它的父级 bash 副本。
exec xterm -T "Window Title" -geometry 120x24+0+20 -e \
bash -c 'sudo -E ./executable -s 2>&1 | tee -i log_file.log'
第 3 步:将 sudo
和 tee
移出管道
虽然上面应该已经解决了您的直接流程,但它仍然留下了一个流程树,其中包含比必要更多的移动部分:您的 Qt 程序启动 xterm
,xterm 启动 bash,bash 的副本产生一个管道(将自身分叉成一个每侧的父 shell 的单独副本),并将管道的一侧替换为 sudo
,另一侧替换为 tee
。
我们可以通过使用 bash 扩展进程替换来使 tee
作为子进程运行,并将 sudo -E ./executable
替换为 exec
'd,替换 bash
的副本,xterm
开始:
exec xterm -T "Window Title" -geometry 120x24+0+20 -e \
bash -c 'exec > >(exec tee -i log_file.log) 2>&1;
exec sudo -E ./executable -s'
请注意,在exec > >(...) 2>&1
中,我们使用了不同形式的exec
:当exec
仅给出重定向作为参数时,它不会关闭当前shell 并将其替换为另一个进程,而是执行那些当前 shell 本身的重定向。因此,当我们运行 exec 2>&1
时,2>&1
重定向会针对当前 shell 执行并一直保留到它退出,因此我们不需要在 ./executable
调用上放置另一个 2>&1
。
第 2 部分:检测 ./executable
何时退出
但是,如果您想让 xterm 保持打开状态(以便用户可以阅读日志)即使在 ./executable
完成后怎么办?
考虑:
#!/usr/bin/env bash
exec > >(tee -i log_file.log)
xterm -T "Window Title" -geometry 120x24+0+20 -e tail -n +0 -f log_file.log &
exec sudo -E ./executable -s'
这里,我们在后台运行xterm
,但在前台运行sudo -E ./executable -s
(exec
'd 替换启动它的shell),所以父进程检测sudo
何时退出,而不是当xterm
退出。
【讨论】:
感谢您的精彩解释。当我运行它时,xterm 立即消失。我希望 xterm 窗口保持打开状态并显示可执行文件的输出。知道为什么会这样吗? 在可执行文件完成后立即消失,你的意思是?因此,修复的棘手之处在于让您的父进程知道可执行文件已完成,而不是让它知道 xterm 何时退出。 ...我现在正忙于工作,但是当我有机会尝试构建一个替代答案来让您跟踪./executable
何时完成时,它可能依赖于父 shell 等待释放锁。
我认为可执行文件实际上并未与您发送的内容一起启动。如果我在终端中尝试,终端会关闭并且什么都不会启动。如果我从前面删除 exec 并在终端中重试,则不会启动任何内容,它只会返回。我知道可执行文件可以正常工作,因为如果我这样做 ./executable 它会在终端中正常启动。
嗯。不幸的是,因为除了你之外没有人拥有./executable
,这不是我可以轻易测试的。以上是关于QProcess 附加到从脚本运行的可执行文件的主要内容,如果未能解决你的问题,请参考以下文章