【问题标题】:How to bring a running background process to foreground?如何将正在运行的后台进程带到前台?
【发布时间】:2020-11-20 18:05:55
【问题描述】:

我有一个进程在服务器上运行,由于某种原因我的客户端系统重新启动,所以我使用终端再次登录到服务器。

进程按预期运行,但终端上不断提示的进程状态由于显而易见的原因消失了(因为我现在在另一个终端上)。

有什么办法可以让我将正在运行的进程的 STDOUT 带到当前终端?

谢谢。

【问题讨论】:

标签: server terminal stdout


【解决方案1】:

This answer

首先我在一个会话中运行命令cat > foo1 并测试来自标准输入的数据是否被复制到文件中。然后在另一个会话中我重定向输出。

首先找到进程的PID:

$ ps aux | grep cat
rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat

现在检查它打开的文件句柄:

$ ls -l /proc/6760/fd
total 3
lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1
lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5

现在运行 GDB:

$ gdb -p 6760 /bin/cat
GNU gdb 6.4.90-debian

[license stuff snipped]

Attaching to program: /bin/cat, process 6760

[snip other stuff that's not interesting now]

(gdb) p close(1)
$1 = 0
(gdb) p creat("/tmp/foo3", 0600)
$2 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760

GDB中的p命令会打印一个表达式的值,一个表达式可以是要调用的函数,也可以是系统调用……所以我执行close()系统调用并传递文件句柄1,然后我执行creat() 系统调用来打开一个新文件。 creat() 的结果是 1,这意味着它替换了之前的文件句柄。如果我想对 stdout 和 stderr 使用相同的文件,或者如果我想用其他数字替换文件句柄,那么我需要调用 dup2() 系统调用来实现该结果。

对于这个示例,我选择使用creat() 而不是open(),因为参数较少。标志的 C 宏在 GDB 中不可用(它不使用 C 头文件),所以我必须阅读头文件才能发现这一点——这样做并不难,但需要更多时间。请注意,0600 是拥有读/写访问权限的所有者以及没有访问权限的组和其他人的八进制权限。也可以为该参数使用 0 并稍后在文件上运行 chmod。

然后我验证结果:

ls -l /proc/6760/fd/
total 3
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 <====
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5

cat 中输入更多数据会导致文件/tmp/foo3 被附加到。

如果要关闭原始会话,则需要关闭它的所有文件句柄,打开一个可以作为控制 tty 的新设备,然后调用setsid()

【讨论】:

    【解决方案2】:

    使用以下脚本从任何进程中更改标准。

    此脚本附加 gdb 并更改进程的文件描述符,分离 gdb 并继续进程。

    用法:

    如果没有指定输出文件,则输出重定向到当前终端

    #!/bin/sh
    
    filename=`tty`
    if [ -z "$2" ]; then
        filename=`tty`
    else
        file_abs_path=`echo $2 | grep "^/.*"`
        if [ -z "$file_abs_path" ]; then
            filename="`pwd`/$2"
        else
            filename=$2
        fi
    fi
    
    original_terminal=`file /proc/$1/fd/1 | grep -o "symbolic.*" | grep -o "\/[^ ']*"`
    echo "Original stdout: $original_terminal"
    echo "" > $1.temp
    echo "p fileno(fopen("\"$filename\"", "\""w"\""))" >> $1.temp
    echo 'call dup2($1, 1)' >> $1.temp
    echo 'call dup2($1, 2)' >> $1.temp
    echo "q" >> $1.temp
    
    
    gdb -p $1  -x $1.temp < /dev/null >& /dev/null
    echo "New stdout: $filename"
    rm -rf $1.temp
    
    

    【讨论】:

      猜你喜欢
      • 2011-08-12
      • 2022-09-26
      • 1970-01-01
      • 1970-01-01
      • 2019-11-22
      • 2012-08-09
      • 1970-01-01
      • 2012-11-20
      • 2018-02-27
      相关资源
      最近更新 更多