如何向后台C++进程注入可被getline(std::cin)识别的输入?
解决后台C++进程持续输入注入问题
首先咱们先搞清楚你之前的方法为啥行不通:
- 当你后台运行进程但没重定向
stdin时,进程的fd 0依然绑定到原来的启动终端。往/proc/${PID}/fd/0写入本质上是往终端的输出流写,而不是给进程的输入缓冲区——进程是从终端的输入队列读取数据,不是从这个fd的写入端,所以getline根本看不到这些内容。 - 管道一次性生效是因为管道在写入端关闭后,进程会收到
EOF,getline读取到EOF后就不会再等待输入了。
下面给你两个无额外依赖、能持续注入输入的方案:
方案一:使用命名管道(FIFO)
这是最简单的方法,利用系统自带的mkfifo创建持久化管道,让进程的stdin绑定到这个管道,就能多次写入输入:
- 创建命名管道:
mkfifo my_process_pipe - 启动后台进程,重定向
stdin到管道,stdout到目标文件:./your_compiled_program < my_process_pipe > output.log & - 现在你可以随时往管道写入输入,每次写入都会被
getline读取:
如果你需要持续交互输入,也可以用echo "Hello world!" > my_process_pipe echo "Another message" > my_process_pipecat往管道写:cat > my_process_pipe # 这里输入任意内容,按Ctrl+D结束本次输入(不会终止进程,只是结束当前cat的写入)
原理:命名管道是一种持久化的IPC机制,只要进程还在运行且管道未被关闭,每次往管道写入的数据都会被进程的stdin读取,不会触发EOF(除非所有写入端都关闭)。
方案二:使用伪终端(PTY)
如果你的场景需要模拟终端环境(比如进程依赖终端特性),可以用系统自带的script命令创建伪终端来启动进程:
用
script启动后台进程,将程序的输出重定向到目标文件:script -q -c "./your_compiled_program > output.log" /dev/null &参数说明:
-q:静默模式,不输出script自身的日志-c:指定要运行的命令- 最后一个
/dev/null:让script自身的日志写入空设备,避免干扰
找到进程绑定的伪终端路径:
ls -l /proc/$(pgrep your_compiled_program)/fd/0输出会类似
lrwx------ 1 user user 64 Aug 28 10:00 /proc/1234/fd/0 -> /dev/pts/5,这里的/dev/pts/5就是伪终端路径。往伪终端写入输入,进程的
getline就能读取到:echo "Hello world!" > /dev/pts/5 echo "Keep sending messages" > /dev/pts/5
原理:script会创建一个伪终端,让进程认为自己在和真实终端交互,往伪终端写入的数据会被进程的stdin正常读取,而且可以持续写入直到进程退出。
注意事项
- 使用命名管道时,如果进程意外退出,后续往管道写入会报错
bash: my_process_pipe: No such device or address,这是正常现象,重新启动进程即可。 - 伪终端方案中,不同系统的
script参数可能略有差异(比如macOS的script没有-q,可以用-s代替),但核心功能一致。
内容的提问来源于stack exchange,提问作者vgonisanz
相关产品推荐
相关产品推荐

