一般来说,linux上后台运行的程序都会写类似于 ./foo 1>/dev/null 2>&1 以此实现不输出任何东西,但是如果需要用到标准输出用来调试,此时就会很要命
对于这样的程序,通过命令 ls -l /proc/<pid>/fd/ 可以看到 1 已经指向/dev/null了。
如果想要获取输出,可以通过以下步骤
gdb attach <pid>call (int)dup2((int)open("/root/foo_stdout.log", 1089, 0777), 1)- 退出gdb即可
此时可以看到指定的log文件已经创建了,通过ls -l /proc/<pid>/fd/可以看到标准输出已经重定向到指定文件了。
原理就是通过gdb向程序插入代码并执行,dup2可以实现类似重定向的效果。如果需要重定向标准错误,把dup2的第二个参数改为2应该就可以了。
open的参数1089是 O_WRONLY | O_CREAT | O_APPEND 的结果,所以对log文件是追加效果,具体可参考:https://stackoverflow.com/questions/72071279/attaching-to-a-process-and-call-dup2-on-aarch64
之后可以通过如下脚本实现这样的功能,第一个参数是pid,第二个参数为指定文件
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <pid> <filename>"
exit 1
fi
PID=$1
FILENAME=$2
if [[ "$FILENAME" != /* ]]; then
if command -v realpath >/dev/null 2>&1; then
FILENAME=$(realpath "$FILENAME")
elif command -v readlink >/dev/null 2>&1; then
FILENAME=$(readlink -f "$FILENAME")
else
echo "Error: realpath or readlink command is not available."
exit 1
fi
fi
if ! kill -0 $PID > /dev/null 2>&1; then
echo "Error: Process with PID $PID does not exist."
exit 1
fi
gdb -ex "attach $PID" -ex "call (int)dup2((int)open(\"$FILENAME\", 1089, 0777), 1)" -batch










没有回复内容