![如何在没有任何事先准备的情况下从不同的终端写入正在运行的进程的终端设备标准输入?](https://linux22.com/image/158498/%E5%A6%82%E4%BD%95%E5%9C%A8%E6%B2%A1%E6%9C%89%E4%BB%BB%E4%BD%95%E4%BA%8B%E5%85%88%E5%87%86%E5%A4%87%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E4%BB%8E%E4%B8%8D%E5%90%8C%E7%9A%84%E7%BB%88%E7%AB%AF%E5%86%99%E5%85%A5%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%E8%BF%9B%E7%A8%8B%E7%9A%84%E7%BB%88%E7%AB%AF%E8%AE%BE%E5%A4%87%E6%A0%87%E5%87%86%E8%BE%93%E5%85%A5%EF%BC%9F%20.png)
类似的问题似乎还有很多,例如:
然而给出的答案是通过将其标准输入设置为管道来预先准备程序。
还有:
这是通过命令运行相关程序的终端多路复用器来回答的。这意味着它也需要事先准备。
这个问题是关于如何做到这一点没有事先做好任何准备。
起初我认为这可能很简单:
echo foo > /proc/$p/fd/0
但这只是写入终端。然后我尝试了:
echo foo > /proc/$terminal_emulator/fd/$ptmx_fd
但这也失败了,因为它只是为回显打开了一个新的终端设备从属设备。
我已经使用gdb
(叹)我将在下面发布,但我想知道是否有人知道更简单更好的替代方案。
答案1
#!/usr/bin/zsh
pid="$1"
stdin_data="$2"
for p in $(pstree -sp "$pid" | grep -Po '(?<=\()\d+(?=\))' | tac); do
[[ -r "/proc/$p/fd" ]] || continue
for f in /proc/$p/fd/*; do
if [[ "$(readlink "$f")" = /dev/ptmx ]]; then
fd="$(basename "$f")"
break 2
fi
done
done
sudo gdb -p "$p" --batch -x =(printf '%s' '
p (int)write($fd, "$stdin_data", (int)strlen("$stdin_data"))
')
我不喜欢 script 参数可以是 C 注入。
答案2
显然你不能,写入进程的标准输入文件不会使进程读取你附加的内容。请参阅此答案以获得完整的解释:https://serverfault.com/a/962956